src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java
changeset 58863 c16ac7a2eba4
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
       
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package jdk.jfr.internal.consumer;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.nio.charset.Charset;
       
    30 
       
    31 public final class StringParser extends Parser {
       
    32 
       
    33     public enum Encoding {
       
    34         NULL(0),
       
    35         EMPTY_STRING(1),
       
    36         CONSTANT_POOL(2),
       
    37         UT8_BYTE_ARRAY(3),
       
    38         CHAR_ARRAY(4),
       
    39         LATIN1_BYTE_ARRAY(5);
       
    40 
       
    41         private byte byteValue;
       
    42 
       
    43         private Encoding(int byteValue) {
       
    44             this.byteValue = (byte) byteValue;
       
    45         }
       
    46 
       
    47         public byte byteValue() {
       
    48             return byteValue;
       
    49         }
       
    50 
       
    51         public boolean is(byte value) {
       
    52             return value == byteValue;
       
    53         }
       
    54 
       
    55     }
       
    56     private final static Charset UTF8 = Charset.forName("UTF-8");
       
    57     private final static Charset LATIN1 = Charset.forName("ISO-8859-1");
       
    58 
       
    59     private final static class CharsetParser extends Parser {
       
    60         private final Charset charset;
       
    61         private int lastSize;
       
    62         private byte[] buffer = new byte[16];
       
    63         private String lastString;
       
    64 
       
    65         CharsetParser(Charset charset) {
       
    66             this.charset = charset;
       
    67         }
       
    68 
       
    69         @Override
       
    70         public Object parse(RecordingInput input) throws IOException {
       
    71             int size = input.readInt();
       
    72             ensureSize(size);
       
    73             if (lastSize == size) {
       
    74                 boolean equalsLastString = true;
       
    75                 for (int i = 0; i < size; i++) {
       
    76                     // TODO: No need to read byte per byte
       
    77                     byte b = input.readByte();
       
    78                     if (buffer[i] != b) {
       
    79                         equalsLastString = false;
       
    80                         buffer[i] = b;
       
    81                     }
       
    82                 }
       
    83                 if (equalsLastString) {
       
    84                     return lastString;
       
    85                 }
       
    86             } else {
       
    87                 for (int i = 0; i < size; i++) {
       
    88                     buffer[i] = input.readByte();
       
    89                 }
       
    90             }
       
    91             lastString = new String(buffer, 0, size, charset);
       
    92             lastSize = size;
       
    93             return lastString;
       
    94         }
       
    95 
       
    96         @Override
       
    97         public void skip(RecordingInput input) throws IOException {
       
    98             int size = input.readInt();
       
    99             input.skipBytes(size);
       
   100         }
       
   101 
       
   102         private void ensureSize(int size) {
       
   103             if (buffer.length < size) {
       
   104                 buffer = new byte[size];
       
   105             }
       
   106         }
       
   107     }
       
   108 
       
   109     private final static class CharArrayParser extends Parser {
       
   110         private char[] buffer = new char[16];
       
   111         private int lastSize = -1;
       
   112         private String lastString = null;
       
   113 
       
   114         @Override
       
   115         public Object parse(RecordingInput input) throws IOException {
       
   116             int size = input.readInt();
       
   117             ensureSize(size);
       
   118             if (lastSize == size) {
       
   119                 boolean equalsLastString = true;
       
   120                 for (int i = 0; i < size; i++) {
       
   121                     char c = input.readChar();
       
   122                     if (buffer[i] != c) {
       
   123                         equalsLastString = false;
       
   124                         buffer[i] = c;
       
   125                     }
       
   126                 }
       
   127                 if (equalsLastString) {
       
   128                     return lastString;
       
   129                 }
       
   130             } else {
       
   131                 for (int i = 0; i < size; i++) {
       
   132                     buffer[i] = input.readChar();
       
   133                 }
       
   134             }
       
   135             lastString = new String(buffer, 0, size);
       
   136             lastSize = size;
       
   137             return lastString;
       
   138         }
       
   139 
       
   140         @Override
       
   141         public void skip(RecordingInput input) throws IOException {
       
   142             int size = input.readInt();
       
   143             for (int i = 0; i < size; i++) {
       
   144                 input.readChar();
       
   145             }
       
   146         }
       
   147 
       
   148         private void ensureSize(int size) {
       
   149             if (buffer.length < size) {
       
   150                 buffer = new char[size];
       
   151             }
       
   152         }
       
   153     }
       
   154 
       
   155     private final ConstantLookup stringLookup;
       
   156     private final CharArrayParser charArrayParser = new CharArrayParser();
       
   157     private final CharsetParser utf8parser = new CharsetParser(UTF8);
       
   158     private final CharsetParser latin1parser = new CharsetParser(LATIN1);
       
   159     private final boolean event;
       
   160 
       
   161     public StringParser(ConstantLookup stringLookup, boolean event) {
       
   162         this.stringLookup = stringLookup;
       
   163         this.event = event;
       
   164     }
       
   165 
       
   166     @Override
       
   167     public Object parse(RecordingInput input) throws IOException {
       
   168         byte encoding = input.readByte();
       
   169         if (Encoding.CONSTANT_POOL.is(encoding)) {
       
   170             long key = input.readLong();
       
   171             if (event) {
       
   172                 return stringLookup.getCurrentResolved(key);
       
   173             } else {
       
   174                 return stringLookup.getCurrent(key);
       
   175             }
       
   176         }
       
   177         if (Encoding.NULL.is(encoding)) {
       
   178             return null;
       
   179         }
       
   180         if (Encoding.EMPTY_STRING.is(encoding)) {
       
   181             return "";
       
   182         }
       
   183         if (Encoding.CHAR_ARRAY.is(encoding)) {
       
   184             return charArrayParser.parse(input);
       
   185         }
       
   186         if (Encoding.UT8_BYTE_ARRAY.is(encoding)) {
       
   187             return utf8parser.parse(input);
       
   188         }
       
   189         if (Encoding.LATIN1_BYTE_ARRAY.is(encoding)) {
       
   190             return latin1parser.parse(input);
       
   191         }
       
   192         throw new IOException("Unknown string encoding " + encoding);
       
   193     }
       
   194 
       
   195     @Override
       
   196     public void skip(RecordingInput input) throws IOException {
       
   197         byte encoding = input.readByte();
       
   198         if (Encoding.CONSTANT_POOL.is(encoding)) {
       
   199             input.readLong();
       
   200             return;
       
   201         }
       
   202         if (Encoding.EMPTY_STRING.is(encoding)) {
       
   203             return;
       
   204         }
       
   205         if (Encoding.NULL.is(encoding)) {
       
   206             return;
       
   207         }
       
   208         if (Encoding.CHAR_ARRAY.is(encoding)) {
       
   209             charArrayParser.skip(input);
       
   210             return;
       
   211         }
       
   212         if (Encoding.UT8_BYTE_ARRAY.is(encoding)) {
       
   213             utf8parser.skip(input);
       
   214             return;
       
   215         }
       
   216         if (Encoding.LATIN1_BYTE_ARRAY.is(encoding)) {
       
   217             latin1parser.skip(input);
       
   218             return;
       
   219         }
       
   220         throw new IOException("Unknown string encoding " + encoding);
       
   221     }
       
   222 }