Esempio n. 1
0
LEAFTYPE
radix_get(struct ROOTSTRUCT * tree, LEAFTYPE leaf, EXTRA_ARG aux) {
    LEAFTYPE result;
    struct _internal_node * node;
    uint32_t dir;

    if (tree->leafcount == 0) return NO_LEAF;
    if (tree->leafcount == 1) {
        result = tree->root.leaf;
        if (COMPARE(result, leaf) == -1) return result;
        else return NO_LEAF;
    } /* root points to a node */

    node = tree->root.node;
    while (1) {
        dir = DECIDE(leaf, node->critbit, aux);
        if (IS_LEAF(node, dir)) {
            result = node->child[dir].leaf;
            break;
        } else {
            node = node->child[dir].node;
        }
    }

    if (COMPARE(result, leaf) == -1) return result;
    else return NO_LEAF;
}
Esempio n. 2
0
LEAFTYPE
radix_del(struct ROOTSTRUCT * tree, LEAFTYPE leaf, EXTRA_ARG aux) {
    LEAFTYPE result;
    struct _internal_node * node, * parent;
    uint32_t dir, dir2;

    if (tree->leafcount == 0) return NO_LEAF;
    if (tree->leafcount == 1) {
        result = tree->root.leaf;
        if (COMPARE(result, leaf) == -1) {
            tree->root.leaf = NO_LEAF;
            tree->leafcount --;
            return result;
        } else return NO_LEAF;
    } /* else */
    node = tree->root.node;
    while (1) {
        dir = DECIDE(leaf, node->critbit, aux);
        if (IS_LEAF(node, dir)) {
            result = node->child[dir].leaf;
            break;
        } else {
            node = node->child[dir].node;
        }
    }
    if (COMPARE(result, leaf) == -1) {
        parent = tree->root.node;
        while (1) {
            dir2 = DECIDE(leaf, parent->critbit, aux);
            if (parent->child[dir2].node == node) break;
            else parent = parent->child[dir2].node;
        }
        if (IS_LEAF(node, 1 - dir)) {
            parent->child[dir2].leaf = node->child[1 - dir].leaf;
            SET_LEAF(parent, dir2);
        } else {
            parent->child[dir2].node = node->child[1 - dir].node;
        }
        tree->leafcount --;
        DEALLOC(node);
        return result;
    } else return NO_LEAF;
}
Esempio n. 3
0
File: p-file.c Progetto: mbk/ren-c
*/	static REB_R File_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action)
/*
**		Internal port handler for files.
**
***********************************************************************/
{
	REBVAL *spec;
	REBVAL *path;
	REBREQ *file = 0;
	REBCNT args = 0;
	REBCNT len;
	REBOOL opened = FALSE;	// had to be opened (shortcut case)

	//Print("FILE ACTION: %r", Get_Action_Word(action));

	Validate_Port(port, action);

	*D_OUT = *D_ARG(1);

	// Validate PORT fields:
	spec = BLK_SKIP(port, STD_PORT_SPEC);
	if (!IS_OBJECT(spec)) Trap1_DEAD_END(RE_INVALID_SPEC, spec);
	path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF);
	if (!path) Trap1_DEAD_END(RE_INVALID_SPEC, spec);

	if (IS_URL(path)) path = Obj_Value(spec, STD_PORT_SPEC_HEAD_PATH);
	else if (!IS_FILE(path)) Trap1_DEAD_END(RE_INVALID_SPEC, path);

	// Get or setup internal state data:
	file = (REBREQ*)Use_Port_State(port, RDI_FILE, sizeof(*file));

	switch (action) {

	case A_READ:
		args = Find_Refines(call_, ALL_READ_REFS);

		// Handle the READ %file shortcut case:
		if (!IS_OPEN(file)) {
			REBCNT nargs = AM_OPEN_READ;
			if (args & AM_READ_SEEK) nargs |= AM_OPEN_SEEK;
			Setup_File(file, nargs, path);
			Open_File_Port(port, file, path);
			opened = TRUE;
		}

		if (args & AM_READ_SEEK) Set_Seek(file, D_ARG(ARG_READ_INDEX));
		len = Set_Length(
			file, D_REF(ARG_READ_PART) ? VAL_INT64(D_ARG(ARG_READ_LENGTH)) : -1
		);
		Read_File_Port(D_OUT, port, file, path, args, len);

		if (opened) {
			OS_DO_DEVICE(file, RDC_CLOSE);
			Cleanup_File(file);
		}

		if (file->error) Trap_Port_DEAD_END(RE_READ_ERROR, port, file->error);
		break;

	case A_APPEND:
		if (!(IS_BINARY(D_ARG(2)) || IS_STRING(D_ARG(2)) || IS_BLOCK(D_ARG(2))))
			Trap1_DEAD_END(RE_INVALID_ARG, D_ARG(2));
		file->special.file.index = file->special.file.size;
		SET_FLAG(file->modes, RFM_RESEEK);

	case A_WRITE:
		args = Find_Refines(call_, ALL_WRITE_REFS);
		spec = D_ARG(2); // data (binary, string, or block)

		// Handle the READ %file shortcut case:
		if (!IS_OPEN(file)) {
			REBCNT nargs = AM_OPEN_WRITE;
			if (args & AM_WRITE_SEEK || args & AM_WRITE_APPEND) nargs |= AM_OPEN_SEEK;
			else nargs |= AM_OPEN_NEW;
			Setup_File(file, nargs, path);
			Open_File_Port(port, file, path);
			opened = TRUE;
		}
		else {
			if (!GET_FLAG(file->modes, RFM_WRITE)) Trap1_DEAD_END(RE_READ_ONLY, path);
		}

		// Setup for /append or /seek:
		if (args & AM_WRITE_APPEND) {
			file->special.file.index = -1; // append
			SET_FLAG(file->modes, RFM_RESEEK);
		}
		if (args & AM_WRITE_SEEK) Set_Seek(file, D_ARG(ARG_WRITE_INDEX));

		// Determine length. Clip /PART to size of string if needed.
		len = VAL_LEN(spec);
		if (args & AM_WRITE_PART) {
			REBCNT n = Int32s(D_ARG(ARG_WRITE_LENGTH), 0);
			if (n <= len) len = n;
		}

		Write_File_Port(file, spec, len, args);

		if (opened) {
			OS_DO_DEVICE(file, RDC_CLOSE);
			Cleanup_File(file);
		}

		if (file->error) Trap1_DEAD_END(RE_WRITE_ERROR, path);
		break;

	case A_OPEN:
		args = Find_Refines(call_, ALL_OPEN_REFS);
		// Default file modes if not specified:
		if (!(args & (AM_OPEN_READ | AM_OPEN_WRITE))) args |= (AM_OPEN_READ | AM_OPEN_WRITE);
		Setup_File(file, args, path);
		Open_File_Port(port, file, path); // !!! needs to change file modes to R/O if necessary
		break;

	case A_COPY:
		if (!IS_OPEN(file)) Trap1_DEAD_END(RE_NOT_OPEN, path); //!!!! wrong msg
		len = Set_Length(file, D_REF(2) ? VAL_INT64(D_ARG(3)) : -1);
		Read_File_Port(D_OUT, port, file, path, args, len);
		break;

	case A_OPENQ:
		if (IS_OPEN(file)) return R_TRUE;
		return R_FALSE;

	case A_CLOSE:
		if (IS_OPEN(file)) {
			OS_DO_DEVICE(file, RDC_CLOSE);
			Cleanup_File(file);
		}
		break;

	case A_DELETE:
		if (IS_OPEN(file)) Trap1_DEAD_END(RE_NO_DELETE, path);
		Setup_File(file, 0, path);
		if (OS_DO_DEVICE(file, RDC_DELETE) < 0 ) Trap1_DEAD_END(RE_NO_DELETE, path);
		break;

	case A_RENAME:
		if (IS_OPEN(file)) Trap1_DEAD_END(RE_NO_RENAME, path);
		else {
			REBSER *target;

			Setup_File(file, 0, path);

			// Convert file name to OS format:
			if (!(target = Value_To_OS_Path(D_ARG(2), TRUE)))
				Trap1_DEAD_END(RE_BAD_FILE_PATH, D_ARG(2));
			file->common.data = BIN_DATA(target);
			OS_DO_DEVICE(file, RDC_RENAME);
			Free_Series(target);
			if (file->error) Trap1_DEAD_END(RE_NO_RENAME, path);
		}
		break;

	case A_CREATE:
		// !!! should it leave file open???
		if (!IS_OPEN(file)) {
			Setup_File(file, AM_OPEN_WRITE | AM_OPEN_NEW, path);
			if (OS_DO_DEVICE(file, RDC_CREATE) < 0) Trap_Port_DEAD_END(RE_CANNOT_OPEN, port, file->error);
			OS_DO_DEVICE(file, RDC_CLOSE);
		}
		break;

	case A_QUERY:
		if (!IS_OPEN(file)) {
			Setup_File(file, 0, path);
			if (OS_DO_DEVICE(file, RDC_QUERY) < 0) return R_NONE;
		}
		Ret_Query_File(port, file, D_OUT);
		// !!! free file path?
		break;

	case A_MODIFY:
		Set_Mode_Value(file, Get_Mode_Id(D_ARG(2)), D_ARG(3));
		if (!IS_OPEN(file)) {
			Setup_File(file, 0, path);
			if (OS_DO_DEVICE(file, RDC_MODIFY) < 0) return R_NONE;
		}
		return R_TRUE;
		break;

	case A_INDEXQ:
		SET_INTEGER(D_OUT, file->special.file.index + 1);
		break;

	case A_LENGTHQ:
		SET_INTEGER(D_OUT, file->special.file.size - file->special.file.index); // !clip at zero
		break;

	case A_HEAD:
		file->special.file.index = 0;
		goto seeked;

    case A_TAIL:
		file->special.file.index = file->special.file.size;
		goto seeked;

	case A_NEXT:
		file->special.file.index++;
		goto seeked;

	case A_BACK:
		if (file->special.file.index > 0) file->special.file.index--;
		goto seeked;

	case A_SKIP:
		file->special.file.index += Get_Num_Arg(D_ARG(2));
		goto seeked;

    case A_HEADQ:
		DECIDE(file->special.file.index == 0);

    case A_TAILQ:
		DECIDE(file->special.file.index >= file->special.file.size);

    case A_PASTQ:
		DECIDE(file->special.file.index > file->special.file.size);

	case A_CLEAR:
		// !! check for write enabled?
		SET_FLAG(file->modes, RFM_RESEEK);
		SET_FLAG(file->modes, RFM_TRUNCATE);
		file->length = 0;
		if (OS_DO_DEVICE(file, RDC_WRITE) < 0) Trap1_DEAD_END(RE_WRITE_ERROR, path);
		break;

	/* Not yet implemented:
		A_AT,					// 38
		A_PICK,					// 41
		A_PATH,					// 42
		A_PATH_SET,				// 43
		A_FIND,					// 44
		A_SELECT,				// 45
		A_TAKE,					// 49
		A_INSERT,				// 50
		A_REMOVE,				// 52
		A_CHANGE,				// 53
		A_POKE,					// 54
		A_QUERY,				// 64
		A_FLUSH,				// 65
	*/

	default:
		Trap_Action_DEAD_END(REB_PORT, action);
	}

	return R_OUT;

