1 /*
2 * Logback: the reliable, generic, fast and flexible logging framework.
3 * Copyright (C) 1999-2023, QOS.ch. All rights reserved.
4 *
5 * This program and the accompanying materials are dual-licensed under
6 * either the terms of the Eclipse Public License v1.0 as published by
7 * the Eclipse Foundation
8 *
9 * or (per the licensee's choosing)
10 *
11 * under the terms of the GNU Lesser General Public License version 2.1
12 * as published by the Free Software Foundation.
13 */
14
15 package ch.qos.logback.core.encoder;
16
17 public class JsonEscapeUtil {
18
19 protected final static char[] HEXADECIMALS_TABLE = "0123456789ABCDEF".toCharArray();
20
21 static final int ESCAPE_CODES_COUNT = 32;
22
23 static final String[] ESCAPE_CODES = new String[ESCAPE_CODES_COUNT];
24
25 // From RFC-8259 page 5
26
27 // " quotation mark U+0022 -- escaped as \"
28 // \ reverse solidus U+005C -- escaped as \\
29 // / solidus U+002F -- escaped as \/
30
31 // backspace U+0008 -- escaped as \b
32 // tab U+0009 -- escaped as \t
33 // line feed U+000A -- escaped as \n
34 // form feed U+000C -- escaped as \f
35 // carriage return U+000D -- escaped as \r
36
37 static {
38 for (char c = 0; c < ESCAPE_CODES_COUNT; c++) {
39
40 switch (c) {
41 case 0x08:
42 ESCAPE_CODES[c] = "\\b";
43 break;
44 case 0x09:
45 ESCAPE_CODES[c] = "\\t";
46 break;
47 case 0x0A:
48 ESCAPE_CODES[c] = "\\n";
49 break;
50 case 0x0C:
51 ESCAPE_CODES[c] = "\\f";
52 break;
53 case 0x0D:
54 ESCAPE_CODES[c] = "\\r";
55 break;
56 default:
57 ESCAPE_CODES[c] = _computeEscapeCodeBelowASCII32(c);
58 }
59 }
60 }
61
62 // this method should not be called by methods except the static initializer
63 private static String _computeEscapeCodeBelowASCII32(char c) {
64 if (c > 32) {
65 throw new IllegalArgumentException("input must be less than 32");
66 }
67
68 StringBuilder sb = new StringBuilder(6);
69 sb.append("\\u00");
70
71 int highPart = c >> 4;
72 sb.append(HEXADECIMALS_TABLE[highPart]);
73
74 int lowPart = c & 0x0F;
75 sb.append(HEXADECIMALS_TABLE[lowPart]);
76
77 return sb.toString();
78 }
79
80 // " quotation mark U+0022 -- escaped as \"
81 // \ reverse solidus U+005C -- escaped as \\
82 // / solidus U+002F -- escaped as \/
83
84 static String getObligatoryEscapeCode(char c) {
85 if (c < 32)
86 return ESCAPE_CODES[c];
87 if (c == 0x22)
88 return "\\\"";
89 if (c == 0x2F)
90 return "\\/";
91 if (c == 0x5C)
92 return "\\\\";
93
94 return null;
95 }
96
97 static public String jsonEscapeString(String input) {
98 int length = input.length();
99 int lenthWithLeeway = (int) (length * 1.1);
100
101 StringBuilder sb = new StringBuilder(lenthWithLeeway);
102 for (int i = 0; i < length; i++) {
103 final char c = input.charAt(i);
104 String escaped = getObligatoryEscapeCode(c);
105 if (escaped == null)
106 sb.append(c);
107 else {
108 sb.append(escaped);
109 }
110 }
111
112 return sb.toString();
113 }
114
115 }