From 382845bc6e433761be83f42065ed098adc837799 Mon Sep 17 00:00:00 2001 From: Chandraprakash Sharma Date: Wed, 4 Nov 2015 19:18:16 +0900 Subject: [PATCH 01/99] Fixed: asShort in LongValueImpl should check isInShortRange instead of isInByteRange --- .../java/org/msgpack/value/impl/ImmutableLongValueImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableLongValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableLongValueImpl.java index c83bda332..872b97af0 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableLongValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableLongValueImpl.java @@ -158,7 +158,7 @@ public byte asByte() @Override public short asShort() { - if (!isInByteRange()) { + if (!isInShortRange()) { throw new MessageIntegerOverflowException(value); } return (short) value; From 919ab704831000930b85a4d6260e68d957ce7098 Mon Sep 17 00:00:00 2001 From: Chandraprakash Sharma Date: Tue, 10 Nov 2015 11:01:57 +0900 Subject: [PATCH 02/99] added tests for integer value range checks and casts --- .../scala/org/msgpack/value/ValueTest.scala | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala index e21c387fb..2d23090ca 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala @@ -16,7 +16,6 @@ package org.msgpack.value import java.math.BigInteger - import org.msgpack.core._ import scala.util.parsing.json.JSON @@ -97,5 +96,35 @@ class ValueTest extends MessagePackSpec } + "check appropriate range for integers" in { + import ValueFactory._ + import java.lang.Byte + import java.lang.Short + + newInteger(Byte.MAX_VALUE).asByte() shouldBe Byte.MAX_VALUE + newInteger(Byte.MIN_VALUE).asByte() shouldBe Byte.MIN_VALUE + newInteger(Short.MAX_VALUE).asShort() shouldBe Short.MAX_VALUE + newInteger(Short.MIN_VALUE).asShort() shouldBe Short.MIN_VALUE + newInteger(Integer.MAX_VALUE).asInt() shouldBe Integer.MAX_VALUE + newInteger(Integer.MIN_VALUE).asInt() shouldBe Integer.MIN_VALUE + intercept[MessageIntegerOverflowException] { + newInteger(Byte.MAX_VALUE+1).asByte() + } + intercept[MessageIntegerOverflowException] { + newInteger(Byte.MIN_VALUE-1).asByte() + } + intercept[MessageIntegerOverflowException] { + newInteger(Short.MAX_VALUE+1).asShort() + } + intercept[MessageIntegerOverflowException] { + newInteger(Short.MIN_VALUE-1).asShort() + } + intercept[MessageIntegerOverflowException] { + newInteger(Integer.MAX_VALUE+1).asInt() + } + intercept[MessageIntegerOverflowException] { + newInteger(Integer.MIN_VALUE-1).asInt() + } + } } } From 6b9d5d315d2e7277e694f2ac2b80b2547fc44904 Mon Sep 17 00:00:00 2001 From: Chandraprakash Sharma Date: Tue, 10 Nov 2015 11:18:43 +0900 Subject: [PATCH 03/99] fixed integer literal related issue in integer range check test --- msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala index 2d23090ca..6cb7af603 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTest.scala @@ -120,10 +120,10 @@ class ValueTest extends MessagePackSpec newInteger(Short.MIN_VALUE-1).asShort() } intercept[MessageIntegerOverflowException] { - newInteger(Integer.MAX_VALUE+1).asInt() + newInteger(Integer.MAX_VALUE+1.toLong).asInt() } intercept[MessageIntegerOverflowException] { - newInteger(Integer.MIN_VALUE-1).asInt() + newInteger(Integer.MIN_VALUE-1.toLong).asInt() } } } From b6d5ff116fdebe8ec77fb8237ab602a87ea888f5 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 12 Nov 2015 23:19:17 +0900 Subject: [PATCH 04/99] Add release notes for 0.7.0 --- RELEASE_NOTES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1419dae66..fdb624745 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,10 @@ # Release Notes +* 0.7.0 + * Support non-string key in jackson-dataformat-msgpack + * Update the version of jackson-databind to 2.6.3 + * Several bug fixes + * 0.7.0-M6 * Add a prototype of Value implementation * Apply strict coding style From 6058ec2369588b3710d5a2b67c9097c955216176 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 12 Nov 2015 23:25:17 +0900 Subject: [PATCH 05/99] Add release notes for 0.7.1 --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index fdb624745..6b691c476 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Release Notes +* 0.7.1 + * Fix ImmutableLongValueImpl#asShort [#287](https://github.com/msgpack/msgpack-java/pull/287) + * 0.7.0 * Support non-string key in jackson-dataformat-msgpack * Update the version of jackson-databind to 2.6.3 From 342a4ea6e86544a7b4584df660bc1470a0c7d8d5 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 12 Nov 2015 23:28:44 +0900 Subject: [PATCH 06/99] Setting version to 0.7.1 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 890da3daa..26dd39738 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.7.1-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.7.1" \ No newline at end of file From 44550d11499fb9eef8c617b63fb8743d709c7cfd Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 12 Nov 2015 23:29:20 +0900 Subject: [PATCH 07/99] Setting version to 0.7.2-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 26dd39738..984699500 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.7.1" \ No newline at end of file +version in ThisBuild := "0.7.2-SNAPSHOT" \ No newline at end of file From 51c4aed466626246049da4435fabdae75dec1164 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Thu, 12 Nov 2015 23:38:04 +0900 Subject: [PATCH 08/99] Update msgpack-java versions in README --- README.md | 6 +++--- msgpack-jackson/README.md | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e3805fde9..c66b668d7 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,13 @@ For Maven users: org.msgpack msgpack-core - 0.7.0-M6 + 0.7.1 ``` For sbt users: ``` -libraryDependencies += "org.msgpack" % "msgpack-core" % "0.7.0-M6" +libraryDependencies += "org.msgpack" % "msgpack-core" % "0.7.1" ``` For gradle users: @@ -34,7 +34,7 @@ repositories { } dependencies { - compile 'org.msgpack:msgpack-core:0.7.0-M6' + compile 'org.msgpack:msgpack-core:0.7.1' } ``` diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index c6509845f..55ed19233 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -3,18 +3,30 @@ This Jackson extension library handles reading and writing of data encoded in [MessagePack](http://msgpack.org/) data format. It extends standard Jackson streaming API (`JsonFactory`, `JsonParser`, `JsonGenerator`), and as such works seamlessly with all the higher level data abstractions (data binding, tree model, and pluggable extensions). For the details of Jackson-annotations, please see https://github.com/FasterXML/jackson-annotations. -## Maven dependency +## Install -To use this module on Maven-based projects, use following dependency: +### Maven ``` org.msgpack jackson-dataformat-msgpack - 0.7.0-p9 + 0.7.1 ``` +### Gradle +``` +repositories { + mavenCentral() +} + +dependencies { + compile 'org.msgpack:jackson-dataformat-msgpack:0.7.1' +} +``` + + ## Usage Only thing you need to do is to instantiate MessagePackFactory and pass it to the constructor of ObjectMapper. From af98ae9c747256ad504d59ef58c4e326964e7d4f Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Sun, 15 Nov 2015 17:42:38 +0900 Subject: [PATCH 09/99] Avoid to flush an extra buffer when the string isn't too large in MessagePack#packString --- .../java/org/msgpack/core/MessagePack.java | 16 +++++++++++++++ .../java/org/msgpack/core/MessagePacker.java | 14 +++++++++++++ .../org/msgpack/core/MessagePackerTest.scala | 20 +++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 70140c8ed..d7e05369c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -50,6 +50,7 @@ public static class Config private final int stringEncoderBufferSize; private final int stringDecoderBufferSize; private final int packerBufferSize; + private final int packerLargeStringThreshold; private final int packerRawDataCopyingThreshold; public Config( @@ -61,6 +62,7 @@ public Config( int stringEncoderBufferSize, int stringDecoderBufferSize, int packerBufferSize, + int packerLargeStringLengthThreshold, int packerRawDataCopyingThreshold) { checkArgument(packerBufferSize > 0, "packer buffer size must be larger than 0: " + packerBufferSize); @@ -75,6 +77,7 @@ public Config( this.stringEncoderBufferSize = stringEncoderBufferSize; this.stringDecoderBufferSize = stringDecoderBufferSize; this.packerBufferSize = packerBufferSize; + this.packerLargeStringThreshold = packerLargeStringLengthThreshold; this.packerRawDataCopyingThreshold = packerRawDataCopyingThreshold; } @@ -133,6 +136,11 @@ public int getPackerBufferSize() return packerBufferSize; } + public int getPackerLargeStringLengthThreshold() + { + return packerLargeStringThreshold; + } + public int getPackerRawDataCopyingThreshold() { return packerRawDataCopyingThreshold; @@ -154,6 +162,7 @@ public static class ConfigBuilder private int stringEncoderBufferSize = 8192; private int stringDecoderBufferSize = 8192; private int packerBufferSize = 8192; + private int packerLargeStringLengthThreshold = 512; private int packerRawDataCopyingThreshold = 512; public Config build() @@ -167,6 +176,7 @@ public Config build() stringEncoderBufferSize, stringDecoderBufferSize, packerBufferSize, + packerLargeStringLengthThreshold, packerRawDataCopyingThreshold ); } @@ -219,6 +229,12 @@ public ConfigBuilder packerBufferSize(int size) return this; } + public ConfigBuilder packerLargeStringThreshold(int threshold) + { + this.packerLargeStringLengthThreshold = threshold; + return this; + } + public ConfigBuilder packerRawDataCopyingThreshold(int threshold) { this.packerRawDataCopyingThreshold = threshold; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index ca40540fa..078d83107 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -442,6 +442,14 @@ public MessagePacker packDouble(double v) return this; } + private void packSmallString(String s) + throws IOException + { + byte[] bytes = s.getBytes("UTF-8"); + packRawStringHeader(bytes.length); + writePayload(bytes); + } + /** * Pack the input String in UTF-8 encoding * @@ -457,6 +465,12 @@ public MessagePacker packString(String s) return this; } + if (s.length() < config.getPackerLargeStringLengthThreshold()) { + // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer + packSmallString(s); + return this; + } + CharBuffer in = CharBuffer.wrap(s); prepareEncoder(); diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index bc2ec9d1c..8ec2487cc 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -22,6 +22,7 @@ import org.msgpack.core.buffer.{ChannelBufferOutput, OutputStreamBufferOutput} import org.msgpack.value.ValueFactory import xerial.core.io.IOUtil +import scala.compat.Platform import scala.util.Random /** @@ -235,6 +236,25 @@ class MessagePackerTest up1.hasNext shouldBe false up1.close } + + "pack a lot of String within expected time" in { + val count = 500000 + + def measureDuration(outputStream: java.io.OutputStream) : Long = { + val packer = MessagePack.newDefaultPacker(outputStream) + val start = Platform.currentTime + for (i <- 0 to count) { + packer.packString("0123456789ABCDEF") + } + packer.close + Platform.currentTime - start + } + + val baseDuration = measureDuration(new ByteArrayOutputStream()) + val (_, fileOutput) = createTempFileWithOutputStream + val targetDuration = measureDuration(fileOutput) + targetDuration shouldBe <= (baseDuration * 3) + } } "compute totalWrittenBytes" in { From 4f5b594e2ac31985165185c7f1d020549f2d9b48 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 15 Nov 2015 09:01:48 -0800 Subject: [PATCH 10/99] Simplify the config object --- .../java/org/msgpack/core/MessagePack.java | 101 +++++------------- .../java/org/msgpack/core/MessagePacker.java | 14 +-- .../org/msgpack/core/MessageUnpacker.java | 22 ++-- 3 files changed, 46 insertions(+), 91 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 70140c8ed..1ca58a64e 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -42,21 +42,36 @@ public class MessagePack */ public static class Config { - private final boolean readStringAsBinary; - private final boolean readBinaryAsString; - private final CodingErrorAction onMalFormedInput; - private final CodingErrorAction onUnmappableCharacter; - private final int maxUnpackStringSize; - private final int stringEncoderBufferSize; - private final int stringDecoderBufferSize; - private final int packerBufferSize; - private final int packerRawDataCopyingThreshold; + /** + * allow unpackBinaryHeader to read str format family (default:true) + */ + public final boolean readStringAsBinary; + /** + * allow unpackRawStringHeader and unpackString to read bin format family (default: true) + */ + public final boolean readBinaryAsString; + /** + * Action when encountered a malformed input + */ + public final CodingErrorAction actionOnMalFormedInput; + /** + * Action when an unmappable character is found + */ + public final CodingErrorAction actionOnUnmappableCharacter; + /** + * unpackString size limit. (default: Integer.MAX_VALUE) + */ + public final int maxUnpackStringSize; + public final int stringEncoderBufferSize; + public final int stringDecoderBufferSize; + public final int packerBufferSize; + public final int packerRawDataCopyingThreshold; public Config( boolean readStringAsBinary, boolean readBinaryAsString, - CodingErrorAction onMalFormedInput, - CodingErrorAction onUnmappableCharacter, + CodingErrorAction actionOnMalFormedInput, + CodingErrorAction actionOnUnmappableCharacter, int maxUnpackStringSize, int stringEncoderBufferSize, int stringDecoderBufferSize, @@ -69,74 +84,14 @@ public Config( this.readStringAsBinary = readStringAsBinary; this.readBinaryAsString = readBinaryAsString; - this.onMalFormedInput = onMalFormedInput; - this.onUnmappableCharacter = onUnmappableCharacter; + this.actionOnMalFormedInput = actionOnMalFormedInput; + this.actionOnUnmappableCharacter = actionOnUnmappableCharacter; this.maxUnpackStringSize = maxUnpackStringSize; this.stringEncoderBufferSize = stringEncoderBufferSize; this.stringDecoderBufferSize = stringDecoderBufferSize; this.packerBufferSize = packerBufferSize; this.packerRawDataCopyingThreshold = packerRawDataCopyingThreshold; } - - /** - * allow unpackBinaryHeader to read str format family (default:true) - */ - public boolean isReadStringAsBinary() - { - return readStringAsBinary; - } - - /** - * allow unpackRawStringHeader and unpackString to read bin format family (default: true) - */ - public boolean isReadBinaryAsString() - { - return readBinaryAsString; - } - - /** - * Action when encountered a malformed input - */ - public CodingErrorAction getActionOnMalFormedInput() - { - return onMalFormedInput; - } - - /** - * Action when an unmappable character is found - */ - public CodingErrorAction getActionOnUnmappableCharacter() - { - return onUnmappableCharacter; - } - - /** - * unpackString size limit. (default: Integer.MAX_VALUE) - */ - public int getMaxUnpackStringSize() - { - return maxUnpackStringSize; - } - - public int getStringEncoderBufferSize() - { - return stringEncoderBufferSize; - } - - public int getStringDecoderBufferSize() - { - return stringDecoderBufferSize; - } - - public int getPackerBufferSize() - { - return packerBufferSize; - } - - public int getPackerRawDataCopyingThreshold() - { - return packerRawDataCopyingThreshold; - } } /** diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index ca40540fa..cf425b830 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -150,7 +150,7 @@ public long getTotalWrittenBytes() private void prepareEncoder() { if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.getActionOnMalFormedInput()).onUnmappableCharacter(config.getActionOnMalFormedInput()); + this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); } } @@ -158,7 +158,7 @@ private void prepareBuffer() throws IOException { if (buffer == null) { - buffer = out.next(config.getPackerBufferSize()); + buffer = out.next(config.packerBufferSize); } } @@ -196,7 +196,7 @@ private void ensureCapacity(int numBytesToWrite) { if (buffer == null || position + numBytesToWrite >= buffer.size()) { flush(); - buffer = out.next(Math.max(config.getPackerBufferSize(), numBytesToWrite)); + buffer = out.next(Math.max(config.packerBufferSize, numBytesToWrite)); } } @@ -490,8 +490,8 @@ public MessagePacker packString(String s) } if (cr.isError()) { - if ((cr.isMalformed() && config.getActionOnMalFormedInput() == CodingErrorAction.REPORT) || - (cr.isUnmappable() && config.getActionOnUnmappableCharacter() == CodingErrorAction.REPORT)) { + if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || + (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { cr.throwException(); } } @@ -649,7 +649,7 @@ public MessagePacker writePayload(ByteBuffer src) throws IOException { int len = src.remaining(); - if (len >= config.getPackerRawDataCopyingThreshold()) { + if (len >= config.packerRawDataCopyingThreshold) { // Use the source ByteBuffer directly to avoid memory copy // First, flush the current buffer contents @@ -687,7 +687,7 @@ public MessagePacker writePayload(byte[] src) public MessagePacker writePayload(byte[] src, int off, int len) throws IOException { - if (len >= config.getPackerRawDataCopyingThreshold()) { + if (len >= config.packerRawDataCopyingThreshold) { // Use the input array directory to avoid memory copy // Flush the current buffer contents diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 43f6eede6..c50d183ee 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -172,10 +172,10 @@ public long getTotalReadBytes() private void prepareDecoder() { if (decoder == null) { - decodeBuffer = CharBuffer.allocate(config.getStringDecoderBufferSize()); + decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize); decoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(config.getActionOnMalFormedInput()) - .onUnmappableCharacter(config.getActionOnUnmappableCharacter()); + .onMalformedInput(config.actionOnMalFormedInput) + .onUnmappableCharacter(config.actionOnUnmappableCharacter); } } @@ -1011,8 +1011,8 @@ public String unpackString() { int strLen = unpackRawStringHeader(); if (strLen > 0) { - if (strLen > config.getMaxUnpackStringSize()) { - throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.getMaxUnpackStringSize(), strLen), strLen); + if (strLen > config.maxUnpackStringSize) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, strLen), strLen); } prepareDecoder(); @@ -1030,7 +1030,7 @@ public String unpackString() int readLen = Math.min(position < buffer.size() ? buffer.size() - position : buffer.size(), strLen - cursor); if (hasIncompleteMultiBytes) { // Prepare enough buffer for decoding multi-bytes character right after running into incomplete one - readLen = Math.min(config.getStringDecoderBufferSize(), strLen - cursor); + readLen = Math.min(config.stringDecoderBufferSize, strLen - cursor); } if (!ensure(readLen)) { throw new EOFException(); @@ -1055,7 +1055,7 @@ public String unpackString() if (cr.isUnderflow() && bb.hasRemaining()) { // input buffer doesn't have enough bytes for multi bytes characters - if (config.getActionOnMalFormedInput() == CodingErrorAction.REPORT) { + if (config.actionOnMalFormedInput == CodingErrorAction.REPORT) { throw new MalformedInputException(strLen); } hasIncompleteMultiBytes = true; @@ -1064,8 +1064,8 @@ public String unpackString() } if (cr.isError()) { - if ((cr.isMalformed() && config.getActionOnMalFormedInput() == CodingErrorAction.REPORT) || - (cr.isUnmappable() && config.getActionOnUnmappableCharacter() == CodingErrorAction.REPORT)) { + if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || + (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { cr.throwException(); } } @@ -1204,7 +1204,7 @@ public int unpackRawStringHeader() return len; } - if (config.isReadBinaryAsString()) { + if (config.readBinaryAsString) { len = readBinaryHeader(b); if (len >= 0) { return len; @@ -1225,7 +1225,7 @@ public int unpackBinaryHeader() return len; } - if (config.isReadStringAsBinary()) { + if (config.readStringAsBinary) { len = readStringHeader(b); if (len >= 0) { return len; From 78ab7c1a27f3d58202dbb2871add3cb11a14c90a Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 15 Nov 2015 10:08:31 -0800 Subject: [PATCH 11/99] Use build.sbt to reduce Scala code --- build.sbt | 115 +++++++++++++ .../dataformat/MessagePackParserTest.java | 6 +- project/Build.scala | 152 ------------------ project/build.properties | 2 +- project/plugins.sbt | 4 +- 5 files changed, 122 insertions(+), 157 deletions(-) create mode 100644 build.sbt delete mode 100644 project/Build.scala diff --git a/build.sbt b/build.sbt new file mode 100644 index 000000000..c796a80a4 --- /dev/null +++ b/build.sbt @@ -0,0 +1,115 @@ +import de.johoop.findbugs4sbt.ReportType + +organization := "org.msgpack" +organizationName := "MessagePack" +organizationHomepage := Some(new + URL("http://msgpack.org/")) +description := "MessagePack for Java" +scalaVersion in Global := "2.11.7" +logBuffered in Test := false +autoScalaLibrary := false +crossPaths := false + +// For performance testing, ensure each test run one-by-one +concurrentRestrictions in Global := Seq( + Tags.limit(Tags.Test, 1) +) + +incOptions := incOptions.value.withNameHashing(true) + +// JVM options for building +scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.6", "-feature") + +javaOptions in Test ++= Seq("-ea") +javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.6", "-target", "1.6") + +// Use lenient validation mode when generating Javadoc (for Java8) +javacOptions in doc := { + val opts = Seq("-source", "1.6") + if (scala.util.Properties.isJavaAtLeast("1.8")) { + opts ++ Seq("-Xdoclint:none") + } + else { + opts + } +} + +val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" + +// Project settings +lazy val root = Project(id = "msgpack-java", base = file(".")) + .settings( + // Do not publish the root project + publishArtifact := false, + publish := {}, + publishLocal := {}, + findbugs := { + // do not run findbugs for the root project + } + ).aggregate(msgpackCore, msgpackJackson) + +lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) + .settings( + description := "Core library of the MessagePack for Java", + libraryDependencies ++= Seq( + // msgpack-core should have no external dependencies + junitInterface, + "org.scalatest" %% "scalatest" % "2.2.4" % "test", + "org.scalacheck" %% "scalacheck" % "1.12.2" % "test", + "org.xerial" % "xerial-core" % "3.3.6" % "test", + "org.msgpack" % "msgpack" % "0.6.11" % "test", + "commons-codec" % "commons-codec" % "1.10" % "test", + "com.typesafe.akka" %% "akka-actor" % "2.3.9" % "test" + ) + ) + +lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-jackson")) + .settings( + name := "jackson-dataformat-msgpack", + description := "Jackson extension that adds support for MessagePack", + libraryDependencies ++= Seq( + "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.3", + junitInterface, + "org.apache.commons" % "commons-math3" % "3.4.1" % "test" + ), + testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") + ).dependsOn(msgpackCore) + + +// Release settings + +import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._ + +releaseTagName := { + (version in ThisBuild).value +} +releaseProcess := Seq[ReleaseStep]( + checkSnapshotDependencies, + inquireVersions, + runClean, + runTest, + setReleaseVersion, + commitReleaseVersion, + tagRelease, + ReleaseStep(action = Command.process("publishSigned", _)), + setNextVersion, + commitNextVersion, + ReleaseStep(action = Command.process("sonatypeReleaseAll", _)), + pushChanges + ) + +// Jacoco code coverage report +jacoco.settings +parallelExecution in jacoco.Config := false + +// Find bugs +findbugsSettings +findbugsReportType := Some(ReportType.FancyHtml) +findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html") + +// Style check config: (sbt-jchekcstyle) +jcheckStyleConfig := "facebook" + +// Run jcheckstyle both for main and test codes +compile <<= (compile in Compile) dependsOn (jcheckStyle in Compile) +compile <<= (compile in Test) dependsOn (jcheckStyle in Test) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index b47278d8f..96af2de32 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -484,8 +484,10 @@ public void testReadPrimitiveObjectViaObjectMapper() ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); assertEquals("foo", objectMapper.readValue(in, new TypeReference() {})); - assertEquals(Long.MAX_VALUE, objectMapper.readValue(in, new TypeReference() {})); - assertEquals(3.14, objectMapper.readValue(in, new TypeReference() {})); + long l = objectMapper.readValue(in, new TypeReference() {}); + assertEquals(Long.MAX_VALUE, l); + double d = objectMapper.readValue(in, new TypeReference() {}); + assertEquals(3.14, d, 0.001); byte[] bs = objectMapper.readValue(in, new TypeReference() {}); assertEquals(bytes.length, bs.length); assertEquals(bytes[0], bs[0]); diff --git a/project/Build.scala b/project/Build.scala deleted file mode 100644 index 3687c74fc..000000000 --- a/project/Build.scala +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2012 Taro L. Saito - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -import de.johoop.findbugs4sbt.ReportType -import sbt._ -import Keys._ -import de.johoop.findbugs4sbt.FindBugs._ -import de.johoop.jacoco4sbt._ -import JacocoPlugin._ -import sbtrelease.ReleasePlugin._ -import sbtrelease.ReleaseStateTransformations._ -import sbtrelease.ReleaseStep -import scala.util.Properties -import xerial.sbt.jcheckstyle.JCheckStyle.JCheckStyleKeys._ - -object Build extends Build { - - val SCALA_VERSION = "2.11.6" - - lazy val buildSettings = Defaults.coreDefaultSettings ++ - releaseSettings ++ - findbugsSettings ++ - jacoco.settings ++ - Seq[Setting[_]]( - organization := "org.msgpack", - organizationName := "MessagePack", - organizationHomepage := Some(new URL("http://msgpack.org/")), - description := "MessagePack for Java", - scalaVersion in Global := SCALA_VERSION, - logBuffered in Test := false, - //parallelExecution in Test := false, - autoScalaLibrary := false, - crossPaths := false, - concurrentRestrictions in Global := Seq( - Tags.limit(Tags.Test, 1) - ), - ReleaseKeys.tagName <<= (version in ThisBuild) map (v => v), - ReleaseKeys.releaseProcess := Seq[ReleaseStep]( - checkSnapshotDependencies, - inquireVersions, - runClean, - runTest, - setReleaseVersion, - commitReleaseVersion, - tagRelease, - ReleaseStep(action = Command.process("publishSigned", _)), - setNextVersion, - commitNextVersion, - ReleaseStep(action = Command.process("sonatypeReleaseAll", _)), - pushChanges - ), - parallelExecution in jacoco.Config := false, - // Since sbt-0.13.2 - incOptions := incOptions.value.withNameHashing(true), - //resolvers += Resolver.mavenLocal, - scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.6", "-feature"), - javaOptions in Test ++= Seq("-ea"), - javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.6", "-target", "1.6"), - javacOptions in doc := { - val opts = Seq("-source", "1.6") - if (Properties.isJavaAtLeast("1.8")) - opts ++ Seq("-Xdoclint:none") - else - opts - }, - findbugsReportType := Some(ReportType.FancyHtml), - findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), - jcheckStyleConfig := "facebook", - compile <<= (compile in Compile) dependsOn (jcheckStyle in Compile), - compile <<= (compile in Test) dependsOn (jcheckStyle in Test) - ) - - import Dependencies._ - - lazy val root = Project( - id = "msgpack-java", - base = file("."), - settings = buildSettings ++ Seq( - // Do not publish the root project - publishArtifact := false, - publish := {}, - publishLocal := {}, - findbugs := { - // do not run findbugs for the root project - } - ) - ).aggregate(msgpackCore, msgpackJackson) - - lazy val msgpackCore = Project( - id = "msgpack-core", - base = file("msgpack-core"), - settings = buildSettings ++ Seq( - description := "Core library of the MessagePack for Java", - libraryDependencies ++= testLib - ) - ) - - lazy val msgpackJackson = Project( - id = "msgpack-jackson", - base = file("msgpack-jackson"), - settings = buildSettings ++ Seq( - name := "jackson-dataformat-msgpack", - description := "Jackson extension that adds support for MessagePack", - libraryDependencies ++= jacksonLib, - testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") - ) - ).dependsOn(msgpackCore) - - object Dependencies { - - val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" - - val testLib = Seq( - "org.scalatest" %% "scalatest" % "2.2.4" % "test", - "org.scalacheck" %% "scalacheck" % "1.12.2" % "test", - "org.xerial" % "xerial-core" % "3.3.6" % "test", - "org.msgpack" % "msgpack" % "0.6.11" % "test", - junitInterface, - "commons-codec" % "commons-codec" % "1.10" % "test", - "com.typesafe.akka" %% "akka-actor"% "2.3.9" % "test" - ) - - val jacksonLib = Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.3", - junitInterface, - "org.apache.commons" % "commons-math3" % "3.4.1" % "test" - ) - } - -} - - - - - - - - diff --git a/project/build.properties b/project/build.properties index 07b0ebbcd..02cb92b32 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=0.13.8 +sbt.version=0.13.9 diff --git a/project/plugins.sbt b/project/plugins.sbt index 0d70c54a7..be8535f05 100755 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,7 @@ -addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.8.5") +addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.0") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "0.5.0") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.0") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") From 1381a513426d20c2046d44badfb2cd5a6f33cecc Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Sun, 15 Nov 2015 10:11:38 -0800 Subject: [PATCH 12/99] Fix code style --- build.sbt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/build.sbt b/build.sbt index c796a80a4..b99461796 100644 --- a/build.sbt +++ b/build.sbt @@ -2,8 +2,7 @@ import de.johoop.findbugs4sbt.ReportType organization := "org.msgpack" organizationName := "MessagePack" -organizationHomepage := Some(new - URL("http://msgpack.org/")) +organizationHomepage := Some(new URL("http://msgpack.org/")) description := "MessagePack for Java" scalaVersion in Global := "2.11.7" logBuffered in Test := false @@ -78,11 +77,9 @@ lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-j // Release settings -import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._ +import ReleaseTransformations._ -releaseTagName := { - (version in ThisBuild).value -} +releaseTagName := { (version in ThisBuild).value } releaseProcess := Seq[ReleaseStep]( checkSnapshotDependencies, inquireVersions, From 0dabac51e9b1190ad7de6e07efcf6c630e89ebb8 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 16 Nov 2015 23:44:15 +0900 Subject: [PATCH 13/99] Benchmark the performance more precisely --- .../org/msgpack/core/MessagePackerTest.scala | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 8ec2487cc..f598a133f 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -22,7 +22,6 @@ import org.msgpack.core.buffer.{ChannelBufferOutput, OutputStreamBufferOutput} import org.msgpack.value.ValueFactory import xerial.core.io.IOUtil -import scala.compat.Platform import scala.util.Random /** @@ -238,22 +237,29 @@ class MessagePackerTest } "pack a lot of String within expected time" in { - val count = 500000 + val count = 20000 - def measureDuration(outputStream: java.io.OutputStream) : Long = { + def measureDuration(outputStream: java.io.OutputStream) = { val packer = MessagePack.newDefaultPacker(outputStream) - val start = Platform.currentTime - for (i <- 0 to count) { + var i = 0 + while (i < count) { packer.packString("0123456789ABCDEF") + i += 1 } packer.close - Platform.currentTime - start } - val baseDuration = measureDuration(new ByteArrayOutputStream()) - val (_, fileOutput) = createTempFileWithOutputStream - val targetDuration = measureDuration(fileOutput) - targetDuration shouldBe <= (baseDuration * 3) + val t = time("packString into OutputStream", repeat = 10) { + block("byte-array-output-stream") { + measureDuration(new ByteArrayOutputStream()) + } + + block("file-output-stream") { + val (_, fileOutput) = createTempFileWithOutputStream + measureDuration(fileOutput) + } + } + t("file-output-stream").averageWithoutMinMax shouldBe < (t("byte-array-output-stream").averageWithoutMinMax * 4) } } From 5c80a861d928d69eff4685271c59d9c8bbe6cedf Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Mon, 16 Nov 2015 23:45:33 +0900 Subject: [PATCH 14/99] Change the param name of configuration to `packerSmallStringOptimizationThreshold` --- .../java/org/msgpack/core/MessagePack.java | 18 +++++++++--------- .../java/org/msgpack/core/MessagePacker.java | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index d7e05369c..1b9d580b5 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -50,7 +50,7 @@ public static class Config private final int stringEncoderBufferSize; private final int stringDecoderBufferSize; private final int packerBufferSize; - private final int packerLargeStringThreshold; + private final int packerSmallStringOptimizationThreshold; // This parameter is subject to change private final int packerRawDataCopyingThreshold; public Config( @@ -62,7 +62,7 @@ public Config( int stringEncoderBufferSize, int stringDecoderBufferSize, int packerBufferSize, - int packerLargeStringLengthThreshold, + int packerSmallStringOptimizationThreshold, int packerRawDataCopyingThreshold) { checkArgument(packerBufferSize > 0, "packer buffer size must be larger than 0: " + packerBufferSize); @@ -77,7 +77,7 @@ public Config( this.stringEncoderBufferSize = stringEncoderBufferSize; this.stringDecoderBufferSize = stringDecoderBufferSize; this.packerBufferSize = packerBufferSize; - this.packerLargeStringThreshold = packerLargeStringLengthThreshold; + this.packerSmallStringOptimizationThreshold = packerSmallStringOptimizationThreshold; this.packerRawDataCopyingThreshold = packerRawDataCopyingThreshold; } @@ -136,9 +136,9 @@ public int getPackerBufferSize() return packerBufferSize; } - public int getPackerLargeStringLengthThreshold() + public int getPackerSmallStringOptimizationThreshold() { - return packerLargeStringThreshold; + return packerSmallStringOptimizationThreshold; } public int getPackerRawDataCopyingThreshold() @@ -162,7 +162,7 @@ public static class ConfigBuilder private int stringEncoderBufferSize = 8192; private int stringDecoderBufferSize = 8192; private int packerBufferSize = 8192; - private int packerLargeStringLengthThreshold = 512; + private int packerSmallStringOptimizationThreshold = 512; // This parameter is subject to change private int packerRawDataCopyingThreshold = 512; public Config build() @@ -176,7 +176,7 @@ public Config build() stringEncoderBufferSize, stringDecoderBufferSize, packerBufferSize, - packerLargeStringLengthThreshold, + packerSmallStringOptimizationThreshold, packerRawDataCopyingThreshold ); } @@ -229,9 +229,9 @@ public ConfigBuilder packerBufferSize(int size) return this; } - public ConfigBuilder packerLargeStringThreshold(int threshold) + public ConfigBuilder packerSmallStringOptimizationThreshold(int threshold) { - this.packerLargeStringLengthThreshold = threshold; + this.packerSmallStringOptimizationThreshold = threshold; return this; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 078d83107..11d673dcd 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -445,7 +445,7 @@ public MessagePacker packDouble(double v) private void packSmallString(String s) throws IOException { - byte[] bytes = s.getBytes("UTF-8"); + byte[] bytes = s.getBytes(MessagePack.UTF8); packRawStringHeader(bytes.length); writePayload(bytes); } @@ -465,7 +465,7 @@ public MessagePacker packString(String s) return this; } - if (s.length() < config.getPackerLargeStringLengthThreshold()) { + if (s.length() < config.getPackerSmallStringOptimizationThreshold()) { // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer packSmallString(s); return this; From f90efe8364896eaa7e0df30953c7fc83c134286d Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Nov 2015 04:47:16 +0900 Subject: [PATCH 15/99] fix build.sbt --- build.sbt | 129 ++++++++++++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/build.sbt b/build.sbt index b99461796..365719b83 100644 --- a/build.sbt +++ b/build.sbt @@ -1,43 +1,71 @@ import de.johoop.findbugs4sbt.ReportType +import ReleaseTransformations._ -organization := "org.msgpack" -organizationName := "MessagePack" -organizationHomepage := Some(new URL("http://msgpack.org/")) -description := "MessagePack for Java" -scalaVersion in Global := "2.11.7" -logBuffered in Test := false -autoScalaLibrary := false -crossPaths := false - -// For performance testing, ensure each test run one-by-one -concurrentRestrictions in Global := Seq( - Tags.limit(Tags.Test, 1) +val buildSettings = findbugsSettings ++ jacoco.settings ++ Seq[Setting[_]]( + organization := "org.msgpack", + organizationName := "MessagePack", + organizationHomepage := Some(new URL("http://msgpack.org/")), + description := "MessagePack for Java", + scalaVersion := "2.11.7", + logBuffered in Test := false, + autoScalaLibrary := false, + crossPaths := false, + // For performance testing, ensure each test run one-by-one + concurrentRestrictions in Global := Seq( + Tags.limit(Tags.Test, 1) + ), + // JVM options for building + scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.6", "-feature"), + javaOptions in Test ++= Seq("-ea"), + javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.6", "-target", "1.6"), + // Use lenient validation mode when generating Javadoc (for Java8) + javacOptions in doc := { + val opts = Seq("-source", "1.6") + if (scala.util.Properties.isJavaAtLeast("1.8")) { + opts ++ Seq("-Xdoclint:none") + } + else { + opts + } + }, + // Release settings + releaseTagName := { (version in ThisBuild).value }, + releaseProcess := Seq[ReleaseStep]( + checkSnapshotDependencies, + inquireVersions, + runClean, + runTest, + setReleaseVersion, + commitReleaseVersion, + tagRelease, + ReleaseStep(action = Command.process("publishSigned", _)), + setNextVersion, + commitNextVersion, + ReleaseStep(action = Command.process("sonatypeReleaseAll", _)), + pushChanges + ), + + // Jacoco code coverage report + parallelExecution in jacoco.Config := false, + + // Find bugs + findbugsReportType := Some(ReportType.FancyHtml), + findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html"), + + // Style check config: (sbt-jchekcstyle) + jcheckStyleConfig := "facebook", + + // Run jcheckstyle both for main and test codes + compile <<= (compile in Compile) dependsOn (jcheckStyle in Compile), + compile <<= (compile in Test) dependsOn (jcheckStyle in Test) ) -incOptions := incOptions.value.withNameHashing(true) - -// JVM options for building -scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-target:jvm-1.6", "-feature") - -javaOptions in Test ++= Seq("-ea") -javacOptions in (Compile, compile) ++= Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "1.6", "-target", "1.6") - -// Use lenient validation mode when generating Javadoc (for Java8) -javacOptions in doc := { - val opts = Seq("-source", "1.6") - if (scala.util.Properties.isJavaAtLeast("1.8")) { - opts ++ Seq("-Xdoclint:none") - } - else { - opts - } -} - val junitInterface = "com.novocode" % "junit-interface" % "0.11" % "test" // Project settings lazy val root = Project(id = "msgpack-java", base = file(".")) .settings( + buildSettings, // Do not publish the root project publishArtifact := false, publish := {}, @@ -49,6 +77,7 @@ lazy val root = Project(id = "msgpack-java", base = file(".")) lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) .settings( + buildSettings, description := "Core library of the MessagePack for Java", libraryDependencies ++= Seq( // msgpack-core should have no external dependencies @@ -64,6 +93,7 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core")) lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-jackson")) .settings( + buildSettings, name := "jackson-dataformat-msgpack", description := "Jackson extension that adds support for MessagePack", libraryDependencies ++= Seq( @@ -73,40 +103,3 @@ lazy val msgpackJackson = Project(id = "msgpack-jackson", base = file("msgpack-j ), testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") ).dependsOn(msgpackCore) - - -// Release settings - -import ReleaseTransformations._ - -releaseTagName := { (version in ThisBuild).value } -releaseProcess := Seq[ReleaseStep]( - checkSnapshotDependencies, - inquireVersions, - runClean, - runTest, - setReleaseVersion, - commitReleaseVersion, - tagRelease, - ReleaseStep(action = Command.process("publishSigned", _)), - setNextVersion, - commitNextVersion, - ReleaseStep(action = Command.process("sonatypeReleaseAll", _)), - pushChanges - ) - -// Jacoco code coverage report -jacoco.settings -parallelExecution in jacoco.Config := false - -// Find bugs -findbugsSettings -findbugsReportType := Some(ReportType.FancyHtml) -findbugsReportPath := Some(crossTarget.value / "findbugs" / "report.html") - -// Style check config: (sbt-jchekcstyle) -jcheckStyleConfig := "facebook" - -// Run jcheckstyle both for main and test codes -compile <<= (compile in Compile) dependsOn (jcheckStyle in Compile) -compile <<= (compile in Test) dependsOn (jcheckStyle in Test) From 1751ba3da5de027c82a01f600ba8144466a79cdb Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 21 Dec 2015 17:13:09 +0900 Subject: [PATCH 16/99] Update sbt-extra --- sbt | 381 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 224 insertions(+), 157 deletions(-) mode change 100755 => 100644 sbt diff --git a/sbt b/sbt old mode 100755 new mode 100644 index 7c9358235..c475bc64b --- a/sbt +++ b/sbt @@ -1,36 +1,27 @@ #!/usr/bin/env bash # # A more capable sbt runner, coincidentally also called sbt. -# Author: Paul Phillips +# Author: Paul Phillips + +set -o pipefail # todo - make this dynamic -declare -r sbt_release_version="0.13.8" -declare -r sbt_unreleased_version="0.13.8-SNAPSHOT" # -sbt-dev doesn't work at present +declare -r sbt_release_version="0.13.9" +declare -r sbt_unreleased_version="0.13.9" declare -r buildProps="project/build.properties" -declare sbt_jar sbt_dir sbt_create sbt_launch_dir -declare scala_version java_home sbt_explicit_version -declare verbose debug quiet noshare batch trace_level log_level -declare sbt_saved_stty - -echoerr () { [[ -z "$quiet" ]] && echo "$@" >&2; } -vlog () { [[ -n "$verbose$debug" ]] && echoerr "$@"; } -dlog () { [[ -n "$debug" ]] && echoerr "$@"; } - -# we'd like these set before we get around to properly processing arguments -for arg in "$@"; do - case "$arg" in - -q|-quiet) quiet=true ;; - -d|-debug) debug=true ;; - -v|-verbose) verbose=true ;; - *) ;; - esac -done +declare sbt_jar sbt_dir sbt_create sbt_version +declare scala_version sbt_explicit_version +declare verbose noshare batch trace_level log_level +declare sbt_saved_stty debugUs + +echoerr () { echo >&2 "$@"; } +vlog () { [[ -n "$verbose" ]] && echoerr "$@"; } # spaces are possible, e.g. sbt.version = 0.13.0 build_props_sbt () { [[ -r "$buildProps" ]] && \ - grep '^sbt\.version' "$buildProps" | tr '=' ' ' | awk '{ print $2; }' + grep '^sbt\.version' "$buildProps" | tr '=\r' ' ' | awk '{ print $2; }' } update_build_props_sbt () { @@ -41,31 +32,24 @@ update_build_props_sbt () { perl -pi -e "s/^sbt\.version\b.*\$/sbt.version=${ver}/" "$buildProps" grep -q '^sbt.version[ =]' "$buildProps" || printf "\nsbt.version=%s\n" "$ver" >> "$buildProps" - echoerr "!!!" - echoerr "!!! Updated file $buildProps setting sbt.version to: $ver" - echoerr "!!! Previous value was: $old" - echoerr "!!!" + vlog "!!!" + vlog "!!! Updated file $buildProps setting sbt.version to: $ver" + vlog "!!! Previous value was: $old" + vlog "!!!" } } -sbt_version () { - if [[ -n "$sbt_explicit_version" ]]; then - echo "$sbt_explicit_version" - else - local v="$(build_props_sbt)" - if [[ -n "$v" ]]; then - echo "$v" - else - echo "$sbt_release_version" - fi - fi +set_sbt_version () { + sbt_version="${sbt_explicit_version:-$(build_props_sbt)}" + [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version + export sbt_version } # restore stty settings (echo in particular) onSbtRunnerExit() { [[ -n "$sbt_saved_stty" ]] || return - dlog "" - dlog "restoring stty: $sbt_saved_stty" + vlog "" + vlog "restoring stty: $sbt_saved_stty" stty "$sbt_saved_stty" unset sbt_saved_stty } @@ -73,7 +57,7 @@ onSbtRunnerExit() { # save stty and trap exit, to ensure echo is reenabled if we are interrupted. trap onSbtRunnerExit EXIT sbt_saved_stty="$(stty -g 2>/dev/null)" -dlog "Saved stty: $sbt_saved_stty" +vlog "Saved stty: $sbt_saved_stty" # this seems to cover the bases on OSX, and someone will # have to tell me about the others. @@ -119,12 +103,13 @@ init_default_option_file () { declare -r cms_opts="-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC" declare -r jit_opts="-XX:ReservedCodeCacheSize=256m -XX:+TieredCompilation" -declare -r default_jvm_opts="-ea -Dfile.encoding=UTF8 -Xms512m -Xmx1536m -Xss2m $jit_opts $cms_opts" +declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m $jit_opts $cms_opts" declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" declare -r latest_28="2.8.2" declare -r latest_29="2.9.3" -declare -r latest_210="2.10.3" -declare -r latest_211="2.11.6" +declare -r latest_210="2.10.5" +declare -r latest_211="2.11.7" +declare -r latest_212="2.12.0-M3" declare -r script_path="$(get_script_path "$BASH_SOURCE")" declare -r script_name="${script_path##*/}" @@ -133,7 +118,7 @@ declare -r script_name="${script_path##*/}" declare java_cmd="java" declare sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)" declare jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)" -declare sbt_launch_repo="http://typesafe.artifactoryonline.com/typesafe/ivy-releases" +declare sbt_launch_repo="http://repo.typesafe.com/typesafe/ivy-releases" # pull -J and -D options to give to java. declare -a residual_args @@ -144,14 +129,79 @@ declare -a sbt_commands # args to jvm/sbt via files or environment variables declare -a extra_jvm_opts extra_sbt_opts -# if set, use JAVA_HOME over java found in path -[[ -e "$JAVA_HOME/bin/java" ]] && java_cmd="$JAVA_HOME/bin/java" +addJava () { + vlog "[addJava] arg = '$1'" + java_args+=("$1") +} +addSbt () { + vlog "[addSbt] arg = '$1'" + sbt_commands+=("$1") +} +setThisBuild () { + vlog "[addBuild] args = '$@'" + local key="$1" && shift + addSbt "set $key in ThisBuild := $@" +} +addScalac () { + vlog "[addScalac] arg = '$1'" + scalac_args+=("$1") +} +addResidual () { + vlog "[residual] arg = '$1'" + residual_args+=("$1") +} +addResolver () { + addSbt "set resolvers += $1" +} +addDebugger () { + addJava "-Xdebug" + addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1" +} +setScalaVersion () { + [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")' + addSbt "++ $1" +} +setJavaHome () { + java_cmd="$1/bin/java" + setThisBuild javaHome "Some(file(\"$1\"))" + export JAVA_HOME="$1" + export JDK_HOME="$1" + export PATH="$JAVA_HOME/bin:$PATH" +} +setJavaHomeQuietly () { + addSbt warn + setJavaHome "$1" + addSbt info +} + +# if set, use JDK_HOME/JAVA_HOME over java found in path +if [[ -e "$JDK_HOME/lib/tools.jar" ]]; then + setJavaHomeQuietly "$JDK_HOME" +elif [[ -e "$JAVA_HOME/bin/java" ]]; then + setJavaHomeQuietly "$JAVA_HOME" +fi # directory to store sbt launchers declare sbt_launch_dir="$HOME/.sbt/launchers" [[ -d "$sbt_launch_dir" ]] || mkdir -p "$sbt_launch_dir" [[ -w "$sbt_launch_dir" ]] || sbt_launch_dir="$(mktemp -d -t sbt_extras_launchers.XXXXXX)" +java_version () { + local version=$("$java_cmd" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d \") + vlog "Detected Java version: $version" + echo "${version:2:1}" +} + +# MaxPermSize critical on pre-8 jvms but incurs noisy warning on 8+ +default_jvm_opts () { + local v="$(java_version)" + if [[ $v -ge 8 ]]; then + echo "$default_jvm_opts_common" + else + echo "-XX:MaxPermSize=384m $default_jvm_opts_common" + fi +} + build_props_scala () { if [[ -r "$buildProps" ]]; then versionLine="$(grep '^build.scala.versions' "$buildProps")" @@ -162,22 +212,20 @@ build_props_scala () { execRunner () { # print the arguments one to a line, quoting any containing spaces - [[ "$verbose" || "$debug" ]] && echo "# Executing command line:" && { + vlog "# Executing command line:" && { for arg; do if [[ -n "$arg" ]]; then if printf "%s\n" "$arg" | grep -q ' '; then - printf "\"%s\"\n" "$arg" + printf >&2 "\"%s\"\n" "$arg" else - printf "%s\n" "$arg" + printf >&2 "%s\n" "$arg" fi fi done - echo "" + vlog "" } - if [[ -n "$batch" ]]; then - exec /dev/null; then - curl --fail --silent "$url" --output "$jar" + curl --fail --silent --location "$url" --output "$jar" elif which wget >/dev/null; then wget --quiet -O "$jar" "$url" fi @@ -207,9 +255,8 @@ download_url () { } acquire_sbt_jar () { - for_sbt_version="$(sbt_version)" - sbt_url="$(jar_url "$for_sbt_version")" - sbt_jar="$(jar_file "$for_sbt_version")" + sbt_url="$(jar_url "$sbt_version")" + sbt_jar="$(jar_file "$sbt_version")" [[ -r "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar" } @@ -218,11 +265,23 @@ usage () { cat < display stack traces with a max of frames (default: -1, traces suppressed) + -debug-inc enable debugging log for the incremental compiler -no-colors disable ANSI color codes -sbt-create start sbt even if current directory contains no sbt project -sbt-dir path to global settings/plugins directory (default: ~/.sbt/) @@ -234,12 +293,12 @@ Usage: $script_name [options] -batch Disable interactive mode -prompt Set the sbt prompt; in expr, 's' is the State and 'e' is Extracted - # sbt version (default: from $buildProps if present, else latest release) - !!! The only way to accomplish this pre-0.12.0 if there is a build.properties file which - !!! contains an sbt.version property is to update the file on disk. That's what this does. + # sbt version (default: sbt.version from $buildProps if present, otherwise $sbt_release_version) + -sbt-force-latest force the use of the latest release of sbt: $sbt_release_version -sbt-version use the specified version of sbt (default: $sbt_release_version) + -sbt-dev use the latest pre-release version of sbt: $sbt_unreleased_version -sbt-jar use the specified jar as the sbt launcher - -sbt-launch-dir directory to hold sbt launchers (default: $sbt_launch_dir) + -sbt-launch-dir directory to hold sbt launchers (default: ~/.sbt/launchers) -sbt-launch-repo repo url for downloading sbt launcher jar (default: $sbt_launch_repo) # scala version (default: as chosen by sbt) @@ -247,6 +306,7 @@ Usage: $script_name [options] -29 use $latest_29 -210 use $latest_210 -211 use $latest_211 + -212 use $latest_212 -scala-home use the scala build at the specified directory -scala-version use the specified version of scala -binary-version use the specified scala version when searching for dependencies @@ -256,7 +316,7 @@ Usage: $script_name [options] # passing options to the jvm - note it does NOT use JAVA_OPTS due to pollution # The default set is used if JVM_OPTS is unset and no -jvm-opts file is found - $default_jvm_opts + $(default_jvm_opts) JVM_OPTS environment variable holding either the jvm args directly, or the reference to a file containing jvm args if given path is prepended by '@' (e.g. '@/etc/jvmopts') Note: "@"-file is overridden by local '.jvmopts' or '-jvm-opts' argument. @@ -273,34 +333,6 @@ Usage: $script_name [options] EOM } -addJava () { - dlog "[addJava] arg = '$1'" - java_args=( "${java_args[@]}" "$1" ) -} -addSbt () { - dlog "[addSbt] arg = '$1'" - sbt_commands=( "${sbt_commands[@]}" "$1" ) -} -addScalac () { - dlog "[addScalac] arg = '$1'" - scalac_args=( "${scalac_args[@]}" "$1" ) -} -addResidual () { - dlog "[residual] arg = '$1'" - residual_args=( "${residual_args[@]}" "$1" ) -} -addResolver () { - addSbt "set resolvers += $1" -} -addDebugger () { - addJava "-Xdebug" - addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1" -} -setScalaVersion () { - [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")' - addSbt "++ $1" -} - process_args () { require_arg () { @@ -314,45 +346,51 @@ process_args () } while [[ $# -gt 0 ]]; do case "$1" in - -h|-help) usage; exit 1 ;; - -v|-verbose) verbose=true && log_level=Info && shift ;; - -d|-debug) debug=true && log_level=Debug && shift ;; - -q|-quiet) quiet=true && log_level=Error && shift ;; - - -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; - -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; - -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; - -no-share) noshare=true && shift ;; - -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; - -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; - -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; - -offline) addSbt "set offline := true" && shift ;; - -jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;; - -batch) batch=true && shift ;; - -prompt) require_arg "expr" "$1" "$2" && addSbt "set shellPrompt in ThisBuild := (s => { val e = Project.extract(s) ; $2 })" && shift 2 ;; - - -sbt-create) sbt_create=true && shift ;; - -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;; - -sbt-version) require_arg version "$1" "$2" && sbt_explicit_version="$2" && shift 2 ;; - -sbt-dev) sbt_explicit_version="$sbt_unreleased_version" && shift ;; --sbt-launch-dir) require_arg path "$1" "$2" && sbt_launch_dir="$2" && shift 2 ;; --sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;; - -scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;; --binary-version) require_arg version "$1" "$2" && addSbt "set scalaBinaryVersion in ThisBuild := \"$2\"" && shift 2 ;; - -scala-home) require_arg path "$1" "$2" && addSbt "set every scalaHome := Some(file(\"$2\"))" && shift 2 ;; - -java-home) require_arg path "$1" "$2" && java_cmd="$2/bin/java" && shift 2 ;; - -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;; - -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;; - - -D*) addJava "$1" && shift ;; - -J*) addJava "${1:2}" && shift ;; - -S*) addScalac "${1:2}" && shift ;; - -28) setScalaVersion "$latest_28" && shift ;; - -29) setScalaVersion "$latest_29" && shift ;; - -210) setScalaVersion "$latest_210" && shift ;; - -211) setScalaVersion "$latest_211" && shift ;; - - *) addResidual "$1" && shift ;; + -h|-help) usage; exit 1 ;; + -v) verbose=true && shift ;; + -d) addSbt "--debug" && addSbt debug && shift ;; + -w) addSbt "--warn" && addSbt warn && shift ;; + -q) addSbt "--error" && addSbt error && shift ;; + -x) debugUs=true && shift ;; + -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; + -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; + -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -no-share) noshare=true && shift ;; + -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; + -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; + -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; + -offline) addSbt "set offline := true" && shift ;; + -jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;; + -batch) batch=true && shift ;; + -prompt) require_arg "expr" "$1" "$2" && setThisBuild shellPrompt "(s => { val e = Project.extract(s) ; $2 })" && shift 2 ;; + + -sbt-create) sbt_create=true && shift ;; + -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;; + -sbt-version) require_arg version "$1" "$2" && sbt_explicit_version="$2" && shift 2 ;; + -sbt-force-latest) sbt_explicit_version="$sbt_release_version" && shift ;; + -sbt-dev) sbt_explicit_version="$sbt_unreleased_version" && shift ;; + -sbt-launch-dir) require_arg path "$1" "$2" && sbt_launch_dir="$2" && shift 2 ;; + -sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;; + -scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;; + -binary-version) require_arg version "$1" "$2" && setThisBuild scalaBinaryVersion "\"$2\"" && shift 2 ;; + -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "Some(file(\"$2\"))" && shift 2 ;; + -java-home) require_arg path "$1" "$2" && setJavaHome "$2" && shift 2 ;; + -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;; + -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;; + + -D*) addJava "$1" && shift ;; + -J*) addJava "${1:2}" && shift ;; + -S*) addScalac "${1:2}" && shift ;; + -28) setScalaVersion "$latest_28" && shift ;; + -29) setScalaVersion "$latest_29" && shift ;; + -210) setScalaVersion "$latest_210" && shift ;; + -211) setScalaVersion "$latest_211" && shift ;; + -212) setScalaVersion "$latest_212" && shift ;; + + --debug) addSbt debug && addResidual "$1" && shift ;; + --warn) addSbt warn && addResidual "$1" && shift ;; + --error) addSbt error && addResidual "$1" && shift ;; + *) addResidual "$1" && shift ;; esac done } @@ -379,21 +417,20 @@ else vlog "No extra sbt options have been defined" fi -[[ -n "$extra_sbt_opts" ]] && process_args "${extra_sbt_opts[@]}" +[[ -n "${extra_sbt_opts[*]}" ]] && process_args "${extra_sbt_opts[@]}" # reset "$@" to the residual args set -- "${residual_args[@]}" argumentCount=$# +# set sbt version +set_sbt_version + # only exists in 0.12+ setTraceLevel() { - case "$(sbt_version)" in - "0.7."* | "0.10."* | "0.11."* ) - echoerr "Cannot set trace level in sbt version $(sbt_version)" - ;; - *) - addSbt "set every traceLevel := $trace_level" - ;; + case "$sbt_version" in + "0.7."* | "0.10."* | "0.11."* ) echoerr "Cannot set trace level in sbt version $sbt_version" ;; + *) setThisBuild traceLevel $trace_level ;; esac } @@ -402,9 +439,9 @@ setTraceLevel() { # Update build.properties on disk to set explicit version - sbt gives us no choice [[ -n "$sbt_explicit_version" ]] && update_build_props_sbt "$sbt_explicit_version" -vlog "Detected sbt version $(sbt_version)" +vlog "Detected sbt version $sbt_version" -[[ -n "$scala_version" ]] && echoerr "Overriding scala version to $scala_version" +[[ -n "$scala_version" ]] && vlog "Overriding scala version to $scala_version" # no args - alert them there's stuff in here (( argumentCount > 0 )) || { @@ -438,10 +475,10 @@ if [[ -n "$noshare" ]]; then addJava "$opt" done else - case "$(sbt_version)" in + case "$sbt_version" in "0.7."* | "0.10."* | "0.11."* | "0.12."* ) [[ -n "$sbt_dir" ]] || { - sbt_dir="$HOME/.sbt/$(sbt_version)" + sbt_dir="$HOME/.sbt/$sbt_version" vlog "Using $sbt_dir as sbt dir, -sbt-dir to override." } ;; @@ -460,22 +497,52 @@ elif [[ -n "$JVM_OPTS" && ! ("$JVM_OPTS" =~ ^@.*) ]]; then extra_jvm_opts=( $JVM_OPTS ) else vlog "Using default jvm options" - extra_jvm_opts=( $default_jvm_opts ) + extra_jvm_opts=( $(default_jvm_opts) ) fi # traceLevel is 0.12+ [[ -n "$trace_level" ]] && setTraceLevel +main () { + execRunner "$java_cmd" \ + "${extra_jvm_opts[@]}" \ + "${java_args[@]}" \ + -jar "$sbt_jar" \ + "${sbt_commands[@]}" \ + "${residual_args[@]}" +} -if [[ -n "$log_level" ]] && [[ "$log_level" != Info ]]; then - sbt_commands=("set logLevel in Global := Level.$log_level" "${sbt_commands[@]}") -fi +# sbt inserts this string on certain lines when formatting is enabled: +# val OverwriteLine = "\r\u001BM\u001B[2K" +# ...in order not to spam the console with a million "Resolving" lines. +# Unfortunately that makes it that much harder to work with when +# we're not going to print those lines anyway. We strip that bit of +# line noise, but leave the other codes to preserve color. +mainFiltered () { + local ansiOverwrite='\r\x1BM\x1B[2K' + local excludeRegex=$(egrep -v '^#|^$' ~/.sbtignore | paste -sd'|' -) + + echoLine () { + local line="$1" + local line1="$(echo "$line" | sed -r 's/\r\x1BM\x1B\[2K//g')" # This strips the OverwriteLine code. + local line2="$(echo "$line1" | sed -r 's/\x1B\[[0-9;]*[JKmsu]//g')" # This strips all codes - we test regexes against this. + + if [[ $line2 =~ $excludeRegex ]]; then + [[ -n $debugUs ]] && echo "[X] $line1" + else + [[ -n $debugUs ]] && echo " $line1" || echo "$line1" + fi + } + + echoLine "Starting sbt with output filtering enabled." + main | while read -r line; do echoLine "$line"; done +} +# Only filter if there's a filter file and we don't see a known interactive command. +# Obviously this is super ad hoc but I don't know how to improve on it. Testing whether +# stdin is a terminal is useless because most of my use cases for this filtering are +# exactly when I'm at a terminal, running sbt non-interactively. +shouldFilter () { [[ -f ~/.sbtignore ]] && ! egrep -q '\b(shell|console|consoleProject)\b' <<<"${residual_args[@]}"; } # run sbt -execRunner "$java_cmd" \ - "${extra_jvm_opts[@]}" \ - "${java_args[@]}" \ - -jar "$sbt_jar" \ - "${sbt_commands[@]}" \ - "${residual_args[@]}" +if shouldFilter; then mainFiltered; else main; fi From ae01c51e5ccdd2c834a171e4e14b6b65294f5b97 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 21 Dec 2015 17:24:06 +0900 Subject: [PATCH 17/99] chmod +x --- sbt | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 sbt diff --git a/sbt b/sbt old mode 100644 new mode 100755 From 6e01b68e581354dd6502b266b1587576a7d62337 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Mon, 21 Dec 2015 21:00:22 +0900 Subject: [PATCH 18/99] optimized unpacker buffer --- .../MessageInsufficientBufferException.java | 40 + .../core/MessageNeverUsedFormatException.java | 38 + .../org/msgpack/core/MessageUnpacker.java | 808 ++++++++++-------- .../msgpack/core/buffer/ArrayBufferInput.java | 5 + .../msgpack/core/buffer/ByteBufferInput.java | 5 + .../core/buffer/ChannelBufferInput.java | 5 + .../core/buffer/InputStreamBufferInput.java | 5 + .../msgpack/core/buffer/MessageBuffer.java | 5 + .../core/buffer/MessageBufferInput.java | 7 +- .../core/buffer/MessageBufferReader.java | 122 +++ .../org/msgpack/core/MessagePackTest.scala | 2 +- .../msgpack/core/MessageUnpackerTest.scala | 2 + .../msgpack/core/buffer/ByteStringTest.scala | 2 + 13 files changed, 689 insertions(+), 357 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java create mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java b/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java new file mode 100644 index 000000000..838dc77ab --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java @@ -0,0 +1,40 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core; + +public class MessageInsufficientBufferException + extends MessagePackException +{ + public MessageInsufficientBufferException() + { + super(); + } + + public MessageInsufficientBufferException(String message) + { + super(message); + } + + public MessageInsufficientBufferException(Throwable cause) + { + super(cause); + } + + public MessageInsufficientBufferException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java b/msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java new file mode 100644 index 000000000..726ffb497 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java @@ -0,0 +1,38 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core; + +/** + * Thrown when the input message pack format is invalid + */ +public class MessageNeverUsedFormatException + extends MessageFormatException +{ + public MessageNeverUsedFormatException(Throwable e) + { + super(e); + } + + public MessageNeverUsedFormatException(String message) + { + super(message); + } + + public MessageNeverUsedFormatException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index c50d183ee..05babb1ce 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -17,6 +17,7 @@ import org.msgpack.core.MessagePack.Code; import org.msgpack.core.buffer.MessageBuffer; +import org.msgpack.core.buffer.MessageBufferReader; import org.msgpack.core.buffer.MessageBufferInput; import org.msgpack.value.ImmutableValue; import org.msgpack.value.Value; @@ -74,10 +75,14 @@ public class MessageUnpacker { private static final MessageBuffer EMPTY_BUFFER = MessageBuffer.wrap(new byte[0]); + private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1; + private final MessagePack.Config config; private MessageBufferInput in; + private byte headByte = HEAD_BYTE_REQUIRED; + /** * Points to the current buffer to read */ @@ -94,19 +99,24 @@ public class MessageUnpacker private long totalReadBytes; /** - * For preserving the next buffer to use + * Extra buffer for fixed-length data at the buffer boundary. At most 17-byte buffer (for FIXEXT16) is required. */ - private MessageBuffer secondaryBuffer = null; + private final MessageBuffer castBuffer = MessageBuffer.newBuffer(24); /** - * Extra buffer for string data at the buffer boundary. Using 17-byte buffer (for FIXEXT16) is sufficient. + * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer. */ - private final MessageBuffer extraBuffer = MessageBuffer.wrap(new byte[24]); + private int readCastBufferPosition; /** - * True if no more data is available from the MessageBufferInput + * For decoding String in unpackString. + */ + private StringBuilder decodeStringBuffer; + + /** + * For decoding String in unpackString. */ - private boolean reachedEOF = false; + private int readingRawRemaining = 0; /** * For decoding String in unpackString. @@ -158,9 +168,9 @@ public MessageBufferInput reset(MessageBufferInput in) this.buffer = EMPTY_BUFFER; this.position = 0; this.totalReadBytes = 0; - this.secondaryBuffer = null; - this.reachedEOF = false; + this.readingRawRemaining = 0; // No need to initialize the already allocated string decoder here since we can reuse it. + return old; } @@ -169,195 +179,118 @@ public long getTotalReadBytes() return totalReadBytes + position; } - private void prepareDecoder() + private byte getHeadByte() + throws IOException { - if (decoder == null) { - decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize); - decoder = MessagePack.UTF8.newDecoder() - .onMalformedInput(config.actionOnMalFormedInput) - .onUnmappableCharacter(config.actionOnUnmappableCharacter); + byte b = headByte; + if (b == HEAD_BYTE_REQUIRED) { + b = headByte = readByte(); + if (b == HEAD_BYTE_REQUIRED) { + throw new MessageNeverUsedFormatException("Encountered 0xC1 NEVER_USED byte"); + } } + return b; } - /** - * Relocate the cursor position so that it points to the real buffer - * - * @return true if it succeeds to move the cursor, or false if there is no more buffer to read - * @throws IOException when failed to retrieve next buffer - */ - private boolean ensureBuffer() - throws IOException + private void resetHeadByte() { - while (buffer != null && position >= buffer.size()) { - // Fetch the next buffer - int bufferSize = buffer.size(); - position -= bufferSize; - totalReadBytes += bufferSize; - buffer = takeNextBuffer(); - } - return buffer != null; + headByte = HEAD_BYTE_REQUIRED; } - private MessageBuffer takeNextBuffer() + private void nextBuffer() throws IOException { - if (reachedEOF) { - return null; - } - - MessageBuffer nextBuffer = null; - if (secondaryBuffer == null) { - nextBuffer = in.next(); - } - else { - nextBuffer = secondaryBuffer; - secondaryBuffer = null; - } - - if (nextBuffer == null) { - reachedEOF = true; + MessageBuffer next = in.next(); + if (next == null) { + throw new MessageInsufficientBufferException(); } - return nextBuffer; + totalReadBytes += buffer.size(); + in.release(buffer); + buffer = next; + position = 0; } - /** - * Ensure that the buffer has the data of at least the specified size. - * - * @param byteSizeToRead the data size to be read - * @return if the buffer can have the data of the specified size returns true, or if the input source reached an EOF, it returns false. - * @throws IOException - */ - private boolean ensure(int byteSizeToRead) + private MessageBuffer readCastBuffer(int length) throws IOException { - if (byteSizeToRead == 0) { - return true; - } - - if (!ensureBuffer()) { - return false; - } - - // The buffer contains the data - if (position + byteSizeToRead <= buffer.size()) { - // OK - return true; + int remaining = buffer.size() - position; + if (remaining >= length) { + readCastBufferPosition = position; + position += length; // here assumes following buffer.getXxx never throws exception + return buffer; } + else { + // TODO loop this method until castBuffer is filled + MessageBuffer next = in.next(); + if (next == null) { + throw new MessageInsufficientBufferException(); + } - // When the data is at the boundary - /* - |---(byte size to read) ----| - -- current buffer --| - |--- extra buffer (slice) --|----| - |-------|---------- secondary buffer (slice) ----------------| - - */ - - // If the byte size to read fits within the extra buffer, use the extraBuffer - MessageBuffer newBuffer = byteSizeToRead <= extraBuffer.size() ? extraBuffer : MessageBuffer.newBuffer(byteSizeToRead); - - // Copy the remaining buffer contents to the new buffer - int firstHalfSize = buffer.size() - position; - if (firstHalfSize > 0) { - buffer.copyTo(position, newBuffer, 0, firstHalfSize); - } + // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer. + // add copy method to MessageBuffer to solve this issue. + castBuffer.putBytes(0, buffer.getArray(), buffer.offset() + position, remaining); + castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining); - // Read the last half contents from the next buffers - int cursor = firstHalfSize; - while (cursor < byteSizeToRead) { - secondaryBuffer = takeNextBuffer(); - if (secondaryBuffer == null) { - return false; // No more buffer to read - } + totalReadBytes += buffer.size(); + in.release(buffer); - // Copy the contents from the secondary buffer to the new buffer - int copyLen = Math.min(byteSizeToRead - cursor, secondaryBuffer.size()); - secondaryBuffer.copyTo(0, newBuffer, cursor, copyLen); + buffer = next; + position = length - remaining; + readCastBufferPosition = 0; - // Truncate the copied part from the secondaryBuffer - secondaryBuffer = copyLen == secondaryBuffer.size() ? null : secondaryBuffer.slice(copyLen, secondaryBuffer.size() - copyLen); - cursor += copyLen; + return castBuffer; } + } - // Replace the current buffer with the new buffer - totalReadBytes += position; - buffer = byteSizeToRead == newBuffer.size() ? newBuffer : newBuffer.slice(0, byteSizeToRead); - position = 0; - - return true; + private static int utf8MultibyteCharacterSize(byte firstByte) + { + System.out.println("first byte: "+(firstByte & 0xff)); + return Integer.numberOfLeadingZeros(~(firstByte & 0xff)); } /** * Returns true true if this unpacker has more elements. * When this returns true, subsequent call to {@link #getNextFormat()} returns an - * MessageFormat instance. If false, {@link #getNextFormat()} will throw an EOFException. + * MessageFormat instance. If false, next {@link #getNextFormat()} call will throw an MessageInsufficientBufferException. * * @return true if this unpacker has more elements to read */ public boolean hasNext() throws IOException { - return ensure(1); + if (buffer.size() <= position) { + MessageBuffer next = in.next(); + if (next == null) { + return false; + } + totalReadBytes += buffer.size(); + in.release(buffer); + buffer = next; + position = 0; + } + return true; } /** * Returns the next MessageFormat type. This method should be called after {@link #hasNext()} returns true. - * If {@link #hasNext()} returns false, calling this method throws {@link java.io.EOFException}. + * If {@link #hasNext()} returns false, calling this method throws {@link MessageInsufficientBufferException}. *

* This method does not proceed the internal cursor. * * @return the next MessageFormat * @throws IOException when failed to read the input data. - * @throws EOFException when the end of file reached, i.e. {@link #hasNext()} == false. + * @throws MessageInsufficientBufferException when the end of file reached, i.e. {@link #hasNext()} == false. */ public MessageFormat getNextFormat() throws IOException { - byte b = lookAhead(); - return MessageFormat.valueOf(b); - } - - /** - * Look-ahead a byte value at the current cursor position. - * This method does not proceed the cursor. - * - * @return - * @throws IOException - */ - private byte lookAhead() - throws IOException - { - if (ensure(1)) { - return buffer.getByte(position); - } - else { - throw new EOFException(); + try { + byte b = getHeadByte(); + return MessageFormat.valueOf(b); } - } - - /** - * Get the head byte value and proceeds the cursor by 1 - */ - private byte consume() - throws IOException - { - byte b = lookAhead(); - position += 1; - return b; - } - - /** - * Proceeds the cursor by the specified byte length - */ - private void consume(int numBytes) - throws IOException - { - assert (numBytes >= 0); - // If position + numBytes becomes negative, it indicates an overflow from Integer.MAX_VALUE. - if (position + numBytes < 0) { - ensureBuffer(); + catch (MessageNeverUsedFormatException ex) { + return MessageFormat.NEVER_USED; } - position += numBytes; } /** @@ -369,81 +302,55 @@ private void consume(int numBytes) private byte readByte() throws IOException { - if (!ensure(1)) { - throw new EOFException("insufficient data length for reading byte value"); + if (buffer.size() > position) { + byte b = buffer.getByte(position); + position++; + return b; + } + else { + nextBuffer(); + if (buffer.size() > 0) { + byte b = buffer.getByte(0); + position = 1; + return b; + } + return readByte(); } - byte b = buffer.getByte(position); - consume(1); - return b; } private short readShort() throws IOException { - if (!ensure(2)) { - throw new EOFException("insufficient data length for reading short value"); - } - short s = buffer.getShort(position); - consume(2); - return s; + MessageBuffer castBuffer = readCastBuffer(2); + return castBuffer.getShort(readCastBufferPosition); } private int readInt() throws IOException { - if (!ensure(4)) { - throw new EOFException("insufficient data length for reading int value"); - } - int i = buffer.getInt(position); - consume(4); - return i; - } - - private float readFloat() - throws IOException - { - if (!ensure(4)) { - throw new EOFException("insufficient data length for reading float value"); - } - float f = buffer.getFloat(position); - consume(4); - return f; + MessageBuffer castBuffer = readCastBuffer(4); + return castBuffer.getInt(readCastBufferPosition); } private long readLong() throws IOException { - if (!ensure(8)) { - throw new EOFException("insufficient data length for reading long value"); - } - long l = buffer.getLong(position); - consume(8); - return l; + MessageBuffer castBuffer = readCastBuffer(8); + return castBuffer.getLong(readCastBufferPosition); } - private double readDouble() + private float readFloat() throws IOException { - if (!ensure(8)) { - throw new EOFException("insufficient data length for reading double value"); - } - double d = buffer.getDouble(position); - consume(8); - return d; + MessageBuffer castBuffer = readCastBuffer(4); + return castBuffer.getFloat(readCastBufferPosition); } - /** - * Skip reading the specified number of bytes. Use this method only if you know skipping data is safe. - * For simply skipping the next value, use {@link #skipValue()}. - * - * @param numBytes - * @throws IOException - */ - public void skipBytes(int numBytes) + private double readDouble() throws IOException { - checkArgument(numBytes >= 0, "skip length must be >= 0: " + numBytes); - consume(numBytes); + MessageBuffer castBuffer = readCastBuffer(8); + return castBuffer.getDouble(readCastBufferPosition); } /** @@ -456,12 +363,9 @@ public void skipValue() { int remainingValues = 1; while (remainingValues > 0) { - if (reachedEOF) { - throw new EOFException(); - } - - MessageFormat f = getNextFormat(); - byte b = consume(); + byte b = getHeadByte(); + MessageFormat f = MessageFormat.valueOf(b); + resetHeadByte(); switch (f) { case POSFIXINT: case NEGFIXINT: @@ -480,62 +384,62 @@ public void skipValue() } case FIXSTR: { int strLen = b & 0x1f; - consume(strLen); + skipPayload(strLen); break; } case INT8: case UINT8: - consume(1); + skipPayload(1); break; case INT16: case UINT16: - consume(2); + skipPayload(2); break; case INT32: case UINT32: case FLOAT32: - consume(4); + skipPayload(4); break; case INT64: case UINT64: case FLOAT64: - consume(8); + skipPayload(8); break; case BIN8: case STR8: - consume(readNextLength8()); + skipPayload(readNextLength8()); break; case BIN16: case STR16: - consume(readNextLength16()); + skipPayload(readNextLength16()); break; case BIN32: case STR32: - consume(readNextLength32()); + skipPayload(readNextLength32()); break; case FIXEXT1: - consume(2); + skipPayload(2); break; case FIXEXT2: - consume(3); + skipPayload(3); break; case FIXEXT4: - consume(5); + skipPayload(5); break; case FIXEXT8: - consume(9); + skipPayload(9); break; case FIXEXT16: - consume(17); + skipPayload(17); break; case EXT8: - consume(readNextLength8() + 1); + skipPayload(readNextLength8() + 1); break; case EXT16: - consume(readNextLength16() + 1); + skipPayload(readNextLength16() + 1); break; case EXT32: - consume(readNextLength32() + 1); + skipPayload(readNextLength32() + 1); break; case ARRAY16: remainingValues += readNextLength16(); @@ -709,8 +613,9 @@ public Variable unpackValue(Variable var) public void unpackNil() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (b == Code.NIL) { + resetHeadByte(); return; } throw unexpected("Nil", b); @@ -719,66 +624,76 @@ public void unpackNil() public boolean unpackBoolean() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (b == Code.FALSE) { + resetHeadByte(); return false; } else if (b == Code.TRUE) { + resetHeadByte(); return true; } - throw unexpected("boolean", b); } public byte unpackByte() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); if (u8 < (byte) 0) { throw overflowU8(u8); } return u8; case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); if (u16 < 0 || u16 > Byte.MAX_VALUE) { throw overflowU16(u16); } return (byte) u16; case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0 || u32 > Byte.MAX_VALUE) { throw overflowU32(u32); } return (byte) u32; case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L || u64 > Byte.MAX_VALUE) { throw overflowU64(u64); } return (byte) u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) { throw overflowI16(i16); } return (byte) i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) { throw overflowI32(i32); } return (byte) i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) { throw overflowI64(i64); } @@ -790,27 +705,32 @@ public byte unpackByte() public short unpackShort() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return (short) b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return (short) (u8 & 0xff); case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); if (u16 < (short) 0) { throw overflowU16(u16); } return u16; case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0 || u32 > Short.MAX_VALUE) { throw overflowU32(u32); } return (short) u32; case Code.UINT64: // unsigned int 64 + resetHeadByte(); long u64 = readLong(); if (u64 < 0L || u64 > Short.MAX_VALUE) { throw overflowU64(u64); @@ -818,18 +738,22 @@ public short unpackShort() return (short) u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return (short) i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) { throw overflowI32(i32); } return (short) i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) { throw overflowI64(i64); } @@ -841,40 +765,49 @@ public short unpackShort() public int unpackInt() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return (int) b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return u8 & 0xff; case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); return u16 & 0xffff; case Code.UINT32: // unsigned int 32 int u32 = readInt(); if (u32 < 0) { throw overflowU32(u32); } + resetHeadByte(); return u32; case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) { throw overflowU64(u64); } return (int) u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); return i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) { throw overflowI64(i64); } @@ -886,19 +819,23 @@ public int unpackInt() public long unpackLong() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return (long) b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return (long) (u8 & 0xff); case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); return (long) (u16 & 0xffff); case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0) { return (long) (u32 & 0x7fffffff) + 0x80000000L; } @@ -907,21 +844,26 @@ public long unpackLong() } case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L) { throw overflowU64(u64); } return u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return (long) i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return (long) i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); return (long) i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); return i64; } throw unexpected("Integer", b); @@ -930,19 +872,23 @@ public long unpackLong() public BigInteger unpackBigInteger() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return BigInteger.valueOf((long) b); } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return BigInteger.valueOf((long) (u8 & 0xff)); case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); return BigInteger.valueOf((long) (u16 & 0xffff)); case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0) { return BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); } @@ -951,6 +897,7 @@ public BigInteger unpackBigInteger() } case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L) { BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); return bi; @@ -960,15 +907,19 @@ public BigInteger unpackBigInteger() } case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return BigInteger.valueOf((long) i8); case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return BigInteger.valueOf((long) i16); case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); return BigInteger.valueOf((long) i32); case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); return BigInteger.valueOf(i64); } throw unexpected("Integer", b); @@ -977,13 +928,15 @@ public BigInteger unpackBigInteger() public float unpackFloat() throws IOException { - byte b = consume(); + byte b = getHeadByte(); switch (b) { case Code.FLOAT32: // float float fv = readFloat(); + resetHeadByte(); return fv; case Code.FLOAT64: // double double dv = readDouble(); + resetHeadByte(); return (float) dv; } throw unexpected("Float", b); @@ -992,13 +945,15 @@ public float unpackFloat() public double unpackDouble() throws IOException { - byte b = consume(); + byte b = getHeadByte(); switch (b) { case Code.FLOAT32: // float float fv = readFloat(); + resetHeadByte(); return (double) fv; case Code.FLOAT64: // double double dv = readDouble(); + resetHeadByte(); return dv; } throw unexpected("Float", b); @@ -1006,107 +961,191 @@ public double unpackDouble() private static final String EMPTY_STRING = ""; + private void resetDecoder() + { + if (decoder == null) { + decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize); + decoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(config.actionOnMalFormedInput) + .onUnmappableCharacter(config.actionOnUnmappableCharacter); + } + else { + decoder.reset(); + } + decodeStringBuffer = new StringBuilder(); + } + + /** + * This method is not repeatable. + */ public String unpackString() throws IOException { - int strLen = unpackRawStringHeader(); - if (strLen > 0) { - if (strLen > config.maxUnpackStringSize) { - throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, strLen), strLen); + if (readingRawRemaining == 0) { + int len = unpackRawStringHeader(); + if (len == 0) { + return EMPTY_STRING; + } + if (len > config.maxUnpackStringSize) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, len), len); } + if (buffer.size() - position >= len) { + return decodeStringFastPath(len); + } + readingRawRemaining = len; + resetDecoder(); + } - prepareDecoder(); - assert (decoder != null); + assert (decoder != null); - decoder.reset(); + try { + while (readingRawRemaining > 0) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= readingRawRemaining) { + ByteBuffer bb = buffer.toByteBuffer(position, readingRawRemaining); + int bbStartPosition = bb.position(); + decodeBuffer.clear(); - try { - int cursor = 0; - decodeBuffer.clear(); - StringBuilder sb = new StringBuilder(); - - boolean hasIncompleteMultiBytes = false; - while (cursor < strLen) { - int readLen = Math.min(position < buffer.size() ? buffer.size() - position : buffer.size(), strLen - cursor); - if (hasIncompleteMultiBytes) { - // Prepare enough buffer for decoding multi-bytes character right after running into incomplete one - readLen = Math.min(config.stringDecoderBufferSize, strLen - cursor); + CoderResult cr = decoder.decode(bb, decodeBuffer, true); + int readLen = bb.position() - bbStartPosition; + position += readLen; + readingRawRemaining -= readLen; + decodeStringBuffer.append(decodeBuffer.flip()); + + if (cr.isError()) { + handleCoderError(cr); } - if (!ensure(readLen)) { - throw new EOFException(); + if (cr.isUnderflow() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) { + throw new MalformedInputException(cr.length()); } - hasIncompleteMultiBytes = false; - ByteBuffer bb = buffer.toByteBuffer(position, readLen); - int startPos = bb.position(); - - while (bb.hasRemaining()) { - boolean endOfInput = (cursor + readLen) >= strLen; - CoderResult cr = decoder.decode(bb, decodeBuffer, endOfInput); - - if (endOfInput && cr.isUnderflow()) { - cr = decoder.flush(decodeBuffer); - } - - if (cr.isOverflow()) { - // The output CharBuffer has insufficient space - decoder.reset(); - } - - if (cr.isUnderflow() && bb.hasRemaining()) { - // input buffer doesn't have enough bytes for multi bytes characters - if (config.actionOnMalFormedInput == CodingErrorAction.REPORT) { - throw new MalformedInputException(strLen); + if (cr.isOverflow()) { + // go to next loop + } + else { + break; + } + } + else if (bufferRemaining == 0) { + nextBuffer(); + } + else { + ByteBuffer bb = buffer.toByteBuffer(position, bufferRemaining); + int bbStartPosition = bb.position(); + decodeBuffer.clear(); + + CoderResult cr = decoder.decode(bb, decodeBuffer, false); + int readLen = bb.position() - bbStartPosition; + position += readLen; + readingRawRemaining -= readLen; + decodeStringBuffer.append(decodeBuffer.flip()); + + if (cr.isError()) { + handleCoderError(cr); + } + if (cr.isUnderflow() && readLen < bufferRemaining) { + // handle incomplete multibyte character + int incompleteMultiBytes = utf8MultibyteCharacterSize(buffer.getByte(position)); + ByteBuffer multiByteBuffer = ByteBuffer.allocate(incompleteMultiBytes); + buffer.getBytes(position, buffer.size() - position, multiByteBuffer); + + // read until multiByteBuffer is filled + while (true) { + nextBuffer(); + + int more = multiByteBuffer.remaining(); + if (buffer.size() >= more) { + buffer.getBytes(0, more, multiByteBuffer); + position = more; + break; + } + else { + buffer.getBytes(0, buffer.size(), multiByteBuffer); + position = buffer.size(); } - hasIncompleteMultiBytes = true; - // Proceed the cursor with the length already decoded successfully. - readLen = bb.position() - startPos; } - + multiByteBuffer.position(0); + decodeBuffer.clear(); + cr = decoder.decode(multiByteBuffer, decodeBuffer, false); if (cr.isError()) { - if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || - (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { + handleCoderError(cr); + } + if (cr.isUnderflow() || cr.isOverflow()) { + // isOverflow or isOverflow must not happen. if happened, throw exception + try { cr.throwException(); + throw new MessageFormatException("Unexpected UTF-8 multibyte sequence"); + } + catch (Exception ex) { + throw new MessageFormatException("Unexpected UTF-8 multibyte sequence", ex); } } - - decodeBuffer.flip(); - sb.append(decodeBuffer); - - decodeBuffer.clear(); - - if (hasIncompleteMultiBytes) { - break; - } + readingRawRemaining -= multiByteBuffer.limit(); + decodeStringBuffer.append(decodeBuffer.flip()); } - - cursor += readLen; - consume(readLen); } + } + return decodeStringBuffer.toString(); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + } - return sb.toString(); + private void handleCoderError(CoderResult cr) + throws CharacterCodingException + { + if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || + (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { + cr.throwException(); + } + } + + private String decodeStringFastPath(int length) + { + if (config.actionOnMalFormedInput == CodingErrorAction.REPLACE && + config.actionOnUnmappableCharacter == CodingErrorAction.REPLACE && + buffer.hasArray()) { + String s = new String(buffer.getArray(), position, length, MessagePack.UTF8); + position += length; + return s; + } + else { + resetDecoder(); + ByteBuffer bb = buffer.toByteBuffer(); + bb.limit(position + length); + bb.position(position); + CharBuffer cb; + try { + cb = decoder.decode(bb); } catch (CharacterCodingException e) { throw new MessageStringCodingException(e); } - } - else { - return EMPTY_STRING; + position += length; + return cb.toString(); } } public int unpackArrayHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedArray(b)) { // fixarray + resetHeadByte(); return b & 0x0f; } switch (b) { - case Code.ARRAY16: // array 16 - return readNextLength16(); - case Code.ARRAY32: // array 32 - return readNextLength32(); + case Code.ARRAY16: { // array 16 + int len = readNextLength16(); + resetHeadByte(); + return len; + } + case Code.ARRAY32: { // array 32 + int len = readNextLength32(); + resetHeadByte(); + return len; + } } throw unexpected("Array", b); } @@ -1114,15 +1153,22 @@ public int unpackArrayHeader() public int unpackMapHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedMap(b)) { // fixmap + resetHeadByte(); return b & 0x0f; } switch (b) { - case Code.MAP16: // map 16 - return readNextLength16(); - case Code.MAP32: // map 32 - return readNextLength32(); + case Code.MAP16: { // map 16 + int len = readNextLength16(); + resetHeadByte(); + return len; + } + case Code.MAP32: { // map 32 + int len = readNextLength32(); + resetHeadByte(); + return len; + } } throw unexpected("Map", b); } @@ -1130,31 +1176,58 @@ public int unpackMapHeader() public ExtensionTypeHeader unpackExtensionTypeHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); switch (b) { - case Code.FIXEXT1: - return new ExtensionTypeHeader(readByte(), 1); - case Code.FIXEXT2: - return new ExtensionTypeHeader(readByte(), 2); - case Code.FIXEXT4: - return new ExtensionTypeHeader(readByte(), 4); - case Code.FIXEXT8: - return new ExtensionTypeHeader(readByte(), 8); - case Code.FIXEXT16: - return new ExtensionTypeHeader(readByte(), 16); - case Code.EXT8: { - int length = readNextLength8(); + case Code.FIXEXT1: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 1); + } + case Code.FIXEXT2: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 2); + } + case Code.FIXEXT4: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 4); + } + case Code.FIXEXT8: { byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 8); + } + case Code.FIXEXT16: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 16); + } + case Code.EXT8: { + MessageBuffer castBuffer = readCastBuffer(2); + resetHeadByte(); + int u8 = castBuffer.getByte(readCastBufferPosition); + int length = u8 & 0xff; + byte type = castBuffer.getByte(readCastBufferPosition + 1); return new ExtensionTypeHeader(type, length); } case Code.EXT16: { - int length = readNextLength16(); - byte type = readByte(); + MessageBuffer castBuffer = readCastBuffer(3); + resetHeadByte(); + int u16 = castBuffer.getShort(readCastBufferPosition); + int length = u16 & 0xffff; + byte type = castBuffer.getByte(readCastBufferPosition + 2); return new ExtensionTypeHeader(type, length); } case Code.EXT32: { - int length = readNextLength32(); - byte type = readByte(); + MessageBuffer castBuffer = readCastBuffer(5); + resetHeadByte(); + int u32 = castBuffer.getInt(readCastBufferPosition); + if (u32 < 0) { + throw overflowU32Size(u32); + } + int length = u32; + byte type = castBuffer.getByte(readCastBufferPosition + 4); return new ExtensionTypeHeader(type, length); } } @@ -1162,7 +1235,7 @@ public ExtensionTypeHeader unpackExtensionTypeHeader() throw unexpected("Ext", b); } - private int readStringHeader(byte b) + private int tryReadStringHeader(byte b) throws IOException { switch (b) { @@ -1177,7 +1250,7 @@ private int readStringHeader(byte b) } } - private int readBinaryHeader(byte b) + private int tryReadBinaryHeader(byte b) throws IOException { switch (b) { @@ -1195,18 +1268,21 @@ private int readBinaryHeader(byte b) public int unpackRawStringHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedRaw(b)) { // FixRaw + resetHeadByte(); return b & 0x1f; } - int len = readStringHeader(b); + int len = tryReadStringHeader(b); if (len >= 0) { + resetHeadByte(); return len; } if (config.readBinaryAsString) { - len = readBinaryHeader(b); + len = tryReadBinaryHeader(b); if (len >= 0) { + resetHeadByte(); return len; } } @@ -1216,36 +1292,65 @@ public int unpackRawStringHeader() public int unpackBinaryHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedRaw(b)) { // FixRaw + resetHeadByte(); return b & 0x1f; } - int len = readBinaryHeader(b); + int len = tryReadBinaryHeader(b); if (len >= 0) { + resetHeadByte(); return len; } if (config.readStringAsBinary) { - len = readStringHeader(b); + len = tryReadStringHeader(b); if (len >= 0) { + resetHeadByte(); return len; } } throw unexpected("Binary", b); } - // TODO returns a buffer reference to the payload (zero-copy) + /** + * Skip reading the specified number of bytes. Use this method only if you know skipping data is safe. + * For simply skipping the next value, use {@link #skipValue()}. + * + * @param numBytes + * @throws IOException + */ + private void skipPayload(int numBytes) + throws IOException + { + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= numBytes) { + position += numBytes; + return; + } + else { + position += bufferRemaining; + } + nextBuffer(); + } + } public void readPayload(ByteBuffer dst) throws IOException { - while (dst.remaining() > 0) { - if (!ensureBuffer()) { - throw new EOFException(); + while (true) { + int dstRemaining = dst.remaining(); + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= dstRemaining) { + buffer.getBytes(position, dstRemaining, dst); + position += dstRemaining; + return; } - int l = Math.min(buffer.size() - position, dst.remaining()); - buffer.getBytes(position, l, dst); - consume(l); + buffer.getBytes(position, bufferRemaining, dst); + position += bufferRemaining; + + nextBuffer(); } } @@ -1274,29 +1379,22 @@ public byte[] readPayload(int length) public void readPayload(byte[] dst, int off, int len) throws IOException { - int writtenLen = 0; - while (writtenLen < len) { - if (!ensureBuffer()) { - throw new EOFException(); - } - int l = Math.min(buffer.size() - position, len - writtenLen); - buffer.getBytes(position, dst, off + writtenLen, l); - consume(l); - writtenLen += l; - } + // TODO optimize + readPayload(ByteBuffer.wrap(dst, off, len)); } public MessageBuffer readPayloadAsReference(int length) throws IOException { - checkArgument(length >= 0); - if (!ensure(length)) { - throw new EOFException(); + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= length) { + MessageBuffer slice = buffer.slice(position, length); + position += length; + return slice; } - - MessageBuffer ref = buffer.slice(position, length); - position += length; - return ref; + MessageBuffer dst = MessageBuffer.newBuffer(length); + readPayload(dst.getReference()); + return dst; } private int readNextLength8() diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 88fe45942..35f76c14c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -87,4 +87,9 @@ public void close() buffer = null; isRead = false; } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index b9b4304ad..1f60b3fec 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -66,4 +66,9 @@ public void close() { // Nothing to do } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index 4b8baeb75..6dd262599 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -85,4 +85,9 @@ public void close() { channel.close(); } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java index 81aabd762..b0d42e4a0 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java @@ -93,4 +93,9 @@ public void close() { in.close(); } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 4dd1396f1..46a777af0 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -328,6 +328,11 @@ else if (bb.hasArray()) { this.reference = reference; } + public MessageBufferReader newReader() + { + return new MessageBufferReader(this); + } + /** * byte size of the buffer * diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index 786ce2721..2a92160b2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -27,9 +27,14 @@ public interface MessageBufferInput /** * Get a next buffer to read. * - * @return the next MessageBuffer, or null if no more buffer is available. + * @return the next MessageBuffer, or return null if no more buffer is available. * @throws IOException when error occurred when reading the data */ public MessageBuffer next() throws IOException; + + /** + * Release an unused buffer formerly returned by next() method. + */ + public void release(MessageBuffer buffer); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java new file mode 100644 index 000000000..f9656d22d --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java @@ -0,0 +1,122 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core.buffer; + +public class MessageBufferReader +{ + // TODO add more reader methods for each type + + private MessageBuffer buffer; + private int position; + + MessageBufferReader(MessageBuffer buffer) + { + this.buffer = buffer; + } + + public MessageBuffer buffer() + { + return buffer; + } + + public int position() + { + return position; + } + + public void position(int newPosition) + { + // TODO validation? + this.position = newPosition; + } + + public int remaining() + { + return buffer.size() - position; + } + + public byte getByte() + { + return buffer.getByte(position); + } + + public byte readByte() + { + byte v = buffer.getByte(position); + position += 1; + return v; + } + + public short getShort() + { + return buffer.getShort(position); + } + + public short readShort() + { + short v = buffer.getShort(position); + position += 1; + return v; + } + + public int getInt() + { + return buffer.getInt(position); + } + + public int readInt() + { + int v = buffer.getInt(position); + position += 1; + return v; + } + + public long getLong() + { + return buffer.getLong(position); + } + + public long readLong() + { + long v = buffer.getLong(position); + position += 1; + return v; + } + + public float getFloat() + { + return buffer.getFloat(position); + } + + public float readFloat() + { + float v = buffer.getFloat(position); + position += 1; + return v; + } + + public double getDouble() + { + return buffer.getDouble(position); + } + + public double readDouble() + { + double v = buffer.getDouble(position); + position += 1; + return v; + } +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 62bf8ae82..f903cf88d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -469,4 +469,4 @@ class MessagePackTest extends MessagePackSpec { } } -} \ No newline at end of file +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 672edd615..179ca5eb1 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -261,6 +261,8 @@ class MessageUnpackerTest extends MessagePackSpec { } } + override def release(buffer: MessageBuffer): Unit = {} + override def close(): Unit = {} } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 362038d95..39526a0ce 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -39,6 +39,8 @@ class ByteStringTest messageBuffer } + override def release(buffer: MessageBuffer): Unit = {} + override def close(): Unit = {} } From 606cf982dd2a2d55dd22a456b4f125ac022f158c Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 22 Dec 2015 10:16:31 +0900 Subject: [PATCH 19/99] Use the local sbt script since TravisCI crashes with the pre-installed sbt --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e30cdb222..59686eaf6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,5 +10,5 @@ branches: - /^v07.*$/ script: - - sbt test - - sbt test -J-Dmsgpack.universal-buffer=true + - ./sbt test + - ./sbt test -J-Dmsgpack.universal-buffer=true From 70098b3b4dfbc9774becddc0d8c17a29d5d7c659 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 22 Dec 2015 10:21:03 +0900 Subject: [PATCH 20/99] Test container-based TravicCI infrastructure --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 59686eaf6..1159165a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: scala +sudo: false + jdk: - openjdk7 - oraclejdk7 From 749684805ada554bbd7cac741755a843e23085c9 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 22 Dec 2015 10:29:09 +0900 Subject: [PATCH 21/99] Cache dependency directories for mvn and sbt --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1159165a7..9dd79943e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,11 @@ language: scala +cache: + directories: + - $HOME/.m2/repository/ + - $HOME/.ivy2/cache/ + - $HOME/.sbt/boot/ + sudo: false jdk: From 61f86994e21858d16306023077a2b1561c0bf5e8 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 22 Dec 2015 10:39:03 +0900 Subject: [PATCH 22/99] fixed MessageUnpacker.utf8MultibyteCharacterSize --- .../org/msgpack/core/MessageUnpacker.java | 29 +++-- .../msgpack/core/buffer/MessageBuffer.java | 7 +- .../core/buffer/MessageBufferReader.java | 122 ------------------ sbt | 0 4 files changed, 20 insertions(+), 138 deletions(-) delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java mode change 100644 => 100755 sbt diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 05babb1ce..b22c98dfb 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -17,7 +17,6 @@ import org.msgpack.core.MessagePack.Code; import org.msgpack.core.buffer.MessageBuffer; -import org.msgpack.core.buffer.MessageBufferReader; import org.msgpack.core.buffer.MessageBufferInput; import org.msgpack.value.ImmutableValue; import org.msgpack.value.Value; @@ -186,7 +185,7 @@ private byte getHeadByte() if (b == HEAD_BYTE_REQUIRED) { b = headByte = readByte(); if (b == HEAD_BYTE_REQUIRED) { - throw new MessageNeverUsedFormatException("Encountered 0xC1 NEVER_USED byte"); + throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte"); } } return b; @@ -205,7 +204,9 @@ private void nextBuffer() throw new MessageInsufficientBufferException(); } totalReadBytes += buffer.size(); - in.release(buffer); + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + } buffer = next; position = 0; } @@ -232,7 +233,9 @@ private MessageBuffer readCastBuffer(int length) castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining); totalReadBytes += buffer.size(); - in.release(buffer); + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + } buffer = next; position = length - remaining; @@ -244,8 +247,7 @@ private MessageBuffer readCastBuffer(int length) private static int utf8MultibyteCharacterSize(byte firstByte) { - System.out.println("first byte: "+(firstByte & 0xff)); - return Integer.numberOfLeadingZeros(~(firstByte & 0xff)); + return Integer.numberOfLeadingZeros(~(firstByte & 0xff) << 24); } /** @@ -264,7 +266,9 @@ public boolean hasNext() return false; } totalReadBytes += buffer.size(); - in.release(buffer); + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + } buffer = next; position = 0; } @@ -490,7 +494,7 @@ public ImmutableValue unpackValue() MessageFormat mf = getNextFormat(); switch (mf.getValueType()) { case NIL: - unpackNil(); + readByte(); return ValueFactory.newNil(); case BOOLEAN: return ValueFactory.newBoolean(unpackBoolean()); @@ -1070,7 +1074,7 @@ else if (bufferRemaining == 0) { if (cr.isError()) { handleCoderError(cr); } - if (cr.isUnderflow() || cr.isOverflow()) { + if (cr.isOverflow() || (cr.isUnderflow() && multiByteBuffer.position() < multiByteBuffer.limit())) { // isOverflow or isOverflow must not happen. if happened, throw exception try { cr.throwException(); @@ -1106,7 +1110,7 @@ private String decodeStringFastPath(int length) if (config.actionOnMalFormedInput == CodingErrorAction.REPLACE && config.actionOnUnmappableCharacter == CodingErrorAction.REPLACE && buffer.hasArray()) { - String s = new String(buffer.getArray(), position, length, MessagePack.UTF8); + String s = new String(buffer.getArray(), buffer.offset() + position, length, MessagePack.UTF8); position += length; return s; } @@ -1425,6 +1429,11 @@ private int readNextLength32() public void close() throws IOException { + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + buffer = EMPTY_BUFFER; + position = 0; + } in.close(); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 46a777af0..302105f83 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -328,11 +328,6 @@ else if (bb.hasArray()) { this.reference = reference; } - public MessageBufferReader newReader() - { - return new MessageBufferReader(this); - } - /** * byte size of the buffer * @@ -408,7 +403,7 @@ public void getBytes(int index, byte[] dst, int dstOffset, int length) public void getBytes(int index, int len, ByteBuffer dst) { - if (dst.remaining() > len) { + if (dst.remaining() < len) { throw new BufferOverflowException(); } ByteBuffer src = toByteBuffer(index, len); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java deleted file mode 100644 index f9656d22d..000000000 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java +++ /dev/null @@ -1,122 +0,0 @@ -// -// MessagePack for Java -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -package org.msgpack.core.buffer; - -public class MessageBufferReader -{ - // TODO add more reader methods for each type - - private MessageBuffer buffer; - private int position; - - MessageBufferReader(MessageBuffer buffer) - { - this.buffer = buffer; - } - - public MessageBuffer buffer() - { - return buffer; - } - - public int position() - { - return position; - } - - public void position(int newPosition) - { - // TODO validation? - this.position = newPosition; - } - - public int remaining() - { - return buffer.size() - position; - } - - public byte getByte() - { - return buffer.getByte(position); - } - - public byte readByte() - { - byte v = buffer.getByte(position); - position += 1; - return v; - } - - public short getShort() - { - return buffer.getShort(position); - } - - public short readShort() - { - short v = buffer.getShort(position); - position += 1; - return v; - } - - public int getInt() - { - return buffer.getInt(position); - } - - public int readInt() - { - int v = buffer.getInt(position); - position += 1; - return v; - } - - public long getLong() - { - return buffer.getLong(position); - } - - public long readLong() - { - long v = buffer.getLong(position); - position += 1; - return v; - } - - public float getFloat() - { - return buffer.getFloat(position); - } - - public float readFloat() - { - float v = buffer.getFloat(position); - position += 1; - return v; - } - - public double getDouble() - { - return buffer.getDouble(position); - } - - public double readDouble() - { - double v = buffer.getDouble(position); - position += 1; - return v; - } -} diff --git a/sbt b/sbt old mode 100644 new mode 100755 From b182ed2ee4d09755d0b1272b414eeffeb915be6e Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 22 Dec 2015 18:18:42 +0900 Subject: [PATCH 23/99] Remove release method from MessageBufferInput --- .../org/msgpack/core/MessageUnpacker.java | 16 ++-------------- .../msgpack/core/buffer/ArrayBufferInput.java | 4 ---- .../msgpack/core/buffer/ByteBufferInput.java | 4 ---- .../core/buffer/ChannelBufferInput.java | 19 ++++--------------- .../core/buffer/InputStreamBufferInput.java | 17 ++--------------- .../core/buffer/MessageBufferInput.java | 6 ++---- .../msgpack/core/MessageUnpackerTest.scala | 2 -- .../msgpack/core/buffer/ByteStringTest.scala | 3 --- 8 files changed, 10 insertions(+), 61 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index b22c98dfb..70a050990 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -204,9 +204,6 @@ private void nextBuffer() throw new MessageInsufficientBufferException(); } totalReadBytes += buffer.size(); - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - } buffer = next; position = 0; } @@ -233,9 +230,6 @@ private MessageBuffer readCastBuffer(int length) castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining); totalReadBytes += buffer.size(); - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - } buffer = next; position = length - remaining; @@ -266,9 +260,6 @@ public boolean hasNext() return false; } totalReadBytes += buffer.size(); - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - } buffer = next; position = 0; } @@ -1429,11 +1420,8 @@ private int readNextLength32() public void close() throws IOException { - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - buffer = EMPTY_BUFFER; - position = 0; - } + buffer = EMPTY_BUFFER; + position = 0; in.close(); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 35f76c14c..a777b8a73 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -88,8 +88,4 @@ public void close() isRead = false; } - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index 1f60b3fec..034d8882b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -67,8 +67,4 @@ public void close() // Nothing to do } - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index 6dd262599..73dcb5db6 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -29,8 +29,7 @@ public class ChannelBufferInput implements MessageBufferInput { private ReadableByteChannel channel; - private boolean reachedEOF = false; - private final int bufferSize; + private final MessageBuffer m; public ChannelBufferInput(ReadableByteChannel channel) { @@ -41,7 +40,7 @@ public ChannelBufferInput(ReadableByteChannel channel, int bufferSize) { this.channel = checkNotNull(channel, "input channel is null"); checkArgument(bufferSize > 0, "buffer size must be > 0: " + bufferSize); - this.bufferSize = bufferSize; + this.m = MessageBuffer.newBuffer(bufferSize); } /** @@ -55,7 +54,6 @@ public ReadableByteChannel reset(ReadableByteChannel channel) { ReadableByteChannel old = this.channel; this.channel = channel; - this.reachedEOF = false; return old; } @@ -63,16 +61,11 @@ public ReadableByteChannel reset(ReadableByteChannel channel) public MessageBuffer next() throws IOException { - if (reachedEOF) { - return null; - } - - MessageBuffer m = MessageBuffer.newBuffer(bufferSize); ByteBuffer b = m.toByteBuffer(); - while (!reachedEOF && b.remaining() > 0) { + while (b.remaining() > 0) { int ret = channel.read(b); if (ret == -1) { - reachedEOF = true; + break; } } b.flip(); @@ -86,8 +79,4 @@ public void close() channel.close(); } - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java index b0d42e4a0..ad8aa462f 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java @@ -29,8 +29,7 @@ public class InputStreamBufferInput implements MessageBufferInput { private InputStream in; - private final int bufferSize; - private boolean reachedEOF = false; + private final byte[] buffer; public static MessageBufferInput newBufferInput(InputStream in) { @@ -52,7 +51,7 @@ public InputStreamBufferInput(InputStream in) public InputStreamBufferInput(InputStream in, int bufferSize) { this.in = checkNotNull(in, "input is null"); - this.bufferSize = bufferSize; + this.buffer = new byte[bufferSize]; } /** @@ -66,7 +65,6 @@ public InputStream reset(InputStream in) { InputStream old = this.in; this.in = in; - reachedEOF = false; return old; } @@ -74,14 +72,8 @@ public InputStream reset(InputStream in) public MessageBuffer next() throws IOException { - if (reachedEOF) { - return null; - } - - byte[] buffer = new byte[bufferSize]; int readLen = in.read(buffer); if (readLen == -1) { - reachedEOF = true; return null; } return MessageBuffer.wrap(buffer).slice(0, readLen); @@ -93,9 +85,4 @@ public void close() { in.close(); } - - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index 2a92160b2..5925557cf 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -27,14 +27,12 @@ public interface MessageBufferInput /** * Get a next buffer to read. * + * When this method is called twice, the formally allocated buffer can be safely discarded. + * * @return the next MessageBuffer, or return null if no more buffer is available. * @throws IOException when error occurred when reading the data */ public MessageBuffer next() throws IOException; - /** - * Release an unused buffer formerly returned by next() method. - */ - public void release(MessageBuffer buffer); } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 179ca5eb1..672edd615 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -261,8 +261,6 @@ class MessageUnpackerTest extends MessagePackSpec { } } - override def release(buffer: MessageBuffer): Unit = {} - override def close(): Unit = {} } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 39526a0ce..92103dc31 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -38,9 +38,6 @@ class ByteStringTest isRead = true messageBuffer } - - override def release(buffer: MessageBuffer): Unit = {} - override def close(): Unit = {} } From 60fc2b286b87c261c3168e5be9e7d3b522ab0369 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 22 Dec 2015 18:24:43 +0900 Subject: [PATCH 24/99] fixed skipPayload --- msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 70a050990..38880d03d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1326,6 +1326,7 @@ private void skipPayload(int numBytes) } else { position += bufferRemaining; + numBytes -= bufferRemaining; } nextBuffer(); } From 3d9e16834d5e908b7af32dde6b9901c186a085bb Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 23 Dec 2015 22:09:00 +0900 Subject: [PATCH 25/99] Improve MessagePackDataformat(Pojo|HugeData)BenchmarkTest --- .../MessagePackDataformatTestBase.java | 13 --- .../dataformat/benchmark/Benchmarker.java | 95 +++++++++++++++++++ ...gePackDataformatHugeDataBenchmarkTest.java | 65 ++++++++----- ...essagePackDataformatPojoBenchmarkTest.java | 85 ++++++++++------- 4 files changed, 184 insertions(+), 74 deletions(-) create mode 100644 msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java index fad09b910..1d5156adc 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java @@ -19,8 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.math3.stat.StatUtils; -import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation; import org.junit.After; import org.junit.Before; @@ -99,17 +97,6 @@ public void teardown() } } - protected void printStat(String label, double[] values) - { - StandardDeviation standardDeviation = new StandardDeviation(); - System.out.println(label + ":"); - System.out.println(String.format(" mean : %.2f", StatUtils.mean(values))); - System.out.println(String.format(" min : %.2f", StatUtils.min(values))); - System.out.println(String.format(" max : %.2f", StatUtils.max(values))); - System.out.println(String.format(" stdev: %.2f", standardDeviation.evaluate(values))); - System.out.println(""); - } - public enum Suit { SPADE, HEART, DIAMOND, CLUB; diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java new file mode 100644 index 000000000..4a11c4307 --- /dev/null +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java @@ -0,0 +1,95 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.jackson.dataformat.benchmark; + +import org.apache.commons.math3.stat.StatUtils; +import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation; + +import java.util.ArrayList; +import java.util.List; + +public class Benchmarker +{ + private final List benchmarkableList = new ArrayList(); + + public abstract static class Benchmarkable + { + private final String label; + + protected Benchmarkable(String label) + { + this.label = label; + } + + public abstract void run() throws Exception; + } + + public void addBenchmark(Benchmarkable benchmark) + { + benchmarkableList.add(benchmark); + } + + private static class Tuple + { + F first; + S second; + + public Tuple(F first, S second) + { + this.first = first; + this.second = second; + } + } + + public void run(int count, int warmupCount) + throws Exception + { + List> benchmarksResults = new ArrayList>(benchmarkableList.size()); + + for (Benchmarkable benchmark : benchmarkableList) { + double[] durations = new double[count]; + + for (int i = 0; i < count + warmupCount; i++) { + if (i >= warmupCount) { + System.gc(); + } + + long currentTimeNanos = System.nanoTime(); + benchmark.run(); + + if (i >= warmupCount) { + durations[i - warmupCount] = (System.nanoTime() - currentTimeNanos) / 1000000.0; + } + } + benchmarksResults.add(new Tuple(benchmark.label, durations)); + } + + for (Tuple benchmarkResult : benchmarksResults) { + printStat(benchmarkResult.first, benchmarkResult.second); + } + } + + private void printStat(String label, double[] values) + { + StandardDeviation standardDeviation = new StandardDeviation(); + System.out.println(label + ":"); + System.out.println(String.format(" mean : %8.3f", StatUtils.mean(values))); + System.out.println(String.format(" min : %8.3f", StatUtils.min(values))); + System.out.println(String.format(" max : %8.3f", StatUtils.max(values))); + System.out.println(String.format(" stdev: %8.3f", standardDeviation.evaluate(values))); + System.out.println(""); + } +} diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java index 342db62f5..07aec379f 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java @@ -19,17 +19,16 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; -import org.msgpack.jackson.dataformat.MessagePackDataformatTestBase; import org.msgpack.jackson.dataformat.MessagePackFactory; import java.util.ArrayList; import java.util.List; public class MessagePackDataformatHugeDataBenchmarkTest - extends MessagePackDataformatTestBase { - private static final int ELM_NUM = 1000000; - private static final int SAMPLING_COUNT = 4; + private static final int ELM_NUM = 100000; + private static final int COUNT = 6; + private static final int WARMUP_COUNT = 4; private final ObjectMapper origObjectMapper = new ObjectMapper(); private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory()); private static final List value; @@ -70,30 +69,44 @@ public class MessagePackDataformatHugeDataBenchmarkTest public void testBenchmark() throws Exception { - double[] durationOfSerializeWithJson = new double[SAMPLING_COUNT]; - double[] durationOfSerializeWithMsgPack = new double[SAMPLING_COUNT]; - double[] durationOfDeserializeWithJson = new double[SAMPLING_COUNT]; - double[] durationOfDeserializeWithMsgPack = new double[SAMPLING_COUNT]; - for (int si = 0; si < SAMPLING_COUNT; si++) { - long currentTimeMillis = System.currentTimeMillis(); - origObjectMapper.writeValueAsBytes(value); - durationOfSerializeWithJson[si] = System.currentTimeMillis() - currentTimeMillis; + Benchmarker benchmarker = new Benchmarker(); - currentTimeMillis = System.currentTimeMillis(); - msgpackObjectMapper.writeValueAsBytes(value); - durationOfSerializeWithMsgPack[si] = System.currentTimeMillis() - currentTimeMillis; + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(huge) with JSON") { + @Override + public void run() + throws Exception + { + origObjectMapper.writeValueAsBytes(value); + } + }); - currentTimeMillis = System.currentTimeMillis(); - origObjectMapper.readValue(packedByOriginal, new TypeReference>() {}); - durationOfDeserializeWithJson[si] = System.currentTimeMillis() - currentTimeMillis; + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(huge) with MessagePack") { + @Override + public void run() + throws Exception + { + msgpackObjectMapper.writeValueAsBytes(value); + } + }); - currentTimeMillis = System.currentTimeMillis(); - msgpackObjectMapper.readValue(packedByMsgPack, new TypeReference>() {}); - durationOfDeserializeWithMsgPack[si] = System.currentTimeMillis() - currentTimeMillis; - } - printStat("serialize(huge) with JSON", durationOfSerializeWithJson); - printStat("serialize(huge) with MessagePack", durationOfSerializeWithMsgPack); - printStat("deserialize(huge) with JSON", durationOfDeserializeWithJson); - printStat("deserialize(huge) with MessagePack", durationOfDeserializeWithMsgPack); + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("deserialize(huge) with JSON") { + @Override + public void run() + throws Exception + { + origObjectMapper.readValue(packedByOriginal, new TypeReference>() {}); + } + }); + + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("deserialize(huge) with MessagePack") { + @Override + public void run() + throws Exception + { + msgpackObjectMapper.readValue(packedByMsgPack, new TypeReference>() {}); + } + }); + + benchmarker.run(COUNT, WARMUP_COUNT); } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index eef58b242..af66c5d66 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -18,19 +18,20 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; -import org.msgpack.jackson.dataformat.MessagePackDataformatTestBase; import org.msgpack.jackson.dataformat.MessagePackFactory; +import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo; +import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; public class MessagePackDataformatPojoBenchmarkTest - extends MessagePackDataformatTestBase { - private static final int LOOP_MAX = 1000; - private static final int LOOP_FACTOR = 50; - private static final int SAMPLING_COUNT = 4; + private static final int LOOP_MAX = 600; + private static final int LOOP_FACTOR = 40; + private static final int COUNT = 6; + private static final int WARMUP_COUNT = 4; private static final List pojos = new ArrayList(LOOP_MAX); private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX); private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX); @@ -91,46 +92,60 @@ public class MessagePackDataformatPojoBenchmarkTest public void testBenchmark() throws Exception { - double[] durationOfSerializeWithJson = new double[SAMPLING_COUNT]; - double[] durationOfSerializeWithMsgPack = new double[SAMPLING_COUNT]; - double[] durationOfDeserializeWithJson = new double[SAMPLING_COUNT]; - double[] durationOfDeserializeWithMsgPack = new double[SAMPLING_COUNT]; - for (int si = 0; si < SAMPLING_COUNT; si++) { - long currentTimeMillis = System.currentTimeMillis(); - for (int j = 0; j < LOOP_FACTOR; j++) { - for (int i = 0; i < LOOP_MAX; i++) { - origObjectMapper.writeValueAsBytes(pojos.get(i)); + Benchmarker benchmarker = new Benchmarker(); + + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(pojo) with JSON") { + @Override + public void run() + throws Exception + { + for (int j = 0; j < LOOP_FACTOR; j++) { + for (int i = 0; i < LOOP_MAX; i++) { + origObjectMapper.writeValueAsBytes(pojos.get(i)); + } } } - durationOfSerializeWithJson[si] = System.currentTimeMillis() - currentTimeMillis; + }); - currentTimeMillis = System.currentTimeMillis(); - for (int j = 0; j < LOOP_FACTOR; j++) { - for (int i = 0; i < LOOP_MAX; i++) { - msgpackObjectMapper.writeValueAsBytes(pojos.get(i)); + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(pojo) with MessagePack") { + @Override + public void run() + throws Exception + { + for (int j = 0; j < LOOP_FACTOR; j++) { + for (int i = 0; i < LOOP_MAX; i++) { + msgpackObjectMapper.writeValueAsBytes(pojos.get(i)); + } } } - durationOfSerializeWithMsgPack[si] = System.currentTimeMillis() - currentTimeMillis; + }); - currentTimeMillis = System.currentTimeMillis(); - for (int j = 0; j < LOOP_FACTOR; j++) { - for (int i = 0; i < LOOP_MAX; i++) { - origObjectMapper.readValue(pojosSerWithOrig.get(i), NormalPojo.class); + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("deserialize(pojo) with JSON") { + @Override + public void run() + throws Exception + { + for (int j = 0; j < LOOP_FACTOR; j++) { + for (int i = 0; i < LOOP_MAX; i++) { + origObjectMapper.readValue(pojosSerWithOrig.get(i), NormalPojo.class); + } } } - durationOfDeserializeWithJson[si] = System.currentTimeMillis() - currentTimeMillis; + }); - currentTimeMillis = System.currentTimeMillis(); - for (int j = 0; j < LOOP_FACTOR; j++) { - for (int i = 0; i < LOOP_MAX; i++) { - msgpackObjectMapper.readValue(pojosSerWithMsgPack.get(i), NormalPojo.class); + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("deserialize(pojo) with MessagePack") { + @Override + public void run() + throws Exception + { + for (int j = 0; j < LOOP_FACTOR; j++) { + for (int i = 0; i < LOOP_MAX; i++) { + msgpackObjectMapper.readValue(pojosSerWithMsgPack.get(i), NormalPojo.class); + } } } - durationOfDeserializeWithMsgPack[si] = System.currentTimeMillis() - currentTimeMillis; - } - printStat("serialize(pojo) with JSON", durationOfSerializeWithJson); - printStat("serialize(pojo) with MessagePack", durationOfSerializeWithMsgPack); - printStat("deserialize(pojo) with JSON", durationOfDeserializeWithJson); - printStat("deserialize(pojo) with MessagePack", durationOfDeserializeWithMsgPack); + }); + + benchmarker.run(COUNT, WARMUP_COUNT); } } From 4d2594e2aafc6037cf3c0709a74c26706e736338 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 23 Dec 2015 22:37:55 +0900 Subject: [PATCH 26/99] Use ObjectMapper#writeValue() instead of writeValueAsBytes() in benchmark --- ...gePackDataformatHugeDataBenchmarkTest.java | 30 +++++++++++++++++-- ...essagePackDataformatPojoBenchmarkTest.java | 30 +++++++++++++++++-- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java index 07aec379f..b3a159111 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java @@ -15,12 +15,16 @@ // package org.msgpack.jackson.dataformat.benchmark; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; import org.msgpack.jackson.dataformat.MessagePackFactory; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -65,18 +69,32 @@ public class MessagePackDataformatHugeDataBenchmarkTest packedByMsgPack = bytes; } + public MessagePackDataformatHugeDataBenchmarkTest() + { + origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + } + @Test public void testBenchmark() throws Exception { Benchmarker benchmarker = new Benchmarker(); + File tempFileJackson = File.createTempFile("msgpack-jackson-", "-huge-jackson"); + tempFileJackson.deleteOnExit(); + final OutputStream outputStreamJackson = new FileOutputStream(tempFileJackson); + + File tempFileMsgpack = File.createTempFile("msgpack-jackson-", "-huge-msgpack"); + tempFileMsgpack.deleteOnExit(); + final OutputStream outputStreamMsgpack = new FileOutputStream(tempFileMsgpack); + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(huge) with JSON") { @Override public void run() throws Exception { - origObjectMapper.writeValueAsBytes(value); + origObjectMapper.writeValue(outputStreamJackson, value); } }); @@ -85,7 +103,7 @@ public void run() public void run() throws Exception { - msgpackObjectMapper.writeValueAsBytes(value); + msgpackObjectMapper.writeValue(outputStreamMsgpack, value); } }); @@ -107,6 +125,12 @@ public void run() } }); - benchmarker.run(COUNT, WARMUP_COUNT); + try { + benchmarker.run(COUNT, WARMUP_COUNT); + } + finally { + outputStreamJackson.close(); + outputStreamMsgpack.close(); + } } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index af66c5d66..de2118508 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -15,6 +15,7 @@ // package org.msgpack.jackson.dataformat.benchmark; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; @@ -22,6 +23,9 @@ import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -88,12 +92,26 @@ public class MessagePackDataformatPojoBenchmarkTest } } + public MessagePackDataformatPojoBenchmarkTest() + { + origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + } + @Test public void testBenchmark() throws Exception { Benchmarker benchmarker = new Benchmarker(); + File tempFileJackson = File.createTempFile("msgpack-jackson-", "-huge-jackson"); + tempFileJackson.deleteOnExit(); + final OutputStream outputStreamJackson = new FileOutputStream(tempFileJackson); + + File tempFileMsgpack = File.createTempFile("msgpack-jackson-", "-huge-msgpack"); + tempFileMsgpack.deleteOnExit(); + final OutputStream outputStreamMsgpack = new FileOutputStream(tempFileMsgpack); + benchmarker.addBenchmark(new Benchmarker.Benchmarkable("serialize(pojo) with JSON") { @Override public void run() @@ -101,7 +119,7 @@ public void run() { for (int j = 0; j < LOOP_FACTOR; j++) { for (int i = 0; i < LOOP_MAX; i++) { - origObjectMapper.writeValueAsBytes(pojos.get(i)); + origObjectMapper.writeValue(outputStreamJackson, pojos.get(i)); } } } @@ -114,7 +132,7 @@ public void run() { for (int j = 0; j < LOOP_FACTOR; j++) { for (int i = 0; i < LOOP_MAX; i++) { - msgpackObjectMapper.writeValueAsBytes(pojos.get(i)); + msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i)); } } } @@ -146,6 +164,12 @@ public void run() } }); - benchmarker.run(COUNT, WARMUP_COUNT); + try { + benchmarker.run(COUNT, WARMUP_COUNT); + } + finally { + outputStreamJackson.close(); + outputStreamMsgpack.close(); + } } } From f45be09506b81f9b90167afd4028285a8ddf7f8a Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Thu, 24 Dec 2015 09:44:27 +0900 Subject: [PATCH 27/99] simplified streaming string decoding code --- .../org/msgpack/core/MessageUnpacker.java | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 38880d03d..c6730a009 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -997,29 +997,9 @@ public String unpackString() while (readingRawRemaining > 0) { int bufferRemaining = buffer.size() - position; if (bufferRemaining >= readingRawRemaining) { - ByteBuffer bb = buffer.toByteBuffer(position, readingRawRemaining); - int bbStartPosition = bb.position(); - decodeBuffer.clear(); - - CoderResult cr = decoder.decode(bb, decodeBuffer, true); - int readLen = bb.position() - bbStartPosition; - position += readLen; - readingRawRemaining -= readLen; - decodeStringBuffer.append(decodeBuffer.flip()); - - if (cr.isError()) { - handleCoderError(cr); - } - if (cr.isUnderflow() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) { - throw new MalformedInputException(cr.length()); - } - - if (cr.isOverflow()) { - // go to next loop - } - else { - break; - } + decodeStringBuffer.append(decodeStringFastPath(readingRawRemaining)); + readingRawRemaining = 0; + break; } else if (bufferRemaining == 0) { nextBuffer(); From 0b03305f0e840f8db4174de0228d5fad11579282 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Thu, 24 Dec 2015 10:00:21 +0900 Subject: [PATCH 28/99] 0xC1 NEVER_USED always throws MessageNeverUsedFormatException regardless of context rather than MessageTypeException or MessageFormatException depending on context --- .../java/org/msgpack/core/MessageUnpacker.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index c6730a009..bd6339418 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -449,7 +449,7 @@ public void skipValue() remainingValues += readNextLength32() * 2; // TODO check int overflow break; case NEVER_USED: - throw new MessageFormatException(String.format("unknown code: %02x is found", b)); + throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte"); } remainingValues--; @@ -464,19 +464,17 @@ public void skipValue() * @return * @throws MessageFormatException */ - private static MessageTypeException unexpected(String expected, byte b) - throws MessageTypeException + private static MessagePackException unexpected(String expected, byte b) { MessageFormat format = MessageFormat.valueOf(b); - String typeName; if (format == MessageFormat.NEVER_USED) { - typeName = "NeverUsed"; + return new MessageNeverUsedFormatException(String.format("Expected %s, but encountered 0xC1 \"NEVER_USED\" byte", expected)); } else { String name = format.getValueType().name(); - typeName = name.substring(0, 1) + name.substring(1).toLowerCase(); + String typeName = name.substring(0, 1) + name.substring(1).toLowerCase(); + return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); } - return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); } public ImmutableValue unpackValue() @@ -530,7 +528,7 @@ public ImmutableValue unpackValue() return ValueFactory.newExtension(extHeader.getType(), readPayload(extHeader.getLength())); } default: - throw new MessageFormatException("Unknown value type"); + throw new MessageNeverUsedFormatException("Unknown value type"); } } From dc1f10b9ac060dc4dea0d1ec773a94808f4a1a48 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 25 Dec 2015 10:19:18 +0900 Subject: [PATCH 29/99] minimum required castBuffer size is 8 bytes --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index bd6339418..9b8e159bc 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -98,9 +98,10 @@ public class MessageUnpacker private long totalReadBytes; /** - * Extra buffer for fixed-length data at the buffer boundary. At most 17-byte buffer (for FIXEXT16) is required. + * Extra buffer for fixed-length data at the buffer boundary. + * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required. */ - private final MessageBuffer castBuffer = MessageBuffer.newBuffer(24); + private final MessageBuffer castBuffer = MessageBuffer.newBuffer(8); /** * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer. From 2ce99168eaa86930f3c57ec5b8821f3e558c4897 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 25 Dec 2015 12:28:43 +0900 Subject: [PATCH 30/99] optimized packer buffer interface --- .../java/org/msgpack/core/MessagePacker.java | 325 ++++++++++-------- .../core/buffer/ChannelBufferOutput.java | 46 ++- .../msgpack/core/buffer/MessageBuffer.java | 5 + .../core/buffer/MessageBufferOutput.java | 48 ++- .../core/buffer/OutputStreamBufferOutput.java | 59 ++-- .../core/example/MessagePackExample.java | 5 - .../org/msgpack/core/MessagePackerTest.scala | 3 +- .../core/buffer/MessageBufferOutputTest.scala | 2 +- .../dataformat/MessagePackGenerator.java | 13 +- 9 files changed, 306 insertions(+), 200 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 032cda7f3..11f2fcb5d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -88,15 +88,15 @@ public class MessagePacker private final MessagePack.Config config; private MessageBufferOutput out; + private MessageBuffer buffer; - private MessageBuffer strLenBuffer; private int position; /** * Total written byte size */ - private long flushedBytes; + private long totalFlushBytes; /** * String encoder @@ -119,7 +119,7 @@ public MessagePacker(MessageBufferOutput out, MessagePack.Config config) this.config = checkNotNull(config, "config is null"); this.out = checkNotNull(out, "MessageBufferOutput is null"); this.position = 0; - this.flushedBytes = 0; + this.totalFlushBytes = 0; } /** @@ -134,50 +134,32 @@ public MessageBufferOutput reset(MessageBufferOutput out) // Validate the argument MessageBufferOutput newOut = checkNotNull(out, "MessageBufferOutput is null"); - // Reset the internal states + // Flush before reset + flush(); MessageBufferOutput old = this.out; this.out = newOut; - this.position = 0; - this.flushedBytes = 0; - return old; - } - public long getTotalWrittenBytes() - { - return flushedBytes + position; - } + // Reset totalFlushBytes + this.totalFlushBytes = 0; - private void prepareEncoder() - { - if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); - } + return old; } - private void prepareBuffer() - throws IOException + public long getTotalWrittenBytes() { - if (buffer == null) { - buffer = out.next(config.packerBufferSize); - } + return totalFlushBytes + position; } public void flush() throws IOException { - if (buffer == null) { - return; + if (position > 0) { + out.writeBuffer(position); + buffer = null; + totalFlushBytes += position; + position = 0; } - - if (position == buffer.size()) { - out.flush(buffer); - } - else { - out.flush(buffer.slice(0, position)); - } - buffer = null; - flushedBytes += position; - position = 0; + out.flush(); } public void close() @@ -191,12 +173,18 @@ public void close() } } - private void ensureCapacity(int numBytesToWrite) + private void ensureCapacity(int mimimumSize) throws IOException { - if (buffer == null || position + numBytesToWrite >= buffer.size()) { - flush(); - buffer = out.next(Math.max(config.packerBufferSize, numBytesToWrite)); + if (buffer == null) { + buffer = out.next(mimimumSize); + } + else if (position + mimimumSize >= buffer.size()) { + out.writeBuffer(position); + buffer = null; + totalFlushBytes += position; + position = 0; + buffer = out.next(mimimumSize); } } @@ -442,14 +430,44 @@ public MessagePacker packDouble(double v) return this; } - private void packSmallString(String s) + private void packStringByGetBytes(String s) throws IOException { byte[] bytes = s.getBytes(MessagePack.UTF8); packRawStringHeader(bytes.length); - writePayload(bytes); + addPayload(bytes); } + private void prepareEncoder() + { + if (encoder == null) { + this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); + } + } + + private int encodeStringToBufferAt(int pos, String s) + { + prepareEncoder(); + ByteBuffer bb = buffer.toByteBuffer(pos, buffer.size() - pos); + int startPosition = bb.position(); + CharBuffer in = CharBuffer.wrap(s); + CoderResult cr = encoder.encode(in, bb, true); + if (cr.isError()) { + try { + cr.throwException(); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + } + if (cr.isUnderflow() || cr.isOverflow()) { + return -1; + } + return bb.position() - startPosition; + } + + private static final int UTF_8_MAX_CHAR_SIZE = 6; + /** * Pack the input String in UTF-8 encoding * @@ -464,77 +482,76 @@ public MessagePacker packString(String s) packRawStringHeader(0); return this; } - - if (s.length() < config.packerSmallStringOptimizationThreshold) { + else if (s.length() < config.packerSmallStringOptimizationThreshold) { // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer - packSmallString(s); + packStringByGetBytes(s); return this; } - - CharBuffer in = CharBuffer.wrap(s); - prepareEncoder(); - - flush(); - - prepareBuffer(); - boolean isExtension = false; - ByteBuffer encodeBuffer = buffer.toByteBuffer(position, buffer.size() - position); - encoder.reset(); - while (in.hasRemaining()) { - try { - CoderResult cr = encoder.encode(in, encodeBuffer, true); - - // Input data is insufficient - if (cr.isUnderflow()) { - cr = encoder.flush(encodeBuffer); + else if (s.length() < (1 << 8)) { + // ensure capacity for 2-byte raw string header + the maximum string size (+ 1 byte for falback code) + ensureCapacity(2 + s.length() * UTF_8_MAX_CHAR_SIZE + 1); + // keep 2-byte header region and write raw string + int written = encodeStringToBufferAt(position + 2, s); + if (written >= 0) { + if (written < (1 << 8)) { + buffer.putByte(position++, STR8); + buffer.putByte(position++, (byte) written); + position += written; } - - // encodeBuffer is too small - if (cr.isOverflow()) { - // Allocate a larger buffer - int estimatedRemainingSize = Math.max(1, (int) (in.remaining() * encoder.averageBytesPerChar())); - encodeBuffer.flip(); - ByteBuffer newBuffer = ByteBuffer.allocate(Math.max((int) (encodeBuffer.capacity() * 1.5), encodeBuffer.remaining() + estimatedRemainingSize)); - // Coy the current encodeBuffer contents to the new buffer - newBuffer.put(encodeBuffer); - encodeBuffer = newBuffer; - isExtension = true; - encoder.reset(); - continue; - } - - if (cr.isError()) { - if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || - (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { - cr.throwException(); + else { + if (written >= (1 << 16)) { + // this must not happen because s.length() is less than 2^8 and (2^8) * UTF_8_MAX_CHAR_SIZE is less than 2^16 + throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); } + // move 1 byte backward to expand 3-byte header region to 3 bytes + buffer.putBytes(position + 3, + buffer.getArray(), buffer.offset() + position + 2, written); + // write 3-byte header header + buffer.putByte(position++, STR16); + buffer.putShort(position, (short) written); + position += 2; + position += written; } + return this; } - catch (CharacterCodingException e) { - throw new MessageStringCodingException(e); + } + else if (s.length() < (1 << 16)) { + // ensure capacity for 3-byte raw string header + the maximum string size (+ 2 bytes for falback code) + ensureCapacity(3 + s.length() * UTF_8_MAX_CHAR_SIZE + 2); + // keep 3-byte header region and write raw string + int written = encodeStringToBufferAt(position + 3, s); + if (written >= 0) { + if (written < (1 << 16)) { + buffer.putByte(position++, STR16); + buffer.putShort(position, (short) written); + position += 2; + position += written; + } + else { + if (written >= (1 << 32)) { + // this must not happen because s.length() is less than 2^16 and (2^16) * UTF_8_MAX_CHAR_SIZE is less than 2^32 + throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); + } + // move 2 bytes backward to expand 3-byte header region to 5 bytes + buffer.putBytes(position + 5, + buffer.getArray(), buffer.offset() + position + 3, written); + // write 3-byte header header + buffer.putByte(position++, STR32); + buffer.putInt(position, written); + position += 4; + position += written; + } + return this; } } - encodeBuffer.flip(); - int strLen = encodeBuffer.remaining(); - - // Preserve the current buffer - MessageBuffer tmpBuf = buffer; - - // Switch the buffer to write the string length - if (strLenBuffer == null) { - strLenBuffer = MessageBuffer.newBuffer(5); - } - buffer = strLenBuffer; - position = 0; - // pack raw string header (string binary size) - packRawStringHeader(strLen); - flush(); // We need to dump the data here to MessageBufferOutput so that we can switch back to the original buffer + // Here doesn't use above optimized code for s.length() < (1 << 32) so that + // ensureCapacity is not called with an integer larger than (3 + ((1 << 16) * UTF_8_MAX_CHAR_SIZE) + 2). + // This makes it sure that MessageBufferOutput.next won't be called a size larger than + // 384KB, which is OK size to keep in memory. - // Reset to the original buffer (or encodeBuffer if new buffer is allocated) - buffer = isExtension ? MessageBuffer.wrap(encodeBuffer) : tmpBuf; - // No need exists to write payload since the encoded string (payload) is already written to the buffer - position = strLen; + // fallback + packStringByGetBytes(s); return this; } @@ -659,72 +676,82 @@ else if (len < (1 << 16)) { return this; } - public MessagePacker writePayload(ByteBuffer src) + /** + * Writes buffer to the output. + * This method is used with packRawStringHeader or packBinaryHeader. + * + * @param src the data to add + * @return this + * @throws IOException + */ + public MessagePacker writePayload(byte[] src) throws IOException { - int len = src.remaining(); - if (len >= config.packerRawDataCopyingThreshold) { - // Use the source ByteBuffer directly to avoid memory copy - - // First, flush the current buffer contents - flush(); + return writePayload(src, 0, src.length); + } - // Wrap the input source as a MessageBuffer - MessageBuffer wrapped = MessageBuffer.wrap(src); - // Then, dump the source data to the output - out.flush(wrapped); - src.position(src.limit()); - flushedBytes += len; + /** + * Writes buffer to the output. + * This method is used with packRawStringHeader or packBinaryHeader. + * + * @param src the data to add + * @param off the start offset in the data + * @param len the number of bytes to add + * @return this + * @throws IOException + */ + public MessagePacker writePayload(byte[] src, int off, int len) + throws IOException + { + if (buffer.size() - position < len || len > 8192) { + flush(); // call flush before write + out.write(src, off, len); + totalFlushBytes += len; } else { - // If the input source is small, simply copy the contents to the buffer - while (src.remaining() > 0) { - if (position >= buffer.size()) { - flush(); - } - prepareBuffer(); - int writeLen = Math.min(buffer.size() - position, src.remaining()); - buffer.putByteBuffer(position, src, writeLen); - position += writeLen; - } + buffer.putBytes(position, src, off, len); + position += len; } - return this; } - public MessagePacker writePayload(byte[] src) + /** + * Writes buffer to the output. + * Unlike writePayload method, addPayload method doesn't copy the source data. It means that the caller + * must not modify the data after calling this method. + * + * @param src the data to add + * @return this + * @throws IOException + */ + public MessagePacker addPayload(byte[] src) throws IOException { - return writePayload(src, 0, src.length); + return addPayload(src, 0, src.length); } - public MessagePacker writePayload(byte[] src, int off, int len) + /** + * Writes buffer to the output. + * Unlike writePayload method, addPayload method doesn't copy the source data. It means that the caller + * must not modify the data after calling this method. + * + * @param src the data to add + * @param off the start offset in the data + * @param len the number of bytes to add + * @return this + * @throws IOException + */ + public MessagePacker addPayload(byte[] src, int off, int len) throws IOException { - if (len >= config.packerRawDataCopyingThreshold) { - // Use the input array directory to avoid memory copy - - // Flush the current buffer contents - flush(); - - // Wrap the input array as a MessageBuffer - MessageBuffer wrapped = MessageBuffer.wrap(src).slice(off, len); - // Dump the source data to the output - out.flush(wrapped); - flushedBytes += len; + if (buffer.size() - position < len || len > 8192) { + flush(); // call flush before add + out.add(src, off, len); + totalFlushBytes += len; } else { - int cursor = 0; - while (cursor < len) { - if (buffer != null && position >= buffer.size()) { - flush(); - } - prepareBuffer(); - int writeLen = Math.min(buffer.size() - position, len - cursor); - buffer.putBytes(position, src, off + cursor, writeLen); - position += writeLen; - cursor += writeLen; - } + buffer.putBytes(position, src, off, len); + position += len; } return this; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java index 9ecddf3ac..b981cc95d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java @@ -31,15 +31,21 @@ public class ChannelBufferOutput private MessageBuffer buffer; public ChannelBufferOutput(WritableByteChannel channel) + { + this(channel, 8192); + } + + public ChannelBufferOutput(WritableByteChannel channel, int bufferSize) { this.channel = checkNotNull(channel, "output channel is null"); + this.buffer = MessageBuffer.newBuffer(bufferSize); } /** - * Reset channel. This method doesn't close the old resource. + * Reset channel. This method doesn't close the old channel. * * @param channel new channel - * @return the old resource + * @return the old channel */ public WritableByteChannel reset(WritableByteChannel channel) throws IOException @@ -50,21 +56,40 @@ public WritableByteChannel reset(WritableByteChannel channel) } @Override - public MessageBuffer next(int bufferSize) + public MessageBuffer next(int mimimumSize) throws IOException { - if (buffer == null || buffer.size() != bufferSize) { - buffer = MessageBuffer.newBuffer(bufferSize); + if (buffer.size() < mimimumSize) { + buffer = MessageBuffer.newBuffer(mimimumSize); } return buffer; } @Override - public void flush(MessageBuffer buf) + public void writeBuffer(int length) + throws IOException + { + ByteBuffer bb = buffer.toByteBuffer(0, length); + while (bb.hasRemaining()) { + channel.write(bb); + } + } + + @Override + public void write(byte[] buffer, int offset, int length) throws IOException { - ByteBuffer bb = buf.toByteBuffer(); - channel.write(bb); + ByteBuffer bb = ByteBuffer.wrap(buffer, offset, length); + while (bb.hasRemaining()) { + channel.write(bb); + } + } + + @Override + public void add(byte[] buffer, int offset, int length) + throws IOException + { + write(buffer, offset, length); } @Override @@ -73,4 +98,9 @@ public void close() { channel.close(); } + + @Override + public void flush() + throws IOException + { } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 302105f83..fce8020ce 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -210,6 +210,11 @@ public static MessageBuffer wrap(byte[] array) return newMessageBuffer(array); } + public static MessageBuffer wrap(byte[] array, int offset, int length) + { + return newMessageBuffer(array).slice(offset, length); + } + public static MessageBuffer wrap(ByteBuffer bb) { return newMessageBuffer(bb).slice(bb.position(), bb.remaining()); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 77fe12454..92eb760a9 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -17,30 +17,60 @@ import java.io.Closeable; import java.io.IOException; +import java.io.Flushable; /** - * Provides a sequence of MessageBuffers for packing the input data + * Provides a buffered output stream for packing objects */ public interface MessageBufferOutput - extends Closeable + extends Closeable, Flushable { /** - * Retrieves the next buffer for writing message packed data + * Allocates the next buffer for writing message packed data. + * If the previously allocated buffer is not flushed yet, this next method should discard + * it without writing it. * - * @param bufferSize the buffer size to retrieve + * @param mimimumSize the mimium required buffer size to allocate * @return * @throws IOException */ - public MessageBuffer next(int bufferSize) + public MessageBuffer next(int mimimumSize) throws IOException; /** - * Output the buffer contents. If you need to output a part of the - * buffer use {@link MessageBuffer#slice(int, int)} + * Flushes the previously allocated buffer. + * This method is not always called because next method also flushes previously allocated buffer. + * This method is called when write method is called or application wants to control the timing of flush. * - * @param buf + * @param length the size of buffer to flush * @throws IOException */ - public void flush(MessageBuffer buf) + public void writeBuffer(int length) + throws IOException; + + /** + * Writes an external payload data. + * This method should follow semantics of OutputStream. + * + * @param buffer the data to write + * @param offset the start offset in the data + * @param length the number of bytes to write + * @return + * @throws IOException + */ + public void write(byte[] buffer, int offset, int length) + throws IOException; + + /** + * Writes an external payload data. + * This buffer is given - this MessageBufferOutput owns the buffer and may modify contents of the buffer. Contents of this buffer won't be modified by the caller. + * + * @param buffer the data to add + * @param offset the start offset in the data + * @param length the number of bytes to add + * @return + * @throws IOException + */ + public void add(byte[] buffer, int offset, int length) throws IOException; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java index 07d423bf0..d6f17c783 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java @@ -28,18 +28,23 @@ public class OutputStreamBufferOutput { private OutputStream out; private MessageBuffer buffer; - private byte[] tmpBuf; public OutputStreamBufferOutput(OutputStream out) + { + this(out, 8192); + } + + public OutputStreamBufferOutput(OutputStream out, int bufferSize) { this.out = checkNotNull(out, "output is null"); + this.buffer = MessageBuffer.newBuffer(bufferSize); } /** - * Reset Stream. This method doesn't close the old resource. + * Reset Stream. This method doesn't close the old stream. * * @param out new stream - * @return the old resource + * @return the old stream */ public OutputStream reset(OutputStream out) throws IOException @@ -50,41 +55,47 @@ public OutputStream reset(OutputStream out) } @Override - public MessageBuffer next(int bufferSize) + public MessageBuffer next(int mimimumSize) throws IOException { - if (buffer == null || buffer.size != bufferSize) { - buffer = MessageBuffer.newBuffer(bufferSize); + if (buffer.size() < mimimumSize) { + buffer = MessageBuffer.newBuffer(mimimumSize); } return buffer; } @Override - public void flush(MessageBuffer buf) + public void writeBuffer(int length) throws IOException { - int writeLen = buf.size(); - if (buf.hasArray()) { - out.write(buf.getArray(), buf.offset(), writeLen); - } - else { - if (tmpBuf == null || tmpBuf.length < writeLen) { - tmpBuf = new byte[writeLen]; - } - buf.getBytes(0, tmpBuf, 0, writeLen); - out.write(tmpBuf, 0, writeLen); - } + write(buffer.getArray(), buffer.offset(), length); + } + + @Override + public void write(byte[] buffer, int offset, int length) + throws IOException + { + out.write(buffer, offset, length); + } + + @Override + public void add(byte[] buffer, int offset, int length) + throws IOException + { + write(buffer, offset, length); } @Override public void close() throws IOException { - try { - out.flush(); - } - finally { - out.close(); - } + out.close(); + } + + @Override + public void flush() + throws IOException + { + out.flush(); } } diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index a74c5cd18..7636742e0 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -153,11 +153,6 @@ public static void packer() .packArrayHeader(2) .packString("xxx-xxxx") .packString("yyy-yyyy"); - - // [Advanced] write data using ByteBuffer - ByteBuffer bb = ByteBuffer.wrap(new byte[] {'b', 'i', 'n', 'a', 'r', 'y', 'd', 'a', 't', 'a'}); - packer.packBinaryHeader(bb.remaining()); - packer.writePayload(bb); } /** diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index f598a133f..f6971b331 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -283,12 +283,11 @@ class MessagePackerTest "support read-only buffer" taggedAs ("read-only") in { val payload = Array[Byte](1) - val buffer = ByteBuffer.wrap(payload).asReadOnlyBuffer() val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) .packBinaryHeader(1) - .writePayload(buffer) + .writePayload(payload) .close() } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala index 8616d1c69..1869f2aad 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala @@ -44,7 +44,7 @@ class MessageBufferOutputTest def writeIntToBuf(buf: MessageBufferOutput) = { val mb0 = buf.next(8) mb0.putInt(0, 42) - buf.flush(mb0) + buf.writeBuffer(4) buf.close } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 189197209..c040ee7dd 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -183,8 +183,17 @@ else if (v instanceof Integer) { } else if (v instanceof ByteBuffer) { ByteBuffer bb = (ByteBuffer) v; - messagePacker.packBinaryHeader(bb.limit()); - messagePacker.writePayload(bb); + int len = bb.remaining(); + if (bb.hasArray()) { + messagePacker.packBinaryHeader(len); + messagePacker.writePayload(bb.array(), bb.arrayOffset(), len); + } + else { + byte[] data = new byte[len]; + bb.get(data); + messagePacker.packBinaryHeader(len); + messagePacker.addPayload(data); + } } else if (v instanceof String) { messagePacker.packString((String) v); From 9b2f4e32d9d85ce1ac0a03b86e6b2df6d24221a4 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Fri, 25 Dec 2015 13:16:01 +0900 Subject: [PATCH 31/99] Take care of the order of benchmarks and remove outliers --- .../dataformat/benchmark/Benchmarker.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java index 4a11c4307..980348024 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/Benchmarker.java @@ -19,6 +19,7 @@ import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class Benchmarker @@ -58,23 +59,20 @@ public void run(int count, int warmupCount) throws Exception { List> benchmarksResults = new ArrayList>(benchmarkableList.size()); - for (Benchmarkable benchmark : benchmarkableList) { - double[] durations = new double[count]; - - for (int i = 0; i < count + warmupCount; i++) { - if (i >= warmupCount) { - System.gc(); - } + benchmarksResults.add(new Tuple(benchmark.label, new double[count])); + } + for (int i = 0; i < count + warmupCount; i++) { + for (int bi = 0; bi < benchmarkableList.size(); bi++) { + Benchmarkable benchmark = benchmarkableList.get(bi); long currentTimeNanos = System.nanoTime(); benchmark.run(); if (i >= warmupCount) { - durations[i - warmupCount] = (System.nanoTime() - currentTimeNanos) / 1000000.0; + benchmarksResults.get(bi).second[i - warmupCount] = (System.nanoTime() - currentTimeNanos) / 1000000.0; } } - benchmarksResults.add(new Tuple(benchmark.label, durations)); } for (Tuple benchmarkResult : benchmarksResults) { @@ -82,8 +80,13 @@ public void run(int count, int warmupCount) } } - private void printStat(String label, double[] values) + private void printStat(String label, double[] origValues) { + double[] values = origValues; + Arrays.sort(origValues); + if (origValues.length > 2) { + values = Arrays.copyOfRange(origValues, 1, origValues.length - 1); + } StandardDeviation standardDeviation = new StandardDeviation(); System.out.println(label + ":"); System.out.println(String.format(" mean : %8.3f", StatUtils.mean(values))); From bc6830e89c7536c19aaf5d4eaea69fd9282aa78a Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 25 Dec 2015 15:28:15 +0900 Subject: [PATCH 32/99] reorganized MessagePacker interface to use MessagePacker --- .../org/msgpack/core/MessageBufferPacker.java | 73 ++++ .../java/org/msgpack/core/MessageFormat.java | 89 ++++- .../java/org/msgpack/core/MessagePack.java | 374 ++---------------- .../org/msgpack/core/MessagePackFactory.java | 203 ++++++++++ .../java/org/msgpack/core/MessagePacker.java | 88 ++--- .../org/msgpack/core/MessageUnpacker.java | 78 ++-- .../core/buffer/ArrayBufferOutput.java | 136 +++++++ .../core/example/MessagePackExample.java | 15 +- .../org/msgpack/core/MessageFormatTest.scala | 2 +- .../org/msgpack/core/MessagePackTest.scala | 24 +- .../org/msgpack/core/MessagePackerTest.scala | 19 +- .../msgpack/core/MessageUnpackerTest.scala | 46 +-- .../core/buffer/MessageBufferInputTest.scala | 6 +- .../org/msgpack/value/ValueTypeTest.scala | 2 +- 14 files changed, 686 insertions(+), 469 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java create mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java new file mode 100644 index 000000000..02b94f773 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -0,0 +1,73 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core; + +import org.msgpack.core.buffer.MessageBuffer; +import org.msgpack.core.buffer.MessageBufferOutput; +import org.msgpack.core.buffer.ArrayBufferOutput; + +import java.io.IOException; +import java.util.List; + +public class MessageBufferPacker + extends MessagePacker +{ + public MessageBufferPacker() + { + this(new ArrayBufferOutput()); + } + + public MessageBufferPacker(ArrayBufferOutput out) + { + super(out); + } + + @Override + public MessageBufferPacker setSmallStringOptimizationThreshold(int bytes) + { + super.setSmallStringOptimizationThreshold(bytes); + return this; + } + + public MessageBufferOutput reset(MessageBufferOutput out) + throws IOException + { + if (!(out instanceof ArrayBufferOutput)) { + throw new IllegalArgumentException("MessageBufferPacker accepts only ArrayBufferOutput"); + } + return super.reset(out); + } + + public void clear() + { + ((ArrayBufferOutput) out).clear(); + } + + public byte[] toByteArray() + { + return ((ArrayBufferOutput) out).toByteArray(); + } + + public MessageBuffer toMessageBuffer() + { + return ((ArrayBufferOutput) out).toMessageBuffer(); + } + + public List toBufferList() + { + return ((ArrayBufferOutput) out).toBufferList(); + } +} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java index 8e44b0aae..17a0f1555 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java @@ -15,7 +15,6 @@ // package org.msgpack.core; -import org.msgpack.core.MessagePack.Code; import org.msgpack.core.annotations.VisibleForTesting; import org.msgpack.value.ValueType; @@ -66,6 +65,94 @@ public enum MessageFormat MAP32(ValueType.MAP), NEGFIXINT(ValueType.INTEGER); + /** + * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. + */ + public static final class Code + { + public static final boolean isFixInt(byte b) + { + int v = b & 0xFF; + return v <= 0x7f || v >= 0xe0; + } + + public static final boolean isPosFixInt(byte b) + { + return (b & POSFIXINT_MASK) == 0; + } + + public static final boolean isNegFixInt(byte b) + { + return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; + } + + public static final boolean isFixStr(byte b) + { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final boolean isFixedArray(byte b) + { + return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; + } + + public static final boolean isFixedMap(byte b) + { + return (b & (byte) 0xe0) == Code.FIXMAP_PREFIX; + } + + public static final boolean isFixedRaw(byte b) + { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final byte POSFIXINT_MASK = (byte) 0x80; + + public static final byte FIXMAP_PREFIX = (byte) 0x80; + public static final byte FIXARRAY_PREFIX = (byte) 0x90; + public static final byte FIXSTR_PREFIX = (byte) 0xa0; + + public static final byte NIL = (byte) 0xc0; + public static final byte NEVER_USED = (byte) 0xc1; + public static final byte FALSE = (byte) 0xc2; + public static final byte TRUE = (byte) 0xc3; + public static final byte BIN8 = (byte) 0xc4; + public static final byte BIN16 = (byte) 0xc5; + public static final byte BIN32 = (byte) 0xc6; + public static final byte EXT8 = (byte) 0xc7; + public static final byte EXT16 = (byte) 0xc8; + public static final byte EXT32 = (byte) 0xc9; + public static final byte FLOAT32 = (byte) 0xca; + public static final byte FLOAT64 = (byte) 0xcb; + public static final byte UINT8 = (byte) 0xcc; + public static final byte UINT16 = (byte) 0xcd; + public static final byte UINT32 = (byte) 0xce; + public static final byte UINT64 = (byte) 0xcf; + + public static final byte INT8 = (byte) 0xd0; + public static final byte INT16 = (byte) 0xd1; + public static final byte INT32 = (byte) 0xd2; + public static final byte INT64 = (byte) 0xd3; + + public static final byte FIXEXT1 = (byte) 0xd4; + public static final byte FIXEXT2 = (byte) 0xd5; + public static final byte FIXEXT4 = (byte) 0xd6; + public static final byte FIXEXT8 = (byte) 0xd7; + public static final byte FIXEXT16 = (byte) 0xd8; + + public static final byte STR8 = (byte) 0xd9; + public static final byte STR16 = (byte) 0xda; + public static final byte STR32 = (byte) 0xdb; + + public static final byte ARRAY16 = (byte) 0xdc; + public static final byte ARRAY32 = (byte) 0xdd; + + public static final byte MAP16 = (byte) 0xde; + public static final byte MAP32 = (byte) 0xdf; + + public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; + } + private static final MessageFormat[] formatTable = new MessageFormat[256]; private final ValueType valueType; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 9847d461e..8af53a884 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -37,406 +37,102 @@ public class MessagePack { public static final Charset UTF8 = Charset.forName("UTF-8"); - /** - * Message packer/unpacker configuration object - */ - public static class Config - { - /** - * allow unpackBinaryHeader to read str format family (default:true) - */ - public final boolean readStringAsBinary; - /** - * allow unpackRawStringHeader and unpackString to read bin format family (default: true) - */ - public final boolean readBinaryAsString; - /** - * Action when encountered a malformed input - */ - public final CodingErrorAction actionOnMalFormedInput; - /** - * Action when an unmappable character is found - */ - public final CodingErrorAction actionOnUnmappableCharacter; - /** - * unpackString size limit. (default: Integer.MAX_VALUE) - */ - public final int maxUnpackStringSize; - public final int stringEncoderBufferSize; - public final int stringDecoderBufferSize; - public final int packerBufferSize; - public final int packerRawDataCopyingThreshold; - /** - * Use String.getBytes() for strings smaller than this threshold. - * Note that this parameter is subject to change. - */ - public final int packerSmallStringOptimizationThreshold; - - public Config( - boolean readStringAsBinary, - boolean readBinaryAsString, - CodingErrorAction actionOnMalFormedInput, - CodingErrorAction actionOnUnmappableCharacter, - int maxUnpackStringSize, - int stringEncoderBufferSize, - int stringDecoderBufferSize, - int packerBufferSize, - int packerSmallStringOptimizationThreshold, - int packerRawDataCopyingThreshold) - { - checkArgument(packerBufferSize > 0, "packer buffer size must be larger than 0: " + packerBufferSize); - checkArgument(stringEncoderBufferSize > 0, "string encoder buffer size must be larger than 0: " + stringEncoderBufferSize); - checkArgument(stringDecoderBufferSize > 0, "string decoder buffer size must be larger than 0: " + stringDecoderBufferSize); - - this.readStringAsBinary = readStringAsBinary; - this.readBinaryAsString = readBinaryAsString; - this.actionOnMalFormedInput = actionOnMalFormedInput; - this.actionOnUnmappableCharacter = actionOnUnmappableCharacter; - this.maxUnpackStringSize = maxUnpackStringSize; - this.stringEncoderBufferSize = stringEncoderBufferSize; - this.stringDecoderBufferSize = stringDecoderBufferSize; - this.packerBufferSize = packerBufferSize; - this.packerSmallStringOptimizationThreshold = packerSmallStringOptimizationThreshold; - this.packerRawDataCopyingThreshold = packerRawDataCopyingThreshold; - } - } - - /** - * Builder of the configuration object - */ - public static class ConfigBuilder - { - private boolean readStringAsBinary = true; - private boolean readBinaryAsString = true; - - private CodingErrorAction onMalFormedInput = CodingErrorAction.REPLACE; - private CodingErrorAction onUnmappableCharacter = CodingErrorAction.REPLACE; - - private int maxUnpackStringSize = Integer.MAX_VALUE; - private int stringEncoderBufferSize = 8192; - private int stringDecoderBufferSize = 8192; - private int packerBufferSize = 8192; - private int packerSmallStringOptimizationThreshold = 512; // This parameter is subject to change - private int packerRawDataCopyingThreshold = 512; - - public Config build() - { - return new Config( - readStringAsBinary, - readBinaryAsString, - onMalFormedInput, - onUnmappableCharacter, - maxUnpackStringSize, - stringEncoderBufferSize, - stringDecoderBufferSize, - packerBufferSize, - packerSmallStringOptimizationThreshold, - packerRawDataCopyingThreshold - ); - } - - public ConfigBuilder readStringAsBinary(boolean enable) - { - this.readStringAsBinary = enable; - return this; - } - - public ConfigBuilder readBinaryAsString(boolean enable) - { - this.readBinaryAsString = enable; - return this; - } - - public ConfigBuilder onMalFormedInput(CodingErrorAction action) - { - this.onMalFormedInput = action; - return this; - } - - public ConfigBuilder onUnmappableCharacter(CodingErrorAction action) - { - this.onUnmappableCharacter = action; - return this; - } - - public ConfigBuilder maxUnpackStringSize(int size) - { - this.maxUnpackStringSize = size; - return this; - } - - public ConfigBuilder stringEncoderBufferSize(int size) - { - this.stringEncoderBufferSize = size; - return this; - } - - public ConfigBuilder stringDecoderBufferSize(int size) - { - this.stringDecoderBufferSize = size; - return this; - } - - public ConfigBuilder packerBufferSize(int size) - { - this.packerBufferSize = size; - return this; - } - - public ConfigBuilder packerSmallStringOptimizationThreshold(int threshold) - { - this.packerSmallStringOptimizationThreshold = threshold; - return this; - } - - public ConfigBuilder packerRawDataCopyingThreshold(int threshold) - { - this.packerRawDataCopyingThreshold = threshold; - return this; - } - } + private static MessagePackFactory defaultFactory = new MessagePackFactory(); /** - * Default configuration, which is visible only from classes in the core package. + * Sets the default configuration used for the static constructor methods of this MessagePack class. */ - static final Config DEFAULT_CONFIG = new ConfigBuilder().build(); - - /** - * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. - */ - public static final class Code - { - public static final boolean isFixInt(byte b) - { - int v = b & 0xFF; - return v <= 0x7f || v >= 0xe0; - } - - public static final boolean isPosFixInt(byte b) - { - return (b & POSFIXINT_MASK) == 0; - } - - public static final boolean isNegFixInt(byte b) - { - return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; - } - - public static final boolean isFixStr(byte b) - { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final boolean isFixedArray(byte b) - { - return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; - } - - public static final boolean isFixedMap(byte b) - { - return (b & (byte) 0xe0) == Code.FIXMAP_PREFIX; - } - - public static final boolean isFixedRaw(byte b) - { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final byte POSFIXINT_MASK = (byte) 0x80; - - public static final byte FIXMAP_PREFIX = (byte) 0x80; - public static final byte FIXARRAY_PREFIX = (byte) 0x90; - public static final byte FIXSTR_PREFIX = (byte) 0xa0; - - public static final byte NIL = (byte) 0xc0; - public static final byte NEVER_USED = (byte) 0xc1; - public static final byte FALSE = (byte) 0xc2; - public static final byte TRUE = (byte) 0xc3; - public static final byte BIN8 = (byte) 0xc4; - public static final byte BIN16 = (byte) 0xc5; - public static final byte BIN32 = (byte) 0xc6; - public static final byte EXT8 = (byte) 0xc7; - public static final byte EXT16 = (byte) 0xc8; - public static final byte EXT32 = (byte) 0xc9; - public static final byte FLOAT32 = (byte) 0xca; - public static final byte FLOAT64 = (byte) 0xcb; - public static final byte UINT8 = (byte) 0xcc; - public static final byte UINT16 = (byte) 0xcd; - public static final byte UINT32 = (byte) 0xce; - public static final byte UINT64 = (byte) 0xcf; - - public static final byte INT8 = (byte) 0xd0; - public static final byte INT16 = (byte) 0xd1; - public static final byte INT32 = (byte) 0xd2; - public static final byte INT64 = (byte) 0xd3; - - public static final byte FIXEXT1 = (byte) 0xd4; - public static final byte FIXEXT2 = (byte) 0xd5; - public static final byte FIXEXT4 = (byte) 0xd6; - public static final byte FIXEXT8 = (byte) 0xd7; - public static final byte FIXEXT16 = (byte) 0xd8; - - public static final byte STR8 = (byte) 0xd9; - public static final byte STR16 = (byte) 0xda; - public static final byte STR32 = (byte) 0xdb; - - public static final byte ARRAY16 = (byte) 0xdc; - public static final byte ARRAY32 = (byte) 0xdd; - - public static final byte MAP16 = (byte) 0xde; - public static final byte MAP32 = (byte) 0xdf; - - public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; - } - - // Packer/Unpacker factory methods - - private final MessagePack.Config config; - - public MessagePack() + public static void setDefaultFactory(MessagePackFactory newDefaultFactory) { - this(MessagePack.DEFAULT_CONFIG); + defaultFactory = newDefaultFactory; } - public MessagePack(MessagePack.Config config) + public static MessagePackFactory getDefaultFactory() { - this.config = config; + return defaultFactory; } - /** - * Default MessagePack packer/unpacker factory - */ - public static final MessagePack DEFAULT = new MessagePack(MessagePack.DEFAULT_CONFIG); + private MessagePack() + { } /** - * Create a MessagePacker that outputs the packed data to the specified stream, using the default configuration + * Equivalent to getDefaultFactory().newPacker(out). * * @param out * @return */ public static MessagePacker newDefaultPacker(OutputStream out) { - return DEFAULT.newPacker(out); + return defaultFactory.newPacker(out); } /** - * Create a MessagePacker that outputs the packed data to the specified channel, using the default configuration + * Equivalent to getDefaultFactory().newPacker(channel). * * @param channel * @return */ public static MessagePacker newDefaultPacker(WritableByteChannel channel) { - return DEFAULT.newPacker(channel); - } - - /** - * Create a MessageUnpacker that reads data from then given InputStream, using the default configuration - * - * @param in - * @return - */ - public static MessageUnpacker newDefaultUnpacker(InputStream in) - { - return DEFAULT.newUnpacker(in); + return defaultFactory.newPacker(channel); } /** - * Create a MessageUnpacker that reads data from the given channel, using the default configuration + * Equivalent to getDefaultFactory().newBufferPacker() * * @param channel * @return */ - public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) - { - return DEFAULT.newUnpacker(channel); - } - - /** - * Create a MessageUnpacker that reads data from the given byte array, using the default configuration - * - * @param arr - * @return - */ - public static MessageUnpacker newDefaultUnpacker(byte[] arr) + public static MessageBufferPacker newDefaultBufferPacker() { - return DEFAULT.newUnpacker(arr); + return defaultFactory.newBufferPacker(); } /** - * Create a MessageUnpacker that reads data form the given byte array [offset, .. offset+length), using the default - * configuration. + * Equivalent to getDefaultFactory().newUnpacker(in). * - * @param arr - * @param offset - * @param length + * @param in * @return */ - public static MessageUnpacker newDefaultUnpacker(byte[] arr, int offset, int length) - { - return DEFAULT.newUnpacker(arr, offset, length); - } - - /** - * Create a MessagePacker that outputs the packed data to the specified stream - * - * @param out - */ - public MessagePacker newPacker(OutputStream out) + public static MessageUnpacker newDefaultUnpacker(InputStream in) { - return new MessagePacker(new OutputStreamBufferOutput(out), config); + return defaultFactory.newUnpacker(in); } /** - * Create a MessagePacker that outputs the packed data to the specified channel + * Equivalent to getDefaultFactory().newUnpacker(channel). * * @param channel + * @return */ - public MessagePacker newPacker(WritableByteChannel channel) - { - return new MessagePacker(new ChannelBufferOutput(channel), config); - } - - /** - * Create a MessageUnpacker that reads data from the given InputStream. - * For reading data efficiently from byte[], use {@link MessageUnpacker(byte[])} or {@link MessageUnpacker(byte[], int, int)} instead of this constructor. - * - * @param in - */ - public MessageUnpacker newUnpacker(InputStream in) - { - return new MessageUnpacker(InputStreamBufferInput.newBufferInput(in), config); - } - - /** - * Create a MessageUnpacker that reads data from the given ReadableByteChannel. - * - * @param in - */ - public MessageUnpacker newUnpacker(ReadableByteChannel in) + public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) { - return new MessageUnpacker(new ChannelBufferInput(in), config); + return defaultFactory.newUnpacker(channel); } /** - * Create a MessageUnpacker that reads data from the given byte array. + * Equivalent to getDefaultFactory().newUnpacker(contents). * - * @param arr + * @param contents + * @return */ - public MessageUnpacker newUnpacker(byte[] arr) + public static MessageUnpacker newDefaultUnpacker(byte[] contents) { - return new MessageUnpacker(new ArrayBufferInput(arr), config); + return defaultFactory.newUnpacker(contents); } /** - * Create a MessageUnpacker that reads data from the given byte array [offset, offset+length) + * Equivalent to getDefaultFactory().newUnpacker(contents, offset, length). * - * @param arr + * @param contents * @param offset * @param length + * @return */ - public MessageUnpacker newUnpacker(byte[] arr, int offset, int length) + public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, int length) { - return new MessageUnpacker(new ArrayBufferInput(arr, offset, length), config); + return defaultFactory.newUnpacker(contents, offset, length); } + + // TODO add convenient methods here to pack/unpack objects with byte array/stream } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java new file mode 100644 index 000000000..f76df5490 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java @@ -0,0 +1,203 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core; + +import org.msgpack.core.buffer.ArrayBufferInput; +import org.msgpack.core.buffer.ChannelBufferInput; +import org.msgpack.core.buffer.ChannelBufferOutput; +import org.msgpack.core.buffer.InputStreamBufferInput; +import org.msgpack.core.buffer.OutputStreamBufferOutput; +import org.msgpack.core.buffer.MessageBufferInput; +import org.msgpack.core.buffer.MessageBufferOutput; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.WritableByteChannel; +import java.nio.channels.ReadableByteChannel; + +import java.nio.charset.CodingErrorAction; +import static org.msgpack.core.Preconditions.checkArgument; + +public class MessagePackFactory +{ + private int packerSmallStringOptimizationThreshold = 512; + + private boolean unpackAllowStringAsBinary = true; + private boolean unpackAllowBinaryAsString = true; + private CodingErrorAction unpackActionOnMalformedString = CodingErrorAction.REPLACE; + private CodingErrorAction unpackActionOnUnmappableString = CodingErrorAction.REPLACE; + private int unpackStringSizeLimit = Integer.MAX_VALUE; + private int unpackStringDecoderBufferSize = 8192; + + private int inputBufferSize = 16*1024; + private int outputBufferSize = 16*1024; + + public MessagePacker newPacker(OutputStream out) + { + return newPacker(new OutputStreamBufferOutput(out)); + } + + public MessagePacker newPacker(WritableByteChannel channel) + { + return newPacker(new ChannelBufferOutput(channel)); + } + + public MessagePacker newPacker(MessageBufferOutput output) + { + return new MessagePacker(output) + .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold); + } + + public MessageBufferPacker newBufferPacker() + { + return new MessageBufferPacker() + .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold); + } + + public MessageUnpacker newUnpacker(byte[] contents) + { + return newUnpacker(contents, 0, contents.length); + } + + public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) + { + return newUnpacker(new ArrayBufferInput(contents, offset, length)); + } + + public MessageUnpacker newUnpacker(InputStream in) + { + return newUnpacker(new InputStreamBufferInput(in)); + } + + public MessageUnpacker newUnpacker(ReadableByteChannel channel) + { + return newUnpacker(new ChannelBufferInput(channel)); + } + + public MessageUnpacker newUnpacker(MessageBufferInput input) + { + return new MessageUnpacker(input) + .setAllowStringAsBinary(unpackAllowStringAsBinary) + .setAllowBinaryAsString(unpackAllowBinaryAsString) + .setActionOnMalformedString(unpackActionOnMalformedString) + .setActionOnUnmappableString(unpackActionOnUnmappableString) + .setStringSizeLimit(unpackStringSizeLimit) + .setStringDecoderBufferSize(unpackStringDecoderBufferSize); + } + + /** + * Use String.getBytes() for strings smaller than this threshold. + * Note that this parameter is subject to change. + */ + public MessagePackFactory packerSmallStringOptimizationThreshold(int bytes) + { + this.packerSmallStringOptimizationThreshold = bytes; + return this; + } + + public MessagePackFactory unpackAllowStringAsBinary(boolean enabled) + { + this.unpackAllowStringAsBinary = enabled; + return this; + } + + public MessagePackFactory unpackAllowBinaryAsString(boolean enabled) + { + this.unpackAllowBinaryAsString = enabled; + return this; + } + + public MessagePackFactory unpackActionOnMalformedString(CodingErrorAction action) + { + this.unpackActionOnMalformedString = action; + return this; + } + + public MessagePackFactory unpackActionOnUnmappableString(CodingErrorAction action) + { + this.unpackActionOnUnmappableString = action; + return this; + } + + public MessagePackFactory unpackStringSizeLimit(int bytes) + { + this.unpackStringSizeLimit = bytes; + return this; + } + + public MessagePackFactory unpackStringDecoderBufferSize(int bytes) + { + this.unpackStringDecoderBufferSize = bytes; + return this; + } + + public MessagePackFactory inputBufferSize(int bytes) + { + this.inputBufferSize = bytes; + return this; + } + + public MessagePackFactory outputBufferSize(int bytes) + { + this.inputBufferSize = bytes; + return this; + } + + private int getPackerSmallStringOptimizationThreshold() + { + return packerSmallStringOptimizationThreshold; + } + + private boolean getUnpackAllowStringAsBinary() + { + return unpackAllowStringAsBinary; + } + + private boolean getUnpackAllowBinaryAsString() + { + return unpackAllowBinaryAsString; + } + + private CodingErrorAction getUnpackActionOnMalformedString() + { + return unpackActionOnMalformedString; + } + + private CodingErrorAction getUnpackActionOnUnmappableString() + { + return unpackActionOnUnmappableString; + } + + private int getUnpackStringSizeLimit() + { + return unpackStringSizeLimit; + } + + private int getUnpackStringDecoderBufferSize() + { + return unpackStringDecoderBufferSize; + } + + private int getInputBufferSize() + { + return inputBufferSize; + } + + private int getOutputBufferSize() + { + return outputBufferSize; + } +} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 11f2fcb5d..a145df162 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -29,40 +29,40 @@ import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; -import static org.msgpack.core.MessagePack.Code.ARRAY16; -import static org.msgpack.core.MessagePack.Code.ARRAY32; -import static org.msgpack.core.MessagePack.Code.BIN16; -import static org.msgpack.core.MessagePack.Code.BIN32; -import static org.msgpack.core.MessagePack.Code.BIN8; -import static org.msgpack.core.MessagePack.Code.EXT16; -import static org.msgpack.core.MessagePack.Code.EXT32; -import static org.msgpack.core.MessagePack.Code.EXT8; -import static org.msgpack.core.MessagePack.Code.FALSE; -import static org.msgpack.core.MessagePack.Code.FIXARRAY_PREFIX; -import static org.msgpack.core.MessagePack.Code.FIXEXT1; -import static org.msgpack.core.MessagePack.Code.FIXEXT16; -import static org.msgpack.core.MessagePack.Code.FIXEXT2; -import static org.msgpack.core.MessagePack.Code.FIXEXT4; -import static org.msgpack.core.MessagePack.Code.FIXEXT8; -import static org.msgpack.core.MessagePack.Code.FIXMAP_PREFIX; -import static org.msgpack.core.MessagePack.Code.FIXSTR_PREFIX; -import static org.msgpack.core.MessagePack.Code.FLOAT32; -import static org.msgpack.core.MessagePack.Code.FLOAT64; -import static org.msgpack.core.MessagePack.Code.INT16; -import static org.msgpack.core.MessagePack.Code.INT32; -import static org.msgpack.core.MessagePack.Code.INT64; -import static org.msgpack.core.MessagePack.Code.INT8; -import static org.msgpack.core.MessagePack.Code.MAP16; -import static org.msgpack.core.MessagePack.Code.MAP32; -import static org.msgpack.core.MessagePack.Code.NIL; -import static org.msgpack.core.MessagePack.Code.STR16; -import static org.msgpack.core.MessagePack.Code.STR32; -import static org.msgpack.core.MessagePack.Code.STR8; -import static org.msgpack.core.MessagePack.Code.TRUE; -import static org.msgpack.core.MessagePack.Code.UINT16; -import static org.msgpack.core.MessagePack.Code.UINT32; -import static org.msgpack.core.MessagePack.Code.UINT64; -import static org.msgpack.core.MessagePack.Code.UINT8; +import static org.msgpack.core.MessageFormat.Code.ARRAY16; +import static org.msgpack.core.MessageFormat.Code.ARRAY32; +import static org.msgpack.core.MessageFormat.Code.BIN16; +import static org.msgpack.core.MessageFormat.Code.BIN32; +import static org.msgpack.core.MessageFormat.Code.BIN8; +import static org.msgpack.core.MessageFormat.Code.EXT16; +import static org.msgpack.core.MessageFormat.Code.EXT32; +import static org.msgpack.core.MessageFormat.Code.EXT8; +import static org.msgpack.core.MessageFormat.Code.FALSE; +import static org.msgpack.core.MessageFormat.Code.FIXARRAY_PREFIX; +import static org.msgpack.core.MessageFormat.Code.FIXEXT1; +import static org.msgpack.core.MessageFormat.Code.FIXEXT16; +import static org.msgpack.core.MessageFormat.Code.FIXEXT2; +import static org.msgpack.core.MessageFormat.Code.FIXEXT4; +import static org.msgpack.core.MessageFormat.Code.FIXEXT8; +import static org.msgpack.core.MessageFormat.Code.FIXMAP_PREFIX; +import static org.msgpack.core.MessageFormat.Code.FIXSTR_PREFIX; +import static org.msgpack.core.MessageFormat.Code.FLOAT32; +import static org.msgpack.core.MessageFormat.Code.FLOAT64; +import static org.msgpack.core.MessageFormat.Code.INT16; +import static org.msgpack.core.MessageFormat.Code.INT32; +import static org.msgpack.core.MessageFormat.Code.INT64; +import static org.msgpack.core.MessageFormat.Code.INT8; +import static org.msgpack.core.MessageFormat.Code.MAP16; +import static org.msgpack.core.MessageFormat.Code.MAP32; +import static org.msgpack.core.MessageFormat.Code.NIL; +import static org.msgpack.core.MessageFormat.Code.STR16; +import static org.msgpack.core.MessageFormat.Code.STR32; +import static org.msgpack.core.MessageFormat.Code.STR8; +import static org.msgpack.core.MessageFormat.Code.TRUE; +import static org.msgpack.core.MessageFormat.Code.UINT16; +import static org.msgpack.core.MessageFormat.Code.UINT32; +import static org.msgpack.core.MessageFormat.Code.UINT64; +import static org.msgpack.core.MessageFormat.Code.UINT8; import static org.msgpack.core.Preconditions.checkNotNull; /** @@ -85,9 +85,9 @@ public class MessagePacker implements Closeable { - private final MessagePack.Config config; + private int smallStringOptimizationThreshold = 512; - private MessageBufferOutput out; + protected MessageBufferOutput out; private MessageBuffer buffer; @@ -111,17 +111,17 @@ public class MessagePacker */ public MessagePacker(MessageBufferOutput out) { - this(out, MessagePack.DEFAULT_CONFIG); - } - - public MessagePacker(MessageBufferOutput out, MessagePack.Config config) - { - this.config = checkNotNull(config, "config is null"); this.out = checkNotNull(out, "MessageBufferOutput is null"); this.position = 0; this.totalFlushBytes = 0; } + public MessagePacker setSmallStringOptimizationThreshold(int bytes) + { + this.smallStringOptimizationThreshold = bytes; + return this; + } + /** * Reset output. This method doesn't close the old resource. * @@ -441,7 +441,7 @@ private void packStringByGetBytes(String s) private void prepareEncoder() { if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); + this.encoder = MessagePack.UTF8.newEncoder(); } } @@ -482,7 +482,7 @@ public MessagePacker packString(String s) packRawStringHeader(0); return this; } - else if (s.length() < config.packerSmallStringOptimizationThreshold) { + else if (s.length() < smallStringOptimizationThreshold) { // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer packStringByGetBytes(s); return this; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 9b8e159bc..7e54d5253 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -15,7 +15,7 @@ // package org.msgpack.core; -import org.msgpack.core.MessagePack.Code; +import org.msgpack.core.MessageFormat.Code; import org.msgpack.core.buffer.MessageBuffer; import org.msgpack.core.buffer.MessageBufferInput; import org.msgpack.value.ImmutableValue; @@ -48,7 +48,7 @@ *

*

  * 
- *     MessageUnpacker unpacker = MessagePackFactory.DEFAULT.newUnpacker(...);
+ *     MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
  *     while(unpacker.hasNext()) {
  *         MessageFormat f = unpacker.getNextFormat();
  *         switch(f) {
@@ -76,7 +76,12 @@ public class MessageUnpacker
 
     private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1;
 
-    private final MessagePack.Config config;
+    private boolean allowStringAsBinary = true;
+    private boolean allowBinaryAsString = true;
+    private CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE;
+    private CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE;
+    private int stringSizeLimit = Integer.MAX_VALUE;
+    private int stringDecoderBufferSize = 8192;
 
     private MessageBufferInput in;
 
@@ -135,20 +140,43 @@ public class MessageUnpacker
      */
     public MessageUnpacker(MessageBufferInput in)
     {
-        this(in, MessagePack.DEFAULT_CONFIG);
+        this.in = checkNotNull(in, "MessageBufferInput is null");
     }
 
-    /**
-     * Create an MessageUnpacker
-     *
-     * @param in
-     * @param config configuration
-     */
-    public MessageUnpacker(MessageBufferInput in, MessagePack.Config config)
+    public MessageUnpacker setAllowStringAsBinary(boolean enabled)
     {
-        // Root constructor. All of the constructors must call this constructor.
-        this.in = checkNotNull(in, "MessageBufferInput is null");
-        this.config = checkNotNull(config, "Config");
+        this.allowStringAsBinary = enabled;
+        return this;
+    }
+
+    public MessageUnpacker setAllowBinaryAsString(boolean enabled)
+    {
+        this.allowBinaryAsString = enabled;
+        return this;
+    }
+
+    public MessageUnpacker setActionOnMalformedString(CodingErrorAction action)
+    {
+        this.actionOnMalformedString = action;
+        return this;
+    }
+
+    public MessageUnpacker setActionOnUnmappableString(CodingErrorAction action)
+    {
+        this.actionOnUnmappableString = action;
+        return this;
+    }
+
+    public MessageUnpacker setStringSizeLimit(int bytes)
+    {
+        this.stringSizeLimit = bytes;
+        return this;
+    }
+
+    public MessageUnpacker setStringDecoderBufferSize(int bytes)
+    {
+        this.stringDecoderBufferSize = bytes;
+        return this;
     }
 
     /**
@@ -958,10 +986,10 @@ public double unpackDouble()
     private void resetDecoder()
     {
         if (decoder == null) {
-            decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize);
+            decodeBuffer = CharBuffer.allocate(stringDecoderBufferSize);
             decoder = MessagePack.UTF8.newDecoder()
-                    .onMalformedInput(config.actionOnMalFormedInput)
-                    .onUnmappableCharacter(config.actionOnUnmappableCharacter);
+                    .onMalformedInput(actionOnMalformedString)
+                    .onUnmappableCharacter(actionOnUnmappableString);
         }
         else {
             decoder.reset();
@@ -980,8 +1008,8 @@ public String unpackString()
             if (len == 0) {
                 return EMPTY_STRING;
             }
-            if (len > config.maxUnpackStringSize) {
-                throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, len), len);
+            if (len > stringSizeLimit) {
+                throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len);
             }
             if (buffer.size() - position >= len) {
                 return decodeStringFastPath(len);
@@ -1069,16 +1097,16 @@ else if (bufferRemaining == 0) {
     private void handleCoderError(CoderResult cr)
         throws CharacterCodingException
     {
-        if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) ||
-                (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) {
+        if ((cr.isMalformed() && actionOnMalformedString == CodingErrorAction.REPORT) ||
+                (cr.isUnmappable() && actionOnUnmappableString == CodingErrorAction.REPORT)) {
             cr.throwException();
         }
     }
 
     private String decodeStringFastPath(int length)
     {
-        if (config.actionOnMalFormedInput == CodingErrorAction.REPLACE &&
-                config.actionOnUnmappableCharacter == CodingErrorAction.REPLACE &&
+        if (actionOnMalformedString == CodingErrorAction.REPLACE &&
+                actionOnUnmappableString == CodingErrorAction.REPLACE &&
                 buffer.hasArray()) {
             String s = new String(buffer.getArray(), buffer.offset() + position, length, MessagePack.UTF8);
             position += length;
@@ -1253,7 +1281,7 @@ public int unpackRawStringHeader()
             return len;
         }
 
-        if (config.readBinaryAsString) {
+        if (allowBinaryAsString) {
             len = tryReadBinaryHeader(b);
             if (len >= 0) {
                 resetHeadByte();
@@ -1277,7 +1305,7 @@ public int unpackBinaryHeader()
             return len;
         }
 
-        if (config.readStringAsBinary) {
+        if (allowStringAsBinary) {
             len = tryReadStringHeader(b);
             if (len >= 0) {
                 resetHeadByte();
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
new file mode 100644
index 000000000..710013153
--- /dev/null
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
@@ -0,0 +1,136 @@
+//
+// MessagePack for Java
+//
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+//
+package org.msgpack.core.buffer;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * MessageBufferOutput adapter that packs data into list of byte arrays.
+ */
+public class ArrayBufferOutput
+        implements MessageBufferOutput
+{
+    private List list;
+    private MessageBuffer lastBuffer;
+    private int bufferSize;
+
+    public ArrayBufferOutput()
+    {
+        this(8192);
+    }
+
+    public ArrayBufferOutput(int bufferSize)
+    {
+        this.bufferSize = bufferSize;
+        this.list = new ArrayList();
+    }
+
+    public int getSize()
+    {
+        int size = 0;
+        for (MessageBuffer buffer : list) {
+            size += buffer.size();
+        }
+        return size;
+    }
+
+    public byte[] toByteArray()
+    {
+        byte[] data = new byte[getSize()];
+        int off = 0;
+        for (MessageBuffer buffer : list) {
+            buffer.getBytes(0, data, off, buffer.size());
+            off += buffer.size();
+        }
+        return data;
+    }
+
+    public MessageBuffer toMessageBuffer()
+    {
+        if (list.size() == 1) {
+            return list.get(0);
+        }
+        else if (list.isEmpty()) {
+            return MessageBuffer.newBuffer(0);
+        }
+        else {
+            return MessageBuffer.wrap(toByteArray());
+        }
+    }
+
+    public List toBufferList()
+    {
+        return new ArrayList(list);
+    }
+
+    /**
+     * Clears the internal buffers
+     */
+    public void clear()
+    {
+        list.clear();
+    }
+
+    @Override
+    public MessageBuffer next(int mimimumSize)
+    {
+        if (lastBuffer != null && lastBuffer.size() > mimimumSize) {
+            return lastBuffer;
+        }
+        else {
+            int size = Math.max(bufferSize, mimimumSize);
+            MessageBuffer buffer = MessageBuffer.newBuffer(size);
+            lastBuffer = buffer;
+            return buffer;
+        }
+    }
+
+    @Override
+    public void writeBuffer(int length)
+    {
+        list.add(lastBuffer.slice(0, length));
+        if (lastBuffer.size() - length > bufferSize / 4) {
+            lastBuffer = lastBuffer.slice(length, lastBuffer.size() - length);
+        }
+        else {
+            lastBuffer = null;
+        }
+    }
+
+    @Override
+    public void write(byte[] buffer, int offset, int length)
+    {
+        MessageBuffer copy = MessageBuffer.newBuffer(length);
+        copy.putBytes(0, buffer, offset, length);
+        list.add(copy);
+    }
+
+    @Override
+    public void add(byte[] buffer, int offset, int length)
+    {
+        MessageBuffer wrapped = MessageBuffer.wrap(buffer, offset, length);
+        list.add(wrapped);
+    }
+
+    @Override
+    public void close()
+    { }
+
+    @Override
+    public void flush()
+    { }
+}
diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
index 7636742e0..d7dffe64b 100644
--- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
+++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
@@ -17,6 +17,7 @@
 
 import org.msgpack.core.MessageFormat;
 import org.msgpack.core.MessagePack;
+import org.msgpack.core.MessagePackFactory;
 import org.msgpack.core.MessagePacker;
 import org.msgpack.core.MessageUnpacker;
 import org.msgpack.value.ArrayValue;
@@ -246,24 +247,22 @@ public static void configuration()
             throws IOException
     {
         // Build a conifiguration
-        MessagePack.Config config = new MessagePack.ConfigBuilder()
-                .onMalFormedInput(CodingErrorAction.REPLACE)         // Drop malformed and unmappable UTF-8 characters
-                .onUnmappableCharacter(CodingErrorAction.REPLACE)
-                .packerBufferSize(8192 * 2)
-                .build();
+        MessagePackFactory factory = new MessagePackFactory()
+                .unpackActionOnMalformedString(CodingErrorAction.REPLACE)         // Drop malformed and unmappable UTF-8 characters
+                .unpackActionOnUnmappableString(CodingErrorAction.REPLACE)
+                .outputBufferSize(8192 * 2);
         // Create a  that uses this configuration
-        MessagePack msgpack = new MessagePack(config);
 
         // Pack data
         ByteArrayOutputStream out = new ByteArrayOutputStream();
-        MessagePacker packer = msgpack.newPacker(out);
+        MessagePacker packer = factory.newPacker(out);
         packer.packInt(10);
         packer.packBoolean(true);
         packer.close();
 
         // Unpack data
         byte[] packedData = out.toByteArray();
-        MessageUnpacker unpacker = msgpack.newUnpacker(packedData);
+        MessageUnpacker unpacker = factory.newUnpacker(packedData);
         int i = unpacker.unpackInt();  // 10
         boolean b = unpacker.unpackBoolean(); // true
         unpacker.close();
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala
index be9d270cd..a6a71e2d9 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala
@@ -15,7 +15,7 @@
 //
 package org.msgpack.core
 
-import org.msgpack.core.MessagePack.Code
+import org.msgpack.core.MessageFormat.Code
 import org.msgpack.value.ValueType
 import org.scalatest.exceptions.TestFailedException
 
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
index f903cf88d..5cf8ea2e6 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
@@ -20,7 +20,7 @@ import java.math.BigInteger
 import java.nio.CharBuffer
 import java.nio.charset.{CodingErrorAction, UnmappableCharacterException}
 
-import org.msgpack.core.MessagePack.Code
+import org.msgpack.core.MessageFormat.Code
 import org.msgpack.value.{Value, Variable}
 
 import scala.util.Random
@@ -117,17 +117,17 @@ class MessagePackTest extends MessagePackSpec {
     }
 
 
-    def check[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A, msgpack: MessagePack = MessagePack.DEFAULT): Unit = {
+    def check[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A, factory: MessagePackFactory = new MessagePackFactory()): Unit = {
       var b: Array[Byte] = null
       try {
         val bs = new ByteArrayOutputStream()
-        val packer = msgpack.newPacker(bs)
+        val packer = factory.newPacker(bs)
         pack(packer)
         packer.close()
 
         b = bs.toByteArray
 
-        val unpacker = msgpack.newUnpacker(b)
+        val unpacker = factory.newUnpacker(b)
         val ret = unpack(unpacker)
         ret shouldBe v
       }
@@ -142,16 +142,16 @@ class MessagePackTest extends MessagePackSpec {
     }
 
     def checkException[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A,
-                          msgpack: MessagePack = MessagePack.DEFAULT): Unit = {
+                          factory: MessagePackFactory = new MessagePackFactory()): Unit = {
       var b: Array[Byte] = null
       val bs = new ByteArrayOutputStream()
-      val packer = msgpack.newPacker(bs)
+      val packer = factory.newPacker(bs)
       pack(packer)
       packer.close()
 
       b = bs.toByteArray
 
-      val unpacker = msgpack.newUnpacker(b)
+      val unpacker = factory.newUnpacker(b)
       val ret = unpack(unpacker)
 
       fail("cannot not reach here")
@@ -297,11 +297,9 @@ class MessagePackTest extends MessagePackSpec {
       //val unmappableChar = Array[Char](new Character(0xfc0a).toChar)
 
       // Report error on unmappable character
-      val config = new MessagePack.ConfigBuilder()
-        .onMalFormedInput(CodingErrorAction.REPORT)
-        .onUnmappableCharacter(CodingErrorAction.REPORT)
-        .build()
-      val msgpack = new MessagePack(config)
+      val factory = new MessagePackFactory()
+        .unpackActionOnMalformedString(CodingErrorAction.REPORT)
+        .unpackActionOnUnmappableString(CodingErrorAction.REPORT);
 
       for (bytes <- Seq(unmappable)) {
         When("unpacking")
@@ -311,7 +309,7 @@ class MessagePackTest extends MessagePackSpec {
             packer.writePayload(bytes)
           },
           _.unpackString(),
-          msgpack)
+          factory)
         }
         catch {
           case e: MessageStringCodingException => // OK
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
index f6971b331..8cb0d723b 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
@@ -30,10 +30,10 @@ import scala.util.Random
 class MessagePackerTest
   extends MessagePackSpec {
 
-  val msgpack = MessagePack.DEFAULT
+  val factory = new MessagePackFactory()
 
   def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) {
-    val unpacker = msgpack.newUnpacker(packed)
+    val unpacker = factory.newUnpacker(packed)
     val b = Array.newBuilder[Int]
     while (unpacker.hasNext) {
       b += unpacker.unpackInt()
@@ -69,7 +69,7 @@ class MessagePackerTest
 
       val b = new
           ByteArrayOutputStream
-      val packer = msgpack.newPacker(b)
+      val packer = factory.newPacker(b)
       intSeq foreach packer.packInt
       packer.close
       verifyIntSeq(intSeq, b.toByteArray)
@@ -102,7 +102,7 @@ class MessagePackerTest
         block("no-buffer-reset") {
           val out = new
               ByteArrayOutputStream
-          IOUtil.withResource(msgpack.newPacker(out)) { packer =>
+          IOUtil.withResource(factory.newPacker(out)) { packer =>
             for (i <- 0 until N) {
               val outputStream = new
                   ByteArrayOutputStream()
@@ -118,7 +118,7 @@ class MessagePackerTest
         block("buffer-reset") {
           val out = new
               ByteArrayOutputStream
-          IOUtil.withResource(msgpack.newPacker(out)) { packer =>
+          IOUtil.withResource(factory.newPacker(out)) { packer =>
             val bufferOut = new
                 OutputStreamBufferOutput(new
                     ByteArrayOutputStream())
@@ -142,15 +142,14 @@ class MessagePackerTest
 
       // TODO: Refactor this test code to fit other ones.
       def test(bufferSize: Int, stringSize: Int): Boolean = {
-        val msgpack = new
-            MessagePack(new
-                MessagePack.ConfigBuilder().packerBufferSize(bufferSize).build)
+        val factory = new MessagePackFactory()
+            .outputBufferSize(bufferSize);
         val str = "a" * stringSize
         val rawString = ValueFactory.newString(str.getBytes("UTF-8"))
         val array = ValueFactory.newArray(rawString)
         val out = new
             ByteArrayOutputStream()
-        val packer = msgpack.newPacker(out)
+        val packer = factory.newPacker(out)
         packer.packValue(array)
         packer.close()
         out.toByteArray
@@ -266,7 +265,7 @@ class MessagePackerTest
   "compute totalWrittenBytes" in {
     val out = new
         ByteArrayOutputStream
-    val packerTotalWrittenBytes = IOUtil.withResource(msgpack.newPacker(out)) { packer =>
+    val packerTotalWrittenBytes = IOUtil.withResource(factory.newPacker(out)) { packer =>
       packer.packByte(0) // 1
         .packBoolean(true) // 1
         .packShort(12) // 1
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
index 672edd615..763b6fe78 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
@@ -29,11 +29,11 @@ import scala.util.Random
  */
 class MessageUnpackerTest extends MessagePackSpec {
 
-  val msgpack = MessagePack.DEFAULT
+  val factory = new MessagePackFactory()
 
   def testData: Array[Byte] = {
     val out = new ByteArrayOutputStream()
-    val packer = msgpack.newPacker(out)
+    val packer = factory.newPacker(out)
 
     packer
       .packArrayHeader(2)
@@ -55,7 +55,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
   def testData2: Array[Byte] = {
     val out = new ByteArrayOutputStream()
-    val packer = msgpack.newPacker(out);
+    val packer = factory.newPacker(out);
 
     packer
       .packBoolean(true)
@@ -125,7 +125,7 @@ class MessageUnpackerTest extends MessagePackSpec {
   def testData3(N: Int): Array[Byte] = {
 
     val out = new ByteArrayOutputStream()
-    val packer = msgpack.newPacker(out)
+    val packer = factory.newPacker(out)
 
     val r = new Random(0)
 
@@ -179,7 +179,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "parse message packed data" taggedAs ("unpack") in {
       val arr = testData
 
-      val unpacker = msgpack.newUnpacker(arr)
+      val unpacker = factory.newUnpacker(arr)
 
       var count = 0
       while (unpacker.hasNext) {
@@ -192,7 +192,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
     "skip reading values" in {
 
-      val unpacker = msgpack.newUnpacker(testData)
+      val unpacker = factory.newUnpacker(testData)
       var skipCount = 0
       while (unpacker.hasNext) {
         unpacker.skipValue()
@@ -209,7 +209,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
       time("skip performance", repeat = 100) {
         block("switch") {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           var skipCount = 0
           while (unpacker.hasNext) {
             unpacker.skipValue()
@@ -227,7 +227,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
       val ib = Seq.newBuilder[Int]
 
-      val unpacker = msgpack.newUnpacker(testData2)
+      val unpacker = factory.newUnpacker(testData2)
       while (unpacker.hasNext) {
         val f = unpacker.getNextFormat
         f.getValueType match {
@@ -269,7 +269,7 @@ class MessageUnpackerTest extends MessagePackSpec {
       trait SplitTest {
         val data: Array[Byte]
         def run {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           val numElems = {
             var c = 0
             while (unpacker.hasNext) {
@@ -326,7 +326,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7") {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           var count = 0
           try {
             while (unpacker.hasNext) {
@@ -428,7 +428,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7") {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           var count = 0
           try {
             while (unpacker.hasNext) {
@@ -449,7 +449,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "be faster for reading binary than v6" taggedAs ("cmp-binary") in {
 
       val bos = new ByteArrayOutputStream()
-      val packer = msgpack.newPacker(bos)
+      val packer = factory.newPacker(bos)
       val L = 10000
       val R = 100
       (0 until R).foreach { i =>
@@ -472,7 +472,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7") {
-          val unpacker = msgpack.newUnpacker(b)
+          val unpacker = factory.newUnpacker(b)
           var i = 0
           while (i < R) {
             val len = unpacker.unpackBinaryHeader()
@@ -484,7 +484,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7-ref") {
-          val unpacker = msgpack.newUnpacker(b)
+          val unpacker = factory.newUnpacker(b)
           var i = 0
           while (i < R) {
             val len = unpacker.unpackBinaryHeader()
@@ -505,12 +505,12 @@ class MessageUnpackerTest extends MessagePackSpec {
         val data = new Array[Byte](s)
         Random.nextBytes(data)
         val b = new ByteArrayOutputStream()
-        val packer = msgpack.newPacker(b)
+        val packer = factory.newPacker(b)
         packer.packBinaryHeader(s)
         packer.writePayload(data)
         packer.close()
 
-        val unpacker = msgpack.newUnpacker(b.toByteArray)
+        val unpacker = factory.newUnpacker(b.toByteArray)
         val len = unpacker.unpackBinaryHeader()
         len shouldBe s
         val ref = unpacker.readPayloadAsReference(len)
@@ -529,7 +529,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
       val data = intSeq
       val b = createMessagePackData(packer => data foreach packer.packInt)
-      val unpacker = msgpack.newUnpacker(b)
+      val unpacker = factory.newUnpacker(b)
 
       val unpacked = Array.newBuilder[Int]
       while (unpacker.hasNext) {
@@ -564,7 +564,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "improve the performance via reset method" taggedAs ("reset-arr") in {
 
       val out = new ByteArrayOutputStream
-      val packer = msgpack.newPacker(out)
+      val packer = factory.newPacker(out)
       packer.packInt(0)
       packer.flush
       val arr = out.toByteArray
@@ -573,7 +573,7 @@ class MessageUnpackerTest extends MessagePackSpec {
       val N = 1000
       val t = time("unpacker", repeat = 10) {
         block("no-buffer-reset") {
-          IOUtil.withResource(msgpack.newUnpacker(arr)) { unpacker =>
+          IOUtil.withResource(factory.newUnpacker(arr)) { unpacker =>
             for (i <- 0 until N) {
               val buf = new ArrayBufferInput(arr)
               unpacker.reset(buf)
@@ -584,7 +584,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("reuse-array-input") {
-          IOUtil.withResource(msgpack.newUnpacker(arr)) { unpacker =>
+          IOUtil.withResource(factory.newUnpacker(arr)) { unpacker =>
             val buf = new ArrayBufferInput(arr)
             for (i <- 0 until N) {
               buf.reset(arr)
@@ -596,7 +596,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("reuse-message-buffer") {
-          IOUtil.withResource(msgpack.newUnpacker(arr)) { unpacker =>
+          IOUtil.withResource(factory.newUnpacker(arr)) { unpacker =>
             val buf = new ArrayBufferInput(arr)
             for (i <- 0 until N) {
               buf.reset(mb)
@@ -640,7 +640,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "unpack large string data" taggedAs ("large-string") in {
       def createLargeData(stringLength: Int): Array[Byte] = {
         val out = new ByteArrayOutputStream()
-        val packer = msgpack.newPacker(out)
+        val packer = factory.newPacker(out)
 
         packer
           .packArrayHeader(2)
@@ -655,7 +655,7 @@ class MessageUnpackerTest extends MessagePackSpec {
       Seq(8191, 8192, 8193, 16383, 16384, 16385).foreach { n =>
         val arr = createLargeData(n)
 
-        val unpacker = msgpack.newUnpacker(arr)
+        val unpacker = factory.newUnpacker(arr)
 
         unpacker.unpackArrayHeader shouldBe 2
         unpacker.unpackString.length shouldBe n
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
index d7ebeac84..b6ee7bf08 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
@@ -135,10 +135,8 @@ class MessageBufferInputTest
 
   def createTempFileWithInputStream = {
     val f = createTempFile
-    val out = new
-        FileOutputStream(f)
-    new
-        MessagePack().newPacker(out).packInt(42).close
+    val out = new FileOutputStream(f)
+    MessagePack.newDefaultPacker(out).packInt(42).close
     val in = new
         FileInputStream(f)
     (f, in)
diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala
index 6634ef606..2bd1c7b14 100644
--- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala
@@ -15,7 +15,7 @@
 //
 package org.msgpack.value
 
-import org.msgpack.core.MessagePack.Code._
+import org.msgpack.core.MessageFormat.Code._
 import org.msgpack.core.{MessageFormat, MessageFormatException, MessagePackSpec}
 
 /**

From 285ec1fcbb838e73d5020f280f776c4348501860 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Fri, 25 Dec 2015 15:51:57 +0900
Subject: [PATCH 33/99] removed support for ByteBuffer

---
 .../java/org/msgpack/core/MessagePack.java    |   2 -
 .../java/org/msgpack/core/MessagePacker.java  |   2 +-
 .../org/msgpack/core/MessageUnpacker.java     |  10 +-
 .../core/buffer/ArrayBufferOutput.java        |   6 +-
 .../msgpack/core/buffer/ByteBufferInput.java  |  70 --------
 .../core/buffer/ChannelBufferInput.java       |   4 +-
 .../core/buffer/ChannelBufferOutput.java      |   6 +-
 .../msgpack/core/buffer/MessageBuffer.java    | 150 +++---------------
 .../msgpack/core/buffer/MessageBufferBE.java  |  15 +-
 .../msgpack/core/buffer/MessageBufferU.java   |  85 +++++-----
 .../core/buffer/OutputStreamBufferOutput.java |   4 +-
 .../msgpack/core/buffer/ByteStringTest.scala  |  15 --
 .../core/buffer/MessageBufferInputTest.scala  |   5 -
 .../core/buffer/MessageBufferTest.scala       |  43 +----
 14 files changed, 91 insertions(+), 326 deletions(-)
 delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
index 8af53a884..f1bee0774 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
@@ -133,6 +133,4 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, in
     {
         return defaultFactory.newUnpacker(contents, offset, length);
     }
-
-    // TODO add convenient methods here to pack/unpack objects with byte array/stream
 }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
index a145df162..7c71b6807 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
@@ -448,7 +448,7 @@ private void prepareEncoder()
     private int encodeStringToBufferAt(int pos, String s)
     {
         prepareEncoder();
-        ByteBuffer bb = buffer.toByteBuffer(pos, buffer.size() - pos);
+        ByteBuffer bb = buffer.sliceAsByteBuffer(pos, buffer.size() - pos);
         int startPosition = bb.position();
         CharBuffer in = CharBuffer.wrap(s);
         CoderResult cr = encoder.encode(in, bb, true);
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 7e54d5253..2e00a5bc3 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -106,7 +106,7 @@ public class MessageUnpacker
      * Extra buffer for fixed-length data at the buffer boundary.
      * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required.
      */
-    private final MessageBuffer castBuffer = MessageBuffer.newBuffer(8);
+    private final MessageBuffer castBuffer = MessageBuffer.allocate(8);
 
     /**
      * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer.
@@ -1032,7 +1032,7 @@ else if (bufferRemaining == 0) {
                     nextBuffer();
                 }
                 else {
-                    ByteBuffer bb = buffer.toByteBuffer(position, bufferRemaining);
+                    ByteBuffer bb = buffer.sliceAsByteBuffer(position, bufferRemaining);
                     int bbStartPosition = bb.position();
                     decodeBuffer.clear();
 
@@ -1114,7 +1114,7 @@ private String decodeStringFastPath(int length)
         }
         else {
             resetDecoder();
-            ByteBuffer bb = buffer.toByteBuffer();
+            ByteBuffer bb = buffer.sliceAsByteBuffer();
             bb.limit(position + length);
             bb.position(position);
             CharBuffer cb;
@@ -1395,8 +1395,8 @@ public MessageBuffer readPayloadAsReference(int length)
             position += length;
             return slice;
         }
-        MessageBuffer dst = MessageBuffer.newBuffer(length);
-        readPayload(dst.getReference());
+        MessageBuffer dst = MessageBuffer.allocate(length);
+        readPayload(dst.sliceAsByteBuffer());
         return dst;
     }
 
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
index 710013153..186a579af 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
@@ -65,7 +65,7 @@ public MessageBuffer toMessageBuffer()
             return list.get(0);
         }
         else if (list.isEmpty()) {
-            return MessageBuffer.newBuffer(0);
+            return MessageBuffer.allocate(0);
         }
         else {
             return MessageBuffer.wrap(toByteArray());
@@ -93,7 +93,7 @@ public MessageBuffer next(int mimimumSize)
         }
         else {
             int size = Math.max(bufferSize, mimimumSize);
-            MessageBuffer buffer = MessageBuffer.newBuffer(size);
+            MessageBuffer buffer = MessageBuffer.allocate(size);
             lastBuffer = buffer;
             return buffer;
         }
@@ -114,7 +114,7 @@ public void writeBuffer(int length)
     @Override
     public void write(byte[] buffer, int offset, int length)
     {
-        MessageBuffer copy = MessageBuffer.newBuffer(length);
+        MessageBuffer copy = MessageBuffer.allocate(length);
         copy.putBytes(0, buffer, offset, length);
         list.add(copy);
     }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java
deleted file mode 100644
index 034d8882b..000000000
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// MessagePack for Java
-//
-//    Licensed under the Apache License, Version 2.0 (the "License");
-//    you may not use this file except in compliance with the License.
-//    You may obtain a copy of the License at
-//
-//        http://www.apache.org/licenses/LICENSE-2.0
-//
-//    Unless required by applicable law or agreed to in writing, software
-//    distributed under the License is distributed on an "AS IS" BASIS,
-//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//    See the License for the specific language governing permissions and
-//    limitations under the License.
-//
-package org.msgpack.core.buffer;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import static org.msgpack.core.Preconditions.checkNotNull;
-
-/**
- * {@link MessageBufferInput} adapter for {@link java.nio.ByteBuffer}
- */
-public class ByteBufferInput
-        implements MessageBufferInput
-{
-    private ByteBuffer input;
-    private boolean isRead = false;
-
-    public ByteBufferInput(ByteBuffer input)
-    {
-        this.input = checkNotNull(input, "input ByteBuffer is null");
-    }
-
-    /**
-     * Reset buffer. This method doesn't close the old resource.
-     *
-     * @param input new buffer
-     * @return the old resource
-     */
-    public ByteBuffer reset(ByteBuffer input)
-    {
-        ByteBuffer old = this.input;
-        this.input = input;
-        isRead = false;
-        return old;
-    }
-
-    @Override
-    public MessageBuffer next()
-            throws IOException
-    {
-        if (isRead) {
-            return null;
-        }
-
-        isRead = true;
-        return MessageBuffer.wrap(input);
-    }
-
-    @Override
-    public void close()
-            throws IOException
-    {
-        // Nothing to do
-    }
-
-}
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
index 73dcb5db6..781b7afb9 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
@@ -40,7 +40,7 @@ public ChannelBufferInput(ReadableByteChannel channel, int bufferSize)
     {
         this.channel = checkNotNull(channel, "input channel is null");
         checkArgument(bufferSize > 0, "buffer size must be > 0: " + bufferSize);
-        this.m = MessageBuffer.newBuffer(bufferSize);
+        this.m = MessageBuffer.allocate(bufferSize);
     }
 
     /**
@@ -61,7 +61,7 @@ public ReadableByteChannel reset(ReadableByteChannel channel)
     public MessageBuffer next()
             throws IOException
     {
-        ByteBuffer b = m.toByteBuffer();
+        ByteBuffer b = m.sliceAsByteBuffer();
         while (b.remaining() > 0) {
             int ret = channel.read(b);
             if (ret == -1) {
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java
index b981cc95d..32969f29a 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java
@@ -38,7 +38,7 @@ public ChannelBufferOutput(WritableByteChannel channel)
     public ChannelBufferOutput(WritableByteChannel channel, int bufferSize)
     {
         this.channel = checkNotNull(channel, "output channel is null");
-        this.buffer = MessageBuffer.newBuffer(bufferSize);
+        this.buffer = MessageBuffer.allocate(bufferSize);
     }
 
     /**
@@ -60,7 +60,7 @@ public MessageBuffer next(int mimimumSize)
             throws IOException
     {
         if (buffer.size() < mimimumSize) {
-            buffer = MessageBuffer.newBuffer(mimimumSize);
+            buffer = MessageBuffer.allocate(mimimumSize);
         }
         return buffer;
     }
@@ -69,7 +69,7 @@ public MessageBuffer next(int mimimumSize)
     public void writeBuffer(int length)
             throws IOException
     {
-        ByteBuffer bb = buffer.toByteBuffer(0, length);
+        ByteBuffer bb = buffer.sliceAsByteBuffer(0, length);
         while (bb.hasRemaining()) {
             channel.write(bb);
         }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
index fce8020ce..e2258265e 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
@@ -39,11 +39,11 @@ public class MessageBuffer
 {
     static final boolean isUniversalBuffer;
     static final Unsafe unsafe;
+
     /**
      * Reference to MessageBuffer Constructors
      */
     private static final Constructor mbArrConstructor;
-    private static final Constructor mbBBConstructor;
 
     /**
      * The offset from the object memory header to its byte array data
@@ -143,14 +143,9 @@ public class MessageBuffer
                 Class bufferCls = Class.forName(bufferClsName);
 
                 // MessageBufferX(byte[]) constructor
-                Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class);
+                Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class);
                 mbArrCstr.setAccessible(true);
                 mbArrConstructor = mbArrCstr;
-
-                // MessageBufferX(ByteBuffer) constructor
-                Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class);
-                mbBBCstr.setAccessible(true);
-                mbBBConstructor = mbBBCstr;
             }
             catch (Exception e) {
                 e.printStackTrace(System.err);
@@ -176,67 +171,19 @@ public class MessageBuffer
      */
     protected final int size;
 
-    /**
-     * Reference is used to hold a reference to an object that holds the underlying memory so that it cannot be
-     * released by the garbage collector.
-     */
-    protected final ByteBuffer reference;
-
-    static MessageBuffer newOffHeapBuffer(int length)
-    {
-        // This method is not available in Android OS
-        if (!isUniversalBuffer) {
-            long address = unsafe.allocateMemory(length);
-            return new MessageBuffer(address, length);
-        }
-        else {
-            return newDirectBuffer(length);
-        }
-    }
-
-    public static MessageBuffer newDirectBuffer(int length)
-    {
-        ByteBuffer m = ByteBuffer.allocateDirect(length);
-        return newMessageBuffer(m);
-    }
-
-    public static MessageBuffer newBuffer(int length)
+    public static MessageBuffer allocate(int length)
     {
-        return newMessageBuffer(new byte[length]);
+        return wrap(new byte[length]);
     }
 
     public static MessageBuffer wrap(byte[] array)
     {
-        return newMessageBuffer(array);
+        return newMessageBuffer(array, 0, array.length);
     }
 
     public static MessageBuffer wrap(byte[] array, int offset, int length)
     {
-        return newMessageBuffer(array).slice(offset, length);
-    }
-
-    public static MessageBuffer wrap(ByteBuffer bb)
-    {
-        return newMessageBuffer(bb).slice(bb.position(), bb.remaining());
-    }
-
-    /**
-     * Creates a new MessageBuffer instance backed by ByteBuffer
-     *
-     * @param bb
-     * @return
-     */
-    private static MessageBuffer newMessageBuffer(ByteBuffer bb)
-    {
-        checkNotNull(bb);
-        try {
-            // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be
-            // generated to resolve one of the method references when two or more classes overrides the method.
-            return (MessageBuffer) mbBBConstructor.newInstance(bb);
-        }
-        catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        return newMessageBuffer(array, offset, length);
     }
 
     /**
@@ -245,11 +192,11 @@ private static MessageBuffer newMessageBuffer(ByteBuffer bb)
      * @param arr
      * @return
      */
-    private static MessageBuffer newMessageBuffer(byte[] arr)
+    private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len)
     {
         checkNotNull(arr);
         try {
-            return (MessageBuffer) mbArrConstructor.newInstance(arr);
+            return (MessageBuffer) mbArrConstructor.newInstance(arr, off, len);
         }
         catch (Throwable e) {
             throw new RuntimeException(e);
@@ -261,76 +208,31 @@ public static void releaseBuffer(MessageBuffer buffer)
         if (isUniversalBuffer || buffer.base instanceof byte[]) {
             // We have nothing to do. Wait until the garbage-collector collects this array object
         }
-        else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) {
-            DirectBufferAccess.clean(buffer.base);
-        }
         else {
             // Maybe cannot reach here
             unsafe.freeMemory(buffer.address);
         }
     }
 
-    /**
-     * Create a MessageBuffer instance from a given memory address and length
-     *
-     * @param address
-     * @param length
-     */
-    MessageBuffer(long address, int length)
-    {
-        this.base = null;
-        this.address = address;
-        this.size = length;
-        this.reference = null;
-    }
-
-    /**
-     * Create a MessageBuffer instance from a given ByteBuffer instance
-     *
-     * @param bb
-     */
-    MessageBuffer(ByteBuffer bb)
-    {
-        if (bb.isDirect()) {
-            if (isUniversalBuffer) {
-                throw new IllegalStateException("Cannot create MessageBuffer from DirectBuffer");
-            }
-            // Direct buffer or off-heap memory
-            this.base = null;
-            this.address = DirectBufferAccess.getAddress(bb);
-            this.size = bb.capacity();
-            this.reference = bb;
-        }
-        else if (bb.hasArray()) {
-            this.base = bb.array();
-            this.address = ARRAY_BYTE_BASE_OFFSET;
-            this.size = bb.array().length;
-            this.reference = null;
-        }
-        else {
-            throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer are supported");
-        }
-    }
-
     /**
      * Create a MessageBuffer instance from an java heap array
      *
      * @param arr
+     * @param offset
+     * @param length
      */
-    MessageBuffer(byte[] arr)
+    MessageBuffer(byte[] arr, int offset, int length)
     {
         this.base = arr;
-        this.address = ARRAY_BYTE_BASE_OFFSET;
-        this.size = arr.length;
-        this.reference = null;
+        this.address = ARRAY_BYTE_BASE_OFFSET + offset;
+        this.size = length;
     }
 
-    MessageBuffer(Object base, long address, int length, ByteBuffer reference)
+    protected MessageBuffer(Object base, long address, int length)
     {
         this.base = base;
         this.address = address;
         this.size = length;
-        this.reference = reference;
     }
 
     /**
@@ -351,7 +253,7 @@ public MessageBuffer slice(int offset, int length)
         }
         else {
             checkArgument(offset + length <= size());
-            return new MessageBuffer(base, address + offset, length, reference);
+            return new MessageBuffer(base, address + offset, length);
         }
     }
 
@@ -411,7 +313,7 @@ public void getBytes(int index, int len, ByteBuffer dst)
         if (dst.remaining() < len) {
             throw new BufferOverflowException();
         }
-        ByteBuffer src = toByteBuffer(index, len);
+        ByteBuffer src = sliceAsByteBuffer(index, len);
         dst.put(src);
     }
 
@@ -499,15 +401,9 @@ else if (src.hasArray()) {
      * @param length
      * @return
      */
-    public ByteBuffer toByteBuffer(int index, int length)
+    public ByteBuffer sliceAsByteBuffer(int index, int length)
     {
-        if (hasArray()) {
-            return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length);
-        }
-        else {
-            assert (!isUniversalBuffer);
-            return DirectBufferAccess.newByteBuffer(address, index, length, reference);
-        }
+        return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length);
     }
 
     /**
@@ -515,9 +411,9 @@ public ByteBuffer toByteBuffer(int index, int length)
      *
      * @return
      */
-    public ByteBuffer toByteBuffer()
+    public ByteBuffer sliceAsByteBuffer()
     {
-        return toByteBuffer(0, size());
+        return sliceAsByteBuffer(0, size());
     }
 
     /**
@@ -567,12 +463,6 @@ public int offset()
         }
     }
 
-    @Insecure
-    public ByteBuffer getReference()
-    {
-        return reference;
-    }
-
     /**
      * Copy this buffer contents to another MessageBuffer
      *
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
index 4fec0cd42..3f5d24976 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
@@ -27,19 +27,14 @@
 public class MessageBufferBE
         extends MessageBuffer
 {
-    MessageBufferBE(ByteBuffer bb)
+    MessageBufferBE(byte[] arr, int offset, int length)
     {
-        super(bb);
+        super(arr, offset, length);
     }
 
-    MessageBufferBE(byte[] arr)
+    private MessageBufferBE(Object base, long address, int length)
     {
-        super(arr);
-    }
-
-    private MessageBufferBE(Object base, long address, int length, ByteBuffer reference)
-    {
-        super(base, address, length, reference);
+        super(base, address, length);
     }
 
     @Override
@@ -50,7 +45,7 @@ public MessageBufferBE slice(int offset, int length)
         }
         else {
             checkArgument(offset + length <= size());
-            return new MessageBufferBE(base, address + offset, length, reference);
+            return new MessageBufferBE(base, address + offset, length);
         }
     }
 
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
index 54caa8838..d5b68c1a4 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
@@ -28,15 +28,18 @@
 public class MessageBufferU
         extends MessageBuffer
 {
-    public MessageBufferU(ByteBuffer bb)
+    private final ByteBuffer wrap;
+
+    MessageBufferU(byte[] arr, int offset, int length)
     {
-        super(null, 0L, bb.capacity(), bb.order(ByteOrder.BIG_ENDIAN));
-        checkNotNull(reference);
+        super(arr, offset, length);
+        this.wrap = ByteBuffer.wrap(arr, offset, length);
     }
 
-    MessageBufferU(byte[] arr)
+    private MessageBufferU(Object base, long address, int length, ByteBuffer wrap)
     {
-        this(ByteBuffer.wrap(arr));
+        super(base, address, length);
+        this.wrap = wrap;
     }
 
     @Override
@@ -48,9 +51,9 @@ public MessageBufferU slice(int offset, int length)
         else {
             checkArgument(offset + length <= size());
             try {
-                reference.position(offset);
-                reference.limit(offset + length);
-                return new MessageBufferU(reference.slice());
+                wrap.position(offset);
+                wrap.limit(offset + length);
+                return new MessageBufferU(base, address + offset, length, wrap.slice());
             }
             finally {
                 resetBufferPosition();
@@ -60,59 +63,59 @@ public MessageBufferU slice(int offset, int length)
 
     private void resetBufferPosition()
     {
-        reference.position(0);
-        reference.limit(size);
+        wrap.position(0);
+        wrap.limit(size);
     }
 
     @Override
     public byte getByte(int index)
     {
-        return reference.get(index);
+        return wrap.get(index);
     }
 
     @Override
     public boolean getBoolean(int index)
     {
-        return reference.get(index) != 0;
+        return wrap.get(index) != 0;
     }
 
     @Override
     public short getShort(int index)
     {
-        return reference.getShort(index);
+        return wrap.getShort(index);
     }
 
     @Override
     public int getInt(int index)
     {
-        return reference.getInt(index);
+        return wrap.getInt(index);
     }
 
     @Override
     public float getFloat(int index)
     {
-        return reference.getFloat(index);
+        return wrap.getFloat(index);
     }
 
     @Override
     public long getLong(int index)
     {
-        return reference.getLong(index);
+        return wrap.getLong(index);
     }
 
     @Override
     public double getDouble(int index)
     {
-        return reference.getDouble(index);
+        return wrap.getDouble(index);
     }
 
     @Override
     public void getBytes(int index, int len, ByteBuffer dst)
     {
         try {
-            reference.position(index);
-            reference.limit(index + len);
-            dst.put(reference);
+            wrap.position(index);
+            wrap.limit(index + len);
+            dst.put(wrap);
         }
         finally {
             resetBufferPosition();
@@ -122,52 +125,52 @@ public void getBytes(int index, int len, ByteBuffer dst)
     @Override
     public void putByte(int index, byte v)
     {
-        reference.put(index, v);
+        wrap.put(index, v);
     }
 
     @Override
     public void putBoolean(int index, boolean v)
     {
-        reference.put(index, v ? (byte) 1 : (byte) 0);
+        wrap.put(index, v ? (byte) 1 : (byte) 0);
     }
 
     @Override
     public void putShort(int index, short v)
     {
-        reference.putShort(index, v);
+        wrap.putShort(index, v);
     }
 
     @Override
     public void putInt(int index, int v)
     {
-        reference.putInt(index, v);
+        wrap.putInt(index, v);
     }
 
     @Override
     public void putFloat(int index, float v)
     {
-        reference.putFloat(index, v);
+        wrap.putFloat(index, v);
     }
 
     @Override
     public void putLong(int index, long l)
     {
-        reference.putLong(index, l);
+        wrap.putLong(index, l);
     }
 
     @Override
     public void putDouble(int index, double v)
     {
-        reference.putDouble(index, v);
+        wrap.putDouble(index, v);
     }
 
     @Override
-    public ByteBuffer toByteBuffer(int index, int length)
+    public ByteBuffer sliceAsByteBuffer(int index, int length)
     {
         try {
-            reference.position(index);
-            reference.limit(index + length);
-            return reference.slice();
+            wrap.position(index);
+            wrap.limit(index + length);
+            return wrap.slice();
         }
         finally {
             resetBufferPosition();
@@ -175,17 +178,17 @@ public ByteBuffer toByteBuffer(int index, int length)
     }
 
     @Override
-    public ByteBuffer toByteBuffer()
+    public ByteBuffer sliceAsByteBuffer()
     {
-        return toByteBuffer(0, size);
+        return sliceAsByteBuffer(0, size);
     }
 
     @Override
     public void getBytes(int index, byte[] dst, int dstOffset, int length)
     {
         try {
-            reference.position(index);
-            reference.get(dst, dstOffset, length);
+            wrap.position(index);
+            wrap.get(dst, dstOffset, length);
         }
         finally {
             resetBufferPosition();
@@ -205,8 +208,8 @@ public void putByteBuffer(int index, ByteBuffer src, int len)
             int prevSrcLimit = src.limit();
             try {
                 src.limit(src.position() + len);
-                reference.position(index);
-                reference.put(src);
+                wrap.position(index);
+                wrap.put(src);
             }
             finally {
                 src.limit(prevSrcLimit);
@@ -218,8 +221,8 @@ public void putByteBuffer(int index, ByteBuffer src, int len)
     public void putBytes(int index, byte[] src, int srcOffset, int length)
     {
         try {
-            reference.position(index);
-            reference.put(src, srcOffset, length);
+            wrap.position(index);
+            wrap.put(src, srcOffset, length);
         }
         finally {
             resetBufferPosition();
@@ -230,8 +233,8 @@ public void putBytes(int index, byte[] src, int srcOffset, int length)
     public void copyTo(int index, MessageBuffer dst, int offset, int length)
     {
         try {
-            reference.position(index);
-            dst.putByteBuffer(offset, reference, length);
+            wrap.position(index);
+            dst.putByteBuffer(offset, wrap, length);
         }
         finally {
             resetBufferPosition();
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
index d6f17c783..f29832b34 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
@@ -37,7 +37,7 @@ public OutputStreamBufferOutput(OutputStream out)
     public OutputStreamBufferOutput(OutputStream out, int bufferSize)
     {
         this.out = checkNotNull(out, "output is null");
-        this.buffer = MessageBuffer.newBuffer(bufferSize);
+        this.buffer = MessageBuffer.allocate(bufferSize);
     }
 
     /**
@@ -59,7 +59,7 @@ public MessageBuffer next(int mimimumSize)
             throws IOException
     {
         if (buffer.size() < mimimumSize) {
-            buffer = MessageBuffer.newBuffer(mimimumSize);
+            buffer = MessageBuffer.allocate(mimimumSize);
         }
         return buffer;
     }
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala
index 92103dc31..eb78432d2 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala
@@ -44,19 +44,4 @@ class ByteStringTest
     new
         MessageUnpacker(input).unpackString()
   }
-
-  "Unpacking a ByteString's ByteBuffer" should {
-    "fail with a regular MessageBuffer" in {
-
-      // can't demonstrate with new ByteBufferInput(byteString.asByteBuffer)
-      // as Travis tests run with JDK6 that picks up MessageBufferU
-      a[RuntimeException] shouldBe thrownBy(unpackString(new
-          MessageBuffer(byteString.asByteBuffer)))
-    }
-
-    "succeed with a MessageBufferU" in {
-      unpackString(new
-          MessageBufferU(byteString.asByteBuffer)) shouldBe unpackedString
-    }
-  }
 }
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
index b6ee7bf08..6333e381c 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
@@ -97,11 +97,6 @@ class MessageBufferInputTest
           ArrayBufferInput(_))
     }
 
-    "support ByteBuffers" in {
-      runTest(b => new
-          ByteBufferInput(b.toByteBuffer))
-    }
-
     "support InputStreams" taggedAs ("is") in {
       runTest(b =>
         new
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala
index db4dec659..75ef00a11 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala
@@ -30,14 +30,13 @@ class MessageBufferTest
   "MessageBuffer" should {
 
     "check buffer type" in {
-      val b = MessageBuffer.newBuffer(0)
+      val b = MessageBuffer.allocate(0)
       info(s"MessageBuffer type: ${b.getClass.getName}")
     }
 
     "wrap ByteBuffer considering position and remaining values" taggedAs ("wrap-bb") in {
       val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
-      val subset = ByteBuffer.wrap(d, 2, 2)
-      val mb = MessageBuffer.wrap(subset)
+      val mb = MessageBuffer.wrap(d, 2, 2)
       mb.getByte(0) shouldBe 12
       mb.size() shouldBe 2
     }
@@ -47,8 +46,7 @@ class MessageBufferTest
       val N = 1000000
       val M = 64 * 1024 * 1024
 
-      val ub = MessageBuffer.newBuffer(M)
-      val ud = MessageBuffer.newDirectBuffer(M)
+      val ub = MessageBuffer.allocate(M)
       val hb = ByteBuffer.allocate(M)
       val db = ByteBuffer.allocateDirect(M)
 
@@ -84,14 +82,6 @@ class MessageBufferTest
           }
         }
 
-        block("unsafe direct") {
-          var i = 0
-          while (i < N) {
-            ud.getInt((i * 4) % M)
-            i += 1
-          }
-        }
-
         block("allocate") {
           var i = 0
           while (i < N) {
@@ -118,14 +108,6 @@ class MessageBufferTest
           }
         }
 
-        block("unsafe direct") {
-          var i = 0
-          while (i < N) {
-            ud.getInt((rs(i) * 4) % M)
-            i += 1
-          }
-        }
-
         block("allocate") {
           var i = 0
           while (i < N) {
@@ -146,11 +128,9 @@ class MessageBufferTest
 
     "convert to ByteBuffer" in {
       for (t <- Seq(
-        MessageBuffer.newBuffer(10),
-        MessageBuffer.newDirectBuffer(10),
-        MessageBuffer.newOffHeapBuffer(10))
+        MessageBuffer.allocate(10))
       ) {
-        val bb = t.toByteBuffer
+        val bb = t.sliceAsByteBuffer
         bb.position shouldBe 0
         bb.limit shouldBe 10
         bb.capacity shouldBe 10
@@ -159,9 +139,7 @@ class MessageBufferTest
 
     "put ByteBuffer on itself" in {
       for (t <- Seq(
-        MessageBuffer.newBuffer(10),
-        MessageBuffer.newDirectBuffer(10),
-        MessageBuffer.newOffHeapBuffer(10))
+        MessageBuffer.allocate(10))
       ) {
         val b = Array[Byte](0x02, 0x03)
         val srcArray = ByteBuffer.wrap(b)
@@ -190,13 +168,6 @@ class MessageBufferTest
         Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07)
       }
 
-      def prepareDirectBuffer : ByteBuffer = {
-        val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length)
-        directBuffer.put(prepareBytes)
-        directBuffer.flip
-        directBuffer
-      }
-
       def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = {
         val sliced = srcBuffer.slice(2, 5)
 
@@ -220,8 +191,6 @@ class MessageBufferTest
       }
 
       checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes))
-      checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)))
-      checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer))
     }
   }
 }

From a82ded243c1190ed9563edd9a187b0d383f5f082 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Fri, 25 Dec 2015 16:03:35 +0900
Subject: [PATCH 34/99] MessageBuffer is now always safe to get internal array,
 and exposing base and address become unnecessary

---
 .../java/org/msgpack/core/MessagePacker.java  |  4 +--
 .../org/msgpack/core/MessageUnpacker.java     |  9 +++---
 .../core/{annotations => }/Nullable.java      |  4 +--
 .../java/org/msgpack/core/Preconditions.java  |  1 -
 .../msgpack/core/annotations/Insecure.java    | 23 -------------
 .../msgpack/core/buffer/MessageBuffer.java    | 32 ++-----------------
 .../msgpack/core/buffer/MessageBufferU.java   |  5 ++-
 .../core/buffer/OutputStreamBufferOutput.java |  2 +-
 8 files changed, 16 insertions(+), 64 deletions(-)
 rename msgpack-core/src/main/java/org/msgpack/core/{annotations => }/Nullable.java (91%)
 delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
index 7c71b6807..b3fcff5a8 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
@@ -505,7 +505,7 @@ else if (s.length() < (1 << 8)) {
                     }
                     // move 1 byte backward to expand 3-byte header region to 3 bytes
                     buffer.putBytes(position + 3,
-                            buffer.getArray(), buffer.offset() + position + 2, written);
+                            buffer.array(), buffer.arrayOffset() + position + 2, written);
                     // write 3-byte header header
                     buffer.putByte(position++, STR16);
                     buffer.putShort(position, (short) written);
@@ -534,7 +534,7 @@ else if (s.length() < (1 << 16)) {
                     }
                     // move 2 bytes backward to expand 3-byte header region to 5 bytes
                     buffer.putBytes(position + 5,
-                            buffer.getArray(), buffer.offset() + position + 3, written);
+                            buffer.array(), buffer.arrayOffset() + position + 3, written);
                     // write 3-byte header header
                     buffer.putByte(position++, STR32);
                     buffer.putInt(position, written);
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 2e00a5bc3..6ef5901f5 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -255,8 +255,8 @@ private MessageBuffer readCastBuffer(int length)
 
             // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
             //      add copy method to MessageBuffer to solve this issue.
-            castBuffer.putBytes(0, buffer.getArray(), buffer.offset() + position, remaining);
-            castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining);
+            castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining);
+            castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining);
 
             totalReadBytes += buffer.size();
 
@@ -1106,9 +1106,8 @@ private void handleCoderError(CoderResult cr)
     private String decodeStringFastPath(int length)
     {
         if (actionOnMalformedString == CodingErrorAction.REPLACE &&
-                actionOnUnmappableString == CodingErrorAction.REPLACE &&
-                buffer.hasArray()) {
-            String s = new String(buffer.getArray(), buffer.offset() + position, length, MessagePack.UTF8);
+                actionOnUnmappableString == CodingErrorAction.REPLACE) {
+            String s = new String(buffer.array(), buffer.arrayOffset() + position, length, MessagePack.UTF8);
             position += length;
             return s;
         }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java b/msgpack-core/src/main/java/org/msgpack/core/Nullable.java
similarity index 91%
rename from msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java
rename to msgpack-core/src/main/java/org/msgpack/core/Nullable.java
index 9e7c94fab..b2e7585a5 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/Nullable.java
@@ -13,11 +13,11 @@
 //    See the License for the specific language governing permissions and
 //    limitations under the License.
 //
-package org.msgpack.core.annotations;
+package org.msgpack.core;
 
 /**
  * Annotates a field which can be null
  */
-public @interface Nullable
+@interface Nullable
 {
 }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java b/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java
index e44d97d15..d8f43bcb7 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java
@@ -31,7 +31,6 @@
  */
 package org.msgpack.core;
 
-import org.msgpack.core.annotations.Nullable;
 import org.msgpack.core.annotations.VisibleForTesting;
 
 /**
diff --git a/msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java b/msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java
deleted file mode 100644
index c8678ae41..000000000
--- a/msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// MessagePack for Java
-//
-//    Licensed under the Apache License, Version 2.0 (the "License");
-//    you may not use this file except in compliance with the License.
-//    You may obtain a copy of the License at
-//
-//        http://www.apache.org/licenses/LICENSE-2.0
-//
-//    Unless required by applicable law or agreed to in writing, software
-//    distributed under the License is distributed on an "AS IS" BASIS,
-//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//    See the License for the specific language governing permissions and
-//    limitations under the License.
-//
-package org.msgpack.core.annotations;
-
-/**
- * Annotates a code which must be used carefully.
- */
-public @interface Insecure
-{
-}
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
index e2258265e..d4d5f2238 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
@@ -15,7 +15,6 @@
 //
 package org.msgpack.core.buffer;
 
-import org.msgpack.core.annotations.Insecure;
 import sun.misc.Unsafe;
 
 import java.lang.reflect.Constructor;
@@ -428,39 +427,14 @@ public byte[] toByteArray()
         return b;
     }
 
-    @Insecure
-    public boolean hasArray()
-    {
-        return base instanceof byte[];
-    }
-
-    @Insecure
-    public byte[] getArray()
+    public byte[] array()
     {
         return (byte[]) base;
     }
 
-    @Insecure
-    public Object getBase()
-    {
-        return base;
-    }
-
-    @Insecure
-    public long getAddress()
+    public int arrayOffset()
     {
-        return address;
-    }
-
-    @Insecure
-    public int offset()
-    {
-        if (hasArray()) {
-            return (int) address - ARRAY_BYTE_BASE_OFFSET;
-        }
-        else {
-            return 0;
-        }
+        return (int) address - ARRAY_BYTE_BASE_OFFSET;
     }
 
     /**
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
index d5b68c1a4..151b6cd2e 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
@@ -33,7 +33,10 @@ public class MessageBufferU
     MessageBufferU(byte[] arr, int offset, int length)
     {
         super(arr, offset, length);
-        this.wrap = ByteBuffer.wrap(arr, offset, length);
+        ByteBuffer bb = ByteBuffer.wrap(arr);
+        bb.position(offset);
+        bb.limit(offset + length);
+        this.wrap = bb.slice();
     }
 
     private MessageBufferU(Object base, long address, int length, ByteBuffer wrap)
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
index f29832b34..08fd3960b 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
@@ -68,7 +68,7 @@ public MessageBuffer next(int mimimumSize)
     public void writeBuffer(int length)
             throws IOException
     {
-        write(buffer.getArray(), buffer.offset(), length);
+        write(buffer.array(), buffer.arrayOffset(), length);
     }
 
     @Override

From 05af0e62bacdb386f404c568f4c47116c67e83ec Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Fri, 25 Dec 2015 16:06:29 +0900
Subject: [PATCH 35/99] Remove unused import

---
 .../test/java/org/msgpack/core/example/MessagePackExample.java   | 1 -
 1 file changed, 1 deletion(-)

diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
index d7dffe64b..9a8242591 100644
--- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
+++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
@@ -32,7 +32,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.nio.charset.CodingErrorAction;
 
 /**

From 7d425ede89b073c86239d8ae7a1e431e05ae63ea Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Fri, 25 Dec 2015 16:06:48 +0900
Subject: [PATCH 36/99] fixed unused import

---
 .../test/java/org/msgpack/core/example/MessagePackExample.java   | 1 -
 1 file changed, 1 deletion(-)

diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
index d7dffe64b..9a8242591 100644
--- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
+++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
@@ -32,7 +32,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.nio.charset.CodingErrorAction;
 
 /**

From e7876009498ffefe92a09201a6e1c3d8f38add59 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Fri, 25 Dec 2015 16:31:48 +0900
Subject: [PATCH 37/99] Lift threshold of benchmark test in MessagePackerTest

---
 .../src/test/scala/org/msgpack/core/MessagePackerTest.scala     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
index f598a133f..20f4f560b 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
@@ -259,7 +259,7 @@ class MessagePackerTest
           measureDuration(fileOutput)
         }
       }
-      t("file-output-stream").averageWithoutMinMax shouldBe < (t("byte-array-output-stream").averageWithoutMinMax * 4)
+      t("file-output-stream").averageWithoutMinMax shouldBe < (t("byte-array-output-stream").averageWithoutMinMax * 5)
     }
   }
 

From 7791ffbc3bebaea5ffc0f1bd21e8945caf45a2ab Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Fri, 25 Dec 2015 16:55:56 +0900
Subject: [PATCH 38/99] Ignore micro benchmark comparison

---
 .../src/test/scala/org/msgpack/core/MessageUnpackerTest.scala | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
index 672edd615..fc03d5680 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
@@ -608,8 +608,8 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
       }
 
-      t("reuse-message-buffer").averageWithoutMinMax should be <= t("no-buffer-reset").averageWithoutMinMax
-      // This performance comparition is too close, so we disabled it
+      // This performance comparison is too close, so we disabled it
+      // t("reuse-message-buffer").averageWithoutMinMax should be <= t("no-buffer-reset").averageWithoutMinMax
       // t("reuse-array-input").averageWithoutMinMax should be <= t("no-buffer-reset").averageWithoutMinMax
     }
 

From f861bd580cbf73cbdb701b6a49aad387c095327b Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Sat, 26 Dec 2015 18:46:29 +0900
Subject: [PATCH 39/99] renamed
 org.msgpack.jackson.dataformat.MessagePackFactory to MessagePackFormatFactory
 to avoid name confusion

---
 msgpack-jackson/README.md                     |  4 +--
 ...ory.java => MessagePackFormatFactory.java} |  2 +-
 .../ExampleOfTypeInformationSerDe.java        |  2 +-
 .../MessagePackDataformatTestBase.java        |  4 +--
 ...java => MessagePackFormatFactoryTest.java} |  2 +-
 .../dataformat/MessagePackGeneratorTest.java  | 12 +++----
 .../dataformat/MessagePackParserTest.java     | 32 +++++++++----------
 ...gePackDataformatHugeDataBenchmarkTest.java |  6 ++--
 ...essagePackDataformatPojoBenchmarkTest.java |  6 ++--
 9 files changed, 35 insertions(+), 35 deletions(-)
 rename msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/{MessagePackFactory.java => MessagePackFormatFactory.java} (98%)
 rename msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/{MessagePackFactoryTest.java => MessagePackFormatFactoryTest.java} (97%)

diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md
index 55ed19233..51435b401 100644
--- a/msgpack-jackson/README.md
+++ b/msgpack-jackson/README.md
@@ -29,10 +29,10 @@ dependencies {
 
 ## Usage
 
-Only thing you need to do is to instantiate MessagePackFactory and pass it to the constructor of ObjectMapper.
+Only thing you need to do is to instantiate MessagePackFormatFactory and pass it to the constructor of ObjectMapper.
 
 ```
-  ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+  ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
   ExamplePojo orig = new ExamplePojo("komamitsu");
   byte[] bytes = objectMapper.writeValueAsBytes(orig);
   ExamplePojo value = objectMapper.readValue(bytes, ExamplePojo.class);
diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java
similarity index 98%
rename from msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java
rename to msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java
index ff7aa373f..1082e5770 100644
--- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java
+++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java
@@ -30,7 +30,7 @@
 import java.io.Writer;
 import java.util.Arrays;
 
-public class MessagePackFactory
+public class MessagePackFormatFactory
         extends JsonFactory
 {
     private static final long serialVersionUID = 2578263992015504347L;
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java
index 5414b0bdc..6a211b3ae 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java
@@ -151,7 +151,7 @@ public void test()
             objectContainer.getObjects().put("pi", pi);
         }
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         byte[] bytes = objectMapper.writeValueAsBytes(objectContainer);
         ObjectContainer restored = objectMapper.readValue(bytes, ObjectContainer.class);
 
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java
index 1d5156adc..c9692ebf9 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java
@@ -35,7 +35,7 @@
 
 public class MessagePackDataformatTestBase
 {
-    protected MessagePackFactory factory;
+    protected MessagePackFormatFactory factory;
     protected ByteArrayOutputStream out;
     protected ByteArrayInputStream in;
     protected ObjectMapper objectMapper;
@@ -47,7 +47,7 @@ public class MessagePackDataformatTestBase
     @Before
     public void setup()
     {
-        factory = new MessagePackFactory();
+        factory = new MessagePackFormatFactory();
         objectMapper = new ObjectMapper(factory);
         out = new ByteArrayOutputStream();
         in = new ByteArrayInputStream(new byte[4096]);
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java
similarity index 97%
rename from msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java
rename to msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java
index 25180f784..f7e5fe045 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java
@@ -24,7 +24,7 @@
 
 import static org.junit.Assert.assertEquals;
 
-public class MessagePackFactoryTest
+public class MessagePackFormatFactoryTest
         extends MessagePackDataformatTestBase
 {
     @Test
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
index b88d0d645..de58e4a1a 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
@@ -230,7 +230,7 @@ else if (key.equals("num")) {
     public void testMessagePackGeneratorDirectly()
             throws Exception
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         File tempFile = createTempFile();
 
         JsonGenerator generator = messagePackFactory.createGenerator(tempFile, JsonEncoding.UTF8);
@@ -257,7 +257,7 @@ public void testMessagePackGeneratorDirectly()
     public void testWritePrimitives()
             throws Exception
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         File tempFile = createTempFile();
 
         JsonGenerator generator = messagePackFactory.createGenerator(tempFile, JsonEncoding.UTF8);
@@ -280,7 +280,7 @@ public void testWritePrimitives()
     public void testBigDecimal()
             throws IOException
     {
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
 
         {
             double d0 = 1.23456789;
@@ -328,7 +328,7 @@ public void testEnableFeatureAutoCloseTarget()
             throws IOException
     {
         OutputStream out = createTempFileOutputStream();
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         ObjectMapper objectMapper = new ObjectMapper(messagePackFactory);
         List integers = Arrays.asList(1);
         objectMapper.writeValue(out, integers);
@@ -341,7 +341,7 @@ public void testDisableFeatureAutoCloseTarget()
     {
         File tempFile = createTempFile();
         OutputStream out = new FileOutputStream(tempFile);
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         ObjectMapper objectMapper = new ObjectMapper(messagePackFactory);
         objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
         List integers = Arrays.asList(1);
@@ -363,7 +363,7 @@ public void testWritePrimitiveObjectViaObjectMapper()
         File tempFile = createTempFile();
         OutputStream out = new FileOutputStream(tempFile);
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
         objectMapper.writeValue(out, 1);
         objectMapper.writeValue(out, "two");
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java
index 96af2de32..3321110d4 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java
@@ -288,7 +288,7 @@ else if (k.equals("child_map_age")) {
     public void testMessagePackParserDirectly()
             throws IOException
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory factory = new MessagePackFormatFactory();
         File tempFile = File.createTempFile("msgpackTest", "msgpack");
         tempFile.deleteOnExit();
 
@@ -301,7 +301,7 @@ public void testMessagePackParserDirectly()
         packer.packFloat(1.0f);
         packer.close();
 
-        JsonParser parser = messagePackFactory.createParser(tempFile);
+        JsonParser parser = factory.createParser(tempFile);
         assertTrue(parser instanceof MessagePackParser);
 
         JsonToken jsonToken = parser.nextToken();
@@ -354,7 +354,7 @@ public void testMessagePackParserDirectly()
     public void testReadPrimitives()
             throws Exception
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory factory = new MessagePackFormatFactory();
         File tempFile = createTempFile();
 
         FileOutputStream out = new FileOutputStream(tempFile);
@@ -367,7 +367,7 @@ public void testReadPrimitives()
         packer.writePayload(bytes);
         packer.close();
 
-        JsonParser parser = messagePackFactory.createParser(new FileInputStream(tempFile));
+        JsonParser parser = factory.createParser(new FileInputStream(tempFile));
         assertEquals(JsonToken.VALUE_STRING, parser.nextToken());
         assertEquals("foo", parser.getText());
         assertEquals(JsonToken.VALUE_NUMBER_FLOAT, parser.nextToken());
@@ -396,7 +396,7 @@ public void testBigDecimal()
         packer.packDouble(Double.MIN_NORMAL);
         packer.flush();
 
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
         mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
         List objects = mapper.readValue(out.toByteArray(), new TypeReference>() {});
         assertEquals(5, objects.size());
@@ -431,9 +431,9 @@ public void testEnableFeatureAutoCloseSource()
             throws Exception
     {
         File tempFile = createTestFile();
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory factory = new MessagePackFormatFactory();
         FileInputStream in = new FileInputStream(tempFile);
-        ObjectMapper objectMapper = new ObjectMapper(messagePackFactory);
+        ObjectMapper objectMapper = new ObjectMapper(factory);
         objectMapper.readValue(in, new TypeReference>() {});
         objectMapper.readValue(in, new TypeReference>() {});
     }
@@ -444,7 +444,7 @@ public void testDisableFeatureAutoCloseSource()
     {
         File tempFile = createTestFile();
         FileInputStream in = new FileInputStream(tempFile);
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
         objectMapper.readValue(in, new TypeReference>() {});
         objectMapper.readValue(in, new TypeReference>() {});
@@ -456,7 +456,7 @@ public void testParseBigDecimal()
     {
         ArrayList list = new ArrayList();
         list.add(new BigDecimal(Long.MAX_VALUE));
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         byte[] bytes = objectMapper.writeValueAsBytes(list);
 
         ArrayList result = objectMapper.readValue(
@@ -481,7 +481,7 @@ public void testReadPrimitiveObjectViaObjectMapper()
         packer.close();
 
         FileInputStream in = new FileInputStream(tempFile);
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
         assertEquals("foo", objectMapper.readValue(in, new TypeReference() {}));
         long l = objectMapper.readValue(in, new TypeReference() {});
@@ -511,7 +511,7 @@ public void testBinaryKey()
         packer.packLong(42);
         packer.close();
 
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
         Map object = mapper.readValue(new FileInputStream(tempFile), new TypeReference>() {});
         assertEquals(2, object.size());
         assertEquals(3.14, object.get("foo"));
@@ -533,7 +533,7 @@ public void testBinaryKeyInNestedObject()
         packer.packInt(1);
         packer.close();
 
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
         List objects = mapper.readValue(out.toByteArray(), new TypeReference>() {});
         assertEquals(2, objects.size());
         @SuppressWarnings(value = "unchecked")
@@ -555,7 +555,7 @@ public void testByteArrayKey()
         messagePacker.packBinaryHeader(1).writePayload(k1).packInt(3);
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(byte[].class, new KeyDeserializer()
         {
@@ -592,7 +592,7 @@ public void testIntegerKey()
         }
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(Integer.class, new KeyDeserializer()
         {
@@ -623,7 +623,7 @@ public void testFloatKey()
         }
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(Float.class, new KeyDeserializer()
         {
@@ -653,7 +653,7 @@ public void testBooleanKey()
         messagePacker.packBoolean(false).packInt(3);
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(Boolean.class, new KeyDeserializer()
         {
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java
index b3a159111..aaf828439 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java
@@ -20,7 +20,7 @@
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Test;
-import org.msgpack.jackson.dataformat.MessagePackFactory;
+import org.msgpack.jackson.dataformat.MessagePackFormatFactory;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -34,7 +34,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
     private final ObjectMapper origObjectMapper = new ObjectMapper();
-    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory());
     private static final List value;
     private static final byte[] packedByOriginal;
     private static final byte[] packedByMsgPack;
@@ -61,7 +61,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest
         packedByOriginal = bytes;
 
         try {
-            bytes = new ObjectMapper(new MessagePackFactory()).writeValueAsBytes(value);
+            bytes = new ObjectMapper(new MessagePackFormatFactory()).writeValueAsBytes(value);
         }
         catch (JsonProcessingException e) {
             e.printStackTrace();
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index de2118508..33c5f024c 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -19,7 +19,7 @@
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Test;
-import org.msgpack.jackson.dataformat.MessagePackFactory;
+import org.msgpack.jackson.dataformat.MessagePackFormatFactory;
 import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo;
 import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit;
 
@@ -40,11 +40,11 @@ public class MessagePackDataformatPojoBenchmarkTest
     private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
     private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
     private final ObjectMapper origObjectMapper = new ObjectMapper();
-    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory());
 
     static {
         final ObjectMapper origObjectMapper = new ObjectMapper();
-        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory());
 
         for (int i = 0; i < LOOP_MAX; i++) {
             NormalPojo pojo = new NormalPojo();

From b84cbb3aaae4d95dda2b89a20b99396b3cba4383 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Sun, 27 Dec 2015 12:58:18 +0900
Subject: [PATCH 40/99] optimized slightly MessageUnpacker.readCastBuffer

---
 .../org/msgpack/core/MessageUnpacker.java     | 26 ++++++++++++-------
 .../core/buffer/InputStreamBufferInput.java   |  2 +-
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 6ef5901f5..4dcc69e80 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -253,18 +253,26 @@ private MessageBuffer readCastBuffer(int length)
                 throw new MessageInsufficientBufferException();
             }
 
-            // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
-            //      add copy method to MessageBuffer to solve this issue.
-            castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining);
-            castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining);
-
             totalReadBytes += buffer.size();
 
-            buffer = next;
-            position = length - remaining;
-            readCastBufferPosition = 0;
+            if (remaining > 0) {
+                // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
+                //      add copy method to MessageBuffer to solve this issue.
+                castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining);
+                castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining);
+
+                buffer = next;
+                position = length - remaining;
+                readCastBufferPosition = 0;
 
-            return castBuffer;
+                return castBuffer;
+            }
+            else {
+                buffer = next;
+                position = length;
+                readCastBufferPosition = 0;
+                return buffer;
+            }
         }
     }
 
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java
index ad8aa462f..d605fec3a 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java
@@ -76,7 +76,7 @@ public MessageBuffer next()
         if (readLen == -1) {
             return null;
         }
-        return MessageBuffer.wrap(buffer).slice(0, readLen);
+        return MessageBuffer.wrap(buffer, 0, readLen);
     }
 
     @Override

From 194bd8ef143c6ee9d14f2d8316bfaf79b6d6b3ab Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Sun, 27 Dec 2015 13:14:25 +0900
Subject: [PATCH 41/99] Gave up repeatable deserialization

Adding support for repeatable to castBuffer seems hard without
performance impact. For now, here removes repeatable read support.
---
 .../org/msgpack/core/MessageUnpacker.java     | 180 ++++--------------
 1 file changed, 38 insertions(+), 142 deletions(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 4dcc69e80..ab7b3e496 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -118,11 +118,6 @@ public class MessageUnpacker
      */
     private StringBuilder decodeStringBuffer;
 
-    /**
-     * For decoding String in unpackString.
-     */
-    private int readingRawRemaining = 0;
-
     /**
      * For decoding String in unpackString.
      */
@@ -196,7 +191,6 @@ public MessageBufferInput reset(MessageBufferInput in)
         this.buffer = EMPTY_BUFFER;
         this.position = 0;
         this.totalReadBytes = 0;
-        this.readingRawRemaining = 0;
         // No need to initialize the already allocated string decoder here since we can reuse it.
 
         return old;
@@ -207,24 +201,6 @@ public long getTotalReadBytes()
         return totalReadBytes + position;
     }
 
-    private byte getHeadByte()
-            throws IOException
-    {
-        byte b = headByte;
-        if (b == HEAD_BYTE_REQUIRED) {
-            b = headByte = readByte();
-            if (b == HEAD_BYTE_REQUIRED) {
-                throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte");
-            }
-        }
-        return b;
-    }
-
-    private void resetHeadByte()
-    {
-        headByte = HEAD_BYTE_REQUIRED;
-    }
-
     private void nextBuffer()
             throws IOException
     {
@@ -291,7 +267,7 @@ private static int utf8MultibyteCharacterSize(byte firstByte)
     public boolean hasNext()
             throws IOException
     {
-        if (buffer.size() <= position) {
+        while (buffer.size() <= position) {
             MessageBuffer next = in.next();
             if (next == null) {
                 return false;
@@ -316,13 +292,12 @@ public boolean hasNext()
     public MessageFormat getNextFormat()
             throws IOException
     {
-        try {
-            byte b = getHeadByte();
-            return MessageFormat.valueOf(b);
-        }
-        catch (MessageNeverUsedFormatException ex) {
-            return MessageFormat.NEVER_USED;
+        // makes sure that buffer has at leat 1 byte
+        if (!hasNext()) {
+            throw new MessageInsufficientBufferException();
         }
+        byte b = buffer.getByte(position);
+        return MessageFormat.valueOf(b);
     }
 
     /**
@@ -395,9 +370,8 @@ public void skipValue()
     {
         int remainingValues = 1;
         while (remainingValues > 0) {
-            byte b = getHeadByte();
+            byte b = readByte();
             MessageFormat f = MessageFormat.valueOf(b);
-            resetHeadByte();
             switch (f) {
                 case POSFIXINT:
                 case NEGFIXINT:
@@ -643,9 +617,8 @@ public Variable unpackValue(Variable var)
     public void unpackNil()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (b == Code.NIL) {
-            resetHeadByte();
             return;
         }
         throw unexpected("Nil", b);
@@ -654,13 +627,11 @@ public void unpackNil()
     public boolean unpackBoolean()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (b == Code.FALSE) {
-            resetHeadByte();
             return false;
         }
         else if (b == Code.TRUE) {
-            resetHeadByte();
             return true;
         }
         throw unexpected("boolean", b);
@@ -669,61 +640,52 @@ else if (b == Code.TRUE) {
     public byte unpackByte()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 if (u8 < (byte) 0) {
                     throw overflowU8(u8);
                 }
                 return u8;
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 if (u16 < 0 || u16 > Byte.MAX_VALUE) {
                     throw overflowU16(u16);
                 }
                 return (byte) u16;
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0 || u32 > Byte.MAX_VALUE) {
                     throw overflowU32(u32);
                 }
                 return (byte) u32;
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L || u64 > Byte.MAX_VALUE) {
                     throw overflowU64(u64);
                 }
                 return (byte) u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) {
                     throw overflowI16(i16);
                 }
                 return (byte) i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) {
                     throw overflowI32(i32);
                 }
                 return (byte) i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) {
                     throw overflowI64(i64);
                 }
@@ -735,32 +697,27 @@ public byte unpackByte()
     public short unpackShort()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return (short) b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return (short) (u8 & 0xff);
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 if (u16 < (short) 0) {
                     throw overflowU16(u16);
                 }
                 return u16;
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0 || u32 > Short.MAX_VALUE) {
                     throw overflowU32(u32);
                 }
                 return (short) u32;
             case Code.UINT64: // unsigned int 64
-                resetHeadByte();
                 long u64 = readLong();
                 if (u64 < 0L || u64 > Short.MAX_VALUE) {
                     throw overflowU64(u64);
@@ -768,22 +725,18 @@ public short unpackShort()
                 return (short) u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return (short) i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) {
                     throw overflowI32(i32);
                 }
                 return (short) i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) {
                     throw overflowI64(i64);
                 }
@@ -795,49 +748,40 @@ public short unpackShort()
     public int unpackInt()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return (int) b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return u8 & 0xff;
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 return u16 & 0xffff;
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
                 if (u32 < 0) {
                     throw overflowU32(u32);
                 }
-                resetHeadByte();
                 return u32;
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) {
                     throw overflowU64(u64);
                 }
                 return (int) u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 return i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) {
                     throw overflowI64(i64);
                 }
@@ -849,23 +793,19 @@ public int unpackInt()
     public long unpackLong()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return (long) b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return (long) (u8 & 0xff);
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 return (long) (u16 & 0xffff);
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0) {
                     return (long) (u32 & 0x7fffffff) + 0x80000000L;
                 }
@@ -874,26 +814,21 @@ public long unpackLong()
                 }
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L) {
                     throw overflowU64(u64);
                 }
                 return u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return (long) i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return (long) i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 return (long) i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 return i64;
         }
         throw unexpected("Integer", b);
@@ -902,23 +837,19 @@ public long unpackLong()
     public BigInteger unpackBigInteger()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return BigInteger.valueOf((long) b);
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return BigInteger.valueOf((long) (u8 & 0xff));
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 return BigInteger.valueOf((long) (u16 & 0xffff));
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0) {
                     return BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L);
                 }
@@ -927,7 +858,6 @@ public BigInteger unpackBigInteger()
                 }
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L) {
                     BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63);
                     return bi;
@@ -937,19 +867,15 @@ public BigInteger unpackBigInteger()
                 }
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return BigInteger.valueOf((long) i8);
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return BigInteger.valueOf((long) i16);
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 return BigInteger.valueOf((long) i32);
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 return BigInteger.valueOf(i64);
         }
         throw unexpected("Integer", b);
@@ -958,15 +884,13 @@ public BigInteger unpackBigInteger()
     public float unpackFloat()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         switch (b) {
             case Code.FLOAT32: // float
                 float fv = readFloat();
-                resetHeadByte();
                 return fv;
             case Code.FLOAT64: // double
                 double dv = readDouble();
-                resetHeadByte();
                 return (float) dv;
         }
         throw unexpected("Float", b);
@@ -975,15 +899,13 @@ public float unpackFloat()
     public double unpackDouble()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         switch (b) {
             case Code.FLOAT32: // float
                 float fv = readFloat();
-                resetHeadByte();
                 return (double) fv;
             case Code.FLOAT64: // double
                 double dv = readDouble();
-                resetHeadByte();
                 return dv;
         }
         throw unexpected("Float", b);
@@ -1005,35 +927,29 @@ private void resetDecoder()
         decodeStringBuffer = new StringBuilder();
     }
 
-    /**
-     * This method is not repeatable.
-     */
     public String unpackString()
             throws IOException
     {
-        if (readingRawRemaining == 0) {
-            int len = unpackRawStringHeader();
-            if (len == 0) {
-                return EMPTY_STRING;
-            }
-            if (len > stringSizeLimit) {
-                throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len);
-            }
-            if (buffer.size() - position >= len) {
-                return decodeStringFastPath(len);
-            }
-            readingRawRemaining = len;
-            resetDecoder();
+        int len = unpackRawStringHeader();
+        if (len == 0) {
+            return EMPTY_STRING;
+        }
+        if (len > stringSizeLimit) {
+            throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len);
+        }
+        if (buffer.size() - position >= len) {
+            return decodeStringFastPath(len);
         }
 
-        assert (decoder != null);
+        resetDecoder();
 
         try {
-            while (readingRawRemaining > 0) {
+            int rawRemaining = len;
+            while (rawRemaining > 0) {
                 int bufferRemaining = buffer.size() - position;
-                if (bufferRemaining >= readingRawRemaining) {
-                    decodeStringBuffer.append(decodeStringFastPath(readingRawRemaining));
-                    readingRawRemaining = 0;
+                if (bufferRemaining >= rawRemaining) {
+                    decodeStringBuffer.append(decodeStringFastPath(rawRemaining));
+                    rawRemaining = 0;
                     break;
                 }
                 else if (bufferRemaining == 0) {
@@ -1047,7 +963,7 @@ else if (bufferRemaining == 0) {
                     CoderResult cr = decoder.decode(bb, decodeBuffer, false);
                     int readLen = bb.position() - bbStartPosition;
                     position += readLen;
-                    readingRawRemaining -= readLen;
+                    rawRemaining -= readLen;
                     decodeStringBuffer.append(decodeBuffer.flip());
 
                     if (cr.isError()) {
@@ -1090,7 +1006,7 @@ else if (bufferRemaining == 0) {
                                 throw new MessageFormatException("Unexpected UTF-8 multibyte sequence", ex);
                             }
                         }
-                        readingRawRemaining -= multiByteBuffer.limit();
+                        rawRemaining -= multiByteBuffer.limit();
                         decodeStringBuffer.append(decodeBuffer.flip());
                     }
                 }
@@ -1139,20 +1055,17 @@ private String decodeStringFastPath(int length)
     public int unpackArrayHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedArray(b)) { // fixarray
-            resetHeadByte();
             return b & 0x0f;
         }
         switch (b) {
             case Code.ARRAY16: { // array 16
                 int len = readNextLength16();
-                resetHeadByte();
                 return len;
             }
             case Code.ARRAY32: { // array 32
                 int len = readNextLength32();
-                resetHeadByte();
                 return len;
             }
         }
@@ -1162,20 +1075,17 @@ public int unpackArrayHeader()
     public int unpackMapHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedMap(b)) { // fixmap
-            resetHeadByte();
             return b & 0x0f;
         }
         switch (b) {
             case Code.MAP16: { // map 16
                 int len = readNextLength16();
-                resetHeadByte();
                 return len;
             }
             case Code.MAP32: { // map 32
                 int len = readNextLength32();
-                resetHeadByte();
                 return len;
             }
         }
@@ -1185,36 +1095,30 @@ public int unpackMapHeader()
     public ExtensionTypeHeader unpackExtensionTypeHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         switch (b) {
             case Code.FIXEXT1: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 1);
             }
             case Code.FIXEXT2: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 2);
             }
             case Code.FIXEXT4: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 4);
             }
             case Code.FIXEXT8: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 8);
             }
             case Code.FIXEXT16: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 16);
             }
             case Code.EXT8: {
                 MessageBuffer castBuffer = readCastBuffer(2);
-                resetHeadByte();
                 int u8 = castBuffer.getByte(readCastBufferPosition);
                 int length = u8 & 0xff;
                 byte type = castBuffer.getByte(readCastBufferPosition + 1);
@@ -1222,7 +1126,6 @@ public ExtensionTypeHeader unpackExtensionTypeHeader()
             }
             case Code.EXT16: {
                 MessageBuffer castBuffer = readCastBuffer(3);
-                resetHeadByte();
                 int u16 = castBuffer.getShort(readCastBufferPosition);
                 int length = u16 & 0xffff;
                 byte type = castBuffer.getByte(readCastBufferPosition + 2);
@@ -1230,7 +1133,6 @@ public ExtensionTypeHeader unpackExtensionTypeHeader()
             }
             case Code.EXT32: {
                 MessageBuffer castBuffer = readCastBuffer(5);
-                resetHeadByte();
                 int u32 = castBuffer.getInt(readCastBufferPosition);
                 if (u32 < 0) {
                     throw overflowU32Size(u32);
@@ -1277,21 +1179,18 @@ private int tryReadBinaryHeader(byte b)
     public int unpackRawStringHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedRaw(b)) { // FixRaw
-            resetHeadByte();
             return b & 0x1f;
         }
         int len = tryReadStringHeader(b);
         if (len >= 0) {
-            resetHeadByte();
             return len;
         }
 
         if (allowBinaryAsString) {
             len = tryReadBinaryHeader(b);
             if (len >= 0) {
-                resetHeadByte();
                 return len;
             }
         }
@@ -1301,21 +1200,18 @@ public int unpackRawStringHeader()
     public int unpackBinaryHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedRaw(b)) { // FixRaw
-            resetHeadByte();
             return b & 0x1f;
         }
         int len = tryReadBinaryHeader(b);
         if (len >= 0) {
-            resetHeadByte();
             return len;
         }
 
         if (allowStringAsBinary) {
             len = tryReadStringHeader(b);
             if (len >= 0) {
-                resetHeadByte();
                 return len;
             }
         }

From 79c998044f986c1067d6aa1bde42fc74e5fea303 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:21:52 +0900
Subject: [PATCH 42/99] Test various lengths of String

---
 ...essagePackDataformatPojoBenchmarkTest.java | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index de2118508..84dfde2fc 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -32,8 +32,9 @@
 
 public class MessagePackDataformatPojoBenchmarkTest
 {
-    private static final int LOOP_MAX = 600;
-    private static final int LOOP_FACTOR = 40;
+    private static final int LOOP_MAX = 200;
+    private static final int LOOP_FACTOR_SER = 40;
+    private static final int LOOP_FACTOR_DESER = 200;
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
     private static final List pojos = new ArrayList(LOOP_MAX);
@@ -52,7 +53,11 @@ public class MessagePackDataformatPojoBenchmarkTest
             pojo.l = i;
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
-            pojo.setS(String.valueOf(i));
+            StringBuilder sb = new StringBuilder();
+            for (int sbi = 0; sbi < i * 40; sbi++) {
+                sb.append("x");
+            }
+            pojo.setS(sb.toString());
             pojo.bool = i % 2 == 0;
             pojo.bi = BigInteger.valueOf(i);
             switch (i % 4) {
@@ -117,7 +122,7 @@ public void testBenchmark()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_SER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         origObjectMapper.writeValue(outputStreamJackson, pojos.get(i));
                     }
@@ -130,7 +135,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_SER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i));
                     }
@@ -143,7 +148,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_DESER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         origObjectMapper.readValue(pojosSerWithOrig.get(i), NormalPojo.class);
                     }
@@ -156,7 +161,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_DESER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         msgpackObjectMapper.readValue(pojosSerWithMsgPack.get(i), NormalPojo.class);
                     }

From c6054b8c5497ae09573522a5f3e54e01e23f3293 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:35:23 +0900
Subject: [PATCH 43/99] Minor refactoring

---
 ...essagePackDataformatPojoBenchmarkTest.java | 25 ++++++++-----------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index 84dfde2fc..179b09891 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -37,15 +37,16 @@ public class MessagePackDataformatPojoBenchmarkTest
     private static final int LOOP_FACTOR_DESER = 200;
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
-    private static final List pojos = new ArrayList(LOOP_MAX);
-    private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
-    private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
+    private final List pojos = new ArrayList(LOOP_MAX);
+    private final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
+    private final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
     private final ObjectMapper origObjectMapper = new ObjectMapper();
     private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
 
-    static {
-        final ObjectMapper origObjectMapper = new ObjectMapper();
-        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    public MessagePackDataformatPojoBenchmarkTest()
+    {
+        origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
+        msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
 
         for (int i = 0; i < LOOP_MAX; i++) {
             NormalPojo pojo = new NormalPojo();
@@ -54,7 +55,7 @@ public class MessagePackDataformatPojoBenchmarkTest
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
             StringBuilder sb = new StringBuilder();
-            for (int sbi = 0; sbi < i * 40; sbi++) {
+            for (int sbi = 0; sbi < i * 50; sbi++) {
                 sb.append("x");
             }
             pojo.setS(sb.toString());
@@ -83,7 +84,7 @@ public class MessagePackDataformatPojoBenchmarkTest
                 pojosSerWithOrig.add(origObjectMapper.writeValueAsBytes(pojos.get(i)));
             }
             catch (JsonProcessingException e) {
-                e.printStackTrace();
+                throw new RuntimeException("Failed to create test data");
             }
         }
 
@@ -92,17 +93,11 @@ public class MessagePackDataformatPojoBenchmarkTest
                 pojosSerWithMsgPack.add(msgpackObjectMapper.writeValueAsBytes(pojos.get(i)));
             }
             catch (JsonProcessingException e) {
-                e.printStackTrace();
+                throw new RuntimeException("Failed to create test data");
             }
         }
     }
 
-    public MessagePackDataformatPojoBenchmarkTest()
-    {
-        origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
-        msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
-    }
-
     @Test
     public void testBenchmark()
             throws Exception

From 10d132a2d5d94c5f7e99b18b607dd2a97e31ec5d Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Mon, 21 Dec 2015 21:00:22 +0900
Subject: [PATCH 44/99] optimized unpacker buffer

---
 .../MessageInsufficientBufferException.java   |  40 +
 .../core/MessageNeverUsedFormatException.java |  38 +
 .../org/msgpack/core/MessageUnpacker.java     | 808 ++++++++++--------
 .../msgpack/core/buffer/ArrayBufferInput.java |   5 +
 .../msgpack/core/buffer/ByteBufferInput.java  |   5 +
 .../core/buffer/ChannelBufferInput.java       |   5 +
 .../core/buffer/InputStreamBufferInput.java   |   5 +
 .../msgpack/core/buffer/MessageBuffer.java    |   5 +
 .../core/buffer/MessageBufferInput.java       |   7 +-
 .../core/buffer/MessageBufferReader.java      | 122 +++
 .../org/msgpack/core/MessagePackTest.scala    |   2 +-
 .../msgpack/core/MessageUnpackerTest.scala    |   2 +
 .../msgpack/core/buffer/ByteStringTest.scala  |   2 +
 13 files changed, 689 insertions(+), 357 deletions(-)
 create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java
 create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java
 create mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java b/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java
new file mode 100644
index 000000000..838dc77ab
--- /dev/null
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageInsufficientBufferException.java
@@ -0,0 +1,40 @@
+//
+// MessagePack for Java
+//
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+//
+package org.msgpack.core;
+
+public class MessageInsufficientBufferException
+        extends MessagePackException
+{
+    public MessageInsufficientBufferException()
+    {
+        super();
+    }
+
+    public MessageInsufficientBufferException(String message)
+    {
+        super(message);
+    }
+
+    public MessageInsufficientBufferException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public MessageInsufficientBufferException(String message, Throwable cause)
+    {
+        super(message, cause);
+    }
+}
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java b/msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java
new file mode 100644
index 000000000..726ffb497
--- /dev/null
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageNeverUsedFormatException.java
@@ -0,0 +1,38 @@
+//
+// MessagePack for Java
+//
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+//
+package org.msgpack.core;
+
+/**
+ * Thrown when the input message pack format is invalid
+ */
+public class MessageNeverUsedFormatException
+        extends MessageFormatException
+{
+    public MessageNeverUsedFormatException(Throwable e)
+    {
+        super(e);
+    }
+
+    public MessageNeverUsedFormatException(String message)
+    {
+        super(message);
+    }
+
+    public MessageNeverUsedFormatException(String message, Throwable cause)
+    {
+        super(message, cause);
+    }
+}
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index c50d183ee..05babb1ce 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -17,6 +17,7 @@
 
 import org.msgpack.core.MessagePack.Code;
 import org.msgpack.core.buffer.MessageBuffer;
+import org.msgpack.core.buffer.MessageBufferReader;
 import org.msgpack.core.buffer.MessageBufferInput;
 import org.msgpack.value.ImmutableValue;
 import org.msgpack.value.Value;
@@ -74,10 +75,14 @@ public class MessageUnpacker
 {
     private static final MessageBuffer EMPTY_BUFFER = MessageBuffer.wrap(new byte[0]);
 
+    private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1;
+
     private final MessagePack.Config config;
 
     private MessageBufferInput in;
 
+    private byte headByte = HEAD_BYTE_REQUIRED;
+
     /**
      * Points to the current buffer to read
      */
@@ -94,19 +99,24 @@ public class MessageUnpacker
     private long totalReadBytes;
 
     /**
-     * For preserving the next buffer to use
+     * Extra buffer for fixed-length data at the buffer boundary. At most 17-byte buffer (for FIXEXT16) is required.
      */
-    private MessageBuffer secondaryBuffer = null;
+    private final MessageBuffer castBuffer = MessageBuffer.newBuffer(24);
 
     /**
-     * Extra buffer for string data at the buffer boundary. Using 17-byte buffer (for FIXEXT16) is sufficient.
+     * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer.
      */
-    private final MessageBuffer extraBuffer = MessageBuffer.wrap(new byte[24]);
+    private int readCastBufferPosition;
 
     /**
-     * True if no more data is available from the MessageBufferInput
+     * For decoding String in unpackString.
+     */
+    private StringBuilder decodeStringBuffer;
+
+    /**
+     * For decoding String in unpackString.
      */
-    private boolean reachedEOF = false;
+    private int readingRawRemaining = 0;
 
     /**
      * For decoding String in unpackString.
@@ -158,9 +168,9 @@ public MessageBufferInput reset(MessageBufferInput in)
         this.buffer = EMPTY_BUFFER;
         this.position = 0;
         this.totalReadBytes = 0;
-        this.secondaryBuffer = null;
-        this.reachedEOF = false;
+        this.readingRawRemaining = 0;
         // No need to initialize the already allocated string decoder here since we can reuse it.
+
         return old;
     }
 
@@ -169,195 +179,118 @@ public long getTotalReadBytes()
         return totalReadBytes + position;
     }
 
-    private void prepareDecoder()
+    private byte getHeadByte()
+            throws IOException
     {
-        if (decoder == null) {
-            decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize);
-            decoder = MessagePack.UTF8.newDecoder()
-                    .onMalformedInput(config.actionOnMalFormedInput)
-                    .onUnmappableCharacter(config.actionOnUnmappableCharacter);
+        byte b = headByte;
+        if (b == HEAD_BYTE_REQUIRED) {
+            b = headByte = readByte();
+            if (b == HEAD_BYTE_REQUIRED) {
+                throw new MessageNeverUsedFormatException("Encountered 0xC1 NEVER_USED byte");
+            }
         }
+        return b;
     }
 
-    /**
-     * Relocate the cursor position so that it points to the real buffer
-     *
-     * @return true if it succeeds to move the cursor, or false if there is no more buffer to read
-     * @throws IOException when failed to retrieve next buffer
-     */
-    private boolean ensureBuffer()
-            throws IOException
+    private void resetHeadByte()
     {
-        while (buffer != null && position >= buffer.size()) {
-            // Fetch the next buffer
-            int bufferSize = buffer.size();
-            position -= bufferSize;
-            totalReadBytes += bufferSize;
-            buffer = takeNextBuffer();
-        }
-        return buffer != null;
+        headByte = HEAD_BYTE_REQUIRED;
     }
 
-    private MessageBuffer takeNextBuffer()
+    private void nextBuffer()
             throws IOException
     {
-        if (reachedEOF) {
-            return null;
-        }
-
-        MessageBuffer nextBuffer = null;
-        if (secondaryBuffer == null) {
-            nextBuffer = in.next();
-        }
-        else {
-            nextBuffer = secondaryBuffer;
-            secondaryBuffer = null;
-        }
-
-        if (nextBuffer == null) {
-            reachedEOF = true;
+        MessageBuffer next = in.next();
+        if (next == null) {
+            throw new MessageInsufficientBufferException();
         }
-        return nextBuffer;
+        totalReadBytes += buffer.size();
+        in.release(buffer);
+        buffer = next;
+        position = 0;
     }
 
-    /**
-     * Ensure that the buffer has the data of at least the specified size.
-     *
-     * @param byteSizeToRead the data size to be read
-     * @return if the buffer can have the data of the specified size returns true, or if the input source reached an EOF, it returns false.
-     * @throws IOException
-     */
-    private boolean ensure(int byteSizeToRead)
+    private MessageBuffer readCastBuffer(int length)
             throws IOException
     {
-        if (byteSizeToRead == 0) {
-            return true;
-        }
-
-        if (!ensureBuffer()) {
-            return false;
-        }
-
-        // The buffer contains the data
-        if (position + byteSizeToRead <= buffer.size()) {
-            // OK
-            return true;
+        int remaining = buffer.size() - position;
+        if (remaining >= length) {
+            readCastBufferPosition = position;
+            position += length;  // here assumes following buffer.getXxx never throws exception
+            return buffer;
         }
+        else {
+            // TODO loop this method until castBuffer is filled
+            MessageBuffer next = in.next();
+            if (next == null) {
+                throw new MessageInsufficientBufferException();
+            }
 
-        // When the data is at the boundary
-        /*
-             |---(byte size to read) ----|
-             -- current buffer --|
-             |--- extra buffer (slice) --|----|
-                                 |-------|---------- secondary buffer (slice) ----------------|
-
-             */
-
-        // If the byte size to read fits within the extra buffer, use the extraBuffer
-        MessageBuffer newBuffer = byteSizeToRead <= extraBuffer.size() ? extraBuffer : MessageBuffer.newBuffer(byteSizeToRead);
-
-        // Copy the remaining buffer contents to the new buffer
-        int firstHalfSize = buffer.size() - position;
-        if (firstHalfSize > 0) {
-            buffer.copyTo(position, newBuffer, 0, firstHalfSize);
-        }
+            // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
+            //      add copy method to MessageBuffer to solve this issue.
+            castBuffer.putBytes(0, buffer.getArray(), buffer.offset() + position, remaining);
+            castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining);
 
-        // Read the last half contents from the next buffers
-        int cursor = firstHalfSize;
-        while (cursor < byteSizeToRead) {
-            secondaryBuffer = takeNextBuffer();
-            if (secondaryBuffer == null) {
-                return false; // No more buffer to read
-            }
+            totalReadBytes += buffer.size();
+            in.release(buffer);
 
-            // Copy the contents from the secondary buffer to the new buffer
-            int copyLen = Math.min(byteSizeToRead - cursor, secondaryBuffer.size());
-            secondaryBuffer.copyTo(0, newBuffer, cursor, copyLen);
+            buffer = next;
+            position = length - remaining;
+            readCastBufferPosition = 0;
 
-            // Truncate the copied part from the secondaryBuffer
-            secondaryBuffer = copyLen == secondaryBuffer.size() ? null : secondaryBuffer.slice(copyLen, secondaryBuffer.size() - copyLen);
-            cursor += copyLen;
+            return castBuffer;
         }
+    }
 
-        // Replace the current buffer with the new buffer
-        totalReadBytes += position;
-        buffer = byteSizeToRead == newBuffer.size() ? newBuffer : newBuffer.slice(0, byteSizeToRead);
-        position = 0;
-
-        return true;
+    private static int utf8MultibyteCharacterSize(byte firstByte)
+    {
+        System.out.println("first byte: "+(firstByte & 0xff));
+        return Integer.numberOfLeadingZeros(~(firstByte & 0xff));
     }
 
     /**
      * Returns true true if this unpacker has more elements.
      * When this returns true, subsequent call to {@link #getNextFormat()} returns an
-     * MessageFormat instance. If false, {@link #getNextFormat()} will throw an EOFException.
+     * MessageFormat instance. If false, next {@link #getNextFormat()} call will throw an MessageInsufficientBufferException.
      *
      * @return true if this unpacker has more elements to read
      */
     public boolean hasNext()
             throws IOException
     {
-        return ensure(1);
+        if (buffer.size() <= position) {
+            MessageBuffer next = in.next();
+            if (next == null) {
+                return false;
+            }
+            totalReadBytes += buffer.size();
+            in.release(buffer);
+            buffer = next;
+            position = 0;
+        }
+        return true;
     }
 
     /**
      * Returns the next MessageFormat type. This method should be called after {@link #hasNext()} returns true.
-     * If {@link #hasNext()} returns false, calling this method throws {@link java.io.EOFException}.
+     * If {@link #hasNext()} returns false, calling this method throws {@link MessageInsufficientBufferException}.
      * 

* This method does not proceed the internal cursor. * * @return the next MessageFormat * @throws IOException when failed to read the input data. - * @throws EOFException when the end of file reached, i.e. {@link #hasNext()} == false. + * @throws MessageInsufficientBufferException when the end of file reached, i.e. {@link #hasNext()} == false. */ public MessageFormat getNextFormat() throws IOException { - byte b = lookAhead(); - return MessageFormat.valueOf(b); - } - - /** - * Look-ahead a byte value at the current cursor position. - * This method does not proceed the cursor. - * - * @return - * @throws IOException - */ - private byte lookAhead() - throws IOException - { - if (ensure(1)) { - return buffer.getByte(position); - } - else { - throw new EOFException(); + try { + byte b = getHeadByte(); + return MessageFormat.valueOf(b); } - } - - /** - * Get the head byte value and proceeds the cursor by 1 - */ - private byte consume() - throws IOException - { - byte b = lookAhead(); - position += 1; - return b; - } - - /** - * Proceeds the cursor by the specified byte length - */ - private void consume(int numBytes) - throws IOException - { - assert (numBytes >= 0); - // If position + numBytes becomes negative, it indicates an overflow from Integer.MAX_VALUE. - if (position + numBytes < 0) { - ensureBuffer(); + catch (MessageNeverUsedFormatException ex) { + return MessageFormat.NEVER_USED; } - position += numBytes; } /** @@ -369,81 +302,55 @@ private void consume(int numBytes) private byte readByte() throws IOException { - if (!ensure(1)) { - throw new EOFException("insufficient data length for reading byte value"); + if (buffer.size() > position) { + byte b = buffer.getByte(position); + position++; + return b; + } + else { + nextBuffer(); + if (buffer.size() > 0) { + byte b = buffer.getByte(0); + position = 1; + return b; + } + return readByte(); } - byte b = buffer.getByte(position); - consume(1); - return b; } private short readShort() throws IOException { - if (!ensure(2)) { - throw new EOFException("insufficient data length for reading short value"); - } - short s = buffer.getShort(position); - consume(2); - return s; + MessageBuffer castBuffer = readCastBuffer(2); + return castBuffer.getShort(readCastBufferPosition); } private int readInt() throws IOException { - if (!ensure(4)) { - throw new EOFException("insufficient data length for reading int value"); - } - int i = buffer.getInt(position); - consume(4); - return i; - } - - private float readFloat() - throws IOException - { - if (!ensure(4)) { - throw new EOFException("insufficient data length for reading float value"); - } - float f = buffer.getFloat(position); - consume(4); - return f; + MessageBuffer castBuffer = readCastBuffer(4); + return castBuffer.getInt(readCastBufferPosition); } private long readLong() throws IOException { - if (!ensure(8)) { - throw new EOFException("insufficient data length for reading long value"); - } - long l = buffer.getLong(position); - consume(8); - return l; + MessageBuffer castBuffer = readCastBuffer(8); + return castBuffer.getLong(readCastBufferPosition); } - private double readDouble() + private float readFloat() throws IOException { - if (!ensure(8)) { - throw new EOFException("insufficient data length for reading double value"); - } - double d = buffer.getDouble(position); - consume(8); - return d; + MessageBuffer castBuffer = readCastBuffer(4); + return castBuffer.getFloat(readCastBufferPosition); } - /** - * Skip reading the specified number of bytes. Use this method only if you know skipping data is safe. - * For simply skipping the next value, use {@link #skipValue()}. - * - * @param numBytes - * @throws IOException - */ - public void skipBytes(int numBytes) + private double readDouble() throws IOException { - checkArgument(numBytes >= 0, "skip length must be >= 0: " + numBytes); - consume(numBytes); + MessageBuffer castBuffer = readCastBuffer(8); + return castBuffer.getDouble(readCastBufferPosition); } /** @@ -456,12 +363,9 @@ public void skipValue() { int remainingValues = 1; while (remainingValues > 0) { - if (reachedEOF) { - throw new EOFException(); - } - - MessageFormat f = getNextFormat(); - byte b = consume(); + byte b = getHeadByte(); + MessageFormat f = MessageFormat.valueOf(b); + resetHeadByte(); switch (f) { case POSFIXINT: case NEGFIXINT: @@ -480,62 +384,62 @@ public void skipValue() } case FIXSTR: { int strLen = b & 0x1f; - consume(strLen); + skipPayload(strLen); break; } case INT8: case UINT8: - consume(1); + skipPayload(1); break; case INT16: case UINT16: - consume(2); + skipPayload(2); break; case INT32: case UINT32: case FLOAT32: - consume(4); + skipPayload(4); break; case INT64: case UINT64: case FLOAT64: - consume(8); + skipPayload(8); break; case BIN8: case STR8: - consume(readNextLength8()); + skipPayload(readNextLength8()); break; case BIN16: case STR16: - consume(readNextLength16()); + skipPayload(readNextLength16()); break; case BIN32: case STR32: - consume(readNextLength32()); + skipPayload(readNextLength32()); break; case FIXEXT1: - consume(2); + skipPayload(2); break; case FIXEXT2: - consume(3); + skipPayload(3); break; case FIXEXT4: - consume(5); + skipPayload(5); break; case FIXEXT8: - consume(9); + skipPayload(9); break; case FIXEXT16: - consume(17); + skipPayload(17); break; case EXT8: - consume(readNextLength8() + 1); + skipPayload(readNextLength8() + 1); break; case EXT16: - consume(readNextLength16() + 1); + skipPayload(readNextLength16() + 1); break; case EXT32: - consume(readNextLength32() + 1); + skipPayload(readNextLength32() + 1); break; case ARRAY16: remainingValues += readNextLength16(); @@ -709,8 +613,9 @@ public Variable unpackValue(Variable var) public void unpackNil() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (b == Code.NIL) { + resetHeadByte(); return; } throw unexpected("Nil", b); @@ -719,66 +624,76 @@ public void unpackNil() public boolean unpackBoolean() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (b == Code.FALSE) { + resetHeadByte(); return false; } else if (b == Code.TRUE) { + resetHeadByte(); return true; } - throw unexpected("boolean", b); } public byte unpackByte() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); if (u8 < (byte) 0) { throw overflowU8(u8); } return u8; case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); if (u16 < 0 || u16 > Byte.MAX_VALUE) { throw overflowU16(u16); } return (byte) u16; case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0 || u32 > Byte.MAX_VALUE) { throw overflowU32(u32); } return (byte) u32; case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L || u64 > Byte.MAX_VALUE) { throw overflowU64(u64); } return (byte) u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) { throw overflowI16(i16); } return (byte) i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) { throw overflowI32(i32); } return (byte) i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) { throw overflowI64(i64); } @@ -790,27 +705,32 @@ public byte unpackByte() public short unpackShort() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return (short) b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return (short) (u8 & 0xff); case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); if (u16 < (short) 0) { throw overflowU16(u16); } return u16; case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0 || u32 > Short.MAX_VALUE) { throw overflowU32(u32); } return (short) u32; case Code.UINT64: // unsigned int 64 + resetHeadByte(); long u64 = readLong(); if (u64 < 0L || u64 > Short.MAX_VALUE) { throw overflowU64(u64); @@ -818,18 +738,22 @@ public short unpackShort() return (short) u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return (short) i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) { throw overflowI32(i32); } return (short) i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) { throw overflowI64(i64); } @@ -841,40 +765,49 @@ public short unpackShort() public int unpackInt() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return (int) b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return u8 & 0xff; case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); return u16 & 0xffff; case Code.UINT32: // unsigned int 32 int u32 = readInt(); if (u32 < 0) { throw overflowU32(u32); } + resetHeadByte(); return u32; case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) { throw overflowU64(u64); } return (int) u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); return i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) { throw overflowI64(i64); } @@ -886,19 +819,23 @@ public int unpackInt() public long unpackLong() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return (long) b; } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return (long) (u8 & 0xff); case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); return (long) (u16 & 0xffff); case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0) { return (long) (u32 & 0x7fffffff) + 0x80000000L; } @@ -907,21 +844,26 @@ public long unpackLong() } case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L) { throw overflowU64(u64); } return u64; case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return (long) i8; case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return (long) i16; case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); return (long) i32; case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); return i64; } throw unexpected("Integer", b); @@ -930,19 +872,23 @@ public long unpackLong() public BigInteger unpackBigInteger() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixInt(b)) { + resetHeadByte(); return BigInteger.valueOf((long) b); } switch (b) { case Code.UINT8: // unsigned int 8 byte u8 = readByte(); + resetHeadByte(); return BigInteger.valueOf((long) (u8 & 0xff)); case Code.UINT16: // unsigned int 16 short u16 = readShort(); + resetHeadByte(); return BigInteger.valueOf((long) (u16 & 0xffff)); case Code.UINT32: // unsigned int 32 int u32 = readInt(); + resetHeadByte(); if (u32 < 0) { return BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L); } @@ -951,6 +897,7 @@ public BigInteger unpackBigInteger() } case Code.UINT64: // unsigned int 64 long u64 = readLong(); + resetHeadByte(); if (u64 < 0L) { BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63); return bi; @@ -960,15 +907,19 @@ public BigInteger unpackBigInteger() } case Code.INT8: // signed int 8 byte i8 = readByte(); + resetHeadByte(); return BigInteger.valueOf((long) i8); case Code.INT16: // signed int 16 short i16 = readShort(); + resetHeadByte(); return BigInteger.valueOf((long) i16); case Code.INT32: // signed int 32 int i32 = readInt(); + resetHeadByte(); return BigInteger.valueOf((long) i32); case Code.INT64: // signed int 64 long i64 = readLong(); + resetHeadByte(); return BigInteger.valueOf(i64); } throw unexpected("Integer", b); @@ -977,13 +928,15 @@ public BigInteger unpackBigInteger() public float unpackFloat() throws IOException { - byte b = consume(); + byte b = getHeadByte(); switch (b) { case Code.FLOAT32: // float float fv = readFloat(); + resetHeadByte(); return fv; case Code.FLOAT64: // double double dv = readDouble(); + resetHeadByte(); return (float) dv; } throw unexpected("Float", b); @@ -992,13 +945,15 @@ public float unpackFloat() public double unpackDouble() throws IOException { - byte b = consume(); + byte b = getHeadByte(); switch (b) { case Code.FLOAT32: // float float fv = readFloat(); + resetHeadByte(); return (double) fv; case Code.FLOAT64: // double double dv = readDouble(); + resetHeadByte(); return dv; } throw unexpected("Float", b); @@ -1006,107 +961,191 @@ public double unpackDouble() private static final String EMPTY_STRING = ""; + private void resetDecoder() + { + if (decoder == null) { + decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize); + decoder = MessagePack.UTF8.newDecoder() + .onMalformedInput(config.actionOnMalFormedInput) + .onUnmappableCharacter(config.actionOnUnmappableCharacter); + } + else { + decoder.reset(); + } + decodeStringBuffer = new StringBuilder(); + } + + /** + * This method is not repeatable. + */ public String unpackString() throws IOException { - int strLen = unpackRawStringHeader(); - if (strLen > 0) { - if (strLen > config.maxUnpackStringSize) { - throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, strLen), strLen); + if (readingRawRemaining == 0) { + int len = unpackRawStringHeader(); + if (len == 0) { + return EMPTY_STRING; + } + if (len > config.maxUnpackStringSize) { + throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, len), len); } + if (buffer.size() - position >= len) { + return decodeStringFastPath(len); + } + readingRawRemaining = len; + resetDecoder(); + } - prepareDecoder(); - assert (decoder != null); + assert (decoder != null); - decoder.reset(); + try { + while (readingRawRemaining > 0) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= readingRawRemaining) { + ByteBuffer bb = buffer.toByteBuffer(position, readingRawRemaining); + int bbStartPosition = bb.position(); + decodeBuffer.clear(); - try { - int cursor = 0; - decodeBuffer.clear(); - StringBuilder sb = new StringBuilder(); - - boolean hasIncompleteMultiBytes = false; - while (cursor < strLen) { - int readLen = Math.min(position < buffer.size() ? buffer.size() - position : buffer.size(), strLen - cursor); - if (hasIncompleteMultiBytes) { - // Prepare enough buffer for decoding multi-bytes character right after running into incomplete one - readLen = Math.min(config.stringDecoderBufferSize, strLen - cursor); + CoderResult cr = decoder.decode(bb, decodeBuffer, true); + int readLen = bb.position() - bbStartPosition; + position += readLen; + readingRawRemaining -= readLen; + decodeStringBuffer.append(decodeBuffer.flip()); + + if (cr.isError()) { + handleCoderError(cr); } - if (!ensure(readLen)) { - throw new EOFException(); + if (cr.isUnderflow() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) { + throw new MalformedInputException(cr.length()); } - hasIncompleteMultiBytes = false; - ByteBuffer bb = buffer.toByteBuffer(position, readLen); - int startPos = bb.position(); - - while (bb.hasRemaining()) { - boolean endOfInput = (cursor + readLen) >= strLen; - CoderResult cr = decoder.decode(bb, decodeBuffer, endOfInput); - - if (endOfInput && cr.isUnderflow()) { - cr = decoder.flush(decodeBuffer); - } - - if (cr.isOverflow()) { - // The output CharBuffer has insufficient space - decoder.reset(); - } - - if (cr.isUnderflow() && bb.hasRemaining()) { - // input buffer doesn't have enough bytes for multi bytes characters - if (config.actionOnMalFormedInput == CodingErrorAction.REPORT) { - throw new MalformedInputException(strLen); + if (cr.isOverflow()) { + // go to next loop + } + else { + break; + } + } + else if (bufferRemaining == 0) { + nextBuffer(); + } + else { + ByteBuffer bb = buffer.toByteBuffer(position, bufferRemaining); + int bbStartPosition = bb.position(); + decodeBuffer.clear(); + + CoderResult cr = decoder.decode(bb, decodeBuffer, false); + int readLen = bb.position() - bbStartPosition; + position += readLen; + readingRawRemaining -= readLen; + decodeStringBuffer.append(decodeBuffer.flip()); + + if (cr.isError()) { + handleCoderError(cr); + } + if (cr.isUnderflow() && readLen < bufferRemaining) { + // handle incomplete multibyte character + int incompleteMultiBytes = utf8MultibyteCharacterSize(buffer.getByte(position)); + ByteBuffer multiByteBuffer = ByteBuffer.allocate(incompleteMultiBytes); + buffer.getBytes(position, buffer.size() - position, multiByteBuffer); + + // read until multiByteBuffer is filled + while (true) { + nextBuffer(); + + int more = multiByteBuffer.remaining(); + if (buffer.size() >= more) { + buffer.getBytes(0, more, multiByteBuffer); + position = more; + break; + } + else { + buffer.getBytes(0, buffer.size(), multiByteBuffer); + position = buffer.size(); } - hasIncompleteMultiBytes = true; - // Proceed the cursor with the length already decoded successfully. - readLen = bb.position() - startPos; } - + multiByteBuffer.position(0); + decodeBuffer.clear(); + cr = decoder.decode(multiByteBuffer, decodeBuffer, false); if (cr.isError()) { - if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || - (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { + handleCoderError(cr); + } + if (cr.isUnderflow() || cr.isOverflow()) { + // isOverflow or isOverflow must not happen. if happened, throw exception + try { cr.throwException(); + throw new MessageFormatException("Unexpected UTF-8 multibyte sequence"); + } + catch (Exception ex) { + throw new MessageFormatException("Unexpected UTF-8 multibyte sequence", ex); } } - - decodeBuffer.flip(); - sb.append(decodeBuffer); - - decodeBuffer.clear(); - - if (hasIncompleteMultiBytes) { - break; - } + readingRawRemaining -= multiByteBuffer.limit(); + decodeStringBuffer.append(decodeBuffer.flip()); } - - cursor += readLen; - consume(readLen); } + } + return decodeStringBuffer.toString(); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + } - return sb.toString(); + private void handleCoderError(CoderResult cr) + throws CharacterCodingException + { + if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || + (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { + cr.throwException(); + } + } + + private String decodeStringFastPath(int length) + { + if (config.actionOnMalFormedInput == CodingErrorAction.REPLACE && + config.actionOnUnmappableCharacter == CodingErrorAction.REPLACE && + buffer.hasArray()) { + String s = new String(buffer.getArray(), position, length, MessagePack.UTF8); + position += length; + return s; + } + else { + resetDecoder(); + ByteBuffer bb = buffer.toByteBuffer(); + bb.limit(position + length); + bb.position(position); + CharBuffer cb; + try { + cb = decoder.decode(bb); } catch (CharacterCodingException e) { throw new MessageStringCodingException(e); } - } - else { - return EMPTY_STRING; + position += length; + return cb.toString(); } } public int unpackArrayHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedArray(b)) { // fixarray + resetHeadByte(); return b & 0x0f; } switch (b) { - case Code.ARRAY16: // array 16 - return readNextLength16(); - case Code.ARRAY32: // array 32 - return readNextLength32(); + case Code.ARRAY16: { // array 16 + int len = readNextLength16(); + resetHeadByte(); + return len; + } + case Code.ARRAY32: { // array 32 + int len = readNextLength32(); + resetHeadByte(); + return len; + } } throw unexpected("Array", b); } @@ -1114,15 +1153,22 @@ public int unpackArrayHeader() public int unpackMapHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedMap(b)) { // fixmap + resetHeadByte(); return b & 0x0f; } switch (b) { - case Code.MAP16: // map 16 - return readNextLength16(); - case Code.MAP32: // map 32 - return readNextLength32(); + case Code.MAP16: { // map 16 + int len = readNextLength16(); + resetHeadByte(); + return len; + } + case Code.MAP32: { // map 32 + int len = readNextLength32(); + resetHeadByte(); + return len; + } } throw unexpected("Map", b); } @@ -1130,31 +1176,58 @@ public int unpackMapHeader() public ExtensionTypeHeader unpackExtensionTypeHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); switch (b) { - case Code.FIXEXT1: - return new ExtensionTypeHeader(readByte(), 1); - case Code.FIXEXT2: - return new ExtensionTypeHeader(readByte(), 2); - case Code.FIXEXT4: - return new ExtensionTypeHeader(readByte(), 4); - case Code.FIXEXT8: - return new ExtensionTypeHeader(readByte(), 8); - case Code.FIXEXT16: - return new ExtensionTypeHeader(readByte(), 16); - case Code.EXT8: { - int length = readNextLength8(); + case Code.FIXEXT1: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 1); + } + case Code.FIXEXT2: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 2); + } + case Code.FIXEXT4: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 4); + } + case Code.FIXEXT8: { byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 8); + } + case Code.FIXEXT16: { + byte type = readByte(); + resetHeadByte(); + return new ExtensionTypeHeader(type, 16); + } + case Code.EXT8: { + MessageBuffer castBuffer = readCastBuffer(2); + resetHeadByte(); + int u8 = castBuffer.getByte(readCastBufferPosition); + int length = u8 & 0xff; + byte type = castBuffer.getByte(readCastBufferPosition + 1); return new ExtensionTypeHeader(type, length); } case Code.EXT16: { - int length = readNextLength16(); - byte type = readByte(); + MessageBuffer castBuffer = readCastBuffer(3); + resetHeadByte(); + int u16 = castBuffer.getShort(readCastBufferPosition); + int length = u16 & 0xffff; + byte type = castBuffer.getByte(readCastBufferPosition + 2); return new ExtensionTypeHeader(type, length); } case Code.EXT32: { - int length = readNextLength32(); - byte type = readByte(); + MessageBuffer castBuffer = readCastBuffer(5); + resetHeadByte(); + int u32 = castBuffer.getInt(readCastBufferPosition); + if (u32 < 0) { + throw overflowU32Size(u32); + } + int length = u32; + byte type = castBuffer.getByte(readCastBufferPosition + 4); return new ExtensionTypeHeader(type, length); } } @@ -1162,7 +1235,7 @@ public ExtensionTypeHeader unpackExtensionTypeHeader() throw unexpected("Ext", b); } - private int readStringHeader(byte b) + private int tryReadStringHeader(byte b) throws IOException { switch (b) { @@ -1177,7 +1250,7 @@ private int readStringHeader(byte b) } } - private int readBinaryHeader(byte b) + private int tryReadBinaryHeader(byte b) throws IOException { switch (b) { @@ -1195,18 +1268,21 @@ private int readBinaryHeader(byte b) public int unpackRawStringHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedRaw(b)) { // FixRaw + resetHeadByte(); return b & 0x1f; } - int len = readStringHeader(b); + int len = tryReadStringHeader(b); if (len >= 0) { + resetHeadByte(); return len; } if (config.readBinaryAsString) { - len = readBinaryHeader(b); + len = tryReadBinaryHeader(b); if (len >= 0) { + resetHeadByte(); return len; } } @@ -1216,36 +1292,65 @@ public int unpackRawStringHeader() public int unpackBinaryHeader() throws IOException { - byte b = consume(); + byte b = getHeadByte(); if (Code.isFixedRaw(b)) { // FixRaw + resetHeadByte(); return b & 0x1f; } - int len = readBinaryHeader(b); + int len = tryReadBinaryHeader(b); if (len >= 0) { + resetHeadByte(); return len; } if (config.readStringAsBinary) { - len = readStringHeader(b); + len = tryReadStringHeader(b); if (len >= 0) { + resetHeadByte(); return len; } } throw unexpected("Binary", b); } - // TODO returns a buffer reference to the payload (zero-copy) + /** + * Skip reading the specified number of bytes. Use this method only if you know skipping data is safe. + * For simply skipping the next value, use {@link #skipValue()}. + * + * @param numBytes + * @throws IOException + */ + private void skipPayload(int numBytes) + throws IOException + { + while (true) { + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= numBytes) { + position += numBytes; + return; + } + else { + position += bufferRemaining; + } + nextBuffer(); + } + } public void readPayload(ByteBuffer dst) throws IOException { - while (dst.remaining() > 0) { - if (!ensureBuffer()) { - throw new EOFException(); + while (true) { + int dstRemaining = dst.remaining(); + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= dstRemaining) { + buffer.getBytes(position, dstRemaining, dst); + position += dstRemaining; + return; } - int l = Math.min(buffer.size() - position, dst.remaining()); - buffer.getBytes(position, l, dst); - consume(l); + buffer.getBytes(position, bufferRemaining, dst); + position += bufferRemaining; + + nextBuffer(); } } @@ -1274,29 +1379,22 @@ public byte[] readPayload(int length) public void readPayload(byte[] dst, int off, int len) throws IOException { - int writtenLen = 0; - while (writtenLen < len) { - if (!ensureBuffer()) { - throw new EOFException(); - } - int l = Math.min(buffer.size() - position, len - writtenLen); - buffer.getBytes(position, dst, off + writtenLen, l); - consume(l); - writtenLen += l; - } + // TODO optimize + readPayload(ByteBuffer.wrap(dst, off, len)); } public MessageBuffer readPayloadAsReference(int length) throws IOException { - checkArgument(length >= 0); - if (!ensure(length)) { - throw new EOFException(); + int bufferRemaining = buffer.size() - position; + if (bufferRemaining >= length) { + MessageBuffer slice = buffer.slice(position, length); + position += length; + return slice; } - - MessageBuffer ref = buffer.slice(position, length); - position += length; - return ref; + MessageBuffer dst = MessageBuffer.newBuffer(length); + readPayload(dst.getReference()); + return dst; } private int readNextLength8() diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 88fe45942..35f76c14c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -87,4 +87,9 @@ public void close() buffer = null; isRead = false; } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index b9b4304ad..1f60b3fec 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -66,4 +66,9 @@ public void close() { // Nothing to do } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index 4b8baeb75..6dd262599 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -85,4 +85,9 @@ public void close() { channel.close(); } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java index 81aabd762..b0d42e4a0 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java @@ -93,4 +93,9 @@ public void close() { in.close(); } + + // TODO + public void release(MessageBuffer buffer) + { + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 4dd1396f1..46a777af0 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -328,6 +328,11 @@ else if (bb.hasArray()) { this.reference = reference; } + public MessageBufferReader newReader() + { + return new MessageBufferReader(this); + } + /** * byte size of the buffer * diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index 786ce2721..2a92160b2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -27,9 +27,14 @@ public interface MessageBufferInput /** * Get a next buffer to read. * - * @return the next MessageBuffer, or null if no more buffer is available. + * @return the next MessageBuffer, or return null if no more buffer is available. * @throws IOException when error occurred when reading the data */ public MessageBuffer next() throws IOException; + + /** + * Release an unused buffer formerly returned by next() method. + */ + public void release(MessageBuffer buffer); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java new file mode 100644 index 000000000..f9656d22d --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java @@ -0,0 +1,122 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core.buffer; + +public class MessageBufferReader +{ + // TODO add more reader methods for each type + + private MessageBuffer buffer; + private int position; + + MessageBufferReader(MessageBuffer buffer) + { + this.buffer = buffer; + } + + public MessageBuffer buffer() + { + return buffer; + } + + public int position() + { + return position; + } + + public void position(int newPosition) + { + // TODO validation? + this.position = newPosition; + } + + public int remaining() + { + return buffer.size() - position; + } + + public byte getByte() + { + return buffer.getByte(position); + } + + public byte readByte() + { + byte v = buffer.getByte(position); + position += 1; + return v; + } + + public short getShort() + { + return buffer.getShort(position); + } + + public short readShort() + { + short v = buffer.getShort(position); + position += 1; + return v; + } + + public int getInt() + { + return buffer.getInt(position); + } + + public int readInt() + { + int v = buffer.getInt(position); + position += 1; + return v; + } + + public long getLong() + { + return buffer.getLong(position); + } + + public long readLong() + { + long v = buffer.getLong(position); + position += 1; + return v; + } + + public float getFloat() + { + return buffer.getFloat(position); + } + + public float readFloat() + { + float v = buffer.getFloat(position); + position += 1; + return v; + } + + public double getDouble() + { + return buffer.getDouble(position); + } + + public double readDouble() + { + double v = buffer.getDouble(position); + position += 1; + return v; + } +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 62bf8ae82..f903cf88d 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -469,4 +469,4 @@ class MessagePackTest extends MessagePackSpec { } } -} \ No newline at end of file +} diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index fc03d5680..9ecf70a21 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -261,6 +261,8 @@ class MessageUnpackerTest extends MessagePackSpec { } } + override def release(buffer: MessageBuffer): Unit = {} + override def close(): Unit = {} } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 362038d95..39526a0ce 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -39,6 +39,8 @@ class ByteStringTest messageBuffer } + override def release(buffer: MessageBuffer): Unit = {} + override def close(): Unit = {} } From ccac8a76f5ba0007644554068f5815a4f6e31390 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 22 Dec 2015 10:39:03 +0900 Subject: [PATCH 45/99] fixed MessageUnpacker.utf8MultibyteCharacterSize --- .../org/msgpack/core/MessageUnpacker.java | 29 +++-- .../msgpack/core/buffer/MessageBuffer.java | 7 +- .../core/buffer/MessageBufferReader.java | 122 ------------------ 3 files changed, 20 insertions(+), 138 deletions(-) delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 05babb1ce..b22c98dfb 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -17,7 +17,6 @@ import org.msgpack.core.MessagePack.Code; import org.msgpack.core.buffer.MessageBuffer; -import org.msgpack.core.buffer.MessageBufferReader; import org.msgpack.core.buffer.MessageBufferInput; import org.msgpack.value.ImmutableValue; import org.msgpack.value.Value; @@ -186,7 +185,7 @@ private byte getHeadByte() if (b == HEAD_BYTE_REQUIRED) { b = headByte = readByte(); if (b == HEAD_BYTE_REQUIRED) { - throw new MessageNeverUsedFormatException("Encountered 0xC1 NEVER_USED byte"); + throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte"); } } return b; @@ -205,7 +204,9 @@ private void nextBuffer() throw new MessageInsufficientBufferException(); } totalReadBytes += buffer.size(); - in.release(buffer); + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + } buffer = next; position = 0; } @@ -232,7 +233,9 @@ private MessageBuffer readCastBuffer(int length) castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining); totalReadBytes += buffer.size(); - in.release(buffer); + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + } buffer = next; position = length - remaining; @@ -244,8 +247,7 @@ private MessageBuffer readCastBuffer(int length) private static int utf8MultibyteCharacterSize(byte firstByte) { - System.out.println("first byte: "+(firstByte & 0xff)); - return Integer.numberOfLeadingZeros(~(firstByte & 0xff)); + return Integer.numberOfLeadingZeros(~(firstByte & 0xff) << 24); } /** @@ -264,7 +266,9 @@ public boolean hasNext() return false; } totalReadBytes += buffer.size(); - in.release(buffer); + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + } buffer = next; position = 0; } @@ -490,7 +494,7 @@ public ImmutableValue unpackValue() MessageFormat mf = getNextFormat(); switch (mf.getValueType()) { case NIL: - unpackNil(); + readByte(); return ValueFactory.newNil(); case BOOLEAN: return ValueFactory.newBoolean(unpackBoolean()); @@ -1070,7 +1074,7 @@ else if (bufferRemaining == 0) { if (cr.isError()) { handleCoderError(cr); } - if (cr.isUnderflow() || cr.isOverflow()) { + if (cr.isOverflow() || (cr.isUnderflow() && multiByteBuffer.position() < multiByteBuffer.limit())) { // isOverflow or isOverflow must not happen. if happened, throw exception try { cr.throwException(); @@ -1106,7 +1110,7 @@ private String decodeStringFastPath(int length) if (config.actionOnMalFormedInput == CodingErrorAction.REPLACE && config.actionOnUnmappableCharacter == CodingErrorAction.REPLACE && buffer.hasArray()) { - String s = new String(buffer.getArray(), position, length, MessagePack.UTF8); + String s = new String(buffer.getArray(), buffer.offset() + position, length, MessagePack.UTF8); position += length; return s; } @@ -1425,6 +1429,11 @@ private int readNextLength32() public void close() throws IOException { + if (buffer != EMPTY_BUFFER) { + in.release(buffer); + buffer = EMPTY_BUFFER; + position = 0; + } in.close(); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 46a777af0..302105f83 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -328,11 +328,6 @@ else if (bb.hasArray()) { this.reference = reference; } - public MessageBufferReader newReader() - { - return new MessageBufferReader(this); - } - /** * byte size of the buffer * @@ -408,7 +403,7 @@ public void getBytes(int index, byte[] dst, int dstOffset, int length) public void getBytes(int index, int len, ByteBuffer dst) { - if (dst.remaining() > len) { + if (dst.remaining() < len) { throw new BufferOverflowException(); } ByteBuffer src = toByteBuffer(index, len); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java deleted file mode 100644 index f9656d22d..000000000 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferReader.java +++ /dev/null @@ -1,122 +0,0 @@ -// -// MessagePack for Java -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -package org.msgpack.core.buffer; - -public class MessageBufferReader -{ - // TODO add more reader methods for each type - - private MessageBuffer buffer; - private int position; - - MessageBufferReader(MessageBuffer buffer) - { - this.buffer = buffer; - } - - public MessageBuffer buffer() - { - return buffer; - } - - public int position() - { - return position; - } - - public void position(int newPosition) - { - // TODO validation? - this.position = newPosition; - } - - public int remaining() - { - return buffer.size() - position; - } - - public byte getByte() - { - return buffer.getByte(position); - } - - public byte readByte() - { - byte v = buffer.getByte(position); - position += 1; - return v; - } - - public short getShort() - { - return buffer.getShort(position); - } - - public short readShort() - { - short v = buffer.getShort(position); - position += 1; - return v; - } - - public int getInt() - { - return buffer.getInt(position); - } - - public int readInt() - { - int v = buffer.getInt(position); - position += 1; - return v; - } - - public long getLong() - { - return buffer.getLong(position); - } - - public long readLong() - { - long v = buffer.getLong(position); - position += 1; - return v; - } - - public float getFloat() - { - return buffer.getFloat(position); - } - - public float readFloat() - { - float v = buffer.getFloat(position); - position += 1; - return v; - } - - public double getDouble() - { - return buffer.getDouble(position); - } - - public double readDouble() - { - double v = buffer.getDouble(position); - position += 1; - return v; - } -} From c1986f54df7e5224318745ba4f85a0aaaa0ec433 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 22 Dec 2015 18:18:42 +0900 Subject: [PATCH 46/99] Remove release method from MessageBufferInput --- .../org/msgpack/core/MessageUnpacker.java | 16 ++-------------- .../msgpack/core/buffer/ArrayBufferInput.java | 4 ---- .../msgpack/core/buffer/ByteBufferInput.java | 4 ---- .../core/buffer/ChannelBufferInput.java | 19 ++++--------------- .../core/buffer/InputStreamBufferInput.java | 17 ++--------------- .../core/buffer/MessageBufferInput.java | 6 ++---- .../msgpack/core/MessageUnpackerTest.scala | 2 -- .../msgpack/core/buffer/ByteStringTest.scala | 3 --- 8 files changed, 10 insertions(+), 61 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index b22c98dfb..70a050990 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -204,9 +204,6 @@ private void nextBuffer() throw new MessageInsufficientBufferException(); } totalReadBytes += buffer.size(); - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - } buffer = next; position = 0; } @@ -233,9 +230,6 @@ private MessageBuffer readCastBuffer(int length) castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining); totalReadBytes += buffer.size(); - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - } buffer = next; position = length - remaining; @@ -266,9 +260,6 @@ public boolean hasNext() return false; } totalReadBytes += buffer.size(); - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - } buffer = next; position = 0; } @@ -1429,11 +1420,8 @@ private int readNextLength32() public void close() throws IOException { - if (buffer != EMPTY_BUFFER) { - in.release(buffer); - buffer = EMPTY_BUFFER; - position = 0; - } + buffer = EMPTY_BUFFER; + position = 0; in.close(); } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 35f76c14c..a777b8a73 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -88,8 +88,4 @@ public void close() isRead = false; } - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java index 1f60b3fec..034d8882b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java @@ -67,8 +67,4 @@ public void close() // Nothing to do } - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index 6dd262599..73dcb5db6 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -29,8 +29,7 @@ public class ChannelBufferInput implements MessageBufferInput { private ReadableByteChannel channel; - private boolean reachedEOF = false; - private final int bufferSize; + private final MessageBuffer m; public ChannelBufferInput(ReadableByteChannel channel) { @@ -41,7 +40,7 @@ public ChannelBufferInput(ReadableByteChannel channel, int bufferSize) { this.channel = checkNotNull(channel, "input channel is null"); checkArgument(bufferSize > 0, "buffer size must be > 0: " + bufferSize); - this.bufferSize = bufferSize; + this.m = MessageBuffer.newBuffer(bufferSize); } /** @@ -55,7 +54,6 @@ public ReadableByteChannel reset(ReadableByteChannel channel) { ReadableByteChannel old = this.channel; this.channel = channel; - this.reachedEOF = false; return old; } @@ -63,16 +61,11 @@ public ReadableByteChannel reset(ReadableByteChannel channel) public MessageBuffer next() throws IOException { - if (reachedEOF) { - return null; - } - - MessageBuffer m = MessageBuffer.newBuffer(bufferSize); ByteBuffer b = m.toByteBuffer(); - while (!reachedEOF && b.remaining() > 0) { + while (b.remaining() > 0) { int ret = channel.read(b); if (ret == -1) { - reachedEOF = true; + break; } } b.flip(); @@ -86,8 +79,4 @@ public void close() channel.close(); } - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java index b0d42e4a0..ad8aa462f 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java @@ -29,8 +29,7 @@ public class InputStreamBufferInput implements MessageBufferInput { private InputStream in; - private final int bufferSize; - private boolean reachedEOF = false; + private final byte[] buffer; public static MessageBufferInput newBufferInput(InputStream in) { @@ -52,7 +51,7 @@ public InputStreamBufferInput(InputStream in) public InputStreamBufferInput(InputStream in, int bufferSize) { this.in = checkNotNull(in, "input is null"); - this.bufferSize = bufferSize; + this.buffer = new byte[bufferSize]; } /** @@ -66,7 +65,6 @@ public InputStream reset(InputStream in) { InputStream old = this.in; this.in = in; - reachedEOF = false; return old; } @@ -74,14 +72,8 @@ public InputStream reset(InputStream in) public MessageBuffer next() throws IOException { - if (reachedEOF) { - return null; - } - - byte[] buffer = new byte[bufferSize]; int readLen = in.read(buffer); if (readLen == -1) { - reachedEOF = true; return null; } return MessageBuffer.wrap(buffer).slice(0, readLen); @@ -93,9 +85,4 @@ public void close() { in.close(); } - - // TODO - public void release(MessageBuffer buffer) - { - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index 2a92160b2..5925557cf 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -27,14 +27,12 @@ public interface MessageBufferInput /** * Get a next buffer to read. * + * When this method is called twice, the formally allocated buffer can be safely discarded. + * * @return the next MessageBuffer, or return null if no more buffer is available. * @throws IOException when error occurred when reading the data */ public MessageBuffer next() throws IOException; - /** - * Release an unused buffer formerly returned by next() method. - */ - public void release(MessageBuffer buffer); } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 9ecf70a21..fc03d5680 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -261,8 +261,6 @@ class MessageUnpackerTest extends MessagePackSpec { } } - override def release(buffer: MessageBuffer): Unit = {} - override def close(): Unit = {} } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index 39526a0ce..92103dc31 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -38,9 +38,6 @@ class ByteStringTest isRead = true messageBuffer } - - override def release(buffer: MessageBuffer): Unit = {} - override def close(): Unit = {} } From 6a4e190c0387b302e756c0052059188f2103191e Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Tue, 22 Dec 2015 18:24:43 +0900 Subject: [PATCH 47/99] fixed skipPayload --- msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 70a050990..38880d03d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -1326,6 +1326,7 @@ private void skipPayload(int numBytes) } else { position += bufferRemaining; + numBytes -= bufferRemaining; } nextBuffer(); } From 0a463e4489e75d787bbca29c7de5c7f8f8d50fa5 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Thu, 24 Dec 2015 09:44:27 +0900 Subject: [PATCH 48/99] simplified streaming string decoding code --- .../org/msgpack/core/MessageUnpacker.java | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 38880d03d..c6730a009 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -997,29 +997,9 @@ public String unpackString() while (readingRawRemaining > 0) { int bufferRemaining = buffer.size() - position; if (bufferRemaining >= readingRawRemaining) { - ByteBuffer bb = buffer.toByteBuffer(position, readingRawRemaining); - int bbStartPosition = bb.position(); - decodeBuffer.clear(); - - CoderResult cr = decoder.decode(bb, decodeBuffer, true); - int readLen = bb.position() - bbStartPosition; - position += readLen; - readingRawRemaining -= readLen; - decodeStringBuffer.append(decodeBuffer.flip()); - - if (cr.isError()) { - handleCoderError(cr); - } - if (cr.isUnderflow() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) { - throw new MalformedInputException(cr.length()); - } - - if (cr.isOverflow()) { - // go to next loop - } - else { - break; - } + decodeStringBuffer.append(decodeStringFastPath(readingRawRemaining)); + readingRawRemaining = 0; + break; } else if (bufferRemaining == 0) { nextBuffer(); From 634fdd8629045c4767a391c205bf233350aa76c1 Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Thu, 24 Dec 2015 10:00:21 +0900 Subject: [PATCH 49/99] 0xC1 NEVER_USED always throws MessageNeverUsedFormatException regardless of context rather than MessageTypeException or MessageFormatException depending on context --- .../java/org/msgpack/core/MessageUnpacker.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index c6730a009..bd6339418 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -449,7 +449,7 @@ public void skipValue() remainingValues += readNextLength32() * 2; // TODO check int overflow break; case NEVER_USED: - throw new MessageFormatException(String.format("unknown code: %02x is found", b)); + throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte"); } remainingValues--; @@ -464,19 +464,17 @@ public void skipValue() * @return * @throws MessageFormatException */ - private static MessageTypeException unexpected(String expected, byte b) - throws MessageTypeException + private static MessagePackException unexpected(String expected, byte b) { MessageFormat format = MessageFormat.valueOf(b); - String typeName; if (format == MessageFormat.NEVER_USED) { - typeName = "NeverUsed"; + return new MessageNeverUsedFormatException(String.format("Expected %s, but encountered 0xC1 \"NEVER_USED\" byte", expected)); } else { String name = format.getValueType().name(); - typeName = name.substring(0, 1) + name.substring(1).toLowerCase(); + String typeName = name.substring(0, 1) + name.substring(1).toLowerCase(); + return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); } - return new MessageTypeException(String.format("Expected %s, but got %s (%02x)", expected, typeName, b)); } public ImmutableValue unpackValue() @@ -530,7 +528,7 @@ public ImmutableValue unpackValue() return ValueFactory.newExtension(extHeader.getType(), readPayload(extHeader.getLength())); } default: - throw new MessageFormatException("Unknown value type"); + throw new MessageNeverUsedFormatException("Unknown value type"); } } From 23b0fd889ee6566ae5dc21a900b29ac065351aba Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 25 Dec 2015 10:19:18 +0900 Subject: [PATCH 50/99] minimum required castBuffer size is 8 bytes --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index bd6339418..9b8e159bc 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -98,9 +98,10 @@ public class MessageUnpacker private long totalReadBytes; /** - * Extra buffer for fixed-length data at the buffer boundary. At most 17-byte buffer (for FIXEXT16) is required. + * Extra buffer for fixed-length data at the buffer boundary. + * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required. */ - private final MessageBuffer castBuffer = MessageBuffer.newBuffer(24); + private final MessageBuffer castBuffer = MessageBuffer.newBuffer(8); /** * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer. From 97b0af40814f4d346a32f667405875d47f751e1a Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 25 Dec 2015 12:28:43 +0900 Subject: [PATCH 51/99] optimized packer buffer interface --- .../java/org/msgpack/core/MessagePacker.java | 325 ++++++++++-------- .../core/buffer/ChannelBufferOutput.java | 46 ++- .../msgpack/core/buffer/MessageBuffer.java | 5 + .../core/buffer/MessageBufferOutput.java | 48 ++- .../core/buffer/OutputStreamBufferOutput.java | 59 ++-- .../core/example/MessagePackExample.java | 5 - .../org/msgpack/core/MessagePackerTest.scala | 3 +- .../core/buffer/MessageBufferOutputTest.scala | 2 +- .../dataformat/MessagePackGenerator.java | 13 +- 9 files changed, 306 insertions(+), 200 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 032cda7f3..11f2fcb5d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -88,15 +88,15 @@ public class MessagePacker private final MessagePack.Config config; private MessageBufferOutput out; + private MessageBuffer buffer; - private MessageBuffer strLenBuffer; private int position; /** * Total written byte size */ - private long flushedBytes; + private long totalFlushBytes; /** * String encoder @@ -119,7 +119,7 @@ public MessagePacker(MessageBufferOutput out, MessagePack.Config config) this.config = checkNotNull(config, "config is null"); this.out = checkNotNull(out, "MessageBufferOutput is null"); this.position = 0; - this.flushedBytes = 0; + this.totalFlushBytes = 0; } /** @@ -134,50 +134,32 @@ public MessageBufferOutput reset(MessageBufferOutput out) // Validate the argument MessageBufferOutput newOut = checkNotNull(out, "MessageBufferOutput is null"); - // Reset the internal states + // Flush before reset + flush(); MessageBufferOutput old = this.out; this.out = newOut; - this.position = 0; - this.flushedBytes = 0; - return old; - } - public long getTotalWrittenBytes() - { - return flushedBytes + position; - } + // Reset totalFlushBytes + this.totalFlushBytes = 0; - private void prepareEncoder() - { - if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); - } + return old; } - private void prepareBuffer() - throws IOException + public long getTotalWrittenBytes() { - if (buffer == null) { - buffer = out.next(config.packerBufferSize); - } + return totalFlushBytes + position; } public void flush() throws IOException { - if (buffer == null) { - return; + if (position > 0) { + out.writeBuffer(position); + buffer = null; + totalFlushBytes += position; + position = 0; } - - if (position == buffer.size()) { - out.flush(buffer); - } - else { - out.flush(buffer.slice(0, position)); - } - buffer = null; - flushedBytes += position; - position = 0; + out.flush(); } public void close() @@ -191,12 +173,18 @@ public void close() } } - private void ensureCapacity(int numBytesToWrite) + private void ensureCapacity(int mimimumSize) throws IOException { - if (buffer == null || position + numBytesToWrite >= buffer.size()) { - flush(); - buffer = out.next(Math.max(config.packerBufferSize, numBytesToWrite)); + if (buffer == null) { + buffer = out.next(mimimumSize); + } + else if (position + mimimumSize >= buffer.size()) { + out.writeBuffer(position); + buffer = null; + totalFlushBytes += position; + position = 0; + buffer = out.next(mimimumSize); } } @@ -442,14 +430,44 @@ public MessagePacker packDouble(double v) return this; } - private void packSmallString(String s) + private void packStringByGetBytes(String s) throws IOException { byte[] bytes = s.getBytes(MessagePack.UTF8); packRawStringHeader(bytes.length); - writePayload(bytes); + addPayload(bytes); } + private void prepareEncoder() + { + if (encoder == null) { + this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); + } + } + + private int encodeStringToBufferAt(int pos, String s) + { + prepareEncoder(); + ByteBuffer bb = buffer.toByteBuffer(pos, buffer.size() - pos); + int startPosition = bb.position(); + CharBuffer in = CharBuffer.wrap(s); + CoderResult cr = encoder.encode(in, bb, true); + if (cr.isError()) { + try { + cr.throwException(); + } + catch (CharacterCodingException e) { + throw new MessageStringCodingException(e); + } + } + if (cr.isUnderflow() || cr.isOverflow()) { + return -1; + } + return bb.position() - startPosition; + } + + private static final int UTF_8_MAX_CHAR_SIZE = 6; + /** * Pack the input String in UTF-8 encoding * @@ -464,77 +482,76 @@ public MessagePacker packString(String s) packRawStringHeader(0); return this; } - - if (s.length() < config.packerSmallStringOptimizationThreshold) { + else if (s.length() < config.packerSmallStringOptimizationThreshold) { // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer - packSmallString(s); + packStringByGetBytes(s); return this; } - - CharBuffer in = CharBuffer.wrap(s); - prepareEncoder(); - - flush(); - - prepareBuffer(); - boolean isExtension = false; - ByteBuffer encodeBuffer = buffer.toByteBuffer(position, buffer.size() - position); - encoder.reset(); - while (in.hasRemaining()) { - try { - CoderResult cr = encoder.encode(in, encodeBuffer, true); - - // Input data is insufficient - if (cr.isUnderflow()) { - cr = encoder.flush(encodeBuffer); + else if (s.length() < (1 << 8)) { + // ensure capacity for 2-byte raw string header + the maximum string size (+ 1 byte for falback code) + ensureCapacity(2 + s.length() * UTF_8_MAX_CHAR_SIZE + 1); + // keep 2-byte header region and write raw string + int written = encodeStringToBufferAt(position + 2, s); + if (written >= 0) { + if (written < (1 << 8)) { + buffer.putByte(position++, STR8); + buffer.putByte(position++, (byte) written); + position += written; } - - // encodeBuffer is too small - if (cr.isOverflow()) { - // Allocate a larger buffer - int estimatedRemainingSize = Math.max(1, (int) (in.remaining() * encoder.averageBytesPerChar())); - encodeBuffer.flip(); - ByteBuffer newBuffer = ByteBuffer.allocate(Math.max((int) (encodeBuffer.capacity() * 1.5), encodeBuffer.remaining() + estimatedRemainingSize)); - // Coy the current encodeBuffer contents to the new buffer - newBuffer.put(encodeBuffer); - encodeBuffer = newBuffer; - isExtension = true; - encoder.reset(); - continue; - } - - if (cr.isError()) { - if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) || - (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) { - cr.throwException(); + else { + if (written >= (1 << 16)) { + // this must not happen because s.length() is less than 2^8 and (2^8) * UTF_8_MAX_CHAR_SIZE is less than 2^16 + throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); } + // move 1 byte backward to expand 3-byte header region to 3 bytes + buffer.putBytes(position + 3, + buffer.getArray(), buffer.offset() + position + 2, written); + // write 3-byte header header + buffer.putByte(position++, STR16); + buffer.putShort(position, (short) written); + position += 2; + position += written; } + return this; } - catch (CharacterCodingException e) { - throw new MessageStringCodingException(e); + } + else if (s.length() < (1 << 16)) { + // ensure capacity for 3-byte raw string header + the maximum string size (+ 2 bytes for falback code) + ensureCapacity(3 + s.length() * UTF_8_MAX_CHAR_SIZE + 2); + // keep 3-byte header region and write raw string + int written = encodeStringToBufferAt(position + 3, s); + if (written >= 0) { + if (written < (1 << 16)) { + buffer.putByte(position++, STR16); + buffer.putShort(position, (short) written); + position += 2; + position += written; + } + else { + if (written >= (1 << 32)) { + // this must not happen because s.length() is less than 2^16 and (2^16) * UTF_8_MAX_CHAR_SIZE is less than 2^32 + throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); + } + // move 2 bytes backward to expand 3-byte header region to 5 bytes + buffer.putBytes(position + 5, + buffer.getArray(), buffer.offset() + position + 3, written); + // write 3-byte header header + buffer.putByte(position++, STR32); + buffer.putInt(position, written); + position += 4; + position += written; + } + return this; } } - encodeBuffer.flip(); - int strLen = encodeBuffer.remaining(); - - // Preserve the current buffer - MessageBuffer tmpBuf = buffer; - - // Switch the buffer to write the string length - if (strLenBuffer == null) { - strLenBuffer = MessageBuffer.newBuffer(5); - } - buffer = strLenBuffer; - position = 0; - // pack raw string header (string binary size) - packRawStringHeader(strLen); - flush(); // We need to dump the data here to MessageBufferOutput so that we can switch back to the original buffer + // Here doesn't use above optimized code for s.length() < (1 << 32) so that + // ensureCapacity is not called with an integer larger than (3 + ((1 << 16) * UTF_8_MAX_CHAR_SIZE) + 2). + // This makes it sure that MessageBufferOutput.next won't be called a size larger than + // 384KB, which is OK size to keep in memory. - // Reset to the original buffer (or encodeBuffer if new buffer is allocated) - buffer = isExtension ? MessageBuffer.wrap(encodeBuffer) : tmpBuf; - // No need exists to write payload since the encoded string (payload) is already written to the buffer - position = strLen; + // fallback + packStringByGetBytes(s); return this; } @@ -659,72 +676,82 @@ else if (len < (1 << 16)) { return this; } - public MessagePacker writePayload(ByteBuffer src) + /** + * Writes buffer to the output. + * This method is used with packRawStringHeader or packBinaryHeader. + * + * @param src the data to add + * @return this + * @throws IOException + */ + public MessagePacker writePayload(byte[] src) throws IOException { - int len = src.remaining(); - if (len >= config.packerRawDataCopyingThreshold) { - // Use the source ByteBuffer directly to avoid memory copy - - // First, flush the current buffer contents - flush(); + return writePayload(src, 0, src.length); + } - // Wrap the input source as a MessageBuffer - MessageBuffer wrapped = MessageBuffer.wrap(src); - // Then, dump the source data to the output - out.flush(wrapped); - src.position(src.limit()); - flushedBytes += len; + /** + * Writes buffer to the output. + * This method is used with packRawStringHeader or packBinaryHeader. + * + * @param src the data to add + * @param off the start offset in the data + * @param len the number of bytes to add + * @return this + * @throws IOException + */ + public MessagePacker writePayload(byte[] src, int off, int len) + throws IOException + { + if (buffer.size() - position < len || len > 8192) { + flush(); // call flush before write + out.write(src, off, len); + totalFlushBytes += len; } else { - // If the input source is small, simply copy the contents to the buffer - while (src.remaining() > 0) { - if (position >= buffer.size()) { - flush(); - } - prepareBuffer(); - int writeLen = Math.min(buffer.size() - position, src.remaining()); - buffer.putByteBuffer(position, src, writeLen); - position += writeLen; - } + buffer.putBytes(position, src, off, len); + position += len; } - return this; } - public MessagePacker writePayload(byte[] src) + /** + * Writes buffer to the output. + * Unlike writePayload method, addPayload method doesn't copy the source data. It means that the caller + * must not modify the data after calling this method. + * + * @param src the data to add + * @return this + * @throws IOException + */ + public MessagePacker addPayload(byte[] src) throws IOException { - return writePayload(src, 0, src.length); + return addPayload(src, 0, src.length); } - public MessagePacker writePayload(byte[] src, int off, int len) + /** + * Writes buffer to the output. + * Unlike writePayload method, addPayload method doesn't copy the source data. It means that the caller + * must not modify the data after calling this method. + * + * @param src the data to add + * @param off the start offset in the data + * @param len the number of bytes to add + * @return this + * @throws IOException + */ + public MessagePacker addPayload(byte[] src, int off, int len) throws IOException { - if (len >= config.packerRawDataCopyingThreshold) { - // Use the input array directory to avoid memory copy - - // Flush the current buffer contents - flush(); - - // Wrap the input array as a MessageBuffer - MessageBuffer wrapped = MessageBuffer.wrap(src).slice(off, len); - // Dump the source data to the output - out.flush(wrapped); - flushedBytes += len; + if (buffer.size() - position < len || len > 8192) { + flush(); // call flush before add + out.add(src, off, len); + totalFlushBytes += len; } else { - int cursor = 0; - while (cursor < len) { - if (buffer != null && position >= buffer.size()) { - flush(); - } - prepareBuffer(); - int writeLen = Math.min(buffer.size() - position, len - cursor); - buffer.putBytes(position, src, off + cursor, writeLen); - position += writeLen; - cursor += writeLen; - } + buffer.putBytes(position, src, off, len); + position += len; } return this; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java index 9ecddf3ac..b981cc95d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java @@ -31,15 +31,21 @@ public class ChannelBufferOutput private MessageBuffer buffer; public ChannelBufferOutput(WritableByteChannel channel) + { + this(channel, 8192); + } + + public ChannelBufferOutput(WritableByteChannel channel, int bufferSize) { this.channel = checkNotNull(channel, "output channel is null"); + this.buffer = MessageBuffer.newBuffer(bufferSize); } /** - * Reset channel. This method doesn't close the old resource. + * Reset channel. This method doesn't close the old channel. * * @param channel new channel - * @return the old resource + * @return the old channel */ public WritableByteChannel reset(WritableByteChannel channel) throws IOException @@ -50,21 +56,40 @@ public WritableByteChannel reset(WritableByteChannel channel) } @Override - public MessageBuffer next(int bufferSize) + public MessageBuffer next(int mimimumSize) throws IOException { - if (buffer == null || buffer.size() != bufferSize) { - buffer = MessageBuffer.newBuffer(bufferSize); + if (buffer.size() < mimimumSize) { + buffer = MessageBuffer.newBuffer(mimimumSize); } return buffer; } @Override - public void flush(MessageBuffer buf) + public void writeBuffer(int length) + throws IOException + { + ByteBuffer bb = buffer.toByteBuffer(0, length); + while (bb.hasRemaining()) { + channel.write(bb); + } + } + + @Override + public void write(byte[] buffer, int offset, int length) throws IOException { - ByteBuffer bb = buf.toByteBuffer(); - channel.write(bb); + ByteBuffer bb = ByteBuffer.wrap(buffer, offset, length); + while (bb.hasRemaining()) { + channel.write(bb); + } + } + + @Override + public void add(byte[] buffer, int offset, int length) + throws IOException + { + write(buffer, offset, length); } @Override @@ -73,4 +98,9 @@ public void close() { channel.close(); } + + @Override + public void flush() + throws IOException + { } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java index 302105f83..fce8020ce 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java @@ -210,6 +210,11 @@ public static MessageBuffer wrap(byte[] array) return newMessageBuffer(array); } + public static MessageBuffer wrap(byte[] array, int offset, int length) + { + return newMessageBuffer(array).slice(offset, length); + } + public static MessageBuffer wrap(ByteBuffer bb) { return newMessageBuffer(bb).slice(bb.position(), bb.remaining()); diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 77fe12454..92eb760a9 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -17,30 +17,60 @@ import java.io.Closeable; import java.io.IOException; +import java.io.Flushable; /** - * Provides a sequence of MessageBuffers for packing the input data + * Provides a buffered output stream for packing objects */ public interface MessageBufferOutput - extends Closeable + extends Closeable, Flushable { /** - * Retrieves the next buffer for writing message packed data + * Allocates the next buffer for writing message packed data. + * If the previously allocated buffer is not flushed yet, this next method should discard + * it without writing it. * - * @param bufferSize the buffer size to retrieve + * @param mimimumSize the mimium required buffer size to allocate * @return * @throws IOException */ - public MessageBuffer next(int bufferSize) + public MessageBuffer next(int mimimumSize) throws IOException; /** - * Output the buffer contents. If you need to output a part of the - * buffer use {@link MessageBuffer#slice(int, int)} + * Flushes the previously allocated buffer. + * This method is not always called because next method also flushes previously allocated buffer. + * This method is called when write method is called or application wants to control the timing of flush. * - * @param buf + * @param length the size of buffer to flush * @throws IOException */ - public void flush(MessageBuffer buf) + public void writeBuffer(int length) + throws IOException; + + /** + * Writes an external payload data. + * This method should follow semantics of OutputStream. + * + * @param buffer the data to write + * @param offset the start offset in the data + * @param length the number of bytes to write + * @return + * @throws IOException + */ + public void write(byte[] buffer, int offset, int length) + throws IOException; + + /** + * Writes an external payload data. + * This buffer is given - this MessageBufferOutput owns the buffer and may modify contents of the buffer. Contents of this buffer won't be modified by the caller. + * + * @param buffer the data to add + * @param offset the start offset in the data + * @param length the number of bytes to add + * @return + * @throws IOException + */ + public void add(byte[] buffer, int offset, int length) throws IOException; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java index 07d423bf0..d6f17c783 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java @@ -28,18 +28,23 @@ public class OutputStreamBufferOutput { private OutputStream out; private MessageBuffer buffer; - private byte[] tmpBuf; public OutputStreamBufferOutput(OutputStream out) + { + this(out, 8192); + } + + public OutputStreamBufferOutput(OutputStream out, int bufferSize) { this.out = checkNotNull(out, "output is null"); + this.buffer = MessageBuffer.newBuffer(bufferSize); } /** - * Reset Stream. This method doesn't close the old resource. + * Reset Stream. This method doesn't close the old stream. * * @param out new stream - * @return the old resource + * @return the old stream */ public OutputStream reset(OutputStream out) throws IOException @@ -50,41 +55,47 @@ public OutputStream reset(OutputStream out) } @Override - public MessageBuffer next(int bufferSize) + public MessageBuffer next(int mimimumSize) throws IOException { - if (buffer == null || buffer.size != bufferSize) { - buffer = MessageBuffer.newBuffer(bufferSize); + if (buffer.size() < mimimumSize) { + buffer = MessageBuffer.newBuffer(mimimumSize); } return buffer; } @Override - public void flush(MessageBuffer buf) + public void writeBuffer(int length) throws IOException { - int writeLen = buf.size(); - if (buf.hasArray()) { - out.write(buf.getArray(), buf.offset(), writeLen); - } - else { - if (tmpBuf == null || tmpBuf.length < writeLen) { - tmpBuf = new byte[writeLen]; - } - buf.getBytes(0, tmpBuf, 0, writeLen); - out.write(tmpBuf, 0, writeLen); - } + write(buffer.getArray(), buffer.offset(), length); + } + + @Override + public void write(byte[] buffer, int offset, int length) + throws IOException + { + out.write(buffer, offset, length); + } + + @Override + public void add(byte[] buffer, int offset, int length) + throws IOException + { + write(buffer, offset, length); } @Override public void close() throws IOException { - try { - out.flush(); - } - finally { - out.close(); - } + out.close(); + } + + @Override + public void flush() + throws IOException + { + out.flush(); } } diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index a74c5cd18..7636742e0 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -153,11 +153,6 @@ public static void packer() .packArrayHeader(2) .packString("xxx-xxxx") .packString("yyy-yyyy"); - - // [Advanced] write data using ByteBuffer - ByteBuffer bb = ByteBuffer.wrap(new byte[] {'b', 'i', 'n', 'a', 'r', 'y', 'd', 'a', 't', 'a'}); - packer.packBinaryHeader(bb.remaining()); - packer.writePayload(bb); } /** diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 20f4f560b..967cf07a1 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -283,12 +283,11 @@ class MessagePackerTest "support read-only buffer" taggedAs ("read-only") in { val payload = Array[Byte](1) - val buffer = ByteBuffer.wrap(payload).asReadOnlyBuffer() val out = new ByteArrayOutputStream() val packer = MessagePack.newDefaultPacker(out) .packBinaryHeader(1) - .writePayload(buffer) + .writePayload(payload) .close() } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala index 8616d1c69..1869f2aad 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferOutputTest.scala @@ -44,7 +44,7 @@ class MessageBufferOutputTest def writeIntToBuf(buf: MessageBufferOutput) = { val mb0 = buf.next(8) mb0.putInt(0, 42) - buf.flush(mb0) + buf.writeBuffer(4) buf.close } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index 189197209..c040ee7dd 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -183,8 +183,17 @@ else if (v instanceof Integer) { } else if (v instanceof ByteBuffer) { ByteBuffer bb = (ByteBuffer) v; - messagePacker.packBinaryHeader(bb.limit()); - messagePacker.writePayload(bb); + int len = bb.remaining(); + if (bb.hasArray()) { + messagePacker.packBinaryHeader(len); + messagePacker.writePayload(bb.array(), bb.arrayOffset(), len); + } + else { + byte[] data = new byte[len]; + bb.get(data); + messagePacker.packBinaryHeader(len); + messagePacker.addPayload(data); + } } else if (v instanceof String) { messagePacker.packString((String) v); From 5c26c6fe3394214fe86c51757f7d6f2eee8da0cc Mon Sep 17 00:00:00 2001 From: Sadayuki Furuhashi Date: Fri, 25 Dec 2015 15:28:15 +0900 Subject: [PATCH 52/99] reorganized MessagePacker interface to use MessagePacker --- .../org/msgpack/core/MessageBufferPacker.java | 73 ++++ .../java/org/msgpack/core/MessageFormat.java | 89 ++++- .../java/org/msgpack/core/MessagePack.java | 374 ++---------------- .../org/msgpack/core/MessagePackFactory.java | 203 ++++++++++ .../java/org/msgpack/core/MessagePacker.java | 88 ++--- .../org/msgpack/core/MessageUnpacker.java | 78 ++-- .../core/buffer/ArrayBufferOutput.java | 136 +++++++ .../core/example/MessagePackExample.java | 15 +- .../org/msgpack/core/MessageFormatTest.scala | 2 +- .../org/msgpack/core/MessagePackTest.scala | 24 +- .../org/msgpack/core/MessagePackerTest.scala | 19 +- .../msgpack/core/MessageUnpackerTest.scala | 46 +-- .../core/buffer/MessageBufferInputTest.scala | 6 +- .../org/msgpack/value/ValueTypeTest.scala | 2 +- 14 files changed, 686 insertions(+), 469 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java create mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java new file mode 100644 index 000000000..02b94f773 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -0,0 +1,73 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core; + +import org.msgpack.core.buffer.MessageBuffer; +import org.msgpack.core.buffer.MessageBufferOutput; +import org.msgpack.core.buffer.ArrayBufferOutput; + +import java.io.IOException; +import java.util.List; + +public class MessageBufferPacker + extends MessagePacker +{ + public MessageBufferPacker() + { + this(new ArrayBufferOutput()); + } + + public MessageBufferPacker(ArrayBufferOutput out) + { + super(out); + } + + @Override + public MessageBufferPacker setSmallStringOptimizationThreshold(int bytes) + { + super.setSmallStringOptimizationThreshold(bytes); + return this; + } + + public MessageBufferOutput reset(MessageBufferOutput out) + throws IOException + { + if (!(out instanceof ArrayBufferOutput)) { + throw new IllegalArgumentException("MessageBufferPacker accepts only ArrayBufferOutput"); + } + return super.reset(out); + } + + public void clear() + { + ((ArrayBufferOutput) out).clear(); + } + + public byte[] toByteArray() + { + return ((ArrayBufferOutput) out).toByteArray(); + } + + public MessageBuffer toMessageBuffer() + { + return ((ArrayBufferOutput) out).toMessageBuffer(); + } + + public List toBufferList() + { + return ((ArrayBufferOutput) out).toBufferList(); + } +} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java index 8e44b0aae..17a0f1555 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java @@ -15,7 +15,6 @@ // package org.msgpack.core; -import org.msgpack.core.MessagePack.Code; import org.msgpack.core.annotations.VisibleForTesting; import org.msgpack.value.ValueType; @@ -66,6 +65,94 @@ public enum MessageFormat MAP32(ValueType.MAP), NEGFIXINT(ValueType.INTEGER); + /** + * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. + */ + public static final class Code + { + public static final boolean isFixInt(byte b) + { + int v = b & 0xFF; + return v <= 0x7f || v >= 0xe0; + } + + public static final boolean isPosFixInt(byte b) + { + return (b & POSFIXINT_MASK) == 0; + } + + public static final boolean isNegFixInt(byte b) + { + return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; + } + + public static final boolean isFixStr(byte b) + { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final boolean isFixedArray(byte b) + { + return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; + } + + public static final boolean isFixedMap(byte b) + { + return (b & (byte) 0xe0) == Code.FIXMAP_PREFIX; + } + + public static final boolean isFixedRaw(byte b) + { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final byte POSFIXINT_MASK = (byte) 0x80; + + public static final byte FIXMAP_PREFIX = (byte) 0x80; + public static final byte FIXARRAY_PREFIX = (byte) 0x90; + public static final byte FIXSTR_PREFIX = (byte) 0xa0; + + public static final byte NIL = (byte) 0xc0; + public static final byte NEVER_USED = (byte) 0xc1; + public static final byte FALSE = (byte) 0xc2; + public static final byte TRUE = (byte) 0xc3; + public static final byte BIN8 = (byte) 0xc4; + public static final byte BIN16 = (byte) 0xc5; + public static final byte BIN32 = (byte) 0xc6; + public static final byte EXT8 = (byte) 0xc7; + public static final byte EXT16 = (byte) 0xc8; + public static final byte EXT32 = (byte) 0xc9; + public static final byte FLOAT32 = (byte) 0xca; + public static final byte FLOAT64 = (byte) 0xcb; + public static final byte UINT8 = (byte) 0xcc; + public static final byte UINT16 = (byte) 0xcd; + public static final byte UINT32 = (byte) 0xce; + public static final byte UINT64 = (byte) 0xcf; + + public static final byte INT8 = (byte) 0xd0; + public static final byte INT16 = (byte) 0xd1; + public static final byte INT32 = (byte) 0xd2; + public static final byte INT64 = (byte) 0xd3; + + public static final byte FIXEXT1 = (byte) 0xd4; + public static final byte FIXEXT2 = (byte) 0xd5; + public static final byte FIXEXT4 = (byte) 0xd6; + public static final byte FIXEXT8 = (byte) 0xd7; + public static final byte FIXEXT16 = (byte) 0xd8; + + public static final byte STR8 = (byte) 0xd9; + public static final byte STR16 = (byte) 0xda; + public static final byte STR32 = (byte) 0xdb; + + public static final byte ARRAY16 = (byte) 0xdc; + public static final byte ARRAY32 = (byte) 0xdd; + + public static final byte MAP16 = (byte) 0xde; + public static final byte MAP32 = (byte) 0xdf; + + public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; + } + private static final MessageFormat[] formatTable = new MessageFormat[256]; private final ValueType valueType; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 9847d461e..8af53a884 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -37,406 +37,102 @@ public class MessagePack { public static final Charset UTF8 = Charset.forName("UTF-8"); - /** - * Message packer/unpacker configuration object - */ - public static class Config - { - /** - * allow unpackBinaryHeader to read str format family (default:true) - */ - public final boolean readStringAsBinary; - /** - * allow unpackRawStringHeader and unpackString to read bin format family (default: true) - */ - public final boolean readBinaryAsString; - /** - * Action when encountered a malformed input - */ - public final CodingErrorAction actionOnMalFormedInput; - /** - * Action when an unmappable character is found - */ - public final CodingErrorAction actionOnUnmappableCharacter; - /** - * unpackString size limit. (default: Integer.MAX_VALUE) - */ - public final int maxUnpackStringSize; - public final int stringEncoderBufferSize; - public final int stringDecoderBufferSize; - public final int packerBufferSize; - public final int packerRawDataCopyingThreshold; - /** - * Use String.getBytes() for strings smaller than this threshold. - * Note that this parameter is subject to change. - */ - public final int packerSmallStringOptimizationThreshold; - - public Config( - boolean readStringAsBinary, - boolean readBinaryAsString, - CodingErrorAction actionOnMalFormedInput, - CodingErrorAction actionOnUnmappableCharacter, - int maxUnpackStringSize, - int stringEncoderBufferSize, - int stringDecoderBufferSize, - int packerBufferSize, - int packerSmallStringOptimizationThreshold, - int packerRawDataCopyingThreshold) - { - checkArgument(packerBufferSize > 0, "packer buffer size must be larger than 0: " + packerBufferSize); - checkArgument(stringEncoderBufferSize > 0, "string encoder buffer size must be larger than 0: " + stringEncoderBufferSize); - checkArgument(stringDecoderBufferSize > 0, "string decoder buffer size must be larger than 0: " + stringDecoderBufferSize); - - this.readStringAsBinary = readStringAsBinary; - this.readBinaryAsString = readBinaryAsString; - this.actionOnMalFormedInput = actionOnMalFormedInput; - this.actionOnUnmappableCharacter = actionOnUnmappableCharacter; - this.maxUnpackStringSize = maxUnpackStringSize; - this.stringEncoderBufferSize = stringEncoderBufferSize; - this.stringDecoderBufferSize = stringDecoderBufferSize; - this.packerBufferSize = packerBufferSize; - this.packerSmallStringOptimizationThreshold = packerSmallStringOptimizationThreshold; - this.packerRawDataCopyingThreshold = packerRawDataCopyingThreshold; - } - } - - /** - * Builder of the configuration object - */ - public static class ConfigBuilder - { - private boolean readStringAsBinary = true; - private boolean readBinaryAsString = true; - - private CodingErrorAction onMalFormedInput = CodingErrorAction.REPLACE; - private CodingErrorAction onUnmappableCharacter = CodingErrorAction.REPLACE; - - private int maxUnpackStringSize = Integer.MAX_VALUE; - private int stringEncoderBufferSize = 8192; - private int stringDecoderBufferSize = 8192; - private int packerBufferSize = 8192; - private int packerSmallStringOptimizationThreshold = 512; // This parameter is subject to change - private int packerRawDataCopyingThreshold = 512; - - public Config build() - { - return new Config( - readStringAsBinary, - readBinaryAsString, - onMalFormedInput, - onUnmappableCharacter, - maxUnpackStringSize, - stringEncoderBufferSize, - stringDecoderBufferSize, - packerBufferSize, - packerSmallStringOptimizationThreshold, - packerRawDataCopyingThreshold - ); - } - - public ConfigBuilder readStringAsBinary(boolean enable) - { - this.readStringAsBinary = enable; - return this; - } - - public ConfigBuilder readBinaryAsString(boolean enable) - { - this.readBinaryAsString = enable; - return this; - } - - public ConfigBuilder onMalFormedInput(CodingErrorAction action) - { - this.onMalFormedInput = action; - return this; - } - - public ConfigBuilder onUnmappableCharacter(CodingErrorAction action) - { - this.onUnmappableCharacter = action; - return this; - } - - public ConfigBuilder maxUnpackStringSize(int size) - { - this.maxUnpackStringSize = size; - return this; - } - - public ConfigBuilder stringEncoderBufferSize(int size) - { - this.stringEncoderBufferSize = size; - return this; - } - - public ConfigBuilder stringDecoderBufferSize(int size) - { - this.stringDecoderBufferSize = size; - return this; - } - - public ConfigBuilder packerBufferSize(int size) - { - this.packerBufferSize = size; - return this; - } - - public ConfigBuilder packerSmallStringOptimizationThreshold(int threshold) - { - this.packerSmallStringOptimizationThreshold = threshold; - return this; - } - - public ConfigBuilder packerRawDataCopyingThreshold(int threshold) - { - this.packerRawDataCopyingThreshold = threshold; - return this; - } - } + private static MessagePackFactory defaultFactory = new MessagePackFactory(); /** - * Default configuration, which is visible only from classes in the core package. + * Sets the default configuration used for the static constructor methods of this MessagePack class. */ - static final Config DEFAULT_CONFIG = new ConfigBuilder().build(); - - /** - * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. - */ - public static final class Code - { - public static final boolean isFixInt(byte b) - { - int v = b & 0xFF; - return v <= 0x7f || v >= 0xe0; - } - - public static final boolean isPosFixInt(byte b) - { - return (b & POSFIXINT_MASK) == 0; - } - - public static final boolean isNegFixInt(byte b) - { - return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; - } - - public static final boolean isFixStr(byte b) - { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final boolean isFixedArray(byte b) - { - return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; - } - - public static final boolean isFixedMap(byte b) - { - return (b & (byte) 0xe0) == Code.FIXMAP_PREFIX; - } - - public static final boolean isFixedRaw(byte b) - { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final byte POSFIXINT_MASK = (byte) 0x80; - - public static final byte FIXMAP_PREFIX = (byte) 0x80; - public static final byte FIXARRAY_PREFIX = (byte) 0x90; - public static final byte FIXSTR_PREFIX = (byte) 0xa0; - - public static final byte NIL = (byte) 0xc0; - public static final byte NEVER_USED = (byte) 0xc1; - public static final byte FALSE = (byte) 0xc2; - public static final byte TRUE = (byte) 0xc3; - public static final byte BIN8 = (byte) 0xc4; - public static final byte BIN16 = (byte) 0xc5; - public static final byte BIN32 = (byte) 0xc6; - public static final byte EXT8 = (byte) 0xc7; - public static final byte EXT16 = (byte) 0xc8; - public static final byte EXT32 = (byte) 0xc9; - public static final byte FLOAT32 = (byte) 0xca; - public static final byte FLOAT64 = (byte) 0xcb; - public static final byte UINT8 = (byte) 0xcc; - public static final byte UINT16 = (byte) 0xcd; - public static final byte UINT32 = (byte) 0xce; - public static final byte UINT64 = (byte) 0xcf; - - public static final byte INT8 = (byte) 0xd0; - public static final byte INT16 = (byte) 0xd1; - public static final byte INT32 = (byte) 0xd2; - public static final byte INT64 = (byte) 0xd3; - - public static final byte FIXEXT1 = (byte) 0xd4; - public static final byte FIXEXT2 = (byte) 0xd5; - public static final byte FIXEXT4 = (byte) 0xd6; - public static final byte FIXEXT8 = (byte) 0xd7; - public static final byte FIXEXT16 = (byte) 0xd8; - - public static final byte STR8 = (byte) 0xd9; - public static final byte STR16 = (byte) 0xda; - public static final byte STR32 = (byte) 0xdb; - - public static final byte ARRAY16 = (byte) 0xdc; - public static final byte ARRAY32 = (byte) 0xdd; - - public static final byte MAP16 = (byte) 0xde; - public static final byte MAP32 = (byte) 0xdf; - - public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; - } - - // Packer/Unpacker factory methods - - private final MessagePack.Config config; - - public MessagePack() + public static void setDefaultFactory(MessagePackFactory newDefaultFactory) { - this(MessagePack.DEFAULT_CONFIG); + defaultFactory = newDefaultFactory; } - public MessagePack(MessagePack.Config config) + public static MessagePackFactory getDefaultFactory() { - this.config = config; + return defaultFactory; } - /** - * Default MessagePack packer/unpacker factory - */ - public static final MessagePack DEFAULT = new MessagePack(MessagePack.DEFAULT_CONFIG); + private MessagePack() + { } /** - * Create a MessagePacker that outputs the packed data to the specified stream, using the default configuration + * Equivalent to getDefaultFactory().newPacker(out). * * @param out * @return */ public static MessagePacker newDefaultPacker(OutputStream out) { - return DEFAULT.newPacker(out); + return defaultFactory.newPacker(out); } /** - * Create a MessagePacker that outputs the packed data to the specified channel, using the default configuration + * Equivalent to getDefaultFactory().newPacker(channel). * * @param channel * @return */ public static MessagePacker newDefaultPacker(WritableByteChannel channel) { - return DEFAULT.newPacker(channel); - } - - /** - * Create a MessageUnpacker that reads data from then given InputStream, using the default configuration - * - * @param in - * @return - */ - public static MessageUnpacker newDefaultUnpacker(InputStream in) - { - return DEFAULT.newUnpacker(in); + return defaultFactory.newPacker(channel); } /** - * Create a MessageUnpacker that reads data from the given channel, using the default configuration + * Equivalent to getDefaultFactory().newBufferPacker() * * @param channel * @return */ - public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) - { - return DEFAULT.newUnpacker(channel); - } - - /** - * Create a MessageUnpacker that reads data from the given byte array, using the default configuration - * - * @param arr - * @return - */ - public static MessageUnpacker newDefaultUnpacker(byte[] arr) + public static MessageBufferPacker newDefaultBufferPacker() { - return DEFAULT.newUnpacker(arr); + return defaultFactory.newBufferPacker(); } /** - * Create a MessageUnpacker that reads data form the given byte array [offset, .. offset+length), using the default - * configuration. + * Equivalent to getDefaultFactory().newUnpacker(in). * - * @param arr - * @param offset - * @param length + * @param in * @return */ - public static MessageUnpacker newDefaultUnpacker(byte[] arr, int offset, int length) - { - return DEFAULT.newUnpacker(arr, offset, length); - } - - /** - * Create a MessagePacker that outputs the packed data to the specified stream - * - * @param out - */ - public MessagePacker newPacker(OutputStream out) + public static MessageUnpacker newDefaultUnpacker(InputStream in) { - return new MessagePacker(new OutputStreamBufferOutput(out), config); + return defaultFactory.newUnpacker(in); } /** - * Create a MessagePacker that outputs the packed data to the specified channel + * Equivalent to getDefaultFactory().newUnpacker(channel). * * @param channel + * @return */ - public MessagePacker newPacker(WritableByteChannel channel) - { - return new MessagePacker(new ChannelBufferOutput(channel), config); - } - - /** - * Create a MessageUnpacker that reads data from the given InputStream. - * For reading data efficiently from byte[], use {@link MessageUnpacker(byte[])} or {@link MessageUnpacker(byte[], int, int)} instead of this constructor. - * - * @param in - */ - public MessageUnpacker newUnpacker(InputStream in) - { - return new MessageUnpacker(InputStreamBufferInput.newBufferInput(in), config); - } - - /** - * Create a MessageUnpacker that reads data from the given ReadableByteChannel. - * - * @param in - */ - public MessageUnpacker newUnpacker(ReadableByteChannel in) + public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) { - return new MessageUnpacker(new ChannelBufferInput(in), config); + return defaultFactory.newUnpacker(channel); } /** - * Create a MessageUnpacker that reads data from the given byte array. + * Equivalent to getDefaultFactory().newUnpacker(contents). * - * @param arr + * @param contents + * @return */ - public MessageUnpacker newUnpacker(byte[] arr) + public static MessageUnpacker newDefaultUnpacker(byte[] contents) { - return new MessageUnpacker(new ArrayBufferInput(arr), config); + return defaultFactory.newUnpacker(contents); } /** - * Create a MessageUnpacker that reads data from the given byte array [offset, offset+length) + * Equivalent to getDefaultFactory().newUnpacker(contents, offset, length). * - * @param arr + * @param contents * @param offset * @param length + * @return */ - public MessageUnpacker newUnpacker(byte[] arr, int offset, int length) + public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, int length) { - return new MessageUnpacker(new ArrayBufferInput(arr, offset, length), config); + return defaultFactory.newUnpacker(contents, offset, length); } + + // TODO add convenient methods here to pack/unpack objects with byte array/stream } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java new file mode 100644 index 000000000..f76df5490 --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java @@ -0,0 +1,203 @@ +// +// MessagePack for Java +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package org.msgpack.core; + +import org.msgpack.core.buffer.ArrayBufferInput; +import org.msgpack.core.buffer.ChannelBufferInput; +import org.msgpack.core.buffer.ChannelBufferOutput; +import org.msgpack.core.buffer.InputStreamBufferInput; +import org.msgpack.core.buffer.OutputStreamBufferOutput; +import org.msgpack.core.buffer.MessageBufferInput; +import org.msgpack.core.buffer.MessageBufferOutput; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.WritableByteChannel; +import java.nio.channels.ReadableByteChannel; + +import java.nio.charset.CodingErrorAction; +import static org.msgpack.core.Preconditions.checkArgument; + +public class MessagePackFactory +{ + private int packerSmallStringOptimizationThreshold = 512; + + private boolean unpackAllowStringAsBinary = true; + private boolean unpackAllowBinaryAsString = true; + private CodingErrorAction unpackActionOnMalformedString = CodingErrorAction.REPLACE; + private CodingErrorAction unpackActionOnUnmappableString = CodingErrorAction.REPLACE; + private int unpackStringSizeLimit = Integer.MAX_VALUE; + private int unpackStringDecoderBufferSize = 8192; + + private int inputBufferSize = 16*1024; + private int outputBufferSize = 16*1024; + + public MessagePacker newPacker(OutputStream out) + { + return newPacker(new OutputStreamBufferOutput(out)); + } + + public MessagePacker newPacker(WritableByteChannel channel) + { + return newPacker(new ChannelBufferOutput(channel)); + } + + public MessagePacker newPacker(MessageBufferOutput output) + { + return new MessagePacker(output) + .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold); + } + + public MessageBufferPacker newBufferPacker() + { + return new MessageBufferPacker() + .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold); + } + + public MessageUnpacker newUnpacker(byte[] contents) + { + return newUnpacker(contents, 0, contents.length); + } + + public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) + { + return newUnpacker(new ArrayBufferInput(contents, offset, length)); + } + + public MessageUnpacker newUnpacker(InputStream in) + { + return newUnpacker(new InputStreamBufferInput(in)); + } + + public MessageUnpacker newUnpacker(ReadableByteChannel channel) + { + return newUnpacker(new ChannelBufferInput(channel)); + } + + public MessageUnpacker newUnpacker(MessageBufferInput input) + { + return new MessageUnpacker(input) + .setAllowStringAsBinary(unpackAllowStringAsBinary) + .setAllowBinaryAsString(unpackAllowBinaryAsString) + .setActionOnMalformedString(unpackActionOnMalformedString) + .setActionOnUnmappableString(unpackActionOnUnmappableString) + .setStringSizeLimit(unpackStringSizeLimit) + .setStringDecoderBufferSize(unpackStringDecoderBufferSize); + } + + /** + * Use String.getBytes() for strings smaller than this threshold. + * Note that this parameter is subject to change. + */ + public MessagePackFactory packerSmallStringOptimizationThreshold(int bytes) + { + this.packerSmallStringOptimizationThreshold = bytes; + return this; + } + + public MessagePackFactory unpackAllowStringAsBinary(boolean enabled) + { + this.unpackAllowStringAsBinary = enabled; + return this; + } + + public MessagePackFactory unpackAllowBinaryAsString(boolean enabled) + { + this.unpackAllowBinaryAsString = enabled; + return this; + } + + public MessagePackFactory unpackActionOnMalformedString(CodingErrorAction action) + { + this.unpackActionOnMalformedString = action; + return this; + } + + public MessagePackFactory unpackActionOnUnmappableString(CodingErrorAction action) + { + this.unpackActionOnUnmappableString = action; + return this; + } + + public MessagePackFactory unpackStringSizeLimit(int bytes) + { + this.unpackStringSizeLimit = bytes; + return this; + } + + public MessagePackFactory unpackStringDecoderBufferSize(int bytes) + { + this.unpackStringDecoderBufferSize = bytes; + return this; + } + + public MessagePackFactory inputBufferSize(int bytes) + { + this.inputBufferSize = bytes; + return this; + } + + public MessagePackFactory outputBufferSize(int bytes) + { + this.inputBufferSize = bytes; + return this; + } + + private int getPackerSmallStringOptimizationThreshold() + { + return packerSmallStringOptimizationThreshold; + } + + private boolean getUnpackAllowStringAsBinary() + { + return unpackAllowStringAsBinary; + } + + private boolean getUnpackAllowBinaryAsString() + { + return unpackAllowBinaryAsString; + } + + private CodingErrorAction getUnpackActionOnMalformedString() + { + return unpackActionOnMalformedString; + } + + private CodingErrorAction getUnpackActionOnUnmappableString() + { + return unpackActionOnUnmappableString; + } + + private int getUnpackStringSizeLimit() + { + return unpackStringSizeLimit; + } + + private int getUnpackStringDecoderBufferSize() + { + return unpackStringDecoderBufferSize; + } + + private int getInputBufferSize() + { + return inputBufferSize; + } + + private int getOutputBufferSize() + { + return outputBufferSize; + } +} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 11f2fcb5d..a145df162 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -29,40 +29,40 @@ import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; -import static org.msgpack.core.MessagePack.Code.ARRAY16; -import static org.msgpack.core.MessagePack.Code.ARRAY32; -import static org.msgpack.core.MessagePack.Code.BIN16; -import static org.msgpack.core.MessagePack.Code.BIN32; -import static org.msgpack.core.MessagePack.Code.BIN8; -import static org.msgpack.core.MessagePack.Code.EXT16; -import static org.msgpack.core.MessagePack.Code.EXT32; -import static org.msgpack.core.MessagePack.Code.EXT8; -import static org.msgpack.core.MessagePack.Code.FALSE; -import static org.msgpack.core.MessagePack.Code.FIXARRAY_PREFIX; -import static org.msgpack.core.MessagePack.Code.FIXEXT1; -import static org.msgpack.core.MessagePack.Code.FIXEXT16; -import static org.msgpack.core.MessagePack.Code.FIXEXT2; -import static org.msgpack.core.MessagePack.Code.FIXEXT4; -import static org.msgpack.core.MessagePack.Code.FIXEXT8; -import static org.msgpack.core.MessagePack.Code.FIXMAP_PREFIX; -import static org.msgpack.core.MessagePack.Code.FIXSTR_PREFIX; -import static org.msgpack.core.MessagePack.Code.FLOAT32; -import static org.msgpack.core.MessagePack.Code.FLOAT64; -import static org.msgpack.core.MessagePack.Code.INT16; -import static org.msgpack.core.MessagePack.Code.INT32; -import static org.msgpack.core.MessagePack.Code.INT64; -import static org.msgpack.core.MessagePack.Code.INT8; -import static org.msgpack.core.MessagePack.Code.MAP16; -import static org.msgpack.core.MessagePack.Code.MAP32; -import static org.msgpack.core.MessagePack.Code.NIL; -import static org.msgpack.core.MessagePack.Code.STR16; -import static org.msgpack.core.MessagePack.Code.STR32; -import static org.msgpack.core.MessagePack.Code.STR8; -import static org.msgpack.core.MessagePack.Code.TRUE; -import static org.msgpack.core.MessagePack.Code.UINT16; -import static org.msgpack.core.MessagePack.Code.UINT32; -import static org.msgpack.core.MessagePack.Code.UINT64; -import static org.msgpack.core.MessagePack.Code.UINT8; +import static org.msgpack.core.MessageFormat.Code.ARRAY16; +import static org.msgpack.core.MessageFormat.Code.ARRAY32; +import static org.msgpack.core.MessageFormat.Code.BIN16; +import static org.msgpack.core.MessageFormat.Code.BIN32; +import static org.msgpack.core.MessageFormat.Code.BIN8; +import static org.msgpack.core.MessageFormat.Code.EXT16; +import static org.msgpack.core.MessageFormat.Code.EXT32; +import static org.msgpack.core.MessageFormat.Code.EXT8; +import static org.msgpack.core.MessageFormat.Code.FALSE; +import static org.msgpack.core.MessageFormat.Code.FIXARRAY_PREFIX; +import static org.msgpack.core.MessageFormat.Code.FIXEXT1; +import static org.msgpack.core.MessageFormat.Code.FIXEXT16; +import static org.msgpack.core.MessageFormat.Code.FIXEXT2; +import static org.msgpack.core.MessageFormat.Code.FIXEXT4; +import static org.msgpack.core.MessageFormat.Code.FIXEXT8; +import static org.msgpack.core.MessageFormat.Code.FIXMAP_PREFIX; +import static org.msgpack.core.MessageFormat.Code.FIXSTR_PREFIX; +import static org.msgpack.core.MessageFormat.Code.FLOAT32; +import static org.msgpack.core.MessageFormat.Code.FLOAT64; +import static org.msgpack.core.MessageFormat.Code.INT16; +import static org.msgpack.core.MessageFormat.Code.INT32; +import static org.msgpack.core.MessageFormat.Code.INT64; +import static org.msgpack.core.MessageFormat.Code.INT8; +import static org.msgpack.core.MessageFormat.Code.MAP16; +import static org.msgpack.core.MessageFormat.Code.MAP32; +import static org.msgpack.core.MessageFormat.Code.NIL; +import static org.msgpack.core.MessageFormat.Code.STR16; +import static org.msgpack.core.MessageFormat.Code.STR32; +import static org.msgpack.core.MessageFormat.Code.STR8; +import static org.msgpack.core.MessageFormat.Code.TRUE; +import static org.msgpack.core.MessageFormat.Code.UINT16; +import static org.msgpack.core.MessageFormat.Code.UINT32; +import static org.msgpack.core.MessageFormat.Code.UINT64; +import static org.msgpack.core.MessageFormat.Code.UINT8; import static org.msgpack.core.Preconditions.checkNotNull; /** @@ -85,9 +85,9 @@ public class MessagePacker implements Closeable { - private final MessagePack.Config config; + private int smallStringOptimizationThreshold = 512; - private MessageBufferOutput out; + protected MessageBufferOutput out; private MessageBuffer buffer; @@ -111,17 +111,17 @@ public class MessagePacker */ public MessagePacker(MessageBufferOutput out) { - this(out, MessagePack.DEFAULT_CONFIG); - } - - public MessagePacker(MessageBufferOutput out, MessagePack.Config config) - { - this.config = checkNotNull(config, "config is null"); this.out = checkNotNull(out, "MessageBufferOutput is null"); this.position = 0; this.totalFlushBytes = 0; } + public MessagePacker setSmallStringOptimizationThreshold(int bytes) + { + this.smallStringOptimizationThreshold = bytes; + return this; + } + /** * Reset output. This method doesn't close the old resource. * @@ -441,7 +441,7 @@ private void packStringByGetBytes(String s) private void prepareEncoder() { if (encoder == null) { - this.encoder = MessagePack.UTF8.newEncoder().onMalformedInput(config.actionOnMalFormedInput).onUnmappableCharacter(config.actionOnMalFormedInput); + this.encoder = MessagePack.UTF8.newEncoder(); } } @@ -482,7 +482,7 @@ public MessagePacker packString(String s) packRawStringHeader(0); return this; } - else if (s.length() < config.packerSmallStringOptimizationThreshold) { + else if (s.length() < smallStringOptimizationThreshold) { // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer packStringByGetBytes(s); return this; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 9b8e159bc..7e54d5253 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -15,7 +15,7 @@ // package org.msgpack.core; -import org.msgpack.core.MessagePack.Code; +import org.msgpack.core.MessageFormat.Code; import org.msgpack.core.buffer.MessageBuffer; import org.msgpack.core.buffer.MessageBufferInput; import org.msgpack.value.ImmutableValue; @@ -48,7 +48,7 @@ *

*

  * 
- *     MessageUnpacker unpacker = MessagePackFactory.DEFAULT.newUnpacker(...);
+ *     MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
  *     while(unpacker.hasNext()) {
  *         MessageFormat f = unpacker.getNextFormat();
  *         switch(f) {
@@ -76,7 +76,12 @@ public class MessageUnpacker
 
     private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1;
 
-    private final MessagePack.Config config;
+    private boolean allowStringAsBinary = true;
+    private boolean allowBinaryAsString = true;
+    private CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE;
+    private CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE;
+    private int stringSizeLimit = Integer.MAX_VALUE;
+    private int stringDecoderBufferSize = 8192;
 
     private MessageBufferInput in;
 
@@ -135,20 +140,43 @@ public class MessageUnpacker
      */
     public MessageUnpacker(MessageBufferInput in)
     {
-        this(in, MessagePack.DEFAULT_CONFIG);
+        this.in = checkNotNull(in, "MessageBufferInput is null");
     }
 
-    /**
-     * Create an MessageUnpacker
-     *
-     * @param in
-     * @param config configuration
-     */
-    public MessageUnpacker(MessageBufferInput in, MessagePack.Config config)
+    public MessageUnpacker setAllowStringAsBinary(boolean enabled)
     {
-        // Root constructor. All of the constructors must call this constructor.
-        this.in = checkNotNull(in, "MessageBufferInput is null");
-        this.config = checkNotNull(config, "Config");
+        this.allowStringAsBinary = enabled;
+        return this;
+    }
+
+    public MessageUnpacker setAllowBinaryAsString(boolean enabled)
+    {
+        this.allowBinaryAsString = enabled;
+        return this;
+    }
+
+    public MessageUnpacker setActionOnMalformedString(CodingErrorAction action)
+    {
+        this.actionOnMalformedString = action;
+        return this;
+    }
+
+    public MessageUnpacker setActionOnUnmappableString(CodingErrorAction action)
+    {
+        this.actionOnUnmappableString = action;
+        return this;
+    }
+
+    public MessageUnpacker setStringSizeLimit(int bytes)
+    {
+        this.stringSizeLimit = bytes;
+        return this;
+    }
+
+    public MessageUnpacker setStringDecoderBufferSize(int bytes)
+    {
+        this.stringDecoderBufferSize = bytes;
+        return this;
     }
 
     /**
@@ -958,10 +986,10 @@ public double unpackDouble()
     private void resetDecoder()
     {
         if (decoder == null) {
-            decodeBuffer = CharBuffer.allocate(config.stringDecoderBufferSize);
+            decodeBuffer = CharBuffer.allocate(stringDecoderBufferSize);
             decoder = MessagePack.UTF8.newDecoder()
-                    .onMalformedInput(config.actionOnMalFormedInput)
-                    .onUnmappableCharacter(config.actionOnUnmappableCharacter);
+                    .onMalformedInput(actionOnMalformedString)
+                    .onUnmappableCharacter(actionOnUnmappableString);
         }
         else {
             decoder.reset();
@@ -980,8 +1008,8 @@ public String unpackString()
             if (len == 0) {
                 return EMPTY_STRING;
             }
-            if (len > config.maxUnpackStringSize) {
-                throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", config.maxUnpackStringSize, len), len);
+            if (len > stringSizeLimit) {
+                throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len);
             }
             if (buffer.size() - position >= len) {
                 return decodeStringFastPath(len);
@@ -1069,16 +1097,16 @@ else if (bufferRemaining == 0) {
     private void handleCoderError(CoderResult cr)
         throws CharacterCodingException
     {
-        if ((cr.isMalformed() && config.actionOnMalFormedInput == CodingErrorAction.REPORT) ||
-                (cr.isUnmappable() && config.actionOnUnmappableCharacter == CodingErrorAction.REPORT)) {
+        if ((cr.isMalformed() && actionOnMalformedString == CodingErrorAction.REPORT) ||
+                (cr.isUnmappable() && actionOnUnmappableString == CodingErrorAction.REPORT)) {
             cr.throwException();
         }
     }
 
     private String decodeStringFastPath(int length)
     {
-        if (config.actionOnMalFormedInput == CodingErrorAction.REPLACE &&
-                config.actionOnUnmappableCharacter == CodingErrorAction.REPLACE &&
+        if (actionOnMalformedString == CodingErrorAction.REPLACE &&
+                actionOnUnmappableString == CodingErrorAction.REPLACE &&
                 buffer.hasArray()) {
             String s = new String(buffer.getArray(), buffer.offset() + position, length, MessagePack.UTF8);
             position += length;
@@ -1253,7 +1281,7 @@ public int unpackRawStringHeader()
             return len;
         }
 
-        if (config.readBinaryAsString) {
+        if (allowBinaryAsString) {
             len = tryReadBinaryHeader(b);
             if (len >= 0) {
                 resetHeadByte();
@@ -1277,7 +1305,7 @@ public int unpackBinaryHeader()
             return len;
         }
 
-        if (config.readStringAsBinary) {
+        if (allowStringAsBinary) {
             len = tryReadStringHeader(b);
             if (len >= 0) {
                 resetHeadByte();
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
new file mode 100644
index 000000000..710013153
--- /dev/null
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
@@ -0,0 +1,136 @@
+//
+// MessagePack for Java
+//
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+//
+package org.msgpack.core.buffer;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * MessageBufferOutput adapter that packs data into list of byte arrays.
+ */
+public class ArrayBufferOutput
+        implements MessageBufferOutput
+{
+    private List list;
+    private MessageBuffer lastBuffer;
+    private int bufferSize;
+
+    public ArrayBufferOutput()
+    {
+        this(8192);
+    }
+
+    public ArrayBufferOutput(int bufferSize)
+    {
+        this.bufferSize = bufferSize;
+        this.list = new ArrayList();
+    }
+
+    public int getSize()
+    {
+        int size = 0;
+        for (MessageBuffer buffer : list) {
+            size += buffer.size();
+        }
+        return size;
+    }
+
+    public byte[] toByteArray()
+    {
+        byte[] data = new byte[getSize()];
+        int off = 0;
+        for (MessageBuffer buffer : list) {
+            buffer.getBytes(0, data, off, buffer.size());
+            off += buffer.size();
+        }
+        return data;
+    }
+
+    public MessageBuffer toMessageBuffer()
+    {
+        if (list.size() == 1) {
+            return list.get(0);
+        }
+        else if (list.isEmpty()) {
+            return MessageBuffer.newBuffer(0);
+        }
+        else {
+            return MessageBuffer.wrap(toByteArray());
+        }
+    }
+
+    public List toBufferList()
+    {
+        return new ArrayList(list);
+    }
+
+    /**
+     * Clears the internal buffers
+     */
+    public void clear()
+    {
+        list.clear();
+    }
+
+    @Override
+    public MessageBuffer next(int mimimumSize)
+    {
+        if (lastBuffer != null && lastBuffer.size() > mimimumSize) {
+            return lastBuffer;
+        }
+        else {
+            int size = Math.max(bufferSize, mimimumSize);
+            MessageBuffer buffer = MessageBuffer.newBuffer(size);
+            lastBuffer = buffer;
+            return buffer;
+        }
+    }
+
+    @Override
+    public void writeBuffer(int length)
+    {
+        list.add(lastBuffer.slice(0, length));
+        if (lastBuffer.size() - length > bufferSize / 4) {
+            lastBuffer = lastBuffer.slice(length, lastBuffer.size() - length);
+        }
+        else {
+            lastBuffer = null;
+        }
+    }
+
+    @Override
+    public void write(byte[] buffer, int offset, int length)
+    {
+        MessageBuffer copy = MessageBuffer.newBuffer(length);
+        copy.putBytes(0, buffer, offset, length);
+        list.add(copy);
+    }
+
+    @Override
+    public void add(byte[] buffer, int offset, int length)
+    {
+        MessageBuffer wrapped = MessageBuffer.wrap(buffer, offset, length);
+        list.add(wrapped);
+    }
+
+    @Override
+    public void close()
+    { }
+
+    @Override
+    public void flush()
+    { }
+}
diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
index 7636742e0..d7dffe64b 100644
--- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
+++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
@@ -17,6 +17,7 @@
 
 import org.msgpack.core.MessageFormat;
 import org.msgpack.core.MessagePack;
+import org.msgpack.core.MessagePackFactory;
 import org.msgpack.core.MessagePacker;
 import org.msgpack.core.MessageUnpacker;
 import org.msgpack.value.ArrayValue;
@@ -246,24 +247,22 @@ public static void configuration()
             throws IOException
     {
         // Build a conifiguration
-        MessagePack.Config config = new MessagePack.ConfigBuilder()
-                .onMalFormedInput(CodingErrorAction.REPLACE)         // Drop malformed and unmappable UTF-8 characters
-                .onUnmappableCharacter(CodingErrorAction.REPLACE)
-                .packerBufferSize(8192 * 2)
-                .build();
+        MessagePackFactory factory = new MessagePackFactory()
+                .unpackActionOnMalformedString(CodingErrorAction.REPLACE)         // Drop malformed and unmappable UTF-8 characters
+                .unpackActionOnUnmappableString(CodingErrorAction.REPLACE)
+                .outputBufferSize(8192 * 2);
         // Create a  that uses this configuration
-        MessagePack msgpack = new MessagePack(config);
 
         // Pack data
         ByteArrayOutputStream out = new ByteArrayOutputStream();
-        MessagePacker packer = msgpack.newPacker(out);
+        MessagePacker packer = factory.newPacker(out);
         packer.packInt(10);
         packer.packBoolean(true);
         packer.close();
 
         // Unpack data
         byte[] packedData = out.toByteArray();
-        MessageUnpacker unpacker = msgpack.newUnpacker(packedData);
+        MessageUnpacker unpacker = factory.newUnpacker(packedData);
         int i = unpacker.unpackInt();  // 10
         boolean b = unpacker.unpackBoolean(); // true
         unpacker.close();
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala
index be9d270cd..a6a71e2d9 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala
@@ -15,7 +15,7 @@
 //
 package org.msgpack.core
 
-import org.msgpack.core.MessagePack.Code
+import org.msgpack.core.MessageFormat.Code
 import org.msgpack.value.ValueType
 import org.scalatest.exceptions.TestFailedException
 
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
index f903cf88d..5cf8ea2e6 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
@@ -20,7 +20,7 @@ import java.math.BigInteger
 import java.nio.CharBuffer
 import java.nio.charset.{CodingErrorAction, UnmappableCharacterException}
 
-import org.msgpack.core.MessagePack.Code
+import org.msgpack.core.MessageFormat.Code
 import org.msgpack.value.{Value, Variable}
 
 import scala.util.Random
@@ -117,17 +117,17 @@ class MessagePackTest extends MessagePackSpec {
     }
 
 
-    def check[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A, msgpack: MessagePack = MessagePack.DEFAULT): Unit = {
+    def check[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A, factory: MessagePackFactory = new MessagePackFactory()): Unit = {
       var b: Array[Byte] = null
       try {
         val bs = new ByteArrayOutputStream()
-        val packer = msgpack.newPacker(bs)
+        val packer = factory.newPacker(bs)
         pack(packer)
         packer.close()
 
         b = bs.toByteArray
 
-        val unpacker = msgpack.newUnpacker(b)
+        val unpacker = factory.newUnpacker(b)
         val ret = unpack(unpacker)
         ret shouldBe v
       }
@@ -142,16 +142,16 @@ class MessagePackTest extends MessagePackSpec {
     }
 
     def checkException[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A,
-                          msgpack: MessagePack = MessagePack.DEFAULT): Unit = {
+                          factory: MessagePackFactory = new MessagePackFactory()): Unit = {
       var b: Array[Byte] = null
       val bs = new ByteArrayOutputStream()
-      val packer = msgpack.newPacker(bs)
+      val packer = factory.newPacker(bs)
       pack(packer)
       packer.close()
 
       b = bs.toByteArray
 
-      val unpacker = msgpack.newUnpacker(b)
+      val unpacker = factory.newUnpacker(b)
       val ret = unpack(unpacker)
 
       fail("cannot not reach here")
@@ -297,11 +297,9 @@ class MessagePackTest extends MessagePackSpec {
       //val unmappableChar = Array[Char](new Character(0xfc0a).toChar)
 
       // Report error on unmappable character
-      val config = new MessagePack.ConfigBuilder()
-        .onMalFormedInput(CodingErrorAction.REPORT)
-        .onUnmappableCharacter(CodingErrorAction.REPORT)
-        .build()
-      val msgpack = new MessagePack(config)
+      val factory = new MessagePackFactory()
+        .unpackActionOnMalformedString(CodingErrorAction.REPORT)
+        .unpackActionOnUnmappableString(CodingErrorAction.REPORT);
 
       for (bytes <- Seq(unmappable)) {
         When("unpacking")
@@ -311,7 +309,7 @@ class MessagePackTest extends MessagePackSpec {
             packer.writePayload(bytes)
           },
           _.unpackString(),
-          msgpack)
+          factory)
         }
         catch {
           case e: MessageStringCodingException => // OK
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
index 967cf07a1..51d411f5f 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala
@@ -30,10 +30,10 @@ import scala.util.Random
 class MessagePackerTest
   extends MessagePackSpec {
 
-  val msgpack = MessagePack.DEFAULT
+  val factory = new MessagePackFactory()
 
   def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) {
-    val unpacker = msgpack.newUnpacker(packed)
+    val unpacker = factory.newUnpacker(packed)
     val b = Array.newBuilder[Int]
     while (unpacker.hasNext) {
       b += unpacker.unpackInt()
@@ -69,7 +69,7 @@ class MessagePackerTest
 
       val b = new
           ByteArrayOutputStream
-      val packer = msgpack.newPacker(b)
+      val packer = factory.newPacker(b)
       intSeq foreach packer.packInt
       packer.close
       verifyIntSeq(intSeq, b.toByteArray)
@@ -102,7 +102,7 @@ class MessagePackerTest
         block("no-buffer-reset") {
           val out = new
               ByteArrayOutputStream
-          IOUtil.withResource(msgpack.newPacker(out)) { packer =>
+          IOUtil.withResource(factory.newPacker(out)) { packer =>
             for (i <- 0 until N) {
               val outputStream = new
                   ByteArrayOutputStream()
@@ -118,7 +118,7 @@ class MessagePackerTest
         block("buffer-reset") {
           val out = new
               ByteArrayOutputStream
-          IOUtil.withResource(msgpack.newPacker(out)) { packer =>
+          IOUtil.withResource(factory.newPacker(out)) { packer =>
             val bufferOut = new
                 OutputStreamBufferOutput(new
                     ByteArrayOutputStream())
@@ -142,15 +142,14 @@ class MessagePackerTest
 
       // TODO: Refactor this test code to fit other ones.
       def test(bufferSize: Int, stringSize: Int): Boolean = {
-        val msgpack = new
-            MessagePack(new
-                MessagePack.ConfigBuilder().packerBufferSize(bufferSize).build)
+        val factory = new MessagePackFactory()
+            .outputBufferSize(bufferSize);
         val str = "a" * stringSize
         val rawString = ValueFactory.newString(str.getBytes("UTF-8"))
         val array = ValueFactory.newArray(rawString)
         val out = new
             ByteArrayOutputStream()
-        val packer = msgpack.newPacker(out)
+        val packer = factory.newPacker(out)
         packer.packValue(array)
         packer.close()
         out.toByteArray
@@ -266,7 +265,7 @@ class MessagePackerTest
   "compute totalWrittenBytes" in {
     val out = new
         ByteArrayOutputStream
-    val packerTotalWrittenBytes = IOUtil.withResource(msgpack.newPacker(out)) { packer =>
+    val packerTotalWrittenBytes = IOUtil.withResource(factory.newPacker(out)) { packer =>
       packer.packByte(0) // 1
         .packBoolean(true) // 1
         .packShort(12) // 1
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
index fc03d5680..2611d8c9d 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala
@@ -29,11 +29,11 @@ import scala.util.Random
  */
 class MessageUnpackerTest extends MessagePackSpec {
 
-  val msgpack = MessagePack.DEFAULT
+  val factory = new MessagePackFactory()
 
   def testData: Array[Byte] = {
     val out = new ByteArrayOutputStream()
-    val packer = msgpack.newPacker(out)
+    val packer = factory.newPacker(out)
 
     packer
       .packArrayHeader(2)
@@ -55,7 +55,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
   def testData2: Array[Byte] = {
     val out = new ByteArrayOutputStream()
-    val packer = msgpack.newPacker(out);
+    val packer = factory.newPacker(out);
 
     packer
       .packBoolean(true)
@@ -125,7 +125,7 @@ class MessageUnpackerTest extends MessagePackSpec {
   def testData3(N: Int): Array[Byte] = {
 
     val out = new ByteArrayOutputStream()
-    val packer = msgpack.newPacker(out)
+    val packer = factory.newPacker(out)
 
     val r = new Random(0)
 
@@ -179,7 +179,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "parse message packed data" taggedAs ("unpack") in {
       val arr = testData
 
-      val unpacker = msgpack.newUnpacker(arr)
+      val unpacker = factory.newUnpacker(arr)
 
       var count = 0
       while (unpacker.hasNext) {
@@ -192,7 +192,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
     "skip reading values" in {
 
-      val unpacker = msgpack.newUnpacker(testData)
+      val unpacker = factory.newUnpacker(testData)
       var skipCount = 0
       while (unpacker.hasNext) {
         unpacker.skipValue()
@@ -209,7 +209,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
       time("skip performance", repeat = 100) {
         block("switch") {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           var skipCount = 0
           while (unpacker.hasNext) {
             unpacker.skipValue()
@@ -227,7 +227,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
       val ib = Seq.newBuilder[Int]
 
-      val unpacker = msgpack.newUnpacker(testData2)
+      val unpacker = factory.newUnpacker(testData2)
       while (unpacker.hasNext) {
         val f = unpacker.getNextFormat
         f.getValueType match {
@@ -269,7 +269,7 @@ class MessageUnpackerTest extends MessagePackSpec {
       trait SplitTest {
         val data: Array[Byte]
         def run {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           val numElems = {
             var c = 0
             while (unpacker.hasNext) {
@@ -326,7 +326,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7") {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           var count = 0
           try {
             while (unpacker.hasNext) {
@@ -428,7 +428,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7") {
-          val unpacker = msgpack.newUnpacker(data)
+          val unpacker = factory.newUnpacker(data)
           var count = 0
           try {
             while (unpacker.hasNext) {
@@ -449,7 +449,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "be faster for reading binary than v6" taggedAs ("cmp-binary") in {
 
       val bos = new ByteArrayOutputStream()
-      val packer = msgpack.newPacker(bos)
+      val packer = factory.newPacker(bos)
       val L = 10000
       val R = 100
       (0 until R).foreach { i =>
@@ -472,7 +472,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7") {
-          val unpacker = msgpack.newUnpacker(b)
+          val unpacker = factory.newUnpacker(b)
           var i = 0
           while (i < R) {
             val len = unpacker.unpackBinaryHeader()
@@ -484,7 +484,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("v7-ref") {
-          val unpacker = msgpack.newUnpacker(b)
+          val unpacker = factory.newUnpacker(b)
           var i = 0
           while (i < R) {
             val len = unpacker.unpackBinaryHeader()
@@ -505,12 +505,12 @@ class MessageUnpackerTest extends MessagePackSpec {
         val data = new Array[Byte](s)
         Random.nextBytes(data)
         val b = new ByteArrayOutputStream()
-        val packer = msgpack.newPacker(b)
+        val packer = factory.newPacker(b)
         packer.packBinaryHeader(s)
         packer.writePayload(data)
         packer.close()
 
-        val unpacker = msgpack.newUnpacker(b.toByteArray)
+        val unpacker = factory.newUnpacker(b.toByteArray)
         val len = unpacker.unpackBinaryHeader()
         len shouldBe s
         val ref = unpacker.readPayloadAsReference(len)
@@ -529,7 +529,7 @@ class MessageUnpackerTest extends MessagePackSpec {
 
       val data = intSeq
       val b = createMessagePackData(packer => data foreach packer.packInt)
-      val unpacker = msgpack.newUnpacker(b)
+      val unpacker = factory.newUnpacker(b)
 
       val unpacked = Array.newBuilder[Int]
       while (unpacker.hasNext) {
@@ -564,7 +564,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "improve the performance via reset method" taggedAs ("reset-arr") in {
 
       val out = new ByteArrayOutputStream
-      val packer = msgpack.newPacker(out)
+      val packer = factory.newPacker(out)
       packer.packInt(0)
       packer.flush
       val arr = out.toByteArray
@@ -573,7 +573,7 @@ class MessageUnpackerTest extends MessagePackSpec {
       val N = 1000
       val t = time("unpacker", repeat = 10) {
         block("no-buffer-reset") {
-          IOUtil.withResource(msgpack.newUnpacker(arr)) { unpacker =>
+          IOUtil.withResource(factory.newUnpacker(arr)) { unpacker =>
             for (i <- 0 until N) {
               val buf = new ArrayBufferInput(arr)
               unpacker.reset(buf)
@@ -584,7 +584,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("reuse-array-input") {
-          IOUtil.withResource(msgpack.newUnpacker(arr)) { unpacker =>
+          IOUtil.withResource(factory.newUnpacker(arr)) { unpacker =>
             val buf = new ArrayBufferInput(arr)
             for (i <- 0 until N) {
               buf.reset(arr)
@@ -596,7 +596,7 @@ class MessageUnpackerTest extends MessagePackSpec {
         }
 
         block("reuse-message-buffer") {
-          IOUtil.withResource(msgpack.newUnpacker(arr)) { unpacker =>
+          IOUtil.withResource(factory.newUnpacker(arr)) { unpacker =>
             val buf = new ArrayBufferInput(arr)
             for (i <- 0 until N) {
               buf.reset(mb)
@@ -640,7 +640,7 @@ class MessageUnpackerTest extends MessagePackSpec {
     "unpack large string data" taggedAs ("large-string") in {
       def createLargeData(stringLength: Int): Array[Byte] = {
         val out = new ByteArrayOutputStream()
-        val packer = msgpack.newPacker(out)
+        val packer = factory.newPacker(out)
 
         packer
           .packArrayHeader(2)
@@ -655,7 +655,7 @@ class MessageUnpackerTest extends MessagePackSpec {
       Seq(8191, 8192, 8193, 16383, 16384, 16385).foreach { n =>
         val arr = createLargeData(n)
 
-        val unpacker = msgpack.newUnpacker(arr)
+        val unpacker = factory.newUnpacker(arr)
 
         unpacker.unpackArrayHeader shouldBe 2
         unpacker.unpackString.length shouldBe n
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
index d7ebeac84..b6ee7bf08 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
@@ -135,10 +135,8 @@ class MessageBufferInputTest
 
   def createTempFileWithInputStream = {
     val f = createTempFile
-    val out = new
-        FileOutputStream(f)
-    new
-        MessagePack().newPacker(out).packInt(42).close
+    val out = new FileOutputStream(f)
+    MessagePack.newDefaultPacker(out).packInt(42).close
     val in = new
         FileInputStream(f)
     (f, in)
diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala
index 6634ef606..2bd1c7b14 100644
--- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala
@@ -15,7 +15,7 @@
 //
 package org.msgpack.value
 
-import org.msgpack.core.MessagePack.Code._
+import org.msgpack.core.MessageFormat.Code._
 import org.msgpack.core.{MessageFormat, MessageFormatException, MessagePackSpec}
 
 /**

From b662828b3f9c70a8137e4ba50a21b9ac53eb0b80 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Fri, 25 Dec 2015 15:51:57 +0900
Subject: [PATCH 53/99] removed support for ByteBuffer

---
 .../java/org/msgpack/core/MessagePack.java    |   2 -
 .../java/org/msgpack/core/MessagePacker.java  |   2 +-
 .../org/msgpack/core/MessageUnpacker.java     |  10 +-
 .../core/buffer/ArrayBufferOutput.java        |   6 +-
 .../msgpack/core/buffer/ByteBufferInput.java  |  70 --------
 .../core/buffer/ChannelBufferInput.java       |   4 +-
 .../core/buffer/ChannelBufferOutput.java      |   6 +-
 .../msgpack/core/buffer/MessageBuffer.java    | 150 +++---------------
 .../msgpack/core/buffer/MessageBufferBE.java  |  15 +-
 .../msgpack/core/buffer/MessageBufferU.java   |  85 +++++-----
 .../core/buffer/OutputStreamBufferOutput.java |   4 +-
 .../msgpack/core/buffer/ByteStringTest.scala  |  15 --
 .../core/buffer/MessageBufferInputTest.scala  |   5 -
 .../core/buffer/MessageBufferTest.scala       |  43 +----
 14 files changed, 91 insertions(+), 326 deletions(-)
 delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
index 8af53a884..f1bee0774 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
@@ -133,6 +133,4 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, in
     {
         return defaultFactory.newUnpacker(contents, offset, length);
     }
-
-    // TODO add convenient methods here to pack/unpack objects with byte array/stream
 }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
index a145df162..7c71b6807 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
@@ -448,7 +448,7 @@ private void prepareEncoder()
     private int encodeStringToBufferAt(int pos, String s)
     {
         prepareEncoder();
-        ByteBuffer bb = buffer.toByteBuffer(pos, buffer.size() - pos);
+        ByteBuffer bb = buffer.sliceAsByteBuffer(pos, buffer.size() - pos);
         int startPosition = bb.position();
         CharBuffer in = CharBuffer.wrap(s);
         CoderResult cr = encoder.encode(in, bb, true);
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 7e54d5253..2e00a5bc3 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -106,7 +106,7 @@ public class MessageUnpacker
      * Extra buffer for fixed-length data at the buffer boundary.
      * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required.
      */
-    private final MessageBuffer castBuffer = MessageBuffer.newBuffer(8);
+    private final MessageBuffer castBuffer = MessageBuffer.allocate(8);
 
     /**
      * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer.
@@ -1032,7 +1032,7 @@ else if (bufferRemaining == 0) {
                     nextBuffer();
                 }
                 else {
-                    ByteBuffer bb = buffer.toByteBuffer(position, bufferRemaining);
+                    ByteBuffer bb = buffer.sliceAsByteBuffer(position, bufferRemaining);
                     int bbStartPosition = bb.position();
                     decodeBuffer.clear();
 
@@ -1114,7 +1114,7 @@ private String decodeStringFastPath(int length)
         }
         else {
             resetDecoder();
-            ByteBuffer bb = buffer.toByteBuffer();
+            ByteBuffer bb = buffer.sliceAsByteBuffer();
             bb.limit(position + length);
             bb.position(position);
             CharBuffer cb;
@@ -1395,8 +1395,8 @@ public MessageBuffer readPayloadAsReference(int length)
             position += length;
             return slice;
         }
-        MessageBuffer dst = MessageBuffer.newBuffer(length);
-        readPayload(dst.getReference());
+        MessageBuffer dst = MessageBuffer.allocate(length);
+        readPayload(dst.sliceAsByteBuffer());
         return dst;
     }
 
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
index 710013153..186a579af 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferOutput.java
@@ -65,7 +65,7 @@ public MessageBuffer toMessageBuffer()
             return list.get(0);
         }
         else if (list.isEmpty()) {
-            return MessageBuffer.newBuffer(0);
+            return MessageBuffer.allocate(0);
         }
         else {
             return MessageBuffer.wrap(toByteArray());
@@ -93,7 +93,7 @@ public MessageBuffer next(int mimimumSize)
         }
         else {
             int size = Math.max(bufferSize, mimimumSize);
-            MessageBuffer buffer = MessageBuffer.newBuffer(size);
+            MessageBuffer buffer = MessageBuffer.allocate(size);
             lastBuffer = buffer;
             return buffer;
         }
@@ -114,7 +114,7 @@ public void writeBuffer(int length)
     @Override
     public void write(byte[] buffer, int offset, int length)
     {
-        MessageBuffer copy = MessageBuffer.newBuffer(length);
+        MessageBuffer copy = MessageBuffer.allocate(length);
         copy.putBytes(0, buffer, offset, length);
         list.add(copy);
     }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java
deleted file mode 100644
index 034d8882b..000000000
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ByteBufferInput.java
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// MessagePack for Java
-//
-//    Licensed under the Apache License, Version 2.0 (the "License");
-//    you may not use this file except in compliance with the License.
-//    You may obtain a copy of the License at
-//
-//        http://www.apache.org/licenses/LICENSE-2.0
-//
-//    Unless required by applicable law or agreed to in writing, software
-//    distributed under the License is distributed on an "AS IS" BASIS,
-//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//    See the License for the specific language governing permissions and
-//    limitations under the License.
-//
-package org.msgpack.core.buffer;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import static org.msgpack.core.Preconditions.checkNotNull;
-
-/**
- * {@link MessageBufferInput} adapter for {@link java.nio.ByteBuffer}
- */
-public class ByteBufferInput
-        implements MessageBufferInput
-{
-    private ByteBuffer input;
-    private boolean isRead = false;
-
-    public ByteBufferInput(ByteBuffer input)
-    {
-        this.input = checkNotNull(input, "input ByteBuffer is null");
-    }
-
-    /**
-     * Reset buffer. This method doesn't close the old resource.
-     *
-     * @param input new buffer
-     * @return the old resource
-     */
-    public ByteBuffer reset(ByteBuffer input)
-    {
-        ByteBuffer old = this.input;
-        this.input = input;
-        isRead = false;
-        return old;
-    }
-
-    @Override
-    public MessageBuffer next()
-            throws IOException
-    {
-        if (isRead) {
-            return null;
-        }
-
-        isRead = true;
-        return MessageBuffer.wrap(input);
-    }
-
-    @Override
-    public void close()
-            throws IOException
-    {
-        // Nothing to do
-    }
-
-}
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
index 73dcb5db6..781b7afb9 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
@@ -40,7 +40,7 @@ public ChannelBufferInput(ReadableByteChannel channel, int bufferSize)
     {
         this.channel = checkNotNull(channel, "input channel is null");
         checkArgument(bufferSize > 0, "buffer size must be > 0: " + bufferSize);
-        this.m = MessageBuffer.newBuffer(bufferSize);
+        this.m = MessageBuffer.allocate(bufferSize);
     }
 
     /**
@@ -61,7 +61,7 @@ public ReadableByteChannel reset(ReadableByteChannel channel)
     public MessageBuffer next()
             throws IOException
     {
-        ByteBuffer b = m.toByteBuffer();
+        ByteBuffer b = m.sliceAsByteBuffer();
         while (b.remaining() > 0) {
             int ret = channel.read(b);
             if (ret == -1) {
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java
index b981cc95d..32969f29a 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferOutput.java
@@ -38,7 +38,7 @@ public ChannelBufferOutput(WritableByteChannel channel)
     public ChannelBufferOutput(WritableByteChannel channel, int bufferSize)
     {
         this.channel = checkNotNull(channel, "output channel is null");
-        this.buffer = MessageBuffer.newBuffer(bufferSize);
+        this.buffer = MessageBuffer.allocate(bufferSize);
     }
 
     /**
@@ -60,7 +60,7 @@ public MessageBuffer next(int mimimumSize)
             throws IOException
     {
         if (buffer.size() < mimimumSize) {
-            buffer = MessageBuffer.newBuffer(mimimumSize);
+            buffer = MessageBuffer.allocate(mimimumSize);
         }
         return buffer;
     }
@@ -69,7 +69,7 @@ public MessageBuffer next(int mimimumSize)
     public void writeBuffer(int length)
             throws IOException
     {
-        ByteBuffer bb = buffer.toByteBuffer(0, length);
+        ByteBuffer bb = buffer.sliceAsByteBuffer(0, length);
         while (bb.hasRemaining()) {
             channel.write(bb);
         }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
index fce8020ce..e2258265e 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
@@ -39,11 +39,11 @@ public class MessageBuffer
 {
     static final boolean isUniversalBuffer;
     static final Unsafe unsafe;
+
     /**
      * Reference to MessageBuffer Constructors
      */
     private static final Constructor mbArrConstructor;
-    private static final Constructor mbBBConstructor;
 
     /**
      * The offset from the object memory header to its byte array data
@@ -143,14 +143,9 @@ public class MessageBuffer
                 Class bufferCls = Class.forName(bufferClsName);
 
                 // MessageBufferX(byte[]) constructor
-                Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class);
+                Constructor mbArrCstr = bufferCls.getDeclaredConstructor(byte[].class, int.class, int.class);
                 mbArrCstr.setAccessible(true);
                 mbArrConstructor = mbArrCstr;
-
-                // MessageBufferX(ByteBuffer) constructor
-                Constructor mbBBCstr = bufferCls.getDeclaredConstructor(ByteBuffer.class);
-                mbBBCstr.setAccessible(true);
-                mbBBConstructor = mbBBCstr;
             }
             catch (Exception e) {
                 e.printStackTrace(System.err);
@@ -176,67 +171,19 @@ public class MessageBuffer
      */
     protected final int size;
 
-    /**
-     * Reference is used to hold a reference to an object that holds the underlying memory so that it cannot be
-     * released by the garbage collector.
-     */
-    protected final ByteBuffer reference;
-
-    static MessageBuffer newOffHeapBuffer(int length)
-    {
-        // This method is not available in Android OS
-        if (!isUniversalBuffer) {
-            long address = unsafe.allocateMemory(length);
-            return new MessageBuffer(address, length);
-        }
-        else {
-            return newDirectBuffer(length);
-        }
-    }
-
-    public static MessageBuffer newDirectBuffer(int length)
-    {
-        ByteBuffer m = ByteBuffer.allocateDirect(length);
-        return newMessageBuffer(m);
-    }
-
-    public static MessageBuffer newBuffer(int length)
+    public static MessageBuffer allocate(int length)
     {
-        return newMessageBuffer(new byte[length]);
+        return wrap(new byte[length]);
     }
 
     public static MessageBuffer wrap(byte[] array)
     {
-        return newMessageBuffer(array);
+        return newMessageBuffer(array, 0, array.length);
     }
 
     public static MessageBuffer wrap(byte[] array, int offset, int length)
     {
-        return newMessageBuffer(array).slice(offset, length);
-    }
-
-    public static MessageBuffer wrap(ByteBuffer bb)
-    {
-        return newMessageBuffer(bb).slice(bb.position(), bb.remaining());
-    }
-
-    /**
-     * Creates a new MessageBuffer instance backed by ByteBuffer
-     *
-     * @param bb
-     * @return
-     */
-    private static MessageBuffer newMessageBuffer(ByteBuffer bb)
-    {
-        checkNotNull(bb);
-        try {
-            // We need to use reflection to create MessageBuffer instances in order to prevent TypeProfile generation for getInt method. TypeProfile will be
-            // generated to resolve one of the method references when two or more classes overrides the method.
-            return (MessageBuffer) mbBBConstructor.newInstance(bb);
-        }
-        catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        return newMessageBuffer(array, offset, length);
     }
 
     /**
@@ -245,11 +192,11 @@ private static MessageBuffer newMessageBuffer(ByteBuffer bb)
      * @param arr
      * @return
      */
-    private static MessageBuffer newMessageBuffer(byte[] arr)
+    private static MessageBuffer newMessageBuffer(byte[] arr, int off, int len)
     {
         checkNotNull(arr);
         try {
-            return (MessageBuffer) mbArrConstructor.newInstance(arr);
+            return (MessageBuffer) mbArrConstructor.newInstance(arr, off, len);
         }
         catch (Throwable e) {
             throw new RuntimeException(e);
@@ -261,76 +208,31 @@ public static void releaseBuffer(MessageBuffer buffer)
         if (isUniversalBuffer || buffer.base instanceof byte[]) {
             // We have nothing to do. Wait until the garbage-collector collects this array object
         }
-        else if (DirectBufferAccess.isDirectByteBufferInstance(buffer.base)) {
-            DirectBufferAccess.clean(buffer.base);
-        }
         else {
             // Maybe cannot reach here
             unsafe.freeMemory(buffer.address);
         }
     }
 
-    /**
-     * Create a MessageBuffer instance from a given memory address and length
-     *
-     * @param address
-     * @param length
-     */
-    MessageBuffer(long address, int length)
-    {
-        this.base = null;
-        this.address = address;
-        this.size = length;
-        this.reference = null;
-    }
-
-    /**
-     * Create a MessageBuffer instance from a given ByteBuffer instance
-     *
-     * @param bb
-     */
-    MessageBuffer(ByteBuffer bb)
-    {
-        if (bb.isDirect()) {
-            if (isUniversalBuffer) {
-                throw new IllegalStateException("Cannot create MessageBuffer from DirectBuffer");
-            }
-            // Direct buffer or off-heap memory
-            this.base = null;
-            this.address = DirectBufferAccess.getAddress(bb);
-            this.size = bb.capacity();
-            this.reference = bb;
-        }
-        else if (bb.hasArray()) {
-            this.base = bb.array();
-            this.address = ARRAY_BYTE_BASE_OFFSET;
-            this.size = bb.array().length;
-            this.reference = null;
-        }
-        else {
-            throw new IllegalArgumentException("Only the array-backed ByteBuffer or DirectBuffer are supported");
-        }
-    }
-
     /**
      * Create a MessageBuffer instance from an java heap array
      *
      * @param arr
+     * @param offset
+     * @param length
      */
-    MessageBuffer(byte[] arr)
+    MessageBuffer(byte[] arr, int offset, int length)
     {
         this.base = arr;
-        this.address = ARRAY_BYTE_BASE_OFFSET;
-        this.size = arr.length;
-        this.reference = null;
+        this.address = ARRAY_BYTE_BASE_OFFSET + offset;
+        this.size = length;
     }
 
-    MessageBuffer(Object base, long address, int length, ByteBuffer reference)
+    protected MessageBuffer(Object base, long address, int length)
     {
         this.base = base;
         this.address = address;
         this.size = length;
-        this.reference = reference;
     }
 
     /**
@@ -351,7 +253,7 @@ public MessageBuffer slice(int offset, int length)
         }
         else {
             checkArgument(offset + length <= size());
-            return new MessageBuffer(base, address + offset, length, reference);
+            return new MessageBuffer(base, address + offset, length);
         }
     }
 
@@ -411,7 +313,7 @@ public void getBytes(int index, int len, ByteBuffer dst)
         if (dst.remaining() < len) {
             throw new BufferOverflowException();
         }
-        ByteBuffer src = toByteBuffer(index, len);
+        ByteBuffer src = sliceAsByteBuffer(index, len);
         dst.put(src);
     }
 
@@ -499,15 +401,9 @@ else if (src.hasArray()) {
      * @param length
      * @return
      */
-    public ByteBuffer toByteBuffer(int index, int length)
+    public ByteBuffer sliceAsByteBuffer(int index, int length)
     {
-        if (hasArray()) {
-            return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length);
-        }
-        else {
-            assert (!isUniversalBuffer);
-            return DirectBufferAccess.newByteBuffer(address, index, length, reference);
-        }
+        return ByteBuffer.wrap((byte[]) base, (int) ((address - ARRAY_BYTE_BASE_OFFSET) + index), length);
     }
 
     /**
@@ -515,9 +411,9 @@ public ByteBuffer toByteBuffer(int index, int length)
      *
      * @return
      */
-    public ByteBuffer toByteBuffer()
+    public ByteBuffer sliceAsByteBuffer()
     {
-        return toByteBuffer(0, size());
+        return sliceAsByteBuffer(0, size());
     }
 
     /**
@@ -567,12 +463,6 @@ public int offset()
         }
     }
 
-    @Insecure
-    public ByteBuffer getReference()
-    {
-        return reference;
-    }
-
     /**
      * Copy this buffer contents to another MessageBuffer
      *
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
index 4fec0cd42..3f5d24976 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
@@ -27,19 +27,14 @@
 public class MessageBufferBE
         extends MessageBuffer
 {
-    MessageBufferBE(ByteBuffer bb)
+    MessageBufferBE(byte[] arr, int offset, int length)
     {
-        super(bb);
+        super(arr, offset, length);
     }
 
-    MessageBufferBE(byte[] arr)
+    private MessageBufferBE(Object base, long address, int length)
     {
-        super(arr);
-    }
-
-    private MessageBufferBE(Object base, long address, int length, ByteBuffer reference)
-    {
-        super(base, address, length, reference);
+        super(base, address, length);
     }
 
     @Override
@@ -50,7 +45,7 @@ public MessageBufferBE slice(int offset, int length)
         }
         else {
             checkArgument(offset + length <= size());
-            return new MessageBufferBE(base, address + offset, length, reference);
+            return new MessageBufferBE(base, address + offset, length);
         }
     }
 
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
index 54caa8838..d5b68c1a4 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
@@ -28,15 +28,18 @@
 public class MessageBufferU
         extends MessageBuffer
 {
-    public MessageBufferU(ByteBuffer bb)
+    private final ByteBuffer wrap;
+
+    MessageBufferU(byte[] arr, int offset, int length)
     {
-        super(null, 0L, bb.capacity(), bb.order(ByteOrder.BIG_ENDIAN));
-        checkNotNull(reference);
+        super(arr, offset, length);
+        this.wrap = ByteBuffer.wrap(arr, offset, length);
     }
 
-    MessageBufferU(byte[] arr)
+    private MessageBufferU(Object base, long address, int length, ByteBuffer wrap)
     {
-        this(ByteBuffer.wrap(arr));
+        super(base, address, length);
+        this.wrap = wrap;
     }
 
     @Override
@@ -48,9 +51,9 @@ public MessageBufferU slice(int offset, int length)
         else {
             checkArgument(offset + length <= size());
             try {
-                reference.position(offset);
-                reference.limit(offset + length);
-                return new MessageBufferU(reference.slice());
+                wrap.position(offset);
+                wrap.limit(offset + length);
+                return new MessageBufferU(base, address + offset, length, wrap.slice());
             }
             finally {
                 resetBufferPosition();
@@ -60,59 +63,59 @@ public MessageBufferU slice(int offset, int length)
 
     private void resetBufferPosition()
     {
-        reference.position(0);
-        reference.limit(size);
+        wrap.position(0);
+        wrap.limit(size);
     }
 
     @Override
     public byte getByte(int index)
     {
-        return reference.get(index);
+        return wrap.get(index);
     }
 
     @Override
     public boolean getBoolean(int index)
     {
-        return reference.get(index) != 0;
+        return wrap.get(index) != 0;
     }
 
     @Override
     public short getShort(int index)
     {
-        return reference.getShort(index);
+        return wrap.getShort(index);
     }
 
     @Override
     public int getInt(int index)
     {
-        return reference.getInt(index);
+        return wrap.getInt(index);
     }
 
     @Override
     public float getFloat(int index)
     {
-        return reference.getFloat(index);
+        return wrap.getFloat(index);
     }
 
     @Override
     public long getLong(int index)
     {
-        return reference.getLong(index);
+        return wrap.getLong(index);
     }
 
     @Override
     public double getDouble(int index)
     {
-        return reference.getDouble(index);
+        return wrap.getDouble(index);
     }
 
     @Override
     public void getBytes(int index, int len, ByteBuffer dst)
     {
         try {
-            reference.position(index);
-            reference.limit(index + len);
-            dst.put(reference);
+            wrap.position(index);
+            wrap.limit(index + len);
+            dst.put(wrap);
         }
         finally {
             resetBufferPosition();
@@ -122,52 +125,52 @@ public void getBytes(int index, int len, ByteBuffer dst)
     @Override
     public void putByte(int index, byte v)
     {
-        reference.put(index, v);
+        wrap.put(index, v);
     }
 
     @Override
     public void putBoolean(int index, boolean v)
     {
-        reference.put(index, v ? (byte) 1 : (byte) 0);
+        wrap.put(index, v ? (byte) 1 : (byte) 0);
     }
 
     @Override
     public void putShort(int index, short v)
     {
-        reference.putShort(index, v);
+        wrap.putShort(index, v);
     }
 
     @Override
     public void putInt(int index, int v)
     {
-        reference.putInt(index, v);
+        wrap.putInt(index, v);
     }
 
     @Override
     public void putFloat(int index, float v)
     {
-        reference.putFloat(index, v);
+        wrap.putFloat(index, v);
     }
 
     @Override
     public void putLong(int index, long l)
     {
-        reference.putLong(index, l);
+        wrap.putLong(index, l);
     }
 
     @Override
     public void putDouble(int index, double v)
     {
-        reference.putDouble(index, v);
+        wrap.putDouble(index, v);
     }
 
     @Override
-    public ByteBuffer toByteBuffer(int index, int length)
+    public ByteBuffer sliceAsByteBuffer(int index, int length)
     {
         try {
-            reference.position(index);
-            reference.limit(index + length);
-            return reference.slice();
+            wrap.position(index);
+            wrap.limit(index + length);
+            return wrap.slice();
         }
         finally {
             resetBufferPosition();
@@ -175,17 +178,17 @@ public ByteBuffer toByteBuffer(int index, int length)
     }
 
     @Override
-    public ByteBuffer toByteBuffer()
+    public ByteBuffer sliceAsByteBuffer()
     {
-        return toByteBuffer(0, size);
+        return sliceAsByteBuffer(0, size);
     }
 
     @Override
     public void getBytes(int index, byte[] dst, int dstOffset, int length)
     {
         try {
-            reference.position(index);
-            reference.get(dst, dstOffset, length);
+            wrap.position(index);
+            wrap.get(dst, dstOffset, length);
         }
         finally {
             resetBufferPosition();
@@ -205,8 +208,8 @@ public void putByteBuffer(int index, ByteBuffer src, int len)
             int prevSrcLimit = src.limit();
             try {
                 src.limit(src.position() + len);
-                reference.position(index);
-                reference.put(src);
+                wrap.position(index);
+                wrap.put(src);
             }
             finally {
                 src.limit(prevSrcLimit);
@@ -218,8 +221,8 @@ public void putByteBuffer(int index, ByteBuffer src, int len)
     public void putBytes(int index, byte[] src, int srcOffset, int length)
     {
         try {
-            reference.position(index);
-            reference.put(src, srcOffset, length);
+            wrap.position(index);
+            wrap.put(src, srcOffset, length);
         }
         finally {
             resetBufferPosition();
@@ -230,8 +233,8 @@ public void putBytes(int index, byte[] src, int srcOffset, int length)
     public void copyTo(int index, MessageBuffer dst, int offset, int length)
     {
         try {
-            reference.position(index);
-            dst.putByteBuffer(offset, reference, length);
+            wrap.position(index);
+            dst.putByteBuffer(offset, wrap, length);
         }
         finally {
             resetBufferPosition();
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
index d6f17c783..f29832b34 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
@@ -37,7 +37,7 @@ public OutputStreamBufferOutput(OutputStream out)
     public OutputStreamBufferOutput(OutputStream out, int bufferSize)
     {
         this.out = checkNotNull(out, "output is null");
-        this.buffer = MessageBuffer.newBuffer(bufferSize);
+        this.buffer = MessageBuffer.allocate(bufferSize);
     }
 
     /**
@@ -59,7 +59,7 @@ public MessageBuffer next(int mimimumSize)
             throws IOException
     {
         if (buffer.size() < mimimumSize) {
-            buffer = MessageBuffer.newBuffer(mimimumSize);
+            buffer = MessageBuffer.allocate(mimimumSize);
         }
         return buffer;
     }
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala
index 92103dc31..eb78432d2 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala
@@ -44,19 +44,4 @@ class ByteStringTest
     new
         MessageUnpacker(input).unpackString()
   }
-
-  "Unpacking a ByteString's ByteBuffer" should {
-    "fail with a regular MessageBuffer" in {
-
-      // can't demonstrate with new ByteBufferInput(byteString.asByteBuffer)
-      // as Travis tests run with JDK6 that picks up MessageBufferU
-      a[RuntimeException] shouldBe thrownBy(unpackString(new
-          MessageBuffer(byteString.asByteBuffer)))
-    }
-
-    "succeed with a MessageBufferU" in {
-      unpackString(new
-          MessageBufferU(byteString.asByteBuffer)) shouldBe unpackedString
-    }
-  }
 }
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
index b6ee7bf08..6333e381c 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala
@@ -97,11 +97,6 @@ class MessageBufferInputTest
           ArrayBufferInput(_))
     }
 
-    "support ByteBuffers" in {
-      runTest(b => new
-          ByteBufferInput(b.toByteBuffer))
-    }
-
     "support InputStreams" taggedAs ("is") in {
       runTest(b =>
         new
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala
index db4dec659..75ef00a11 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferTest.scala
@@ -30,14 +30,13 @@ class MessageBufferTest
   "MessageBuffer" should {
 
     "check buffer type" in {
-      val b = MessageBuffer.newBuffer(0)
+      val b = MessageBuffer.allocate(0)
       info(s"MessageBuffer type: ${b.getClass.getName}")
     }
 
     "wrap ByteBuffer considering position and remaining values" taggedAs ("wrap-bb") in {
       val d = Array[Byte](10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
-      val subset = ByteBuffer.wrap(d, 2, 2)
-      val mb = MessageBuffer.wrap(subset)
+      val mb = MessageBuffer.wrap(d, 2, 2)
       mb.getByte(0) shouldBe 12
       mb.size() shouldBe 2
     }
@@ -47,8 +46,7 @@ class MessageBufferTest
       val N = 1000000
       val M = 64 * 1024 * 1024
 
-      val ub = MessageBuffer.newBuffer(M)
-      val ud = MessageBuffer.newDirectBuffer(M)
+      val ub = MessageBuffer.allocate(M)
       val hb = ByteBuffer.allocate(M)
       val db = ByteBuffer.allocateDirect(M)
 
@@ -84,14 +82,6 @@ class MessageBufferTest
           }
         }
 
-        block("unsafe direct") {
-          var i = 0
-          while (i < N) {
-            ud.getInt((i * 4) % M)
-            i += 1
-          }
-        }
-
         block("allocate") {
           var i = 0
           while (i < N) {
@@ -118,14 +108,6 @@ class MessageBufferTest
           }
         }
 
-        block("unsafe direct") {
-          var i = 0
-          while (i < N) {
-            ud.getInt((rs(i) * 4) % M)
-            i += 1
-          }
-        }
-
         block("allocate") {
           var i = 0
           while (i < N) {
@@ -146,11 +128,9 @@ class MessageBufferTest
 
     "convert to ByteBuffer" in {
       for (t <- Seq(
-        MessageBuffer.newBuffer(10),
-        MessageBuffer.newDirectBuffer(10),
-        MessageBuffer.newOffHeapBuffer(10))
+        MessageBuffer.allocate(10))
       ) {
-        val bb = t.toByteBuffer
+        val bb = t.sliceAsByteBuffer
         bb.position shouldBe 0
         bb.limit shouldBe 10
         bb.capacity shouldBe 10
@@ -159,9 +139,7 @@ class MessageBufferTest
 
     "put ByteBuffer on itself" in {
       for (t <- Seq(
-        MessageBuffer.newBuffer(10),
-        MessageBuffer.newDirectBuffer(10),
-        MessageBuffer.newOffHeapBuffer(10))
+        MessageBuffer.allocate(10))
       ) {
         val b = Array[Byte](0x02, 0x03)
         val srcArray = ByteBuffer.wrap(b)
@@ -190,13 +168,6 @@ class MessageBufferTest
         Array[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07)
       }
 
-      def prepareDirectBuffer : ByteBuffer = {
-        val directBuffer = ByteBuffer.allocateDirect(prepareBytes.length)
-        directBuffer.put(prepareBytes)
-        directBuffer.flip
-        directBuffer
-      }
-
       def checkSliceAndCopyTo(srcBuffer: MessageBuffer, dstBuffer: MessageBuffer) = {
         val sliced = srcBuffer.slice(2, 5)
 
@@ -220,8 +191,6 @@ class MessageBufferTest
       }
 
       checkSliceAndCopyTo(MessageBuffer.wrap(prepareBytes), MessageBuffer.wrap(prepareBytes))
-      checkSliceAndCopyTo(MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)), MessageBuffer.wrap(ByteBuffer.wrap(prepareBytes)))
-      checkSliceAndCopyTo(MessageBuffer.wrap(prepareDirectBuffer), MessageBuffer.wrap(prepareDirectBuffer))
     }
   }
 }

From e6811be1b63932ec716cb125fe0c8892ed999c20 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Fri, 25 Dec 2015 16:03:35 +0900
Subject: [PATCH 54/99] MessageBuffer is now always safe to get internal array,
 and exposing base and address become unnecessary

---
 .../java/org/msgpack/core/MessagePacker.java  |  4 +--
 .../org/msgpack/core/MessageUnpacker.java     |  9 +++---
 .../core/{annotations => }/Nullable.java      |  4 +--
 .../java/org/msgpack/core/Preconditions.java  |  1 -
 .../msgpack/core/annotations/Insecure.java    | 23 -------------
 .../msgpack/core/buffer/MessageBuffer.java    | 32 ++-----------------
 .../msgpack/core/buffer/MessageBufferU.java   |  5 ++-
 .../core/buffer/OutputStreamBufferOutput.java |  2 +-
 8 files changed, 16 insertions(+), 64 deletions(-)
 rename msgpack-core/src/main/java/org/msgpack/core/{annotations => }/Nullable.java (91%)
 delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
index 7c71b6807..b3fcff5a8 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
@@ -505,7 +505,7 @@ else if (s.length() < (1 << 8)) {
                     }
                     // move 1 byte backward to expand 3-byte header region to 3 bytes
                     buffer.putBytes(position + 3,
-                            buffer.getArray(), buffer.offset() + position + 2, written);
+                            buffer.array(), buffer.arrayOffset() + position + 2, written);
                     // write 3-byte header header
                     buffer.putByte(position++, STR16);
                     buffer.putShort(position, (short) written);
@@ -534,7 +534,7 @@ else if (s.length() < (1 << 16)) {
                     }
                     // move 2 bytes backward to expand 3-byte header region to 5 bytes
                     buffer.putBytes(position + 5,
-                            buffer.getArray(), buffer.offset() + position + 3, written);
+                            buffer.array(), buffer.arrayOffset() + position + 3, written);
                     // write 3-byte header header
                     buffer.putByte(position++, STR32);
                     buffer.putInt(position, written);
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 2e00a5bc3..6ef5901f5 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -255,8 +255,8 @@ private MessageBuffer readCastBuffer(int length)
 
             // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
             //      add copy method to MessageBuffer to solve this issue.
-            castBuffer.putBytes(0, buffer.getArray(), buffer.offset() + position, remaining);
-            castBuffer.putBytes(remaining, next.getArray(), next.offset(), length - remaining);
+            castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining);
+            castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining);
 
             totalReadBytes += buffer.size();
 
@@ -1106,9 +1106,8 @@ private void handleCoderError(CoderResult cr)
     private String decodeStringFastPath(int length)
     {
         if (actionOnMalformedString == CodingErrorAction.REPLACE &&
-                actionOnUnmappableString == CodingErrorAction.REPLACE &&
-                buffer.hasArray()) {
-            String s = new String(buffer.getArray(), buffer.offset() + position, length, MessagePack.UTF8);
+                actionOnUnmappableString == CodingErrorAction.REPLACE) {
+            String s = new String(buffer.array(), buffer.arrayOffset() + position, length, MessagePack.UTF8);
             position += length;
             return s;
         }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java b/msgpack-core/src/main/java/org/msgpack/core/Nullable.java
similarity index 91%
rename from msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java
rename to msgpack-core/src/main/java/org/msgpack/core/Nullable.java
index 9e7c94fab..b2e7585a5 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/Nullable.java
@@ -13,11 +13,11 @@
 //    See the License for the specific language governing permissions and
 //    limitations under the License.
 //
-package org.msgpack.core.annotations;
+package org.msgpack.core;
 
 /**
  * Annotates a field which can be null
  */
-public @interface Nullable
+@interface Nullable
 {
 }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java b/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java
index e44d97d15..d8f43bcb7 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java
@@ -31,7 +31,6 @@
  */
 package org.msgpack.core;
 
-import org.msgpack.core.annotations.Nullable;
 import org.msgpack.core.annotations.VisibleForTesting;
 
 /**
diff --git a/msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java b/msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java
deleted file mode 100644
index c8678ae41..000000000
--- a/msgpack-core/src/main/java/org/msgpack/core/annotations/Insecure.java
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// MessagePack for Java
-//
-//    Licensed under the Apache License, Version 2.0 (the "License");
-//    you may not use this file except in compliance with the License.
-//    You may obtain a copy of the License at
-//
-//        http://www.apache.org/licenses/LICENSE-2.0
-//
-//    Unless required by applicable law or agreed to in writing, software
-//    distributed under the License is distributed on an "AS IS" BASIS,
-//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//    See the License for the specific language governing permissions and
-//    limitations under the License.
-//
-package org.msgpack.core.annotations;
-
-/**
- * Annotates a code which must be used carefully.
- */
-public @interface Insecure
-{
-}
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
index e2258265e..d4d5f2238 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
@@ -15,7 +15,6 @@
 //
 package org.msgpack.core.buffer;
 
-import org.msgpack.core.annotations.Insecure;
 import sun.misc.Unsafe;
 
 import java.lang.reflect.Constructor;
@@ -428,39 +427,14 @@ public byte[] toByteArray()
         return b;
     }
 
-    @Insecure
-    public boolean hasArray()
-    {
-        return base instanceof byte[];
-    }
-
-    @Insecure
-    public byte[] getArray()
+    public byte[] array()
     {
         return (byte[]) base;
     }
 
-    @Insecure
-    public Object getBase()
-    {
-        return base;
-    }
-
-    @Insecure
-    public long getAddress()
+    public int arrayOffset()
     {
-        return address;
-    }
-
-    @Insecure
-    public int offset()
-    {
-        if (hasArray()) {
-            return (int) address - ARRAY_BYTE_BASE_OFFSET;
-        }
-        else {
-            return 0;
-        }
+        return (int) address - ARRAY_BYTE_BASE_OFFSET;
     }
 
     /**
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
index d5b68c1a4..151b6cd2e 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java
@@ -33,7 +33,10 @@ public class MessageBufferU
     MessageBufferU(byte[] arr, int offset, int length)
     {
         super(arr, offset, length);
-        this.wrap = ByteBuffer.wrap(arr, offset, length);
+        ByteBuffer bb = ByteBuffer.wrap(arr);
+        bb.position(offset);
+        bb.limit(offset + length);
+        this.wrap = bb.slice();
     }
 
     private MessageBufferU(Object base, long address, int length, ByteBuffer wrap)
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
index f29832b34..08fd3960b 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/OutputStreamBufferOutput.java
@@ -68,7 +68,7 @@ public MessageBuffer next(int mimimumSize)
     public void writeBuffer(int length)
             throws IOException
     {
-        write(buffer.getArray(), buffer.offset(), length);
+        write(buffer.array(), buffer.arrayOffset(), length);
     }
 
     @Override

From 4098489fcaf60307315ddaf9897ee7a6097e1a25 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Fri, 25 Dec 2015 16:06:29 +0900
Subject: [PATCH 55/99] Remove unused import

---
 .../test/java/org/msgpack/core/example/MessagePackExample.java   | 1 -
 1 file changed, 1 deletion(-)

diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
index d7dffe64b..9a8242591 100644
--- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
+++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java
@@ -32,7 +32,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
-import java.nio.ByteBuffer;
 import java.nio.charset.CodingErrorAction;
 
 /**

From 6390efce5b1cd0ee380b1f74551d8cbd9e6ff469 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Sat, 26 Dec 2015 18:46:29 +0900
Subject: [PATCH 56/99] renamed
 org.msgpack.jackson.dataformat.MessagePackFactory to MessagePackFormatFactory
 to avoid name confusion

---
 msgpack-jackson/README.md                     |  4 +--
 ...ory.java => MessagePackFormatFactory.java} |  2 +-
 .../ExampleOfTypeInformationSerDe.java        |  2 +-
 .../MessagePackDataformatTestBase.java        |  4 +--
 ...java => MessagePackFormatFactoryTest.java} |  2 +-
 .../dataformat/MessagePackGeneratorTest.java  | 12 +++----
 .../dataformat/MessagePackParserTest.java     | 32 +++++++++----------
 ...gePackDataformatHugeDataBenchmarkTest.java |  6 ++--
 ...essagePackDataformatPojoBenchmarkTest.java |  6 ++--
 9 files changed, 35 insertions(+), 35 deletions(-)
 rename msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/{MessagePackFactory.java => MessagePackFormatFactory.java} (98%)
 rename msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/{MessagePackFactoryTest.java => MessagePackFormatFactoryTest.java} (97%)

diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md
index 55ed19233..51435b401 100644
--- a/msgpack-jackson/README.md
+++ b/msgpack-jackson/README.md
@@ -29,10 +29,10 @@ dependencies {
 
 ## Usage
 
-Only thing you need to do is to instantiate MessagePackFactory and pass it to the constructor of ObjectMapper.
+Only thing you need to do is to instantiate MessagePackFormatFactory and pass it to the constructor of ObjectMapper.
 
 ```
-  ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+  ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
   ExamplePojo orig = new ExamplePojo("komamitsu");
   byte[] bytes = objectMapper.writeValueAsBytes(orig);
   ExamplePojo value = objectMapper.readValue(bytes, ExamplePojo.class);
diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java
similarity index 98%
rename from msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java
rename to msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java
index ff7aa373f..1082e5770 100644
--- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java
+++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java
@@ -30,7 +30,7 @@
 import java.io.Writer;
 import java.util.Arrays;
 
-public class MessagePackFactory
+public class MessagePackFormatFactory
         extends JsonFactory
 {
     private static final long serialVersionUID = 2578263992015504347L;
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java
index 5414b0bdc..6a211b3ae 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java
@@ -151,7 +151,7 @@ public void test()
             objectContainer.getObjects().put("pi", pi);
         }
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         byte[] bytes = objectMapper.writeValueAsBytes(objectContainer);
         ObjectContainer restored = objectMapper.readValue(bytes, ObjectContainer.class);
 
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java
index 1d5156adc..c9692ebf9 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java
@@ -35,7 +35,7 @@
 
 public class MessagePackDataformatTestBase
 {
-    protected MessagePackFactory factory;
+    protected MessagePackFormatFactory factory;
     protected ByteArrayOutputStream out;
     protected ByteArrayInputStream in;
     protected ObjectMapper objectMapper;
@@ -47,7 +47,7 @@ public class MessagePackDataformatTestBase
     @Before
     public void setup()
     {
-        factory = new MessagePackFactory();
+        factory = new MessagePackFormatFactory();
         objectMapper = new ObjectMapper(factory);
         out = new ByteArrayOutputStream();
         in = new ByteArrayInputStream(new byte[4096]);
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java
similarity index 97%
rename from msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java
rename to msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java
index 25180f784..f7e5fe045 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java
@@ -24,7 +24,7 @@
 
 import static org.junit.Assert.assertEquals;
 
-public class MessagePackFactoryTest
+public class MessagePackFormatFactoryTest
         extends MessagePackDataformatTestBase
 {
     @Test
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
index b88d0d645..de58e4a1a 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
@@ -230,7 +230,7 @@ else if (key.equals("num")) {
     public void testMessagePackGeneratorDirectly()
             throws Exception
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         File tempFile = createTempFile();
 
         JsonGenerator generator = messagePackFactory.createGenerator(tempFile, JsonEncoding.UTF8);
@@ -257,7 +257,7 @@ public void testMessagePackGeneratorDirectly()
     public void testWritePrimitives()
             throws Exception
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         File tempFile = createTempFile();
 
         JsonGenerator generator = messagePackFactory.createGenerator(tempFile, JsonEncoding.UTF8);
@@ -280,7 +280,7 @@ public void testWritePrimitives()
     public void testBigDecimal()
             throws IOException
     {
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
 
         {
             double d0 = 1.23456789;
@@ -328,7 +328,7 @@ public void testEnableFeatureAutoCloseTarget()
             throws IOException
     {
         OutputStream out = createTempFileOutputStream();
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         ObjectMapper objectMapper = new ObjectMapper(messagePackFactory);
         List integers = Arrays.asList(1);
         objectMapper.writeValue(out, integers);
@@ -341,7 +341,7 @@ public void testDisableFeatureAutoCloseTarget()
     {
         File tempFile = createTempFile();
         OutputStream out = new FileOutputStream(tempFile);
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory();
         ObjectMapper objectMapper = new ObjectMapper(messagePackFactory);
         objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
         List integers = Arrays.asList(1);
@@ -363,7 +363,7 @@ public void testWritePrimitiveObjectViaObjectMapper()
         File tempFile = createTempFile();
         OutputStream out = new FileOutputStream(tempFile);
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
         objectMapper.writeValue(out, 1);
         objectMapper.writeValue(out, "two");
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java
index 96af2de32..3321110d4 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java
@@ -288,7 +288,7 @@ else if (k.equals("child_map_age")) {
     public void testMessagePackParserDirectly()
             throws IOException
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory factory = new MessagePackFormatFactory();
         File tempFile = File.createTempFile("msgpackTest", "msgpack");
         tempFile.deleteOnExit();
 
@@ -301,7 +301,7 @@ public void testMessagePackParserDirectly()
         packer.packFloat(1.0f);
         packer.close();
 
-        JsonParser parser = messagePackFactory.createParser(tempFile);
+        JsonParser parser = factory.createParser(tempFile);
         assertTrue(parser instanceof MessagePackParser);
 
         JsonToken jsonToken = parser.nextToken();
@@ -354,7 +354,7 @@ public void testMessagePackParserDirectly()
     public void testReadPrimitives()
             throws Exception
     {
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory factory = new MessagePackFormatFactory();
         File tempFile = createTempFile();
 
         FileOutputStream out = new FileOutputStream(tempFile);
@@ -367,7 +367,7 @@ public void testReadPrimitives()
         packer.writePayload(bytes);
         packer.close();
 
-        JsonParser parser = messagePackFactory.createParser(new FileInputStream(tempFile));
+        JsonParser parser = factory.createParser(new FileInputStream(tempFile));
         assertEquals(JsonToken.VALUE_STRING, parser.nextToken());
         assertEquals("foo", parser.getText());
         assertEquals(JsonToken.VALUE_NUMBER_FLOAT, parser.nextToken());
@@ -396,7 +396,7 @@ public void testBigDecimal()
         packer.packDouble(Double.MIN_NORMAL);
         packer.flush();
 
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
         mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
         List objects = mapper.readValue(out.toByteArray(), new TypeReference>() {});
         assertEquals(5, objects.size());
@@ -431,9 +431,9 @@ public void testEnableFeatureAutoCloseSource()
             throws Exception
     {
         File tempFile = createTestFile();
-        MessagePackFactory messagePackFactory = new MessagePackFactory();
+        MessagePackFormatFactory factory = new MessagePackFormatFactory();
         FileInputStream in = new FileInputStream(tempFile);
-        ObjectMapper objectMapper = new ObjectMapper(messagePackFactory);
+        ObjectMapper objectMapper = new ObjectMapper(factory);
         objectMapper.readValue(in, new TypeReference>() {});
         objectMapper.readValue(in, new TypeReference>() {});
     }
@@ -444,7 +444,7 @@ public void testDisableFeatureAutoCloseSource()
     {
         File tempFile = createTestFile();
         FileInputStream in = new FileInputStream(tempFile);
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
         objectMapper.readValue(in, new TypeReference>() {});
         objectMapper.readValue(in, new TypeReference>() {});
@@ -456,7 +456,7 @@ public void testParseBigDecimal()
     {
         ArrayList list = new ArrayList();
         list.add(new BigDecimal(Long.MAX_VALUE));
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         byte[] bytes = objectMapper.writeValueAsBytes(list);
 
         ArrayList result = objectMapper.readValue(
@@ -481,7 +481,7 @@ public void testReadPrimitiveObjectViaObjectMapper()
         packer.close();
 
         FileInputStream in = new FileInputStream(tempFile);
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
         assertEquals("foo", objectMapper.readValue(in, new TypeReference() {}));
         long l = objectMapper.readValue(in, new TypeReference() {});
@@ -511,7 +511,7 @@ public void testBinaryKey()
         packer.packLong(42);
         packer.close();
 
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
         Map object = mapper.readValue(new FileInputStream(tempFile), new TypeReference>() {});
         assertEquals(2, object.size());
         assertEquals(3.14, object.get("foo"));
@@ -533,7 +533,7 @@ public void testBinaryKeyInNestedObject()
         packer.packInt(1);
         packer.close();
 
-        ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory());
         List objects = mapper.readValue(out.toByteArray(), new TypeReference>() {});
         assertEquals(2, objects.size());
         @SuppressWarnings(value = "unchecked")
@@ -555,7 +555,7 @@ public void testByteArrayKey()
         messagePacker.packBinaryHeader(1).writePayload(k1).packInt(3);
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(byte[].class, new KeyDeserializer()
         {
@@ -592,7 +592,7 @@ public void testIntegerKey()
         }
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(Integer.class, new KeyDeserializer()
         {
@@ -623,7 +623,7 @@ public void testFloatKey()
         }
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(Float.class, new KeyDeserializer()
         {
@@ -653,7 +653,7 @@ public void testBooleanKey()
         messagePacker.packBoolean(false).packInt(3);
         messagePacker.close();
 
-        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory());
         SimpleModule module = new SimpleModule();
         module.addKeyDeserializer(Boolean.class, new KeyDeserializer()
         {
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java
index b3a159111..aaf828439 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java
@@ -20,7 +20,7 @@
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Test;
-import org.msgpack.jackson.dataformat.MessagePackFactory;
+import org.msgpack.jackson.dataformat.MessagePackFormatFactory;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -34,7 +34,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
     private final ObjectMapper origObjectMapper = new ObjectMapper();
-    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory());
     private static final List value;
     private static final byte[] packedByOriginal;
     private static final byte[] packedByMsgPack;
@@ -61,7 +61,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest
         packedByOriginal = bytes;
 
         try {
-            bytes = new ObjectMapper(new MessagePackFactory()).writeValueAsBytes(value);
+            bytes = new ObjectMapper(new MessagePackFormatFactory()).writeValueAsBytes(value);
         }
         catch (JsonProcessingException e) {
             e.printStackTrace();
diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index de2118508..33c5f024c 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -19,7 +19,7 @@
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.Test;
-import org.msgpack.jackson.dataformat.MessagePackFactory;
+import org.msgpack.jackson.dataformat.MessagePackFormatFactory;
 import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo;
 import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit;
 
@@ -40,11 +40,11 @@ public class MessagePackDataformatPojoBenchmarkTest
     private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
     private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
     private final ObjectMapper origObjectMapper = new ObjectMapper();
-    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory());
 
     static {
         final ObjectMapper origObjectMapper = new ObjectMapper();
-        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory());
 
         for (int i = 0; i < LOOP_MAX; i++) {
             NormalPojo pojo = new NormalPojo();

From 9eff0cac5a2099e7c35f2768ef9b744e7025fe84 Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Sun, 27 Dec 2015 12:58:18 +0900
Subject: [PATCH 57/99] optimized slightly MessageUnpacker.readCastBuffer

---
 .../org/msgpack/core/MessageUnpacker.java     | 26 ++++++++++++-------
 .../core/buffer/InputStreamBufferInput.java   |  2 +-
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 6ef5901f5..4dcc69e80 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -253,18 +253,26 @@ private MessageBuffer readCastBuffer(int length)
                 throw new MessageInsufficientBufferException();
             }
 
-            // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
-            //      add copy method to MessageBuffer to solve this issue.
-            castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining);
-            castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining);
-
             totalReadBytes += buffer.size();
 
-            buffer = next;
-            position = length - remaining;
-            readCastBufferPosition = 0;
+            if (remaining > 0) {
+                // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer.
+                //      add copy method to MessageBuffer to solve this issue.
+                castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining);
+                castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining);
+
+                buffer = next;
+                position = length - remaining;
+                readCastBufferPosition = 0;
 
-            return castBuffer;
+                return castBuffer;
+            }
+            else {
+                buffer = next;
+                position = length;
+                readCastBufferPosition = 0;
+                return buffer;
+            }
         }
     }
 
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java
index ad8aa462f..d605fec3a 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/InputStreamBufferInput.java
@@ -76,7 +76,7 @@ public MessageBuffer next()
         if (readLen == -1) {
             return null;
         }
-        return MessageBuffer.wrap(buffer).slice(0, readLen);
+        return MessageBuffer.wrap(buffer, 0, readLen);
     }
 
     @Override

From ab592c88de05f0bce33124cae8d040b63343257c Mon Sep 17 00:00:00 2001
From: Sadayuki Furuhashi 
Date: Sun, 27 Dec 2015 13:14:25 +0900
Subject: [PATCH 58/99] Gave up repeatable deserialization

Adding support for repeatable to castBuffer seems hard without
performance impact. For now, here removes repeatable read support.
---
 .../org/msgpack/core/MessageUnpacker.java     | 180 ++++--------------
 1 file changed, 38 insertions(+), 142 deletions(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index 4dcc69e80..ab7b3e496 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -118,11 +118,6 @@ public class MessageUnpacker
      */
     private StringBuilder decodeStringBuffer;
 
-    /**
-     * For decoding String in unpackString.
-     */
-    private int readingRawRemaining = 0;
-
     /**
      * For decoding String in unpackString.
      */
@@ -196,7 +191,6 @@ public MessageBufferInput reset(MessageBufferInput in)
         this.buffer = EMPTY_BUFFER;
         this.position = 0;
         this.totalReadBytes = 0;
-        this.readingRawRemaining = 0;
         // No need to initialize the already allocated string decoder here since we can reuse it.
 
         return old;
@@ -207,24 +201,6 @@ public long getTotalReadBytes()
         return totalReadBytes + position;
     }
 
-    private byte getHeadByte()
-            throws IOException
-    {
-        byte b = headByte;
-        if (b == HEAD_BYTE_REQUIRED) {
-            b = headByte = readByte();
-            if (b == HEAD_BYTE_REQUIRED) {
-                throw new MessageNeverUsedFormatException("Encountered 0xC1 \"NEVER_USED\" byte");
-            }
-        }
-        return b;
-    }
-
-    private void resetHeadByte()
-    {
-        headByte = HEAD_BYTE_REQUIRED;
-    }
-
     private void nextBuffer()
             throws IOException
     {
@@ -291,7 +267,7 @@ private static int utf8MultibyteCharacterSize(byte firstByte)
     public boolean hasNext()
             throws IOException
     {
-        if (buffer.size() <= position) {
+        while (buffer.size() <= position) {
             MessageBuffer next = in.next();
             if (next == null) {
                 return false;
@@ -316,13 +292,12 @@ public boolean hasNext()
     public MessageFormat getNextFormat()
             throws IOException
     {
-        try {
-            byte b = getHeadByte();
-            return MessageFormat.valueOf(b);
-        }
-        catch (MessageNeverUsedFormatException ex) {
-            return MessageFormat.NEVER_USED;
+        // makes sure that buffer has at leat 1 byte
+        if (!hasNext()) {
+            throw new MessageInsufficientBufferException();
         }
+        byte b = buffer.getByte(position);
+        return MessageFormat.valueOf(b);
     }
 
     /**
@@ -395,9 +370,8 @@ public void skipValue()
     {
         int remainingValues = 1;
         while (remainingValues > 0) {
-            byte b = getHeadByte();
+            byte b = readByte();
             MessageFormat f = MessageFormat.valueOf(b);
-            resetHeadByte();
             switch (f) {
                 case POSFIXINT:
                 case NEGFIXINT:
@@ -643,9 +617,8 @@ public Variable unpackValue(Variable var)
     public void unpackNil()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (b == Code.NIL) {
-            resetHeadByte();
             return;
         }
         throw unexpected("Nil", b);
@@ -654,13 +627,11 @@ public void unpackNil()
     public boolean unpackBoolean()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (b == Code.FALSE) {
-            resetHeadByte();
             return false;
         }
         else if (b == Code.TRUE) {
-            resetHeadByte();
             return true;
         }
         throw unexpected("boolean", b);
@@ -669,61 +640,52 @@ else if (b == Code.TRUE) {
     public byte unpackByte()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 if (u8 < (byte) 0) {
                     throw overflowU8(u8);
                 }
                 return u8;
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 if (u16 < 0 || u16 > Byte.MAX_VALUE) {
                     throw overflowU16(u16);
                 }
                 return (byte) u16;
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0 || u32 > Byte.MAX_VALUE) {
                     throw overflowU32(u32);
                 }
                 return (byte) u32;
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L || u64 > Byte.MAX_VALUE) {
                     throw overflowU64(u64);
                 }
                 return (byte) u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 if (i16 < Byte.MIN_VALUE || i16 > Byte.MAX_VALUE) {
                     throw overflowI16(i16);
                 }
                 return (byte) i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 if (i32 < Byte.MIN_VALUE || i32 > Byte.MAX_VALUE) {
                     throw overflowI32(i32);
                 }
                 return (byte) i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 if (i64 < Byte.MIN_VALUE || i64 > Byte.MAX_VALUE) {
                     throw overflowI64(i64);
                 }
@@ -735,32 +697,27 @@ public byte unpackByte()
     public short unpackShort()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return (short) b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return (short) (u8 & 0xff);
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 if (u16 < (short) 0) {
                     throw overflowU16(u16);
                 }
                 return u16;
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0 || u32 > Short.MAX_VALUE) {
                     throw overflowU32(u32);
                 }
                 return (short) u32;
             case Code.UINT64: // unsigned int 64
-                resetHeadByte();
                 long u64 = readLong();
                 if (u64 < 0L || u64 > Short.MAX_VALUE) {
                     throw overflowU64(u64);
@@ -768,22 +725,18 @@ public short unpackShort()
                 return (short) u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return (short) i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 if (i32 < Short.MIN_VALUE || i32 > Short.MAX_VALUE) {
                     throw overflowI32(i32);
                 }
                 return (short) i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 if (i64 < Short.MIN_VALUE || i64 > Short.MAX_VALUE) {
                     throw overflowI64(i64);
                 }
@@ -795,49 +748,40 @@ public short unpackShort()
     public int unpackInt()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return (int) b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return u8 & 0xff;
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 return u16 & 0xffff;
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
                 if (u32 < 0) {
                     throw overflowU32(u32);
                 }
-                resetHeadByte();
                 return u32;
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L || u64 > (long) Integer.MAX_VALUE) {
                     throw overflowU64(u64);
                 }
                 return (int) u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 return i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 if (i64 < (long) Integer.MIN_VALUE || i64 > (long) Integer.MAX_VALUE) {
                     throw overflowI64(i64);
                 }
@@ -849,23 +793,19 @@ public int unpackInt()
     public long unpackLong()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return (long) b;
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return (long) (u8 & 0xff);
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 return (long) (u16 & 0xffff);
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0) {
                     return (long) (u32 & 0x7fffffff) + 0x80000000L;
                 }
@@ -874,26 +814,21 @@ public long unpackLong()
                 }
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L) {
                     throw overflowU64(u64);
                 }
                 return u64;
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return (long) i8;
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return (long) i16;
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 return (long) i32;
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 return i64;
         }
         throw unexpected("Integer", b);
@@ -902,23 +837,19 @@ public long unpackLong()
     public BigInteger unpackBigInteger()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixInt(b)) {
-            resetHeadByte();
             return BigInteger.valueOf((long) b);
         }
         switch (b) {
             case Code.UINT8: // unsigned int 8
                 byte u8 = readByte();
-                resetHeadByte();
                 return BigInteger.valueOf((long) (u8 & 0xff));
             case Code.UINT16: // unsigned int 16
                 short u16 = readShort();
-                resetHeadByte();
                 return BigInteger.valueOf((long) (u16 & 0xffff));
             case Code.UINT32: // unsigned int 32
                 int u32 = readInt();
-                resetHeadByte();
                 if (u32 < 0) {
                     return BigInteger.valueOf((long) (u32 & 0x7fffffff) + 0x80000000L);
                 }
@@ -927,7 +858,6 @@ public BigInteger unpackBigInteger()
                 }
             case Code.UINT64: // unsigned int 64
                 long u64 = readLong();
-                resetHeadByte();
                 if (u64 < 0L) {
                     BigInteger bi = BigInteger.valueOf(u64 + Long.MAX_VALUE + 1L).setBit(63);
                     return bi;
@@ -937,19 +867,15 @@ public BigInteger unpackBigInteger()
                 }
             case Code.INT8: // signed int 8
                 byte i8 = readByte();
-                resetHeadByte();
                 return BigInteger.valueOf((long) i8);
             case Code.INT16: // signed int 16
                 short i16 = readShort();
-                resetHeadByte();
                 return BigInteger.valueOf((long) i16);
             case Code.INT32: // signed int 32
                 int i32 = readInt();
-                resetHeadByte();
                 return BigInteger.valueOf((long) i32);
             case Code.INT64: // signed int 64
                 long i64 = readLong();
-                resetHeadByte();
                 return BigInteger.valueOf(i64);
         }
         throw unexpected("Integer", b);
@@ -958,15 +884,13 @@ public BigInteger unpackBigInteger()
     public float unpackFloat()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         switch (b) {
             case Code.FLOAT32: // float
                 float fv = readFloat();
-                resetHeadByte();
                 return fv;
             case Code.FLOAT64: // double
                 double dv = readDouble();
-                resetHeadByte();
                 return (float) dv;
         }
         throw unexpected("Float", b);
@@ -975,15 +899,13 @@ public float unpackFloat()
     public double unpackDouble()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         switch (b) {
             case Code.FLOAT32: // float
                 float fv = readFloat();
-                resetHeadByte();
                 return (double) fv;
             case Code.FLOAT64: // double
                 double dv = readDouble();
-                resetHeadByte();
                 return dv;
         }
         throw unexpected("Float", b);
@@ -1005,35 +927,29 @@ private void resetDecoder()
         decodeStringBuffer = new StringBuilder();
     }
 
-    /**
-     * This method is not repeatable.
-     */
     public String unpackString()
             throws IOException
     {
-        if (readingRawRemaining == 0) {
-            int len = unpackRawStringHeader();
-            if (len == 0) {
-                return EMPTY_STRING;
-            }
-            if (len > stringSizeLimit) {
-                throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len);
-            }
-            if (buffer.size() - position >= len) {
-                return decodeStringFastPath(len);
-            }
-            readingRawRemaining = len;
-            resetDecoder();
+        int len = unpackRawStringHeader();
+        if (len == 0) {
+            return EMPTY_STRING;
+        }
+        if (len > stringSizeLimit) {
+            throw new MessageSizeException(String.format("cannot unpack a String of size larger than %,d: %,d", stringSizeLimit, len), len);
+        }
+        if (buffer.size() - position >= len) {
+            return decodeStringFastPath(len);
         }
 
-        assert (decoder != null);
+        resetDecoder();
 
         try {
-            while (readingRawRemaining > 0) {
+            int rawRemaining = len;
+            while (rawRemaining > 0) {
                 int bufferRemaining = buffer.size() - position;
-                if (bufferRemaining >= readingRawRemaining) {
-                    decodeStringBuffer.append(decodeStringFastPath(readingRawRemaining));
-                    readingRawRemaining = 0;
+                if (bufferRemaining >= rawRemaining) {
+                    decodeStringBuffer.append(decodeStringFastPath(rawRemaining));
+                    rawRemaining = 0;
                     break;
                 }
                 else if (bufferRemaining == 0) {
@@ -1047,7 +963,7 @@ else if (bufferRemaining == 0) {
                     CoderResult cr = decoder.decode(bb, decodeBuffer, false);
                     int readLen = bb.position() - bbStartPosition;
                     position += readLen;
-                    readingRawRemaining -= readLen;
+                    rawRemaining -= readLen;
                     decodeStringBuffer.append(decodeBuffer.flip());
 
                     if (cr.isError()) {
@@ -1090,7 +1006,7 @@ else if (bufferRemaining == 0) {
                                 throw new MessageFormatException("Unexpected UTF-8 multibyte sequence", ex);
                             }
                         }
-                        readingRawRemaining -= multiByteBuffer.limit();
+                        rawRemaining -= multiByteBuffer.limit();
                         decodeStringBuffer.append(decodeBuffer.flip());
                     }
                 }
@@ -1139,20 +1055,17 @@ private String decodeStringFastPath(int length)
     public int unpackArrayHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedArray(b)) { // fixarray
-            resetHeadByte();
             return b & 0x0f;
         }
         switch (b) {
             case Code.ARRAY16: { // array 16
                 int len = readNextLength16();
-                resetHeadByte();
                 return len;
             }
             case Code.ARRAY32: { // array 32
                 int len = readNextLength32();
-                resetHeadByte();
                 return len;
             }
         }
@@ -1162,20 +1075,17 @@ public int unpackArrayHeader()
     public int unpackMapHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedMap(b)) { // fixmap
-            resetHeadByte();
             return b & 0x0f;
         }
         switch (b) {
             case Code.MAP16: { // map 16
                 int len = readNextLength16();
-                resetHeadByte();
                 return len;
             }
             case Code.MAP32: { // map 32
                 int len = readNextLength32();
-                resetHeadByte();
                 return len;
             }
         }
@@ -1185,36 +1095,30 @@ public int unpackMapHeader()
     public ExtensionTypeHeader unpackExtensionTypeHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         switch (b) {
             case Code.FIXEXT1: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 1);
             }
             case Code.FIXEXT2: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 2);
             }
             case Code.FIXEXT4: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 4);
             }
             case Code.FIXEXT8: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 8);
             }
             case Code.FIXEXT16: {
                 byte type = readByte();
-                resetHeadByte();
                 return new ExtensionTypeHeader(type, 16);
             }
             case Code.EXT8: {
                 MessageBuffer castBuffer = readCastBuffer(2);
-                resetHeadByte();
                 int u8 = castBuffer.getByte(readCastBufferPosition);
                 int length = u8 & 0xff;
                 byte type = castBuffer.getByte(readCastBufferPosition + 1);
@@ -1222,7 +1126,6 @@ public ExtensionTypeHeader unpackExtensionTypeHeader()
             }
             case Code.EXT16: {
                 MessageBuffer castBuffer = readCastBuffer(3);
-                resetHeadByte();
                 int u16 = castBuffer.getShort(readCastBufferPosition);
                 int length = u16 & 0xffff;
                 byte type = castBuffer.getByte(readCastBufferPosition + 2);
@@ -1230,7 +1133,6 @@ public ExtensionTypeHeader unpackExtensionTypeHeader()
             }
             case Code.EXT32: {
                 MessageBuffer castBuffer = readCastBuffer(5);
-                resetHeadByte();
                 int u32 = castBuffer.getInt(readCastBufferPosition);
                 if (u32 < 0) {
                     throw overflowU32Size(u32);
@@ -1277,21 +1179,18 @@ private int tryReadBinaryHeader(byte b)
     public int unpackRawStringHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedRaw(b)) { // FixRaw
-            resetHeadByte();
             return b & 0x1f;
         }
         int len = tryReadStringHeader(b);
         if (len >= 0) {
-            resetHeadByte();
             return len;
         }
 
         if (allowBinaryAsString) {
             len = tryReadBinaryHeader(b);
             if (len >= 0) {
-                resetHeadByte();
                 return len;
             }
         }
@@ -1301,21 +1200,18 @@ public int unpackRawStringHeader()
     public int unpackBinaryHeader()
             throws IOException
     {
-        byte b = getHeadByte();
+        byte b = readByte();
         if (Code.isFixedRaw(b)) { // FixRaw
-            resetHeadByte();
             return b & 0x1f;
         }
         int len = tryReadBinaryHeader(b);
         if (len >= 0) {
-            resetHeadByte();
             return len;
         }
 
         if (allowStringAsBinary) {
             len = tryReadStringHeader(b);
             if (len >= 0) {
-                resetHeadByte();
                 return len;
             }
         }

From d89ce27d0c54f28c796d6e9608374295583d481f Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:21:52 +0900
Subject: [PATCH 59/99] Test various lengths of String

---
 ...essagePackDataformatPojoBenchmarkTest.java | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index de2118508..84dfde2fc 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -32,8 +32,9 @@
 
 public class MessagePackDataformatPojoBenchmarkTest
 {
-    private static final int LOOP_MAX = 600;
-    private static final int LOOP_FACTOR = 40;
+    private static final int LOOP_MAX = 200;
+    private static final int LOOP_FACTOR_SER = 40;
+    private static final int LOOP_FACTOR_DESER = 200;
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
     private static final List pojos = new ArrayList(LOOP_MAX);
@@ -52,7 +53,11 @@ public class MessagePackDataformatPojoBenchmarkTest
             pojo.l = i;
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
-            pojo.setS(String.valueOf(i));
+            StringBuilder sb = new StringBuilder();
+            for (int sbi = 0; sbi < i * 40; sbi++) {
+                sb.append("x");
+            }
+            pojo.setS(sb.toString());
             pojo.bool = i % 2 == 0;
             pojo.bi = BigInteger.valueOf(i);
             switch (i % 4) {
@@ -117,7 +122,7 @@ public void testBenchmark()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_SER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         origObjectMapper.writeValue(outputStreamJackson, pojos.get(i));
                     }
@@ -130,7 +135,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_SER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i));
                     }
@@ -143,7 +148,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_DESER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         origObjectMapper.readValue(pojosSerWithOrig.get(i), NormalPojo.class);
                     }
@@ -156,7 +161,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_DESER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         msgpackObjectMapper.readValue(pojosSerWithMsgPack.get(i), NormalPojo.class);
                     }

From b6fc9c994eb442e6eb2485d0af77551210ee09cd Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:35:23 +0900
Subject: [PATCH 60/99] Minor refactoring

---
 ...essagePackDataformatPojoBenchmarkTest.java | 25 ++++++++-----------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index 84dfde2fc..179b09891 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -37,15 +37,16 @@ public class MessagePackDataformatPojoBenchmarkTest
     private static final int LOOP_FACTOR_DESER = 200;
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
-    private static final List pojos = new ArrayList(LOOP_MAX);
-    private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
-    private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
+    private final List pojos = new ArrayList(LOOP_MAX);
+    private final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
+    private final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
     private final ObjectMapper origObjectMapper = new ObjectMapper();
     private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
 
-    static {
-        final ObjectMapper origObjectMapper = new ObjectMapper();
-        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    public MessagePackDataformatPojoBenchmarkTest()
+    {
+        origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
+        msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
 
         for (int i = 0; i < LOOP_MAX; i++) {
             NormalPojo pojo = new NormalPojo();
@@ -54,7 +55,7 @@ public class MessagePackDataformatPojoBenchmarkTest
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
             StringBuilder sb = new StringBuilder();
-            for (int sbi = 0; sbi < i * 40; sbi++) {
+            for (int sbi = 0; sbi < i * 50; sbi++) {
                 sb.append("x");
             }
             pojo.setS(sb.toString());
@@ -83,7 +84,7 @@ public class MessagePackDataformatPojoBenchmarkTest
                 pojosSerWithOrig.add(origObjectMapper.writeValueAsBytes(pojos.get(i)));
             }
             catch (JsonProcessingException e) {
-                e.printStackTrace();
+                throw new RuntimeException("Failed to create test data");
             }
         }
 
@@ -92,17 +93,11 @@ public class MessagePackDataformatPojoBenchmarkTest
                 pojosSerWithMsgPack.add(msgpackObjectMapper.writeValueAsBytes(pojos.get(i)));
             }
             catch (JsonProcessingException e) {
-                e.printStackTrace();
+                throw new RuntimeException("Failed to create test data");
             }
         }
     }
 
-    public MessagePackDataformatPojoBenchmarkTest()
-    {
-        origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
-        msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
-    }
-
     @Test
     public void testBenchmark()
             throws Exception

From d6dbfec7ef64be664fa0a0eae5c5a89e037dff14 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 21:36:24 +0900
Subject: [PATCH 61/99] Fix MessageFormat.Code#isFixedMap

---
 .../java/org/msgpack/core/MessageFormat.java  |  2 +-
 .../org/msgpack/core/MessagePackTest.scala    | 32 +++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java
index 17a0f1555..5a20518dc 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java
@@ -98,7 +98,7 @@ public static final boolean isFixedArray(byte b)
 
         public static final boolean isFixedMap(byte b)
         {
-            return (b & (byte) 0xe0) == Code.FIXMAP_PREFIX;
+            return (b & (byte) 0xf0) == Code.FIXMAP_PREFIX;
         }
 
         public static final boolean isFixedRaw(byte b)
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
index 5cf8ea2e6..8c2339f7d 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
@@ -59,6 +59,38 @@ class MessagePackTest extends MessagePackSpec {
       }
     }
 
+    "detect fixarray values" in {
+
+      val packer = new MessagePackFactory().newBufferPacker()
+      packer.packArrayHeader(0)
+      packer.close
+      val bytes = packer.toByteArray
+      new MessagePackFactory().newUnpacker(bytes).unpackArrayHeader() shouldBe 0
+      try {
+        new MessagePackFactory().newUnpacker(bytes).unpackMapHeader()
+        fail("Shouldn't reach here")
+      }
+      catch {
+        case e: MessageTypeException => // OK
+      }
+    }
+
+    "detect fixmap values" in {
+
+      val packer = new MessagePackFactory().newBufferPacker()
+      packer.packMapHeader(0)
+      packer.close
+      val bytes = packer.toByteArray
+      new MessagePackFactory().newUnpacker(bytes).unpackMapHeader() shouldBe 0
+      try {
+        new MessagePackFactory().newUnpacker(bytes).unpackArrayHeader()
+        fail("Shouldn't reach here")
+      }
+      catch {
+        case e: MessageTypeException => // OK
+      }
+    }
+
     "detect fixint quickly" in {
 
       val N = 100000

From c8c908e844aa716f93c5e651a05dcda9194efce9 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:21:52 +0900
Subject: [PATCH 62/99] Test various lengths of String

---
 ...essagePackDataformatPojoBenchmarkTest.java | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index de2118508..84dfde2fc 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -32,8 +32,9 @@
 
 public class MessagePackDataformatPojoBenchmarkTest
 {
-    private static final int LOOP_MAX = 600;
-    private static final int LOOP_FACTOR = 40;
+    private static final int LOOP_MAX = 200;
+    private static final int LOOP_FACTOR_SER = 40;
+    private static final int LOOP_FACTOR_DESER = 200;
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
     private static final List pojos = new ArrayList(LOOP_MAX);
@@ -52,7 +53,11 @@ public class MessagePackDataformatPojoBenchmarkTest
             pojo.l = i;
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
-            pojo.setS(String.valueOf(i));
+            StringBuilder sb = new StringBuilder();
+            for (int sbi = 0; sbi < i * 40; sbi++) {
+                sb.append("x");
+            }
+            pojo.setS(sb.toString());
             pojo.bool = i % 2 == 0;
             pojo.bi = BigInteger.valueOf(i);
             switch (i % 4) {
@@ -117,7 +122,7 @@ public void testBenchmark()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_SER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         origObjectMapper.writeValue(outputStreamJackson, pojos.get(i));
                     }
@@ -130,7 +135,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_SER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i));
                     }
@@ -143,7 +148,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_DESER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         origObjectMapper.readValue(pojosSerWithOrig.get(i), NormalPojo.class);
                     }
@@ -156,7 +161,7 @@ public void run()
             public void run()
                     throws Exception
             {
-                for (int j = 0; j < LOOP_FACTOR; j++) {
+                for (int j = 0; j < LOOP_FACTOR_DESER; j++) {
                     for (int i = 0; i < LOOP_MAX; i++) {
                         msgpackObjectMapper.readValue(pojosSerWithMsgPack.get(i), NormalPojo.class);
                     }

From 380f05b2f5f5f0519346585a910a6aac7c6c54b1 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:35:23 +0900
Subject: [PATCH 63/99] Minor refactoring

---
 ...essagePackDataformatPojoBenchmarkTest.java | 25 ++++++++-----------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index 84dfde2fc..179b09891 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -37,15 +37,16 @@ public class MessagePackDataformatPojoBenchmarkTest
     private static final int LOOP_FACTOR_DESER = 200;
     private static final int COUNT = 6;
     private static final int WARMUP_COUNT = 4;
-    private static final List pojos = new ArrayList(LOOP_MAX);
-    private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
-    private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
+    private final List pojos = new ArrayList(LOOP_MAX);
+    private final List pojosSerWithOrig = new ArrayList(LOOP_MAX);
+    private final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX);
     private final ObjectMapper origObjectMapper = new ObjectMapper();
     private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
 
-    static {
-        final ObjectMapper origObjectMapper = new ObjectMapper();
-        final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory());
+    public MessagePackDataformatPojoBenchmarkTest()
+    {
+        origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
+        msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
 
         for (int i = 0; i < LOOP_MAX; i++) {
             NormalPojo pojo = new NormalPojo();
@@ -54,7 +55,7 @@ public class MessagePackDataformatPojoBenchmarkTest
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
             StringBuilder sb = new StringBuilder();
-            for (int sbi = 0; sbi < i * 40; sbi++) {
+            for (int sbi = 0; sbi < i * 50; sbi++) {
                 sb.append("x");
             }
             pojo.setS(sb.toString());
@@ -83,7 +84,7 @@ public class MessagePackDataformatPojoBenchmarkTest
                 pojosSerWithOrig.add(origObjectMapper.writeValueAsBytes(pojos.get(i)));
             }
             catch (JsonProcessingException e) {
-                e.printStackTrace();
+                throw new RuntimeException("Failed to create test data");
             }
         }
 
@@ -92,17 +93,11 @@ public class MessagePackDataformatPojoBenchmarkTest
                 pojosSerWithMsgPack.add(msgpackObjectMapper.writeValueAsBytes(pojos.get(i)));
             }
             catch (JsonProcessingException e) {
-                e.printStackTrace();
+                throw new RuntimeException("Failed to create test data");
             }
         }
     }
 
-    public MessagePackDataformatPojoBenchmarkTest()
-    {
-        origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
-        msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
-    }
-
     @Test
     public void testBenchmark()
             throws Exception

From c39b250d1356ce2067f3f3a5d7b334d58da8e808 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:21:52 +0900
Subject: [PATCH 64/99] Test various lengths of String

---
 .../benchmark/MessagePackDataformatPojoBenchmarkTest.java       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index 179b09891..9fb6b21d9 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -55,7 +55,7 @@ public MessagePackDataformatPojoBenchmarkTest()
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
             StringBuilder sb = new StringBuilder();
-            for (int sbi = 0; sbi < i * 50; sbi++) {
+            for (int sbi = 0; sbi < i * 40; sbi++) {
                 sb.append("x");
             }
             pojo.setS(sb.toString());

From aea539741a8b2682399a5d170a2236f02fd9ac8c Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 27 Dec 2015 17:35:23 +0900
Subject: [PATCH 65/99] Minor refactoring

---
 .../benchmark/MessagePackDataformatPojoBenchmarkTest.java       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
index 9fb6b21d9..179b09891 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java
@@ -55,7 +55,7 @@ public MessagePackDataformatPojoBenchmarkTest()
             pojo.f = Float.valueOf(i);
             pojo.d = Double.valueOf(i);
             StringBuilder sb = new StringBuilder();
-            for (int sbi = 0; sbi < i * 40; sbi++) {
+            for (int sbi = 0; sbi < i * 50; sbi++) {
                 sb.append("x");
             }
             pojo.setS(sb.toString());

From 28be745eaca17a8ded241a67a6774e25aa24d2c0 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Fri, 1 Jan 2016 00:24:27 +0900
Subject: [PATCH 66/99] Add concurrent serialization test in
 MessagePackGeneratorTest

---
 .../dataformat/MessagePackGeneratorTest.java  | 56 +++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
index b88d0d645..18fd9ec62 100644
--- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
+++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java
@@ -24,6 +24,7 @@
 import org.msgpack.core.MessageUnpacker;
 import org.msgpack.core.buffer.ArrayBufferInput;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -36,6 +37,11 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -379,4 +385,54 @@ public void testWritePrimitiveObjectViaObjectMapper()
         assertEquals(4, unpacker.unpackInt());
         assertEquals(5, unpacker.unpackLong());
     }
+
+    @Test
+    public void testInMultiThreads()
+            throws Exception
+    {
+        int threadCount = 8;
+        final int loopCount = 4000;
+        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
+        final ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
+        objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
+        final List buffers = new ArrayList(threadCount);
+        List> results = new ArrayList>();
+
+        for (int ti = 0; ti < threadCount; ti++) {
+            buffers.add(new ByteArrayOutputStream());
+            final int threadIndex = ti;
+            results.add(executorService.submit(new Callable()
+            {
+                @Override
+                public Exception call()
+                        throws Exception
+                {
+                    try {
+                        for (int i = 0; i < loopCount; i++) {
+                            objectMapper.writeValue(buffers.get(threadIndex), threadIndex);
+                        }
+                        return null;
+                    }
+                    catch (IOException e) {
+                        return e;
+                    }
+                }
+            }));
+        }
+
+        for (int ti = 0; ti < threadCount; ti++) {
+            Future exceptionFuture = results.get(ti);
+            Exception exception = exceptionFuture.get(20, TimeUnit.SECONDS);
+            if (exception != null) {
+                throw exception;
+            }
+            else {
+                ByteArrayOutputStream outputStream = buffers.get(ti);
+                MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(outputStream.toByteArray());
+                for (int i = 0; i < loopCount; i++) {
+                    assertEquals(ti, unpacker.unpackInt());
+                }
+            }
+        }
+    }
 }

From 7ad3f0a26b53d6796dcc26b86bb30200df0724a4 Mon Sep 17 00:00:00 2001
From: Mitsunori Komatsu 
Date: Sun, 3 Jan 2016 22:23:54 +0900
Subject: [PATCH 67/99] Fix MessagePack.Code#isFixedMap

---
 .../java/org/msgpack/core/MessagePack.java    |  2 +-
 .../org/msgpack/core/MessagePackTest.scala    | 34 +++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
index 9847d461e..83d06b211 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
@@ -234,7 +234,7 @@ public static final boolean isFixedArray(byte b)
 
         public static final boolean isFixedMap(byte b)
         {
-            return (b & (byte) 0xe0) == Code.FIXMAP_PREFIX;
+            return (b & (byte) 0xf0) == Code.FIXMAP_PREFIX;
         }
 
         public static final boolean isFixedRaw(byte b)
diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
index 62bf8ae82..f00340f25 100644
--- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
+++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala
@@ -59,6 +59,40 @@ class MessagePackTest extends MessagePackSpec {
       }
     }
 
+    "detect fixarray values" in {
+
+      val outputStream = new ByteArrayOutputStream
+      val packer = MessagePack.newDefaultPacker(outputStream)
+      packer.packArrayHeader(0)
+      packer.close
+      val bytes = outputStream.toByteArray
+      MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() shouldBe 0
+      try {
+        MessagePack.newDefaultUnpacker(bytes).unpackMapHeader()
+        fail("Shouldn't reach here")
+      }
+      catch {
+        case e: MessageTypeException => // OK
+      }
+    }
+
+    "detect fixmap values" in {
+
+      val outputStream = new ByteArrayOutputStream
+      val packer = MessagePack.newDefaultPacker(outputStream)
+      packer.packMapHeader(0)
+      packer.close
+      val bytes = outputStream.toByteArray
+      MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() shouldBe 0
+      try {
+        MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader()
+        fail("Shouldn't reach here")
+      }
+      catch {
+        case e: MessageTypeException => // OK
+      }
+    }
+
     "detect fixint quickly" in {
 
       val N = 100000

From e261c59080f599e48dcaad01b97de16cf20da3eb Mon Sep 17 00:00:00 2001
From: "Taro L. Saito" 
Date: Mon, 4 Jan 2016 12:16:44 +0900
Subject: [PATCH 68/99] Merge v07-develop and fix code style

---
 .../java/org/msgpack/core/MessagePack.java    | 13 +----
 .../org/msgpack/core/MessagePackFactory.java  | 26 ++++-----
 .../java/org/msgpack/core/MessagePacker.java  |  1 -
 .../org/msgpack/core/MessageUnpacker.java     |  5 +-
 .../msgpack/core/buffer/ArrayBufferInput.java |  1 -
 .../core/buffer/ChannelBufferInput.java       |  1 -
 .../msgpack/core/buffer/MessageBufferBE.java  |  2 -
 .../core/buffer/MessageBufferInput.java       |  5 +-
 .../msgpack/core/buffer/MessageBufferU.java   |  2 -
 .../value/impl/ImmutableArrayValueImpl.java   |  3 +-
 .../impl/ImmutableBigIntegerValueImpl.java    |  9 ++-
 .../value/impl/ImmutableDoubleValueImpl.java  |  3 +-
 .../value/impl/ImmutableMapValueImpl.java     |  6 +-
 .../org/msgpack/core/MessagePackTest.scala    |  2 -
 .../jackson/dataformat/MessagePackParser.java | 10 +++-
 .../dataformat/MessagePackGeneratorTest.java  | 56 +++++++++++++++++++
 ...essagePackDataformatPojoBenchmarkTest.java | 42 +++++++-------
 17 files changed, 114 insertions(+), 73 deletions(-)

diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
index f1bee0774..f7fec9f24 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java
@@ -15,20 +15,11 @@
 //
 package org.msgpack.core;
 
-import org.msgpack.core.buffer.ArrayBufferInput;
-import org.msgpack.core.buffer.ChannelBufferInput;
-import org.msgpack.core.buffer.ChannelBufferOutput;
-import org.msgpack.core.buffer.InputStreamBufferInput;
-import org.msgpack.core.buffer.OutputStreamBufferOutput;
-
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
-import java.nio.charset.CodingErrorAction;
-
-import static org.msgpack.core.Preconditions.checkArgument;
 
 /**
  * This class has MessagePack prefix code definitions and packer/unpacker factory methods.
@@ -53,7 +44,8 @@ public static MessagePackFactory getDefaultFactory()
     }
 
     private MessagePack()
-    { }
+    {
+    }
 
     /**
      * Equivalent to getDefaultFactory().newPacker(out).
@@ -80,7 +72,6 @@ public static MessagePacker newDefaultPacker(WritableByteChannel channel)
     /**
      * Equivalent to getDefaultFactory().newBufferPacker()
      *
-     * @param channel
      * @return
      */
     public static MessageBufferPacker newDefaultBufferPacker()
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java
index f76df5490..8863e4637 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java
@@ -19,17 +19,15 @@
 import org.msgpack.core.buffer.ChannelBufferInput;
 import org.msgpack.core.buffer.ChannelBufferOutput;
 import org.msgpack.core.buffer.InputStreamBufferInput;
-import org.msgpack.core.buffer.OutputStreamBufferOutput;
 import org.msgpack.core.buffer.MessageBufferInput;
 import org.msgpack.core.buffer.MessageBufferOutput;
+import org.msgpack.core.buffer.OutputStreamBufferOutput;
 
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.nio.channels.WritableByteChannel;
 import java.nio.channels.ReadableByteChannel;
-
+import java.nio.channels.WritableByteChannel;
 import java.nio.charset.CodingErrorAction;
-import static org.msgpack.core.Preconditions.checkArgument;
 
 public class MessagePackFactory
 {
@@ -42,8 +40,8 @@ public class MessagePackFactory
     private int unpackStringSizeLimit = Integer.MAX_VALUE;
     private int unpackStringDecoderBufferSize = 8192;
 
-    private int inputBufferSize = 16*1024;
-    private int outputBufferSize = 16*1024;
+    private int inputBufferSize = 16 * 1024;
+    private int outputBufferSize = 16 * 1024;
 
     public MessagePacker newPacker(OutputStream out)
     {
@@ -58,13 +56,13 @@ public MessagePacker newPacker(WritableByteChannel channel)
     public MessagePacker newPacker(MessageBufferOutput output)
     {
         return new MessagePacker(output)
-            .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold);
+                .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold);
     }
 
     public MessageBufferPacker newBufferPacker()
     {
         return new MessageBufferPacker()
-            .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold);
+                .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold);
     }
 
     public MessageUnpacker newUnpacker(byte[] contents)
@@ -90,12 +88,12 @@ public MessageUnpacker newUnpacker(ReadableByteChannel channel)
     public MessageUnpacker newUnpacker(MessageBufferInput input)
     {
         return new MessageUnpacker(input)
-            .setAllowStringAsBinary(unpackAllowStringAsBinary)
-            .setAllowBinaryAsString(unpackAllowBinaryAsString)
-            .setActionOnMalformedString(unpackActionOnMalformedString)
-            .setActionOnUnmappableString(unpackActionOnUnmappableString)
-            .setStringSizeLimit(unpackStringSizeLimit)
-            .setStringDecoderBufferSize(unpackStringDecoderBufferSize);
+                .setAllowStringAsBinary(unpackAllowStringAsBinary)
+                .setAllowBinaryAsString(unpackAllowBinaryAsString)
+                .setActionOnMalformedString(unpackActionOnMalformedString)
+                .setActionOnUnmappableString(unpackActionOnUnmappableString)
+                .setStringSizeLimit(unpackStringSizeLimit)
+                .setStringDecoderBufferSize(unpackStringDecoderBufferSize);
     }
 
     /**
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
index b3fcff5a8..5d2ff6323 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java
@@ -27,7 +27,6 @@
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
 
 import static org.msgpack.core.MessageFormat.Code.ARRAY16;
 import static org.msgpack.core.MessageFormat.Code.ARRAY32;
diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
index ab7b3e496..017022204 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
@@ -24,7 +24,6 @@
 import org.msgpack.value.Variable;
 
 import java.io.Closeable;
-import java.io.EOFException;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
@@ -33,13 +32,11 @@
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
-import java.nio.charset.MalformedInputException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import static org.msgpack.core.Preconditions.checkArgument;
 import static org.msgpack.core.Preconditions.checkNotNull;
 
 /**
@@ -1019,7 +1016,7 @@ else if (bufferRemaining == 0) {
     }
 
     private void handleCoderError(CoderResult cr)
-        throws CharacterCodingException
+            throws CharacterCodingException
     {
         if ((cr.isMalformed() && actionOnMalformedString == CodingErrorAction.REPORT) ||
                 (cr.isUnmappable() && actionOnUnmappableString == CodingErrorAction.REPORT)) {
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java
index a777b8a73..88fe45942 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java
@@ -87,5 +87,4 @@ public void close()
         buffer = null;
         isRead = false;
     }
-
 }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
index 781b7afb9..6553e497f 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java
@@ -78,5 +78,4 @@ public void close()
     {
         channel.close();
     }
-
 }
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
index 3f5d24976..1326b396e 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferBE.java
@@ -15,8 +15,6 @@
 //
 package org.msgpack.core.buffer;
 
-import java.nio.ByteBuffer;
-
 import static org.msgpack.core.Preconditions.checkArgument;
 
 /**
diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java
index 5925557cf..cb5f7743d 100644
--- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java
+++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java
@@ -26,13 +26,12 @@ public interface MessageBufferInput
 {
     /**
      * Get a next buffer to read.
-     *
-     * When this method is called twice, the formally allocated buffer can be safely discarded.
+     * 

+ * When this method is called, the formally allocated buffer can be safely discarded. * * @return the next MessageBuffer, or return null if no more buffer is available. * @throws IOException when error occurred when reading the data */ public MessageBuffer next() throws IOException; - } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java index 151b6cd2e..1e8783738 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferU.java @@ -16,10 +16,8 @@ package org.msgpack.core.buffer; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import static org.msgpack.core.Preconditions.checkArgument; -import static org.msgpack.core.Preconditions.checkNotNull; /** * Universal MessageBuffer implementation supporting Java6 and Android. diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableArrayValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableArrayValueImpl.java index 09fc18e52..3e1b732c2 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableArrayValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableArrayValueImpl.java @@ -196,7 +196,8 @@ private static void appendString(StringBuilder sb, Value value) { if (value.isRawValue()) { sb.append(value.toJson()); - } else { + } + else { sb.append(value.toString()); } } diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableBigIntegerValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableBigIntegerValueImpl.java index b1c7c0b10..c6fe39386 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableBigIntegerValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableBigIntegerValueImpl.java @@ -38,16 +38,16 @@ public class ImmutableBigIntegerValueImpl { public static MessageFormat mostSuccinctMessageFormat(IntegerValue v) { - if(v.isInByteRange()) { + if (v.isInByteRange()) { return MessageFormat.INT8; } - else if(v.isInShortRange()) { + else if (v.isInShortRange()) { return MessageFormat.INT16; } - else if(v.isInIntRange()) { + else if (v.isInIntRange()) { return MessageFormat.INT32; } - else if(v.isInLongRange()) { + else if (v.isInLongRange()) { return MessageFormat.INT64; } else { @@ -55,7 +55,6 @@ else if(v.isInLongRange()) { } } - private final BigInteger value; public ImmutableBigIntegerValueImpl(BigInteger value) diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableDoubleValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableDoubleValueImpl.java index b7fa39397..2aae1633a 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableDoubleValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableDoubleValueImpl.java @@ -130,7 +130,8 @@ public String toJson() { if (Double.isNaN(value) || Double.isInfinite(value)) { return "null"; - } else { + } + else { return Double.toString(value); } } diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableMapValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableMapValueImpl.java index 3df98d619..dc55d783f 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableMapValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableMapValueImpl.java @@ -172,7 +172,8 @@ private static void appendJsonKey(StringBuilder sb, Value key) { if (key.isRawValue()) { sb.append(key.toJson()); - } else { + } + else { ImmutableStringValueImpl.appendJsonString(sb, key.toString()); } } @@ -202,7 +203,8 @@ private static void appendString(StringBuilder sb, Value value) { if (value.isRawValue()) { sb.append(value.toJson()); - } else { + } + else { sb.append(value.toString()); } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 8c2339f7d..e1dc1d673 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -60,7 +60,6 @@ class MessagePackTest extends MessagePackSpec { } "detect fixarray values" in { - val packer = new MessagePackFactory().newBufferPacker() packer.packArrayHeader(0) packer.close @@ -76,7 +75,6 @@ class MessagePackTest extends MessagePackSpec { } "detect fixmap values" in { - val packer = new MessagePackFactory().newBufferPacker() packer.packMapHeader(0) packer.close diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 7ac2fa5af..08be64e59 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -32,7 +32,12 @@ import org.msgpack.core.buffer.ArrayBufferInput; import org.msgpack.core.buffer.InputStreamBufferInput; import org.msgpack.core.buffer.MessageBufferInput; -import org.msgpack.value.*; +import org.msgpack.value.ExtensionValue; +import org.msgpack.value.IntegerValue; +import org.msgpack.value.Value; +import org.msgpack.value.ValueFactory; +import org.msgpack.value.ValueType; +import org.msgpack.value.Variable; import java.io.IOException; import java.io.InputStream; @@ -278,7 +283,8 @@ else if (newStack instanceof StackItemForObject) { @Override protected void _handleEOF() throws JsonParseException - {} + { + } @Override public String getText() diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index de58e4a1a..845c45f40 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -24,6 +24,7 @@ import org.msgpack.core.MessageUnpacker; import org.msgpack.core.buffer.ArrayBufferInput; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -36,6 +37,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -379,4 +385,54 @@ public void testWritePrimitiveObjectViaObjectMapper() assertEquals(4, unpacker.unpackInt()); assertEquals(5, unpacker.unpackLong()); } + + @Test + public void testInMultiThreads() + throws Exception + { + int threadCount = 8; + final int loopCount = 4000; + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + final ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + final List buffers = new ArrayList(threadCount); + List> results = new ArrayList>(); + + for (int ti = 0; ti < threadCount; ti++) { + buffers.add(new ByteArrayOutputStream()); + final int threadIndex = ti; + results.add(executorService.submit(new Callable() + { + @Override + public Exception call() + throws Exception + { + try { + for (int i = 0; i < loopCount; i++) { + objectMapper.writeValue(buffers.get(threadIndex), threadIndex); + } + return null; + } + catch (IOException e) { + return e; + } + } + })); + } + + for (int ti = 0; ti < threadCount; ti++) { + Future exceptionFuture = results.get(ti); + Exception exception = exceptionFuture.get(20, TimeUnit.SECONDS); + if (exception != null) { + throw exception; + } + else { + ByteArrayOutputStream outputStream = buffers.get(ti); + MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(outputStream.toByteArray()); + for (int i = 0; i < loopCount; i++) { + assertEquals(ti, unpacker.unpackInt()); + } + } + } + } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index 33c5f024c..e6b627f5c 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -32,19 +32,21 @@ public class MessagePackDataformatPojoBenchmarkTest { - private static final int LOOP_MAX = 600; - private static final int LOOP_FACTOR = 40; + private static final int LOOP_MAX = 200; + private static final int LOOP_FACTOR_SER = 40; + private static final int LOOP_FACTOR_DESER = 200; private static final int COUNT = 6; private static final int WARMUP_COUNT = 4; - private static final List pojos = new ArrayList(LOOP_MAX); - private static final List pojosSerWithOrig = new ArrayList(LOOP_MAX); - private static final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX); + private final List pojos = new ArrayList(LOOP_MAX); + private final List pojosSerWithOrig = new ArrayList(LOOP_MAX); + private final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX); private final ObjectMapper origObjectMapper = new ObjectMapper(); private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory()); - static { - final ObjectMapper origObjectMapper = new ObjectMapper(); - final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory()); + public MessagePackDataformatPojoBenchmarkTest() + { + origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); for (int i = 0; i < LOOP_MAX; i++) { NormalPojo pojo = new NormalPojo(); @@ -52,7 +54,11 @@ public class MessagePackDataformatPojoBenchmarkTest pojo.l = i; pojo.f = Float.valueOf(i); pojo.d = Double.valueOf(i); - pojo.setS(String.valueOf(i)); + StringBuilder sb = new StringBuilder(); + for (int sbi = 0; sbi < i * 50; sbi++) { + sb.append("x"); + } + pojo.setS(sb.toString()); pojo.bool = i % 2 == 0; pojo.bi = BigInteger.valueOf(i); switch (i % 4) { @@ -78,7 +84,7 @@ public class MessagePackDataformatPojoBenchmarkTest pojosSerWithOrig.add(origObjectMapper.writeValueAsBytes(pojos.get(i))); } catch (JsonProcessingException e) { - e.printStackTrace(); + throw new RuntimeException("Failed to create test data"); } } @@ -87,17 +93,11 @@ public class MessagePackDataformatPojoBenchmarkTest pojosSerWithMsgPack.add(msgpackObjectMapper.writeValueAsBytes(pojos.get(i))); } catch (JsonProcessingException e) { - e.printStackTrace(); + throw new RuntimeException("Failed to create test data"); } } } - public MessagePackDataformatPojoBenchmarkTest() - { - origObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - msgpackObjectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); - } - @Test public void testBenchmark() throws Exception @@ -117,7 +117,7 @@ public void testBenchmark() public void run() throws Exception { - for (int j = 0; j < LOOP_FACTOR; j++) { + for (int j = 0; j < LOOP_FACTOR_SER; j++) { for (int i = 0; i < LOOP_MAX; i++) { origObjectMapper.writeValue(outputStreamJackson, pojos.get(i)); } @@ -130,7 +130,7 @@ public void run() public void run() throws Exception { - for (int j = 0; j < LOOP_FACTOR; j++) { + for (int j = 0; j < LOOP_FACTOR_SER; j++) { for (int i = 0; i < LOOP_MAX; i++) { msgpackObjectMapper.writeValue(outputStreamMsgpack, pojos.get(i)); } @@ -143,7 +143,7 @@ public void run() public void run() throws Exception { - for (int j = 0; j < LOOP_FACTOR; j++) { + for (int j = 0; j < LOOP_FACTOR_DESER; j++) { for (int i = 0; i < LOOP_MAX; i++) { origObjectMapper.readValue(pojosSerWithOrig.get(i), NormalPojo.class); } @@ -156,7 +156,7 @@ public void run() public void run() throws Exception { - for (int j = 0; j < LOOP_FACTOR; j++) { + for (int j = 0; j < LOOP_FACTOR_DESER; j++) { for (int i = 0; i < LOOP_MAX; i++) { msgpackObjectMapper.readValue(pojosSerWithMsgPack.get(i), NormalPojo.class); } From 8cb71d95f18a7911287bf60c2af8b68a898d02f8 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 13:00:33 +0900 Subject: [PATCH 69/99] Move Nullable to annocation package --- .../src/main/java/org/msgpack/core/Preconditions.java | 1 + .../java/org/msgpack/core/{ => annotations}/Nullable.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) rename msgpack-core/src/main/java/org/msgpack/core/{ => annotations}/Nullable.java (91%) diff --git a/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java b/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java index d8f43bcb7..e44d97d15 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java +++ b/msgpack-core/src/main/java/org/msgpack/core/Preconditions.java @@ -31,6 +31,7 @@ */ package org.msgpack.core; +import org.msgpack.core.annotations.Nullable; import org.msgpack.core.annotations.VisibleForTesting; /** diff --git a/msgpack-core/src/main/java/org/msgpack/core/Nullable.java b/msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java similarity index 91% rename from msgpack-core/src/main/java/org/msgpack/core/Nullable.java rename to msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java index b2e7585a5..9e7c94fab 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/Nullable.java +++ b/msgpack-core/src/main/java/org/msgpack/core/annotations/Nullable.java @@ -13,11 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.core; +package org.msgpack.core.annotations; /** * Annotates a field which can be null */ -@interface Nullable +public @interface Nullable { } From 0215af902b40dab982f916f865ee696b09dcab02 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 13:02:58 +0900 Subject: [PATCH 70/99] Fix typo --- .../java/org/msgpack/core/buffer/MessageBufferOutput.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 92eb760a9..055fb309e 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -30,11 +30,11 @@ public interface MessageBufferOutput * If the previously allocated buffer is not flushed yet, this next method should discard * it without writing it. * - * @param mimimumSize the mimium required buffer size to allocate + * @param minimumSize the mimium required buffer size to allocate * @return * @throws IOException */ - public MessageBuffer next(int mimimumSize) + public MessageBuffer next(int minimumSize) throws IOException; /** From 7102ecb084ff7bcd0d3ba2d95aaaf5779773c759 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 13:04:39 +0900 Subject: [PATCH 71/99] Remove unnecessary public declaration from the interface --- .../java/org/msgpack/core/buffer/MessageBufferInput.java | 2 +- .../java/org/msgpack/core/buffer/MessageBufferOutput.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java index cb5f7743d..46eea243e 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferInput.java @@ -32,6 +32,6 @@ public interface MessageBufferInput * @return the next MessageBuffer, or return null if no more buffer is available. * @throws IOException when error occurred when reading the data */ - public MessageBuffer next() + MessageBuffer next() throws IOException; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java index 055fb309e..024414bae 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBufferOutput.java @@ -34,7 +34,7 @@ public interface MessageBufferOutput * @return * @throws IOException */ - public MessageBuffer next(int minimumSize) + MessageBuffer next(int minimumSize) throws IOException; /** @@ -45,7 +45,7 @@ public MessageBuffer next(int minimumSize) * @param length the size of buffer to flush * @throws IOException */ - public void writeBuffer(int length) + void writeBuffer(int length) throws IOException; /** @@ -58,7 +58,7 @@ public void writeBuffer(int length) * @return * @throws IOException */ - public void write(byte[] buffer, int offset, int length) + void write(byte[] buffer, int offset, int length) throws IOException; /** @@ -71,6 +71,6 @@ public void write(byte[] buffer, int offset, int length) * @return * @throws IOException */ - public void add(byte[] buffer, int offset, int length) + void add(byte[] buffer, int offset, int length) throws IOException; } From 7b7012fb775ade50a554424fcd0086180aeba056 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 13:07:15 +0900 Subject: [PATCH 72/99] Extract common code --- .../java/org/msgpack/core/MessagePacker.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 5d2ff6323..e0b1b6c65 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -153,10 +153,7 @@ public void flush() throws IOException { if (position > 0) { - out.writeBuffer(position); - buffer = null; - totalFlushBytes += position; - position = 0; + flushBuffer(); } out.flush(); } @@ -172,6 +169,15 @@ public void close() } } + private void flushBuffer() + throws IOException + { + out.writeBuffer(position); + buffer = null; + totalFlushBytes += position; + position = 0; + } + private void ensureCapacity(int mimimumSize) throws IOException { @@ -179,10 +185,7 @@ private void ensureCapacity(int mimimumSize) buffer = out.next(mimimumSize); } else if (position + mimimumSize >= buffer.size()) { - out.writeBuffer(position); - buffer = null; - totalFlushBytes += position; - position = 0; + flushBuffer(); buffer = out.next(mimimumSize); } } From 5cbd2e0e2c38501ae5b75f5890434b864acd628d Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 13:10:28 +0900 Subject: [PATCH 73/99] Use the root constructor --- .../main/java/org/msgpack/core/buffer/ArrayBufferInput.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java index 88fe45942..36f0ad3c1 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ArrayBufferInput.java @@ -17,7 +17,6 @@ import java.io.IOException; -import static org.msgpack.core.Preconditions.checkArgument; import static org.msgpack.core.Preconditions.checkNotNull; /** @@ -41,8 +40,7 @@ public ArrayBufferInput(byte[] arr) public ArrayBufferInput(byte[] arr, int offset, int length) { - checkArgument(offset + length <= arr.length); - this.buffer = MessageBuffer.wrap(checkNotNull(arr, "input array is null")).slice(offset, length); + this(MessageBuffer.wrap(checkNotNull(arr, "input array is null")).slice(offset, length)); } /** From b391406a9da1a14d20a230d673afc485dae7bd60 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 13:46:37 +0900 Subject: [PATCH 74/99] remove default factory setter --- .../java/org/msgpack/core/MessagePack.java | 29 +++++-------------- .../msgpack/core/MesssagePackerConfig.java | 8 +++++ 2 files changed, 16 insertions(+), 21 deletions(-) create mode 100644 msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index f7fec9f24..65177ae79 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -28,27 +28,14 @@ public class MessagePack { public static final Charset UTF8 = Charset.forName("UTF-8"); - private static MessagePackFactory defaultFactory = new MessagePackFactory(); - - /** - * Sets the default configuration used for the static constructor methods of this MessagePack class. - */ - public static void setDefaultFactory(MessagePackFactory newDefaultFactory) - { - defaultFactory = newDefaultFactory; - } - - public static MessagePackFactory getDefaultFactory() - { - return defaultFactory; - } + private final static MessagePackFactory defaultFactory = new MessagePackFactory(); private MessagePack() { } /** - * Equivalent to getDefaultFactory().newPacker(out). + * Equivalent to defaultFactory().newPacker(out). * * @param out * @return @@ -59,7 +46,7 @@ public static MessagePacker newDefaultPacker(OutputStream out) } /** - * Equivalent to getDefaultFactory().newPacker(channel). + * Equivalent to defaultFactory().newPacker(channel). * * @param channel * @return @@ -70,7 +57,7 @@ public static MessagePacker newDefaultPacker(WritableByteChannel channel) } /** - * Equivalent to getDefaultFactory().newBufferPacker() + * Equivalent to defaultFactory().newBufferPacker() * * @return */ @@ -80,7 +67,7 @@ public static MessageBufferPacker newDefaultBufferPacker() } /** - * Equivalent to getDefaultFactory().newUnpacker(in). + * Equivalent to defaultFactory().newUnpacker(in). * * @param in * @return @@ -91,7 +78,7 @@ public static MessageUnpacker newDefaultUnpacker(InputStream in) } /** - * Equivalent to getDefaultFactory().newUnpacker(channel). + * Equivalent to defaultFactory().newUnpacker(channel). * * @param channel * @return @@ -102,7 +89,7 @@ public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) } /** - * Equivalent to getDefaultFactory().newUnpacker(contents). + * Equivalent to defaultFactory().newUnpacker(contents). * * @param contents * @return @@ -113,7 +100,7 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents) } /** - * Equivalent to getDefaultFactory().newUnpacker(contents, offset, length). + * Equivalent to defaultFactory().newUnpacker(contents, offset, length). * * @param contents * @param offset diff --git a/msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java b/msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java new file mode 100644 index 000000000..c3e39462d --- /dev/null +++ b/msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java @@ -0,0 +1,8 @@ +package org.msgpack.core; + +/** + * + */ +public class MesssagePackerConfig +{ +} From d9dfb062f1aaa0a6d33b343b91c23e66048910cf Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 15:35:26 +0900 Subject: [PATCH 75/99] Replace MessagePackFactory with mutable Packer/UnpackerConfig-based code --- .../org/msgpack/core/MessageBufferPacker.java | 30 +-- .../java/org/msgpack/core/MessagePack.java | 173 +++++++++++++-- .../org/msgpack/core/MessagePackFactory.java | 201 ------------------ .../java/org/msgpack/core/MessagePacker.java | 12 +- .../org/msgpack/core/MessageUnpacker.java | 57 ++--- .../msgpack/core/MesssagePackerConfig.java | 8 - .../core/example/MessagePackExample.java | 20 +- .../org/msgpack/core/MessagePackTest.scala | 59 ++--- .../org/msgpack/core/MessagePackerTest.scala | 27 +-- .../msgpack/core/MessageUnpackerTest.scala | 50 +++-- .../msgpack/core/buffer/ByteStringTest.scala | 5 +- .../core/buffer/MessageBufferInputTest.scala | 6 +- .../dataformat/MessagePackGenerator.java | 3 +- .../jackson/dataformat/MessagePackParser.java | 3 +- .../dataformat/MessagePackGeneratorTest.java | 4 +- .../dataformat/MessagePackParserTest.java | 6 +- 16 files changed, 275 insertions(+), 389 deletions(-) delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java delete mode 100644 msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index 02b94f773..829803a2d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -22,24 +22,20 @@ import java.io.IOException; import java.util.List; +/** + * MessagePacker that is useful to produce byte array output + */ public class MessageBufferPacker extends MessagePacker { - public MessageBufferPacker() + public MessageBufferPacker(MessagePack.PackerConfig config) { - this(new ArrayBufferOutput()); + this(new ArrayBufferOutput(), config); } - public MessageBufferPacker(ArrayBufferOutput out) + public MessageBufferPacker(ArrayBufferOutput out, MessagePack.PackerConfig config) { - super(out); - } - - @Override - public MessageBufferPacker setSmallStringOptimizationThreshold(int bytes) - { - super.setSmallStringOptimizationThreshold(bytes); - return this; + super(out, config); } public MessageBufferOutput reset(MessageBufferOutput out) @@ -51,23 +47,27 @@ public MessageBufferOutput reset(MessageBufferOutput out) return super.reset(out); } + private ArrayBufferOutput getArrayBufferOut() { + return (ArrayBufferOutput) out; + } + public void clear() { - ((ArrayBufferOutput) out).clear(); + getArrayBufferOut().clear(); } public byte[] toByteArray() { - return ((ArrayBufferOutput) out).toByteArray(); + return getArrayBufferOut().toByteArray(); } public MessageBuffer toMessageBuffer() { - return ((ArrayBufferOutput) out).toMessageBuffer(); + return getArrayBufferOut().toMessageBuffer(); } public List toBufferList() { - return ((ArrayBufferOutput) out).toBufferList(); + return getArrayBufferOut().toBufferList(); } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 65177ae79..02f94cde4 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -15,11 +15,20 @@ // package org.msgpack.core; +import org.msgpack.core.buffer.ArrayBufferInput; +import org.msgpack.core.buffer.ChannelBufferInput; +import org.msgpack.core.buffer.ChannelBufferOutput; +import org.msgpack.core.buffer.InputStreamBufferInput; +import org.msgpack.core.buffer.MessageBufferInput; +import org.msgpack.core.buffer.MessageBufferOutput; +import org.msgpack.core.buffer.OutputStreamBufferOutput; + import java.io.InputStream; import java.io.OutputStream; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.charset.Charset; +import java.nio.charset.CodingErrorAction; /** * This class has MessagePack prefix code definitions and packer/unpacker factory methods. @@ -28,79 +37,100 @@ public class MessagePack { public static final Charset UTF8 = Charset.forName("UTF-8"); - private final static MessagePackFactory defaultFactory = new MessagePackFactory(); - private MessagePack() { + // Prohibit instantiation of this class + } + + /** + * Create a packer that outputs the packed data to the specified output + * + * @param out + * @return + */ + public static MessagePacker newDefaultPacker(MessageBufferOutput out) + { + return new PackerConfig().newPacker(out); } /** - * Equivalent to defaultFactory().newPacker(out). + * Create a packer that outputs the packed data to a target output stream * * @param out * @return */ public static MessagePacker newDefaultPacker(OutputStream out) { - return defaultFactory.newPacker(out); + return new PackerConfig().newPacker(out); } /** - * Equivalent to defaultFactory().newPacker(channel). + * Create a packer that outputs the packed data to a channel * * @param channel * @return */ public static MessagePacker newDefaultPacker(WritableByteChannel channel) { - return defaultFactory.newPacker(channel); + return new PackerConfig().newPacker(channel); } /** - * Equivalent to defaultFactory().newBufferPacker() + * Create a packer for storing packed data into a byte array * * @return */ public static MessageBufferPacker newDefaultBufferPacker() { - return defaultFactory.newBufferPacker(); + return new PackerConfig().newBufferPacker(); } /** - * Equivalent to defaultFactory().newUnpacker(in). + * Create an unpacker that reads the data from a given input + * + * @param in + * @return + */ + public static MessageUnpacker newDefaultUnpacker(MessageBufferInput in) + { + return new UnpackerConfig().newUnpacker(in); + } + + /** + * Create an unpacker that reads the data from a given input stream * * @param in * @return */ public static MessageUnpacker newDefaultUnpacker(InputStream in) { - return defaultFactory.newUnpacker(in); + return new UnpackerConfig().newUnpacker(in); } /** - * Equivalent to defaultFactory().newUnpacker(channel). + * Create an unpacker that reads the data from a given channel * * @param channel * @return */ public static MessageUnpacker newDefaultUnpacker(ReadableByteChannel channel) { - return defaultFactory.newUnpacker(channel); + return new UnpackerConfig().newUnpacker(channel); } /** - * Equivalent to defaultFactory().newUnpacker(contents). + * Create an unpacker that reads the data from a given byte array * * @param contents * @return */ public static MessageUnpacker newDefaultUnpacker(byte[] contents) { - return defaultFactory.newUnpacker(contents); + return new UnpackerConfig().newUnpacker(contents); } /** - * Equivalent to defaultFactory().newUnpacker(contents, offset, length). + * Create an unpacker that reads the data from a given byte array [offset, offset+length) * * @param contents * @param offset @@ -109,6 +139,117 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents) */ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, int length) { - return defaultFactory.newUnpacker(contents, offset, length); + return new UnpackerConfig().newUnpacker(contents, offset, length); + } + + /** + * MessagePacker configuration. + */ + public static class PackerConfig + { + public int smallStringOptimizationThreshold = 512; + + /** + * Create a packer that outputs the packed data to a given output + * + * @param out + * @return + */ + public MessagePacker newPacker(MessageBufferOutput out) { + return new MessagePacker(out, this); + } + + /** + * Create a packer that outputs the packed data to a given output stream + * + * @param out + * @return + */ + public MessagePacker newPacker(OutputStream out) { + return newPacker(new OutputStreamBufferOutput(out)); + } + + /** + * Create a packer that outputs the packed data to a given output channel + * + * @param channel + * @return + */ + public MessagePacker newPacker(WritableByteChannel channel) { + return newPacker(new ChannelBufferOutput(channel)); + } + + /** + * Create a packer for storing packed data into a byte array + * + * @return + */ + public MessageBufferPacker newBufferPacker() { + return new MessageBufferPacker(this); + } + } + + /** + * MessageUnpacker configuration. + */ + public static class UnpackerConfig + { + public boolean allowStringAsBinary = true; + public boolean allowBinaryAsString = true; + public CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE; + public CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE; + public int stringSizeLimit = Integer.MAX_VALUE; + public int stringDecoderBufferSize = 8192; + + /** + * Create an unpacker that reads the data from a given input + * + * @param in + * @return + */ + public MessageUnpacker newUnpacker(MessageBufferInput in) { + return new MessageUnpacker(in, this); + } + + /** + * Create an unpacker that reads the data from a given input stream + * + * @param in + * @return + */ + public MessageUnpacker newUnpacker(InputStream in) { + return newUnpacker(new InputStreamBufferInput(in)); + } + + /** + * Create an unpacker that reads the data from a given channel + * + * @param channel + * @return + */ + public MessageUnpacker newUnpacker(ReadableByteChannel channel) { + return newUnpacker(new ChannelBufferInput(channel)); + } + + /** + * Create an unpacker that reads the data from a given byte array + * + * @param contents + * @return + */ + public MessageUnpacker newUnpacker(byte[] contents) { + return newUnpacker(new ArrayBufferInput(contents)); + } + + /** + * Create an unpacker that reads the data from a given byte array [offset, offset+size) + * + * @param contents + * @return + */ + public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { + return newUnpacker(new ArrayBufferInput(contents, offset, length)); + } + } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java deleted file mode 100644 index 8863e4637..000000000 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePackFactory.java +++ /dev/null @@ -1,201 +0,0 @@ -// -// MessagePack for Java -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -package org.msgpack.core; - -import org.msgpack.core.buffer.ArrayBufferInput; -import org.msgpack.core.buffer.ChannelBufferInput; -import org.msgpack.core.buffer.ChannelBufferOutput; -import org.msgpack.core.buffer.InputStreamBufferInput; -import org.msgpack.core.buffer.MessageBufferInput; -import org.msgpack.core.buffer.MessageBufferOutput; -import org.msgpack.core.buffer.OutputStreamBufferOutput; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.charset.CodingErrorAction; - -public class MessagePackFactory -{ - private int packerSmallStringOptimizationThreshold = 512; - - private boolean unpackAllowStringAsBinary = true; - private boolean unpackAllowBinaryAsString = true; - private CodingErrorAction unpackActionOnMalformedString = CodingErrorAction.REPLACE; - private CodingErrorAction unpackActionOnUnmappableString = CodingErrorAction.REPLACE; - private int unpackStringSizeLimit = Integer.MAX_VALUE; - private int unpackStringDecoderBufferSize = 8192; - - private int inputBufferSize = 16 * 1024; - private int outputBufferSize = 16 * 1024; - - public MessagePacker newPacker(OutputStream out) - { - return newPacker(new OutputStreamBufferOutput(out)); - } - - public MessagePacker newPacker(WritableByteChannel channel) - { - return newPacker(new ChannelBufferOutput(channel)); - } - - public MessagePacker newPacker(MessageBufferOutput output) - { - return new MessagePacker(output) - .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold); - } - - public MessageBufferPacker newBufferPacker() - { - return new MessageBufferPacker() - .setSmallStringOptimizationThreshold(packerSmallStringOptimizationThreshold); - } - - public MessageUnpacker newUnpacker(byte[] contents) - { - return newUnpacker(contents, 0, contents.length); - } - - public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) - { - return newUnpacker(new ArrayBufferInput(contents, offset, length)); - } - - public MessageUnpacker newUnpacker(InputStream in) - { - return newUnpacker(new InputStreamBufferInput(in)); - } - - public MessageUnpacker newUnpacker(ReadableByteChannel channel) - { - return newUnpacker(new ChannelBufferInput(channel)); - } - - public MessageUnpacker newUnpacker(MessageBufferInput input) - { - return new MessageUnpacker(input) - .setAllowStringAsBinary(unpackAllowStringAsBinary) - .setAllowBinaryAsString(unpackAllowBinaryAsString) - .setActionOnMalformedString(unpackActionOnMalformedString) - .setActionOnUnmappableString(unpackActionOnUnmappableString) - .setStringSizeLimit(unpackStringSizeLimit) - .setStringDecoderBufferSize(unpackStringDecoderBufferSize); - } - - /** - * Use String.getBytes() for strings smaller than this threshold. - * Note that this parameter is subject to change. - */ - public MessagePackFactory packerSmallStringOptimizationThreshold(int bytes) - { - this.packerSmallStringOptimizationThreshold = bytes; - return this; - } - - public MessagePackFactory unpackAllowStringAsBinary(boolean enabled) - { - this.unpackAllowStringAsBinary = enabled; - return this; - } - - public MessagePackFactory unpackAllowBinaryAsString(boolean enabled) - { - this.unpackAllowBinaryAsString = enabled; - return this; - } - - public MessagePackFactory unpackActionOnMalformedString(CodingErrorAction action) - { - this.unpackActionOnMalformedString = action; - return this; - } - - public MessagePackFactory unpackActionOnUnmappableString(CodingErrorAction action) - { - this.unpackActionOnUnmappableString = action; - return this; - } - - public MessagePackFactory unpackStringSizeLimit(int bytes) - { - this.unpackStringSizeLimit = bytes; - return this; - } - - public MessagePackFactory unpackStringDecoderBufferSize(int bytes) - { - this.unpackStringDecoderBufferSize = bytes; - return this; - } - - public MessagePackFactory inputBufferSize(int bytes) - { - this.inputBufferSize = bytes; - return this; - } - - public MessagePackFactory outputBufferSize(int bytes) - { - this.inputBufferSize = bytes; - return this; - } - - private int getPackerSmallStringOptimizationThreshold() - { - return packerSmallStringOptimizationThreshold; - } - - private boolean getUnpackAllowStringAsBinary() - { - return unpackAllowStringAsBinary; - } - - private boolean getUnpackAllowBinaryAsString() - { - return unpackAllowBinaryAsString; - } - - private CodingErrorAction getUnpackActionOnMalformedString() - { - return unpackActionOnMalformedString; - } - - private CodingErrorAction getUnpackActionOnUnmappableString() - { - return unpackActionOnUnmappableString; - } - - private int getUnpackStringSizeLimit() - { - return unpackStringSizeLimit; - } - - private int getUnpackStringDecoderBufferSize() - { - return unpackStringDecoderBufferSize; - } - - private int getInputBufferSize() - { - return inputBufferSize; - } - - private int getOutputBufferSize() - { - return outputBufferSize; - } -} diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index e0b1b6c65..c54943d2c 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -84,7 +84,7 @@ public class MessagePacker implements Closeable { - private int smallStringOptimizationThreshold = 512; + private final int smallStringOptimizationThreshold; protected MessageBufferOutput out; @@ -108,19 +108,15 @@ public class MessagePacker * @param out MessageBufferOutput. Use {@link org.msgpack.core.buffer.OutputStreamBufferOutput}, {@link org.msgpack.core.buffer.ChannelBufferOutput} or * your own implementation of {@link org.msgpack.core.buffer.MessageBufferOutput} interface. */ - public MessagePacker(MessageBufferOutput out) + public MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config) { this.out = checkNotNull(out, "MessageBufferOutput is null"); + // We must copy the configuration parameters here since the config object is mutable + this.smallStringOptimizationThreshold = config.smallStringOptimizationThreshold; this.position = 0; this.totalFlushBytes = 0; } - public MessagePacker setSmallStringOptimizationThreshold(int bytes) - { - this.smallStringOptimizationThreshold = bytes; - return this; - } - /** * Reset output. This method doesn't close the old resource. * diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 017022204..1602aa165 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -73,12 +73,12 @@ public class MessageUnpacker private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1; - private boolean allowStringAsBinary = true; - private boolean allowBinaryAsString = true; - private CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE; - private CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE; - private int stringSizeLimit = Integer.MAX_VALUE; - private int stringDecoderBufferSize = 8192; + private final boolean allowStringAsBinary; + private final boolean allowBinaryAsString; + private final CodingErrorAction actionOnMalformedString; + private final CodingErrorAction actionOnUnmappableString; + private final int stringSizeLimit; + private final int stringDecoderBufferSize; private MessageBufferInput in; @@ -130,45 +130,16 @@ public class MessageUnpacker * * @param in */ - public MessageUnpacker(MessageBufferInput in) + public MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig config) { this.in = checkNotNull(in, "MessageBufferInput is null"); - } - - public MessageUnpacker setAllowStringAsBinary(boolean enabled) - { - this.allowStringAsBinary = enabled; - return this; - } - - public MessageUnpacker setAllowBinaryAsString(boolean enabled) - { - this.allowBinaryAsString = enabled; - return this; - } - - public MessageUnpacker setActionOnMalformedString(CodingErrorAction action) - { - this.actionOnMalformedString = action; - return this; - } - - public MessageUnpacker setActionOnUnmappableString(CodingErrorAction action) - { - this.actionOnUnmappableString = action; - return this; - } - - public MessageUnpacker setStringSizeLimit(int bytes) - { - this.stringSizeLimit = bytes; - return this; - } - - public MessageUnpacker setStringDecoderBufferSize(int bytes) - { - this.stringDecoderBufferSize = bytes; - return this; + // We need to copy the configuration parameters since the config object is mutable + this.allowStringAsBinary = config.allowStringAsBinary; + this.allowBinaryAsString = config.allowBinaryAsString; + this.actionOnMalformedString = config.actionOnMalformedString; + this.actionOnUnmappableString = config.actionOnUnmappableString; + this.stringSizeLimit = config.stringSizeLimit; + this.stringDecoderBufferSize = config.stringDecoderBufferSize; } /** diff --git a/msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java b/msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java deleted file mode 100644 index c3e39462d..000000000 --- a/msgpack-core/src/main/java/org/msgpack/core/MesssagePackerConfig.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.msgpack.core; - -/** - * - */ -public class MesssagePackerConfig -{ -} diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index 9a8242591..cbaf44f9b 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -17,7 +17,7 @@ import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePack; -import org.msgpack.core.MessagePackFactory; +import org.msgpack.core.MessagePack.PackerConfig; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; import org.msgpack.value.ArrayValue; @@ -245,23 +245,21 @@ else if (iv.isInLongRange()) { public static void configuration() throws IOException { - // Build a conifiguration - MessagePackFactory factory = new MessagePackFactory() - .unpackActionOnMalformedString(CodingErrorAction.REPLACE) // Drop malformed and unmappable UTF-8 characters - .unpackActionOnUnmappableString(CodingErrorAction.REPLACE) - .outputBufferSize(8192 * 2); - // Create a that uses this configuration - - // Pack data ByteArrayOutputStream out = new ByteArrayOutputStream(); - MessagePacker packer = factory.newPacker(out); + PackerConfig packerConfig = new PackerConfig(); + packerConfig.smallStringOptimizationThreshold = 256; // String + MessagePacker packer = packerConfig.newPacker(out); + packer.packInt(10); packer.packBoolean(true); packer.close(); // Unpack data + MessagePack.UnpackerConfig unpackerConfig = new MessagePack.UnpackerConfig(); + unpackerConfig.stringDecoderBufferSize = 16 * 1024; // If your data contains many large strings (the default is 8k) + byte[] packedData = out.toByteArray(); - MessageUnpacker unpacker = factory.newUnpacker(packedData); + MessageUnpacker unpacker = unpackerConfig.newUnpacker(packedData); int i = unpacker.unpackInt(); // 10 boolean b = unpacker.unpackBoolean(); // true unpacker.close(); diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index e1dc1d673..d11383e7f 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -21,6 +21,7 @@ import java.nio.CharBuffer import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} import org.msgpack.core.MessageFormat.Code +import org.msgpack.core.MessagePack.{UnpackerConfig, PackerConfig} import org.msgpack.value.{Value, Variable} import scala.util.Random @@ -60,13 +61,13 @@ class MessagePackTest extends MessagePackSpec { } "detect fixarray values" in { - val packer = new MessagePackFactory().newBufferPacker() + val packer = MessagePack.newDefaultBufferPacker() packer.packArrayHeader(0) packer.close val bytes = packer.toByteArray - new MessagePackFactory().newUnpacker(bytes).unpackArrayHeader() shouldBe 0 + MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() shouldBe 0 try { - new MessagePackFactory().newUnpacker(bytes).unpackMapHeader() + MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() fail("Shouldn't reach here") } catch { @@ -75,13 +76,13 @@ class MessagePackTest extends MessagePackSpec { } "detect fixmap values" in { - val packer = new MessagePackFactory().newBufferPacker() + val packer = MessagePack.newDefaultBufferPacker() packer.packMapHeader(0) packer.close val bytes = packer.toByteArray - new MessagePackFactory().newUnpacker(bytes).unpackMapHeader() shouldBe 0 + MessagePack.newDefaultUnpacker(bytes).unpackMapHeader() shouldBe 0 try { - new MessagePackFactory().newUnpacker(bytes).unpackArrayHeader() + MessagePack.newDefaultUnpacker(bytes).unpackArrayHeader() fail("Shouldn't reach here") } catch { @@ -147,17 +148,23 @@ class MessagePackTest extends MessagePackSpec { } - def check[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A, factory: MessagePackFactory = new MessagePackFactory()): Unit = { + def check[A]( + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A, + packerConfig: PackerConfig = new PackerConfig(), + unpackerConfig: UnpackerConfig = new UnpackerConfig() + ): Unit = { var b: Array[Byte] = null try { val bs = new ByteArrayOutputStream() - val packer = factory.newPacker(bs) + val packer = packerConfig.newPacker(bs) pack(packer) packer.close() b = bs.toByteArray - val unpacker = factory.newUnpacker(b) + val unpacker = unpackerConfig.newUnpacker(b) val ret = unpack(unpacker) ret shouldBe v } @@ -171,17 +178,22 @@ class MessagePackTest extends MessagePackSpec { } } - def checkException[A](v: A, pack: MessagePacker => Unit, unpack: MessageUnpacker => A, - factory: MessagePackFactory = new MessagePackFactory()): Unit = { + def checkException[A]( + v: A, + pack: MessagePacker => Unit, + unpack: MessageUnpacker => A, + packerConfig: PackerConfig = new PackerConfig(), + unpaackerConfig: UnpackerConfig = new UnpackerConfig() + ): Unit = { var b: Array[Byte] = null val bs = new ByteArrayOutputStream() - val packer = factory.newPacker(bs) + val packer = packerConfig.newPacker(bs) pack(packer) packer.close() b = bs.toByteArray - val unpacker = factory.newUnpacker(b) + val unpacker = unpaackerConfig.newUnpacker(b) val ret = unpack(unpacker) fail("cannot not reach here") @@ -196,9 +208,6 @@ class MessagePackTest extends MessagePackSpec { } } - - - "pack/unpack primitive values" taggedAs ("prim") in { forAll { (v: Boolean) => check(v, _.packBoolean(v), _.unpackBoolean) } forAll { (v: Byte) => check(v, _.packByte(v), _.unpackByte) } @@ -327,9 +336,9 @@ class MessagePackTest extends MessagePackSpec { //val unmappableChar = Array[Char](new Character(0xfc0a).toChar) // Report error on unmappable character - val factory = new MessagePackFactory() - .unpackActionOnMalformedString(CodingErrorAction.REPORT) - .unpackActionOnUnmappableString(CodingErrorAction.REPORT); + val unpackerConfig = new UnpackerConfig() + unpackerConfig.actionOnMalformedString = CodingErrorAction.REPORT + unpackerConfig.actionOnUnmappableString = CodingErrorAction.REPORT for (bytes <- Seq(unmappable)) { When("unpacking") @@ -339,20 +348,12 @@ class MessagePackTest extends MessagePackSpec { packer.writePayload(bytes) }, _.unpackString(), - factory) + new PackerConfig(), + unpackerConfig) } catch { case e: MessageStringCodingException => // OK } - - // When("packing") - // try { - // val s = new String(unmappableChar) - // checkException(s, _.packString(s), _.unpackString()) - // } - // catch { - // case e:MessageStringCodingException => // OK - // } } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala index 51d411f5f..2fbe461d1 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackerTest.scala @@ -16,8 +16,8 @@ package org.msgpack.core import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} -import java.nio.ByteBuffer +import org.msgpack.core.MessagePack.{UnpackerConfig, PackerConfig} import org.msgpack.core.buffer.{ChannelBufferOutput, OutputStreamBufferOutput} import org.msgpack.value.ValueFactory import xerial.core.io.IOUtil @@ -27,13 +27,10 @@ import scala.util.Random /** * */ -class MessagePackerTest - extends MessagePackSpec { - - val factory = new MessagePackFactory() +class MessagePackerTest extends MessagePackSpec { def verifyIntSeq(answer: Array[Int], packed: Array[Byte]) { - val unpacker = factory.newUnpacker(packed) + val unpacker = MessagePack.newDefaultUnpacker(packed) val b = Array.newBuilder[Int] while (unpacker.hasNext) { b += unpacker.unpackInt() @@ -69,7 +66,7 @@ class MessagePackerTest val b = new ByteArrayOutputStream - val packer = factory.newPacker(b) + val packer = MessagePack.newDefaultPacker(b) intSeq foreach packer.packInt packer.close verifyIntSeq(intSeq, b.toByteArray) @@ -102,7 +99,7 @@ class MessagePackerTest block("no-buffer-reset") { val out = new ByteArrayOutputStream - IOUtil.withResource(factory.newPacker(out)) { packer => + IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => for (i <- 0 until N) { val outputStream = new ByteArrayOutputStream() @@ -118,7 +115,7 @@ class MessagePackerTest block("buffer-reset") { val out = new ByteArrayOutputStream - IOUtil.withResource(factory.newPacker(out)) { packer => + IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => val bufferOut = new OutputStreamBufferOutput(new ByteArrayOutputStream()) @@ -140,23 +137,19 @@ class MessagePackerTest "pack larger string array than byte buf" taggedAs ("larger-string-array-than-byte-buf") in { // Based on https://github.com/msgpack/msgpack-java/issues/154 - // TODO: Refactor this test code to fit other ones. def test(bufferSize: Int, stringSize: Int): Boolean = { - val factory = new MessagePackFactory() - .outputBufferSize(bufferSize); val str = "a" * stringSize val rawString = ValueFactory.newString(str.getBytes("UTF-8")) val array = ValueFactory.newArray(rawString) - val out = new - ByteArrayOutputStream() - val packer = factory.newPacker(out) + val out = new ByteArrayOutputStream(bufferSize) + val packer = MessagePack.newDefaultPacker(out) packer.packValue(array) packer.close() out.toByteArray true } - val testCases = List( + val testCases = Seq( 32 -> 30, 33 -> 31, 32 -> 31, @@ -265,7 +258,7 @@ class MessagePackerTest "compute totalWrittenBytes" in { val out = new ByteArrayOutputStream - val packerTotalWrittenBytes = IOUtil.withResource(factory.newPacker(out)) { packer => + val packerTotalWrittenBytes = IOUtil.withResource(MessagePack.newDefaultPacker(out)) { packer => packer.packByte(0) // 1 .packBoolean(true) // 1 .packShort(12) // 1 diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala index 2611d8c9d..e8ed65be7 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageUnpackerTest.scala @@ -29,11 +29,9 @@ import scala.util.Random */ class MessageUnpackerTest extends MessagePackSpec { - val factory = new MessagePackFactory() - def testData: Array[Byte] = { val out = new ByteArrayOutputStream() - val packer = factory.newPacker(out) + val packer = MessagePack.newDefaultPacker(out) packer .packArrayHeader(2) @@ -55,7 +53,7 @@ class MessageUnpackerTest extends MessagePackSpec { def testData2: Array[Byte] = { val out = new ByteArrayOutputStream() - val packer = factory.newPacker(out); + val packer = MessagePack.newDefaultPacker(out); packer .packBoolean(true) @@ -125,7 +123,7 @@ class MessageUnpackerTest extends MessagePackSpec { def testData3(N: Int): Array[Byte] = { val out = new ByteArrayOutputStream() - val packer = factory.newPacker(out) + val packer = MessagePack.newDefaultPacker(out) val r = new Random(0) @@ -179,7 +177,7 @@ class MessageUnpackerTest extends MessagePackSpec { "parse message packed data" taggedAs ("unpack") in { val arr = testData - val unpacker = factory.newUnpacker(arr) + val unpacker = MessagePack.newDefaultUnpacker(arr) var count = 0 while (unpacker.hasNext) { @@ -192,7 +190,7 @@ class MessageUnpackerTest extends MessagePackSpec { "skip reading values" in { - val unpacker = factory.newUnpacker(testData) + val unpacker = MessagePack.newDefaultUnpacker(testData) var skipCount = 0 while (unpacker.hasNext) { unpacker.skipValue() @@ -209,7 +207,7 @@ class MessageUnpackerTest extends MessagePackSpec { time("skip performance", repeat = 100) { block("switch") { - val unpacker = factory.newUnpacker(data) + val unpacker = MessagePack.newDefaultUnpacker(data) var skipCount = 0 while (unpacker.hasNext) { unpacker.skipValue() @@ -227,7 +225,7 @@ class MessageUnpackerTest extends MessagePackSpec { val ib = Seq.newBuilder[Int] - val unpacker = factory.newUnpacker(testData2) + val unpacker = MessagePack.newDefaultUnpacker(testData2) while (unpacker.hasNext) { val f = unpacker.getNextFormat f.getValueType match { @@ -269,7 +267,7 @@ class MessageUnpackerTest extends MessagePackSpec { trait SplitTest { val data: Array[Byte] def run { - val unpacker = factory.newUnpacker(data) + val unpacker = MessagePack.newDefaultUnpacker(data) val numElems = { var c = 0 while (unpacker.hasNext) { @@ -283,7 +281,7 @@ class MessageUnpackerTest extends MessagePackSpec { debug(s"split at $splitPoint") val (h, t) = data.splitAt(splitPoint) val bin = new SplitMessageBufferInput(Array(h, t)) - val unpacker = new MessageUnpacker(bin) + val unpacker = MessagePack.newDefaultUnpacker(bin) var count = 0 while (unpacker.hasNext) { count += 1 @@ -326,7 +324,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7") { - val unpacker = factory.newUnpacker(data) + val unpacker = MessagePack.newDefaultUnpacker(data) var count = 0 try { while (unpacker.hasNext) { @@ -428,7 +426,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7") { - val unpacker = factory.newUnpacker(data) + val unpacker = MessagePack.newDefaultUnpacker(data) var count = 0 try { while (unpacker.hasNext) { @@ -449,7 +447,7 @@ class MessageUnpackerTest extends MessagePackSpec { "be faster for reading binary than v6" taggedAs ("cmp-binary") in { val bos = new ByteArrayOutputStream() - val packer = factory.newPacker(bos) + val packer = MessagePack.newDefaultPacker(bos) val L = 10000 val R = 100 (0 until R).foreach { i => @@ -472,7 +470,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7") { - val unpacker = factory.newUnpacker(b) + val unpacker = MessagePack.newDefaultUnpacker(b) var i = 0 while (i < R) { val len = unpacker.unpackBinaryHeader() @@ -484,7 +482,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("v7-ref") { - val unpacker = factory.newUnpacker(b) + val unpacker = MessagePack.newDefaultUnpacker(b) var i = 0 while (i < R) { val len = unpacker.unpackBinaryHeader() @@ -505,12 +503,12 @@ class MessageUnpackerTest extends MessagePackSpec { val data = new Array[Byte](s) Random.nextBytes(data) val b = new ByteArrayOutputStream() - val packer = factory.newPacker(b) + val packer = MessagePack.newDefaultPacker(b) packer.packBinaryHeader(s) packer.writePayload(data) packer.close() - val unpacker = factory.newUnpacker(b.toByteArray) + val unpacker = MessagePack.newDefaultUnpacker(b.toByteArray) val len = unpacker.unpackBinaryHeader() len shouldBe s val ref = unpacker.readPayloadAsReference(len) @@ -529,7 +527,7 @@ class MessageUnpackerTest extends MessagePackSpec { val data = intSeq val b = createMessagePackData(packer => data foreach packer.packInt) - val unpacker = factory.newUnpacker(b) + val unpacker = MessagePack.newDefaultUnpacker(b) val unpacked = Array.newBuilder[Int] while (unpacker.hasNext) { @@ -564,7 +562,7 @@ class MessageUnpackerTest extends MessagePackSpec { "improve the performance via reset method" taggedAs ("reset-arr") in { val out = new ByteArrayOutputStream - val packer = factory.newPacker(out) + val packer = MessagePack.newDefaultPacker(out) packer.packInt(0) packer.flush val arr = out.toByteArray @@ -573,7 +571,7 @@ class MessageUnpackerTest extends MessagePackSpec { val N = 1000 val t = time("unpacker", repeat = 10) { block("no-buffer-reset") { - IOUtil.withResource(factory.newUnpacker(arr)) { unpacker => + IOUtil.withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => for (i <- 0 until N) { val buf = new ArrayBufferInput(arr) unpacker.reset(buf) @@ -584,7 +582,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("reuse-array-input") { - IOUtil.withResource(factory.newUnpacker(arr)) { unpacker => + IOUtil.withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => val buf = new ArrayBufferInput(arr) for (i <- 0 until N) { buf.reset(arr) @@ -596,7 +594,7 @@ class MessageUnpackerTest extends MessagePackSpec { } block("reuse-message-buffer") { - IOUtil.withResource(factory.newUnpacker(arr)) { unpacker => + IOUtil.withResource(MessagePack.newDefaultUnpacker(arr)) { unpacker => val buf = new ArrayBufferInput(arr) for (i <- 0 until N) { buf.reset(mb) @@ -640,7 +638,7 @@ class MessageUnpackerTest extends MessagePackSpec { "unpack large string data" taggedAs ("large-string") in { def createLargeData(stringLength: Int): Array[Byte] = { val out = new ByteArrayOutputStream() - val packer = factory.newPacker(out) + val packer = MessagePack.newDefaultPacker(out) packer .packArrayHeader(2) @@ -655,7 +653,7 @@ class MessageUnpackerTest extends MessagePackSpec { Seq(8191, 8192, 8193, 16383, 16384, 16385).foreach { n => val arr = createLargeData(n) - val unpacker = factory.newUnpacker(arr) + val unpacker = MessagePack.newDefaultUnpacker(arr) unpacker.unpackArrayHeader shouldBe 2 unpacker.unpackString.length shouldBe n @@ -676,7 +674,7 @@ class MessageUnpackerTest extends MessagePackSpec { packer.packString(expected) packer.close - val unpacker = new MessageUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(out.toByteArray))) + val unpacker = MessagePack.newDefaultUnpacker(new InputStreamBufferInput(new ByteArrayInputStream(out.toByteArray))) val len = unpacker.unpackBinaryHeader unpacker.readPayload(len) val got = unpacker.unpackString diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala index eb78432d2..2c080b59a 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/ByteStringTest.scala @@ -16,7 +16,7 @@ package org.msgpack.core.buffer import akka.util.ByteString -import org.msgpack.core.{MessagePackSpec, MessageUnpacker} +import org.msgpack.core.{MessagePack, MessagePackSpec, MessageUnpacker} class ByteStringTest extends MessagePackSpec { @@ -41,7 +41,6 @@ class ByteStringTest override def close(): Unit = {} } - new - MessageUnpacker(input).unpackString() + MessagePack.newDefaultUnpacker(input).unpackString() } } diff --git a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala index 6333e381c..1638806ee 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala @@ -24,9 +24,6 @@ import xerial.core.io.IOUtil._ import scala.util.Random -/** - * Created on 5/30/14. - */ class MessageBufferInputTest extends MessagePackSpec { @@ -144,8 +141,7 @@ class MessageBufferInputTest } def readInt(buf: MessageBufferInput): Int = { - val unpacker = new - MessageUnpacker(buf) + val unpacker = MessagePack.newDefaultUnpacker(buf) unpacker.unpackInt } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java index c040ee7dd..e62528a75 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.core.base.GeneratorBase; import com.fasterxml.jackson.core.json.JsonWriteContext; +import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; import org.msgpack.core.buffer.OutputStreamBufferOutput; @@ -109,7 +110,7 @@ public MessagePackGenerator(int features, ObjectCodec codec, OutputStream out) messageBufferOutputHolder.set(messageBufferOutput); if (messagePacker == null) { - messagePacker = new MessagePacker(messageBufferOutput); + messagePacker = MessagePack.newDefaultPacker(messageBufferOutput); } else { messagePacker.reset(messageBufferOutput); diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 08be64e59..e85ff7cd6 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -28,6 +28,7 @@ import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.json.DupDetector; import com.fasterxml.jackson.core.json.JsonReadContext; +import org.msgpack.core.MessagePack; import org.msgpack.core.MessageUnpacker; import org.msgpack.core.buffer.ArrayBufferInput; import org.msgpack.core.buffer.InputStreamBufferInput; @@ -126,7 +127,7 @@ private MessagePackParser(IOContext ctxt, int features, MessageBufferInput input MessageUnpacker messageUnpacker; Tuple messageUnpackerTuple = messageUnpackerHolder.get(); if (messageUnpackerTuple == null) { - messageUnpacker = new MessageUnpacker(input); + messageUnpacker = MessagePack.newDefaultUnpacker(input); } else { // Considering to reuse InputStream with JsonParser.Feature.AUTO_CLOSE_SOURCE, diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index 845c45f40..d7f8be600 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -86,7 +86,7 @@ public void testGeneratorShouldWriteObject() long bitmap = 0; byte[] bytes = objectMapper.writeValueAsBytes(hashMap); - MessageUnpacker messageUnpacker = new MessageUnpacker(new ArrayBufferInput(bytes)); + MessageUnpacker messageUnpacker = MessagePack.newDefaultUnpacker(new ArrayBufferInput(bytes)); assertEquals(hashMap.size(), messageUnpacker.unpackMapHeader()); for (int i = 0; i < hashMap.size(); i++) { String key = messageUnpacker.unpackString(); @@ -199,7 +199,7 @@ public void testGeneratorShouldWriteArray() long bitmap = 0; byte[] bytes = objectMapper.writeValueAsBytes(array); - MessageUnpacker messageUnpacker = new MessageUnpacker(new ArrayBufferInput(bytes)); + MessageUnpacker messageUnpacker = MessagePack.newDefaultUnpacker(new ArrayBufferInput(bytes)); assertEquals(array.size(), messageUnpacker.unpackArrayHeader()); // #1 assertEquals("komamitsu", messageUnpacker.unpackString()); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 3321110d4..065d398b3 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -54,7 +54,7 @@ public class MessagePackParserTest public void testParserShouldReadObject() throws IOException { - MessagePacker packer = new MessagePacker(new OutputStreamBufferOutput(out)); + MessagePacker packer = MessagePack.newDefaultPacker(out); packer.packMapHeader(9); // #1 packer.packString("str"); @@ -182,7 +182,7 @@ else if (k.equals("ext")) { public void testParserShouldReadArray() throws IOException { - MessagePacker packer = new MessagePacker(new OutputStreamBufferOutput(out)); + MessagePacker packer = MessagePack.newDefaultPacker(out); packer.packArrayHeader(11); // #1 packer.packArrayHeader(3); @@ -387,7 +387,7 @@ public void testBigDecimal() { double d0 = 1.23456789; double d1 = 1.23450000000000000000006789; - MessagePacker packer = new MessagePacker(new OutputStreamBufferOutput(out)); + MessagePacker packer = MessagePack.newDefaultPacker(out); packer.packArrayHeader(5); packer.packDouble(d0); packer.packDouble(d1); From 645abde9c1f76a184d78ae0e56ccd384da2c7456 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 15:36:27 +0900 Subject: [PATCH 76/99] Revert MessagePackFormatFactory -> MessagePackFactory --- ...atFactory.java => MessagePackFactory.java} | 2 +- .../ExampleOfTypeInformationSerDe.java | 2 +- .../MessagePackDataformatTestBase.java | 4 +-- ...yTest.java => MessagePackFactoryTest.java} | 2 +- .../dataformat/MessagePackGeneratorTest.java | 14 +++++----- .../dataformat/MessagePackParserTest.java | 27 +++++++++---------- ...gePackDataformatHugeDataBenchmarkTest.java | 6 ++--- ...essagePackDataformatPojoBenchmarkTest.java | 4 +-- 8 files changed, 30 insertions(+), 31 deletions(-) rename msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/{MessagePackFormatFactory.java => MessagePackFactory.java} (98%) rename msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/{MessagePackFormatFactoryTest.java => MessagePackFactoryTest.java} (97%) diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java similarity index 98% rename from msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java rename to msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java index 1082e5770..ff7aa373f 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFormatFactory.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java @@ -30,7 +30,7 @@ import java.io.Writer; import java.util.Arrays; -public class MessagePackFormatFactory +public class MessagePackFactory extends JsonFactory { private static final long serialVersionUID = 2578263992015504347L; diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java index 6a211b3ae..5414b0bdc 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/ExampleOfTypeInformationSerDe.java @@ -151,7 +151,7 @@ public void test() objectContainer.getObjects().put("pi", pi); } - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); byte[] bytes = objectMapper.writeValueAsBytes(objectContainer); ObjectContainer restored = objectMapper.readValue(bytes, ObjectContainer.class); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java index c9692ebf9..1d5156adc 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java @@ -35,7 +35,7 @@ public class MessagePackDataformatTestBase { - protected MessagePackFormatFactory factory; + protected MessagePackFactory factory; protected ByteArrayOutputStream out; protected ByteArrayInputStream in; protected ObjectMapper objectMapper; @@ -47,7 +47,7 @@ public class MessagePackDataformatTestBase @Before public void setup() { - factory = new MessagePackFormatFactory(); + factory = new MessagePackFactory(); objectMapper = new ObjectMapper(factory); out = new ByteArrayOutputStream(); in = new ByteArrayInputStream(new byte[4096]); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java similarity index 97% rename from msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java rename to msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java index f7e5fe045..25180f784 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFormatFactoryTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackFactoryTest.java @@ -24,7 +24,7 @@ import static org.junit.Assert.assertEquals; -public class MessagePackFormatFactoryTest +public class MessagePackFactoryTest extends MessagePackDataformatTestBase { @Test diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java index d7f8be600..fd2ea313f 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java @@ -236,7 +236,7 @@ else if (key.equals("num")) { public void testMessagePackGeneratorDirectly() throws Exception { - MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory(); + MessagePackFactory messagePackFactory = new MessagePackFactory(); File tempFile = createTempFile(); JsonGenerator generator = messagePackFactory.createGenerator(tempFile, JsonEncoding.UTF8); @@ -263,7 +263,7 @@ public void testMessagePackGeneratorDirectly() public void testWritePrimitives() throws Exception { - MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory(); + MessagePackFactory messagePackFactory = new MessagePackFactory(); File tempFile = createTempFile(); JsonGenerator generator = messagePackFactory.createGenerator(tempFile, JsonEncoding.UTF8); @@ -286,7 +286,7 @@ public void testWritePrimitives() public void testBigDecimal() throws IOException { - ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); { double d0 = 1.23456789; @@ -334,7 +334,7 @@ public void testEnableFeatureAutoCloseTarget() throws IOException { OutputStream out = createTempFileOutputStream(); - MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory(); + MessagePackFactory messagePackFactory = new MessagePackFactory(); ObjectMapper objectMapper = new ObjectMapper(messagePackFactory); List integers = Arrays.asList(1); objectMapper.writeValue(out, integers); @@ -347,7 +347,7 @@ public void testDisableFeatureAutoCloseTarget() { File tempFile = createTempFile(); OutputStream out = new FileOutputStream(tempFile); - MessagePackFormatFactory messagePackFactory = new MessagePackFormatFactory(); + MessagePackFactory messagePackFactory = new MessagePackFactory(); ObjectMapper objectMapper = new ObjectMapper(messagePackFactory); objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); List integers = Arrays.asList(1); @@ -369,7 +369,7 @@ public void testWritePrimitiveObjectViaObjectMapper() File tempFile = createTempFile(); OutputStream out = new FileOutputStream(tempFile); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); objectMapper.writeValue(out, 1); objectMapper.writeValue(out, "two"); @@ -393,7 +393,7 @@ public void testInMultiThreads() int threadCount = 8; final int loopCount = 4000; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); - final ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + final ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); final List buffers = new ArrayList(threadCount); List> results = new ArrayList>(); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java index 065d398b3..112390598 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackParserTest.java @@ -27,7 +27,6 @@ import org.junit.Test; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePacker; -import org.msgpack.core.buffer.OutputStreamBufferOutput; import java.io.ByteArrayOutputStream; import java.io.File; @@ -288,7 +287,7 @@ else if (k.equals("child_map_age")) { public void testMessagePackParserDirectly() throws IOException { - MessagePackFormatFactory factory = new MessagePackFormatFactory(); + MessagePackFactory factory = new MessagePackFactory(); File tempFile = File.createTempFile("msgpackTest", "msgpack"); tempFile.deleteOnExit(); @@ -354,7 +353,7 @@ public void testMessagePackParserDirectly() public void testReadPrimitives() throws Exception { - MessagePackFormatFactory factory = new MessagePackFormatFactory(); + MessagePackFactory factory = new MessagePackFactory(); File tempFile = createTempFile(); FileOutputStream out = new FileOutputStream(tempFile); @@ -396,7 +395,7 @@ public void testBigDecimal() packer.packDouble(Double.MIN_NORMAL); packer.flush(); - ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true); List objects = mapper.readValue(out.toByteArray(), new TypeReference>() {}); assertEquals(5, objects.size()); @@ -431,7 +430,7 @@ public void testEnableFeatureAutoCloseSource() throws Exception { File tempFile = createTestFile(); - MessagePackFormatFactory factory = new MessagePackFormatFactory(); + MessagePackFactory factory = new MessagePackFactory(); FileInputStream in = new FileInputStream(tempFile); ObjectMapper objectMapper = new ObjectMapper(factory); objectMapper.readValue(in, new TypeReference>() {}); @@ -444,7 +443,7 @@ public void testDisableFeatureAutoCloseSource() { File tempFile = createTestFile(); FileInputStream in = new FileInputStream(tempFile); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); objectMapper.readValue(in, new TypeReference>() {}); objectMapper.readValue(in, new TypeReference>() {}); @@ -456,7 +455,7 @@ public void testParseBigDecimal() { ArrayList list = new ArrayList(); list.add(new BigDecimal(Long.MAX_VALUE)); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); byte[] bytes = objectMapper.writeValueAsBytes(list); ArrayList result = objectMapper.readValue( @@ -481,7 +480,7 @@ public void testReadPrimitiveObjectViaObjectMapper() packer.close(); FileInputStream in = new FileInputStream(tempFile); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); assertEquals("foo", objectMapper.readValue(in, new TypeReference() {})); long l = objectMapper.readValue(in, new TypeReference() {}); @@ -511,7 +510,7 @@ public void testBinaryKey() packer.packLong(42); packer.close(); - ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); Map object = mapper.readValue(new FileInputStream(tempFile), new TypeReference>() {}); assertEquals(2, object.size()); assertEquals(3.14, object.get("foo")); @@ -533,7 +532,7 @@ public void testBinaryKeyInNestedObject() packer.packInt(1); packer.close(); - ObjectMapper mapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper mapper = new ObjectMapper(new MessagePackFactory()); List objects = mapper.readValue(out.toByteArray(), new TypeReference>() {}); assertEquals(2, objects.size()); @SuppressWarnings(value = "unchecked") @@ -555,7 +554,7 @@ public void testByteArrayKey() messagePacker.packBinaryHeader(1).writePayload(k1).packInt(3); messagePacker.close(); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); SimpleModule module = new SimpleModule(); module.addKeyDeserializer(byte[].class, new KeyDeserializer() { @@ -592,7 +591,7 @@ public void testIntegerKey() } messagePacker.close(); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); SimpleModule module = new SimpleModule(); module.addKeyDeserializer(Integer.class, new KeyDeserializer() { @@ -623,7 +622,7 @@ public void testFloatKey() } messagePacker.close(); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); SimpleModule module = new SimpleModule(); module.addKeyDeserializer(Float.class, new KeyDeserializer() { @@ -653,7 +652,7 @@ public void testBooleanKey() messagePacker.packBoolean(false).packInt(3); messagePacker.close(); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFormatFactory()); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); SimpleModule module = new SimpleModule(); module.addKeyDeserializer(Boolean.class, new KeyDeserializer() { diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java index aaf828439..b3a159111 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatHugeDataBenchmarkTest.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; -import org.msgpack.jackson.dataformat.MessagePackFormatFactory; +import org.msgpack.jackson.dataformat.MessagePackFactory; import java.io.File; import java.io.FileOutputStream; @@ -34,7 +34,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest private static final int COUNT = 6; private static final int WARMUP_COUNT = 4; private final ObjectMapper origObjectMapper = new ObjectMapper(); - private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory()); + private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory()); private static final List value; private static final byte[] packedByOriginal; private static final byte[] packedByMsgPack; @@ -61,7 +61,7 @@ public class MessagePackDataformatHugeDataBenchmarkTest packedByOriginal = bytes; try { - bytes = new ObjectMapper(new MessagePackFormatFactory()).writeValueAsBytes(value); + bytes = new ObjectMapper(new MessagePackFactory()).writeValueAsBytes(value); } catch (JsonProcessingException e) { e.printStackTrace(); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java index e6b627f5c..179b09891 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/benchmark/MessagePackDataformatPojoBenchmarkTest.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; -import org.msgpack.jackson.dataformat.MessagePackFormatFactory; +import org.msgpack.jackson.dataformat.MessagePackFactory; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.NormalPojo; import static org.msgpack.jackson.dataformat.MessagePackDataformatTestBase.Suit; @@ -41,7 +41,7 @@ public class MessagePackDataformatPojoBenchmarkTest private final List pojosSerWithOrig = new ArrayList(LOOP_MAX); private final List pojosSerWithMsgPack = new ArrayList(LOOP_MAX); private final ObjectMapper origObjectMapper = new ObjectMapper(); - private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFormatFactory()); + private final ObjectMapper msgpackObjectMapper = new ObjectMapper(new MessagePackFactory()); public MessagePackDataformatPojoBenchmarkTest() { From 2cb2fcc3f63d4b83ace398dccb9e421a5ac4a570 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 15:42:47 +0900 Subject: [PATCH 77/99] Fix typo --- .../src/main/java/org/msgpack/core/MessagePacker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index c54943d2c..e3ba1e0d2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -174,15 +174,15 @@ private void flushBuffer() position = 0; } - private void ensureCapacity(int mimimumSize) + private void ensureCapacity(int minimumSize) throws IOException { if (buffer == null) { - buffer = out.next(mimimumSize); + buffer = out.next(minimumSize); } - else if (position + mimimumSize >= buffer.size()) { + else if (position + minimumSize >= buffer.size()) { flushBuffer(); - buffer = out.next(mimimumSize); + buffer = out.next(minimumSize); } } From 23b188226fbbbb633245aa8180b63636c8983ade Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 15:44:38 +0900 Subject: [PATCH 78/99] Use static import --- .../test/java/org/msgpack/core/example/MessagePackExample.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index cbaf44f9b..0b0e50123 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -18,6 +18,7 @@ import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePack.PackerConfig; +import org.msgpack.core.MessagePack.UnpackerConfig; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; import org.msgpack.value.ArrayValue; @@ -255,7 +256,7 @@ public static void configuration() packer.close(); // Unpack data - MessagePack.UnpackerConfig unpackerConfig = new MessagePack.UnpackerConfig(); + UnpackerConfig unpackerConfig = new UnpackerConfig(); unpackerConfig.stringDecoderBufferSize = 16 * 1024; // If your data contains many large strings (the default is 8k) byte[] packedData = out.toByteArray(); From 1fab3f7d6e613801915d5785aa5fbf078398d0af Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 15:46:38 +0900 Subject: [PATCH 79/99] Remove comment --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 1602aa165..176e60863 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -549,9 +549,6 @@ public Variable unpackValue(Variable var) int size = unpackArrayHeader(); List list = new ArrayList(size); for (int i = 0; i < size; i++) { - //Variable e = new Variable(); - //unpackValue(e); - //list.add(e); list.add(unpackValue()); } var.setArrayValue(list); @@ -561,10 +558,6 @@ public Variable unpackValue(Variable var) int size = unpackMapHeader(); Map map = new HashMap(); for (int i = 0; i < size; i++) { - //Variable k = new Variable(); - //unpackValue(k); - //Variable v = new Variable(); - //unpackValue(v); Value k = unpackValue(); Value v = unpackValue(); map.put(k, v); From d29276f7b6417af5d7a6a0a4837cb3cbed0c829d Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 15:53:49 +0900 Subject: [PATCH 80/99] Revert the removed configuration comments and use more redable configuration names --- .../java/org/msgpack/core/MessagePack.java | 59 +++++++++++++++---- .../org/msgpack/core/MessageUnpacker.java | 14 ++--- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 02f94cde4..626447c31 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -147,6 +147,10 @@ public static MessageUnpacker newDefaultUnpacker(byte[] contents, int offset, in */ public static class PackerConfig { + /** + * Use String.getBytes() for converting Java Strings that are smaller than this threshold into UTF8. + * Note that this parameter is subject to change. + */ public int smallStringOptimizationThreshold = 512; /** @@ -155,7 +159,8 @@ public static class PackerConfig * @param out * @return */ - public MessagePacker newPacker(MessageBufferOutput out) { + public MessagePacker newPacker(MessageBufferOutput out) + { return new MessagePacker(out, this); } @@ -165,7 +170,8 @@ public MessagePacker newPacker(MessageBufferOutput out) { * @param out * @return */ - public MessagePacker newPacker(OutputStream out) { + public MessagePacker newPacker(OutputStream out) + { return newPacker(new OutputStreamBufferOutput(out)); } @@ -175,7 +181,8 @@ public MessagePacker newPacker(OutputStream out) { * @param channel * @return */ - public MessagePacker newPacker(WritableByteChannel channel) { + public MessagePacker newPacker(WritableByteChannel channel) + { return newPacker(new ChannelBufferOutput(channel)); } @@ -184,7 +191,8 @@ public MessagePacker newPacker(WritableByteChannel channel) { * * @return */ - public MessageBufferPacker newBufferPacker() { + public MessageBufferPacker newBufferPacker() + { return new MessageBufferPacker(this); } } @@ -194,11 +202,34 @@ public MessageBufferPacker newBufferPacker() { */ public static class UnpackerConfig { - public boolean allowStringAsBinary = true; - public boolean allowBinaryAsString = true; + /** + * Allow unpackBinaryHeader to read str format family (default:true) + */ + public boolean allowReadingStringAsBinary = true; + + /** + * Allow unpackRawStringHeader and unpackString to read bin format family (default: true) + */ + public boolean allowReadingBinaryAsString = true; + + /** + * Action when encountered a malformed input + */ public CodingErrorAction actionOnMalformedString = CodingErrorAction.REPLACE; + + /** + * Action when an unmappable character is found + */ public CodingErrorAction actionOnUnmappableString = CodingErrorAction.REPLACE; + + /** + * unpackString size limit. (default: Integer.MAX_VALUE) + */ public int stringSizeLimit = Integer.MAX_VALUE; + + /** + * + */ public int stringDecoderBufferSize = 8192; /** @@ -207,7 +238,8 @@ public static class UnpackerConfig * @param in * @return */ - public MessageUnpacker newUnpacker(MessageBufferInput in) { + public MessageUnpacker newUnpacker(MessageBufferInput in) + { return new MessageUnpacker(in, this); } @@ -217,7 +249,8 @@ public MessageUnpacker newUnpacker(MessageBufferInput in) { * @param in * @return */ - public MessageUnpacker newUnpacker(InputStream in) { + public MessageUnpacker newUnpacker(InputStream in) + { return newUnpacker(new InputStreamBufferInput(in)); } @@ -227,7 +260,8 @@ public MessageUnpacker newUnpacker(InputStream in) { * @param channel * @return */ - public MessageUnpacker newUnpacker(ReadableByteChannel channel) { + public MessageUnpacker newUnpacker(ReadableByteChannel channel) + { return newUnpacker(new ChannelBufferInput(channel)); } @@ -237,7 +271,8 @@ public MessageUnpacker newUnpacker(ReadableByteChannel channel) { * @param contents * @return */ - public MessageUnpacker newUnpacker(byte[] contents) { + public MessageUnpacker newUnpacker(byte[] contents) + { return newUnpacker(new ArrayBufferInput(contents)); } @@ -247,9 +282,9 @@ public MessageUnpacker newUnpacker(byte[] contents) { * @param contents * @return */ - public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) { + public MessageUnpacker newUnpacker(byte[] contents, int offset, int length) + { return newUnpacker(new ArrayBufferInput(contents, offset, length)); } - } } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 176e60863..c4a8fc35b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -73,8 +73,8 @@ public class MessageUnpacker private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1; - private final boolean allowStringAsBinary; - private final boolean allowBinaryAsString; + private final boolean allowReadingStringAsBinary; + private final boolean allowReadingBinaryAsString; private final CodingErrorAction actionOnMalformedString; private final CodingErrorAction actionOnUnmappableString; private final int stringSizeLimit; @@ -134,10 +134,10 @@ public MessageUnpacker(MessageBufferInput in, MessagePack.UnpackerConfig config) { this.in = checkNotNull(in, "MessageBufferInput is null"); // We need to copy the configuration parameters since the config object is mutable - this.allowStringAsBinary = config.allowStringAsBinary; - this.allowBinaryAsString = config.allowBinaryAsString; + this.allowReadingStringAsBinary = config.allowReadingStringAsBinary; + this.allowReadingBinaryAsString = config.allowReadingBinaryAsString; this.actionOnMalformedString = config.actionOnMalformedString; - this.actionOnUnmappableString = config.actionOnUnmappableString; + this.actionOnUnmappableString = config.actionOnUnmappableString; this.stringSizeLimit = config.stringSizeLimit; this.stringDecoderBufferSize = config.stringDecoderBufferSize; } @@ -1149,7 +1149,7 @@ public int unpackRawStringHeader() return len; } - if (allowBinaryAsString) { + if (allowReadingBinaryAsString) { len = tryReadBinaryHeader(b); if (len >= 0) { return len; @@ -1170,7 +1170,7 @@ public int unpackBinaryHeader() return len; } - if (allowStringAsBinary) { + if (allowReadingStringAsBinary) { len = tryReadStringHeader(b); if (len >= 0) { return len; From f7d57e3f98fe3dccb0ff5f886545cd279c8aa755 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 16:10:08 +0900 Subject: [PATCH 81/99] Relocate Code class inside MessagePack again since it is used for Packer/Unpacker, which do not need to depend on MessageFormat enum --- .../java/org/msgpack/core/MessageFormat.java | 89 +------------------ .../java/org/msgpack/core/MessagePack.java | 89 +++++++++++++++++++ .../java/org/msgpack/core/MessagePacker.java | 68 +++++++------- .../org/msgpack/core/MessageUnpacker.java | 2 +- .../org/msgpack/core/MessageFormatTest.scala | 2 +- .../org/msgpack/core/MessagePackTest.scala | 2 +- .../org/msgpack/value/ValueTypeTest.scala | 12 +-- 7 files changed, 134 insertions(+), 130 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java index 5a20518dc..d57c446f2 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageFormat.java @@ -17,6 +17,7 @@ import org.msgpack.core.annotations.VisibleForTesting; import org.msgpack.value.ValueType; +import org.msgpack.core.MessagePack.Code; /** * Describes the list of the message format types defined in the MessagePack specification. @@ -65,94 +66,6 @@ public enum MessageFormat MAP32(ValueType.MAP), NEGFIXINT(ValueType.INTEGER); - /** - * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. - */ - public static final class Code - { - public static final boolean isFixInt(byte b) - { - int v = b & 0xFF; - return v <= 0x7f || v >= 0xe0; - } - - public static final boolean isPosFixInt(byte b) - { - return (b & POSFIXINT_MASK) == 0; - } - - public static final boolean isNegFixInt(byte b) - { - return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; - } - - public static final boolean isFixStr(byte b) - { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final boolean isFixedArray(byte b) - { - return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; - } - - public static final boolean isFixedMap(byte b) - { - return (b & (byte) 0xf0) == Code.FIXMAP_PREFIX; - } - - public static final boolean isFixedRaw(byte b) - { - return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; - } - - public static final byte POSFIXINT_MASK = (byte) 0x80; - - public static final byte FIXMAP_PREFIX = (byte) 0x80; - public static final byte FIXARRAY_PREFIX = (byte) 0x90; - public static final byte FIXSTR_PREFIX = (byte) 0xa0; - - public static final byte NIL = (byte) 0xc0; - public static final byte NEVER_USED = (byte) 0xc1; - public static final byte FALSE = (byte) 0xc2; - public static final byte TRUE = (byte) 0xc3; - public static final byte BIN8 = (byte) 0xc4; - public static final byte BIN16 = (byte) 0xc5; - public static final byte BIN32 = (byte) 0xc6; - public static final byte EXT8 = (byte) 0xc7; - public static final byte EXT16 = (byte) 0xc8; - public static final byte EXT32 = (byte) 0xc9; - public static final byte FLOAT32 = (byte) 0xca; - public static final byte FLOAT64 = (byte) 0xcb; - public static final byte UINT8 = (byte) 0xcc; - public static final byte UINT16 = (byte) 0xcd; - public static final byte UINT32 = (byte) 0xce; - public static final byte UINT64 = (byte) 0xcf; - - public static final byte INT8 = (byte) 0xd0; - public static final byte INT16 = (byte) 0xd1; - public static final byte INT32 = (byte) 0xd2; - public static final byte INT64 = (byte) 0xd3; - - public static final byte FIXEXT1 = (byte) 0xd4; - public static final byte FIXEXT2 = (byte) 0xd5; - public static final byte FIXEXT4 = (byte) 0xd6; - public static final byte FIXEXT8 = (byte) 0xd7; - public static final byte FIXEXT16 = (byte) 0xd8; - - public static final byte STR8 = (byte) 0xd9; - public static final byte STR16 = (byte) 0xda; - public static final byte STR32 = (byte) 0xdb; - - public static final byte ARRAY16 = (byte) 0xdc; - public static final byte ARRAY32 = (byte) 0xdd; - - public static final byte MAP16 = (byte) 0xde; - public static final byte MAP32 = (byte) 0xdf; - - public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; - } - private static final MessageFormat[] formatTable = new MessageFormat[256]; private final ValueType valueType; diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 626447c31..bcc9d9359 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -37,6 +37,95 @@ public class MessagePack { public static final Charset UTF8 = Charset.forName("UTF-8"); + /** + * The prefix code set of MessagePack. See also https://github.com/msgpack/msgpack/blob/master/spec.md for details. + */ + public static final class Code + { + public static final boolean isFixInt(byte b) + { + int v = b & 0xFF; + return v <= 0x7f || v >= 0xe0; + } + + public static final boolean isPosFixInt(byte b) + { + return (b & POSFIXINT_MASK) == 0; + } + + public static final boolean isNegFixInt(byte b) + { + return (b & NEGFIXINT_PREFIX) == NEGFIXINT_PREFIX; + } + + public static final boolean isFixStr(byte b) + { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final boolean isFixedArray(byte b) + { + return (b & (byte) 0xf0) == Code.FIXARRAY_PREFIX; + } + + public static final boolean isFixedMap(byte b) + { + return (b & (byte) 0xf0) == Code.FIXMAP_PREFIX; + } + + public static final boolean isFixedRaw(byte b) + { + return (b & (byte) 0xe0) == Code.FIXSTR_PREFIX; + } + + public static final byte POSFIXINT_MASK = (byte) 0x80; + + public static final byte FIXMAP_PREFIX = (byte) 0x80; + public static final byte FIXARRAY_PREFIX = (byte) 0x90; + public static final byte FIXSTR_PREFIX = (byte) 0xa0; + + public static final byte NIL = (byte) 0xc0; + public static final byte NEVER_USED = (byte) 0xc1; + public static final byte FALSE = (byte) 0xc2; + public static final byte TRUE = (byte) 0xc3; + public static final byte BIN8 = (byte) 0xc4; + public static final byte BIN16 = (byte) 0xc5; + public static final byte BIN32 = (byte) 0xc6; + public static final byte EXT8 = (byte) 0xc7; + public static final byte EXT16 = (byte) 0xc8; + public static final byte EXT32 = (byte) 0xc9; + public static final byte FLOAT32 = (byte) 0xca; + public static final byte FLOAT64 = (byte) 0xcb; + public static final byte UINT8 = (byte) 0xcc; + public static final byte UINT16 = (byte) 0xcd; + public static final byte UINT32 = (byte) 0xce; + public static final byte UINT64 = (byte) 0xcf; + + public static final byte INT8 = (byte) 0xd0; + public static final byte INT16 = (byte) 0xd1; + public static final byte INT32 = (byte) 0xd2; + public static final byte INT64 = (byte) 0xd3; + + public static final byte FIXEXT1 = (byte) 0xd4; + public static final byte FIXEXT2 = (byte) 0xd5; + public static final byte FIXEXT4 = (byte) 0xd6; + public static final byte FIXEXT8 = (byte) 0xd7; + public static final byte FIXEXT16 = (byte) 0xd8; + + public static final byte STR8 = (byte) 0xd9; + public static final byte STR16 = (byte) 0xda; + public static final byte STR32 = (byte) 0xdb; + + public static final byte ARRAY16 = (byte) 0xdc; + public static final byte ARRAY32 = (byte) 0xdd; + + public static final byte MAP16 = (byte) 0xde; + public static final byte MAP32 = (byte) 0xdf; + + public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; + } + + private MessagePack() { // Prohibit instantiation of this class diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index e3ba1e0d2..c06cc5804 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -28,40 +28,40 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; -import static org.msgpack.core.MessageFormat.Code.ARRAY16; -import static org.msgpack.core.MessageFormat.Code.ARRAY32; -import static org.msgpack.core.MessageFormat.Code.BIN16; -import static org.msgpack.core.MessageFormat.Code.BIN32; -import static org.msgpack.core.MessageFormat.Code.BIN8; -import static org.msgpack.core.MessageFormat.Code.EXT16; -import static org.msgpack.core.MessageFormat.Code.EXT32; -import static org.msgpack.core.MessageFormat.Code.EXT8; -import static org.msgpack.core.MessageFormat.Code.FALSE; -import static org.msgpack.core.MessageFormat.Code.FIXARRAY_PREFIX; -import static org.msgpack.core.MessageFormat.Code.FIXEXT1; -import static org.msgpack.core.MessageFormat.Code.FIXEXT16; -import static org.msgpack.core.MessageFormat.Code.FIXEXT2; -import static org.msgpack.core.MessageFormat.Code.FIXEXT4; -import static org.msgpack.core.MessageFormat.Code.FIXEXT8; -import static org.msgpack.core.MessageFormat.Code.FIXMAP_PREFIX; -import static org.msgpack.core.MessageFormat.Code.FIXSTR_PREFIX; -import static org.msgpack.core.MessageFormat.Code.FLOAT32; -import static org.msgpack.core.MessageFormat.Code.FLOAT64; -import static org.msgpack.core.MessageFormat.Code.INT16; -import static org.msgpack.core.MessageFormat.Code.INT32; -import static org.msgpack.core.MessageFormat.Code.INT64; -import static org.msgpack.core.MessageFormat.Code.INT8; -import static org.msgpack.core.MessageFormat.Code.MAP16; -import static org.msgpack.core.MessageFormat.Code.MAP32; -import static org.msgpack.core.MessageFormat.Code.NIL; -import static org.msgpack.core.MessageFormat.Code.STR16; -import static org.msgpack.core.MessageFormat.Code.STR32; -import static org.msgpack.core.MessageFormat.Code.STR8; -import static org.msgpack.core.MessageFormat.Code.TRUE; -import static org.msgpack.core.MessageFormat.Code.UINT16; -import static org.msgpack.core.MessageFormat.Code.UINT32; -import static org.msgpack.core.MessageFormat.Code.UINT64; -import static org.msgpack.core.MessageFormat.Code.UINT8; +import static org.msgpack.core.MessagePack.Code.ARRAY16; +import static org.msgpack.core.MessagePack.Code.ARRAY32; +import static org.msgpack.core.MessagePack.Code.BIN16; +import static org.msgpack.core.MessagePack.Code.BIN32; +import static org.msgpack.core.MessagePack.Code.BIN8; +import static org.msgpack.core.MessagePack.Code.EXT16; +import static org.msgpack.core.MessagePack.Code.EXT32; +import static org.msgpack.core.MessagePack.Code.EXT8; +import static org.msgpack.core.MessagePack.Code.FALSE; +import static org.msgpack.core.MessagePack.Code.FIXARRAY_PREFIX; +import static org.msgpack.core.MessagePack.Code.FIXEXT1; +import static org.msgpack.core.MessagePack.Code.FIXEXT16; +import static org.msgpack.core.MessagePack.Code.FIXEXT2; +import static org.msgpack.core.MessagePack.Code.FIXEXT4; +import static org.msgpack.core.MessagePack.Code.FIXEXT8; +import static org.msgpack.core.MessagePack.Code.FIXMAP_PREFIX; +import static org.msgpack.core.MessagePack.Code.FIXSTR_PREFIX; +import static org.msgpack.core.MessagePack.Code.FLOAT32; +import static org.msgpack.core.MessagePack.Code.FLOAT64; +import static org.msgpack.core.MessagePack.Code.INT16; +import static org.msgpack.core.MessagePack.Code.INT32; +import static org.msgpack.core.MessagePack.Code.INT64; +import static org.msgpack.core.MessagePack.Code.INT8; +import static org.msgpack.core.MessagePack.Code.MAP16; +import static org.msgpack.core.MessagePack.Code.MAP32; +import static org.msgpack.core.MessagePack.Code.NIL; +import static org.msgpack.core.MessagePack.Code.STR16; +import static org.msgpack.core.MessagePack.Code.STR32; +import static org.msgpack.core.MessagePack.Code.STR8; +import static org.msgpack.core.MessagePack.Code.TRUE; +import static org.msgpack.core.MessagePack.Code.UINT16; +import static org.msgpack.core.MessagePack.Code.UINT32; +import static org.msgpack.core.MessagePack.Code.UINT64; +import static org.msgpack.core.MessagePack.Code.UINT8; import static org.msgpack.core.Preconditions.checkNotNull; /** diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index c4a8fc35b..d642fad6e 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -15,7 +15,7 @@ // package org.msgpack.core; -import org.msgpack.core.MessageFormat.Code; +import org.msgpack.core.MessagePack.Code; import org.msgpack.core.buffer.MessageBuffer; import org.msgpack.core.buffer.MessageBufferInput; import org.msgpack.value.ImmutableValue; diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala index a6a71e2d9..be9d270cd 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessageFormatTest.scala @@ -15,7 +15,7 @@ // package org.msgpack.core -import org.msgpack.core.MessageFormat.Code +import org.msgpack.core.MessagePack.Code import org.msgpack.value.ValueType import org.scalatest.exceptions.TestFailedException diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index d11383e7f..112c3e5a7 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -20,7 +20,7 @@ import java.math.BigInteger import java.nio.CharBuffer import java.nio.charset.{CodingErrorAction, UnmappableCharacterException} -import org.msgpack.core.MessageFormat.Code +import org.msgpack.core.MessagePack.Code import org.msgpack.core.MessagePack.{UnpackerConfig, PackerConfig} import org.msgpack.value.{Value, Variable} diff --git a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala index 2bd1c7b14..979c33c9b 100644 --- a/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/value/ValueTypeTest.scala @@ -15,20 +15,22 @@ // package org.msgpack.value -import org.msgpack.core.MessageFormat.Code._ +import org.msgpack.core.MessagePack.Code._ import org.msgpack.core.{MessageFormat, MessageFormatException, MessagePackSpec} /** - * Created on 2014/05/06. - */ + * Created on 2014/05/06. + */ class ValueTypeTest - extends MessagePackSpec { + extends MessagePackSpec +{ "ValueType" should { "lookup ValueType from a byte value" taggedAs ("code") in { - def check(b: Byte, tpe: ValueType) { + def check(b: Byte, tpe: ValueType) + { MessageFormat.valueOf(b).getValueType shouldBe tpe } From 031ead346902e6c69b3a8a95a0805395771e52f3 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 16:23:20 +0900 Subject: [PATCH 82/99] Rename to PackStringWithGetBytes and add comments --- .../src/main/java/org/msgpack/core/MessagePacker.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index c06cc5804..cb8ccd371 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -428,10 +428,12 @@ public MessagePacker packDouble(double v) return this; } - private void packStringByGetBytes(String s) + private void packStringWithGetBytes(String s) throws IOException { + // JVM performs various optimizations (memory allocation, reusing encoder etc.) when String.getBytes is used byte[] bytes = s.getBytes(MessagePack.UTF8); + // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer packRawStringHeader(bytes.length); addPayload(bytes); } @@ -481,8 +483,8 @@ public MessagePacker packString(String s) return this; } else if (s.length() < smallStringOptimizationThreshold) { - // Write the length and payload of small string to the buffer so that it avoids an extra flush of buffer - packStringByGetBytes(s); + // Using String.getBytes is generally faster for small strings + packStringWithGetBytes(s); return this; } else if (s.length() < (1 << 8)) { @@ -549,7 +551,7 @@ else if (s.length() < (1 << 16)) { // 384KB, which is OK size to keep in memory. // fallback - packStringByGetBytes(s); + packStringWithGetBytes(s); return this; } From 4230539a63e305368004b0bba78062c18c4c011d Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 17:15:28 +0900 Subject: [PATCH 83/99] Rename castBuffer to numberBuffer to clarify the usage of this buffer --- .../org/msgpack/core/MessageBufferPacker.java | 5 +- .../java/org/msgpack/core/MessagePack.java | 1 - .../org/msgpack/core/MessageUnpacker.java | 108 ++++++++++-------- 3 files changed, 66 insertions(+), 48 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java index 829803a2d..640b35f9d 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageBufferPacker.java @@ -15,9 +15,9 @@ // package org.msgpack.core; +import org.msgpack.core.buffer.ArrayBufferOutput; import org.msgpack.core.buffer.MessageBuffer; import org.msgpack.core.buffer.MessageBufferOutput; -import org.msgpack.core.buffer.ArrayBufferOutput; import java.io.IOException; import java.util.List; @@ -47,7 +47,8 @@ public MessageBufferOutput reset(MessageBufferOutput out) return super.reset(out); } - private ArrayBufferOutput getArrayBufferOut() { + private ArrayBufferOutput getArrayBufferOut() + { return (ArrayBufferOutput) out; } diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index bcc9d9359..7643f18f4 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -125,7 +125,6 @@ public static final boolean isFixedRaw(byte b) public static final byte NEGFIXINT_PREFIX = (byte) 0xe0; } - private MessagePack() { // Prohibit instantiation of this class diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index d642fad6e..c5dc4db2b 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -100,15 +100,15 @@ public class MessageUnpacker private long totalReadBytes; /** - * Extra buffer for fixed-length data at the buffer boundary. + * An extra buffer for reading a small number value across the input buffer boundary. * At most 8-byte buffer (for readLong used by uint 64 and UTF-8 character decoding) is required. */ - private final MessageBuffer castBuffer = MessageBuffer.allocate(8); + private final MessageBuffer numberBuffer = MessageBuffer.allocate(8); /** - * Variable by ensureHeader method. Caller of the method should use this variable to read from returned MessageBuffer. + * After calling prepareNumberBuffer(), the caller should use this variable to read from the returned MessageBuffer. */ - private int readCastBufferPosition; + private int nextReadPosition; /** * For decoding String in unpackString. @@ -169,7 +169,12 @@ public long getTotalReadBytes() return totalReadBytes + position; } - private void nextBuffer() + /** + * Get the next buffer without changing the position + * @return + * @throws IOException + */ + private MessageBuffer getNextBuffer() throws IOException { MessageBuffer next = in.next(); @@ -177,44 +182,57 @@ private void nextBuffer() throw new MessageInsufficientBufferException(); } totalReadBytes += buffer.size(); - buffer = next; + return next; + } + + private void nextBuffer() + throws IOException + { + buffer = getNextBuffer(); position = 0; } - private MessageBuffer readCastBuffer(int length) + /** + * Returns a short size buffer (upto 8 bytes) to read a number value + * @param readLength + * @return + * @throws IOException + * @throws MessageInsufficientBufferException If no more buffer can be acquired from the input source for reading the specified data length + */ + private MessageBuffer prepareNumberBuffer(int readLength) throws IOException { int remaining = buffer.size() - position; - if (remaining >= length) { - readCastBufferPosition = position; - position += length; // here assumes following buffer.getXxx never throws exception - return buffer; + if (remaining >= readLength) { + // When the data is contained inside the default buffer + nextReadPosition = position; + position += readLength; // here assumes following buffer.getXxx never throws exception + return buffer; // Return the default buffer } else { - // TODO loop this method until castBuffer is filled - MessageBuffer next = in.next(); - if (next == null) { - throw new MessageInsufficientBufferException(); - } + // When the default buffer doesn't contain the whole length - totalReadBytes += buffer.size(); + // TODO loop this method until castBuffer is filled + MessageBuffer next = getNextBuffer(); if (remaining > 0) { - // TODO this doesn't work if MessageBuffer is allocated by newDirectBuffer. - // add copy method to MessageBuffer to solve this issue. - castBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining); - castBuffer.putBytes(remaining, next.array(), next.arrayOffset(), length - remaining); + // TODO This doesn't work if MessageBuffer is allocated by newDirectBuffer. + // Add copy method to MessageBuffer to solve this issue. + + // Copy the data fragment from the current buffer + numberBuffer.putBytes(0, buffer.array(), buffer.arrayOffset() + position, remaining); + numberBuffer.putBytes(remaining, next.array(), next.arrayOffset(), readLength - remaining); buffer = next; - position = length - remaining; - readCastBufferPosition = 0; + position = readLength - remaining; + nextReadPosition = 0; - return castBuffer; + return numberBuffer; // Return the numberBuffer } else { buffer = next; - position = length; - readCastBufferPosition = 0; + position = readLength; + nextReadPosition = 0; return buffer; } } @@ -296,36 +314,36 @@ private byte readByte() private short readShort() throws IOException { - MessageBuffer castBuffer = readCastBuffer(2); - return castBuffer.getShort(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(2); + return numberBuffer.getShort(nextReadPosition); } private int readInt() throws IOException { - MessageBuffer castBuffer = readCastBuffer(4); - return castBuffer.getInt(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(4); + return numberBuffer.getInt(nextReadPosition); } private long readLong() throws IOException { - MessageBuffer castBuffer = readCastBuffer(8); - return castBuffer.getLong(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(8); + return numberBuffer.getLong(nextReadPosition); } private float readFloat() throws IOException { - MessageBuffer castBuffer = readCastBuffer(4); - return castBuffer.getFloat(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(4); + return numberBuffer.getFloat(nextReadPosition); } private double readDouble() throws IOException { - MessageBuffer castBuffer = readCastBuffer(8); - return castBuffer.getDouble(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(8); + return numberBuffer.getDouble(nextReadPosition); } /** @@ -1079,27 +1097,27 @@ public ExtensionTypeHeader unpackExtensionTypeHeader() return new ExtensionTypeHeader(type, 16); } case Code.EXT8: { - MessageBuffer castBuffer = readCastBuffer(2); - int u8 = castBuffer.getByte(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(2); + int u8 = numberBuffer.getByte(nextReadPosition); int length = u8 & 0xff; - byte type = castBuffer.getByte(readCastBufferPosition + 1); + byte type = numberBuffer.getByte(nextReadPosition + 1); return new ExtensionTypeHeader(type, length); } case Code.EXT16: { - MessageBuffer castBuffer = readCastBuffer(3); - int u16 = castBuffer.getShort(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(3); + int u16 = numberBuffer.getShort(nextReadPosition); int length = u16 & 0xffff; - byte type = castBuffer.getByte(readCastBufferPosition + 2); + byte type = numberBuffer.getByte(nextReadPosition + 2); return new ExtensionTypeHeader(type, length); } case Code.EXT32: { - MessageBuffer castBuffer = readCastBuffer(5); - int u32 = castBuffer.getInt(readCastBufferPosition); + MessageBuffer numberBuffer = prepareNumberBuffer(5); + int u32 = numberBuffer.getInt(nextReadPosition); if (u32 < 0) { throw overflowU32Size(u32); } int length = u32; - byte type = castBuffer.getByte(readCastBufferPosition + 4); + byte type = numberBuffer.getByte(nextReadPosition + 4); return new ExtensionTypeHeader(type, length); } } From 3d328e9f25c782931126e5ea5c846739855c6c97 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 23:09:56 +0900 Subject: [PATCH 84/99] Add assertion --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index c5dc4db2b..219c11d26 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -171,6 +171,7 @@ public long getTotalReadBytes() /** * Get the next buffer without changing the position + * * @return * @throws IOException */ @@ -181,6 +182,7 @@ private MessageBuffer getNextBuffer() if (next == null) { throw new MessageInsufficientBufferException(); } + assert (buffer != null); totalReadBytes += buffer.size(); return next; } @@ -194,6 +196,7 @@ private void nextBuffer() /** * Returns a short size buffer (upto 8 bytes) to read a number value + * * @param readLength * @return * @throws IOException From 66ce882fb7ec990acf4574d5db9c895e4344a054 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 23:13:44 +0900 Subject: [PATCH 85/99] Remove unused variable --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 219c11d26..52fdc5fed 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -71,8 +71,6 @@ public class MessageUnpacker { private static final MessageBuffer EMPTY_BUFFER = MessageBuffer.wrap(new byte[0]); - private static final byte HEAD_BYTE_REQUIRED = (byte) 0xc1; - private final boolean allowReadingStringAsBinary; private final boolean allowReadingBinaryAsString; private final CodingErrorAction actionOnMalformedString; @@ -82,8 +80,6 @@ public class MessageUnpacker private MessageBufferInput in; - private byte headByte = HEAD_BYTE_REQUIRED; - /** * Points to the current buffer to read */ From 72ceb0c92dafad20ff3b6fd774945ba58d2a80a1 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 23:14:36 +0900 Subject: [PATCH 86/99] Fix comment --- .../src/main/java/org/msgpack/core/MessagePacker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index cb8ccd371..fe0363e99 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -506,7 +506,7 @@ else if (s.length() < (1 << 8)) { // move 1 byte backward to expand 3-byte header region to 3 bytes buffer.putBytes(position + 3, buffer.array(), buffer.arrayOffset() + position + 2, written); - // write 3-byte header header + // write 3-byte header buffer.putByte(position++, STR16); buffer.putShort(position, (short) written); position += 2; @@ -516,7 +516,7 @@ else if (s.length() < (1 << 8)) { } } else if (s.length() < (1 << 16)) { - // ensure capacity for 3-byte raw string header + the maximum string size (+ 2 bytes for falback code) + // ensure capacity for 3-byte raw string header + the maximum string size (+ 2 bytes for fallback code) ensureCapacity(3 + s.length() * UTF_8_MAX_CHAR_SIZE + 2); // keep 3-byte header region and write raw string int written = encodeStringToBufferAt(position + 3, s); From 10c241b0d522f143b0145fa69f5e74053191efbc Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Mon, 4 Jan 2016 23:27:54 +0900 Subject: [PATCH 87/99] Use a config param for 8192 --- .../src/main/java/org/msgpack/core/MessagePack.java | 6 ++++++ .../src/main/java/org/msgpack/core/MessagePacker.java | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java index 7643f18f4..59bbbad48 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePack.java @@ -241,6 +241,12 @@ public static class PackerConfig */ public int smallStringOptimizationThreshold = 512; + /** + * When the next payload size exceeds this threshold, MessagePacker will call MessageBufferOutput.flush() before + * packing the data. + */ + public int bufferFlushThreshold = 8192; + /** * Create a packer that outputs the packed data to a given output * diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index fe0363e99..c99653fc9 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -86,6 +86,8 @@ public class MessagePacker { private final int smallStringOptimizationThreshold; + private final int bufferFlushThreshold; + protected MessageBufferOutput out; private MessageBuffer buffer; @@ -113,6 +115,7 @@ public MessagePacker(MessageBufferOutput out, MessagePack.PackerConfig config) this.out = checkNotNull(out, "MessageBufferOutput is null"); // We must copy the configuration parameters here since the config object is mutable this.smallStringOptimizationThreshold = config.smallStringOptimizationThreshold; + this.bufferFlushThreshold = config.bufferFlushThreshold; this.position = 0; this.totalFlushBytes = 0; } @@ -703,7 +706,7 @@ public MessagePacker writePayload(byte[] src) public MessagePacker writePayload(byte[] src, int off, int len) throws IOException { - if (buffer.size() - position < len || len > 8192) { + if (buffer.size() - position < len || len > bufferFlushThreshold) { flush(); // call flush before write out.write(src, off, len); totalFlushBytes += len; @@ -744,7 +747,7 @@ public MessagePacker addPayload(byte[] src) public MessagePacker addPayload(byte[] src, int off, int len) throws IOException { - if (buffer.size() - position < len || len > 8192) { + if (buffer.size() - position < len || len > bufferFlushThreshold) { flush(); // call flush before add out.add(src, off, len); totalFlushBytes += len; From 9a966a5a7ffdfa6497c434e65ea48b64e0823e62 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 00:06:45 +0900 Subject: [PATCH 88/99] Small optimization --- .../src/main/java/org/msgpack/core/MessageUnpacker.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 52fdc5fed..25b397359 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -534,7 +534,7 @@ public Variable unpackValue(Variable var) MessageFormat mf = getNextFormat(); switch (mf.getValueType()) { case NIL: - unpackNil(); + readByte(); var.setNilValue(); return var; case BOOLEAN: @@ -902,7 +902,12 @@ private void resetDecoder() else { decoder.reset(); } - decodeStringBuffer = new StringBuilder(); + if (decodeStringBuffer == null) { + decodeStringBuffer = new StringBuilder(); + } + else { + decodeStringBuffer.setLength(0); + } } public String unpackString() From 0d78ca7d10e97b25c869d64d119f0eb8f2f2e05c Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 00:48:24 +0900 Subject: [PATCH 89/99] Remove unused code --- msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java | 1 - 1 file changed, 1 deletion(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java index 25b397359..a7cf970eb 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java @@ -932,7 +932,6 @@ public String unpackString() int bufferRemaining = buffer.size() - position; if (bufferRemaining >= rawRemaining) { decodeStringBuffer.append(decodeStringFastPath(rawRemaining)); - rawRemaining = 0; break; } else if (bufferRemaining == 0) { From 31e1efa3adc6f5888e5d3d27affeac5b088ed7de Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 02:25:07 +0900 Subject: [PATCH 90/99] Rename variable --- .../java/org/msgpack/core/buffer/ChannelBufferInput.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java index 6553e497f..f00cb0c30 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java +++ b/msgpack-core/src/main/java/org/msgpack/core/buffer/ChannelBufferInput.java @@ -29,7 +29,7 @@ public class ChannelBufferInput implements MessageBufferInput { private ReadableByteChannel channel; - private final MessageBuffer m; + private final MessageBuffer buffer; public ChannelBufferInput(ReadableByteChannel channel) { @@ -40,7 +40,7 @@ public ChannelBufferInput(ReadableByteChannel channel, int bufferSize) { this.channel = checkNotNull(channel, "input channel is null"); checkArgument(bufferSize > 0, "buffer size must be > 0: " + bufferSize); - this.m = MessageBuffer.allocate(bufferSize); + this.buffer = MessageBuffer.allocate(bufferSize); } /** @@ -61,7 +61,7 @@ public ReadableByteChannel reset(ReadableByteChannel channel) public MessageBuffer next() throws IOException { - ByteBuffer b = m.sliceAsByteBuffer(); + ByteBuffer b = buffer.sliceAsByteBuffer(); while (b.remaining() > 0) { int ret = channel.read(b); if (ret == -1) { @@ -69,7 +69,7 @@ public MessageBuffer next() } } b.flip(); - return b.remaining() == 0 ? null : m.slice(0, b.limit()); + return b.remaining() == 0 ? null : buffer.slice(0, b.limit()); } @Override From cb38acad1cab8d040eaec455f84f3b8dba5d7a65 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 02:30:47 +0900 Subject: [PATCH 91/99] Set the version to 0.8.0-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 984699500..48bb0f19e 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.7.2-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.0-SNAPSHOT" \ No newline at end of file From 5e9bce63d1c742f506c8498f9ddb21f8782cef22 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:04:08 +0900 Subject: [PATCH 92/99] Prepare 0.8.0 release --- RELEASE_NOTES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6b691c476..6ee94b80b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,10 @@ # Release Notes +* 0.8.0 + * Changed MessageBuffer API to alloww releasing the previously allocated buffers upon MessageBufferInput.next() call. + * Split MessagePack.Config into MessagePack.Packer/UnpackerConfig + * Performance improvement of packString + * 0.7.1 * Fix ImmutableLongValueImpl#asShort [#287](https://github.com/msgpack/msgpack-java/pull/287) From 172863371531a81b825cf0b86b49eb8fb0f77eff Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:05:59 +0900 Subject: [PATCH 93/99] Setting version to 0.8.0 --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 48bb0f19e..5a3cb9897 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.0-SNAPSHOT" \ No newline at end of file +version in ThisBuild := "0.8.0" \ No newline at end of file From 328a97c302be55de995f9e25bd0b08a7bd8a70b4 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:06:24 +0900 Subject: [PATCH 94/99] Setting version to 0.8.1-SNAPSHOT --- version.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sbt b/version.sbt index 5a3cb9897..93d712300 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.8.0" \ No newline at end of file +version in ThisBuild := "0.8.1-SNAPSHOT" \ No newline at end of file From 61f11480fb73675bfb53f568fd6648ec9e4f0427 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:08:08 +0900 Subject: [PATCH 95/99] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6ee94b80b..2f51f5db6 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,7 @@ # Release Notes * 0.8.0 - * Changed MessageBuffer API to alloww releasing the previously allocated buffers upon MessageBufferInput.next() call. + * Changed MessageBuffer API to allow releasing the previously allocated buffers upon MessageBufferInput.next() call. * Split MessagePack.Config into MessagePack.Packer/UnpackerConfig * Performance improvement of packString From 875456158c9030998ab2074a13c463e59d5e9b73 Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:13:22 +0900 Subject: [PATCH 96/99] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2f51f5db6..5a269852b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,8 +1,12 @@ # Release Notes * 0.8.0 - * Changed MessageBuffer API to allow releasing the previously allocated buffers upon MessageBufferInput.next() call. * Split MessagePack.Config into MessagePack.Packer/UnpackerConfig + * Changed MessageBuffer API + * It allows releasing the previously allocated buffers upon MessageBufferInput.next() call. + * MessageBufferOutput now can read data from external byte arrays + * MessagePacker supports addPayload(byte[]) to feed the data from an external data source + * This saves the cost of copying large data to the internal message buffer * Performance improvement of packString * 0.7.1 From 12791691c9c0c5b37754f55ad14415a9b767edef Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:14:36 +0900 Subject: [PATCH 97/99] Update RELEASE_NOTES.md --- RELEASE_NOTES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5a269852b..52b12f9d4 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -3,8 +3,8 @@ * 0.8.0 * Split MessagePack.Config into MessagePack.Packer/UnpackerConfig * Changed MessageBuffer API - * It allows releasing the previously allocated buffers upon MessageBufferInput.next() call. - * MessageBufferOutput now can read data from external byte arrays + * It allows releasing the previously allocated buffers upon MessageBufferInput.next() call. + * MessageBufferOutput now can read data from external byte arrays * MessagePacker supports addPayload(byte[]) to feed the data from an external data source * This saves the cost of copying large data to the internal message buffer * Performance improvement of packString From cb7f64286fa4365fa68cd9d5ef29a77df712363d Mon Sep 17 00:00:00 2001 From: "Taro L. Saito" Date: Tue, 5 Jan 2016 14:23:10 +0900 Subject: [PATCH 98/99] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c66b668d7..d2787d7e0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ MessagePack for Java * Message Pack specification: -MessagePack v7 (0.7.x) is a faster implementation of the previous version [v06](https://github.com/msgpack/msgpack-java/tree/v06), and +MessagePack v7 (or later) is a faster implementation of the previous version [v06](https://github.com/msgpack/msgpack-java/tree/v06), and supports all of the message pack types, including [extension format](https://github.com/msgpack/msgpack/blob/master/spec.md#formats-ext). ## Limitation @@ -18,13 +18,13 @@ For Maven users: org.msgpack msgpack-core - 0.7.1 + 0.8.0 ``` For sbt users: ``` -libraryDependencies += "org.msgpack" % "msgpack-core" % "0.7.1" +libraryDependencies += "org.msgpack" % "msgpack-core" % "0.8.0" ``` For gradle users: @@ -34,7 +34,7 @@ repositories { } dependencies { - compile 'org.msgpack:msgpack-core:0.7.1' + compile 'org.msgpack:msgpack-core:0.8.0' } ``` From 94e3cee8d837bc06e567ceeebd44ba4308cbe476 Mon Sep 17 00:00:00 2001 From: Mitsunori Komatsu Date: Wed, 6 Jan 2016 22:56:06 +0900 Subject: [PATCH 99/99] Remove unused import in MessagePackExample --- .../test/java/org/msgpack/core/example/MessagePackExample.java | 1 - 1 file changed, 1 deletion(-) diff --git a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java index 0b0e50123..e8802a037 100644 --- a/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java +++ b/msgpack-core/src/test/java/org/msgpack/core/example/MessagePackExample.java @@ -33,7 +33,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.math.BigInteger; -import java.nio.charset.CodingErrorAction; /** * This class describes the usage of MessagePack v07