001/* A token that contains an unsigned byte number in the range 0 through 255.
002
003 Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027
028 */
029package ptolemy.data;
030
031import ptolemy.data.type.BaseType;
032import ptolemy.data.type.Type;
033import ptolemy.data.type.TypeLattice;
034import ptolemy.graph.CPO;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.math.Complex;
037
038///////////////////////////////////////////////////////////////////
039//// UnsignedByteToken
040
041/**
042 A token that contains a byte number in the range 0 through 255.  This
043 UnsignedByteToken definition is in contrast to Java's definition of a
044 byte as a number in the range -128 through 127.
045
046 <p>Overflow and underflow are handled by returning the result of all
047 operations modulo 256.  Thus, the result is always in the range 0
048 through 255.  Likewise, constructors of this class generate tokens
049 whose values are the argument modulo 256.  Note, for example, that
050 UnsignedByteToken((byte)(-100)) generates a UnsignedByteToken
051 representing the value 156, which is -100 modulo 256.
052
053 <p>Note, also, that the byteValue() method returns a Java byte in the
054 range -128 through 127.  This is in contrast to the intValue(),
055 longValue(), doubleValue(), and complexValue() methods which all
056 return values in the range 0 through 255.  The value returned by
057 byteValue() is the value represented by the UnsignedByteToken but with
058 256 subtracted if this value is greater than 127.  In other words, the
059 result and the argument are equal modulo 256.
060
061 @author Winthrop Williams, Steve Neuendorffer, Contributor: Christopher Hylands
062 @version $Id$
063 @since Ptolemy II 2.0
064 @Pt.ProposedRating Yellow (cxh) ONE, ZERO, nil Token
065 @Pt.AcceptedRating Red (winthrop)
066 */
067public class UnsignedByteToken extends ScalarToken {
068    /** Construct a token with byte 0.
069     */
070    public UnsignedByteToken() {
071        _value = 0;
072    }
073
074    /** Construct a UnsignedByteToken with the specified byte value.  The
075     *  UnsignedByteToken constructed represents a value in the range 0
076     *  through 255.  However, the byte passed in as the argument to
077     *  this method represents a value in Java in the range -128 to
078     *  127.  Due to the difference between these definitions, this
079     *  method effectively adds 256 if the argument is negative,
080     *  resulting in a positive value for the UnsignedByteToken.
081     *  @param value The specified value.
082     */
083    public UnsignedByteToken(byte value) {
084        _value = value;
085    }
086
087    /** Construct a UnsignedByteToken with the specified integer value.  The
088     *  UnsignedByteToken constructed represents a value in the range 0
089     *  through 255.  However, the integer passed in as the argument
090     *  to this method represents a value in Java in the range -2^31
091     *  to (2^31)-1.  This method's cast to (byte) keeps only the low
092     *  order 8 bits of the integer.  This effectively adds or
093     *  subtracts a multiple of 256 to/from the argument.  The
094     *  resulting UnsignedByteToken falls in the range 0 through 255.
095     *  @param value The specified value.
096     */
097    public UnsignedByteToken(int value) {
098        _value = (byte) value;
099    }
100
101    /** Construct a UnsignedByteToken from the specified string.  The string
102     *  is parsed by the parseByte() method of the Java Byte object.
103     *  @param init The initialization string, which is an integer from
104     *  0 to 255.  -1 and 256 are illegal values.
105     *  @exception IllegalActionException If the token could not
106     *   be created from the given string.
107     */
108    public UnsignedByteToken(String init) throws IllegalActionException {
109        if (init == null || init.equals("nil")) {
110            throw new IllegalActionException(notSupportedNullNilStringMessage(
111                    "UnsignedByteToken", init));
112        }
113        try {
114            // Note that Byte.parseByte performs signed conversion,
115            // which is not really what we want.
116            int value = Integer.parseInt(init);
117
118            if (value > 255 || value < 0) {
119                throw new IllegalActionException("Value '" + init
120                        + "' is out of the range of Unsigned Byte");
121            }
122
123            _value = (byte) value;
124        } catch (NumberFormatException e) {
125            throw new IllegalActionException(null, e,
126                    "Failed to parse \"" + init + "\" as a number.");
127        }
128    }
129
130    ///////////////////////////////////////////////////////////////////
131    ////                         public methods                    ////
132
133    /** Return the value in this token as a byte, modulo 256.  The
134     *  UnsignedByteToken being converted represents a value in the range 0
135     *  through 255.  However, the Java byte it is being converted to
136     *  represents a value in the range -128 through 127.  Thus, this
137     *  method has the effect subtracting 256 from the value if the
138     *  value is greater than 127.
139     *  @return The byte value contained in this token, modulo 256.
140     */
141    @Override
142    public byte byteValue() {
143        return _value;
144    }
145
146    /** Return the value of this token as a Complex. The real part
147     *  of the Complex is the value of this token, the imaginary part
148     *  is set to 0.
149     *  @return A Complex.
150     */
151    @Override
152    public Complex complexValue() {
153        return new Complex(unsignedConvert(_value));
154    }
155
156    /** Convert the specified token into an instance of
157     *  UnsignedByteToken.  The units of the returned token will be
158     *  the same as the units of the given token.  If the argument is
159     *  already an instance of UnsignedByteToken, it is returned
160     *  without any change.  If the argument is null or a nil token,
161     *  then {@link #NIL} is returned.  Otherwise, if the argument is
162     *  above UnsignedByteToken in the type hierarchy or is
163     *  incomparable with UnsignedByteToken, an exception is thrown
164     *  with a message stating that either the conversion is not
165     *  supported, or the types are incomparable.  If none of the
166     *  above conditions is met, then the argument must be below
167     *  UnsignedByteToken in the type hierarchy.  However, not such
168     *  types exist at this time, so an exception is thrown with a
169     *  message stating simply that the conversion is not supported.
170     *  @param token The token to be converted to a UnsignedByteToken.
171     *  @return A UnsignedByteToken.
172     *  @exception IllegalActionException If the conversion
173     *   cannot be carried out.
174     */
175    public static UnsignedByteToken convert(Token token)
176            throws IllegalActionException {
177        if (token instanceof UnsignedByteToken) {
178            return (UnsignedByteToken) token;
179        }
180
181        if (token.isNil()) {
182            return UnsignedByteToken.NIL;
183        }
184        int compare = TypeLattice.compare(BaseType.UNSIGNED_BYTE, token);
185
186        if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) {
187            throw new IllegalActionException(
188                    notSupportedIncomparableConversionMessage(token, "byte"));
189        }
190
191        throw new IllegalActionException(
192                notSupportedConversionMessage(token, "byte"));
193    }
194
195    /** Return the value in the token as a double.
196     *  @return The value contained in this token as a double.
197     */
198    @Override
199    public double doubleValue() {
200        return unsignedConvert(_value);
201    }
202
203    /** Return true if the class of the argument is UnsignedByteToken,
204     *  and it has the same value as this token.
205     *  @param object An instance of Object.
206     *  @return True if the argument is an instance of
207     *  UnsignedByteToken with the same value.  If either this object
208     *  or the argument is a nil Token, return false.
209     */
210    @Override
211    public boolean equals(Object object) {
212        if (object == null) {
213            return false;
214        }
215        // This test rules out subclasses.
216        if (object.getClass() != getClass()) {
217            return false;
218        }
219
220        if (isNil() || ((UnsignedByteToken) object).isNil()) {
221            return false;
222        }
223
224        if (((UnsignedByteToken) object).byteValue() == _value) {
225            return true;
226        }
227
228        return false;
229    }
230
231    /** Return the type of this token.
232     *  @return BaseType.UNSIGNED_BYTE
233     */
234    @Override
235    public Type getType() {
236        return BaseType.UNSIGNED_BYTE;
237    }
238
239    /** Return a hash code value for this token. This method just returns
240     *  the value of this token.
241     *  @return A hash code value for this token.
242     */
243    @Override
244    public int hashCode() {
245        return _value;
246    }
247
248    /** Return the value in the token as an integer.
249     *  @return The byte value contained in this token as a int.
250     */
251    @Override
252    public int intValue() {
253        return unsignedConvert(_value);
254    }
255
256    /** Return true if the token is nil, (aka null or missing).
257     *  Nil or missing tokens occur when a data source is sparsely populated.
258     *  @return True if the token is the {@link #NIL} token.
259     */
260    @Override
261    public boolean isNil() {
262        // We use a method here so that we can easily change how
263        // we determine if a token is nil without modify lots of classes.
264        // Can't use equals() here, or we'll go into an infinite loop.
265        return this == UnsignedByteToken.NIL;
266    }
267
268    /** Returns a token representing the result of shifting the bits
269     *  of this token towards the most significant bit, filling the
270     *  least significant bits with zeros.
271     *  @param bits The number of bits to shift.
272     *  @return The left shift.
273     *  If this token is nil, then {@link #NIL} is returned.
274     */
275    @Override
276    public ScalarToken leftShift(int bits) {
277        if (isNil()) {
278            return UnsignedByteToken.NIL;
279        }
280        return new UnsignedByteToken(_value << bits);
281    }
282
283    /** Returns a token representing the result of shifting the bits
284     *  of this token towards the least significant bit, filling the
285     *  most significant bits with zeros.  This treats the value as an
286     *  unsigned number, which may have the effect of destroying the
287     *  sign of the value.
288     *  @param bits The number of bits to shift.
289     *  @return The logical right shift.
290     *  If this token is nil, then {@link #NIL} is returned.
291     */
292    @Override
293    public ScalarToken logicalRightShift(int bits) {
294        if (isNil()) {
295            return UnsignedByteToken.NIL;
296        }
297        return new UnsignedByteToken(_value >>> bits);
298    }
299
300    /** Return the value in the token as a long.
301     *  @return The byte value contained in this token as a long.
302     */
303    @Override
304    public long longValue() {
305        return unsignedConvert(_value);
306    }
307
308    /** Returns an UnsignedByteToken with value 1.
309     *  @return an UnsignedByteToken with value 1.
310     */
311    @Override
312    public Token one() {
313        return ONE;
314    }
315
316    /** Returns a token representing the result of shifting the bits
317     *  of this token towards the least significant bit, filling the
318     *  most significant bits with the sign of the value.  This preserves
319     *  the sign of the result.
320     *  @param bits The number of bits to shift.
321     *  @return The right shift.
322     *  If this token is nil, then {@link #NIL} is returned.
323     */
324    @Override
325    public ScalarToken rightShift(int bits) {
326        if (isNil()) {
327            return UnsignedByteToken.NIL;
328        }
329        // Note that this performs a logicalRightShift, since we are
330        // interpreting the byte to always be unsigned.
331        return new UnsignedByteToken(_value >>> bits);
332    }
333
334    /** Return the value in the token as a short.
335     *  @return The value contained in this token as a short.
336     */
337    @Override
338    public short shortValue() {
339        return unsignedConvert(_value);
340    }
341
342    /** Return the value of this token as a string that can be parsed
343     *  by the expression language to recover a token with the same value.
344     *  If this token has a unit, the return string also includes a unit
345     *  string produced by the unitsString() method in the super class.
346     *  @return A String representing the byte value and the units (if
347     *   any) of this token.
348     *  @see ptolemy.data.ScalarToken#unitsString
349     */
350    @Override
351    public String toString() {
352        String unitString = "";
353
354        if (!_isUnitless()) {
355            unitString = " * " + unitsString();
356        }
357
358        if (isNil()) {
359            // FIXME: what about units?
360            return super.toString();
361        }
362
363        return Integer.toString(unsignedConvert(_value)) + "ub" + unitString;
364    }
365
366    /** Convert a byte to an integer, treating the byte as an unsigned
367     *  value in the range 0 through 255.  Note that Java defines the
368     *  byte as having a value ranging from -128 through 127, so 256
369     *  is added if this value is negative.
370     *  @param value The byte to convert to an unsigned byte.
371     *  @return An integer in the range 0 through 255.
372     */
373    public static short unsignedConvert(byte value) {
374        short intValue = value;
375
376        if (intValue < 0) {
377            intValue += 256;
378        }
379
380        return intValue;
381    }
382
383    /** Returns an UnsignedByteToken with value 0.
384     *  @return An UnsignedByteToken with value 0.
385     */
386    @Override
387    public Token zero() {
388        return ZERO;
389    }
390
391    ///////////////////////////////////////////////////////////////////
392    ////                         public variablesds                ////
393
394    /** A token that represents a missing value.
395     *  Null or missing tokens are common in analytical systems
396     *  like R and SAS where they are used to handle sparsely populated data
397     *  sources.  In database parlance, missing tokens are sometimes called
398     *  null tokens.  Since null is a Java keyword, we use the term "nil".
399     *  The toString() method on a nil token returns the string "nil".
400     */
401    public static final UnsignedByteToken NIL = new UnsignedByteToken();
402
403    /** A UnsignedByteToken with the value 1. */
404    public static final UnsignedByteToken ONE = new UnsignedByteToken(1);
405
406    /** A UnsignedByteToken with the value 0. */
407    public static final UnsignedByteToken ZERO = new UnsignedByteToken(0);
408
409    ///////////////////////////////////////////////////////////////////
410    ////                         protected methods                 ////
411
412    /** Return a ScalarToken containing the absolute value of the
413     *  value of this token. If this token contains a non-negative
414     *  number, it is returned directly; otherwise, a new token is is
415     *  return.  Note that it is explicitly allowable to return this
416     *  token, since the units are the same.  Since we have defined
417     *  the byte as ranging from 0 through 255, its absolute value is
418     *  equal to itself.  Although this method does not actually do
419     *  anything, it is included to make the UnsignedByteToken interface
420     *  compatible with the interfaces of the other types.
421     *  @return An UnsignedByteToken.
422     */
423    @Override
424    protected ScalarToken _absolute() {
425        return this;
426    }
427
428    /** Return a new token whose value is the value of the argument
429     *  Token added to the value of this Token.  It is assumed that
430     *  the type of the argument is an UnsignedByteToken.  Overflow is handled
431     *  by subtracting 256 so that the resulting sum falls in the
432     *  range 0 through 255.
433     *  @param rightArgument The token to add to this token.
434     *  @return A new UnsignedByteToken containing the result.
435     */
436    @Override
437    protected ScalarToken _add(ScalarToken rightArgument) {
438        byte sum = (byte) (_value
439                + ((UnsignedByteToken) rightArgument).byteValue());
440        return new UnsignedByteToken(sum);
441    }
442
443    /** Returns a token representing the bitwise AND of this token and
444     *  the given token.  It is assumed that the type of the argument is
445     *  UnsignedByteToken.
446     *  @param rightArgument The UnsignedByteToken to bitwise AND with
447     *  this one.
448     *  @return The bitwise AND.
449     */
450    @Override
451    protected ScalarToken _bitwiseAnd(ScalarToken rightArgument) {
452        byte sum = (byte) (_value
453                & ((UnsignedByteToken) rightArgument).byteValue());
454        return new UnsignedByteToken(sum);
455    }
456
457    /** Returns a token representing the bitwise NOT of this token.
458     *  @return The bitwise NOT of this token.
459     */
460    @Override
461    protected ScalarToken _bitwiseNot() {
462        UnsignedByteToken result = new UnsignedByteToken((byte) ~_value);
463        return result;
464    }
465
466    /** Returns a token representing the bitwise OR of this token and
467     *  the given token.  It is assumed that the type of the argument is
468     *  UnsignedByteToken.
469     *  @param rightArgument The UnsignedByteToken to bitwise OR with
470     *  this one.
471     *  @return The bitwise OR.
472     */
473    @Override
474    protected ScalarToken _bitwiseOr(ScalarToken rightArgument) {
475        byte sum = (byte) (_value
476                | ((UnsignedByteToken) rightArgument).byteValue());
477        return new UnsignedByteToken(sum);
478    }
479
480    /** Returns a token representing the bitwise XOR of this token and
481     *  the given token.  It is assumed that the type of the argument is
482     *  UnsignedByteToken.
483     *  @param rightArgument The UnsignedByteToken to bitwise XOR with
484     *  this one.
485     *  @return The bitwise XOR.
486     */
487    @Override
488    protected ScalarToken _bitwiseXor(ScalarToken rightArgument) {
489        byte sum = (byte) (_value
490                ^ ((UnsignedByteToken) rightArgument).byteValue());
491        return new UnsignedByteToken(sum);
492    }
493
494    /** Return a new token whose value is the value of this token
495     *  divided by the value of the argument token. It is assumed that
496     *  the type of the argument is an UnsignedByteToken.  The result will be
497     *  a byte containing the quotient.  For example, 255 divided by
498     *  10 returns 25.  This method does not test for or attempt to
499     *  prevent division by 0.
500     *  @param rightArgument The token to divide this token by.
501     *  @return A new UnsignedByteToken containing the result.
502     */
503    @Override
504    protected ScalarToken _divide(ScalarToken rightArgument) {
505        byte quotient = (byte) (unsignedConvert(_value) / unsignedConvert(
506                ((UnsignedByteToken) rightArgument).byteValue()));
507        return new UnsignedByteToken(quotient);
508    }
509
510    /** Test whether the value of this token is close to the first argument,
511     *  where "close" means that the distance between them is less than
512     *  or equal to the second argument.  It is assumed that the argument is
513     *         an UnsignedByteToken.
514     *  @param rightArgument The token to compare to this token.
515     *  @param epsilon The distance.
516     *  @return A true-valued token if the first argument is close to
517     *  this token.
518     */
519    @Override
520    protected BooleanToken _isCloseTo(ScalarToken rightArgument,
521            double epsilon) {
522        long right = ((UnsignedByteToken) rightArgument).longValue();
523        long left = longValue();
524        long distance = Math.round(Math.floor(epsilon));
525
526        if (right > left + distance || right < left - distance) {
527            return BooleanToken.FALSE;
528        } else {
529            return BooleanToken.TRUE;
530        }
531    }
532
533    /** Test for ordering of the values of this Token and the argument
534     *  Token.  It is assumed that the type of the argument is
535     *  UnsignedByteToken.
536     *  @param rightArgument The token to add to this token.
537     *  @return A new Token containing the result.
538     */
539    @Override
540    protected BooleanToken _isLessThan(ScalarToken rightArgument) {
541        UnsignedByteToken convertedArgument = (UnsignedByteToken) rightArgument;
542        return BooleanToken.getInstance(unsignedConvert(
543                _value) < unsignedConvert(convertedArgument.byteValue()));
544    }
545
546    /** Return a new token whose value is the value of this token
547     *  modulo the value of the argument token.  It is assumed that
548     *  the type of the argument is UnsignedByteToken.  This method does not
549     *  test for or attempt to prevent division by 0.
550     *  @param rightArgument The token to modulo this token by.
551     *  @return A new UnsignedByteToken containing the result.
552     */
553    @Override
554    protected ScalarToken _modulo(ScalarToken rightArgument) {
555        byte remainder = (byte) (unsignedConvert(_value) % unsignedConvert(
556                ((UnsignedByteToken) rightArgument).byteValue()));
557        return new UnsignedByteToken(remainder);
558    }
559
560    /** Return a new token whose value is the value of this token
561     *  multiplied by the value of the argument token.  It is assumed
562     *  that the type of the argument is UnsignedByteToken.  Overflow is
563     *  handled by subtracting the multiple of 256 which puts the
564     *  result into the range 0 through 255.  In other words, return
565     *  the product modulo 256.
566     *  @param rightArgument The token to multiply this token by.
567     *  @return A new UnsignedByteToken containing the product modulo 256.
568     */
569    @Override
570    protected ScalarToken _multiply(ScalarToken rightArgument) {
571        byte product = (byte) (unsignedConvert(_value) * unsignedConvert(
572                ((UnsignedByteToken) rightArgument).byteValue()));
573        return new UnsignedByteToken(product);
574    }
575
576    /** Return a new token whose value is the value of the argument
577     *  token subtracted from the value of this token.  It is assumed
578     *  that the type of the argument is UnsignedByteToken.  Underflow is
579     *  handled by adding 256 to the result if it is less than 0.
580     *  Thus the result is always in the range 0 through 255.
581     *  @param rightArgument The token to subtract from this token.
582     *  @return A new UnsignedByteToken containing the difference modulo 256.
583     */
584    @Override
585    protected ScalarToken _subtract(ScalarToken rightArgument) {
586        byte difference = (byte) (unsignedConvert(_value) - unsignedConvert(
587                ((UnsignedByteToken) rightArgument).byteValue()));
588        return new UnsignedByteToken(difference);
589    }
590
591    ///////////////////////////////////////////////////////////////////
592    ////                         private variables                 ////
593    private byte _value;
594}