• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010 Google Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.typography.font.sfntly.testutils;
18 
19 import com.google.typography.font.sfntly.data.ReadableFontData;
20 
21 import com.ibm.icu.charset.CharsetICU;
22 
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.OutputStream;
28 import java.io.RandomAccessFile;
29 import java.io.UnsupportedEncodingException;
30 import java.nio.ByteBuffer;
31 import java.nio.CharBuffer;
32 import java.nio.channels.FileChannel;
33 import java.nio.charset.Charset;
34 import java.nio.charset.CharsetEncoder;
35 import java.nio.charset.CoderResult;
36 
37 /**
38  * @author Stuart Gill
39  */
40 public class TestUtils {
TestUtils()41   private TestUtils() {}
42 
43   /**
44    * Compare sections of two byte arrays for equality.
45    * @param b1 byte array 1
46    * @param offset1 offset for comparison in byte array 1
47    * @param b2 byte array 2
48    * @param offset2 offset for comparison in byte array 2
49    * @param length the length of the byte arrays to compare
50    * @return true if the array segments are equal; false otherwise
51    */
equals(byte[] b1, int offset1, byte[] b2, int offset2, int length)52   public static boolean equals(byte[] b1, int offset1, byte[] b2, int offset2, int length) {
53     for (int i = 0; i < length; i++) {
54       if (b1[i + offset1] != b2[i + offset2]) {
55         return false;
56       }
57     }
58     return true;
59   }
60 
createFileChannelForWriting(File file)61   public static FileChannel createFileChannelForWriting(File file) throws IOException {
62     createNewFile(file);
63 
64     RandomAccessFile raf = new RandomAccessFile(file, "rw");
65     return raf.getChannel();
66   }
67 
68   /**
69    * Creates a new file including deleting an already existing file with the same path
70    * and name and creating any needed directories.
71    *
72    * @param file the file to create
73    * @throws IOException
74    */
createNewFile(File file)75   public static void createNewFile(File file) throws IOException {
76     if (file.exists()) {
77       file.delete();
78     }
79     file.getParentFile().mkdirs();
80     file.createNewFile();
81   }
82 
createOutputStream(File file)83   public static OutputStream createOutputStream(File file) throws IOException {
84     createNewFile(file);
85     return new FileOutputStream(file);
86   }
87 
88   /**
89    * Converts an integer into a 4 character string using the ASCII encoding.
90    * @param i the value to convert
91    * @return the String based on the number
92    */
dumpLongAsString(int i)93   public static String dumpLongAsString(int i) {
94     byte[] b = new byte[] {
95         (byte) (i >> 24 & 0xff),
96         (byte) (i >> 16 & 0xff),
97         (byte) (i >> 8 & 0xff),
98         (byte) (i & 0xff)};
99 
100     String s;
101     try {
102       s = new String(b, "US-ASCII");
103     } catch (UnsupportedEncodingException e) {
104       throw new RuntimeException("Guaranteed encoding US-ASCII missing.");
105     }
106     return s;
107   }
108 
109   /**
110    * Calculate an OpenType checksum from the array.
111    * @param b the array to calculate checksum on
112    * @param offset the starting index in the array
113    * @param length the number of bytes to check; <b>must</b> be a multiple of 4
114    * @return checksum
115    */
checkSum(byte[] b, int offset, int length)116   public static long checkSum(byte[] b, int offset, int length) {
117     long checkSum = 0;
118 
119     for (int i = offset; i < length; i+=4) {
120       for (int j = 0; j < 4; j++) {
121         if (j + i < length) {
122           checkSum += (b[j+i] & 0xff) << (24 - 8*j);
123         }
124       }
125     }
126     return checkSum & 0xffffffffL;
127   }
128 
129   /**
130    * Encode a single character in UTF-16.
131    * @param encoder the encoder to use for the encoding
132    * @param uchar the Unicode character to encode
133    * @return the encoded character
134    */
encodeOneChar(CharsetEncoder encoder, int uchar)135   public static int encodeOneChar(CharsetEncoder encoder, int uchar) {
136     ByteBuffer bb = ByteBuffer.allocate(10);
137     CharBuffer cb = CharBuffer.wrap(new char[] {(char) uchar});
138     CoderResult result = encoder.encode(cb, bb, true);
139     if (result.isError()) {
140       return 0;
141     }
142     if (bb.position() > 4) {
143       return 0;
144     }
145     int encChar = 0;
146     for (int position = 0; position < bb.position(); position++) {
147       encChar <<= 8;
148       encChar |= (bb.get(position) & 0xff);
149     }
150     return encChar;
151   }
152 
153   /**
154    * Get an encoder for the charset name.
155    * If the name is null or the empty string then just return null.
156    * @param charsetName the charset to get an encoder for
157    * @return an encoder or null if no encoder available for charset name
158    */
getEncoder(String charsetName)159   public static CharsetEncoder getEncoder(String charsetName) {
160     if (charsetName == null || charsetName.equals("")) {
161       return null;
162     }
163     Charset cs = CharsetICU.forNameICU(charsetName);
164     return cs.newEncoder();
165   }
166 
167   private static final char EXTENSION_SEPARATOR = '.';
168 
extension(File file)169   public static String extension(File file) {
170     String ext = file.getName();
171     int extPosition = ext.lastIndexOf(EXTENSION_SEPARATOR);
172     if (extPosition == -1) {
173       return "";
174     }
175     return ext.substring(extPosition);
176   }
177 
178   /**
179    * Read a file fully into a new byte array.
180    * @param file the file to read
181    * @return the byte array
182    * @throws IOException
183    */
readFile(File file)184   public static byte[] readFile(File file) throws IOException {
185     int length = (int) file.length();
186     byte[] b = new byte[length];
187 
188     FileInputStream fis = null;
189     try {
190       fis = new FileInputStream(file);
191       while (length > 0) {
192         length -= fis.read(b, b.length - length, length);
193       }
194       return b;
195     } finally {
196       fis.close();
197     }
198   }
199 
200   /**
201    * @param offset1 offset to start comparing the first ReadableFontData from
202    * @param rfd1 the first ReadableFontData
203    * @param offset2 offset to start comparing the second ReadableFontData from
204    * @param rfd2 the second ReadableFontData
205    * @param length the number of bytes to compare
206    * @return true if all bytes in the ranges given are equal; false otherwise
207    */
equals( int offset1, ReadableFontData rfd1, int offset2, ReadableFontData rfd2, int length)208   public static boolean equals(
209       int offset1, ReadableFontData rfd1, int offset2, ReadableFontData rfd2, int length) {
210     for (int i = 0; i < length; i++) {
211       int b1 = rfd1.readByte(i + offset1);
212       int b2 = rfd2.readByte(i + offset2);
213       if (b1 != b2) {
214         return false;
215       }
216     }
217     return true;
218   }
219 
220   /**
221    * Checks that both objects are equal as defined by the object itself. If one
222    * is null then they are not equal. If both are null they are considered
223    * equal.
224    *
225    * @param o1 first object
226    * @param o2 second object
227    * @return true if equal
228    */
equalsNullOk(Object o1, Object o2)229   public static boolean equalsNullOk(Object o1, Object o2) {
230     if (o1 == o2) {
231       return true;
232     }
233     if (o1 == null || o2 == null) {
234       // both can't be null - caught above
235       return false;
236     }
237     return o1.equals(o2);
238   }
239 }
240