⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wipdb.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			OSConnectorFree(currentElement->data.s);
	}
	OSConnectorFree(currentElement);
}



#define DB_DUPLICATE_STR(s) {UINT8 error; db_duplicateStrMem(s, DB_flag_str, &error;}
#define DB_DUPLICATE_MEM(s) {UINT8 error; db_duplicateStrMem(s, DB_flag_mem, &error;}
/*
 * Copy a string or memory block.
 */
static BYTE* 
db_duplicateStrMem (BYTE* s, UINT16 type, UINT8 *errorCode)
{
	BYTE*  temp;
	size_t len;

	if (type == DB_flag_str) /* str */
		len = strlen((char*) s) + 1;
	else /* mem */
		len = *(UINT16*) s;

	temp = (BYTE*) OSConnectorAlloc(len);
	#ifndef HAS_SETJMP
	/* NOTE: if this paragraph is removed, also remove the 'errorCode' parameter and change macros! */
	if (temp == NULL) {
		*errorCode = DB_err_outOfMemory;
		return NULL;
	}
	#endif
	memcpy(temp, s, len);

	*errorCode = DB_err_success;
	return temp;
}



/*
 * Create a null-terminated string by allocating new memory and
 * copying 'length' characters from 'p'.
 */
BYTE* db_createStr(const char* p, UINT16 length) {
	BYTE* ptr = NULL;

	if (length > 0 && p != NULL) {
		ptr = (BYTE*) OSConnectorAlloc(length + 1);
		if (ptr) {
			memcpy(ptr, p, length);
			ptr[length] = '\0';
		}
	}
	return ptr;
}



/*
 * Create a memory block by allocating new memory and
 * copying 'length' characters from 'p'.
 */
BYTE* db_createMem(const char* p, UINT16 length) {
	BYTE* ptr = NULL;

	if (length > 0 && p != NULL) {
		ptr = (BYTE*) OSConnectorAlloc(length + sizeof(UINT16));
		if (ptr) {
			memcpy(ptr + sizeof(UINT16), p, length);
			*(UINT16*) ptr = length + sizeof(UINT16);
		}
	}
	return ptr;
}



/*
 * Update nextId field in persistent memory. Do not use ';'
 * after macro;
 *
 * ElementPtr element
 * UINT32     nextId
 */
#define DB_SET_NEXT_ID(element, nextId) \
{UINT32 temp = (nextId); Storage_Put(&store, db_getBlockId(element), 0, 4, &temp);}



/*
 * Update childId field in persistent memory. Do not use ';'
 * after macro;
 *
 * UINT32 id
 * UINT32 nextId
 */
#define DB_SET_CHILD_ID(id, nextId) \
{UINT32 temp = (nextId); Storage_Put(&store, (id), 4, 4, &temp);}



/*
 * Search through idArr and sets the MSB of the element equal
 * to 'id'. Only used at startup by the write-through functions.
 */
static void 
db_markId (UINT32 id)
{
	UINT32* p;

	for (p=idArr; *p != id; p++)
		;
	*p |= 0x80000000;
}



/* ======== get ======== */



/*
 * Return data from element. The element pointed out by 'record'
 * and 'key' must be of the of the same type as 'type' indicates,
 * with one exception:  it is legal to get a pointer from a 
 * string or memory block.
 *
 * If 'del' is true, the element is deleted and so is its data
 * with a few exceptions. Deleting a pointer element does not delete
 * its data. Getting a pointer from a string or memory block element 
 * and deleting it at the same time does not delete its data.
 *
 * 'type' takes the values of DB_int, DB_str, DB_mem or DB_ptr.
 */
