00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cstring>
00022 #include <iostream>
00023 #include <boost/shared_ptr.hpp>
00024
00025 #include <libopenraw/types.h>
00026
00027 #include "io/file.h"
00028 #include "ciffcontainer.h"
00029 #include "debug.h"
00030
00031 using namespace Debug;
00032
00033 namespace OpenRaw {
00034 namespace Internals {
00035
00036 namespace CIFF {
00037
00038
00039 RecordEntry::RecordEntry()
00040 : typeCode(0), length(0), offset(0)
00041 {
00042 }
00043
00044 bool RecordEntry::readFrom(CIFFContainer *container)
00045 {
00046 bool ret;
00047 IO::Stream *file = container->file();
00048 ret = container->readUInt16(file, typeCode);
00049 ret = container->readUInt32(file, length);
00050 ret = container->readUInt32(file, offset);
00051 return ret;
00052 }
00053
00054 size_t RecordEntry::fetchData(Heap* heap, void* buf, size_t size)
00055 {
00056 return heap->container()->fetchData(buf,
00057 offset + heap->offset(), size);
00058 }
00059
00060
00061 Heap::Heap(off_t start, off_t length, CIFFContainer * container)
00062 : m_start(start),
00063 m_length(length),
00064 m_container(container),
00065 m_records()
00066 {
00067 }
00068
00069 std::vector<RecordEntry> & Heap::records()
00070 {
00071 if (m_records.size() == 0) {
00072 _loadRecords();
00073 }
00074 return m_records;
00075 }
00076
00077
00078 bool Heap::_loadRecords()
00079 {
00080 IO::Stream *file = m_container->file();
00081 file->seek(m_start + m_length - 4, SEEK_SET);
00082 int32_t offset;
00083 bool ret = m_container->readInt32(file, offset);
00084
00085 if (ret) {
00086 int16_t numRecords;
00087
00088 m_records.clear();
00089 file->seek(m_start + offset, SEEK_SET);
00090 ret = m_container->readInt16(file, numRecords);
00091 if (!ret)
00092 {
00093 Trace(DEBUG1) << "read failed: " << ret << "\n";
00094 }
00095 Trace(DEBUG2) << "numRecords " << numRecords << "\n";
00096 int16_t i;
00097 for (i = 0; i < numRecords; i++) {
00098 m_records.push_back(RecordEntry());
00099 m_records.back().readFrom(m_container);
00100 }
00101 }
00102 return ret;
00103 }
00104
00105
00106 #if 0
00107 class OffsetTable {
00108 uint16_t numRecords;
00109 RecordEntry tblArray[1];
00110 };
00111 #endif
00112
00113
00114 bool HeapFileHeader::readFrom(CIFFContainer *container)
00115 {
00116 endian = RawContainer::ENDIAN_NULL;
00117 bool ret = false;
00118 IO::Stream *file = container->file();
00119 int s = file->read(byteOrder, 2);
00120 if (s == 2) {
00121 if((byteOrder[0] == 'I') && (byteOrder[1] == 'I')) {
00122 endian = RawContainer::ENDIAN_LITTLE;
00123 }
00124 else if((byteOrder[0] == 'M') && (byteOrder[1] == 'M')) {
00125 endian = RawContainer::ENDIAN_BIG;
00126 }
00127 container->setEndian(endian);
00128 ret = container->readUInt32(file, headerLength);
00129 if (ret) {
00130 ret = (file->read(type, 4) == 4);
00131 }
00132 if (ret) {
00133 ret = (file->read(subType, 4) == 4);
00134 }
00135 if (ret) {
00136 ret = container->readUInt32(file, version);
00137 }
00138 }
00139 return ret;
00140 }
00141 }
00142
00143 CIFFContainer::CIFFContainer(IO::Stream *file)
00144 : RawContainer(file, 0),
00145 m_hdr(),
00146 m_heap((CIFF::Heap*)NULL)
00147 {
00148 m_endian = _readHeader();
00149 }
00150
00151 CIFFContainer::~CIFFContainer()
00152 {
00153 }
00154
00155 CIFF::Heap::Ref CIFFContainer::heap()
00156 {
00157 if (m_heap == NULL) {
00158 _loadHeap();
00159 }
00160 return m_heap;
00161 }
00162
00163 bool CIFFContainer::_loadHeap()
00164 {
00165 bool ret = false;
00166 if (m_heap == NULL) {
00167 if(m_endian != ENDIAN_NULL) {
00168 off_t heapLength = m_file->filesize() - m_hdr.headerLength;
00169
00170 Trace(DEBUG1) << "heap len " << heapLength << "\n";
00171 m_heap = CIFF::Heap::Ref(new CIFF::Heap(m_hdr.headerLength,
00172 heapLength, this));
00173
00174 ret = true;
00175 }
00176 else {
00177 Trace(DEBUG1) << "Unknown endian\n";
00178 }
00179 }
00180 return ret;
00181 }
00182
00183
00184 RawContainer::EndianType CIFFContainer::_readHeader()
00185 {
00186 EndianType endian = ENDIAN_NULL;
00187 m_hdr.readFrom(this);
00188 if ((::strncmp(m_hdr.type, "HEAP", 4) == 0)
00189 && (::strncmp(m_hdr.subType, "CCDR", 4) == 0)) {
00190 endian = m_hdr.endian;
00191 }
00192 return endian;
00193 }
00194
00195 }
00196 }