1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.Short; 13 14 import hunt.Byte; 15 import hunt.Nullable; 16 import hunt.Number; 17 import std.conv; 18 /** 19 * The {@code Short} class wraps a value of primitive type {@code 20 * short} in an object. An object of type {@code Short} contains a 21 * single field whose type is {@code short}. 22 * 23 * <p>In addition, this class provides several methods for converting 24 * a {@code short} to a {@code string} and a {@code string} to a 25 * {@code short}, as well as other constants and methods useful when 26 * dealing with a {@code short}. 27 * 28 * @author Nakul Saraiya 29 * @author Joseph D. Darcy 30 * @see java.lang.Number 31 */ 32 class Short : AbstractNumber!short /*implements Comparable<Short> */{ 33 34 /** 35 * A constant holding the minimum value a {@code short} can 36 * have, -2<sup>15</sup>. 37 */ 38 enum short MIN_VALUE = -32768; 39 40 /** 41 * A constant holding the maximum value a {@code short} can 42 * have, 2<sup>15</sup>-1. 43 */ 44 enum short MAX_VALUE = 32767; 45 46 /** 47 * The {@code Class} instance representing the primitive type 48 * {@code short}. 49 */ 50 // @SuppressWarnings("unchecked") 51 // static Class<Short> TYPE = (Class<Short>) Class.getPrimitiveClass("short"); 52 53 /** 54 * Returns a new {@code string} object representing the 55 * specified {@code short}. The radix is assumed to be 10. 56 * 57 * @param s the {@code short} to be converted 58 * @return the string representation of the specified {@code short} 59 * @see java.lang.Integer#toString(int) 60 */ 61 static string toString(short s) { 62 return to!string(s); 63 } 64 65 /** 66 * Parses the string argument as a signed {@code short} in the 67 * radix specified by the second argument. The characters in the 68 * string must all be digits, of the specified radix (as 69 * determined by whether {@link java.lang.Character#digit(char, 70 * int)} returns a nonnegative value) except that the first 71 * character may be an ASCII minus sign {@code '-'} 72 * ({@code '\u005Cu002D'}) to indicate a negative value or an 73 * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to 74 * indicate a positive value. The resulting {@code short} value 75 * is returned. 76 * 77 * <p>An exception of type {@code NumberFormatException} is 78 * thrown if any of the following situations occurs: 79 * <ul> 80 * <li> The first argument is {@code null} or is a string of 81 * length zero. 82 * 83 * <li> The radix is either smaller than {@link 84 * java.lang.Character#MIN_RADIX} or larger than {@link 85 * java.lang.Character#MAX_RADIX}. 86 * 87 * <li> Any character of the string is not a digit of the 88 * specified radix, except that the first character may be a minus 89 * sign {@code '-'} ({@code '\u005Cu002D'}) or plus sign 90 * {@code '+'} ({@code '\u005Cu002B'}) provided that the 91 * string is longer than length 1. 92 * 93 * <li> The value represented by the string is not a value of type 94 * {@code short}. 95 * </ul> 96 * 97 * @param s the {@code string} containing the 98 * {@code short} representation to be parsed 99 * @param radix the radix to be used while parsing {@code s} 100 * @return the {@code short} represented by the string 101 * argument in the specified radix. 102 * @throws NumberFormatException If the {@code string} 103 * does not contain a parsable {@code short}. 104 */ 105 // static short parseShort(string s, int radix) 106 // throws NumberFormatException { 107 // int i = Integer.parseInt(s, radix); 108 // if (i < MIN_VALUE || i > MAX_VALUE) 109 // throw new NumberFormatException( 110 // "Value out of range. Value:\"" ~ s ~ "\" Radix:" ~ radix); 111 // return (short)i; 112 // } 113 114 /** 115 * Parses the string argument as a signed decimal {@code 116 * short}. The characters in the string must all be decimal 117 * digits, except that the first character may be an ASCII minus 118 * sign {@code '-'} ({@code '\u005Cu002D'}) to indicate a 119 * negative value or an ASCII plus sign {@code '+'} 120 * ({@code '\u005Cu002B'}) to indicate a positive value. The 121 * resulting {@code short} value is returned, exactly as if the 122 * argument and the radix 10 were given as arguments to the {@link 123 * #parseShort(java.lang.string, int)} method. 124 * 125 * @param s a {@code string} containing the {@code short} 126 * representation to be parsed 127 * @return the {@code short} value represented by the 128 * argument in decimal. 129 * @throws NumberFormatException If the string does not 130 * contain a parsable {@code short}. 131 */ 132 // static short parseShort(string s) throws NumberFormatException { 133 // return parseShort(s, 10); 134 // } 135 136 /** 137 * Returns a {@code Short} object holding the value 138 * extracted from the specified {@code string} when parsed 139 * with the radix given by the second argument. The first argument 140 * is interpreted as representing a signed {@code short} in 141 * the radix specified by the second argument, exactly as if the 142 * argument were given to the {@link #parseShort(java.lang.string, 143 * int)} method. The result is a {@code Short} object that 144 * represents the {@code short} value specified by the string. 145 * 146 * <p>In other words, this method returns a {@code Short} object 147 * equal to the value of: 148 * 149 * <blockquote> 150 * {@code new Short(Short.parseShort(s, radix))} 151 * </blockquote> 152 * 153 * @param s the string to be parsed 154 * @param radix the radix to be used in interpreting {@code s} 155 * @return a {@code Short} object holding the value 156 * represented by the string argument in the 157 * specified radix. 158 * @throws NumberFormatException If the {@code string} does 159 * not contain a parsable {@code short}. 160 */ 161 // static Short valueOf(string s, int radix) 162 // throws NumberFormatException { 163 // return valueOf(parseShort(s, radix)); 164 // } 165 166 /** 167 * Returns a {@code Short} object holding the 168 * value given by the specified {@code string}. The argument 169 * is interpreted as representing a signed decimal 170 * {@code short}, exactly as if the argument were given to 171 * the {@link #parseShort(java.lang.string)} method. The result is 172 * a {@code Short} object that represents the 173 * {@code short} value specified by the string. 174 * 175 * <p>In other words, this method returns a {@code Short} object 176 * equal to the value of: 177 * 178 * <blockquote> 179 * {@code new Short(Short.parseShort(s))} 180 * </blockquote> 181 * 182 * @param s the string to be parsed 183 * @return a {@code Short} object holding the value 184 * represented by the string argument 185 * @throws NumberFormatException If the {@code string} does 186 * not contain a parsable {@code short}. 187 */ 188 // static Short valueOf(string s) throws NumberFormatException { 189 // return valueOf(s, 10); 190 // } 191 192 // private static class ShortCache { 193 // private ShortCache(){} 194 195 // static Short cache[] = new Short[-(-128) + 127 + 1]; 196 197 // static { 198 // for(int i = 0; i < cache.length; i++) 199 // cache[i] = new Short((short)(i - 128)); 200 // } 201 // } 202 203 /** 204 * Returns a {@code Short} instance representing the specified 205 * {@code short} value. 206 * If a new {@code Short} instance is not required, this method 207 * should generally be used in preference to the constructor 208 * {@link #Short(short)}, as this method is likely to yield 209 * significantly better space and time performance by caching 210 * frequently requested values. 211 * 212 * This method will always cache values in the range -128 to 127, 213 * inclusive, and may cache other values outside of this range. 214 * 215 * @param s a short value. 216 * @return a {@code Short} instance representing {@code s}. 217 */ 218 // static Short valueOf(short s) { 219 // int offset = 128; 220 // int sAsInt = s; 221 // if (sAsInt >= -128 && sAsInt <= 127) { // must cache 222 // return ShortCache.cache[sAsInt + offset]; 223 // } 224 // return new Short(s); 225 // } 226 227 /** 228 * Decodes a {@code string} into a {@code Short}. 229 * Accepts decimal, hexadecimal, and octal numbers given by 230 * the following grammar: 231 * 232 * <blockquote> 233 * <dl> 234 * <dt><i>DecodableString:</i> 235 * <dd><i>Sign<sub>opt</sub> DecimalNumeral</i> 236 * <dd><i>Sign<sub>opt</sub></i> {@code 0x} <i>HexDigits</i> 237 * <dd><i>Sign<sub>opt</sub></i> {@code 0X} <i>HexDigits</i> 238 * <dd><i>Sign<sub>opt</sub></i> {@code #} <i>HexDigits</i> 239 * <dd><i>Sign<sub>opt</sub></i> {@code 0} <i>OctalDigits</i> 240 * 241 * <dt><i>Sign:</i> 242 * <dd>{@code -} 243 * <dd>{@code +} 244 * </dl> 245 * </blockquote> 246 * 247 * <i>DecimalNumeral</i>, <i>HexDigits</i>, and <i>OctalDigits</i> 248 * are as defined in section 3.10.1 of 249 * <cite>The Java™ Language Specification</cite>, 250 * except that underscores are not accepted between digits. 251 * 252 * <p>The sequence of characters following an optional 253 * sign and/or radix specifier ("{@code 0x}", "{@code 0X}", 254 * "{@code #}", or leading zero) is parsed as by the {@code 255 * Short.parseShort} method with the indicated radix (10, 16, or 256 * 8). This sequence of characters must represent a positive 257 * value or a {@link NumberFormatException} will be thrown. The 258 * result is negated if first character of the specified {@code 259 * string} is the minus sign. No whitespace characters are 260 * permitted in the {@code string}. 261 * 262 * @param nm the {@code string} to decode. 263 * @return a {@code Short} object holding the {@code short} 264 * value represented by {@code nm} 265 * @throws NumberFormatException if the {@code string} does not 266 * contain a parsable {@code short}. 267 * @see java.lang.Short#parseShort(java.lang.string, int) 268 */ 269 // static Short decode(string nm) throws NumberFormatException { 270 // int i = Integer.decode(nm); 271 // if (i < MIN_VALUE || i > MAX_VALUE) 272 // throw new NumberFormatException( 273 // "Value " ~ i ~ " out of range from input " ~ nm); 274 // return valueOf((short)i); 275 // } 276 277 /** 278 * The value of the {@code Short}. 279 * 280 * @serial 281 */ 282 // private short value; 283 284 /** 285 * Constructs a newly allocated {@code Short} object that 286 * represents the specified {@code short} value. 287 * 288 * @param value the value to be represented by the 289 * {@code Short}. 290 */ 291 this(short value) { 292 super(value); 293 } 294 295 this(int value) { 296 super(cast(short)value); 297 } 298 299 /** 300 * Constructs a newly allocated {@code Short} object that 301 * represents the {@code short} value indicated by the 302 * {@code string} parameter. The string is converted to a 303 * {@code short} value in exactly the manner used by the 304 * {@code parseShort} method for radix 10. 305 * 306 * @param s the {@code string} to be converted to a 307 * {@code Short} 308 * @throws NumberFormatException If the {@code string} 309 * does not contain a parsable {@code short}. 310 * @see java.lang.Short#parseShort(java.lang.string, int) 311 */ 312 // Short(string s) throws NumberFormatException { 313 // this.value = parseShort(s, 10); 314 // } 315 316 317 /** 318 * Returns a hash code for this {@code Short}; equal to the result 319 * of invoking {@code intValue()}. 320 * 321 * @return a hash code value for this {@code Short} 322 */ 323 override 324 size_t toHash() @trusted nothrow { 325 return cast(int)(value); 326 } 327 328 329 /** 330 * The number of bits used to represent a {@code short} value in two's 331 * complement binary form. 332 */ 333 enum int SIZE = 16; 334 335 /** 336 * The number of bytes used to represent a {@code short} value in two's 337 * complement binary form. 338 * 339 */ 340 enum int BYTES = SIZE / Byte.SIZE; 341 342 /** 343 * Returns the value obtained by reversing the order of the bytes in the 344 * two's complement representation of the specified {@code short} value. 345 * 346 * @param i the value whose bytes are to be reversed 347 * @return the value obtained by reversing (or, equivalently, swapping) 348 * the bytes in the specified {@code short} value. 349 */ 350 static short reverseBytes(short i) { 351 return cast(short) (((i & 0xFF00) >> 8) | (i << 8)); 352 } 353 354 355 /** 356 * Converts the argument to an {@code int} by an unsigned 357 * conversion. In an unsigned conversion to an {@code int}, the 358 * high-order 16 bits of the {@code int} are zero and the 359 * low-order 16 bits are equal to the bits of the {@code short} argument. 360 * 361 * Consequently, zero and positive {@code short} values are mapped 362 * to a numerically equal {@code int} value and negative {@code 363 * short} values are mapped to an {@code int} value equal to the 364 * input plus 2<sup>16</sup>. 365 * 366 * @param x the value to convert to an unsigned {@code int} 367 * @return the argument converted to {@code int} by an unsigned 368 * conversion 369 */ 370 static int toUnsignedInt(short x) { 371 return (cast(int) x) & 0xffff; 372 } 373 374 /** 375 * Converts the argument to a {@code long} by an unsigned 376 * conversion. In an unsigned conversion to a {@code long}, the 377 * high-order 48 bits of the {@code long} are zero and the 378 * low-order 16 bits are equal to the bits of the {@code short} argument. 379 * 380 * Consequently, zero and positive {@code short} values are mapped 381 * to a numerically equal {@code long} value and negative {@code 382 * short} values are mapped to a {@code long} value equal to the 383 * input plus 2<sup>16</sup>. 384 * 385 * @param x the value to convert to an unsigned {@code long} 386 * @return the argument converted to {@code long} by an unsigned 387 * conversion 388 */ 389 static long toUnsignedLong(short x) { 390 return (cast(long) x) & 0xffffL; 391 } 392 393 /** use serialVersionUID from JDK 1.1. for interoperability */ 394 private static long serialVersionUID = 7515723908773894738L; 395 396 static short parseShort(string s) { 397 auto i = to!int(s); 398 if (i < MIN_VALUE || i > MAX_VALUE) 399 { 400 throw new Exception( 401 "Value " ~s ~ " out of range from input "); 402 } 403 404 return cast(short)i; 405 } 406 }