Implement Count1Types, Get1IndType, Get1IndResource, GetResInfo, DetachResource

This commit is contained in:
Iliyas Jorio 2021-07-18 13:16:43 +02:00
parent 630e8e9b24
commit 644ade79c3
4 changed files with 151 additions and 31 deletions

View File

@ -1,10 +1,12 @@
#include "Pomme.h"
#include "PommeFiles.h"
#include "Memory/BlockDescriptor.h"
#include "Utilities/bigendianstreams.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <cstring>
#include "CompilerSupport/filesystem.h"
#if _DEBUG
@ -295,6 +297,29 @@ short Count1Resources(ResType theType)
}
}
short Count1Types()
{
return (short) GetCurRF().resourceMap.size();
}
void Get1IndType(ResType* theType, short index)
{
const auto& resourceMap = GetCurRF().resourceMap;
for (auto& it : resourceMap)
{
if (index == 1) // remember, index is 1-based here
{
*theType = it.first;
return;
}
index--;
}
*theType = 0;
}
Handle GetResource(ResType theType, short theID)
{
lastResError = noErr;
@ -310,9 +335,16 @@ Handle GetResource(ResType theType, short theID)
if (resourcesOfType.end() == resourcesOfType.find(theID))
continue;
// Found it!
const auto& meta = fork.resourceMap.at(theType).at(theID);
auto& forkStream = Pomme::Files::GetStream(rezSearchStack[i].fileRefNum);
// Allocate handle
Handle handle = NewHandle(meta.size);
// Set pointer to resource metadata
Pomme::Memory::BlockDescriptor::HandleToBlock(handle)->rezMeta = &meta;
forkStream.seekg(meta.dataOffset, std::ios::beg);
forkStream.read(*handle, meta.size);
@ -323,6 +355,54 @@ Handle GetResource(ResType theType, short theID)
return nil;
}
Handle Get1IndResource(ResType theType, short index)
{
lastResError = noErr;
const auto& idsToResources = GetCurRF().resourceMap.at(theType);
for (auto& it : idsToResources)
{
if (index == 1) // remember, index is 1-based here
{
return GetResource(theType, it.second.id);
}
index--;
}
lastResError = resNotFound;
return nullptr;
}
void GetResInfo(Handle theResource, short* theID, ResType* theType, char* name256)
{
lastResError = noErr;
if (!theResource)
{
lastResError = resNotFound;
return;
}
auto blockDescriptor = Pomme::Memory::BlockDescriptor::HandleToBlock(theResource);
if (!blockDescriptor->rezMeta)
{
lastResError = resNotFound;
return;
}
if (theID)
*theID = blockDescriptor->rezMeta->id;
if (theType)
*theType = blockDescriptor->rezMeta->type;
if (name256)
snprintf(name256, 256, "%s", blockDescriptor->rezMeta->name.c_str());
}
void ReleaseResource(Handle theResource)
{
DisposeHandle(theResource);
@ -352,7 +432,13 @@ void WriteResource(Handle theResource)
void DetachResource(Handle theResource)
{
lastResError = noErr;
ONCE(TODOMINOR());
auto* blockDescriptor = Pomme::Memory::BlockDescriptor::HandleToBlock(theResource);
if (!blockDescriptor->rezMeta)
lastResError = resNotFound;
blockDescriptor->rezMeta = nullptr;
}
long GetResourceSizeOnDisk(Handle theResource)

View File

@ -0,0 +1,24 @@
#pragma once
namespace Pomme::Files
{
struct ResourceMetadata;
}
namespace Pomme::Memory
{
class BlockDescriptor
{
public:
Ptr buf;
OSType magic;
Size size;
const Pomme::Files::ResourceMetadata* rezMeta;
BlockDescriptor(Size theSize);
~BlockDescriptor();
static BlockDescriptor* HandleToBlock(Handle h);
};
}

View File

@ -3,31 +3,36 @@
#include <cstring>
#include "Pomme.h"
#include "Utilities/FixedPool.h"
#include "Memory/BlockDescriptor.h"
using namespace Pomme;
using namespace Pomme::Memory;
#define LOG POMME_GENLOG(POMME_DEBUG_MEMORY, "MEMO")
//-----------------------------------------------------------------------------
// Implementation-specific stuff
static const int HANDLE_MAGIC_LENGTH = 8;
static const char HANDLE_MAGIC[HANDLE_MAGIC_LENGTH] = "LIVEhdl";
static const char HANDLE_MAGIC_DEAD[HANDLE_MAGIC_LENGTH] = "DEADhdl";
struct BlockDescriptor
BlockDescriptor::BlockDescriptor(Size theSize)
{
Ptr buf;
char magic[HANDLE_MAGIC_LENGTH];
Size size;
};
buf = new char[theSize];
magic = 'LIVE';
size = theSize;
}
// these must not move around
static Pomme::FixedPool<BlockDescriptor, UInt16, 1000> blocks;
BlockDescriptor::~BlockDescriptor()
{
delete[] buf;
buf = nullptr;
size = 0;
rezMeta = nullptr;
magic = 'DEAD';
}
static BlockDescriptor* HandleToBlock(Handle h)
BlockDescriptor* BlockDescriptor::HandleToBlock(Handle h)
{
auto bd = (BlockDescriptor*) h;
if (0 != memcmp(bd->magic, HANDLE_MAGIC, HANDLE_MAGIC_LENGTH))
if (bd->magic != 'LIVE')
throw std::runtime_error("corrupted handle");
return bd;
}
@ -35,20 +40,16 @@ static BlockDescriptor* HandleToBlock(Handle h)
//-----------------------------------------------------------------------------
// Memory: Handle
Handle NewHandle(Size s)
Handle NewHandle(Size size)
{
if (s < 0) throw std::invalid_argument("trying to alloc negative size handle");
if (size < 0)
throw std::invalid_argument("trying to alloc negative size handle");
BlockDescriptor* block = blocks.Alloc();
block->buf = new char[s];
memcpy(block->magic, HANDLE_MAGIC, HANDLE_MAGIC_LENGTH);
block->size = s;
BlockDescriptor* block = new BlockDescriptor(size);
if ((Ptr) &block->buf != (Ptr) block)
throw std::runtime_error("buffer address mismatches block address");
LOG << (void*) block->buf << ", size " << s << "\n";
return &block->buf;
}
@ -78,7 +79,7 @@ Handle TempNewHandle(Size s, OSErr* err)
Size GetHandleSize(Handle h)
{
return HandleToBlock(h)->size;
return BlockDescriptor::HandleToBlock(h)->size;
}
void SetHandleSize(Handle handle, Size byteCount)
@ -88,13 +89,7 @@ void SetHandleSize(Handle handle, Size byteCount)
void DisposeHandle(Handle h)
{
LOG << (void*) *h << "\n";
BlockDescriptor* b = HandleToBlock(h);
delete[] b->buf;
b->buf = 0;
b->size = -1;
memcpy(b->magic, HANDLE_MAGIC_DEAD, HANDLE_MAGIC_LENGTH);
blocks.Dispose(b);
delete BlockDescriptor::HandleToBlock(h);
}
OSErr PtrToHand(const void* srcPtr, Handle* dstHndl, Size size)

View File

@ -97,8 +97,23 @@ void CloseResFile(short refNum);
// in the current resource file only.
short Count1Resources(ResType);
// Returns total number of resource types
// in the current resource file only.
short Count1Types(void);
// Gets resource type available in current resource file.
// Note that the index is 1-based!
void Get1IndType(ResType* theType, short index);
Handle GetResource(ResType theType, short theID);
// Reads a resource from the current resource file.
// `index` isn't the actual resource ID!
// `index` ranges from 1 to the number returned by Get1IndType().
Handle Get1IndResource(ResType theType, short index);
void GetResInfo(Handle theResource, short* theID, ResType* theType, char* name256);
void ReleaseResource(Handle theResource);
void RemoveResource(Handle theResource);