1    /* ====================================================================
2     * The Apache Software License, Version 1.1
3     *
4     * Copyright (c) 2002 The Apache Software Foundation.  All rights
5     * reserved.
6     *
7     * Redistribution and use in source and binary forms, with or without
8     * modification, are permitted provided that the following conditions
9     * are met:
10    *
11    * 1. Redistributions of source code must retain the above copyright
12    *    notice, this list of conditions and the following disclaimer.
13    *
14    * 2. Redistributions in binary form must reproduce the above copyright
15    *    notice, this list of conditions and the following disclaimer in
16    *    the documentation and/or other materials provided with the
17    *    distribution.
18    *
19    * 3. The end-user documentation included with the redistribution,
20    *    if any, must include the following acknowledgment:
21    *       "This product includes software developed by the
22    *        Apache Software Foundation (http://www.apache.org/)."
23    *    Alternately, this acknowledgment may appear in the software itself,
24    *    if and wherever such third-party acknowledgments normally appear.
25    *
26    * 4. The names "Apache" and "Apache Software Foundation" and
27    *    "Apache POI" must not be used to endorse or promote products
28    *    derived from this software without prior written permission. For
29    *    written permission, please contact apache@apache.org.
30    *
31    * 5. Products derived from this software may not be called "Apache",
32    *    "Apache POI", nor may "Apache" appear in their name, without
33    *    prior written permission of the Apache Software Foundation.
34    *
35    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46    * SUCH DAMAGE.
47    * ====================================================================
48    *
49    * This software consists of voluntary contributions made by many
50    * individuals on behalf of the Apache Software Foundation.  For more
51    * information on the Apache Software Foundation, please see
52    * <http://www.apache.org/>.
53    */
54   
55   package org.apache.poi.util;
56   
57   import java.io.IOException;
58   import java.io.File;
59   import java.io.FileInputStream;
60   import java.io.InputStream;
61   import java.util.List;
62   import java.util.ArrayList;
63   
64   /**
65    * Utilities to read hex from files.
66    *
67    * @author Marc Johnson
68    * @author Glen Stampoultzis (glens at apache.org)
69    */
70   public class HexRead
71   {
72       /**
73        * This method reads hex data from a filename and returns a byte array.
74        * The file may contain line comments that are preceeded with a # symbol.
75        *
76        * @param filename  The filename to read
77        * @return The bytes read from the file.
78        * @throws IOException If there was a problem while reading the file.
79        */
80       public static byte[] readData( String filename )
81               throws IOException
82       {
83           File file = new File( filename );
84           FileInputStream stream = new FileInputStream( file );
85           try
86           {
87               return readData(stream, -1);
88           }
89           finally
90           {
91               stream.close();
92           }
93       }
94   
95       /**
96        * Same as readData(String) except that this method allows you to specify sections within
97        * a file.  Sections are referenced using section headers in the form:
98        * <pre>
99        *  [sectioname]
100       * </pre>
101       *
102       * @see #readData(String)
103       */
104      public static byte[] readData(String filename, String section)
105          throws IOException
106      {
107          File file = new File( filename );
108          FileInputStream stream = new FileInputStream( file );
109          try
110          {
111              StringBuffer sectionText = new StringBuffer();
112              boolean inSection = false;
113              int c = stream.read();
114              while (c != -1)
115              {
116                  switch(c)
117                  {
118                      case '[':
119                          inSection = true;
120                          break;
121                      case '\n': case '\r':
122                          inSection = false;
123                          sectionText = new StringBuffer();
124                          break;
125                      case ']':
126                          inSection = false;
127                          if (sectionText.toString().equals(section))
128                              return readData(stream, '[');
129                          sectionText = new StringBuffer();
130                          break;
131                      default:
132                          if (inSection)
133                              sectionText.append((char)c);
134                  }
135  
136                  c = stream.read();
137              }
138          }
139          finally
140          {
141              stream.close();
142          }
143          throw new IOException("Section '" + section + "' not found");
144      }
145  
146      static private byte[] readData( FileInputStream stream, int eofChar ) throws IOException
147      {
148          int characterCount = 0;
149          byte b = (byte) 0;
150          List bytes = new ArrayList();
151          boolean done = false;
152  
153          while ( !done )
154          {
155              int count = stream.read();
156              char baseChar = 'a';
157  
158              if ( count == eofChar)
159                  break;
160  
161              switch ( count )
162              {
163  
164                  case '#':
165                      readToEOL(stream);
166                      break;
167                  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
168                      b <<= 4;
169                      b += (byte) ( count - '0' );
170                      characterCount++;
171                      if ( characterCount == 2 )
172                      {
173                          bytes.add( new Byte( b ) );
174                          characterCount = 0;
175                          b = (byte) 0;
176                      }
177                      break;
178  
179                  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
180                      baseChar = 'A';
181  
182                  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
183                      b <<= 4;
184                      b += (byte) ( count + 10 - baseChar );
185                      characterCount++;
186                      if ( characterCount == 2 )
187                      {
188                          bytes.add( new Byte( b ) );
189                          characterCount = 0;
190                          b = (byte) 0;
191                      }
192                      break;
193  
194                  case -1:
195                      done = true;
196                      break;
197  
198                  default :
199                      break;
200              }
201          }
202          Byte[] polished = (Byte[]) bytes.toArray( new Byte[0] );
203          byte[] rval = new byte[polished.length];
204  
205          for ( int j = 0; j < polished.length; j++ )
206          {
207              rval[j] = polished[j].byteValue();
208          }
209          return rval;
210      }
211  
212      static private void readToEOL( InputStream stream ) throws IOException
213      {
214          int c = stream.read();
215          while ( c != -1 && c != '\n' && c != '\r')
216          {
217              c = stream.read();
218          }
219      }
220  
221  
222  }
223