22
33import java .util .Arrays ;
44
5+ /**
6+ * Converts between different representations of trytes, bytes, trits and numbers.
7+ *
8+ * <p>
9+ * The IOTA protocol is represented in Trits and Trytes, while data is stored and broadcast in Bytes.
10+ * This class is used to convert between the representations.
11+ * </p>
12+ * <p>
13+ * This class also provides additional conversion tools:
14+ * <ul>
15+ * <li>Converting Trits to numerical values based on <i>Balanced ternary</i> arithmetic</li>
16+ * <li>Converting ascii to a Tryte string</li>
17+ * </ul>
18+ * </p>
19+ */
520public class Converter {
621
722 public static final int RADIX = 3 ;
@@ -21,7 +36,7 @@ public class Converter {
2136
2237 public static final int MIN_TRYTE_VALUE = -13 , MAX_TRYTE_VALUE = 13 ;
2338
24-
39+ //lookup tables for bytes->trits and trytes->trits conversion
2540 static {
2641
2742 final byte [] trits = new byte [NUMBER_OF_TRITS_IN_A_BYTE ];
@@ -35,26 +50,41 @@ public class Converter {
3550 TRYTE_TO_TRITS_MAPPINGS [i ] = Arrays .copyOf (trits , NUMBER_OF_TRITS_IN_A_TRYTE );
3651 increment (trits , NUMBER_OF_TRITS_IN_A_TRYTE );
3752 }
38- }
39-
40- public static long longValue (final byte [] trits , final int srcPos , final int size ) {
4153
42- long value = 0 ;
43- for (int i = size ; i -- > 0 ; ) {
44- value = value * RADIX + trits [srcPos + i ];
54+ }
55+ private static void increment (final byte [] trits , final int size ) {
56+ for (int i = 0 ; i < size ; i ++) {
57+ if (++trits [i ] > Converter .MAX_TRIT_VALUE ) {
58+ trits [i ] = Converter .MIN_TRIT_VALUE ;
59+ } else {
60+ break ;
61+ }
4562 }
46- return value ;
4763 }
4864
65+ // Bytes <-> Trits
66+
67+ /**
68+ * Allocates a byte array large enough to fit trits, used for converting trits to bytes.
69+ *
70+ * @param tritCount length of trit array (to be converted)
71+ * @return a new byte array large enough to fit trits
72+ */
4973 public static byte [] allocateBytesForTrits (int tritCount ) {
5074 final int expectedLength = (tritCount + NUMBER_OF_TRITS_IN_A_BYTE - 1 ) / NUMBER_OF_TRITS_IN_A_BYTE ;
5175 return new byte [expectedLength ];
5276 }
5377
54- public static byte [] allocateTritsForTrytes (int tryteCount ) {
55- return new byte [tryteCount * NUMBER_OF_TRITS_IN_A_TRYTE ];
56- }
57-
78+ /**
79+ * Converts trits array to bytes array based on {@link #NUMBER_OF_TRITS_IN_A_BYTE}.<br>
80+ * this method will override the content of {@code dest}
81+ *
82+ * @param trits source trits array
83+ * @param srcPos starting position for trits
84+ * @param dest destination bytes array
85+ * @param destPos starting position for destination bytes array
86+ * @param tritsLength amount of trits to convert
87+ */
5888 public static void bytes (final byte [] trits , final int srcPos , byte [] dest , int destPos , final int tritsLength ) {
5989
6090 final int expectedLength = (tritsLength + NUMBER_OF_TRITS_IN_A_BYTE - 1 ) / NUMBER_OF_TRITS_IN_A_BYTE ;
@@ -72,10 +102,36 @@ public static void bytes(final byte[] trits, final int srcPos, byte[] dest, int
72102 }
73103 }
74104
105+ /**
106+ * Converts trits array to bytes array. <br>
107+ * this method will override the content of {@code dest}
108+ * @see #bytes(byte[], int, byte[], int, int)
109+ *
110+ * @param trits source trits array
111+ * @param dest destination bytes array
112+ */
75113 public static void bytes (final byte [] trits , byte [] dest ) {
76114 bytes (trits , 0 , dest , 0 , trits .length );
77115 }
78116
117+ /**
118+ * Allocates trits (a byte array) large enough to fit trytes, used for converting trytes to trits.
119+ *
120+ * @param tryteCount length of tryte array (to be converted)
121+ * @return a new byte array large enough to fit trytes
122+ */
123+ public static byte [] allocateTritsForTrytes (int tryteCount ) {
124+ return new byte [tryteCount * NUMBER_OF_TRITS_IN_A_TRYTE ];
125+ }
126+
127+ /**
128+ * Converts bytes array to trits array based on {@link #NUMBER_OF_TRITS_IN_A_BYTE}.<br>
129+ * the inverse of {@link #bytes(byte[], int, byte[], int, int)}. <br>
130+ * this method will override the content of {@code trits}
131+ *
132+ * @param bytes source bytes array
133+ * @param trits destination trits array
134+ */
79135 public static void getTrits (final byte [] bytes , final byte [] trits ) {
80136
81137 int offset = 0 ;
@@ -88,6 +144,17 @@ public static void getTrits(final byte[] bytes, final byte[] trits) {
88144 }
89145 }
90146
147+
148+
149+ // Trytes <-> Trits
150+ /**
151+ * Converts a tryte string to trits (bytes array) based on {@link #NUMBER_OF_TRITS_IN_A_TRYTE}.<br>
152+ * this method will override the content of {@code dest}
153+ *
154+ * @param trytes source trytes string
155+ * @param dest destination trits array
156+ * @param destOffset starting position for destination bytes array
157+ */
91158 public static void trits (final String trytes , byte [] dest , int destOffset ) {
92159 if ((dest .length - destOffset ) < trytes .length () * NUMBER_OF_TRITS_IN_A_TRYTE ) {
93160 throw new IllegalArgumentException ("Destination array is not large enough." );
@@ -99,8 +166,81 @@ public static void trits(final String trytes, byte[] dest, int destOffset) {
99166 }
100167 }
101168
102- public static void copyTrits (final long value , final byte [] destination , final int offset , final int size ) {
169+ /**
170+ * Converts trits (bytes array)to a tryte string based on {@link #NUMBER_OF_TRITS_IN_A_TRYTE}.<br>
171+ * the inverse of {@link #trits(String, byte[], int)}.
172+ *
173+ * @param trits source trits array
174+ * @param offset starting position for trits
175+ * @param size amount of trits to convert
176+ * @return tryte string
177+ */
178+ public static String trytes (final byte [] trits , final int offset , final int size ) {
179+ final StringBuilder trytes = new StringBuilder ();
180+ for (int i = 0 ; i < (size + NUMBER_OF_TRITS_IN_A_TRYTE - 1 ) / NUMBER_OF_TRITS_IN_A_TRYTE ; i ++) {
181+ int j = trits [offset + i * 3 ] + trits [offset + i * 3 + 1 ] * 3 + trits [offset + i * 3 + 2 ] * 9 ;
182+ if (j < 0 ) {
183+ j += TRYTE_ALPHABET .length ();
184+ }
185+ trytes .append (TRYTE_ALPHABET .charAt (j ));
186+ }
187+ return trytes .toString ();
188+ }
189+
190+ /**
191+ * Converts trits (bytes array)to a tryte string.<br>
192+ * @see #trytes(byte[], int, int)
193+ *
194+ * @param trits source trits array
195+ * @return tryte string
196+ */
197+ public static String trytes (final byte [] trits ) {
198+ return trytes (trits , 0 , trits .length );
199+ }
200+
201+ /**
202+ * Creates a new trits array with the converted tryte string.<br>
203+ * should be used only for testing as it allocates memory.
204+ * @see #allocatingTritsFromTrytes(String)
205+ * @see #trits(String, byte[], int)
206+ *
207+ * @param trytes source trytes string
208+ * @return a new trit array
209+ */
210+ public static byte [] allocatingTritsFromTrytes (String trytes ) {
211+ byte [] trits = allocateTritsForTrytes (trytes .length ());
212+ trits (trytes , trits , 0 );
213+ return trits ;
214+ }
103215
216+
217+ // Long <-> Trits
218+
219+ /**
220+ * Parses the trits argument as a long value, based on <i>Balanced ternary</i> arithmetic
221+ * @param trits Array of trits to be parsed
222+ * @param srcPos Starting position in trits array
223+ * @param size Amount of trits to parse
224+ * @return the long value represented by the trits array
225+ */
226+ public static long longValue (final byte [] trits , final int srcPos , final int size ) {
227+
228+ long value = 0 ;
229+ for (int i = size ; i -- > 0 ; ) {
230+ value = value * RADIX + trits [srcPos + i ];
231+ }
232+ return value ;
233+ }
234+
235+ /**
236+ * fills a trit array with a representation of the {@code value} argument in <i>Balanced ternary</i> arithmetic
237+
238+ * @param value a long value
239+ * @param destination destination trit array
240+ * @param offset starting position of destination array
241+ * @param size max amount of trits to fill
242+ */
243+ public static void copyTrits (final long value , final byte [] destination , final int offset , final int size ) {
104244 long absoluteValue = value < 0 ? -value : value ;
105245 for (int i = 0 ; i < size ; i ++) {
106246
@@ -122,35 +262,31 @@ public static void copyTrits(final long value, final byte[] destination, final i
122262 }
123263
124264
125- public static String trytes ( final byte [] trits , final int offset , final int size ) {
265+ // Additional conversions
126266
127- final StringBuilder trytes = new StringBuilder ();
128- for (int i = 0 ; i < (size + NUMBER_OF_TRITS_IN_A_TRYTE - 1 ) / NUMBER_OF_TRITS_IN_A_TRYTE ; i ++) {
129- int j = trits [offset + i * 3 ] + trits [offset + i * 3 + 1 ] * 3 + trits [offset + i * 3 + 2 ] * 9 ;
130- if (j < 0 ) {
131- j += TRYTE_ALPHABET .length ();
267+ /**
268+ * Converts an {@code ASCII string} into a {@code TryteString} representation.
269+ * <p>
270+ * each ASCII character is converted to 2 Trytes.
271+ * </p>
272+ *
273+ * @param input ASCII string.
274+ * @return Trytes string
275+ */
276+ public static String asciiToTrytes (String input ) {
277+ StringBuilder sb = new StringBuilder (80 );
278+ for (int i = 0 ; i < input .length (); i ++) {
279+ int asciiValue = input .charAt (i );
280+ // If not recognizable ASCII character, return null
281+ if (asciiValue > 255 ) {
282+ return null ;
132283 }
133- trytes .append (TRYTE_ALPHABET .charAt (j ));
134- }
135- return trytes .toString ();
136- }
137-
138- public static String trytes (final byte [] trits ) {
139- return trytes (trits , 0 , trits .length );
140- }
141-
142- public static int tryteValue (final byte [] trits , final int offset ) {
143- return trits [offset ] + trits [offset + 1 ] * 3 + trits [offset + 2 ] * 9 ;
144- }
145-
146- public static Pair <byte [], byte []> intPair (byte [] trits ) {
147- byte [] low = new byte [trits .length ];
148- byte [] hi = new byte [trits .length ];
149- for (int i = 0 ; i < trits .length ; i ++) {
150- low [i ] = trits [i ] != (byte ) 1 ? HIGH_INTEGER_BITS : (byte ) 0 ;
151- hi [i ] = trits [i ] != (byte ) -1 ? HIGH_INTEGER_BITS : (byte ) 0 ;
284+ int firstValue = asciiValue % 27 ;
285+ int secondValue = (asciiValue - firstValue ) / 27 ;
286+ sb .append (TRYTE_ALPHABET .charAt (firstValue ));
287+ sb .append (TRYTE_ALPHABET .charAt (secondValue ));
152288 }
153- return new Pair <>( low , hi );
289+ return sb . toString ( );
154290 }
155291
156292 public static Pair <long [], long []> longPair (byte [] trits ) {
@@ -163,19 +299,6 @@ public static Pair<long[], long[]> longPair(byte[] trits) {
163299 return new Pair <>(low , hi );
164300 }
165301
166- public static void shiftPair (Pair <long [], long []> source , Pair <long [], long []> dest ) {
167- if (source .low .length == dest .low .length && source .hi .length == dest .hi .length ) {
168- for (int i = 0 ; i < dest .low .length ; i ++) {
169- dest .low [i ] <<= 1 ;
170- dest .low [i ] |= source .low [i ] & 1 ;
171- }
172- for (int i = 0 ; i < dest .hi .length ; i ++) {
173- dest .hi [i ] <<= 1 ;
174- dest .hi [i ] |= source .hi [i ] & 1 ;
175- }
176- }
177- }
178-
179302 public static byte [] trits (final Pair <long [], long []> pair , final int bitIndex ) {
180303 final int length ;
181304 if (pair .low .length == pair .hi .length || pair .low .length < pair .hi .length ) {
@@ -216,36 +339,4 @@ public static byte[] trits(byte[] low, byte[] hi) {
216339 }
217340 return trits ;
218341 }
219-
220- private static void increment (final byte [] trits , final int size ) {
221- for (int i = 0 ; i < size ; i ++) {
222- if (++trits [i ] > Converter .MAX_TRIT_VALUE ) {
223- trits [i ] = Converter .MIN_TRIT_VALUE ;
224- } else {
225- break ;
226- }
227- }
228- }
229-
230- public static String asciiToTrytes (String input ) {
231- StringBuilder sb = new StringBuilder (80 );
232- for (int i = 0 ; i < input .length (); i ++) {
233- int asciiValue = input .charAt (i );
234- // If not recognizable ASCII character, return null
235- if (asciiValue > 255 ) {
236- return null ;
237- }
238- int firstValue = asciiValue % 27 ;
239- int secondValue = (asciiValue - firstValue ) / 27 ;
240- sb .append (TRYTE_ALPHABET .charAt (firstValue ));
241- sb .append (TRYTE_ALPHABET .charAt (secondValue ));
242- }
243- return sb .toString ();
244- }
245-
246- public static byte [] allocatingTritsFromTrytes (String trytes ) {
247- byte [] trits = allocateTritsForTrytes (trytes .length ());
248- trits (trytes , trits , 0 );
249- return trits ;
250- }
251342}
0 commit comments