1 /* 2 * Copyright (c) 2009-2012 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.scene.plugins.blender.file; 33 34 import com.jme3.scene.plugins.blender.BlenderContext; 35 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 36 import java.util.ArrayList; 37 import java.util.List; 38 39 /** 40 * A class that represents a pointer of any level that can be stored in the file. 41 * @author Marcin Roguski 42 */ 43 public class Pointer { 44 45 /** The blender context. */ 46 private BlenderContext blenderContext; 47 /** The level of the pointer. */ 48 private int pointerLevel; 49 /** The address in file it points to. */ 50 private long oldMemoryAddress; 51 /** This variable indicates if the field is a function pointer. */ 52 public boolean function; 53 54 /** 55 * Constructr. Stores the basic data about the pointer. 56 * @param pointerLevel 57 * the level of the pointer 58 * @param function 59 * this variable indicates if the field is a function pointer 60 * @param blenderContext 61 * the repository f data; used in fetching the value that the pointer points 62 */ 63 public Pointer(int pointerLevel, boolean function, BlenderContext blenderContext) { 64 this.pointerLevel = pointerLevel; 65 this.function = function; 66 this.blenderContext = blenderContext; 67 } 68 69 /** 70 * This method fills the pointer with its address value (it doesn't get the actual data yet. Use the 'fetch' method 71 * for this. 72 * @param inputStream 73 * the stream we read the pointer value from 74 */ 75 public void fill(BlenderInputStream inputStream) { 76 oldMemoryAddress = inputStream.readPointer(); 77 } 78 79 /** 80 * This method fetches the data stored under the given address. 81 * @param inputStream 82 * the stream we read data from 83 * @return the data read from the file 84 * @throws BlenderFileException 85 * this exception is thrown when the blend file structure is somehow invalid or corrupted 86 */ 87 public List<Structure> fetchData(BlenderInputStream inputStream) throws BlenderFileException { 88 if (oldMemoryAddress == 0) { 89 throw new NullPointerException("The pointer points to nothing!"); 90 } 91 List<Structure> structures = null; 92 FileBlockHeader dataFileBlock = blenderContext.getFileBlock(oldMemoryAddress); 93 if (pointerLevel > 1) { 94 int pointersAmount = dataFileBlock.getSize() / inputStream.getPointerSize() * dataFileBlock.getCount(); 95 for (int i = 0; i < pointersAmount; ++i) { 96 inputStream.setPosition(dataFileBlock.getBlockPosition() + inputStream.getPointerSize() * i); 97 long oldMemoryAddress = inputStream.readPointer(); 98 if (oldMemoryAddress != 0L) { 99 Pointer p = new Pointer(pointerLevel - 1, this.function, blenderContext); 100 p.oldMemoryAddress = oldMemoryAddress; 101 if (structures == null) { 102 structures = p.fetchData(inputStream); 103 } else { 104 structures.addAll(p.fetchData(inputStream)); 105 } 106 } 107 } 108 } else { 109 inputStream.setPosition(dataFileBlock.getBlockPosition()); 110 structures = new ArrayList<Structure>(dataFileBlock.getCount()); 111 for (int i = 0; i < dataFileBlock.getCount(); ++i) { 112 Structure structure = blenderContext.getDnaBlockData().getStructure(dataFileBlock.getSdnaIndex()); 113 structure.fill(inputStream); 114 structures.add(structure); 115 } 116 return structures; 117 } 118 return structures; 119 } 120 121 /** 122 * This method indicates if this pointer points to a function. 123 * @return <b>true</b> if this is a function pointer and <b>false</b> otherwise 124 */ 125 public boolean isFunction() { 126 return function; 127 } 128 129 /** 130 * This method indicates if this is a null-pointer or not. 131 * @return <b>true</b> if the pointer is null and <b>false</b> otherwise 132 */ 133 public boolean isNull() { 134 return oldMemoryAddress == 0; 135 } 136 137 /** 138 * This method indicates if this is a null-pointer or not. 139 * @return <b>true</b> if the pointer is not null and <b>false</b> otherwise 140 */ 141 public boolean isNotNull() { 142 return oldMemoryAddress != 0; 143 } 144 145 /** 146 * This method returns the old memory address of the structure pointed by the pointer. 147 * @return the old memory address of the structure pointed by the pointer 148 */ 149 public long getOldMemoryAddress() { 150 return oldMemoryAddress; 151 } 152 153 @Override 154 public String toString() { 155 return oldMemoryAddress == 0 ? "{$null$}" : "{$" + oldMemoryAddress + "$}"; 156 } 157 158 @Override 159 public int hashCode() { 160 return 31 + (int) (oldMemoryAddress ^ oldMemoryAddress >>> 32); 161 } 162 163 @Override 164 public boolean equals(Object obj) { 165 if (this == obj) { 166 return true; 167 } 168 if (obj == null) { 169 return false; 170 } 171 if (this.getClass() != obj.getClass()) { 172 return false; 173 } 174 Pointer other = (Pointer) obj; 175 if (oldMemoryAddress != other.oldMemoryAddress) { 176 return false; 177 } 178 return true; 179 } 180 } 181