seeked:
	SET_FLAG(file->modes, RFM_RESEEK);
	return R_ARG1;

is_true:
	return R_TRUE;

is_false:
	return R_FALSE;
}
Esempio n. 4
0
*/	REBINT Do_Series_Action(REBCNT action, REBVAL *value, REBVAL *arg)
/*
**		Common series functions.
**
***********************************************************************/
{
	REBINT	index;
	REBINT	tail;
	REBINT	len = 0;

	// Common setup code for all actions:
	if (action != A_MAKE && action != A_TO) {
		index = (REBINT)VAL_INDEX(value);
		tail  = (REBINT)VAL_TAIL(value);
	} else return -1;

	switch (action) {

	//-- Navigation:

	case A_HEAD:
		VAL_INDEX(value) = 0;
		break;

	case A_TAIL:
		VAL_INDEX(value) = (REBCNT)tail;
		break;

	case A_HEADQ:
		DECIDE(index == 0);

	case A_TAILQ:
		DECIDE(index >= tail);

	case A_PASTQ:
		DECIDE(index > tail);

	case A_NEXT:
		if (index < tail) VAL_INDEX(value)++;
		break;

	case A_BACK:
		if (index > 0) VAL_INDEX(value)--;
		break;

	case A_SKIP:
	case A_AT:
		len = Get_Num_Arg(arg);
		{
			REBI64 i = (REBI64)index + (REBI64)len;
			if (action == A_SKIP) {
				if (IS_LOGIC(arg)) i--;
			} else { // A_AT
				if (len > 0) i--;
			}
			if (i > (REBI64)tail) i = (REBI64)tail;
			else if (i < 0) i = 0;
			VAL_INDEX(value) = (REBCNT)i;
		}
		break;
/*
	case A_ATZ:
		len = Get_Num_Arg(arg);
		{
			REBI64 idx = Add_Max(0, index, len, MAX_I32);
			if (idx < 0) idx = 0;
			VAL_INDEX(value) = (REBCNT)idx;
		}
		break;
*/
	case A_INDEXQ:
		SET_INTEGER(DS_RETURN, ((REBI64)index) + 1);
		return R_RET;

	case A_LENGTHQ:
		SET_INTEGER(DS_RETURN, tail > index ? tail - index : 0);
		return R_RET;

	case A_REMOVE:
		// /PART length
		TRAP_PROTECT(VAL_SERIES(value));
		len = DS_REF(2) ? Partial(value, 0, DS_ARG(3), 0) : 1;
		index = (REBINT)VAL_INDEX(value);
		if (index < tail && len != 0)
			Remove_Series(VAL_SERIES(value), VAL_INDEX(value), len);
		break;

	case A_ADD:			// Join_Strings(value, arg);
	case A_SUBTRACT:	// "test this" - 10
	case A_MULTIPLY:	// "t" * 4 = "tttt"
	case A_DIVIDE:
	case A_REMAINDER:
	case A_POWER:
	case A_ODDQ:
	case A_EVENQ:
	case A_ABSOLUTE:
		Trap_Action(VAL_TYPE(value), action);

	default:
		return -1;
	}

	DS_RET_VALUE(value);
	return R_RET;

is_false:
	return R_FALSE;

is_true:
	return R_TRUE;
}
Esempio n. 5
0
LEAFTYPE radix_add(struct ROOTSTRUCT * tree, LEAFTYPE leaf, EXTRA_ARG aux, int should_replace, int* error) 
{
    LEAFTYPE result;
    struct _internal_node * node, * parent, * child;
    uint32_t dir, dir2;
    int32_t critbit;

    *error = 0;
    if (tree->leafcount == 0) {
        tree->root.leaf = leaf;
        tree->leafcount ++;

        return NO_LEAF;
    } else if (tree->leafcount == 1) {
        result = tree->root.leaf;
        critbit = COMPARE(leaf, result);
        if (critbit == -1) {
            if (should_replace) {
                node->child[dir].leaf = leaf;
                return result;
            } else return leaf;
        } else {
            node = (struct _internal_node *) ALLOC(sizeof (struct _internal_node));
            if (node == NULL) {
                *error = -1;
                return NO_LEAF;
            } else {
                node->critbit = critbit;
                dir = DECIDE(leaf, critbit, aux);
                node->child[dir].leaf = leaf;
                SET_LEAF(node, dir);
            }
            result = tree->root.leaf;
            node->child[1 - dir].leaf = tree->root.leaf;
            SET_LEAF(node, 1 - dir);
            tree->root.node = node;
            tree->leafcount ++;
            return NO_LEAF;
        }
    } /* else */
    node = tree->root.node;
    while (1) {
        dir = DECIDE(leaf, node->critbit, aux);
        if (IS_LEAF(node, dir)) {
            result = node->child[dir].leaf;
            break;
        } else {
            node = node->child[dir].node;
        }
    }
    critbit = COMPARE(leaf, result);
    if (critbit == -1) {
        if (should_replace) {
            node->child[dir].leaf = leaf;
            return result;
        } else return leaf;
    } else {
        node = (struct _internal_node *) ALLOC(sizeof (struct _internal_node));
        if (node == NULL) {
            *error = -1;
            return NO_LEAF;
        } else {
            node->critbit = critbit;
            dir = DECIDE(leaf, critbit, aux);
            node->child[dir].leaf = leaf;
            SET_LEAF(node, dir);
        }
        child = tree->root.node;
        if (node->critbit < child->critbit) {
            node->child[1 - dir].node = child;
            SET_NODE(node, 1 - dir);
            tree->root.node = node;
        } else while (1) {
                parent = child;
                dir2 = DECIDE(leaf, parent->critbit, aux);
                if (IS_LEAF(parent, dir2)) {
                    result = parent->child[dir2].leaf;
                    //node->child[1 - dir].leaf = tree->root.leaf;
                    node->child[1 - dir].leaf = parent->child[dir2].leaf;
                    SET_LEAF(node, 1 - dir);
                    parent->child[dir2].node = node;
                    SET_NODE(parent, dir2);
                    break;
                } else {
                    child = parent->child[dir2].node;
                    if (node->critbit < child->critbit) {
                        node->child[1 - dir].node = child;
                        SET_NODE(node, 1 - dir);
                        parent->child[dir2].node = node;
                        SET_NODE(parent, dir2);

                        break;
                    }
                }
            }
        tree->leafcount ++;
        return NO_LEAF;
    }
}