262 lines
7.8 KiB
C++
262 lines
7.8 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "nsTOC.h"
|
|
#include "plstr.h"
|
|
#include "memory.h"
|
|
#include "prlog.h"
|
|
|
|
static const PRUint32 kTOC_FLAT_FILE_VERSION = 1;
|
|
static const PRUint32 kTOC_MAGIC_NUMBER = 19712809;
|
|
static const PRUint32 kTOC_HEADER_SIZE = 2* sizeof(PRUint32);
|
|
|
|
//TODO change this to a memory mapped file!
|
|
nsTOC::nsTOC(const char* i_pFilename, nsFlatFile* i_pFlatFile):
|
|
m_pFilename( new char[PL_strlen(i_pFilename) + 1]),
|
|
m_pFD(0),
|
|
m_bIsValid(PR_FALSE),
|
|
m_pFlatFile(i_pFlatFile),
|
|
m_Entries(1)
|
|
{
|
|
PL_strcpy(m_pFilename, i_pFilename);
|
|
Init();
|
|
}
|
|
|
|
nsTOC::~nsTOC()
|
|
{
|
|
delete[] m_pFilename;
|
|
if (m_pFD)
|
|
{
|
|
PR_Close(m_pFD);
|
|
m_pFD = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
nsrefcnt nsTOC::AddRef(void)
|
|
{
|
|
return ++m_RefCnt;
|
|
}
|
|
nsrefcnt nsTOC::Release(void)
|
|
{
|
|
if (--m_RefCnt == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_RefCnt;
|
|
}
|
|
|
|
nsresult nsTOC::QueryInterface(const nsIID& aIID,
|
|
void** aInstancePtrResult)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
*/
|
|
|
|
void nsTOC::Init(void)
|
|
{
|
|
if (m_pFilename)
|
|
{
|
|
m_pFD = PR_Open(m_pFilename, PR_CREATE_FILE | PR_RDWR, 0600);
|
|
if (!m_pFD)
|
|
{
|
|
return;
|
|
}
|
|
PRFileInfo info;
|
|
// if the file is just being created then write magic number
|
|
// and flat file version, else verify
|
|
if (PR_SUCCESS == PR_GetOpenFileInfo(m_pFD, &info))
|
|
{
|
|
PRInt32 status;
|
|
if (info.size > 0)
|
|
{
|
|
char buf[kTOC_HEADER_SIZE];
|
|
//verify
|
|
status = PR_Read(m_pFD, &buf, kTOC_HEADER_SIZE);
|
|
if (status > 0)
|
|
{
|
|
char* cur_ptr = &buf[0];
|
|
PRUint32 test;
|
|
COPY_INT32(&test, cur_ptr);
|
|
if (test != kTOC_MAGIC_NUMBER)
|
|
{
|
|
PR_Close(m_pFD);
|
|
m_pFD = 0;
|
|
//PR_ASSERT(!"Bad TOC file!");
|
|
return;
|
|
}
|
|
cur_ptr += sizeof(PRUint32);
|
|
COPY_INT32(&test, cur_ptr);
|
|
if (test != kTOC_FLAT_FILE_VERSION)
|
|
{
|
|
PR_Close(m_pFD);
|
|
m_pFD = 0;
|
|
//PR_ASSERT(!"Bad version of TOC file!");
|
|
return;
|
|
}
|
|
|
|
// Number of entries in the TOC
|
|
status = PR_Read(m_pFD, &buf, sizeof(PRUint32));
|
|
if (status > 0)
|
|
{
|
|
cur_ptr = &buf[0];
|
|
COPY_INT32(&m_Entries, cur_ptr);
|
|
}
|
|
//Read in the list of entries
|
|
nsFFEntry* pCurrent;
|
|
Serialize(pCurrent, PR_TRUE);
|
|
//There has got to be a free entry.
|
|
PR_ASSERT(pCurrent /*&& pCurrent->IsValid() TODO*/);
|
|
m_pContents = pCurrent;
|
|
PRUint32 count = 1; //Definitely one!
|
|
Serialize(pCurrent, PR_TRUE);
|
|
while (pCurrent)
|
|
{
|
|
count++;
|
|
m_pContents->AddEntry(pCurrent);
|
|
Serialize(pCurrent, PR_TRUE);
|
|
}
|
|
|
|
PR_ASSERT(count == m_Entries);
|
|
|
|
//Everything was as expected so
|
|
m_bIsValid = PR_TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//write out
|
|
char* buf = new char[kTOC_HEADER_SIZE];
|
|
char* cur_ptr = buf;
|
|
COPY_INT32((void*) cur_ptr, &kTOC_MAGIC_NUMBER);
|
|
cur_ptr += sizeof(PRUint32);
|
|
COPY_INT32((void*) cur_ptr, &kTOC_FLAT_FILE_VERSION);
|
|
status = PR_Write(m_pFD, buf, kTOC_HEADER_SIZE);
|
|
|
|
// Number of entries in the TOC
|
|
COPY_INT32((void*)buf, &m_Entries);
|
|
status = PR_Write(m_pFD, buf, sizeof(PRUint32));
|
|
|
|
delete[] buf;
|
|
|
|
//Since the TOC is being created afresh, reset the flat file with everything marked as
|
|
//free.
|
|
m_pContents = new nsFFEntry(
|
|
0,
|
|
m_pFlatFile->HeaderSize(),
|
|
m_pFlatFile->Size()-m_pFlatFile->HeaderSize());
|
|
//Serialize the only entry-
|
|
Serialize(m_pContents);
|
|
|
|
m_bIsValid = PR_TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
nsFFEntry* nsTOC::AddEntry(PRUint32 i_Size)
|
|
{
|
|
if (i_Size > FreeEntry()->Size())
|
|
{
|
|
//Garbage collect
|
|
}
|
|
nsFFEntry* pEntry = new nsFFEntry(
|
|
NextID(),
|
|
FreeEntry()->FirstObject()->Offset(),
|
|
i_Size);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
PRBool nsTOC::Serialize(nsFFEntry* io_Entry, PRBool bRead )
|
|
{
|
|
PR_ASSERT(m_pFD);
|
|
if (bRead)
|
|
{
|
|
io_Entry = new nsFFEntry();
|
|
if (!io_Entry)
|
|
return PR_FALSE;
|
|
char* buf = new char[sizeof(PRUint32)];
|
|
PRUint32 temp, objects, size;
|
|
//Read ID
|
|
PR_Read(m_pFD, buf, sizeof(PRUint32));
|
|
COPY_INT32(&temp, buf);
|
|
io_Entry->ID(temp);
|
|
//Read number of objects
|
|
PR_Read(m_pFD, buf, sizeof(PRUint32));
|
|
COPY_INT32(&objects, buf);
|
|
//Read objects
|
|
for (int i= objects; i>0; --i)
|
|
{
|
|
PR_Read(m_pFD, buf, sizeof(PRUint32));
|
|
COPY_INT32(&temp, buf);
|
|
PR_Read(m_pFD, buf, sizeof(PRUint32));
|
|
COPY_INT32(&size, buf);
|
|
io_Entry->AddObject(new nsFFObject(io_Entry->ID(), temp, size));
|
|
}
|
|
delete[] buf;
|
|
PR_ASSERT(io_Entry->Objects() == objects);
|
|
if (io_Entry->Objects() != objects)
|
|
return PR_FALSE;
|
|
return PR_TRUE;
|
|
}
|
|
else
|
|
{
|
|
PR_ASSERT(io_Entry);
|
|
if (!io_Entry)
|
|
return PR_FALSE;
|
|
|
|
//TODO speed this up by increasing the buffer size to write out
|
|
//more than one int at a time!
|
|
|
|
char* buf = new char[sizeof(PRUint32)];
|
|
PRUint32 temp;
|
|
//Write ID
|
|
temp = io_Entry->ID();
|
|
COPY_INT32((void*) buf, &temp);
|
|
PR_Write(m_pFD, buf, sizeof(PRUint32));
|
|
//Write number of Objects
|
|
temp = io_Entry->Objects();
|
|
COPY_INT32((void*) buf, &temp);
|
|
PR_Write(m_pFD, buf, sizeof(PRUint32));
|
|
//Write Objects
|
|
if (temp > 0)
|
|
{
|
|
nsFFObject* current = io_Entry->FirstObject();
|
|
while (current)
|
|
{
|
|
PR_ASSERT(current->ID() == io_Entry->ID());
|
|
//Offset
|
|
temp = current->Offset();
|
|
COPY_INT32((void*) buf, &temp);
|
|
PR_Write(m_pFD, buf, sizeof(PRUint32));
|
|
//size
|
|
temp = current->Size();
|
|
COPY_INT32((void*) buf, &temp);
|
|
PR_Write(m_pFD, buf, sizeof(PRUint32));
|
|
|
|
current = current->Next();
|
|
}
|
|
}
|
|
delete[] buf;
|
|
return PR_TRUE;
|
|
}
|
|
return PR_FALSE;
|
|
} |