DB_elementData 
db_getElementData (DB_ref record, const BYTE* key, BOOL del, UINT16 type, UINT8* errorCode)
{
	FieldPtr       field;
	DB_elementData temp;

	temp.i = 0;

	if (db_findRecord(record) == NULL) {
		*errorCode = DB_err_record;
		return temp;
	}
	field = db_findField(key);
	if (field == NULL) {
		*errorCode = DB_err_field;
		return temp;
	}
	
	{
	UINT16 elementType = field->flags & DB_mask_type;
	if (elementType != type && 
		!(type == DB_flag_ptr && (elementType == DB_flag_str || elementType == DB_flag_mem))) {
		*errorCode = DB_err_wrongType;
		return temp;
	}
	}
	*errorCode = DB_err_success;

	if (del) {
		temp = *(DB_elementData*) &field->data;
		db_deleteElement(TRUE);
	} else {
		if (type == DB_flag_ptr)                               /* ptr or str/mem + db_getPtr() */
			temp.p = field->data.p;
		else if ((field->flags & DB_mask_type) == DB_flag_int) /* int */
			temp.i = field->data.i;
		else                                                   /* str, mem */
			temp.s = db_duplicateStrMem(field->data.s,
			                         (UINT16) (field->flags & DB_mask_type), errorCode);
			/* errorCode may signal and error, but may be passed on since
			 * there is no code between here and the end of the function. */
	}
	return temp;
}



/*
 * Return reference to record element.
 */
DB_ref 
db_getRef (DB_ref record, const BYTE* key, UINT8* errorCode)
{
	FieldPtr field;

	if (db_findRecord(record) == NULL) {
		*errorCode = DB_err_record;
		return DB_null;
	}
	field = db_findField(key);
	if (field == NULL) {
		*errorCode = DB_err_field;
		return DB_null;
	}
	if ((field->flags & DB_mask_dataUse) != DB_flag_dataChild) {
		*errorCode = DB_err_wrongType;
		return DB_null;
	} else {
		*errorCode = DB_err_success;
		currentRecord = (RecordPtr)field;      /* Guess the next search uses the\*/
		currentRef = ((RecordPtr)field)->ref;  /* returned ref. Cache result. */
		return currentRef;
	}
}



/*
 * Return type of element.
 */
UINT8 
db_getType (DB_ref record, const BYTE* key, UINT8* errorCode)
{
	FieldPtr field;

	if (db_findRecord(record) == NULL) {
		*errorCode = DB_err_record;
		return 0;
	}
	field = db_findField(key);
	if (field == NULL) {
		*errorCode = DB_err_field;
		return 0;
	}
	*errorCode = DB_err_success;
	return field->flags & DB_mask_type;
}





/* ======== set ======== */

/*
 * Create a new element. 'rec' is used for deciding persistent
 * state and and seting key flag. The new element is added
 * after 'prev' if 'prev' != NULL, else as first element below
 * 'rec'. If 'element' != NULL, it is updated with 'data' and
 * no new element is created. 
 */
