*/ REBSER *Copy_Sequence(REBSER *source) /* ** Copy any series that *isn't* an "array" (such as STRING!, ** BINARY!, BITSET!, VECTOR!...). Includes the terminator. ** ** Use Copy_Array routines (which specify Shallow, Deep, etc.) for ** greater detail needed when expressing intent for Rebol Arrays. ** ** Note: No suitable name for "non-array-series" has been picked. ** "Sequence" is used for now because Copy_Non_Array() doesn't ** look good and lots of things aren't "Rebol Arrays" that aren't ** series. The main idea was just to get rid of the generic ** Copy_Series() routine, which doesn't call any attention ** to the importance of stating one's intentions specifically ** about semantics when copying an array. ** ***********************************************************************/ { REBCNT len = source->tail + 1; REBSER *series = Make_Series(len, SERIES_WIDE(source), MKS_NONE); assert(!Is_Array_Series(source)); memcpy(series->data, source->data, len * SERIES_WIDE(source)); series->tail = source->tail; return series; }
// // Dump_Series: C // void Dump_Series(REBSER *series, const char *memo) { if (!series) return; Debug_Fmt( "%s Series %x \"%s\":" " wide: %2d" " size: %6d" " bias: %d" " tail: %d" " rest: %d" " flags: %x", memo, series, "-", // !label SER_WIDE(series), SER_TOTAL(series), SER_BIAS(series), SER_LEN(series), SER_REST(series), series->info.bits // flags + width ); if (Is_Array_Series(series)) { Dump_Values(ARR_HEAD(AS_ARRAY(series)), SER_LEN(series)); } else Dump_Bytes( SER_DATA_RAW(series), (SER_LEN(series) + 1) * SER_WIDE(series) ); }
// // Append_Series: C // // Append value(s) onto the tail of a series. The len is // the number of units (bytes, REBVALS, etc.) of the data, // and does not include the terminator (which will be added). // The new tail position will be returned as the result. // A terminator will be added to the end of the appended data. // void Append_Series(REBSER *s, const REBYTE *data, REBCNT len) { REBCNT len_old = SER_LEN(s); REBYTE wide = SER_WIDE(s); assert(!Is_Array_Series(s)); EXPAND_SERIES_TAIL(s, len); memcpy(SER_DATA_RAW(s) + (wide * len_old), data, wide * len); TERM_SERIES(s); }
// // Trim_Tail: C // // Used to trim off hanging spaces during FORM and MOLD. // void Trim_Tail(REBSER *src, REBYTE chr) { REBOOL unicode = NOT(BYTE_SIZE(src)); REBCNT tail; REBUNI c; assert(!Is_Array_Series(src)); for (tail = SER_LEN(src); tail > 0; tail--) { c = unicode ? *UNI_AT(src, tail - 1) : *BIN_AT(src, tail - 1); if (c != chr) break; } SET_SERIES_LEN(src, tail); TERM_SEQUENCE(src); }
/* set storage memory to external addr: raw_addr */ static void set_ext_storage (REBVAL *out, REBINT raw_size, REBUPT raw_addr) { REBSER *data_ser = VAL_STRUCT_DATA_BIN(out); REBSER *ser = NULL; if (raw_size >= 0 && raw_size != cast(REBINT, VAL_STRUCT_LEN(out))) raise Error_0(RE_INVALID_DATA); ser = Make_Series( SERIES_LEN(data_ser) + 1, // include term. SERIES_WIDE(data_ser), Is_Array_Series(data_ser) ? (MKS_ARRAY | MKS_EXTERNAL) : MKS_EXTERNAL ); ser->data = (REBYTE*)raw_addr; VAL_STRUCT_DATA_BIN(out) = ser; MANAGE_SERIES(ser); }
*/ void Trim_Tail(REBSER *src, REBYTE chr) /* ** Used to trim off hanging spaces during FORM and MOLD. ** ***********************************************************************/ { REBOOL is_uni = !BYTE_SIZE(src); REBCNT tail; REBUNI c; assert(!Is_Array_Series(src)); for (tail = SERIES_TAIL(src); tail > 0; tail--) { c = is_uni ? *UNI_SKIP(src, tail - 1) : *BIN_SKIP(src, tail - 1); if (c != chr) break; } SERIES_TAIL(src) = tail; TERM_SEQUENCE(src); }
*/ void Assert_Series_Term_Core(REBSER *series) /* ***********************************************************************/ { if (Is_Array_Series(series)) { // REB_END values may not be canonized to zero bytes, check type only if (!IS_END(BLK_SKIP(series, series->tail))) { Debug_Fmt("Unterminated blocklike series detected"); Panic_Series(series); } } else { // Non-REBVAL-bearing series must have their terminal as all 0 bytes int n; for (n = 0; n < SERIES_WIDE(series); n++) { if (0 != series->data[series->tail * SERIES_WIDE(series) + n]) { Debug_Fmt("Non-zero byte in terminator of non-block series"); Panic_Series(series); } } } }
*/ REBSER *Copy_Sequence_At_Len(REBSER *source, REBCNT index, REBCNT len) /* ** Copy a subseries out of a series that is not an array. ** Includes the terminator for it. ** ** Use Copy_Array routines (which specify Shallow, Deep, etc.) for ** greater detail needed when expressing intent for Rebol Arrays. ** ***********************************************************************/ { REBSER *series = Make_Series(len + 1, SERIES_WIDE(source), MKS_NONE); assert(!Is_Array_Series(source)); memcpy( series->data, source->data + index * SERIES_WIDE(source), (len + 1) * SERIES_WIDE(source) ); series->tail = len; return series; }
*/ REBSER *Copy_Buffer(REBSER *buf, void *end) /* ** Copy a shared buffer. Set tail and termination. ** ***********************************************************************/ { REBSER *ser; REBCNT len; len = BYTE_SIZE(buf) ? ((REBYTE *)end) - BIN_HEAD(buf) : ((REBUNI *)end) - UNI_HEAD(buf); ser = Make_Series( len + 1, SERIES_WIDE(buf), Is_Array_Series(buf) ? MKS_ARRAY : MKS_NONE ); memcpy(ser->data, buf->data, SERIES_WIDE(buf) * len); ser->tail = len; TERM_SERIES(ser); return ser; }