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.util.Objects; 29 30 /** 31 * JsonNumber implementation class 32 */ 33 final class JsonNumberImpl implements JsonNumber, JsonValueImpl { 34 35 private final JsonDocumentInfo docInfo; 36 private final int startOffset; 37 private final int endOffset; 38 private final int endIndex; 39 private Number theNumber; 40 private String numString; 41 42 JsonNumberImpl(Number num) { 43 theNumber = num; 44 numString = num.toString(); 45 startOffset = 0; 46 endOffset = 0; 47 endIndex = 0; 48 docInfo = null; 49 } 50 51 JsonNumberImpl(JsonDocumentInfo doc, int offset, int index) { 52 docInfo = doc; 53 startOffset = offset; 54 endIndex = docInfo.nextIndex(index); 55 endOffset = endIndex != -1 ? docInfo.getOffset(endIndex) : docInfo.getEndOffset(); 56 } 57 58 @Override 59 public Number value() { 60 if (theNumber == null) { 61 theNumber = toNum(string()); 62 } 63 return theNumber; 64 } 65 66 private String string() { 67 if (numString == null) { // Trim back only 68 numString = docInfo.substring(startOffset, endOffset).stripTrailing(); 69 } 70 return numString; 71 } 72 73 @Override 74 public int getEndIndex() { 75 return endIndex; 76 } 77 78 @Override 79 public boolean equals(Object o) { 80 return this == o || 81 o instanceof JsonNumberImpl ojni && 82 Objects.equals(string(), ojni.string()); 83 } 84 85 @Override 86 public int hashCode() { 87 return Objects.hash(string()); 88 } 89 90 Number toNum(String numStr) { 91 // Determine if fp 92 boolean fp = false; 93 for (char c : numStr.toCharArray()) { 94 if (c == 'e' || c == 'E' || c =='.') { 95 fp = true; 96 break; 97 } 98 } 99 100 // Make conversion 101 if (!fp) { 102 // integral numbers 103 try { 104 return Integer.valueOf(numStr); 105 } catch (NumberFormatException _) { 106 // int overflow. try long 107 try { 108 return Long.valueOf(numStr); 109 } catch (NumberFormatException _) { 110 // long overflow. convert to Double 111 } 112 } 113 } 114 var num = Double.valueOf(numStr); 115 if (Double.isInfinite(num)) { 116 throw new NumberFormatException("The number is infinitely large in magnitude"); 117 } 118 return num; 119 } 120 121 @Override 122 public Number toUntyped() { 123 return value(); 124 } 125 126 @Override 127 public String toString() { 128 return string(); 129 } 130 }