/* BOOKMARK:FLAGS */
ElementPtr 
db_createNewElement (RecordPtr rec, const BYTE* key, UINT16 flags, DataUnion data,
                               ElementPtr prev, ElementPtr element, UINT8 *errorCode)
{
	BYTE*      s;
	int        i;

	if (rec != db_root)
		/* Inherit the parent's persistent status */
		flags = (flags & ~ DB_mask_persistent) | (rec->flags & DB_mask_persistent);

	if (flags & DB_mask_persistent && (flags & DB_mask_type) == DB_flag_ptr) {
			*errorCode = DB_err_persistentTypeError;
			return NULL;
	}

	/* Create element */
	if ((rec->flags & DB_mask_type) == DB_flag_set) { 
		/* --------------------------------------------------------  DB_flag_set */
		/* ===================================================  Create a new element */
		if (flags & DB_mask_writeThrough)
			element = (ElementPtr) OSConnectorAlloc(sizeof(ElementBlock));
		else
			element = (ElementPtr) OSConnectorAlloc(sizeof(Element));
		#ifndef HAS_SETJMP
		if (element == NULL) {
			*errorCode = DB_err_outOfMemory;
			return NULL;
		}
		#endif
		element->flags = 0; /* clear DB_flag_key */

	} else {  
		/* --------------------------------------------------------  DB_flag_rec */
		if (key == NULL) {
			*errorCode = DB_err_nullValue;
			return NULL;
		}
		
		if (element != NULL) { /* ============================  Update existing element */
			if ((element->flags & DB_mask_type) != (flags & DB_mask_type)) {
				*errorCode = DB_err_wrongType;
				return NULL;
			} else {
				if ((flags & DB_mask_dataUse) == DB_flag_dataExternal)
					OSConnectorFree(element->data.s);
				element->data = data;
				if (flags & DB_mask_writeThrough)
					if (! db_saveElement_wt(rec, element, prev))
						/* No persistent save, set warning. Return value still valid. */
						*errorCode = DB_err_noPersistentSave;
				return element;
			}
		
		} else { /* ==========================================  Create a new element */
			if (flags & DB_mask_writeThrough)
				element = (ElementPtr) OSConnectorAlloc(sizeof(FieldBlock));
			else
				element = (ElementPtr) OSConnectorAlloc(sizeof(Field));
			#ifndef HAS_SETJMP
			if (element == NULL) {
				*errorCode = DB_err_outOfMemory;
				return NULL;
			}
			#endif
			
			/* Copy key */
			for (s=((FieldPtr)element)->key, i=1; *s = *key; s++, key++, i++)
				if (i == DB_keyLen) { /* In case of too long input keys. */
					OSConnectorFree(element);
					*errorCode = DB_err_tooLongKey;
					return NULL;
				}
			element->flags = DB_flag_key;
		}
	}

	/* Init data */
	element->flags |= flags;
	element->data   = data;

	/* Add element */
	if (prev == NULL)
		db_addBelow(rec, (ElementPtr) element);
	else
		db_addAfter(prev, (ElementPtr) element);

	/* Save element, if write-through */
	*errorCode = DB_err_success;
	if (flags & DB_mask_writeThrough && ! db_serviceMode) {
		if (element->flags & DB_mask_key)
			((FieldBlockPtr) element)->blockId = 0;
		else
			((ElementBlockPtr) element)->blockId = 0;
		if (! db_saveElement_wt(rec, element, prev))
			/* No persistent save, set warning. Return value still valid. */
			*errorCode = DB_err_noPersistentSave;
	}

	return element;
}



/*
 * Create and insert an Element or Field. If an element named
 * 'key' already exists, 'flags' must signal the same type of
 * the element. Old strings or memory blocks are freed.
 *
 * If NULL is returned, an error has occurred and its number
 * is returned in 'errorCode'.
 */
static ElementPtr 
db_setItem (DB_ref record, const BYTE* key, UINT16 flags, DataUnion data,
                      UINT8 *errorCode)
{
	ElementPtr element;
	RecordPtr  rec;

	*errorCode = DB_err_success;

	rec = db_findRecord(record);
	if (rec == NULL) { 
		*errorCode = DB_err_record;
		return NULL;
	}
	
	db_findField(key);
	element = db_createNewElement(rec, key, flags, data, NULL, currentElement, errorCode);

	return element;
}



/*
 * Update or insert an int field.
 */
UINT8 
db_setInt (DB_ref record, const BYTE* key, INT32 value)
{
	DataUnion  data;
	UINT8      error;

	data.i = value; /* BOOKMARK:FLAGS */
	db_setItem(record, key, DB_flag_int | DB_flag_dataInternal, data, &error);
	return error;
}



/*
 * Update or insert a string field. 'value' is taken over by
 * the database and is deallocated when this element is deleted.
 */
UINT8 
db_setStr (DB_ref record, const BYTE* key, BYTE* value)
{
	DataUnion  data;
	UINT8      error;

	if (value == NULL)
		return DB_err_nullValue;
	data.s = value; /* BOOKMARK:FLAGS */
	db_setItem(record, key, DB_flag_str | DB_flag_dataExternal, data, &error);
	return error;
}



/*
 * Update or insert a memory block field. 'value' is taken over by
 * the database and is deallocated when this element is deleted.
 */
UINT8 
db_setMem (DB_ref record, const BYTE* key, BYTE* value)
{
	DataUnion  data;
	UINT8      error;

	if (value == NULL)
		return DB_err_nullValue;
	data.s = value; /* BOOKMARK:FLAGS */
	db_setItem(record, key, DB_flag_mem | DB_flag_dataExternal, data, &error);
	return error;
}



