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