src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java
changeset 54601 c40b2a190173
child 55509 d58442b8abc1
child 58678 9cf78a70fa4f
equal deleted inserted replaced
54600:69cfd80f8706 54601:c40b2a190173
       
     1 /*
       
     2  * Copyright (c) 2018, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 
       
    25 package jdk.internal.vm.compiler.libgraal;
       
    26 
       
    27 import java.io.ByteArrayInputStream;
       
    28 import java.io.ByteArrayOutputStream;
       
    29 import java.io.DataInputStream;
       
    30 import java.io.DataOutputStream;
       
    31 import java.io.IOException;
       
    32 import java.util.HashMap;
       
    33 import java.util.Map;
       
    34 
       
    35 /**
       
    36  * Facilities for encoding/decoding a set of options to/from a byte array.
       
    37  */
       
    38 public final class OptionsEncoder {
       
    39 
       
    40     private OptionsEncoder() {
       
    41     }
       
    42 
       
    43     /**
       
    44      * Determines if {@code value} is supported by {@link #encode(Map)}.
       
    45      */
       
    46     public static boolean isValueSupported(Object value) {
       
    47         if (value == null) {
       
    48             return false;
       
    49         }
       
    50         Class<?> valueClass = value.getClass();
       
    51         return valueClass == Boolean.class ||
       
    52                         valueClass == Byte.class ||
       
    53                         valueClass == Short.class ||
       
    54                         valueClass == Character.class ||
       
    55                         valueClass == Integer.class ||
       
    56                         valueClass == Long.class ||
       
    57                         valueClass == Float.class ||
       
    58                         valueClass == Double.class ||
       
    59                         valueClass == String.class ||
       
    60                         value.getClass().isEnum();
       
    61     }
       
    62 
       
    63     /**
       
    64      * Encodes {@code options} into a byte array.
       
    65      *
       
    66      * @throws IllegalArgumentException if any value in {@code options} is not
       
    67      *             {@linkplain #isValueSupported(Object) supported}
       
    68      */
       
    69     public static byte[] encode(final Map<String, Object> options) {
       
    70         try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) {
       
    71             try (DataOutputStream out = new DataOutputStream(baout)) {
       
    72                 out.writeInt(options.size());
       
    73                 for (Map.Entry<String, Object> e : options.entrySet()) {
       
    74                     final String key = e.getKey();
       
    75                     out.writeUTF(key);
       
    76                     final Object value = e.getValue();
       
    77                     final Class<?> valueClz = value.getClass();
       
    78                     if (valueClz == Boolean.class) {
       
    79                         out.writeByte('Z');
       
    80                         out.writeBoolean((Boolean) value);
       
    81                     } else if (valueClz == Byte.class) {
       
    82                         out.writeByte('B');
       
    83                         out.writeByte((Byte) value);
       
    84                     } else if (valueClz == Short.class) {
       
    85                         out.writeByte('S');
       
    86                         out.writeShort((Short) value);
       
    87                     } else if (valueClz == Character.class) {
       
    88                         out.writeByte('C');
       
    89                         out.writeChar((Character) value);
       
    90                     } else if (valueClz == Integer.class) {
       
    91                         out.writeByte('I');
       
    92                         out.writeInt((Integer) value);
       
    93                     } else if (valueClz == Long.class) {
       
    94                         out.writeByte('J');
       
    95                         out.writeLong((Long) value);
       
    96                     } else if (valueClz == Float.class) {
       
    97                         out.writeByte('F');
       
    98                         out.writeFloat((Float) value);
       
    99                     } else if (valueClz == Double.class) {
       
   100                         out.writeByte('D');
       
   101                         out.writeDouble((Double) value);
       
   102                     } else if (valueClz == String.class) {
       
   103                         out.writeByte('U');
       
   104                         out.writeUTF((String) value);
       
   105                     } else if (valueClz.isEnum()) {
       
   106                         out.writeByte('U');
       
   107                         out.writeUTF(((Enum<?>) value).name());
       
   108                     } else {
       
   109                         throw new IllegalArgumentException(String.format("Key: %s, Value: %s, Value type: %s", key, value, valueClz));
       
   110                     }
       
   111                 }
       
   112             }
       
   113             return baout.toByteArray();
       
   114         } catch (IOException ioe) {
       
   115             throw new IllegalArgumentException(ioe);
       
   116         }
       
   117     }
       
   118 
       
   119     /**
       
   120      * Decodes {@code input} into a name/value map.
       
   121      *
       
   122      * @throws IllegalArgumentException if {@code input} cannot be decoded
       
   123      */
       
   124     public static Map<String, Object> decode(byte[] input) {
       
   125         Map<String, Object> res = new HashMap<>();
       
   126         try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(input))) {
       
   127             final int size = in.readInt();
       
   128             for (int i = 0; i < size; i++) {
       
   129                 final String key = in.readUTF();
       
   130                 final Object value;
       
   131                 final byte type = in.readByte();
       
   132                 switch (type) {
       
   133                     case 'Z':
       
   134                         value = in.readBoolean();
       
   135                         break;
       
   136                     case 'B':
       
   137                         value = in.readByte();
       
   138                         break;
       
   139                     case 'S':
       
   140                         value = in.readShort();
       
   141                         break;
       
   142                     case 'C':
       
   143                         value = in.readChar();
       
   144                         break;
       
   145                     case 'I':
       
   146                         value = in.readInt();
       
   147                         break;
       
   148                     case 'J':
       
   149                         value = in.readLong();
       
   150                         break;
       
   151                     case 'F':
       
   152                         value = in.readFloat();
       
   153                         break;
       
   154                     case 'D':
       
   155                         value = in.readDouble();
       
   156                         break;
       
   157                     case 'U':
       
   158                         value = in.readUTF();
       
   159                         break;
       
   160                     default:
       
   161                         throw new IllegalArgumentException("Unsupported value type: " + Integer.toHexString(type));
       
   162                 }
       
   163                 res.put(key, value);
       
   164             }
       
   165         } catch (IOException ioe) {
       
   166             throw new IllegalArgumentException(ioe);
       
   167         }
       
   168         return res;
       
   169     }
       
   170 }
       
   171