1/* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package std.core; 17 18/** 19 * Represents boxed long value and related operations 20 */ 21export final class Long extends Integral implements Comparable<Long>, JSONable<Int> { 22 private value: long; 23 24 /** 25 * Constructs a new Long instance with initial value zero 26 */ 27 public constructor() { 28 this.value = 0; 29 } 30 31 /** 32 * Constructs a new Long instance with provided initial value 33 * 34 * @param value the initial value 35 */ 36 public constructor(value: long) { 37 this.value = value; 38 } 39 40 /** 41 * Constructs a new Long instance with provided initial value 42 * 43 * @param value the initial value 44 */ 45 public constructor(value: Long) { 46 this.value = value.longValue(); 47 } 48 49 /** 50 * Returns value of this instance as a primitive 51 * 52 * @returns value of this instance 53 */ 54 public unboxed(): long { 55 return this.value; 56 } 57 58 /** 59 * Returns boxed representation of the primitive 60 * 61 * @param value value to box 62 * 63 * @returns boxed value 64 */ 65 public static valueOf(value: long): Long { 66 // TODO(ivan-tyulyandin): caching is possible 67 return new Long(value); 68 } 69 70 /** 71 * Minimal value that this type can have as a long 72 */ 73 public static MIN_VALUE: long = -9223372036854775808; 74 75 /** 76 * Maximal value that this type can have as a long 77 */ 78 public static MAX_VALUE: long = 9223372036854775807; 79 80 /** 81 * Size of this type in bits 82 */ 83 public static BIT_SIZE: byte = 64; 84 85 /** 86 * Size of this type in bytes 87 */ 88 public static BYTE_SIZE: byte = 8; 89 90 /** 91 * Returns value of this instance 92 * 93 * @returns value as long 94 */ 95 public override byteValue(): byte { 96 return this.value as byte; 97 } 98 99 /** 100 * Returns value of this instance 101 * 102 * @returns value as short 103 */ 104 public override shortValue(): short { 105 return this.value as short; 106 } 107 108 /** 109 * Returns value of this instance 110 * 111 * @returns value as int 112 */ 113 public override intValue(): int { 114 return this.value as int; 115 } 116 117 /** 118 * Returns value of this instance 119 * 120 * @returns value as long 121 */ 122 public override longValue(): long { 123 return this.value; 124 } 125 126 /** 127 * Returns value of this instance 128 * 129 * @returns value as long 130 */ 131 public override floatValue(): float { 132 return this.value as float; 133 } 134 135 /** 136 * Returns value of this instance 137 * 138 * @returns value as double 139 */ 140 public override doubleValue(): double { 141 return this.value as double; 142 } 143 144 /** 145 * Compares this instance to other Long object 146 * The result is less than 0 if this instance lesser than provided object 147 * 0 if they are equal 148 * and greater than 0 otherwise. 149 * 150 * @param other Long object to compare with 151 * 152 * @returns result of the comparison 153 */ 154 public override compareTo(other: Long): int { 155 return (this.value - other.unboxed()) as int; 156 } 157 158 /** 159 * Converts this object to a string 160 * 161 * @returns result of the conversion 162 */ 163 public override toString(): String { 164 return StringBuilder.toString(this.value); 165 } 166 167 /** 168 * Converts this object to a string 169 * 170 * @returns result of the conversion 171 */ 172 public toString(radix: number): string { 173 if ((radix as int) < 2 || (radix as int) > 36) { 174 throw new RangeError('Radix must be between 2 and 36'); 175 } 176 if (this.value == 0) { 177 return "0"; 178 } 179 const chars = '0123456789abcdefghijklmnopqrstuvwxyz'; 180 let val = this.value; 181 let negative: boolean = (val < 0); 182 let digitsNum = (log(abs(val)) / log(radix as int) + 1) as int; 183 if (negative) { 184 ++digitsNum; 185 } 186 let data = new char[digitsNum]; 187 let curPlace = digitsNum - 1; 188 while (val != 0) { 189 let remainder = val % (radix as int); 190 if (negative) { 191 remainder = -remainder; 192 } 193 data[curPlace] = chars.charAt(remainder as int); 194 val /= (radix as int); 195 curPlace -= 1; 196 } 197 if (negative) { 198 data[0] = c'-'; 199 } 200 return new String(data); 201 } 202 203 /** 204 * Returns a hash code (integer representation) for this instance 205 * 206 * @returns representation of this instance 207 */ 208 public override $_hashCode(): int { 209 return this.intValue(); 210 } 211 212 /** 213 * Checks for equality this instance with provided object, treated as a Long 214 * 215 * @param other object to be checked against 216 * 217 * @returns true if provided object and this instance have same value, false otherwise 218 * Returns false if type of provided object is not the same as this type 219 */ 220 public equals(other: NullishType): boolean { 221 if (__runtimeIsSameReference(this, other)) { 222 return true 223 } 224 225 if (!(other instanceof Long)) { 226 return false 227 } 228 229 return this.value == (other as Long).value 230 } 231 232 /** 233 * Performs integral addition of this instance with provided one, returns the result as new instance 234 * 235 * @param other Right hand side of the addition 236 * 237 * @returns Result of the addition 238 */ 239 public add(other: Long): Long { 240 return Long.valueOf((this.value + other.longValue()) as long) 241 } 242 243 /** 244 * Performs integral subtraction of this instance with provided one, returns the result as new instance 245 * 246 * @param other Right hand side of the subtraction 247 * 248 * @returns Result of the subtraction 249 */ 250 public sub(other: Long): Long { 251 return Long.valueOf((this.value - other.longValue()) as long) 252 } 253 254 /** 255 * Performs integral multiplication of this instance with provided one, returns the result as new instance 256 * 257 * @param other Right hand side of the multiplication 258 * 259 * @returns Result of the multiplication 260 */ 261 public mul(other: Long): Long { 262 return Long.valueOf((this.value * other.longValue()) as long) 263 } 264 265 /** 266 * Performs integral division of this instance with provided one, returns the result as new instance 267 * 268 * @param other Right hand side of the division 269 * 270 * @returns Result of the division 271 */ 272 public div(other: Long): Long { 273 return Long.valueOf((this.value / other.longValue()) as long) 274 } 275 276 /** 277 * Checks if this instance value is less than value of provided instance 278 * 279 * @param other Right hand side of the comparison 280 * 281 * @returns true if this value is less than provided, false otherwise 282 */ 283 public isLessThan(other: Long): boolean { 284 return this.value < other.longValue(); 285 } 286 287 /** 288 * Checks if this instance value is less than or equal to value of provided instance 289 * 290 * @param other Right hand side of the comparison 291 * 292 * @returns true if this value is less than or equal to provided, false otherwise 293 */ 294 public isLessEqualThan(other: Long): boolean { 295 return this.value <= other.longValue(); 296 } 297 298 /** 299 * Checks if this instance value is greater than value of provided instance 300 * 301 * @param other Right hand side of the comparison 302 * 303 * @returns true if this value is greater than provided, false otherwise 304 */ 305 public isGreaterThan(other: Long): boolean { 306 return this.value > other.longValue(); 307 } 308 309 /** 310 * Checks if this instance value is greater than or equal to value of provided instance 311 * 312 * @param other Right hand side of the comparison 313 * 314 * @returns true if this value is greater than or equal to provided, false otherwise 315 */ 316 public isGreaterEqualThan(other: Long): boolean { 317 return this.value >= other.longValue(); 318 } 319 320 /** 321 * Creates a Long instance based on JSONValue 322 * 323 * @param json: JSONValue - a JSON representation 324 * 325 * @throws JSONTypeError if json does not encode a valid long 326 * 327 * @returns Long - long value decoded from JSON 328 */ 329 static createFromJSONValue(json: JSONValue): Long { 330 if (json instanceof JSONNumber) { 331 let num = (json as JSONNumber).value 332 if (Double.isInteger(num) && Long.MIN_VALUE <= num && num <= Long.MAX_VALUE) { 333 return Long.valueOf(num as long) 334 } 335 } 336 throw new JSONTypeError("Cannot create Long from JSON", new ErrorOptions(json as Object)) 337 } 338} 339