1 /* 2 * Copyright (c) 2025, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package oracle.code.json; 27 28 import java.math.BigDecimal; 29 import java.math.BigInteger; 30 import java.util.Objects; 31 32 /** 33 * JsonNumber implementation class 34 */ 35 final class JsonNumberImpl implements JsonNumber, JsonValueImpl { 36 37 private final JsonDocumentInfo docInfo; 38 private final int startOffset; 39 private final int endOffset; 40 private final int endIndex; 41 private Number theNumber; 42 private String numString; 43 44 JsonNumberImpl(Number num) { 45 theNumber = num; 46 numString = num.toString(); 47 startOffset = 0; 48 endOffset = 0; 49 endIndex = 0; 50 docInfo = null; 51 } 52 53 JsonNumberImpl(JsonDocumentInfo doc, int offset, int index) { 54 docInfo = doc; 55 startOffset = offset; 56 endIndex = docInfo.nextIndex(index); 57 endOffset = endIndex != -1 ? docInfo.getOffset(endIndex) : docInfo.getEndOffset(); 58 } 59 60 @Override 61 public Number value() { 62 if (theNumber == null) { 63 theNumber = toNum(string()); 64 } 65 return theNumber; 66 } 67 68 private String string() { 69 if (numString == null) { // Trim back only 70 numString = docInfo.substring(startOffset, endOffset).stripTrailing(); 71 } 72 return numString; 73 } 74 75 @Override 76 public int getEndIndex() { 77 return endIndex; 78 } 79 80 @Override 81 public boolean equals(Object o) { 82 return this == o || 83 o instanceof JsonNumberImpl ojni && 84 Objects.equals(string(), ojni.string()); 85 } 86 87 @Override 88 public int hashCode() { 89 return Objects.hash(string()); 90 } 91 92 Number toNum(String numStr) { 93 try { 94 return Long.parseLong(numStr); 95 } catch (NumberFormatException e) { 96 } 97 98 try { 99 return new BigInteger(numStr); 100 } catch (NumberFormatException e) { 101 } 102 103 if (Double.valueOf(numStr) instanceof double d && !Double.isInfinite(d)) { 104 return d; 105 } 106 107 return new BigDecimal(numStr); 108 109 // // Determine if fp 110 // boolean fp = false; 111 // for (char c : numStr.toCharArray()) { 112 // if (c == 'e' || c == 'E' || c =='.') { 113 // fp = true; 114 // break; 115 // } 116 // } 117 // 118 // // Make conversion 119 // if (!fp) { 120 // // integral numbers 121 // try { 122 // return Integer.valueOf(numStr); 123 // } catch (NumberFormatException _) { 124 // // int overflow. try long 125 // try { 126 // return Long.valueOf(numStr); 127 // } catch (NumberFormatException _) { 128 // // long overflow. convert to Double 129 // } 130 // } 131 // } 132 // var num = Double.valueOf(numStr); 133 // if (Double.isInfinite(num)) { 134 // throw new NumberFormatException("The number is infinitely large in magnitude"); 135 // } 136 // return num; 137 } 138 139 @Override 140 public Number toUntyped() { 141 return value(); 142 } 143 144 @Override 145 public String toString() { 146 return string(); 147 } 148 }