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