Copied userlandfs code from the test tree to the haiku source tree,

where it will be ported to Haiku.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20216 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2007-02-24 00:30:19 +00:00
parent d5e020e912
commit 83812f6752
96 changed files with 25005 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
/*
Copyright 1999-2001, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#ifndef _CACHE_H_
#define _CACHE_H_
#include <BeBuild.h>
#include "lock.h"
#ifndef _IMPEXP_KERNEL
#define _IMPEXP_KERNEL
#endif
typedef struct hash_ent {
int dev;
off_t bnum;
off_t hash_val;
void *data;
struct hash_ent *next;
} hash_ent;
typedef struct hash_table {
hash_ent **table;
int max;
int mask; /* == max - 1 */
int num_elements;
} hash_table;
#define HT_DEFAULT_MAX 128
typedef struct cache_ent {
int dev;
off_t block_num;
int bsize;
volatile int flags;
void *data;
void *clone; /* copy of data by set_block_info() */
int lock;
void (*func)(off_t bnum, size_t num_blocks, void *arg);
off_t logged_bnum;
void *arg;
struct cache_ent *next, /* points toward mru end of list */
*prev; /* points toward lru end of list */
} cache_ent;
#define CE_NORMAL 0x0000 /* a nice clean pristine page */
#define CE_DIRTY 0x0002 /* needs to be written to disk */
#define CE_BUSY 0x0004 /* this block has i/o happening, don't touch it */
typedef struct cache_ent_list {
cache_ent *lru; /* tail of the list */
cache_ent *mru; /* head of the list */
} cache_ent_list;
typedef struct block_cache {
struct lock lock;
int flags;
int cur_blocks;
int max_blocks;
hash_table ht;
cache_ent_list normal, /* list of "normal" blocks (clean & dirty) */
locked; /* list of clean and locked blocks */
} block_cache;
#if 0 /* XXXdbg -- need to deal with write through caches */
#define DC_WRITE_THROUGH 0x0001 /* cache is write-through (for floppies) */
#endif
#define ALLOW_WRITES 1
#define NO_WRITES 0
#ifdef __cplusplus
extern "C" {
#endif
extern _IMPEXP_KERNEL int init_block_cache(int max_blocks, int flags);
extern _IMPEXP_KERNEL void shutdown_block_cache(void);
extern _IMPEXP_KERNEL void force_cache_flush(int dev, int prefer_log_blocks);
extern _IMPEXP_KERNEL int flush_blocks(int dev, off_t bnum, int nblocks);
extern _IMPEXP_KERNEL int flush_device(int dev, int warn_locked);
extern _IMPEXP_KERNEL int init_cache_for_device(int fd, off_t max_blocks);
extern _IMPEXP_KERNEL int remove_cached_device_blocks(int dev, int allow_write);
extern _IMPEXP_KERNEL void *get_block(int dev, off_t bnum, int bsize);
extern _IMPEXP_KERNEL void *get_empty_block(int dev, off_t bnum, int bsize);
extern _IMPEXP_KERNEL int release_block(int dev, off_t bnum);
extern _IMPEXP_KERNEL int mark_blocks_dirty(int dev, off_t bnum, int nblocks);
extern _IMPEXP_KERNEL int cached_read(int dev, off_t bnum, void *data, off_t num_blocks, int bsize);
extern _IMPEXP_KERNEL int cached_write(int dev, off_t bnum, const void *data,
off_t num_blocks, int bsize);
extern _IMPEXP_KERNEL int cached_write_locked(int dev, off_t bnum, const void *data,
off_t num_blocks, int bsize);
extern _IMPEXP_KERNEL int set_blocks_info(int dev, off_t *blocks, int nblocks,
void (*func)(off_t bnum, size_t nblocks, void *arg),
void *arg);
extern _IMPEXP_KERNEL size_t read_phys_blocks (int fd, off_t bnum, void *data, uint num_blocks, int bsize);
extern _IMPEXP_KERNEL size_t write_phys_blocks(int fd, off_t bnum, void *data, uint num_blocks, int bsize);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* _CACHE_H_ */
+258
View File
@@ -0,0 +1,258 @@
#ifndef _FSPROTO_H
#define _FSPROTO_H
#include <sys/dirent.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iovec.h>
#include <OS.h>
#include <fs_attr.h>
#include <fs_info.h>
#include <BeBuild.h>
#include <Drivers.h>
#ifndef _IMPEXP_KERNEL
#define _IMPEXP_KERNEL
#endif
typedef dev_t nspace_id;
typedef ino_t vnode_id;
/*
* PUBLIC PART OF THE FILE SYSTEM PROTOCOL
*/
#define WSTAT_MODE 0x0001
#define WSTAT_UID 0x0002
#define WSTAT_GID 0x0004
#define WSTAT_SIZE 0x0008
#define WSTAT_ATIME 0x0010
#define WSTAT_MTIME 0x0020
#define WSTAT_CRTIME 0x0040
#define WFSSTAT_NAME 0x0001
#define B_ENTRY_CREATED 1
#define B_ENTRY_REMOVED 2
#define B_ENTRY_MOVED 3
#define B_STAT_CHANGED 4
#define B_ATTR_CHANGED 5
#define B_DEVICE_MOUNTED 6
#define B_DEVICE_UNMOUNTED 7
#define B_STOP_WATCHING 0x0000
#define B_WATCH_NAME 0x0001
#define B_WATCH_STAT 0x0002
#define B_WATCH_ATTR 0x0004
#define B_WATCH_DIRECTORY 0x0008
#define SELECT_READ 1
#define SELECT_WRITE 2
#define SELECT_EXCEPTION 3
// missing ioctl() call added
#define IOCTL_FILE_UNCACHED_IO 10000
#define IOCTL_CREATE_TIME 10002
#define IOCTL_MODIFIED_TIME 10003
#define B_CUR_FS_API_VERSION 2
struct attr_info;
struct index_info;
typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node);
typedef int op_write_vnode(void *ns, void *node, char r);
typedef int op_remove_vnode(void *ns, void *node, char r);
typedef int op_secure_vnode(void *ns, void *node);
typedef int op_walk(void *ns, void *base, const char *file, char **newpath,
vnode_id *vnid);
typedef int op_access(void *ns, void *node, int mode);
typedef int op_create(void *ns, void *dir, const char *name,
int omode, int perms, vnode_id *vnid, void **cookie);
typedef int op_mkdir(void *ns, void *dir, const char *name, int perms);
typedef int op_symlink(void *ns, void *dir, const char *name,
const char *path);
typedef int op_link(void *ns, void *dir, const char *name, void *node);
typedef int op_rename(void *ns, void *olddir, const char *oldname,
void *newdir, const char *newname);
typedef int op_unlink(void *ns, void *dir, const char *name);
typedef int op_rmdir(void *ns, void *dir, const char *name);
typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize);
typedef int op_opendir(void *ns, void *node, void **cookie);
typedef int op_closedir(void *ns, void *node, void *cookie);
typedef int op_rewinddir(void *ns, void *node, void *cookie);
typedef int op_readdir(void *ns, void *node, void *cookie, long *num,
struct dirent *buf, size_t bufsize);
typedef int op_open(void *ns, void *node, int omode, void **cookie);
typedef int op_close(void *ns, void *node, void *cookie);
typedef int op_free_cookie(void *ns, void *node, void *cookie);
typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf,
size_t *len);
typedef int op_write(void *ns, void *node, void *cookie, off_t pos,
const void *buf, size_t *len);
typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec,
size_t count, size_t *len);
typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec,
size_t count, size_t *len);
typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf,
size_t len);
typedef int op_setflags(void *ns, void *node, void *cookie, int flags);
typedef int op_rstat(void *ns, void *node, struct stat *);
typedef int op_wstat(void *ns, void *node, struct stat *, long mask);
typedef int op_fsync(void *ns, void *node);
typedef int op_select(void *ns, void *node, void *cookie, uint8 event,
uint32 ref, selectsync *sync);
typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event,
selectsync *sync);
typedef int op_initialize(const char *devname, void *parms, size_t len);
typedef int op_mount(nspace_id nsid, const char *devname, ulong flags,
void *parms, size_t len, void **data, vnode_id *vnid);
typedef int op_unmount(void *ns);
typedef int op_sync(void *ns);
typedef int op_rfsstat(void *ns, struct fs_info *);
typedef int op_wfsstat(void *ns, struct fs_info *, long mask);
typedef int op_open_attrdir(void *ns, void *node, void **cookie);
typedef int op_close_attrdir(void *ns, void *node, void *cookie);
typedef int op_rewind_attrdir(void *ns, void *node, void *cookie);
typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num,
struct dirent *buf, size_t bufsize);
typedef int op_remove_attr(void *ns, void *node, const char *name);
typedef int op_rename_attr(void *ns, void *node, const char *oldname,
const char *newname);
typedef int op_stat_attr(void *ns, void *node, const char *name,
struct attr_info *buf);
typedef int op_write_attr(void *ns, void *node, const char *name, int type,
const void *buf, size_t *len, off_t pos);
typedef int op_read_attr(void *ns, void *node, const char *name, int type,
void *buf, size_t *len, off_t pos);
typedef int op_open_indexdir(void *ns, void **cookie);
typedef int op_close_indexdir(void *ns, void *cookie);
typedef int op_rewind_indexdir(void *ns, void *cookie);
typedef int op_read_indexdir(void *ns, void *cookie, long *num,
struct dirent *buf, size_t bufsize);
typedef int op_create_index(void *ns, const char *name, int type, int flags);
typedef int op_remove_index(void *ns, const char *name);
typedef int op_rename_index(void *ns, const char *oldname,
const char *newname);
typedef int op_stat_index(void *ns, const char *name, struct index_info *buf);
typedef int op_open_query(void *ns, const char *query, ulong flags,
port_id port, long token, void **cookie);
typedef int op_close_query(void *ns, void *cookie);
typedef int op_read_query(void *ns, void *cookie, long *num,
struct dirent *buf, size_t bufsize);
typedef struct vnode_ops {
op_read_vnode (*read_vnode);
op_write_vnode (*write_vnode);
op_remove_vnode (*remove_vnode);
op_secure_vnode (*secure_vnode);
op_walk (*walk);
op_access (*access);
op_create (*create);
op_mkdir (*mkdir);
op_symlink (*symlink);
op_link (*link);
op_rename (*rename);
op_unlink (*unlink);
op_rmdir (*rmdir);
op_readlink (*readlink);
op_opendir (*opendir);
op_closedir (*closedir);
op_free_cookie (*free_dircookie);
op_rewinddir (*rewinddir);
op_readdir (*readdir);
op_open (*open);
op_close (*close);
op_free_cookie (*free_cookie);
op_read (*read);
op_write (*write);
op_readv (*readv);
op_writev (*writev);
op_ioctl (*ioctl);
op_setflags (*setflags);
op_rstat (*rstat);
op_wstat (*wstat);
op_fsync (*fsync);
op_initialize (*initialize);
op_mount (*mount);
op_unmount (*unmount);
op_sync (*sync);
op_rfsstat (*rfsstat);
op_wfsstat (*wfsstat);
op_select (*select);
op_deselect (*deselect);
op_open_indexdir (*open_indexdir);
op_close_indexdir (*close_indexdir);
op_free_cookie (*free_indexdircookie);
op_rewind_indexdir (*rewind_indexdir);
op_read_indexdir (*read_indexdir);
op_create_index (*create_index);
op_remove_index (*remove_index);
op_rename_index (*rename_index);
op_stat_index (*stat_index);
op_open_attrdir (*open_attrdir);
op_close_attrdir (*close_attrdir);
op_free_cookie (*free_attrdircookie);
op_rewind_attrdir (*rewind_attrdir);
op_read_attrdir (*read_attrdir);
op_write_attr (*write_attr);
op_read_attr (*read_attr);
op_remove_attr (*remove_attr);
op_rename_attr (*rename_attr);
op_stat_attr (*stat_attr);
op_open_query (*open_query);
op_close_query (*close_query);
op_free_cookie (*free_querycookie);
op_read_query (*read_query);
} vnode_ops;
#ifdef __cplusplus
extern "C" {
#endif
extern _IMPEXP_KERNEL int new_path(const char *path, char **copy);
extern _IMPEXP_KERNEL void free_path(char *p);
extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid,
vnode_id vnida, vnode_id vnidb,
vnode_id vnidc, const char *name);
extern _IMPEXP_KERNEL void notify_select_event(selectsync *sync, uint32 ref);
extern _IMPEXP_KERNEL int send_notification(port_id port, long token,
ulong what, long op, nspace_id nsida,
nspace_id nsidb, vnode_id vnida,
vnode_id vnidb, vnode_id vnidc,
const char *name);
extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data);
extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid);
extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data);
extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid);
extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid);
extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid);
extern _EXPORT vnode_ops fs_entry;
extern _EXPORT int32 api_version;
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+55
View File
@@ -0,0 +1,55 @@
/*
Copyright 1999-2001, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#ifndef _LOCK_H
#define _LOCK_H
#include <BeBuild.h>
#include <OS.h>
#ifndef _IMPEXP_KERNEL
#define _IMPEXP_KERNEL
#endif
#ifdef __cplusplus
extern "C" {
#else
typedef struct lock lock;
typedef struct mlock mlock;
#endif
struct lock {
sem_id s;
long c;
};
struct mlock {
sem_id s;
};
extern _IMPEXP_KERNEL int new_lock(lock *l, const char *name);
extern _IMPEXP_KERNEL int free_lock(lock *l);
#ifdef LOCK
#undef LOCK
#endif
#define LOCK(l) if (atomic_add(&l.c, -1) <= 0) acquire_sem(l.s);
#define UNLOCK(l) if (atomic_add(&l.c, 1) < 0) release_sem(l.s);
extern _IMPEXP_KERNEL int new_mlock(mlock *l, long c, const char *name);
extern _IMPEXP_KERNEL int free_mlock(mlock *l);
#define LOCKM(l,cnt) acquire_sem_etc(l.s, cnt, 0, 0)
#define UNLOCKM(l,cnt) release_sem_etc(l.s, cnt, 0)
#ifdef __cplusplus
} // extern "C"
#endif
#endif
@@ -0,0 +1,17 @@
// AreaSupport.h
#ifndef USERLAND_FS_AREA_SUPPORT_H
#define USERLAND_FS_AREA_SUPPORT_H
#include <OS.h>
namespace UserlandFSUtil {
status_t get_area_for_address(void* address, int32 size, area_id* area,
int32* offset, void** areaBaseAddress = NULL);
} // namespace UserlandFSUtil
using UserlandFSUtil::get_area_for_address;
#endif // USERLAND_FS_AREA_SUPPORT_H
@@ -0,0 +1,21 @@
// DispatcherDefs.h
#ifndef USERLAND_FS_DISPATCHER_DEFS_H
#define USERLAND_FS_DISPATCHER_DEFS_H
namespace UserlandFSUtil {
extern const char* kUserlandFSDispatcherPortName;
extern const char* kUserlandFSDispatcherReplyPortName;
} // namespace UserlandFSUtil
using UserlandFSUtil::kUserlandFSDispatcherPortName;
using UserlandFSUtil::kUserlandFSDispatcherReplyPortName;
enum {
UFS_DISPATCHER_CONNECT = 'cnct',
UFS_DISPATCHER_CONNECT_ACK = 'cack',
};
#endif // USERLAND_FS_DISPATCHER_DEFS_H
+58
View File
@@ -0,0 +1,58 @@
// Port.h
#ifndef USERLAND_FS_PORT_H
#define USERLAND_FS_PORT_H
#include <OS.h>
namespace UserlandFSUtil {
struct PortInfo {
};
class Port {
public:
struct Info {
port_id owner_port;
port_id client_port;
int32 size;
};
public:
Port(int32 size);
Port(const Info* info);
~Port();
void Close();
status_t InitCheck() const;
const Info* GetInfo() const;
void* GetBuffer() const;
int32 GetCapacity() const;
void* GetMessage() const;
int32 GetMessageSize() const;
status_t Send(int32 size);
status_t SendAndReceive(int32 size);
status_t Receive(bigtime_t timeout = -1);
private:
friend class KernelDebug;
Info fInfo;
uint8* fBuffer;
int32 fCapacity;
int32 fMessageSize;
status_t fInitStatus;
bool fOwner;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::PortInfo;
using UserlandFSUtil::Port;
#endif // USERLAND_FS_PORT_H
@@ -0,0 +1,84 @@
// Request.h
#ifndef USERLAND_FS_REQUEST_H
#define USERLAND_FS_REQUEST_H
#include <OS.h>
// address info flags
enum {
ADDRESS_NOT_NULL = 0x01,
ADDRESS_IS_STRING = 0x02,
};
namespace UserlandFSUtil {
class RequestAllocator;
// Address
class Address {
public:
Address();
void* GetData() const { return fRelocated; }
int32 GetSize() const { return fSize; }
//private:
void SetTo(area_id area, int32 offset, int32 size);
void SetRelocatedAddress(void* address)
{ fRelocated = address; }
area_id GetArea() const { return fUnrelocated.area; }
int32 GetOffset() const
{ return fUnrelocated.offset; }
private:
friend class RequestAllocator;
struct Unrelocated {
area_id area;
int32 offset;
};
union {
Unrelocated fUnrelocated;
void* fRelocated;
};
int32 fSize;
};
// AddressInfo
struct AddressInfo {
Address *address;
uint32 flags;
int32 max_size;
};
// Request
class Request {
public:
Request(uint32 type);
uint32 GetType() const;
status_t Check() const;
status_t GetAddressInfos(AddressInfo* infos,
int32* count);
private:
uint32 fType;
};
// implemented in Requests.cpp
bool is_kernel_request(uint32 type);
bool is_userland_request(uint32 type);
} // namespace UserlandFSUtil
using UserlandFSUtil::Address;
using UserlandFSUtil::AddressInfo;
using UserlandFSUtil::Request;
using UserlandFSUtil::is_kernel_request;
using UserlandFSUtil::is_userland_request;
#endif // USERLAND_FS_REQUEST_H
@@ -0,0 +1,89 @@
// RequestAllocator.h
#ifndef USERLAND_FS_REQUEST_ALLOCATOR_H
#define USERLAND_FS_REQUEST_ALLOCATOR_H
#include <new>
#include <OS.h>
#include "Debug.h"
#include "Requests.h"
namespace UserlandFSUtil {
class Port;
// RequestAllocator
class RequestAllocator {
public:
RequestAllocator(Port* port);
~RequestAllocator();
status_t Init(Port* port);
void Uninit();
status_t Error() const;
void FinishDeferredInit();
status_t AllocateRequest(int32 size);
status_t ReadRequest();
Request* GetRequest() const;
int32 GetRequestSize() const;
status_t AllocateAddress(Address& address, int32 size,
int32 align, void** data,
bool deferredInit = false);
status_t AllocateData(Address& address, const void* data,
int32 size, int32 align,
bool deferredInit = false);
status_t AllocateString(Address& address,
const char* data,
bool deferredInit = false);
// status_t SetAddress(Address& address, void* data,
// int32 size = 0);
private:
struct DeferredInitInfo {
Address* target;
uint8* data; // only if in port buffer
area_id area; // only if in area, otherwise -1
int32 offset;
int32 size;
bool inPortBuffer;
};
status_t fError;
Port* fPort;
Request* fRequest;
int32 fRequestSize;
area_id fAllocatedAreas[MAX_REQUEST_ADDRESS_COUNT];
int32 fAllocatedAreaCount;
DeferredInitInfo fDeferredInitInfos[MAX_REQUEST_ADDRESS_COUNT];
int32 fDeferredInitInfoCount;
bool fRequestInPortBuffer;
};
// AllocateRequest
// Should be a member, but we don't have member templates on PPC.
// TODO: Actually we seem to have. Check!
template<typename SpecificRequest>
status_t
AllocateRequest(RequestAllocator& allocator, SpecificRequest** request)
{
if (!request)
RETURN_ERROR(B_BAD_VALUE);
status_t error = allocator.AllocateRequest(sizeof(SpecificRequest));
if (error == B_OK)
*request = new(allocator.GetRequest()) SpecificRequest;
return error;
}
} // namespace UserlandFSUtil
using UserlandFSUtil::RequestAllocator;
using UserlandFSUtil::AllocateRequest;
#endif // USERLAND_FS_REQUEST_ALLOCATOR_H
@@ -0,0 +1,35 @@
// RequestHandler.h
#ifndef USERLAND_FS_REQUEST_HANDLER_H
#define USERLAND_FS_REQUEST_HANDLER_H
#include <SupportDefs.h>
namespace UserlandFSUtil {
class Request;
class RequestPort;
class RequestHandler {
public:
RequestHandler();
virtual ~RequestHandler();
void SetPort(RequestPort* port);
bool IsDone() const;
virtual status_t HandleRequest(Request* request) = 0;
protected:
RequestPort* fPort;
bool fDone;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::Request;
using UserlandFSUtil::RequestHandler;
using UserlandFSUtil::RequestPort;
#endif // USERLAND_FS_REQUEST_HANDLER_H
@@ -0,0 +1,73 @@
// RequestPort.h
#ifndef USERLAND_FS_REQUEST_PORT_H
#define USERLAND_FS_REQUEST_PORT_H
#include "Port.h"
#include "RequestAllocator.h"
namespace UserlandFSUtil {
class RequestHandler;
// RequestPort
class RequestPort {
public:
RequestPort(int32 size);
RequestPort(const Port::Info* info);
~RequestPort();
void Close();
status_t InitCheck() const;
Port* GetPort();
const Port::Info* GetPortInfo() const;
status_t SendRequest(RequestAllocator* allocator);
status_t SendRequest(RequestAllocator* allocator,
RequestHandler* handler,
Request** reply = NULL,
bigtime_t timeout = -1);
status_t ReceiveRequest(Request** request,
bigtime_t timeout = -1);
status_t HandleRequests(RequestHandler* handler,
Request** reply = NULL,
bigtime_t timeout = -1);
void ReleaseRequest(Request* request);
private:
void _PopAllocator();
private:
friend class KernelDebug;
struct AllocatorNode;
Port fPort;
AllocatorNode* fCurrentAllocatorNode;
};
// RequestReleaser
class RequestReleaser {
public:
inline RequestReleaser(RequestPort* port, Request* request)
: fPort(port), fRequest(request) {}
inline ~RequestReleaser()
{
if (fPort && fRequest)
fPort->ReleaseRequest(fRequest);
}
private:
RequestPort* fPort;
Request* fRequest;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::RequestPort;
using UserlandFSUtil::RequestReleaser;
#endif // USERLAND_FS_REQUEST_PORT_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,26 @@
// SingleReplyRequestHandler.h
#ifndef USERLAND_FS_SINGLE_REPLY_REQUEST_HANDLER_H
#define USERLAND_FS_SINGLE_REPLY_REQUEST_HANDLER_H
#include "RequestHandler.h"
namespace UserlandFSUtil {
class SingleReplyRequestHandler : public RequestHandler {
public:
SingleReplyRequestHandler();
SingleReplyRequestHandler(uint32 expectedReply);
virtual status_t HandleRequest(Request* request);
private:
bool fAcceptAnyRequest;
uint32 fExpectedReply;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::SingleReplyRequestHandler;
#endif // USERLAND_FS_SINGLE_REPLY_REQUEST_HANDLER_H
@@ -0,0 +1,55 @@
// userlandfs_ioctl.h
#ifndef USERLAND_FS_IOCTL_H
#define USERLAND_FS_IOCTL_H
#include <Drivers.h>
// the ioctl command we use for tunnelling our commands
enum {
USERLANDFS_IOCTL = B_DEVICE_OP_CODES_END + 666,
};
// the supported commands
enum {
USERLAND_IOCTL_PUT_ALL_PENDING_VNODES = 1,
};
// the length of the magic we use
enum {
USERLAND_IOCTL_MAGIC_LENGTH = 20,
};
// the version of the ioctl protocol
enum {
USERLAND_IOCTL_CURRENT_VERSION = 1,
};
// the errors
enum {
USERLAND_IOCTL_STILL_CONNECTED = B_ERRORS_END + 666,
USERLAND_IOCTL_VNODE_COUNTING_DISABLED,
USERLAND_IOCTL_OPEN_FILES,
USERLAND_IOCTL_OPEN_DIRECTORIES,
USERLAND_IOCTL_OPEN_ATTRIBUTE_DIRECTORIES,
USERLAND_IOCTL_OPEN_INDEX_DIRECTORIES,
USERLAND_IOCTL_OPEN_QUERIES,
};
namespace UserlandFSUtil {
struct userlandfs_ioctl {
char magic[USERLAND_IOCTL_MAGIC_LENGTH];
int version;
int command;
status_t error;
};
extern const char kUserlandFSIOCtlMagic[USERLAND_IOCTL_MAGIC_LENGTH];
} // namespace UserlandFSUtil
using UserlandFSUtil::userlandfs_ioctl;
using UserlandFSUtil::kUserlandFSIOCtlMagic;
#endif // USERLAND_FS_IOCTL_H
@@ -0,0 +1,136 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2004, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: AutoDeleter.h
// Author(s): Ingo Weinhold ([email protected])
// Description: Scope-based automatic deletion of objects/arrays.
// ObjectDeleter - deletes an object
// ArrayDeleter - deletes an array
// MemoryDeleter - free()s malloc()ed memory
//------------------------------------------------------------------------------
#ifndef _AUTO_DELETER_H
#define _AUTO_DELETER_H
#include <stdlib.h>
namespace BPrivate {
// AutoDeleter
template<typename C, typename Delete>
class AutoDeleter {
public:
inline AutoDeleter()
: fObject(NULL)
{
}
inline AutoDeleter(C *object)
: fObject(object)
{
}
inline ~AutoDeleter()
{
fDelete(fObject);
}
inline void SetTo(C *object)
{
fDelete(fObject);
fObject = object;
}
inline C *Detach()
{
C *object = fObject;
fObject = NULL;
return object;
}
private:
C *fObject;
Delete fDelete;
};
// ObjectDeleter
template<typename C>
struct ObjectDelete
{
inline void operator()(C *object)
{
delete object;
}
};
template<typename C>
struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> >
{
ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {}
ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {}
};
// ArrayDeleter
template<typename C>
struct ArrayDelete
{
inline void operator()(C *array)
{
delete[] array;
}
};
template<typename C>
struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> >
{
ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {}
ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {}
};
// MemoryDeleter
struct MemoryDelete
{
inline void operator()(void *memory)
{
free(memory);
}
};
struct MemoryDeleter : AutoDeleter<void, MemoryDelete >
{
MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {}
MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {}
};
} // namespace BPrivate
using BPrivate::ObjectDeleter;
using BPrivate::ArrayDeleter;
using BPrivate::MemoryDeleter;
#endif // _AUTO_DELETER_H
@@ -0,0 +1,164 @@
// AutoLocker.h
//
// Copyright (c) 2004, Ingo Weinhold ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef AUTO_LOCKER_H
#define AUTO_LOCKER_H
#include <SupportDefs.h>
// locking
// AutoLockerStandardLocking
template<typename Lockable>
class AutoLockerStandardLocking {
public:
inline bool Lock(Lockable *lockable)
{
return lockable->Lock();
}
inline void Unlock(Lockable *lockable)
{
lockable->Unlock();
}
};
// AutoLockerReadLocking
template<typename Lockable>
class AutoLockerReadLocking {
public:
inline bool Lock(Lockable *lockable)
{
return lockable->ReadLock();
}
inline void Unlock(Lockable *lockable)
{
lockable->ReadUnlock();
}
};
// AutoLockerWriteLocking
template<typename Lockable>
class AutoLockerWriteLocking {
public:
inline bool Lock(Lockable *lockable)
{
return lockable->WriteLock();
}
inline void Unlock(Lockable *lockable)
{
lockable->WriteUnlock();
}
};
// AutoLocker
template<typename Lockable,
typename Locking = AutoLockerStandardLocking<Lockable> >
class AutoLocker {
private:
typedef AutoLocker<Lockable, Locking> ThisClass;
public:
inline AutoLocker(Lockable *lockable, bool alreadyLocked = false)
: fLockable(lockable),
fLocked(fLockable && alreadyLocked)
{
if (!fLocked)
_Lock();
}
inline AutoLocker(Lockable &lockable, bool alreadyLocked = false)
: fLockable(&lockable),
fLocked(fLockable && alreadyLocked)
{
if (!fLocked)
_Lock();
}
inline ~AutoLocker()
{
Unlock();
}
inline void SetTo(Lockable *lockable, bool alreadyLocked)
{
Unlock();
fLockable = lockable;
fLocked = alreadyLocked;
if (!fLocked)
_Lock();
}
inline void SetTo(Lockable &lockable, bool alreadyLocked)
{
SetTo(&lockable, alreadyLocked);
}
inline void Unset()
{
Unlock();
}
inline AutoLocker<Lockable, Locking> &operator=(Lockable *lockable)
{
SetTo(lockable);
return *this;
}
inline AutoLocker<Lockable, Locking> &operator=(Lockable &lockable)
{
SetTo(&lockable);
return *this;
}
inline bool IsLocked() const { return fLocked; }
inline void Unlock()
{
if (fLockable && fLocked) {
fLocking.Unlock(fLockable);
fLocked = false;
}
}
inline operator bool() const { return fLocked; }
private:
inline void _Lock()
{
if (fLockable)
fLocked = fLocking.Lock(fLockable);
}
private:
Lockable *fLockable;
bool fLocked;
Locking fLocking;
};
#endif // AUTO_LOCKER_H
@@ -0,0 +1,51 @@
// Compatibility.h
//
// Copyright (c) 2004, Ingo Weinhold ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef USERLAND_FS_COMPATIBILITY_H
#define USERLAND_FS_COMPATIBILITY_H
#include <BeBuild.h>
#if B_BEOS_VERSION <= B_BEOS_VERSION_5
//# define B_BAD_DATA -2147483632L
#else
# ifndef closesocket
# define closesocket(fd) close(fd)
# endif
#endif
// a Haiku definition
#ifndef B_BUFFER_OVERFLOW
# define B_BUFFER_OVERFLOW EOVERFLOW
#endif
// make Zeta R5 source compatible without needing to link against libzeta.so
#ifdef find_directory
# undef find_directory
#endif
#endif // USERLAND_FS_COMPATIBILITY_H
+384
View File
@@ -0,0 +1,384 @@
// DLList.h
//
// Copyright (c) 2003, Ingo Weinhold ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef DL_LIST_H
#define DL_LIST_H
#include <SupportDefs.h>
namespace UserlandFSUtil {
// DLListLink
template<typename Element>
class DLListLink {
public:
DLListLink() : previous(NULL), next(NULL) {}
~DLListLink() {}
Element *previous;
Element *next;
};
// DLListLinkImpl
template<typename Element>
class DLListLinkImpl {
private:
typedef DLListLink<Element> MyLink;
public:
DLListLinkImpl() : fDLListLink() {}
~DLListLinkImpl() {}
MyLink *GetDLListLink() { return &fDLListLink; }
const MyLink *GetDLListLink() const { return &fDLListLink; }
private:
MyLink fDLListLink;
};
// DLListStandardGetLink
template<typename Element>
class DLListStandardGetLink {
private:
typedef DLListLink<Element> Link;
public:
inline Link *operator()(Element *element) const
{
return element->GetDLListLink();
}
inline const Link *operator()(const Element *element) const
{
return element->GetDLListLink();
}
};
// for convenience
#define DL_LIST_TEMPLATE_LIST template<typename Element, typename GetLink>
#define DL_LIST_CLASS_NAME DLList<Element, GetLink>
// DLList
template<typename Element, typename GetLink = DLListStandardGetLink<Element> >
class DLList {
private:
typedef DLList<Element, GetLink> List;
typedef DLListLink<Element> Link;
public:
class Iterator {
public:
Iterator(List *list)
: fList(list),
fCurrent(NULL),
fNext(fList->GetFirst())
{
}
Iterator(const Iterator &other)
{
*this = other;
}
bool HasNext() const
{
return fNext;
}
Element *Next()
{
fCurrent = fNext;
if (fNext)
fNext = fList->GetNext(fNext);
return fCurrent;
}
Element *Remove()
{
Element *element = fCurrent;
if (fCurrent) {
fList->Remove(fCurrent);
fCurrent = NULL;
}
return element;
}
Iterator &operator=(const Iterator &other)
{
fList = other.fList;
fCurrent = other.fCurrent;
fNext = other.fNext;
return *this;
}
private:
List *fList;
Element *fCurrent;
Element *fNext;
};
class ConstIterator {
public:
ConstIterator(const List *list)
: fList(list),
fNext(list->GetFirst())
{
}
ConstIterator(const ConstIterator &other)
{
*this = other;
}
bool HasNext() const
{
return fNext;
}
Element *Next()
{
Element *element = fNext;
if (fNext)
fNext = fList->GetNext(fNext);
return element;
}
ConstIterator &operator=(const ConstIterator &other)
{
fList = other.fList;
fNext = other.fNext;
return *this;
}
private:
const List *fList;
Element *fNext;
};
public:
DLList() : fFirst(NULL), fLast(NULL) {}
DLList(const GetLink &getLink)
: fFirst(NULL), fLast(NULL), fGetLink(getLink) {}
~DLList() {}
inline bool IsEmpty() const { return (fFirst == NULL); }
inline void Insert(Element *element, bool back = true);
inline void Remove(Element *element);
inline void Swap(Element *a, Element *b);
inline void MoveFrom(DL_LIST_CLASS_NAME *fromList);
inline void RemoveAll();
inline Element *GetFirst() const { return fFirst; }
inline Element *GetLast() const { return fLast; }
inline Element *GetHead() const { return fFirst; }
inline Element *GetTail() const { return fLast; }
inline Element *GetPrevious(Element *element) const;
inline Element *GetNext(Element *element) const;
inline int32 Size() const;
// O(n)!
inline Iterator GetIterator() { return Iterator(this); }
inline ConstIterator GetIterator() const { return ConstIterator(this); }
private:
Element *fFirst;
Element *fLast;
GetLink fGetLink;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::DLList;
using UserlandFSUtil::DLListLink;
using UserlandFSUtil::DLListLinkImpl;
// inline methods
// Insert
DL_LIST_TEMPLATE_LIST
void
DL_LIST_CLASS_NAME::Insert(Element *element, bool back)
{
if (element) {
if (back) {
// append
Link *elLink = fGetLink(element);
elLink->previous = fLast;
elLink->next = NULL;
if (fLast)
fGetLink(fLast)->next = element;
else
fFirst = element;
fLast = element;
} else {
// prepend
Link *elLink = fGetLink(element);
elLink->previous = NULL;
elLink->next = fFirst;
if (fFirst)
fGetLink(fFirst)->previous = element;
else
fLast = element;
fFirst = element;
}
}
}
// Remove
DL_LIST_TEMPLATE_LIST
void
DL_LIST_CLASS_NAME::Remove(Element *element)
{
if (element) {
Link *elLink = fGetLink(element);
if (elLink->previous)
fGetLink(elLink->previous)->next = elLink->next;
else
fFirst = elLink->next;
if (elLink->next)
fGetLink(elLink->next)->previous = elLink->previous;
else
fLast = elLink->previous;
elLink->previous = NULL;
elLink->next = NULL;
}
}
// Swap
DL_LIST_TEMPLATE_LIST
void
DL_LIST_CLASS_NAME::Swap(Element *a, Element *b)
{
if (a && b && a != b) {
Link *aLink = fGetLink(a);
Link *bLink = fGetLink(b);
Element *aPrev = aLink->previous;
Element *bPrev = bLink->previous;
Element *aNext = aLink->next;
Element *bNext = bLink->next;
// place a
if (bPrev)
fGetLink(bPrev)->next = a;
else
fFirst = a;
if (bNext)
fGetLink(bNext)->previous = a;
else
fLast = a;
aLink->previous = bPrev;
aLink->next = bNext;
// place b
if (aPrev)
fGetLink(aPrev)->next = b;
else
fFirst = b;
if (aNext)
fGetLink(aNext)->previous = b;
else
fLast = b;
bLink->previous = aPrev;
bLink->next = aNext;
}
}
// MoveFrom
DL_LIST_TEMPLATE_LIST
void
DL_LIST_CLASS_NAME::MoveFrom(DL_LIST_CLASS_NAME *fromList)
{
if (fromList && fromList->fFirst) {
if (fFirst) {
fGetLink(fLast)->next = fromList->fFirst;
fGetLink(fFirst)->previous = fLast;
fLast = fromList->fLast;
} else {
fFirst = fromList->fFirst;
fLast = fromList->fLast;
}
fromList->fFirst = NULL;
fromList->fLast = NULL;
}
}
// RemoveAll
DL_LIST_TEMPLATE_LIST
void
DL_LIST_CLASS_NAME::RemoveAll()
{
Element *element = fFirst;
while (element) {
Link *elLink = fGetLink(element);
element = elLink->next;
elLink->previous = NULL;
elLink->next = NULL;
}
fFirst = NULL;
fLast = NULL;
}
// GetPrevious
DL_LIST_TEMPLATE_LIST
Element *
DL_LIST_CLASS_NAME::GetPrevious(Element *element) const
{
Element *result = NULL;
if (element)
result = fGetLink(element)->previous;
return result;
}
// GetNext
DL_LIST_TEMPLATE_LIST
Element *
DL_LIST_CLASS_NAME::GetNext(Element *element) const
{
Element *result = NULL;
if (element)
result = fGetLink(element)->next;
return result;
}
// Size
DL_LIST_TEMPLATE_LIST
int32
DL_LIST_CLASS_NAME::Size() const
{
int32 count = 0;
for (Element* element = GetFirst(); element; element = GetNext(element))
count++;
return count;
}
#endif // DL_LIST_H
+140
View File
@@ -0,0 +1,140 @@
#ifndef DEBUG_H
#define DEBUG_H
/* Debug - debug stuff
**
** Initial version by Axel Dörfler, [email protected]
** This file may be used under the terms of the OpenBeOS License.
*/
#include <string.h>
#if !USER
# include <KernelExport.h>
#endif
#include <OS.h>
#include <SupportDefs.h>
// define all macros we work with -- undefined macros are set to defaults
#ifndef USER
# define USER 0
#endif
#ifndef DEBUG
# define DEBUG 0
#endif
#if !DEBUG
# undef DEBUG_PRINT
# define DEBUG_PRINT 0
#endif
#ifndef DEBUG_PRINT
# define DEBUG_PRINT 0
#endif
#ifndef DEBUG_APP
# define DEBUG_APP "debug"
#endif
#ifndef DEBUG_PRINT_FILE
# define DEBUG_PRINT_FILE "/var/log/" DEBUG_APP ".log"
#endif
// define the debug output function
#if USER
# include <stdio.h>
# if DEBUG_PRINT
# define __out dbg_printf
# else
# define __out printf
# endif
#else
# include <KernelExport.h>
# include <null.h>
# if DEBUG_PRINT
# define __out dbg_printf
# else
# define __out dprintf
# endif
#endif
// define the PANIC() macro
#ifndef PANIC
# if USER
# define PANIC(str) debugger(str)
# else
# define PANIC(str) panic(str)
# endif
#endif
// functions exported by this module
status_t init_debugging();
status_t exit_debugging();
void dbg_printf_begin();
void dbg_printf_end();
#if DEBUG_PRINT
void dbg_printf(const char *format,...);
#else
static inline void dbg_printf(const char *,...) {}
#endif
// Short overview over the debug output macros:
// PRINT()
// is for general messages that very unlikely should appear in a release build
// FATAL()
// this is for fatal messages, when something has really gone wrong
// INFORM()
// general information, as disk size, etc.
// REPORT_ERROR(status_t)
// prints out error information
// RETURN_ERROR(status_t)
// calls REPORT_ERROR() and return the value
// D()
// the statements in D() are only included if DEBUG is defined
#if __MWERKS__
# define __FUNCTION__ ""
#endif
#define DEBUG_THREAD find_thread(NULL)
#define DEBUG_CONTEXT(x) { dbg_printf_begin(); __out(DEBUG_APP " [%Ld: %5ld] ", system_time(), DEBUG_THREAD); x; dbg_printf_end(); }
#define DEBUG_CONTEXT_FUNCTION(prefix, x) { dbg_printf_begin(); __out(DEBUG_APP " [%Ld: %5ld] %s()" prefix, system_time(), DEBUG_THREAD, __FUNCTION__); x; dbg_printf_end(); }
#define DEBUG_CONTEXT_LINE(x) { dbg_printf_begin(); __out(DEBUG_APP " [%Ld: %5ld] %s():%d: ", system_time(), DEBUG_THREAD, __FUNCTION__, __LINE__); x; dbg_printf_end(); }
#define TPRINT(x) DEBUG_CONTEXT( __out x )
#define TREPORT_ERROR(status) DEBUG_CONTEXT_LINE( __out("%s\n", strerror(status)) )
#define TRETURN_ERROR(err) { status_t _status = err; if (_status < B_OK) TREPORT_ERROR(_status); return _status;}
#define TSET_ERROR(var, err) { status_t _status = err; if (_status < B_OK) TREPORT_ERROR(_status); var = _status; }
#define TFUNCTION(x) DEBUG_CONTEXT_FUNCTION( ": ", __out x )
#define TFUNCTION_START() DEBUG_CONTEXT_FUNCTION( "\n", )
#define TFUNCTION_END() DEBUG_CONTEXT_FUNCTION( " done\n", )
#if DEBUG
#define PRINT(x) TPRINT(x)
#define REPORT_ERROR(status) TREPORT_ERROR(status)
#define RETURN_ERROR(err) TRETURN_ERROR(err)
#define SET_ERROR(var, err) TSET_ERROR(var, err)
#define FATAL(x) DEBUG_CONTEXT( __out x )
#define ERROR(x) DEBUG_CONTEXT( __out x )
#define WARN(x) DEBUG_CONTEXT( __out x )
#define INFORM(x) DEBUG_CONTEXT( __out x )
#define FUNCTION(x) TFUNCTION(x)
#define FUNCTION_START() TFUNCTION_START()
#define FUNCTION_END() TFUNCTION_END()
#define DARG(x) x
#define D(x) {x;};
#else
#define PRINT(x) ;
#define REPORT_ERROR(status) ;
#define RETURN_ERROR(status) return status;
#define SET_ERROR(var, err) var = err;
#define FATAL(x) DEBUG_CONTEXT( __out x )
#define ERROR(x) DEBUG_CONTEXT( __out x )
#define WARN(x) DEBUG_CONTEXT( __out x )
#define INFORM(x) DEBUG_CONTEXT( __out x )
#define FUNCTION(x) ;
#define FUNCTION_START() ;
#define FUNCTION_END() ;
#define DARG(x)
#define D(x) ;
#endif
#ifndef TOUCH
#define TOUCH(var) (void)var
#endif
#endif /* DEBUG_H */
@@ -0,0 +1,130 @@
// DriverSettings.h
#ifndef USERLAND_FS_DRIVER_SETTINGS_H
#define USERLAND_FS_DRIVER_SETTINGS_H
struct driver_parameter;
struct driver_settings;
namespace UserlandFSUtil {
class DriverParameter;
class DriverParameterContainer;
// DriverParameterIterator
class DriverParameterIterator {
public:
DriverParameterIterator();
DriverParameterIterator(
const DriverParameterIterator& other);
~DriverParameterIterator();
bool HasNext() const;
bool GetNext(DriverParameter* parameter);
DriverParameterIterator& operator=(
const DriverParameterIterator& other);
private:
friend class DriverParameterContainer;
class Delegate;
DriverParameterIterator(Delegate* delegate);
void _SetTo(Delegate* delegate, bool addReference);
Delegate* fDelegate;
};
// DriverParameterContainer
class DriverParameterContainer {
public:
DriverParameterContainer();
virtual ~DriverParameterContainer();
int32 CountParameters() const;
const driver_parameter* GetParameters() const;
bool GetParameterAt(int32 index,
DriverParameter* parameter) const;
bool FindParameter(const char* name,
DriverParameter* parameter) const;
DriverParameterIterator GetParameterIterator() const;
DriverParameterIterator GetParameterIterator(
const char* name) const;
const char* GetParameterValue(const char* name,
const char* unknownValue = NULL,
const char* noValue = NULL) const;
bool GetBoolParameterValue(const char* name,
bool unknownValue = false,
bool noValue = false) const;
int32 GetInt32ParameterValue(const char* name,
int32 unknownValue = 0,
int32 noValue = 0) const;
int64 GetInt64ParameterValue(const char* name,
int64 unknownValue = 0,
int64 noValue = 0) const;
protected:
virtual const driver_parameter*
GetParametersAndCount(int32* count) const = 0;
private:
class Iterator;
class NameIterator;
};
// DriverSettings
class DriverSettings : public DriverParameterContainer {
public:
DriverSettings();
virtual ~DriverSettings();
status_t Load(const char* driverName);
void Unset();
protected:
virtual const driver_parameter*
GetParametersAndCount(int32* count) const;
private:
void* fSettingsHandle;
const driver_settings* fSettings;
};
// DriverParameter
class DriverParameter : public DriverParameterContainer {
public:
DriverParameter();
virtual ~DriverParameter();
void SetTo(const driver_parameter* parameter);
const char* GetName() const;
int32 CountValues() const;
const char* const* GetValues() const;
const char* ValueAt(int32 index,
const char* noValue = NULL) const;
bool BoolValueAt(int32 index,
bool noValue = false) const;
int32 Int32ValueAt(int32 index,
int32 noValue = 0) const;
int64 Int64ValueAt(int32 index,
int64 noValue = 0) const;
protected:
virtual const driver_parameter*
GetParametersAndCount(int32* count) const;
private:
const driver_parameter* fParameter;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::DriverParameterIterator;
using UserlandFSUtil::DriverParameterContainer;
using UserlandFSUtil::DriverSettings;
using UserlandFSUtil::DriverParameter;
#endif // USERLAND_FS_DRIVER_SETTINGS_H
+444
View File
@@ -0,0 +1,444 @@
// HashMap.h
//
// Copyright (c) 2004, Ingo Weinhold ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef HASH_MAP_H
#define HASH_MAP_H
//#include <Debug.h>
#include "AutoLocker.h"
#include "Locker.h"
#include "OpenHashTable.h"
// HashMapElement
template<typename Key, typename Value>
class HashMapElement : public OpenHashElement {
private:
typedef HashMapElement<Key, Value> Element;
public:
HashMapElement() : OpenHashElement(), fKey(), fValue()
{
fNext = -1;
}
inline uint32 Hash() const
{
return fKey.GetHashCode();
}
inline bool operator==(const OpenHashElement &_element) const
{
const Element &element = static_cast<const Element&>(_element);
return (fKey == element.fKey);
}
inline void Adopt(Element &element)
{
fKey = element.fKey;
fValue = element.fValue;
}
Key fKey;
Value fValue;
};
// HashMap
template<typename Key, typename Value>
class HashMap {
public:
class Entry {
public:
Entry() {}
Entry(const Key& key, Value value) : key(key), value(value) {}
Key key;
Value value;
};
class Iterator {
private:
typedef HashMapElement<Key, Value> Element;
public:
Iterator(const Iterator& other)
: fMap(other.fMap),
fIndex(other.fIndex),
fElement(other.fElement),
fLastElement(other.fElement)
{
}
bool HasNext() const
{
return fElement;
}
Entry Next()
{
if (!fElement)
return Entry();
Entry result(fElement->fKey, fElement->fValue);
_FindNext();
return result;
}
Entry Remove()
{
if (!fLastElement)
return Entry();
Entry result(fLastElement->fKey, fLastElement->fValue);
fMap->fTable.Remove(fLastElement, true);
fLastElement = NULL;
return result;
}
Iterator& operator=(const Iterator& other)
{
fMap = other.fMap;
fIndex = other.fIndex;
fElement = other.fElement;
fLastElement = other.fLastElement;
return *this;
}
private:
Iterator(HashMap<Key, Value>* map)
: fMap(map),
fIndex(0),
fElement(NULL),
fLastElement(NULL)
{
// find first
_FindNext();
}
void _FindNext()
{
fLastElement = fElement;
if (fElement && fElement->fNext >= 0) {
fElement = fMap->fTable.ElementAt(fElement->fNext);
return;
}
fElement = NULL;
int32 arraySize = fMap->fTable.ArraySize();
for (; !fElement && fIndex < arraySize; fIndex++)
fElement = fMap->fTable.FindFirst(fIndex);
}
private:
friend class HashMap<Key, Value>;
HashMap<Key, Value>* fMap;
int32 fIndex;
Element* fElement;
Element* fLastElement;
};
HashMap();
~HashMap();
status_t InitCheck() const;
status_t Put(const Key& key, Value value);
Value Remove(const Key& key);
void Clear();
Value Get(const Key& key) const;
bool ContainsKey(const Key& key) const;
int32 Size() const;
Iterator GetIterator();
protected:
typedef HashMapElement<Key, Value> Element;
friend class Iterator;
private:
Element *_FindElement(const Key& key) const;
protected:
OpenHashElementArray<Element> fElementArray;
OpenHashTable<Element, OpenHashElementArray<Element> > fTable;
};
// SynchronizedHashMap
template<typename Key, typename Value>
class SynchronizedHashMap : public Locker {
public:
typedef HashMap<Key, Value>::Entry Entry;
typedef HashMap<Key, Value>::Iterator Iterator;
SynchronizedHashMap() : Locker("synchronized hash map") {}
~SynchronizedHashMap() { Lock(); }
status_t InitCheck() const
{
return fMap.InitCheck();
}
status_t Put(const Key& key, Value value)
{
MapLocker locker(this);
if (!locker.IsLocked())
return B_ERROR;
return fMap.Put(key, value);
}
Value Remove(const Key& key)
{
MapLocker locker(this);
if (!locker.IsLocked())
return Value();
return fMap.Remove(key);
}
void Clear()
{
MapLocker locker(this);
return fMap.Clear();
}
Value Get(const Key& key) const
{
const Locker* lock = this;
MapLocker locker(const_cast<Locker*>(lock));
if (!locker.IsLocked())
return Value();
return fMap.Get(key);
}
bool ContainsKey(const Key& key) const
{
const Locker* lock = this;
MapLocker locker(const_cast<Locker*>(lock));
if (!locker.IsLocked())
return false;
return fMap.ContainsKey(key);
}
int32 Size() const
{
const Locker* lock = this;
MapLocker locker(const_cast<Locker*>(lock));
return fMap.Size();
}
Iterator GetIterator()
{
return fMap.GetIterator();
}
// for debugging only
const HashMap<Key, Value>& GetUnsynchronizedMap() const { return fMap; }
HashMap<Key, Value>& GetUnsynchronizedMap() { return fMap; }
protected:
typedef AutoLocker<Locker> MapLocker;
HashMap<Key, Value> fMap;
};
// HashKey32
template<typename Value>
struct HashKey32 {
HashKey32() {}
HashKey32(const Value& value) : value(value) {}
uint32 GetHashCode() const
{
return (uint32)value;
}
HashKey32<Value> operator=(const HashKey32<Value>& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKey32<Value>& other) const
{
return (value == other.value);
}
bool operator!=(const HashKey32<Value>& other) const
{
return (value != other.value);
}
Value value;
};
// HashKey64
template<typename Value>
struct HashKey64 {
HashKey64() {}
HashKey64(const Value& value) : value(value) {}
uint32 GetHashCode() const
{
uint64 v = (uint64)value;
return (uint32)(v >> 32) ^ (uint32)v;
}
HashKey64<Value> operator=(const HashKey64<Value>& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKey64<Value>& other) const
{
return (value == other.value);
}
bool operator!=(const HashKey64<Value>& other) const
{
return (value != other.value);
}
Value value;
};
// HashMap
// constructor
template<typename Key, typename Value>
HashMap<Key, Value>::HashMap()
: fElementArray(1000),
fTable(1000, &fElementArray)
{
}
// destructor
template<typename Key, typename Value>
HashMap<Key, Value>::~HashMap()
{
}
// InitCheck
template<typename Key, typename Value>
status_t
HashMap<Key, Value>::InitCheck() const
{
return (fTable.InitCheck() && fElementArray.InitCheck()
? B_OK : B_NO_MEMORY);
}
// Put
template<typename Key, typename Value>
status_t
HashMap<Key, Value>::Put(const Key& key, Value value)
{
Element* element = _FindElement(key);
if (element) {
// already contains the key: just set the new value
element->fValue = value;
return B_OK;
}
// does not contain the key yet: add an element
element = fTable.Add(key.GetHashCode());
if (!element)
return B_NO_MEMORY;
element->fKey = key;
element->fValue = value;
return B_OK;
}
// Remove
template<typename Key, typename Value>
Value
HashMap<Key, Value>::Remove(const Key& key)
{
Value value = Value();
if (Element* element = _FindElement(key)) {
value = element->fValue;
fTable.Remove(element);
}
return value;
}
// Clear
template<typename Key, typename Value>
void
HashMap<Key, Value>::Clear()
{
fTable.RemoveAll();
}
// Get
template<typename Key, typename Value>
Value
HashMap<Key, Value>::Get(const Key& key) const
{
if (Element* element = _FindElement(key))
return element->fValue;
return Value();
}
// ContainsKey
template<typename Key, typename Value>
bool
HashMap<Key, Value>::ContainsKey(const Key& key) const
{
return _FindElement(key);
}
// Size
template<typename Key, typename Value>
int32
HashMap<Key, Value>::Size() const
{
return fTable.CountElements();
}
// GetIterator
template<typename Key, typename Value>
HashMap<Key, Value>::Iterator
HashMap<Key, Value>::GetIterator()
{
return Iterator(this);
}
// _FindElement
template<typename Key, typename Value>
HashMap<Key, Value>::Element *
HashMap<Key, Value>::_FindElement(const Key& key) const
{
Element* element = fTable.FindFirst(key.GetHashCode());
while (element && element->fKey != key) {
if (element->fNext >= 0)
element = fTable.ElementAt(element->fNext);
else
element = NULL;
}
return element;
}
#endif // HASH_MAP_H
+323
View File
@@ -0,0 +1,323 @@
// HashSet.h
//
// Copyright (c) 2004, Ingo Weinhold ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef HASH_SET_H
#define HASH_SET_H
#include "AutoLocker.h"
#include "Locker.h"
#include "OpenHashTable.h"
// HashSetElement
template<typename Key>
class HashSetElement : public OpenHashElement {
private:
typedef HashSetElement<Key> Element;
public:
HashSetElement() : OpenHashElement(), fKey()
{
fNext = -1;
}
inline uint32 Hash() const
{
return fKey.GetHashCode();
}
inline bool operator==(const OpenHashElement &_element) const
{
const Element &element = static_cast<const Element&>(_element);
return (fKey == element.fKey);
}
inline void Adopt(Element &element)
{
fKey = element.fKey;
}
Key fKey;
};
// HashSet
template<typename Key>
class HashSet {
public:
class Iterator {
private:
typedef HashSetElement<Key> Element;
public:
Iterator(const Iterator& other)
: fSet(other.fSet),
fIndex(other.fIndex),
fElement(other.fElement),
fLastElement(other.fElement)
{
}
bool HasNext() const
{
return fElement;
}
Key Next()
{
if (!fElement)
return Key();
Key result(fElement->fKey);
_FindNext();
return result;
}
bool Remove()
{
if (!fLastElement)
return false;
fSet->fTable.Remove(fLastElement);
fLastElement = NULL;
return true;
}
Iterator& operator=(const Iterator& other)
{
fSet = other.fSet;
fIndex = other.fIndex;
fElement = other.fElement;
fLastElement = other.fLastElement;
return *this;
}
private:
Iterator(HashSet<Key>* map)
: fSet(map),
fIndex(0),
fElement(NULL),
fLastElement(NULL)
{
// find first
_FindNext();
}
void _FindNext()
{
fLastElement = fElement;
if (fElement && fElement->fNext >= 0) {
fElement = fSet->fTable.ElementAt(fElement->fNext);
return;
}
fElement = NULL;
int32 arraySize = fSet->fTable.ArraySize();
for (; !fElement && fIndex < arraySize; fIndex++)
fElement = fSet->fTable.FindFirst(fIndex);
}
private:
friend class HashSet<Key>;
HashSet<Key>* fSet;
int32 fIndex;
Element* fElement;
Element* fLastElement;
};
HashSet();
~HashSet();
status_t InitCheck() const;
status_t Add(const Key& key);
bool Remove(const Key& key);
bool Contains(const Key& key) const;
int32 Size() const;
Iterator GetIterator();
protected:
typedef HashSetElement<Key> Element;
friend class Iterator;
private:
Element *_FindElement(const Key& key) const;
protected:
OpenHashElementArray<Element> fElementArray;
OpenHashTable<Element, OpenHashElementArray<Element> > fTable;
};
// SynchronizedHashSet
template<typename Key>
class SynchronizedHashSet : public Locker {
public:
typedef HashSet<Key>::Iterator Iterator;
SynchronizedHashSet() : Locker("synchronized hash map") {}
~SynchronizedHashSet() { Lock(); }
status_t InitCheck() const
{
return fSet.InitCheck();
}
status_t Add(const Key& key)
{
MapLocker locker(this);
if (!locker.IsLocked())
return B_ERROR;
return fSet.Add(key);
}
bool Remove(const Key& key)
{
MapLocker locker(this);
if (!locker.IsLocked())
return false;
return fSet.Remove(key);
}
bool Contains(const Key& key) const
{
const Locker* lock = this;
MapLocker locker(const_cast<Locker*>(lock));
if (!locker.IsLocked())
return false;
return fSet.Contains(key);
}
int32 Size() const
{
const Locker* lock = this;
MapLocker locker(const_cast<Locker*>(lock));
return fSet.Size();
}
Iterator GetIterator()
{
return fSet.GetIterator();
}
// for debugging only
const HashSet<Key>& GetUnsynchronizedSet() const { return fSet; }
HashSet<Key>& GetUnsynchronizedSet() { return fSet; }
protected:
typedef AutoLocker<Locker> MapLocker;
HashSet<Key> fSet;
};
// HashSet
// constructor
template<typename Key>
HashSet<Key>::HashSet()
: fElementArray(1000),
fTable(1000, &fElementArray)
{
}
// destructor
template<typename Key>
HashSet<Key>::~HashSet()
{
}
// InitCheck
template<typename Key>
status_t
HashSet<Key>::InitCheck() const
{
return (fTable.InitCheck() && fElementArray.InitCheck()
? B_OK : B_NO_MEMORY);
}
// Add
template<typename Key>
status_t
HashSet<Key>::Add(const Key& key)
{
if (Contains(key))
return B_OK;
Element* element = fTable.Add(key.GetHashCode());
if (!element)
return B_NO_MEMORY;
element->fKey = key;
return B_OK;
}
// Remove
template<typename Key>
bool
HashSet<Key>::Remove(const Key& key)
{
if (Element* element = _FindElement(key)) {
fTable.Remove(element);
return true;
}
return false;
}
// Contains
template<typename Key>
bool
HashSet<Key>::Contains(const Key& key) const
{
return _FindElement(key);
}
// Size
template<typename Key>
int32
HashSet<Key>::Size() const
{
return fTable.CountElements();
}
// GetIterator
template<typename Key>
HashSet<Key>::Iterator
HashSet<Key>::GetIterator()
{
return Iterator(this);
}
// _FindElement
template<typename Key>
HashSet<Key>::Element *
HashSet<Key>::_FindElement(const Key& key) const
{
Element* element = fTable.FindFirst(key.GetHashCode());
while (element && element->fKey != key) {
if (element->fNext >= 0)
element = fTable.ElementAt(element->fNext);
else
element = NULL;
}
return element;
}
#endif // HASH_SET_H
@@ -0,0 +1,31 @@
// LazyInitializable.h
#ifndef USERLAND_FS_LAZY_INITIALIZABLE_H
#define USERLAND_FS_LAZY_INITIALIZABLE_H
#include <OS.h>
namespace UserlandFSUtil {
class LazyInitializable {
public:
LazyInitializable();
LazyInitializable(bool init);
virtual ~LazyInitializable();
status_t Access();
status_t InitCheck() const;
protected:
virtual status_t FirstTimeInit() = 0;
protected:
status_t fInitStatus;
sem_id fInitSemaphore;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::LazyInitializable;
#endif // USERLAND_FS_LAZY_INITIALIZABLE_H
@@ -0,0 +1,59 @@
//
// $Id: Locker.h,v 1.1 2002/07/09 12:24:33 ejakowatz Exp $
//
// This is the Locker interface for OpenBeOS. It has been created to
// be source and binary compatible with the BeOS version of Locker.
//
// bonefish:
// * Removed `virtual' from destructor and FBC reserved space.
// * Renamed to Locker.
#ifndef _OPENBEOS_LOCKER_H
#define _OPENBEOS_LOCKER_H
#include <OS.h>
#include <SupportDefs.h>
namespace UserlandFSUtil {
class Locker {
public:
Locker();
Locker(const char *name);
Locker(bool benaphore_style);
Locker(const char *name, bool benaphore_style);
// The following constructor is not documented in the BeBook
// and is only listed here to ensure binary compatibility.
// DO NOT USE THIS CONSTRUCTOR!
Locker(const char *name, bool benaphore_style, bool);
~Locker();
bool Lock(void);
status_t LockWithTimeout(bigtime_t timeout);
void Unlock(void);
thread_id LockingThread(void) const;
bool IsLocked(void) const;
int32 CountLocks(void) const;
int32 CountLockRequests(void) const;
sem_id Sem(void) const;
private:
void InitLocker(const char *name, bool benaphore_style);
bool AcquireLock(bigtime_t timeout, status_t *error);
int32 fBenaphoreCount;
sem_id fSemaphoreID;
thread_id fLockOwner;
int32 fRecursiveCount;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::Locker;
#endif // _OPENBEOS_LOCKER_H
@@ -0,0 +1,80 @@
// ObjectTracker.h
#ifndef USERLAND_FS_OBJECT_TRACKER_H
#define USERLAND_FS_OBJECT_TRACKER_H
#include "DLList.h"
#include "Locker.h"
namespace UserlandFSUtil {
class ObjectTracker;
class GetObjectTrackableLink;
// ObjectTrackable
class ObjectTrackable {
public:
ObjectTrackable();
virtual ~ObjectTrackable();
private:
friend class ObjectTracker;
friend class GetObjectTrackableLink;
DLListLink<ObjectTrackable> fLink;
};
// GetObjectTrackableLink
struct GetObjectTrackableLink {
inline DLListLink<ObjectTrackable> *operator()(
ObjectTrackable* trackable) const
{
return &trackable->fLink;
}
inline const DLListLink<ObjectTrackable> *operator()(
const ObjectTrackable* trackable) const
{
return &trackable->fLink;
}
};
// ObjectTracker
class ObjectTracker {
private:
ObjectTracker();
~ObjectTracker();
public:
static ObjectTracker* InitDefault();
static void ExitDefault();
static ObjectTracker* GetDefault();
private:
friend class ObjectTrackable;
void AddTrackable(ObjectTrackable* trackable);
void RemoveTrackable(ObjectTrackable* trackable);
private:
Locker fLock;
DLList<ObjectTrackable, GetObjectTrackableLink> fTrackables;
static ObjectTracker* sTracker;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::ObjectTrackable;
using UserlandFSUtil::ObjectTracker;
#ifdef DEBUG_OBJECT_TRACKING
# define ONLY_OBJECT_TRACKABLE_BASE_CLASS : private ObjectTrackable
# define FIRST_OBJECT_TRACKABLE_BASE_CLASS private ObjectTrackable,
#else
# define ONLY_OBJECT_TRACKABLE_BASE_CLASS
# define FIRST_OBJECT_TRACKABLE_BASE_CLASS
#endif
#endif // USERLAND_FS_OBJECT_TRACKER_H
@@ -0,0 +1,510 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice applies to all licensees
and shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
// bonefish:
// * removed need for exceptions
// * fixed warnings
// * implemented rehashing
// * added RemoveAll()
// TODO:
// * shrinking of element vectors
// Hash table with open addresssing
#ifndef __OPEN_HASH_TABLE__
#define __OPEN_HASH_TABLE__
#include <malloc.h>
#include <new.h>
// don't include <Debug.h>
#define ASSERT(E) (void)0
#define TRESPASS() (void)0
//namespace BPrivate {
template <class Element>
class ElementVector {
// element vector for OpenHashTable needs to implement this
// interface
public:
Element &At(int32 index);
Element *Add();
int32 IndexOf(const Element &) const;
void Remove(int32 index);
};
class OpenHashElement {
public:
uint32 Hash() const;
bool operator==(const OpenHashElement &) const;
void Adopt(OpenHashElement &);
// low overhead copy, original element is in undefined state
// after call (calls Adopt on BString members, etc.)
int32 fNext;
};
const uint32 kPrimes [] = {
509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
134217689, 268435399, 536870909, 1073741789, 2147483647, 0
};
template <class Element, class ElementVec = ElementVector<Element> >
class OpenHashTable {
public:
OpenHashTable(int32 minSize, ElementVec *elementVector = 0,
float maxLoadFactor = 0.8);
// it is up to the subclass of OpenHashTable to supply
// elementVector
~OpenHashTable();
bool InitCheck() const;
void SetElementVector(ElementVec *elementVector);
Element *FindFirst(uint32 elementHash) const;
Element *Add(uint32 elementHash);
void Remove(Element *element, bool dontRehash = false);
void RemoveAll();
// when calling Add, any outstanding element pointer may become
// invalid; to deal with this, get the element index and restore
// it after the add
int32 ElementIndex(const Element *) const;
Element *ElementAt(int32 index) const;
int32 ArraySize() const;
int32 VectorSize() const;
int32 CountElements() const;
protected:
static int32 OptimalSize(int32 minSize);
private:
bool _RehashIfNeeded();
bool _Rehash();
int32 fArraySize;
int32 fInitialSize;
int32 fElementCount;
int32 *fHashArray;
ElementVec *fElementVector;
float fMaxLoadFactor;
};
template <class Element>
class OpenHashElementArray : public ElementVector<Element> {
// this is a straightforward implementation of an element vector
// deleting is handled by linking deleted elements into a free list
// the vector never shrinks
public:
OpenHashElementArray(int32 initialSize);
~OpenHashElementArray();
bool InitCheck() const;
Element &At(int32 index);
const Element &At(int32 index) const;
Element *Add(const Element &);
Element *Add();
void Remove(int32 index);
int32 IndexOf(const Element &) const;
int32 Size() const;
private:
Element *fData;
int32 fSize;
int32 fNextFree;
int32 fNextDeleted;
};
//-----------------------------------
template<class Element, class ElementVec>
OpenHashTable<Element, ElementVec>::OpenHashTable(int32 minSize,
ElementVec *elementVector, float maxLoadFactor)
: fArraySize(OptimalSize(minSize)),
fInitialSize(fArraySize),
fElementCount(0),
fElementVector(elementVector),
fMaxLoadFactor(maxLoadFactor)
{
// sanity check the maximal load factor
if (fMaxLoadFactor < 0.5)
fMaxLoadFactor = 0.5;
// allocate and init the array
fHashArray = (int32*)calloc(fArraySize, sizeof(int32));
if (fHashArray) {
for (int32 index = 0; index < fArraySize; index++)
fHashArray[index] = -1;
}
}
template<class Element, class ElementVec>
OpenHashTable<Element, ElementVec>::~OpenHashTable()
{
RemoveAll();
free(fHashArray);
}
template<class Element, class ElementVec>
bool
OpenHashTable<Element, ElementVec>::InitCheck() const
{
return (fHashArray && fElementVector);
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::OptimalSize(int32 minSize)
{
for (int32 index = 0; ; index++)
if (!kPrimes[index] || kPrimes[index] >= (uint32)minSize)
return (int32)kPrimes[index];
return 0;
}
template<class Element, class ElementVec>
Element *
OpenHashTable<Element, ElementVec>::FindFirst(uint32 hash) const
{
ASSERT(fElementVector);
hash %= fArraySize;
if (fHashArray[hash] < 0)
return 0;
return &fElementVector->At(fHashArray[hash]);
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::ElementIndex(const Element *element) const
{
return fElementVector->IndexOf(*element);
}
template<class Element, class ElementVec>
Element *
OpenHashTable<Element, ElementVec>::ElementAt(int32 index) const
{
return &fElementVector->At(index);
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::ArraySize() const
{
return fArraySize;
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::VectorSize() const
{
return fElementVector->Size();
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::CountElements() const
{
return fElementCount;
}
template<class Element, class ElementVec>
Element *
OpenHashTable<Element, ElementVec>::Add(uint32 hash)
{
ASSERT(fElementVector);
_RehashIfNeeded();
hash %= fArraySize;
Element *result = fElementVector->Add();
if (result) {
result->fNext = fHashArray[hash];
fHashArray[hash] = fElementVector->IndexOf(*result);
fElementCount++;
}
return result;
}
template<class Element, class ElementVec>
void
OpenHashTable<Element, ElementVec>::Remove(Element *element, bool dontRehash)
{
if (!dontRehash)
_RehashIfNeeded();
uint32 hash = element->Hash() % fArraySize;
int32 next = fHashArray[hash];
ASSERT(next >= 0);
if (&fElementVector->At(next) == element) {
fHashArray[hash] = element->fNext;
fElementVector->Remove(next);
fElementCount--;
return;
}
for (int32 index = next; index >= 0; ) {
// look for an existing match in table
next = fElementVector->At(index).fNext;
if (next < 0) {
TRESPASS();
return;
}
if (&fElementVector->At(next) == element) {
fElementVector->At(index).fNext = element->fNext;
fElementVector->Remove(next);
fElementCount--;
return;
}
index = next;
}
}
template<class Element, class ElementVec>
void
OpenHashTable<Element, ElementVec>::RemoveAll()
{
for (int32 i = 0; fElementCount > 0 && i < fArraySize; i++) {
int32 index = fHashArray[i];
while (index >= 0) {
Element* element = &fElementVector->At(index);
int32 next = element->fNext;
fElementVector->Remove(index);
fElementCount--;
index = next;
}
fHashArray[i] = -1;
}
_RehashIfNeeded();
}
template<class Element, class ElementVec>
void
OpenHashTable<Element, ElementVec>::SetElementVector(ElementVec *elementVector)
{
fElementVector = elementVector;
}
// _RehashIfNeeded
template<class Element, class ElementVec>
bool
OpenHashTable<Element, ElementVec>::_RehashIfNeeded()
{
// The load factor range [fMaxLoadFactor / 3, fMaxLoadFactor] is fine,
// I think. After rehashing the load factor will be about
// fMaxLoadFactor * 2 / 3, respectively fMaxLoadFactor / 2.
float loadFactor = (float)fElementCount / (float)fArraySize;
if (loadFactor > fMaxLoadFactor
|| (fArraySize > fInitialSize && loadFactor < fMaxLoadFactor / 3)) {
return _Rehash();
}
return true;
}
// _Rehash
template<class Element, class ElementVec>
bool
OpenHashTable<Element, ElementVec>::_Rehash()
{
bool result = true;
int32 newSize = int32(fElementCount * 1.73 * fMaxLoadFactor);
newSize = (fInitialSize > newSize ? fInitialSize : newSize);
if (newSize != fArraySize) {
// allocate a new array
int32 *newHashArray = (int32*)calloc(newSize, sizeof(int32));
if (newHashArray) {
// init the new hash array
for (int32 index = 0; index < newSize; index++)
newHashArray[index] = -1;
// iterate through all elements and put them into the new
// hash array
for (int i = 0; i < fArraySize; i++) {
int32 index = fHashArray[i];
while (index >= 0) {
// insert the element in the new array
Element &element = fElementVector->At(index);
int32 next = element.fNext;
uint32 hash = (element.Hash() % newSize);
element.fNext = newHashArray[hash];
newHashArray[hash] = index;
// next element in old list
index = next;
}
}
// delete the old array and set the new one
free(fHashArray);
fHashArray = newHashArray;
fArraySize = newSize;
} else
result = false;
}
return result;
}
template<class Element>
OpenHashElementArray<Element>::OpenHashElementArray(int32 initialSize)
: fSize(initialSize),
fNextFree(0),
fNextDeleted(-1)
{
fData = (Element*)calloc((size_t)initialSize, sizeof(Element));
}
template<class Element>
OpenHashElementArray<Element>::~OpenHashElementArray()
{
free(fData);
}
template<class Element>
bool
OpenHashElementArray<Element>::InitCheck() const
{
return fData;
}
template<class Element>
Element &
OpenHashElementArray<Element>::At(int32 index)
{
ASSERT(index < fSize);
return fData[index];
}
template<class Element>
const Element &
OpenHashElementArray<Element>::At(int32 index) const
{
ASSERT(index < fSize);
return fData[index];
}
template<class Element>
int32
OpenHashElementArray<Element>::IndexOf(const Element &element) const
{
int32 result = &element - fData;
if (result < 0 || result > fSize)
return -1;
return result;
}
template<class Element>
int32
OpenHashElementArray<Element>::Size() const
{
return fSize;
}
template<class Element>
Element *
OpenHashElementArray<Element>::Add(const Element &newElement)
{
Element *element = Add();
if (element)
element.Adopt(newElement);
return element;
}
#if DEBUG
const int32 kGrowChunk = 10;
#else
const int32 kGrowChunk = 1024;
#endif
template<class Element>
Element *
OpenHashElementArray<Element>::Add()
{
int32 index = fNextFree;
if (fNextDeleted >= 0) {
index = fNextDeleted;
fNextDeleted = At(index).fNext;
} else if (fNextFree >= fSize - 1) {
int32 newSize = fSize + kGrowChunk;
/*
Element *newData = (Element *)calloc((size_t)newSize , sizeof(Element));
if (!newData)
return NULL;
memcpy(newData, fData, fSize * sizeof(Element));
free(fData);
*/
Element *newData = (Element*)realloc(fData,
(size_t)newSize * sizeof(Element));
if (!newData)
return NULL;
fData = newData;
fSize = newSize;
index = fNextFree;
fNextFree++;
} else
fNextFree++;
new (&At(index)) Element;
// call placement new to initialize the element properly
ASSERT(At(index).fNext == -1);
return &At(index);
}
template<class Element>
void
OpenHashElementArray<Element>::Remove(int32 index)
{
// delete by chaining empty elements in a single linked
// list, reusing the next field
ASSERT(index < fSize);
At(index).~Element();
// call the destructor explicitly to destroy the element
// properly
At(index).fNext = fNextDeleted;
fNextDeleted = index;
}
//} // namespace BPrivate
//using namespace BPrivate;
#endif
@@ -0,0 +1,118 @@
// Referencable.h
#ifndef USERLAND_FS_REFERENCABLE_H
#define USERLAND_FS_REFERENCABLE_H
#include <SupportDefs.h>
#include "ObjectTracker.h"
namespace UserlandFSUtil {
// Referencable
class Referencable ONLY_OBJECT_TRACKABLE_BASE_CLASS {
public:
Referencable(
bool deleteWhenUnreferenced = false);
virtual ~Referencable();
void AddReference();
bool RemoveReference(); // returns true after last
int32 CountReferences() const;
protected:
vint32 fReferenceCount;
bool fDeleteWhenUnreferenced;
};
// Reference
template<typename Type>
class Reference {
public:
Reference()
: fObject(NULL)
{
}
Reference(Type* object, bool alreadyHasReference = false)
: fObject(NULL)
{
SetTo(object, alreadyHasReference);
}
Reference(const Reference<Type>& other)
: fObject(NULL)
{
SetTo(other.fObject);
}
~Reference()
{
Unset();
}
void SetTo(Type* object, bool alreadyHasReference = false)
{
Unset();
fObject = object;
if (fObject && !alreadyHasReference)
fObject->AddReference();
}
void Unset()
{
if (fObject) {
fObject->RemoveReference();
fObject = NULL;
}
}
Type* Get() const
{
return fObject;
}
Type* Detach()
{
Type* object = fObject;
fObject = NULL;
return object;
}
Type& operator*() const
{
return *fObject;
}
Type* operator->() const
{
return fObject;
}
Reference& operator=(const Reference<Type>& other)
{
SetTo(other.fObject);
return *this;
}
bool operator==(const Reference<Type>& other) const
{
return (fObject == other.fObject);
}
bool operator!=(const Reference<Type>& other) const
{
return (fObject != other.fObject);
}
private:
Type* fObject;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::Referencable;
using UserlandFSUtil::Reference;
#endif // USERLAND_FS_REFERENCABLE_H
+332
View File
@@ -0,0 +1,332 @@
// SLList.h
#ifndef SL_LIST_H
#define SL_LIST_H
#include <SupportDefs.h>
namespace UserlandFSUtil {
// SLListLink
template<typename Element>
class SLListLink {
public:
SLListLink() : next(NULL) {}
~SLListLink() {}
Element *next;
};
// SLListLinkImpl
template<typename Element>
class SLListLinkImpl {
private:
typedef SLListLink<Element> Link;
public:
SLListLinkImpl() : fSLListLink() {}
~SLListLinkImpl() {}
Link *GetSLListLink() { return &fSLListLink; }
const Link *GetSLListLink() const { return &fSLListLink; }
private:
Link fSLListLink;
};
// SLListStandardGetLink
template<typename Element>
class SLListStandardGetLink {
private:
typedef SLListLink<Element> Link;
public:
inline Link *operator()(Element *element) const
{
return element->GetSLListLink();
}
inline const Link *operator()(const Element *element) const
{
return element->GetSLListLink();
}
};
// for convenience
#define SL_LIST_TEMPLATE_LIST template<typename Element, typename GetLink>
#define SL_LIST_CLASS_NAME SLList<Element, GetLink>
// SLList
template<typename Element, typename GetLink = SLListStandardGetLink<Element> >
class SLList {
private:
typedef SLList<Element, GetLink> List;
typedef SLListLink<Element> Link;
public:
class Iterator {
public:
Iterator(List *list)
: fList(list),
fPrevious(NULL),
fCurrent(NULL),
fNext(fList->GetFirst())
{
}
Iterator(const Iterator &other)
{
*this = other;
}
bool HasNext() const
{
return fNext;
}
Element *Next()
{
if (fCurrent)
fPrevious = fCurrent;
fCurrent = fNext;
if (fNext)
fNext = fList->GetNext(fNext);
return fCurrent;
}
Element *Remove()
{
Element *element = fCurrent;
if (fCurrent) {
fList->_Remove(fPrevious, fCurrent);
fCurrent = NULL;
}
return element;
}
Iterator &operator=(const Iterator &other)
{
fList = other.fList;
fPrevious = other.fPrevious;
fCurrent = other.fCurrent;
fNext = other.fNext;
return *this;
}
private:
List *fList;
Element *fPrevious;
Element *fCurrent;
Element *fNext;
};
class ConstIterator {
public:
ConstIterator(const List *list)
: fList(list),
fNext(list->GetFirst())
{
}
ConstIterator(const ConstIterator &other)
{
*this = other;
}
bool HasNext() const
{
return fNext;
}
Element *Next()
{
Element *element = fNext;
if (fNext)
fNext = fList->GetNext(fNext);
return element;
}
ConstIterator &operator=(const ConstIterator &other)
{
fList = other.fList;
fNext = other.fNext;
return *this;
}
private:
const List *fList;
Element *fNext;
};
public:
SLList() : fFirst(NULL), fLast(NULL) {}
SLList(const GetLink &getLink)
: fFirst(NULL), fLast(NULL), fGetLink(getLink) {}
~SLList() {}
inline bool IsEmpty() const { return (fFirst == NULL); }
inline void Insert(Element *element, bool back = true);
inline void InsertAfter(Element *previous, Element *element);
inline void Remove(Element *element);
// O(n)!
inline void MoveFrom(SL_LIST_CLASS_NAME *fromList);
inline void RemoveAll();
inline Element *GetFirst() const { return fFirst; }
inline Element *GetLast() const { return fLast; }
inline Element *GetHead() const { return fFirst; }
inline Element *GetTail() const { return fLast; }
inline Element *GetNext(Element *element) const;
inline int32 Size() const;
// O(n)!
inline Iterator GetIterator() { return Iterator(this); }
inline ConstIterator GetIterator() const { return ConstIterator(this); }
private:
friend class Iterator;
inline void _Remove(Element *previous, Element *element);
private:
Element *fFirst;
Element *fLast;
GetLink fGetLink;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::SLList;
using UserlandFSUtil::SLListLink;
using UserlandFSUtil::SLListLinkImpl;
// inline methods
// Insert
SL_LIST_TEMPLATE_LIST
void
SL_LIST_CLASS_NAME::Insert(Element *element, bool back)
{
InsertAfter((back ? fLast : NULL), element);
}
// InsertAfter
SL_LIST_TEMPLATE_LIST
void
SL_LIST_CLASS_NAME::InsertAfter(Element *previous, Element *element)
{
if (element) {
Link *elLink = fGetLink(element);
if (previous) {
// insert after previous element
Link *prevLink = fGetLink(previous);
elLink->next = prevLink->next;
prevLink->next = element;
} else {
// no previous element given: prepend
elLink->next = fFirst;
fFirst = element;
}
// element may be new last element
if (fLast == previous)
fLast = element;
}
}
// Remove
SL_LIST_TEMPLATE_LIST
void
SL_LIST_CLASS_NAME::Remove(Element *element)
{
if (!element)
return;
for (Iterator it = GetIterator(); it.HasNext();) {
if (element == it.Next()) {
it.Remove();
return;
}
}
}
// MoveFrom
SL_LIST_TEMPLATE_LIST
void
SL_LIST_CLASS_NAME::MoveFrom(SL_LIST_CLASS_NAME *fromList)
{
if (fromList && fromList->fFirst) {
if (fFirst) {
fGetLink(fLast)->next = fromList->fFirst;
fLast = fromList->fLast;
} else {
fFirst = fromList->fFirst;
fLast = fromList->fLast;
}
fromList->fFirst = NULL;
fromList->fLast = NULL;
}
}
// RemoveAll
SL_LIST_TEMPLATE_LIST
void
SL_LIST_CLASS_NAME::RemoveAll()
{
Element *element = fFirst;
while (element) {
Link *elLink = fGetLink(element);
element = elLink->next;
elLink->next = NULL;
}
fFirst = NULL;
fLast = NULL;
}
// GetNext
SL_LIST_TEMPLATE_LIST
Element *
SL_LIST_CLASS_NAME::GetNext(Element *element) const
{
return (element ? fGetLink(element)->next : NULL);
}
// _Remove
SL_LIST_TEMPLATE_LIST
void
SL_LIST_CLASS_NAME::_Remove(Element *previous, Element *element)
{
Link *elLink = fGetLink(element);
if (previous)
fGetLink(previous)->next = elLink->next;
else
fFirst = elLink->next;
if (element == fLast)
fLast = previous;
elLink->next = NULL;
}
// Size
SL_LIST_TEMPLATE_LIST
int32
SL_LIST_CLASS_NAME::Size() const
{
int32 count = 0;
for (Element* element = GetFirst(); element; element = GetNext(element))
count++;
return count;
}
#endif // SL_LIST_H
@@ -0,0 +1,70 @@
// String.h
#ifndef STRING_H
#define STRING_H
#include <string.h>
#include <SupportDefs.h>
// string_hash
//
// from the Dragon Book: a slightly modified hashpjw()
static inline
uint32
string_hash(const char *name)
{
uint32 h = 0;
if (name) {
for (; *name; name++) {
uint32 g = h & 0xf0000000;
if (g)
h ^= g >> 24;
h = (h << 4) + *name;
}
}
return h;
}
#ifdef __cplusplus
namespace UserlandFSUtil {
// String
class String {
public:
String();
String(const String &string);
String(const char *string, int32 length = -1);
~String();
bool SetTo(const char *string, int32 maxLength = -1);
void Unset();
void Truncate(int32 newLength);
const char *GetString() const;
int32 GetLength() const { return fLength; }
uint32 GetHashCode() const { return string_hash(GetString()); }
String &operator=(const String &string);
bool operator==(const String &string) const;
bool operator!=(const String &string) const { return !(*this == string); }
private:
bool _SetTo(const char *string, int32 length);
private:
int32 fLength;
char *fString;
};
} // namespace UserlandFSUtil
using UserlandFSUtil::String;
#endif // __cplusplus
#endif // STRING_H
+798
View File
@@ -0,0 +1,798 @@
// Vector.h
//
// Copyright (c) 2003, Ingo Weinhold ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef _VECTOR_H
#define _VECTOR_H
#include <new>
#include <stdlib.h>
#include <string.h>
#include <SupportDefs.h>
template<typename Value> class VectorIterator;
// for convenience
#define _VECTOR_TEMPLATE_LIST template<typename Value>
#define _VECTOR_CLASS_NAME Vector<Value>
/*!
\class Vector
\brief A generic vector implementation.
*/
template<typename Value>
class Vector {
public:
typedef VectorIterator<Value> Iterator;
typedef VectorIterator<const Value> ConstIterator;
private:
static const size_t kDefaultChunkSize = 10;
static const size_t kMaximalChunkSize = 1024 * 1024;
public:
Vector(size_t chunkSize = kDefaultChunkSize);
~Vector();
status_t PushFront(const Value &value);
status_t PushBack(const Value &value);
void PopFront();
void PopBack();
status_t Insert(const Value &value, int32 index);
status_t Insert(const Value &value, const Iterator &iterator);
int32 Remove(const Value &value);
Iterator Erase(int32 index);
Iterator Erase(const Iterator &iterator);
inline int32 Count() const;
inline bool IsEmpty() const;
void MakeEmpty();
inline Iterator Begin();
inline ConstIterator Begin() const;
inline Iterator End();
inline ConstIterator End() const;
inline Iterator Null();
inline ConstIterator Null() const;
inline Iterator IteratorForIndex(int32 index);
inline ConstIterator IteratorForIndex(int32 index) const;
inline const Value &ElementAt(int32 index) const;
inline Value &ElementAt(int32 index);
int32 IndexOf(const Value &value, int32 start = 0) const;
Iterator Find(const Value &value);
Iterator Find(const Value &value, const Iterator &start);
ConstIterator Find(const Value &value) const;
ConstIterator Find(const Value &value, const ConstIterator &start) const;
inline Value &operator[](int32 index);
inline const Value &operator[](int32 index) const;
// debugging
int32 GetCapacity() const { return fCapacity; }
private:
inline static void _MoveItems(Value *values, int32 offset, int32 count);
bool _Resize(size_t count);
inline int32 _IteratorIndex(const Iterator &iterator) const;
inline int32 _IteratorIndex(const ConstIterator &iterator) const;
private:
size_t fCapacity;
size_t fChunkSize;
int32 fItemCount;
Value *fItems;
};
// VectorIterator
template<typename Value>
class VectorIterator {
private:
typedef VectorIterator<Value> Iterator;
public:
inline VectorIterator<Value>()
: fElement(NULL)
{
}
inline VectorIterator<Value>(const Iterator &other)
: fElement(other.fElement)
{
}
inline Iterator &operator++()
{
if (fElement)
++fElement;
return *this;
}
inline Iterator operator++(int)
{
Iterator it(*this);
++*this;
return it;
}
inline Iterator &operator--()
{
if (fElement)
--fElement;
return *this;
}
inline Iterator operator--(int)
{
Iterator it(*this);
--*this;
return it;
}
inline Iterator &operator=(const Iterator &other)
{
fElement = other.fElement;
return *this;
}
inline bool operator==(const Iterator &other) const
{
return (fElement == other.fElement);
}
inline bool operator!=(const Iterator &other) const
{
return !(*this == other);
}
inline Value &operator*() const
{
return *fElement;
}
inline Value *operator->() const
{
return fElement;
}
inline operator bool() const
{
return fElement;
}
// private
public:
inline VectorIterator<Value>(Value *element)
: fElement(element)
{
}
inline Value *Element() const
{
return fElement;
}
protected:
Value *fElement;
};
// Vector
// constructor
/*! \brief Creates an empty vector.
\param chunkSize The granularity for the vector's capacity, i.e. the
minimal number of elements the capacity grows or shrinks when
necessary.
*/
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::Vector(size_t chunkSize)
: fCapacity(0),
fChunkSize(chunkSize),
fItemCount(0),
fItems(NULL)
{
if (fChunkSize == 0 || fChunkSize > kMaximalChunkSize)
fChunkSize = kDefaultChunkSize;
_Resize(0);
}
// destructor
/*! \brief Frees all resources associated with the object.
The contained elements are destroyed. Note, that, if the element
type is a pointer type, only the pointer is destroyed, not the object
it points to.
*/
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::~Vector()
{
MakeEmpty();
free(fItems);
}
// PushFront
/*! \brief Inserts a copy of the supplied value at the beginning of the
vector.
\param value The element to be inserted.
\return
- \c B_OK: Everything went fine.
- \c B_NO_MEMORY: Insufficient memory for this operation.
*/
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::PushFront(const Value &value)
{
return Insert(value, 0);
}
// PushBack
/*! \brief Inserts a copy of the supplied value at the end of the vector.
\param value The element to be inserted.
\return
- \c B_OK: Everything went fine.
- \c B_NO_MEMORY: Insufficient memory for this operation.
*/
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::PushBack(const Value &value)
{
return Insert(value, fItemCount);
}
// PopFront
/*! \brief Removes the first element of the vector.
Invocation on an empty vector is harmless.
*/
_VECTOR_TEMPLATE_LIST
void
_VECTOR_CLASS_NAME::PopFront()
{
if (fItemCount > 0)
Erase(0);
}
// PopBack
/*! \brief Removes the last element of the vector.
Invocation on an empty vector is harmless.
*/
_VECTOR_TEMPLATE_LIST
void
_VECTOR_CLASS_NAME::PopBack()
{
if (fItemCount > 0)
Erase(fItemCount - 1);
}
// _MoveItems
/*! \brief Moves elements within an array.
\param items The elements to be moved.
\param offset The index to which the elements shall be moved. May be
negative.
\param count The number of elements to be moved.
*/
_VECTOR_TEMPLATE_LIST
inline
void
_VECTOR_CLASS_NAME::_MoveItems(Value* items, int32 offset, int32 count)
{
if (count > 0 && offset != 0)
memmove(items + offset, items, count * sizeof(Value));
}
// Insert
/*! \brief Inserts a copy of the the supplied value at the given index.
\param value The value to be inserted.
\param index The index at which to insert the new element. It must
hold: 0 <= \a index <= Count().
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \a index is out of range.
- \c B_NO_MEMORY: Insufficient memory for this operation.
*/
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::Insert(const Value &value, int32 index)
{
if (index < 0 || index > fItemCount)
return B_BAD_VALUE;
if (!_Resize(fItemCount + 1))
return B_NO_MEMORY;
_MoveItems(fItems + index, 1, fItemCount - index - 1);
new(fItems + index) Value(value);
return B_OK;
}
// Insert
/*! \brief Inserts a copy of the the supplied value at the given position.
\param value The value to be inserted.
\param iterator An iterator specifying the position at which to insert
the new element.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \a iterator is is invalid.
- \c B_NO_MEMORY: Insufficient memory for this operation.
*/
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::Insert(const Value &value, const Iterator &iterator)
{
int32 index = _IteratorIndex(iterator);
if (index >= 0)
return Insert(value, index);
return B_BAD_VALUE;
}
// Remove
/*! \brief Removes all elements of the supplied value.
\param value The value of the elements to be removed.
\return The number of removed occurrences.
*/
_VECTOR_TEMPLATE_LIST
int32
_VECTOR_CLASS_NAME::Remove(const Value &value)
{
int32 count = 0;
for (int32 i = fItemCount - 1; i >= 0; i--) {
if (ElementAt(i) == value) {
Erase(i);
count++;
}
}
return count;
}
// Erase
/*! \brief Removes the element at the given index.
\param index The position of the element to be removed.
\return An iterator referring to the element now being located at index
\a index (End(), if it was the last element that has been
removed), or Null(), if \a index was out of range.
*/
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::Erase(int32 index)
{
if (index >= 0 && index < fItemCount) {
fItems[index].~Value();
_MoveItems(fItems + index + 1, -1, fItemCount - index - 1);
_Resize(fItemCount - 1);
return Iterator(fItems + index);
}
return Null();
}
// Erase
/*! \brief Removes the element at the given position.
\param iterator An iterator referring to the element to be removed.
\return An iterator referring to the element succeeding the removed
one (End(), if it was the last element that has been
removed), or Null(), if \a iterator was an invalid iterator
(in this case including End()).
*/
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::Erase(const Iterator &iterator)
{
int32 index = _IteratorIndex(iterator);
if (index >= 0 && index < fItemCount)
return Erase(index);
return Null();
}
// Count
/*! \brief Returns the number of elements the vector contains.
\return The number of elements the vector contains.
*/
_VECTOR_TEMPLATE_LIST
inline
int32
_VECTOR_CLASS_NAME::Count() const
{
return fItemCount;
}
// IsEmpty
/*! \brief Returns whether the vector is empty.
\return \c true, if the vector is empty, \c false otherwise.
*/
_VECTOR_TEMPLATE_LIST
inline
bool
_VECTOR_CLASS_NAME::IsEmpty() const
{
return (fItemCount == 0);
}
// MakeEmpty
/*! \brief Removes all elements from the vector.
*/
_VECTOR_TEMPLATE_LIST
void
_VECTOR_CLASS_NAME::MakeEmpty()
{
for (int32 i = 0; i < fItemCount; i++)
fItems[i].~Value();
_Resize(0);
}
// Begin
/*! \brief Returns an iterator referring to the beginning of the vector.
If the vector is not empty, Begin() refers to its first element,
otherwise it is equal to End() and must not be dereferenced!
\return An iterator referring to the beginning of the vector.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::Begin()
{
return Iterator(fItems);
}
// Begin
/*! \brief Returns an iterator referring to the beginning of the vector.
If the vector is not empty, Begin() refers to its first element,
otherwise it is equal to End() and must not be dereferenced!
\return An iterator referring to the beginning of the vector.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::ConstIterator
_VECTOR_CLASS_NAME::Begin() const
{
return ConstIterator(fItems);
}
// End
/*! \brief Returns an iterator referring to the end of the vector.
The position identified by End() is the one succeeding the last
element, i.e. it must not be dereferenced!
\return An iterator referring to the end of the vector.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::End()
{
return Iterator(fItems + fItemCount);
}
// End
/*! \brief Returns an iterator referring to the end of the vector.
The position identified by End() is the one succeeding the last
element, i.e. it must not be dereferenced!
\return An iterator referring to the end of the vector.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::ConstIterator
_VECTOR_CLASS_NAME::End() const
{
return ConstIterator(fItems + fItemCount);
}
// Null
/*! \brief Returns an invalid iterator.
Null() is used as a return value, if something went wrong. It must
neither be incremented or decremented nor dereferenced!
\return An invalid iterator.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::Null()
{
return Iterator(NULL);
}
// Null
/*! \brief Returns an invalid iterator.
Null() is used as a return value, if something went wrong. It must
neither be incremented or decremented nor dereferenced!
\return An invalid iterator.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::ConstIterator
_VECTOR_CLASS_NAME::Null() const
{
return ConstIterator(NULL);
}
// IteratorForIndex
/*! \brief Returns an iterator for a given index.
\return An iterator referring to the same element as \a index, or
End(), if \a index is out of range.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::IteratorForIndex(int32 index)
{
if (index >= 0 && index <= fItemCount)
return Iterator(fItems + index);
return End();
}
// IteratorForIndex
/*! \brief Returns an iterator for a given index.
\return An iterator referring to the same element as \a index, or
End(), if \a index is out of range.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::ConstIterator
_VECTOR_CLASS_NAME::IteratorForIndex(int32 index) const
{
if (index >= 0 && index <= fItemCount)
return ConstIterator(fItems + index);
return End();
}
// ElementAt
/*! \brief Returns the element at a given index.
\param index The index identifying the element to be returned.
\return The element identified by the given index.
*/
_VECTOR_TEMPLATE_LIST
inline
const Value &
_VECTOR_CLASS_NAME::ElementAt(int32 index) const
{
if (index >= 0 && index < fItemCount)
return fItems[index];
// Return the 0th element by default. Unless the allocation failed, there
// is always a 0th element -- uninitialized perhaps.
return fItems[0];
}
// ElementAt
/*! \brief Returns the element at a given index.
\param index The index identifying the element to be returned.
\return The element identified by the given index.
*/
_VECTOR_TEMPLATE_LIST
inline
Value &
_VECTOR_CLASS_NAME::ElementAt(int32 index)
{
if (index >= 0 && index < fItemCount)
return fItems[index];
// Return the 0th element by default. Unless the allocation failed, there
// is always a 0th element -- uninitialized perhaps.
return fItems[0];
}
// IndexOf
/*! \brief Returns the index of the next element with the specified value.
\param value The value of the element to be found.
\param start The index at which to be started to search for the element.
\return The index of the found element, or \c -1, if no further element
with the given value could be found or \a index is out of range.
*/
_VECTOR_TEMPLATE_LIST
int32
_VECTOR_CLASS_NAME::IndexOf(const Value &value, int32 start) const
{
if (start >= 0) {
for (int32 i = start; i < fItemCount; i++) {
if (fItems[i] == value)
return i;
}
}
return -1;
}
// Find
/*! \brief Returns an iterator referring to the next element with the
specified value.
\param value The value of the element to be found.
\return An iterator referring to the found element, or End(), if no
further with the given value could be found.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::Find(const Value &value)
{
return Find(value, Begin());
}
// Find
/*! \brief Returns an iterator referring to the next element with the
specified value.
\param value The value of the element to be found.
\param start And iterator specifying where to start searching for the
element.
\return An iterator referring to the found element, or End(), if no
further with the given value could be found or \a start was
invalid.
*/
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::Iterator
_VECTOR_CLASS_NAME::Find(const Value &value, const Iterator &start)
{
int32 index = IndexOf(value, _IteratorIndex(start));
if (index >= 0)
return Iterator(fItems + index);
return End();
}
// Find
/*! \brief Returns an iterator referring to the of the next element with the
specified value.
\param value The value of the element to be found.
\return An iterator referring to the found element, or End(), if no
further with the given value could be found.
*/
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_NAME::ConstIterator
_VECTOR_CLASS_NAME::Find(const Value &value) const
{
return Find(value, Begin());
}
// Find
/*! \brief Returns an iterator referring to the of the next element with the
specified value.
\param value The value of the element to be found.
\param start And iterator specifying where to start searching for the
element.
\return An iterator referring to the found element, or End(), if no
further with the given value could be found or \a start was
invalid.
*/
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::ConstIterator
_VECTOR_CLASS_NAME::Find(const Value &value, const ConstIterator &start) const
{
int32 index = IndexOf(value, _IteratorIndex(start));
if (index >= 0)
return ConstIterator(fItems + index);
return End();
}
// []
/*! \brief Semantically equivalent to ElementAt().
*/
_VECTOR_TEMPLATE_LIST
inline
Value &
_VECTOR_CLASS_NAME::operator[](int32 index)
{
return ElementAt(index);
}
// []
/*! \brief Semantically equivalent to ElementAt().
*/
_VECTOR_TEMPLATE_LIST
inline
const Value &
_VECTOR_CLASS_NAME::operator[](int32 index) const
{
return ElementAt(index);
}
// _Resize
/*! \brief Resizes the vector.
The internal element array will be grown or shrunk to the next multiple
of \a fChunkSize >= \a count, but no less than \a fChunkSize.
Also adjusts \a fItemCount according to the supplied \a count, but does
not invoke a destructor or constructor on any element.
\param count The number of element.
\return \c true, if everything went fine, \c false, if the memory
allocation failed.
*/
_VECTOR_TEMPLATE_LIST
bool
_VECTOR_CLASS_NAME::_Resize(size_t count)
{
bool result = true;
// calculate the new capacity
int32 newSize = count;
if (newSize <= 0)
newSize = 1;
newSize = ((newSize - 1) / fChunkSize + 1) * fChunkSize;
// resize if necessary
if ((size_t)newSize != fCapacity) {
Value* newItems = (Value*)realloc(fItems, newSize * sizeof(Value));
if (newItems) {
fItems = newItems;
fCapacity = newSize;
} else
result = false;
}
if (result)
fItemCount = count;
return result;
}
// _IteratorIndex
/*! \brief Returns index of the element the supplied iterator refers to.
\return The index of the element the supplied iterator refers to, or
\c -1, if the iterator is invalid (End() is considered valid
here, and Count() is returned).
*/
_VECTOR_TEMPLATE_LIST
inline
int32
_VECTOR_CLASS_NAME::_IteratorIndex(const Iterator &iterator) const
{
if (iterator.Element()) {
int32 index = iterator.Element() - fItems;
if (index >= 0 && index <= fItemCount)
return index;
}
return -1;
}
// _IteratorIndex
/*! \brief Returns index of the element the supplied iterator refers to.
\return The index of the element the supplied iterator refers to, or
\c -1, if the iterator is invalid (End() is considered valid
here, and Count() is returned).
*/
_VECTOR_TEMPLATE_LIST
inline
int32
_VECTOR_CLASS_NAME::_IteratorIndex(const ConstIterator &iterator) const
{
if (iterator.Element()) {
int32 index = iterator.Element() - fItems;
if (index >= 0 && index <= fItemCount)
return index;
}
return -1;
}
#endif // _VECTOR_H