/*
 * Update or insert a pointer field.
 */
UINT8 
db_setPtr (DB_ref record, const BYTE* key, void* value)
{
	DataUnion  data;
	UINT8      error;

	data.p = value; /* BOOKMARK:FLAGS */
	db_setItem(record, key, DB_flag_ptr | DB_flag_dataInternal, data, &error);
	return error;
}



/* ======== structural operations ======== */


/*
 * Create a new record.
 *
 * The only bits of 'flags' used are the persistent flags and
 * DB_flag_rec/DB_flag_set.
 */
static RecordPtr 
db_createNewRecord (RecordPtr rec, const BYTE* key, UINT16 flags, ElementPtr prev,
                    UINT8 *errorCode)
{
	RecordPtr  newRec;
	BYTE*      s;
	int        len;

  if (rec == db_root) {
		if (flags & DB_mask_writeThrough)
			/* Write-through and backup cannot be active at the same time */
			flags &= ~DB_flag_backup;
	} else
		/* Inherit the parent's persistent status */
		flags = flags & ~ DB_mask_persistent | rec->flags & DB_mask_persistent;

	/* Create record */
	if (flags & DB_mask_writeThrough)
		newRec = (RecordPtr) OSConnectorAlloc(sizeof(RecordBlock)); 
	else
		newRec = (RecordPtr) OSConnectorAlloc(sizeof(Record)); 
	#ifndef HAS_SETJMP
	if (newRec == NULL) {
		*errorCode = DB_err_outOfMemory;
		return NULL;
	}
	#endif
	
	/* Copy key */
	for (s=newRec->key, len=1; *s = *key; s++, key++, len++) 
		if (len == DB_keyLen) {
			OSConnectorFree(newRec);
			*errorCode = DB_err_tooLongKey;
			return NULL;
		}

	/* Init data */
	newRec->data.r = newRec; 	
	newRec->flags = flags & DB_mask_persistent;
	if ((flags & DB_mask_type) == DB_flag_rec)  /* BOOKMARK:FLAGS */
		newRec->flags |= DB_flag_rec | DB_flag_key | DB_flag_dataChild; /* rec */
	else
		newRec->flags |= DB_flag_set | DB_flag_key | DB_flag_dataChild; /* set */
	newRec->ref     = ++recordNbr;
	
	/* Add element */
	newRec->nextRec = refHashTable[recordNbr & DB_refHashMask];
	refHashTable[recordNbr & DB_refHashMask] = newRec;

	if (prev == NULL)
		db_addBelow(rec, (ElementPtr) newRec);
	else
		db_addAfter(prev, (ElementPtr) newRec);

	/* Save element, if write-through */
	*errorCode = DB_err_success;
	if (flags & DB_mask_writeThrough && ! db_serviceMode) {
		((RecordBlockPtr) newRec)->blockId = 0;
		if (! db_saveElement_wt(rec, (ElementPtr) newRec, prev))
			/* No persistent save, set warning. Anyway, the record was created. */
			*errorCode = DB_err_noPersistentSave;			
	}

	return newRec;
}



/*
 * Create a new record. If a field with the same name exists, an
 * error will be generated, except when the parent record is a
 * set. If 'flags' bit 0 is set, it signals this is a set, not a
 * record. This can be done by using paramater DB_set instead of
 * DB_rec for record.
 *
 * 'errorCode' returns the status of the function. DB_err_success
 * when the operation i successfully completed.
 *
 * If 'key' is NULL, the key of the new record will be an empty
 * string.
 */
DB_ref 
db_createRecord (DB_ref record, const BYTE* key, UINT16 flags, UINT8 *errorCode)
{
	RecordPtr newRec;
	RecordPtr rec;

	if (recordNbr == DB_max) { 
		*errorCode = DB_err_outOfRefs;
		return DB_null;
	}

	rec = db_findRecord(record);
	if (rec == NULL) { 
		*errorCode = DB_err_record;
		return DB_null;
	} 
	if ((rec->flags & DB_mask_type) == DB_flag_rec && db_findField(key)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -