Coverage Report - org.ini4j.spi.RegEscapeTool
 
Classes in this File Line Coverage Branch Coverage Complexity
RegEscapeTool
87%
87/99
83%
36/43
4
RegEscapeTool$1
100%
1/1
N/A
4
 
 1  
 /*
 2  
  * Copyright 2005,2009 Ivan SZKIBA
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.ini4j.spi;
 17  
 
 18  
 import org.ini4j.Registry;
 19  
 
 20  
 import org.ini4j.Registry.Type;
 21  
 
 22  
 import java.io.UnsupportedEncodingException;
 23  
 
 24  
 import java.nio.charset.Charset;
 25  
 
 26  
 import java.util.Arrays;
 27  
 
 28  1
 public class RegEscapeTool extends EscapeTool
 29  
 {
 30  1
     private static final RegEscapeTool INSTANCE = ServiceFinder.findService(RegEscapeTool.class);
 31  1
     private static final Charset HEX_CHARSET = Charset.forName("UTF-16LE");
 32  
     private static final int LOWER_DIGIT = 0x0f;
 33  
     private static final int UPPER_DIGIT = 0xf0;
 34  
     private static final int DIGIT_SIZE = 4;
 35  
 
 36  
     public static final RegEscapeTool getInstance()
 37  
     {
 38  1080
         return INSTANCE;
 39  
     }
 40  
 
 41  
     public TypeValuesPair decode(String raw)
 42  
     {
 43  494
         Type type = type(raw);
 44  494
         String value = (type == Type.REG_SZ) ? unquote(raw) : raw.substring(type.toString().length() + 1);
 45  
         String[] values;
 46  
 
 47  1
         switch (type)
 48  
         {
 49  
 
 50  
             case REG_EXPAND_SZ:
 51  
             case REG_MULTI_SZ:
 52  100
                 value = bytes2string(binary(value));
 53  100
                 break;
 54  
 
 55  
             case REG_DWORD:
 56  75
                 value = String.valueOf(Long.parseLong(value, HEX_RADIX));
 57  75
                 break;
 58  
 
 59  
             case REG_SZ:
 60  319
                 break;
 61  
 
 62  
             default:
 63  1
                 break;
 64  
         }
 65  
 
 66  494
         if (type == Type.REG_MULTI_SZ)
 67  
         {
 68  30
             values = splitMulti(value);
 69  
         }
 70  
         else
 71  
         {
 72  464
             values = new String[] { value };
 73  
         }
 74  
 
 75  494
         return new TypeValuesPair(type, values);
 76  
     }
 77  
 
 78  
     public String encode(TypeValuesPair data)
 79  
     {
 80  89
         String ret = null;
 81  
 
 82  89
         if (data.getType() == Type.REG_SZ)
 83  
         {
 84  67
             ret = quote(data.getValues()[0]);
 85  
         }
 86  22
         else if (data.getValues()[0] != null)
 87  
         {
 88  22
             ret = encode(data.getType(), data.getValues());
 89  
         }
 90  
 
 91  89
         return ret;
 92  
     }
 93  
 
 94  
     byte[] binary(String value)
 95  
     {
 96  100
         byte[] bytes = new byte[value.length()];
 97  100
         int idx = 0;
 98  100
         int shift = DIGIT_SIZE;
 99  
 
 100  7260
         for (int i = 0; i < value.length(); i++)
 101  
         {
 102  7160
             char c = value.charAt(i);
 103  
 
 104  7160
             if (Character.isWhitespace(c))
 105  
             {
 106  0
                 continue;
 107  
             }
 108  
 
 109  7160
             if (c == ',')
 110  
             {
 111  2320
                 idx++;
 112  2320
                 shift = DIGIT_SIZE;
 113  
             }
 114  
             else
 115  
             {
 116  4840
                 int digit = Character.digit(c, HEX_RADIX);
 117  
 
 118  4840
                 if (digit >= 0)
 119  
                 {
 120  4840
                     bytes[idx] |= digit << shift;
 121  4840
                     shift = 0;
 122  
                 }
 123  
             }
 124  
         }
 125  
 
 126  100
         return Arrays.copyOfRange(bytes, 0, idx + 1);
 127  
     }
 128  
 
 129  
     String encode(Type type, String[] values)
 130  
     {
 131  22
         StringBuilder buff = new StringBuilder();
 132  
 
 133  22
         buff.append(type.toString());
 134  22
         buff.append(Type.SEPARATOR_CHAR);
 135  22
         switch (type)
 136  
         {
 137  
 
 138  
             case REG_EXPAND_SZ:
 139  7
                 buff.append(hexadecimal(values[0]));
 140  7
                 break;
 141  
 
 142  
             case REG_DWORD:
 143  12
                 buff.append(String.format("%08x", Long.parseLong(values[0])));
 144  12
                 break;
 145  
 
 146  
             case REG_MULTI_SZ:
 147  3
                 int n = values.length;
 148  
 
 149  11
                 for (int i = 0; i < n; i++)
 150  
                 {
 151  8
                     buff.append(hexadecimal(values[i]));
 152  8
                     buff.append(',');
 153  
                 }
 154  
 
 155  3
                 buff.append("00,00");
 156  3
                 break;
 157  
 
 158  
             default:
 159  0
                 buff.append(values[0]);
 160  
                 break;
 161  
         }
 162  
 
 163  22
         return buff.toString();
 164  
     }
 165  
 
 166  
     String hexadecimal(String value)
 167  
     {
 168  17
         StringBuilder buff = new StringBuilder();
 169  
 
 170  17
         if ((value != null) && (value.length() != 0))
 171  
         {
 172  15
             byte[] bytes = string2bytes(value);
 173  
 
 174  221
             for (int i = 0; i < bytes.length; i++)
 175  
             {
 176  206
                 buff.append(Character.forDigit((bytes[i] & UPPER_DIGIT) >> DIGIT_SIZE, HEX_RADIX));
 177  206
                 buff.append(Character.forDigit(bytes[i] & LOWER_DIGIT, HEX_RADIX));
 178  206
                 buff.append(',');
 179  
             }
 180  
 
 181  15
             buff.append("00,00");
 182  
         }
 183  
 
 184  17
         return buff.toString();
 185  
     }
 186  
 
 187  
     Registry.Type type(String raw)
 188  
     {
 189  
         Registry.Type type;
 190  
 
 191  494
         if (raw.charAt(0) == DOUBLE_QUOTE)
 192  
         {
 193  319
             type = Registry.Type.REG_SZ;
 194  
         }
 195  
         else
 196  
         {
 197  175
             int idx = raw.indexOf(Registry.TYPE_SEPARATOR);
 198  
 
 199  175
             type = (idx < 0) ? Registry.Type.REG_SZ : Registry.Type.fromString(raw.substring(0, idx));
 200  
         }
 201  
 
 202  494
         return type;
 203  
     }
 204  
 
 205  
     // XXX Java 1.4 compatibility hack
 206  
     private String bytes2string(byte[] bytes)
 207  
     {
 208  
         String str;
 209  
 
 210  
         try
 211  
         {
 212  100
             str = new String(bytes, 0, bytes.length - 2, HEX_CHARSET);
 213  
         }
 214  0
         catch (NoSuchMethodError x)
 215  
         {
 216  
             try
 217  
             {
 218  0
                 str = new String(bytes, 0, bytes.length, HEX_CHARSET.name());
 219  
             }
 220  0
             catch (UnsupportedEncodingException ex)
 221  
             {
 222  0
                 throw new IllegalStateException(ex);
 223  0
             }
 224  100
         }
 225  
 
 226  100
         return str;
 227  
     }
 228  
 
 229  
     private String[] splitMulti(String value)
 230  
     {
 231  30
         int len = value.length();
 232  
         int start;
 233  
         int end;
 234  30
         int n = 0;
 235  
 
 236  30
         start = 0;
 237  80
         for (end = value.indexOf(0, start); end >= 0; end = value.indexOf(0, start))
 238  
         {
 239  80
             n++;
 240  80
             start = end + 1;
 241  80
             if (start >= len)
 242  
             {
 243  30
                 break;
 244  
             }
 245  
         }
 246  
 
 247  30
         String[] values = new String[n];
 248  
 
 249  30
         start = 0;
 250  110
         for (int i = 0; i < n; i++)
 251  
         {
 252  80
             end = value.indexOf(0, start);
 253  80
             values[i] = value.substring(start, end);
 254  80
             start = end + 1;
 255  
         }
 256  
 
 257  30
         return values;
 258  
     }
 259  
 
 260  
     // XXX Java 1.4 compatibility hack
 261  
     private byte[] string2bytes(String value)
 262  
     {
 263  
         byte[] bytes;
 264  
 
 265  
         try
 266  
         {
 267  15
             bytes = value.getBytes(HEX_CHARSET);
 268  
         }
 269  0
         catch (NoSuchMethodError x)
 270  
         {
 271  
             try
 272  
             {
 273  0
                 bytes = value.getBytes(HEX_CHARSET.name());
 274  
             }
 275  0
             catch (UnsupportedEncodingException ex)
 276  
             {
 277  0
                 throw new IllegalStateException(ex);
 278  0
             }
 279  15
         }
 280  
 
 281  15
         return bytes;
 282  
     }
 283  
 }