4b8ed6017795e428105fb0f0f6d31b4e61f85acf
[smo/teiv.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2024 Ericsson
4  *  Modifications Copyright (C) 2024 OpenInfra Foundation Europe
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21 package org.oran.smo.yangtools.parser.model.util;
22
23 import java.math.BigDecimal;
24 import java.math.BigInteger;
25
26 import org.oran.smo.yangtools.parser.model.util.DataTypeHelper.YangDataType;
27
28 /**
29  * Utility class to deal with numbers in Yang.
30  *
31  * @author Mark Hollmann
32  */
33 public abstract class NumberHelper {
34
35     /*
36      * integer-value = ("-" non-negative-integer-value) / non-negative-integer-value
37      * non-negative-integer-value = "0" / positive-integer-value
38      * positive-integer-value = (non-zero-digit *DIGIT)
39      * non-zero-digit = %x31-39
40      * decimal-value = integer-value ("." zero-integer-value)
41      * zero-integer-value = 1*DIGIT
42      */
43
44     /**
45      * Extracts a decimal number representing a yang "integer-value" or "decimal-value". Note that a BigDecimal
46      * will be returned even if the underlying number is mathematically integer.
47      */
48     public static BigDecimal extractYangIntegerValueOrDecimalValue(final String string) {
49         return new BigDecimal(string);
50     }
51
52     public static final BigDecimal INT8_MIN_VALUE = new BigDecimal("-128");
53     public static final BigDecimal INT16_MIN_VALUE = new BigDecimal("-32768");
54     public static final BigDecimal INT32_MIN_VALUE = new BigDecimal("-2147483648");
55     public static final BigDecimal INT64_MIN_VALUE = new BigDecimal("-9223372036854775808");
56
57     public static final BigDecimal UINT8_MAX_VALUE = new BigDecimal("255");
58     public static final BigDecimal UINT16_MAX_VALUE = new BigDecimal("65535");
59     public static final BigDecimal UINT32_MAX_VALUE = new BigDecimal("4294967295");
60     public static final BigDecimal UINT64_MAX_VALUE = new BigDecimal("18446744073709551615");
61
62     public static final BigDecimal INT8_MAX_VALUE = new BigDecimal("127");
63     public static final BigDecimal INT16_MAX_VALUE = new BigDecimal("32767");
64     public static final BigDecimal INT32_MAX_VALUE = new BigDecimal("2147483647");
65     public static final BigDecimal INT64_MAX_VALUE = new BigDecimal("9223372036854775807");
66
67     public static BigDecimal getMinValueForYangIntegerDataType(final YangDataType yangDataType) {
68
69         switch (yangDataType) {
70             case UINT8:
71             case UINT16:
72             case UINT32:
73             case UINT64:
74                 return BigDecimal.ZERO;
75             case INT8:
76                 return INT8_MIN_VALUE;
77             case INT16:
78                 return INT16_MIN_VALUE;
79             case INT32:
80                 return INT32_MIN_VALUE;
81             case INT64:
82                 return INT64_MIN_VALUE;
83             default:
84                 throw new RuntimeException("Not an integer data type");
85         }
86     }
87
88     public static BigDecimal getMaxValueForYangIntegerDataType(final YangDataType yangDataType) {
89
90         switch (yangDataType) {
91             case UINT8:
92                 return UINT8_MAX_VALUE;
93             case UINT16:
94                 return UINT16_MAX_VALUE;
95             case UINT32:
96                 return UINT32_MAX_VALUE;
97             case UINT64:
98                 return UINT64_MAX_VALUE;
99             case INT8:
100                 return INT8_MAX_VALUE;
101             case INT16:
102                 return INT16_MAX_VALUE;
103             case INT32:
104                 return INT32_MAX_VALUE;
105             case INT64:
106                 return INT64_MAX_VALUE;
107             default:
108                 throw new RuntimeException("Not an integer data type");
109         }
110     }
111
112     public static BigDecimal getMinValueForYangDecimalDataType(final int digits) {
113         return (digits >= 1 && digits <= 18) ?
114                 new BigDecimal("-9223372036854775808").divide(BigDecimal.valueOf(10L).pow(digits)) :
115                 null;
116     }
117
118     public static BigDecimal getMaxValueForYangDecimalDataType(final int digits) {
119         return (digits >= 1 && digits <= 18) ?
120                 new BigDecimal("9223372036854775807").divide(BigDecimal.valueOf(10L).pow(digits)) :
121                 null;
122     }
123
124     /**
125      * Returns the integer value (in a BigInteger) of a default value. Will return null
126      * if the supplied string cannot be translated to a BigInteger.
127      * <p>
128      * Special handling applies as follows (taken from the RFC):
129      * <p>
130      * "For convenience, when specifying a default value for an integer in a
131      * YANG module, an alternative lexical representation can be used that
132      * represents the value in a hexadecimal or octal notation. The
133      * hexadecimal notation consists of an optional sign ("+" or "-"),
134      * followed by the characters "0x", followed by a number of hexadecimal
135      * digits where letters may be uppercase or lowercase. The octal
136      * notation consists of an optional sign ("+" or "-"), followed by the
137      * character "0", followed by a number of octal digits.
138      * <p>
139      * Note that if a default value in a YANG module has a leading zero
140      * ("0"), it is interpreted as an octal number. In the XML encoding, an
141      * integer is always interpreted as a decimal number, and leading zeros
142      * are allowed."
143      */
144     public static BigInteger getIntegerDefaultValue(final String stringefiedValue) {
145
146         try {
147             if (stringefiedValue.equals("0") || stringefiedValue.equals("+0") || stringefiedValue.equals("-0")) {
148                 return BigInteger.ZERO;
149             } else if (stringefiedValue.startsWith("-0x")) {
150                 return new BigInteger(stringefiedValue.substring(3), 16).negate();
151             } else if (stringefiedValue.startsWith("+0x")) {
152                 return new BigInteger(stringefiedValue.substring(3), 16);
153             } else if (stringefiedValue.startsWith("0x")) {
154                 return new BigInteger(stringefiedValue.substring(2), 16);
155             } else if (stringefiedValue.startsWith("-0")) {
156                 return new BigInteger(stringefiedValue.substring(2), 8).negate();
157             } else if (stringefiedValue.startsWith("+0")) {
158                 return new BigInteger(stringefiedValue.substring(2), 8);
159             } else if (stringefiedValue.startsWith("0")) {
160                 return new BigInteger(stringefiedValue.substring(1), 8);
161             }
162
163             return getIntegerValue(stringefiedValue);
164
165         } catch (final Exception ignored) {
166             /* no-op */
167         }
168
169         return null;
170     }
171
172     /**
173      * Returns the integer value (in a BigInteger) of a value. Will return null
174      * if the supplied string cannot be translated to a BigInteger.
175      * <p>
176      * Note that special default value handling is <b>not</b> applied by this
177      * method, i.e. a leading zero is interpreted as the number zero.
178      */
179     public static BigInteger getIntegerValue(final String stringefiedValue) {
180         try {
181             return new BigInteger(stringefiedValue);
182         } catch (final Exception ignored) {
183             /* no-op */
184         }
185
186         return null;
187     }
188
189     /**
190      * Returns the decimal value (in a BigDecimal) of a value. Will return null
191      * if the supplied string cannot be translated to a BigDecimal.
192      * <p>
193      * Note that special handling (as for integers above) does NOT apply for
194      * decimal values.
195      */
196     public static BigDecimal getDecimalValue(final String stringefiedValue) {
197         try {
198             return new BigDecimal(stringefiedValue);
199         } catch (final Exception ex) {
200             /* no-op */
201         }
202
203         return null;
204     }
205 }