View Javadoc
1   package io.jawk.jrt;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2026 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.math.BigDecimal;
26  
27  /**
28   * An input-derived scalar: text that may also act as a number, following
29   * POSIX "numeric string" (strnum) semantics. Input fields, {@code getline}
30   * results, {@code split()} pieces, and similar input-originated values are
31   * represented as instances of this class so comparisons and gawk's
32   * {@code typeof()} can distinguish them from plain string constants.
33   */
34  public final class StrNum {
35  
36  	private final String value;
37  	private final char decimalSeparator;
38  	private Boolean numeric;
39  	private Double numericValue;
40  
41  	StrNum(String value) {
42  		this(value, '.');
43  	}
44  
45  	StrNum(String value, char decimalSeparator) {
46  		this.value = value == null ? "" : value;
47  		this.decimalSeparator = decimalSeparator;
48  	}
49  
50  	/**
51  	 * Returns whether this scalar's text parses as an AWK number, making it a
52  	 * strnum.
53  	 *
54  	 * @return {@code true} when the text is a valid AWK number
55  	 */
56  	public boolean isNumber() {
57  		if (numeric == null) {
58  			numeric = Boolean.valueOf(JRT.isParseableNumber(value, decimalSeparator));
59  		}
60  		return numeric.booleanValue();
61  	}
62  
63  	/**
64  	 * Returns this scalar's numeric value.
65  	 *
66  	 * @return the parsed numeric value
67  	 */
68  	public double doubleValue() {
69  		if (numericValue == null) {
70  			numericValue = Double.valueOf(parseDoubleValue());
71  		}
72  		return numericValue.doubleValue();
73  	}
74  
75  	private double parseDoubleValue() {
76  		String normalizedValue = JRT.normalizeNumberForComparison(value, decimalSeparator);
77  		try {
78  			return Double.parseDouble(normalizedValue);
79  		} catch (NumberFormatException nfe) {
80  			return new BigDecimal(normalizedValue).doubleValue();
81  		}
82  	}
83  
84  	@Override
85  	public String toString() {
86  		return value;
87  	}
88  }