Example #1
0
static REBOOL same_fields(REBSER *tgt, REBSER *src)
{
	struct Struct_Field *tgt_fields = (struct Struct_Field *) SERIES_DATA(tgt);
	struct Struct_Field *src_fields = (struct Struct_Field *) SERIES_DATA(src);
	REBCNT n;

	if (SERIES_TAIL(tgt) != SERIES_TAIL(src)) {
		return FALSE;
	}

	for(n = 0; n < SERIES_TAIL(src); n ++) {
		if (tgt_fields[n].type != src_fields[n].type) {
			return FALSE;
		}
		if (VAL_SYM_CANON(BLK_SKIP(PG_Word_Table.series, tgt_fields[n].sym))
			!= VAL_SYM_CANON(BLK_SKIP(PG_Word_Table.series, src_fields[n].sym))
			|| tgt_fields[n].offset != src_fields[n].offset
			|| tgt_fields[n].dimension != src_fields[n].dimension
			|| tgt_fields[n].size != src_fields[n].size) {
			return FALSE;
		}
		if (tgt_fields[n].type == STRUCT_TYPE_STRUCT
			&& ! same_fields(tgt_fields[n].fields, src_fields[n].fields)) {
			return FALSE;
		}
	}

	return TRUE;
}
Example #2
0
*/	static REBFLG Get_Struct_Var(REBSTU *stu, REBVAL *word, REBVAL *val)
/*
***********************************************************************/
{
	struct Struct_Field *field = NULL;
	REBCNT i = 0;
	field = (struct Struct_Field *)SERIES_DATA(stu->fields);
	for (i = 0; i < SERIES_TAIL(stu->fields); i ++, field ++) {
		if (VAL_WORD_CANON(word) == VAL_SYM_CANON(BLK_SKIP(PG_Word_Table.series, field->sym))) {
			if (field->array) {
				REBSER *ser = Make_Array(field->dimension);
				REBCNT n = 0;
				for (n = 0; n < field->dimension; n ++) {
					REBVAL elem;
					get_scalar(stu, field, n, &elem);
					Append_Value(ser, &elem);
				}
				Val_Init_Block(val, ser);
			} else {
				get_scalar(stu, field, 0, val);
			}
			return TRUE;
		}
	}
	return FALSE;
}
Example #3
0
*/	static REBFLG Set_Struct_Var(REBSTU *stu, REBVAL *word, REBVAL *elem, REBVAL *val)
/*
***********************************************************************/
{
	struct Struct_Field *field = NULL;
	REBCNT i = 0;
	field = (struct Struct_Field *)SERIES_DATA(stu->fields);
	for (i = 0; i < SERIES_TAIL(stu->fields); i ++, field ++) {
		if (VAL_WORD_CANON(word) == VAL_SYM_CANON(BLK_SKIP(PG_Word_Table.series, field->sym))) {
			if (field->array) {
				if (elem == NULL) { //set the whole array
					REBCNT n = 0;
					if ((!IS_BLOCK(val) || field->dimension != VAL_LEN(val))) {
						return FALSE;
					}

					for(n = 0; n < field->dimension; n ++) {
						if (!assign_scalar(stu, field, n, VAL_BLK_SKIP(val, n))) {
							return FALSE;
						}
					}

				} else {// set only one element
					if (!IS_INTEGER(elem)
						|| VAL_INT32(elem) <= 0
						|| VAL_INT32(elem) > cast(REBINT, field->dimension)) {
						return FALSE;
					}
					return assign_scalar(stu, field, VAL_INT32(elem) - 1, val);
				}
				return TRUE;
			} else {
				return assign_scalar(stu, field, 0, val);
			}
			return TRUE;
		}
	}
	return FALSE;
}
Example #4
0
RL_API int RL_Series(REBSER *series, REBCNT what)
/*
**	Get series information.
**
**	Returns:
**		Returns information related to a series.
**	Arguments:
**		series - any series pointer (string or block)
**		what - indicates what information to return (see RXI_SER enum)
**	Notes:
**		Invalid what arg nums will return zero.
*/
{
	switch (what) {
	case RXI_SER_DATA: return (int)SERIES_DATA(series); // problem for 64 bit !!
	case RXI_SER_TAIL: return SERIES_TAIL(series);
	case RXI_SER_LEFT: return SERIES_AVAIL(series);
	case RXI_SER_SIZE: return SERIES_REST(series);
	case RXI_SER_WIDE: return SERIES_WIDE(series);
	}
	return 0;
}
Example #5
0
static REBOOL get_scalar(const REBSTU *stu,
				  const struct Struct_Field *field,
				  REBCNT n, /* element index, starting from 0 */
				  REBVAL *val)
{
	REBYTE *data = SERIES_SKIP(STRUCT_DATA_BIN(stu),
							 STRUCT_OFFSET(stu) + field->offset + n * field->size);
	switch (field->type) {
		case STRUCT_TYPE_UINT8:
			SET_INTEGER(val, *(u8*)data);
			break;
		case STRUCT_TYPE_INT8:
			SET_INTEGER(val, *(i8*)data);
			break;
		case STRUCT_TYPE_UINT16:
			SET_INTEGER(val, *(u16*)data);
			break;
		case STRUCT_TYPE_INT16:
			SET_INTEGER(val, *(i8*)data);
			break;
		case STRUCT_TYPE_UINT32:
			SET_INTEGER(val, *(u32*)data);
			break;
		case STRUCT_TYPE_INT32:
			SET_INTEGER(val, *(i32*)data);
			break;
		case STRUCT_TYPE_UINT64:
			SET_INTEGER(val, *(u64*)data);
			break;
		case STRUCT_TYPE_INT64:
			SET_INTEGER(val, *(i64*)data);
			break;
		case STRUCT_TYPE_FLOAT:
			SET_DECIMAL(val, *(float*)data);
			break;
		case STRUCT_TYPE_DOUBLE:
			SET_DECIMAL(val, *(double*)data);
			break;
		case STRUCT_TYPE_POINTER:
			SET_INTEGER(val, cast(REBUPT, *cast(void**, data)));
			break;
		case STRUCT_TYPE_STRUCT:
			{
				SET_TYPE(val, REB_STRUCT);
				VAL_STRUCT_FIELDS(val) = field->fields;
				VAL_STRUCT_SPEC(val) = field->spec;

				VAL_STRUCT_DATA(val) = Make_Series(
					1, sizeof(struct Struct_Data), MKS_NONE
				);
				MANAGE_SERIES(VAL_STRUCT_DATA(val));

				VAL_STRUCT_DATA_BIN(val) = STRUCT_DATA_BIN(stu);
				VAL_STRUCT_OFFSET(val) = data - SERIES_DATA(VAL_STRUCT_DATA_BIN(val));
				VAL_STRUCT_LEN(val) = field->size;
			}
			break;
		case STRUCT_TYPE_REBVAL:
			memcpy(val, data, sizeof(REBVAL));
			break;
		default:
			/* should never be here */
			return FALSE;
	}
	return TRUE;
}
Example #6
0
*/	REBSER *Struct_To_Block(const REBSTU *stu)
/*
**		Used by MOLD to create a block.
**
***********************************************************************/
{
	REBSER *ser = Make_Array(10);
	struct Struct_Field *field = (struct Struct_Field*) SERIES_DATA(stu->fields);
	REBCNT i;

	// We are building a recursive structure.  So if we did not hand each
	// sub-series over to the GC then a single Free_Series() would not know
	// how to free them all.  There would have to be a specialized walk to
	// free the resulting structure.  Hence, don't invoke the GC until the
	// root series being returned is done being used or is safe from GC!
	MANAGE_SERIES(ser);

	for(i = 0; i < SERIES_TAIL(stu->fields); i ++, field ++) {
		REBVAL *val = NULL;
		REBVAL *type_blk = NULL;

		/* required field name */
		val = Alloc_Tail_Array(ser);
		Val_Init_Word_Unbound(val, REB_SET_WORD, field->sym);

		/* required type */
		type_blk = Alloc_Tail_Array(ser);
		Val_Init_Block(type_blk, Make_Array(1));

		val = Alloc_Tail_Array(VAL_SERIES(type_blk));
		if (field->type == STRUCT_TYPE_STRUCT) {
			REBVAL *nested = NULL;
			DS_PUSH_NONE;
			nested = DS_TOP;

			Val_Init_Word_Unbound(val, REB_WORD, SYM_STRUCT_TYPE);
			get_scalar(stu, field, 0, nested);
			val = Alloc_Tail_Array(VAL_SERIES(type_blk));
			Val_Init_Block(val, Struct_To_Block(&VAL_STRUCT(nested)));

			DS_DROP;
		} else
			Val_Init_Word_Unbound(val, REB_WORD, type_to_sym[field->type]);

		/* optional dimension */
		if (field->dimension > 1) {
			REBSER *dim = Make_Array(1);
			REBVAL *dv = NULL;
			val = Alloc_Tail_Array(VAL_SERIES(type_blk));
			Val_Init_Block(val, dim);

			dv = Alloc_Tail_Array(dim);
			SET_INTEGER(dv, field->dimension);
		}

		/* optional initialization */
		if (field->dimension > 1) {
			REBSER *dim = Make_Array(1);
			REBCNT n = 0;
			val = Alloc_Tail_Array(ser);
			Val_Init_Block(val, dim);
			for (n = 0; n < field->dimension; n ++) {
				REBVAL *dv = Alloc_Tail_Array(dim);
				get_scalar(stu, field, n, dv);
			}
		} else {
			val = Alloc_Tail_Array(ser);
			get_scalar(stu, field, 0, val);
		}
	}
	return ser;
}
Example #7
0
*/  REBSER *Compress(REBSER *input, REBINT index, REBCNT len, REBFLG gzip, REBFLG raw)
/*
**		This is a wrapper over Zlib which will compress a BINARY!
**		series to produce another BINARY!.  It can use either gzip
**		or zlib envelopes, and has a "raw" option for no header.
**
**		!!! Adds 32-bit size info to zlib non-raw compressions for
**		compatibility with Rebol2 and R3-Alpha, at the cost of
**		inventing yet-another-format.  Consider removing.
**
**		!!! Does not expose the "streaming" ability of zlib.
**
***********************************************************************/
{
	REBCNT buf_size;
	REBSER *output;
	int ret;
	z_stream strm;

	assert(BYTE_SIZE(input)); // must be BINARY!

	// compression level can be a value from 1 to 9, or Z_DEFAULT_COMPRESSION
	// if you want it to pick what the library author considers the "worth it"
	// tradeoff of time to generally suggest.
	//
	strm.zalloc = Z_NULL;
	strm.zfree = Z_NULL;
	strm.opaque = Z_NULL;

	ret = deflateInit2(
		&strm,
		Z_DEFAULT_COMPRESSION,
		Z_DEFLATED,
		raw
			? (gzip ? window_bits_gzip_raw : window_bits_zlib_raw)
			: (gzip ? window_bits_gzip : window_bits_zlib),
		8,
		Z_DEFAULT_STRATEGY
	);

	if (ret != Z_OK)
		raise Error_Compression(&strm, ret);

	// http://stackoverflow.com/a/4938401/211160
	buf_size = deflateBound(&strm, len);

	strm.avail_in = len;
	strm.next_in = BIN_HEAD(input) + index;

	output = Make_Binary(buf_size);
	strm.avail_out = buf_size;
	strm.next_out = BIN_HEAD(output);

	ret = deflate(&strm, Z_FINISH);
	deflateEnd(&strm);

	if (ret != Z_STREAM_END)
		raise Error_Compression(&strm, ret);

	SET_STR_END(output, buf_size - strm.avail_out);
	SERIES_TAIL(output) = buf_size - strm.avail_out;

	if (gzip) {
		// GZIP contains its own CRC.  It also has a 32-bit uncompressed
		// length (and CRC), conveniently (and perhaps confusingly) at the
		// tail in the same format that Rebol used.

		REBCNT gzip_len = Bytes_To_REBCNT(
			SERIES_DATA(output) + buf_size - strm.avail_out - sizeof(REBCNT)
		);
		assert(len == gzip_len);
	}
	else if (!raw) {
		// Add 32-bit length to the end.
		//
		// !!! In ZLIB format the length can be found by decompressing, but
		// not known a priori.  So this is for efficiency.  It would likely be
		// better to not include this as it only confuses matters for those
		// expecting the data to be in a known format...though it means that
		// clients who wanted to decompress to a known allocation size would
		// have to save the size somewhere.

		REBYTE out_size[sizeof(REBCNT)];
		REBCNT_To_Bytes(out_size, cast(REBCNT, len));
		Append_Series(output, cast(REBYTE*, out_size), sizeof(REBCNT));
	}
Example #8
0
*/  void Mold_Value(REB_MOLD *mold, const REBVAL *value, REBFLG molded)
/*
**		Mold or form any value to string series tail.
**
***********************************************************************/
{
	REBYTE buf[60];
	REBINT len;
	REBSER *ser = mold->series;

	CHECK_C_STACK_OVERFLOW(&len);

	assert(SERIES_WIDE(mold->series) == sizeof(REBUNI));
	assert(ser);

	// Special handling of string series: {
	if (ANY_STR(value) && !IS_TAG(value)) {

		// Forming a string:
		if (!molded) {
			Insert_String(ser, -1, VAL_SERIES(value), VAL_INDEX(value), VAL_LEN(value), 0);
			return;
		}

		// Special format for ALL string series when not at head:
		if (GET_MOPT(mold, MOPT_MOLD_ALL) && VAL_INDEX(value) != 0) {
			Mold_All_String(value, mold);
			return;
		}
	}

	switch (VAL_TYPE(value)) {
	case REB_NONE:
		Emit(mold, "+N", SYM_NONE);
		break;

	case REB_LOGIC:
//		if (!molded || !VAL_LOGIC_WORDS(value) || !GET_MOPT(mold, MOPT_MOLD_ALL))
			Emit(mold, "+N", VAL_LOGIC(value) ? SYM_TRUE : SYM_FALSE);
//		else
//			Mold_Logic(mold, value);
		break;

	case REB_INTEGER:
		len = Emit_Integer(buf, VAL_INT64(value));
		goto append;

	case REB_DECIMAL:
	case REB_PERCENT:
		len = Emit_Decimal(buf, VAL_DECIMAL(value), IS_PERCENT(value)?DEC_MOLD_PERCENT:0,
			Punctuation[GET_MOPT(mold, MOPT_COMMA_PT) ? PUNCT_COMMA : PUNCT_DOT], mold->digits);
		goto append;

	case REB_MONEY:
		len = Emit_Money(value, buf, mold->opts);
		goto append;

	case REB_CHAR:
		Mold_Uni_Char(ser, VAL_CHAR(value), (REBOOL)molded, (REBOOL)GET_MOPT(mold, MOPT_MOLD_ALL));
		break;

	case REB_PAIR:
		len = Emit_Decimal(buf, VAL_PAIR_X(value), DEC_MOLD_MINIMAL, Punctuation[PUNCT_DOT], mold->digits/2);
		Append_Unencoded_Len(ser, s_cast(buf), len);
		Append_Byte(ser, 'x');
		len = Emit_Decimal(buf, VAL_PAIR_Y(value), DEC_MOLD_MINIMAL, Punctuation[PUNCT_DOT], mold->digits/2);
		Append_Unencoded_Len(ser, s_cast(buf), len);
		//Emit(mold, "IxI", VAL_PAIR_X(value), VAL_PAIR_Y(value));
		break;

	case REB_TUPLE:
		len = Emit_Tuple(value, buf);
		goto append;

	case REB_TIME:
		//len = Emit_Time(value, buf, Punctuation[GET_MOPT(mold, MOPT_COMMA_PT) ? PUNCT_COMMA : PUNCT_DOT]);
		Emit_Time(mold, value);
		break;

	case REB_DATE:
		Emit_Date(mold, value);
		break;

	case REB_STRING:
		// FORM happens in top section.
		Mold_String_Series(value, mold);
		break;

	case REB_BINARY:
		if (GET_MOPT(mold, MOPT_MOLD_ALL) && VAL_INDEX(value) != 0) {
			Mold_All_String(value, mold);
			return;
		}
		Mold_Binary(value, mold);
		break;

	case REB_FILE:
		if (VAL_LEN(value) == 0) {
			Append_Unencoded(ser, "%\"\"");
			break;
		}
		Mold_File(value, mold);
		break;

	case REB_EMAIL:
	case REB_URL:
		Mold_Url(value, mold);
		break;

	case REB_TAG:
		if (GET_MOPT(mold, MOPT_MOLD_ALL) && VAL_INDEX(value) != 0) {
			Mold_All_String(value, mold);
			return;
		}
		Mold_Tag(value, mold);
		break;

//		Mold_Issue(value, mold);
//		break;

	case REB_BITSET:
		Pre_Mold(value, mold); // #[bitset! or make bitset!
		Mold_Bitset(value, mold);
		End_Mold(mold);
		break;

	case REB_IMAGE:
		Pre_Mold(value, mold);
		if (!GET_MOPT(mold, MOPT_MOLD_ALL)) {
			Append_Byte(ser, '[');
			Mold_Image_Data(value, mold);
			Append_Byte(ser, ']');
			End_Mold(mold);
		}
		else {
			REBVAL val = *value;
			VAL_INDEX(&val) = 0; // mold all of it
			Mold_Image_Data(&val, mold);
			Post_Mold(value, mold);
		}
		break;

	case REB_BLOCK:
	case REB_PAREN:
		if (!molded)
			Form_Block_Series(VAL_SERIES(value), VAL_INDEX(value), mold, 0);
		else
			Mold_Block(value, mold);
		break;

	case REB_PATH:
	case REB_SET_PATH:
	case REB_GET_PATH:
	case REB_LIT_PATH:
		Mold_Block(value, mold);
		break;

	case REB_VECTOR:
		Mold_Vector(value, mold, molded);
		break;

	case REB_DATATYPE:
		if (!molded)
			Emit(mold, "N", VAL_DATATYPE(value) + 1);
		else
			Emit(mold, "+DN", SYM_DATATYPE_TYPE, VAL_DATATYPE(value) + 1);
		break;

	case REB_TYPESET:
		Mold_Typeset(value, mold, molded);
		break;

	case REB_WORD:
		// This is a high frequency function, so it is optimized.
		Append_UTF8(ser, Get_Sym_Name(VAL_WORD_SYM(value)), -1);
		break;

	case REB_SET_WORD:
		Emit(mold, "W:", value);
		break;

	case REB_GET_WORD:
		Emit(mold, ":W", value);
		break;

	case REB_LIT_WORD:
		Emit(mold, "\'W", value);
		break;

	case REB_REFINEMENT:
		Emit(mold, "/W", value);
		break;

	case REB_ISSUE:
		Emit(mold, "#W", value);
		break;

	case REB_CLOSURE:
	case REB_FUNCTION:
	case REB_NATIVE:
	case REB_ACTION:
	case REB_COMMAND:
		Mold_Function(value, mold);
		break;

	case REB_OBJECT:
	case REB_MODULE:
	case REB_PORT:
		if (!molded) Form_Object(value, mold);
		else Mold_Object(value, mold);
		break;

	case REB_TASK:
		Mold_Object(value, mold); //// | (1<<MOPT_NO_NONE));
		break;

	case REB_ERROR:
		Mold_Error(value, mold, molded);
		break;

	case REB_MAP:
		Mold_Map(value, mold, molded);
		break;

	case REB_GOB:
	{
		REBSER *blk;
		Pre_Mold(value, mold);
		blk = Gob_To_Block(VAL_GOB(value));
		Mold_Block_Series(mold, blk, 0, 0);
		End_Mold(mold);
	}
		break;


	case REB_EVENT:
		Mold_Event(value, mold);
		break;

	case REB_STRUCT:
	{
		REBSER *blk;
		Pre_Mold(value, mold);
		blk = Struct_To_Block(&VAL_STRUCT(value));
		Mold_Block_Series(mold, blk, 0, 0);
		End_Mold(mold);
	}
		break;

	case REB_ROUTINE:
		Pre_Mold(value, mold);
		Mold_Block_Series(mold, VAL_ROUTINE_SPEC(value), 0, NULL);
		End_Mold(mold);
		break;
	case REB_LIBRARY:
		Pre_Mold(value, mold);

		DS_PUSH_NONE;
		*DS_TOP = *(REBVAL*)SERIES_DATA(VAL_LIB_SPEC(value));
		Mold_File(DS_TOP, mold);
		DS_DROP;

		End_Mold(mold);
		break;
	case REB_CALLBACK:
		Pre_Mold(value, mold);
		Mold_Block_Series(mold, VAL_ROUTINE_SPEC(value), 0, NULL);
		End_Mold(mold);
		break;
	case REB_REBCODE:
	case REB_OP:
	case REB_FRAME:
	case REB_HANDLE:
	case REB_UTYPE:
		// Value has no printable form, so just print its name.
		if (!molded) Emit(mold, "?T?", value);
		else Emit(mold, "+T", value);
		break;

	case REB_END:
	case REB_UNSET:
		if (molded) Emit(mold, "+T", value);
		break;

	default:
		assert(FALSE);
		Panic_Core(RP_DATATYPE+5, VAL_TYPE(value));
	}
	return;

append:
	Append_Unencoded_Len(ser, s_cast(buf), len);

}