View Javadoc

1   /*
2    * $Id: DefaultFormChunk.java,v 1.1 2005/11/01 00:22:09 weiju Exp $
3    * 
4    * Created on 2005/09/23
5    * Copyright 2005 by Wei-ju Wu
6    *
7    * This file is part of The Z-machine Preservation Project (ZMPP).
8    *
9    * ZMPP is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as published by
11   * the Free Software Foundation; either version 2 of the License, or
12   * (at your option) any later version.
13   *
14   * ZMPP is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with ZMPP; if not, write to the Free Software
21   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22   */
23  package org.zmpp.iff;
24  
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  import org.zmpp.base.MemoryAccess;
31  import org.zmpp.base.MemorySection;
32  
33  /***
34   * This class implements the FormChunk interface.
35   * 
36   * @author Wei-ju Wu
37   * @version 1.0
38   */
39  public class DefaultFormChunk extends DefaultChunk implements FormChunk {
40  
41    /***
42     * The sub type id.
43     */
44    private byte[] subId;
45    
46    /***
47     * The list of sub chunks.
48     */
49    private List<Chunk> subChunks;
50    
51    /***
52     * Constructor.
53     * 
54     * @param memaccess a MemoryAccess object
55     */
56    public DefaultFormChunk(MemoryAccess memaccess) {
57  
58      super(memaccess);
59      initBaseInfo();
60      readSubChunks();
61    }
62    
63    /***
64     * Initialize the id field.
65     */
66    private void initBaseInfo() {
67      
68      // Determine the sub id
69      subId = new byte[CHUNK_ID_LENGTH];
70      int offset = CHUNK_HEADER_LENGTH;
71      for (int i = 0; i < 4; i++) {
72        
73        subId[i] = memaccess.readByte(i + offset);
74      }
75    }
76    
77    /***
78     * Read this form chunk's sub chunks.
79     */
80    private void readSubChunks() {
81      
82      subChunks = new ArrayList<Chunk>();
83      
84      // skip the identifying information
85      int length = getSize();
86      int offset = CHUNK_HEADER_LENGTH + CHUNK_ID_LENGTH;
87      int chunkTotalSize = 0;
88      
89      while (offset < length) {
90        MemoryAccess memarray = new MemorySection(memaccess, offset,
91                                                length - offset);
92        Chunk subchunk = new DefaultChunk(memarray);
93        subChunks.add(subchunk);
94        chunkTotalSize = subchunk.getSize() + CHUNK_HEADER_LENGTH;
95        
96        // Determine if padding is necessary
97        chunkTotalSize = (chunkTotalSize % 2) == 0 ? chunkTotalSize :
98                                                     chunkTotalSize + 1;
99        offset += chunkTotalSize;
100     }    
101   }
102   
103   /***
104    * {@inheritDoc}
105    */
106   public boolean isValid() {
107     
108     return (new String(getId())).equals("FORM");
109   }
110   
111   /***
112    * {@inheritDoc}
113    */
114   public byte[] getSubId() {
115     
116     return subId;
117   }
118 
119   /***
120    * {@inheritDoc}
121    */
122   public Iterator<Chunk> getSubChunks() {
123 
124     return subChunks.iterator();
125   }
126   
127   /***
128    * {@inheritDoc}
129    */
130   public Chunk getSubChunk(byte[] id) {
131 
132     for (Chunk chunk : subChunks) {
133       
134       if (Arrays.equals(id, chunk.getId())) {
135         
136         return chunk;
137       }
138     }
139     return null;
140   }
141 }