mirror of
https://github.com/ksherlock/profuse.git
synced 2025-02-27 16:29:52 +00:00
new branch to integrate BlockDevice, BlockCache
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@336 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
ea0d1c198b
commit
664dee7578
200
ProDOS/Bitmap.cpp
Normal file
200
ProDOS/Bitmap.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <ProDOS/Bitmap.h>
|
||||
#include <ProDOS/BlockDevice.h>
|
||||
#include "auto.h"
|
||||
|
||||
|
||||
using namespace ProDOS;
|
||||
|
||||
// returns # of 1-bits set (0-8)
|
||||
inline static unsigned popCount(uint8_t x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_popcount(x);
|
||||
#endif
|
||||
|
||||
// Brian Kernighan / Peter Wegner in CACM 3 (1960), 322.
|
||||
|
||||
unsigned count;
|
||||
for (count = 0; x; ++count)
|
||||
{
|
||||
x &= x - 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bitmap::Bitmap(unsigned blocks)
|
||||
{
|
||||
_blocks = _freeBlocks = blocks;
|
||||
|
||||
_bitmapBlocks = (blocks + 4095) / 4096;
|
||||
_freeIndex = 0;
|
||||
|
||||
unsigned bitmapSize = _bitmapBlocks * 512;
|
||||
unsigned blockSize = blocks / 8;
|
||||
|
||||
auto_array<uint8_t> bitmap(new uint8_t[bitmapSize]);
|
||||
|
||||
// mark overflow in use, everything else free.
|
||||
|
||||
std::memset(bitmap, 0xff, blocks / 8);
|
||||
std::memset(bitmap + blockSize, 0x00, bitmapSize - blockSize);
|
||||
|
||||
// edge case
|
||||
unsigned tmp = blocks & 0x07;
|
||||
|
||||
bitmap[blocks / 8] = ~(0xff >> tmp);
|
||||
|
||||
_bitmap = bitmap.release();
|
||||
|
||||
|
||||
}
|
||||
|
||||
Bitmap::Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks)
|
||||
{
|
||||
_blocks = blocks;
|
||||
_freeBlocks = 0;
|
||||
_freeIndex = 0;
|
||||
|
||||
_bitmapBlocks = (blocks + 4095) / 4096;
|
||||
|
||||
unsigned bitmapSize = _bitmapBlocks * 512;
|
||||
unsigned blockSize = blocks / 8;
|
||||
|
||||
auto_array<uint8_t> bitmap(new uint8_t[bitmapSize]);
|
||||
|
||||
for (unsigned i = 0; i < blockSize; ++i)
|
||||
{
|
||||
device->read(keyPointer + i, bitmap + 512 * i);
|
||||
}
|
||||
|
||||
// make sure all trailing bits are marked in use.
|
||||
|
||||
// edge case
|
||||
unsigned tmp = blocks & 0x07;
|
||||
|
||||
bitmap[blocks / 8] &= ~(0xff >> tmp);
|
||||
|
||||
std::memset(bitmap + blockSize, 0x00, bitmapSize - blockSize);
|
||||
|
||||
// set _freeBlocks and _freeIndex;
|
||||
for (unsigned i = 0; i < (blocks + 7) / 8; ++i)
|
||||
{
|
||||
_freeBlocks += popCount(bitmap[i]);
|
||||
}
|
||||
|
||||
if (_freeBlocks)
|
||||
{
|
||||
for (unsigned i = 0; i < (blocks + 7) / 8; ++i)
|
||||
{
|
||||
if (bitmap[i])
|
||||
{
|
||||
_freeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_bitmap = bitmap.release();
|
||||
}
|
||||
|
||||
Bitmap::~Bitmap()
|
||||
{
|
||||
if (_bitmap) delete []_bitmap;
|
||||
}
|
||||
|
||||
|
||||
void Bitmap::freeBlock(unsigned block)
|
||||
{
|
||||
if (block >= _blocks) return;
|
||||
|
||||
unsigned index = block / 8;
|
||||
unsigned offset = block & 0x07;
|
||||
unsigned mask = 0x80 >> offset;
|
||||
|
||||
uint8_t tmp = _bitmap[index];
|
||||
|
||||
if ((tmp & mask) == 0)
|
||||
{
|
||||
++_freeBlocks;
|
||||
_bitmap[index] = tmp | mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Bitmap::allocBlock(unsigned block)
|
||||
{
|
||||
if (block >= _blocks) return -1;
|
||||
|
||||
|
||||
unsigned index = block / 8;
|
||||
unsigned offset = block & 0x07;
|
||||
unsigned mask = 0x80 >> offset;
|
||||
|
||||
uint8_t tmp = _bitmap[index];
|
||||
|
||||
if ((tmp & mask))
|
||||
{
|
||||
--_freeBlocks;
|
||||
_bitmap[index] = tmp & ~mask;
|
||||
return block;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Bitmap::allocBlock()
|
||||
{
|
||||
if (!_freeBlocks) return -1;
|
||||
|
||||
unsigned freeIndex = _freeIndex;
|
||||
unsigned maxIndex = (_blocks + 7) / 8;
|
||||
|
||||
|
||||
for (unsigned index = _freeIndex; index < maxIndex; ++index)
|
||||
{
|
||||
uint8_t tmp = _bitmap[index];
|
||||
if (!tmp) continue;
|
||||
|
||||
unsigned mask = 0x80;
|
||||
for (unsigned offset = 0; offset < 8; ++offset)
|
||||
{
|
||||
if (tmp & mask)
|
||||
{
|
||||
_freeIndex = index;
|
||||
_bitmap[index] = tmp & ~mask;
|
||||
--_freeBlocks;
|
||||
return index * 8 + offset;
|
||||
}
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned index = 0; index < freeIndex; ++index)
|
||||
{
|
||||
uint8_t tmp = _bitmap[index];
|
||||
if (!tmp) continue;
|
||||
|
||||
unsigned mask = 0x80;
|
||||
for (unsigned offset = 0; offset < 8; ++offset)
|
||||
{
|
||||
if (tmp & mask)
|
||||
{
|
||||
_freeIndex = index;
|
||||
_bitmap[index] = tmp & ~mask;
|
||||
--_freeBlocks;
|
||||
return index * 8 + offset;
|
||||
}
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// should never happen...
|
||||
return -1;
|
||||
}
|
48
ProDOS/Bitmap.h
Normal file
48
ProDOS/Bitmap.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef __BITMAP_H__
|
||||
#define __BITMAP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
namespace ProDOS {
|
||||
|
||||
class BlockDevice;
|
||||
|
||||
|
||||
class Bitmap {
|
||||
public:
|
||||
|
||||
Bitmap(unsigned blocks);
|
||||
Bitmap(BlockDevice *device, unsigned keyPointer, unsigned blocks);
|
||||
//todo -- constructor by loading from, block device...
|
||||
~Bitmap();
|
||||
|
||||
int allocBlock();
|
||||
int allocBlock(unsigned block);
|
||||
|
||||
void freeBlock(unsigned block);
|
||||
|
||||
|
||||
unsigned freeBlocks() const { return _freeBlocks; }
|
||||
unsigned blocks() const { return _blocks; }
|
||||
unsigned bitmapBlocks() const { return _bitmapBlocks; }
|
||||
unsigned bitmapSize() const { return _bitmapBlocks * 512; }
|
||||
const void *bitmap() const { return _bitmap; }
|
||||
|
||||
private:
|
||||
|
||||
unsigned _freeIndex;
|
||||
unsigned _freeBlocks;
|
||||
|
||||
unsigned _blocks;
|
||||
unsigned _bitmapBlocks;
|
||||
|
||||
uint8_t *_bitmap;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
144
ProDOS/DateTime.cpp
Normal file
144
ProDOS/DateTime.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <cstring>
|
||||
|
||||
#include <ProDOS/DateTime.h>
|
||||
|
||||
using namespace ProDOS;
|
||||
|
||||
/*
|
||||
* date is a 16 bit value:
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||
* +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||
* | Year | Month | Day |
|
||||
* +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* time is a 16 bit value:
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||
* +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||
* |0 0 0| Hour | |0 0| Minute |
|
||||
* +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* ProDOS technote 28
|
||||
*
|
||||
* The following definition allows the same range of years that the Apple IIgs
|
||||
* Control Panel CDA currently does:
|
||||
*
|
||||
* o A seven-bit ProDOS year value is in the range 0 to 99
|
||||
* (100 through 127 are invalid)
|
||||
* o Year values from 40 to 99 represent 1940 through 1999
|
||||
* o Year values from 0 to 39 represent 2000 through 2039
|
||||
*/
|
||||
|
||||
|
||||
DateTime::DateTime() :
|
||||
_yymmdd(0), _hhmm(0)
|
||||
{
|
||||
init(std::time(NULL));
|
||||
}
|
||||
|
||||
DateTime::DateTime(uint32_t dtm) :
|
||||
_yymmdd((dtm >> 16) & 0xff), _hhmm(dtm & 0xff)
|
||||
{
|
||||
}
|
||||
|
||||
DateTime::DateTime(unsigned yymmdd, unsigned hhmm) :
|
||||
_yymmdd(yymmdd), _hhmm(hhmm)
|
||||
{
|
||||
}
|
||||
|
||||
DateTime::DateTime(std::time_t time) :
|
||||
_yymmdd(0), _hhmm(0)
|
||||
{
|
||||
init(time);
|
||||
}
|
||||
|
||||
|
||||
DateTime::DateTime(unsigned year, unsigned month, unsigned day,
|
||||
unsigned hour, unsigned minute) :
|
||||
_yymmdd(0), _hhmm(0)
|
||||
{
|
||||
init(year, month, day, hour, minute);
|
||||
}
|
||||
|
||||
void DateTime::init(std::time_t time)
|
||||
{
|
||||
tm t;
|
||||
::localtime_r(&time, &t);
|
||||
init(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min);
|
||||
}
|
||||
|
||||
void DateTime::init(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute)
|
||||
{
|
||||
|
||||
//printf("%d %d %d %d %d\n", year, month, day, hour, minute);
|
||||
|
||||
// 1940 is the earliest year, so clamp to 1940-01-01 00:00
|
||||
if (year < 1940)
|
||||
{
|
||||
_yymmdd = (40 << 9) | (1 << 5) | 1;
|
||||
_hhmm = 0;
|
||||
return;
|
||||
}
|
||||
// 2039 is the latest year, so clamp to 2039-12-31 23:59
|
||||
if (year > 2039)
|
||||
{
|
||||
_yymmdd = (39 << 9) | (12 << 5) | 31;
|
||||
_hhmm = (23 << 8) | 59;
|
||||
return;
|
||||
}
|
||||
|
||||
if (year >= 2000) year -= 2000;
|
||||
else year -= 1900;
|
||||
|
||||
_hhmm = minute | (hour << 8);
|
||||
|
||||
_yymmdd = day | (month << 5) | (year << 9);
|
||||
}
|
||||
|
||||
unsigned DateTime::year() const
|
||||
{
|
||||
unsigned tmp = _yymmdd >> 9;
|
||||
//if (tmp > 100) return 0;
|
||||
|
||||
if (tmp <= 39) tmp += 100;
|
||||
|
||||
return tmp + 1900;
|
||||
}
|
||||
|
||||
/*
|
||||
* A positive or 0 value for tm_isdst causes mktime() to presume initially
|
||||
* that Daylight Savings Time, respectively, is or is not in effect for
|
||||
* the specified time. A negative value for tm_isdst causes mktime() to
|
||||
* attempt to determine whether Daylight Saving Time is in effect for the
|
||||
* specified time.
|
||||
*/
|
||||
|
||||
std::time_t DateTime::toUnix() const
|
||||
{
|
||||
tm t;
|
||||
|
||||
if (_yymmdd == 0) return 0;
|
||||
|
||||
std::memset(&t, 0, sizeof(tm));
|
||||
|
||||
t.tm_min = minute();
|
||||
t.tm_hour = hour();
|
||||
t.tm_isdst = -1;
|
||||
|
||||
t.tm_mday = day();
|
||||
t.tm_mon = month() - 1;
|
||||
t.tm_year = year() - 1900;
|
||||
|
||||
return std::mktime(&t);
|
||||
// convert back via locatime & fudge for dst?
|
||||
}
|
||||
|
96
ProDOS/DateTime.h
Normal file
96
ProDOS/DateTime.h
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef __PRODOS_DATE_TIME__
|
||||
#define __PRODOS_DATE_TIME__
|
||||
|
||||
#include <ctime>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ProDOS {
|
||||
|
||||
class DateTime
|
||||
{
|
||||
public:
|
||||
DateTime();
|
||||
DateTime(std::time_t);
|
||||
DateTime(uint32_t);
|
||||
DateTime(unsigned, unsigned);
|
||||
|
||||
DateTime(unsigned year, unsigned month, unsigned day,
|
||||
unsigned hour, unsigned minute);
|
||||
|
||||
std::time_t toUnix() const;
|
||||
|
||||
|
||||
operator std::time_t() const;
|
||||
operator uint32_t() const;
|
||||
|
||||
unsigned date() const;
|
||||
unsigned time() const;
|
||||
|
||||
unsigned minute() const;
|
||||
unsigned hour() const;
|
||||
unsigned day() const;
|
||||
unsigned month() const;
|
||||
unsigned year() const;
|
||||
|
||||
private:
|
||||
void init(std::time_t);
|
||||
void init(unsigned, unsigned, unsigned, unsigned, unsigned);
|
||||
|
||||
unsigned _yymmdd;
|
||||
unsigned _hhmm;
|
||||
};
|
||||
|
||||
|
||||
inline DateTime::operator std::time_t() const
|
||||
{
|
||||
return toUnix();
|
||||
}
|
||||
|
||||
inline DateTime::operator uint32_t() const
|
||||
{
|
||||
return (_yymmdd << 16) | _hhmm;
|
||||
}
|
||||
|
||||
inline unsigned DateTime::date() const
|
||||
{
|
||||
return _yymmdd;
|
||||
}
|
||||
|
||||
inline unsigned DateTime::time() const
|
||||
{
|
||||
return _hhmm;
|
||||
}
|
||||
|
||||
inline unsigned DateTime::minute() const
|
||||
{
|
||||
return _hhmm & 0x3f;
|
||||
}
|
||||
|
||||
inline unsigned DateTime::hour() const
|
||||
{
|
||||
return (_hhmm >> 8) & 0x1f;
|
||||
}
|
||||
|
||||
inline unsigned DateTime::day() const
|
||||
{
|
||||
return _yymmdd & 0x1f;
|
||||
}
|
||||
|
||||
inline unsigned DateTime::month() const
|
||||
{
|
||||
return (_yymmdd >> 5) & 0x0f;
|
||||
}
|
||||
|
||||
/*
|
||||
inline unsigned DateTime::year() const
|
||||
{
|
||||
unsigned tmp = _yymmdd >> 9;
|
||||
if (tmp <= 39) tmp += 100;
|
||||
return tmp + 1900;
|
||||
}
|
||||
*/
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
7
ProDOS/Makefile
Normal file
7
ProDOS/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
CC = g++
|
||||
CPPFLAGS += -g -Wall -I../
|
||||
|
||||
|
||||
all : DateTime.o
|
||||
|
||||
DateTime.o : DateTime.cpp DateTime.h
|
Loading…
x
Reference in New Issue
Block a user