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:
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user