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&trade; 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&nbsp;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