Coverage Report - org.apache.johnzon.core.Strings
 
Classes in this File Line Coverage Branch Coverage Complexity
Strings
65 %
32/49
56 %
22/39
10,75
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements. See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License. You may obtain a copy of the License at
 9  
  *
 10  
  * http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied. See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.johnzon.core;
 20  
 
 21  
 import java.util.concurrent.ConcurrentHashMap;
 22  
 import java.util.concurrent.ConcurrentMap;
 23  
 
 24  
 import javax.json.stream.JsonParsingException;
 25  
 
 26  
 class Strings implements JsonChars {
 27  1
     private static final BufferStrategy.BufferProvider<StringBuilder> BUILDER_CACHE =
 28  
         BufferStrategy.valueOf(System.getProperty("johnzon.string-builder.strategy", "QUEUE"))
 29  
             .newStringBuilderProvider(Integer.getInteger("org.apache.johnzon.default-string-builder", 1024));
 30  
 
 31  
     private static final String UNICODE_PREFIX = "\\u";
 32  
     private static final String UNICODE_PREFIX_HELPER = "000";
 33  1
     private static final ConcurrentMap<Character, String> UNICODE_CACHE = new ConcurrentHashMap<Character, String>();
 34  
 
 35  
     static char asEscapedChar(final char current) {
 36  10886
         switch (current) {
 37  
             case 'r':
 38  3805
                 return '\r';
 39  
             case 't':
 40  3197
                 return '\t';
 41  
             case 'b':
 42  1
                 return '\b';
 43  
             case 'f':
 44  1
                 return '\f';
 45  
             case 'n':
 46  3805
                 return '\n';
 47  
             case '"':
 48  75
                 return '\"';
 49  
             case '\\':
 50  0
                 return '\\';  
 51  
             case '/':
 52  1
                 return '/';  
 53  
             default:
 54  1
                 if(Character.isHighSurrogate(current) || Character.isLowSurrogate(current)) {
 55  0
                     return current;
 56  
                 }
 57  1
                 throw new JsonParsingException("Invalid escape sequence '"+current +"' (Codepoint: "+String.valueOf(current).
 58  
                         codePointAt(0),JsonLocationImpl.UNKNOWN_LOCATION);
 59  
         }
 60  
 
 61  
     }
 62  
 
 63  
     static String escape(final String value) {
 64  
         
 65  12
         if(value == null || value.length()==0) {
 66  0
             return value;
 67  
         }
 68  
         
 69  12
         final StringBuilder builder = BUILDER_CACHE.newBuffer();
 70  
         try {
 71  32
             for (int i = 0; i < value.length(); i++) {
 72  20
                 final char c = value.charAt(i);
 73  20
                 switch (c) {
 74  
                     case QUOTE_CHAR:
 75  
                     case ESCAPE_CHAR:
 76  3
                         builder.append(ESCAPE_CHAR).append(c);
 77  3
                         break;
 78  
                     default:
 79  17
                         if (c < SPACE) { // we could do a single switch but actually we should rarely enter this if so no need to pay it
 80  1
                             switch (c) {
 81  
                                 case EOL:
 82  0
                                     builder.append("\\n");
 83  0
                                     break;
 84  
                                 case '\r':
 85  0
                                     builder.append("\\r");
 86  0
                                     break;
 87  
                                 case '\t':
 88  0
                                     builder.append("\\t");
 89  0
                                     break;
 90  
                                 case '\b':
 91  0
                                     builder.append("\\b");
 92  0
                                     break;
 93  
                                 case '\f':
 94  0
                                     builder.append("\\f");
 95  0
                                     break;
 96  
                                 default:
 97  1
                                     builder.append(toUnicode(c));
 98  
                             }
 99  16
                         } else if ((c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
 100  0
                             builder.append(toUnicode(c));
 101  
                         } else {
 102  16
                             builder.append(c);
 103  
                         }
 104  
                 }
 105  
             }
 106  12
             return builder.toString();
 107  
         } finally {
 108  12
             BUILDER_CACHE.release(builder);
 109  
         }
 110  
     }
 111  
 
 112  
     private static String toUnicode(final char c) {
 113  1
         final String found = UNICODE_CACHE.get(c);
 114  1
         if (found != null) {
 115  0
             return found;
 116  
         }
 117  
 
 118  1
         final String hex = UNICODE_PREFIX_HELPER + Integer.toHexString(c);
 119  1
         final String s = UNICODE_PREFIX + hex.substring(hex.length() - 4);
 120  1
         UNICODE_CACHE.putIfAbsent(c, s);
 121  1
         return s;
 122  
     }
 123  
 
 124  0
     private Strings() {
 125  
         // no-op
 126  0
     }
 127  
 }