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