001 /* JAPI - (Yet another (hopefully) useful) Java API
002 *
003 * Copyright (C) 2006 Christian Hujer
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License as
007 * published by the Free Software Foundation; either version 2 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but
011 * WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013 * General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018 * 02111-1307, USA.
019 */
020
021 package net.sf.japi.io;
022
023 /** A class with methods for converting BCD data from and to Binary data.
024 * Currently only int is supported.
025 * Probably <code>net.sf.japi.io</code> is not the ideal package for this class, yet it seems most appropriate.
026 * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
027 */
028 public final class BCD {
029
030 /** Private constructor - no instances needed. */
031 private BCD() {
032 }
033
034 /** Convert a BCD value to an int value.
035 * @param bcd BCD value
036 * @return int value for bcd value
037 */
038 public static int bcd2int(final int bcd) {
039 int ret = 0;
040 for (int i = 0; i < 8; i++) {
041 ret += (0xF & bcd >> 4 * i) * base10(i);
042 }
043 return ret;
044 }
045
046 /** Convert an int value to a BCD value.
047 * @param val int value
048 * @return bcd value for int value
049 */
050 public static int int2bcd(final int val) {
051 int bcd = 0;
052 int work = val;
053 for (int i = 0; i < 8; i++) {
054 final int nibble = work % 10;
055 work /= 10;
056 bcd += nibble * (1 << 4 * i);
057 }
058 return bcd;
059 }
060
061 /** Check wether a BCD value is correct.
062 * If the supplied value contains a nibble with a value >= 10, it will throw an IllegalArgumentException.
063 * Otherwise it will simply return.
064 * @param bcd number to check
065 */
066 public static void check(final int bcd) {
067 for (int i = 0; i < 8; i++) {
068 if ((0xF & bcd >> 4 * i) >= 10) {
069 throw new IllegalArgumentException();
070 }
071 }
072 }
073
074 /** Check wether a BCD value is correct.
075 * @param bcd bcd value to check
076 * @return <code>true</code> if supplied value is bcd, otherwise <code>false</code>
077 */
078 public static boolean isBcd(final int bcd) {
079 for (int i = 0; i < 8; i++) {
080 if ((0xF & bcd >> 4 * i) >= 10) {
081 return false;
082 }
083 }
084 return true;
085 }
086
087 /** Return the 10 base (10^n).
088 * @param n power
089 * @return <code>10^<var>n</var></code>
090 */
091 public static int base10(final int n) {
092 int ret = 1;
093 for (int i = 0; i < n; i++) {
094 ret *= 10;
095 }
096 return ret;
097 }
098
099 /** Perform a BCD correction.
100 * For each nibble that contains a value greater than or equal 10, the next nibble will be incremented.
101 * Any overflow is added to the low byte, so an overflow bcd value will toggle even/odd.
102 * @param bcd bcd value to correct
103 * @return corrected bcd value
104 */
105 public static int correct(final int bcd) {
106 int newBcd = bcd;
107 for (int i = 0; i < 8; i++) {
108 if ((0xF & bcd >> 4 * i) >= 10) {
109 newBcd -= 10 << 4 * i;
110 newBcd += 1 << 4 * (i + 1);
111 }
112 }
113 assert isBcd(newBcd);
114 return newBcd;
115 }
116
117 } // class BCD