spinjar.com.minidev.json.JStylerObj Maven / Gradle / Ivy
package net.minidev.json;
/*
* Copyright 2011-2023 JSON-SMART authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
/**
* protected class used to stored Internal methods
*
* @author Uriel Chemouni <[email protected]>
*/
class JStylerObj {
public final static MPSimple MP_SIMPLE = new MPSimple();
public final static MPTrue MP_TRUE = new MPTrue();
public final static MPAgressive MP_AGGRESIVE = new MPAgressive();
public final static EscapeLT ESCAPE_LT = new EscapeLT();
public final static Escape4Web ESCAPE4Web = new Escape4Web();
public static interface MustProtect {
public boolean mustBeProtect(String s);
}
private static class MPTrue implements MustProtect {
public boolean mustBeProtect(String s) {
return true;
}
}
private static class MPSimple implements MustProtect {
/**
* can a String can be store without enclosing quotes. ie: should not
* contain any special json char
*
* @param s
* @return
*/
public boolean mustBeProtect(final String s) {
if (s == null)
return false;
int len = s.length();
if (len == 0)
return true;
if (s.trim() != s)
return true;
char ch = s.charAt(0);
if (ch >= '0' && ch <= '9' || ch == '-')
return true;
for (int i = 0; i < len; i++) {
ch = s.charAt(i);
if (isSpace(ch))
return true;
if (isSpecial(ch))
return true;
if (isSpecialChar(ch))
return true;
if (isUnicode(ch))
return true;
}
// keyword check
if (isKeyword(s))
return true;
return false;
}
}
private static class MPAgressive implements MustProtect {
public boolean mustBeProtect(final String s) {
if (s == null)
return false;
int len = s.length();
// protect empty String
if (len == 0)
return true;
// protect trimable String
if (s.trim() != s)
return true;
// json special char
char ch = s.charAt(0);
if (isSpecial(ch) || isUnicode(ch))
return true;
for (int i = 1; i < len; i++) {
ch = s.charAt(i);
if (isSpecialClose(ch) || isUnicode(ch))
return true;
}
// keyWord must be protect
if (isKeyword(s))
return true;
// Digit like text must be protect
ch = s.charAt(0);
// only test String if First Ch is a digit
if (ch >= '0' && ch <= '9' || ch == '-') {
int p = 1;
// skip first digits
for (; p < len; p++) {
ch = s.charAt(p);
if (ch < '0' || ch > '9')
break;
}
// int/long
if (p == len)
return true;
// Floating point
if (ch == '.') {
p++;
}
// Skip digits
for (; p < len; p++) {
ch = s.charAt(p);
if (ch < '0' || ch > '9')
break;
}
if (p == len)
return true; // can be read as an floating number
// Double
if (ch == 'E' || ch == 'e') {
p++;
if (p == len) // no power data not a digits
return false;
ch = s.charAt(p);
if (ch == '+' || ch == '-') {
p++;
ch = s.charAt(p);
}
}
if (p == len) // no power data => not a digit
return false;
for (; p < len; p++) {
ch = s.charAt(p);
if (ch < '0' || ch > '9')
break;
}
// floating point With power of data.
if (p == len)
return true;
return false;
}
return false;
}
}
public static boolean isSpace(char c) {
return (c == '\r' || c == '\n' || c == '\t' || c == ' ');
}
public static boolean isSpecialChar(char c) {
return (c == '\b' || c == '\f' || c == '\n');
}
public static boolean isSpecialOpen(char c) {
return (c == '{' || c == '[' || c == ',' || c == ':');
}
public static boolean isSpecialClose(char c) {
return (c == '}' || c == ']' || c == ',' || c == ':');
}
public static boolean isSpecial(char c) {
return (c == '{' || c == '[' || c == ',' || c == '}' || c == ']' || c == ':' || c == '\'' || c == '"');
}
public static boolean isUnicode(char c) {
// ANSI control char
return ((c >= '\u0000' && c <= '\u001F') ||
// DEL or unicode ctrl
(c >= '\u007F' && c <= '\u009F') ||
// '\u00A0' No-breakable space ?
// En Quad .. more
(c >= '\u2000' && c <= '\u20FF'));
}
public static boolean isKeyword(String s) {
if (s.length() < 3)
return false;
char c = s.charAt(0);
if (c == 'n')
return s.equals("null");
if (c == 't')
return s.equals("true");
if (c == 'f')
return s.equals("false");
if (c == 'N')
return s.equals("NaN");
return false;
}
public static interface StringProtector {
public void escape(String s, Appendable out);
}
private static class EscapeLT implements StringProtector {
/**
* Escape special chars form String except /
*
* @param s
* - Must not be null.
* @param out
*/
public void escape(String s, Appendable out) {
try {
int len = s.length();
for (int i = 0; i < len; i++) {
char ch = s.charAt(i);
switch (ch) {
case '"':
out.append("\\\"");
break;
case '\\':
out.append("\\\\");
break;
case '\b':
out.append("\\b");
break;
case '\f':
out.append("\\f");
break;
case '\n':
out.append("\\n");
break;
case '\r':
out.append("\\r");
break;
case '\t':
out.append("\\t");
break;
default:
// Reference:
// http://www.unicode.org/versions/Unicode5.1.0/
if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F')
|| (ch >= '\u2000' && ch <= '\u20FF')) {
out.append("\\u");
String hex = "0123456789ABCDEF";
out.append(hex.charAt(ch >> 12 & 0x000F));
out.append(hex.charAt(ch >> 8 & 0x000F));
out.append(hex.charAt(ch >> 4 & 0x000F));
out.append(hex.charAt(ch >> 0 & 0x000F));
} else {
out.append(ch);
}
}
}
} catch (IOException e) {
throw new RuntimeException("Impossible Exception");
}
}
}
private static class Escape4Web implements StringProtector {
/**
* Escape special chars form String including /
*
* @param s
* - Must not be null.
* @param sb
*/
public void escape(String s, Appendable sb) {
try {
int len = s.length();
for (int i = 0; i < len; i++) {
char ch = s.charAt(i);
switch (ch) {
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
// Reference:
// http://www.unicode.org/versions/Unicode5.1.0/
if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F')
|| (ch >= '\u2000' && ch <= '\u20FF')) {
sb.append("\\u");
String hex = "0123456789ABCDEF";
sb.append(hex.charAt(ch >> 12 & 0x0F));
sb.append(hex.charAt(ch >> 8 & 0x0F));
sb.append(hex.charAt(ch >> 4 & 0x0F));
sb.append(hex.charAt(ch >> 0 & 0x0F));
} else {
sb.append(ch);
}
}
}
} catch (IOException e) {
throw new RuntimeException("Impossible Error");
}
}
}
}