*/ static void Read_File_Port(REBVAL *out, REBSER *port, REBREQ *file, REBVAL *path, REBCNT args, REBCNT len) /* ** Read from a file port. ** ***********************************************************************/ { REBSER *ser; // Allocate read result buffer: ser = Make_Binary(len); Set_Series(REB_BINARY, out, ser); //??? what if already set? // Do the read, check for errors: file->common.data = BIN_HEAD(ser); file->length = len; if (OS_DO_DEVICE(file, RDC_READ) < 0) Trap_Port(RE_READ_ERROR, port, file->error); SERIES_TAIL(ser) = file->actual; STR_TERM(ser); // Convert to string or block of strings. // NOTE: This code is incorrect for files read in chunks!!! if (args & (AM_READ_STRING | AM_READ_LINES)) { REBSER *nser = Decode_UTF_String(BIN_HEAD(ser), file->actual, -1); if (nser == NULL) { Trap(RE_BAD_DECODE); } Set_String(out, nser); if (args & AM_READ_LINES) Set_Block(out, Split_Lines(out)); } }
// Used for file loading during very early development. static REBSER *Read_All_File(char *fname) { REBREQ file; REBSER *ser = 0; CLEAR(&file, sizeof(file)); file.clen = sizeof(file); file.device = RDI_FILE; file.file.path = fname; SET_FLAG(file.modes, RFM_READ); OS_DO_DEVICE(&file, RDC_OPEN); if (file.error) return 0; ser = Make_Binary((REBCNT)(file.file.size)); file.data = BIN_DATA(ser); file.length = (REBCNT)(file.file.size); OS_DO_DEVICE(&file, RDC_READ); if (file.error) { ser = 0; } else { ser->tail = file.actual; STR_TERM(ser); } OS_DO_DEVICE(&file, RDC_CLOSE); return ser; }
*/ REBSER *Copy_Bytes(const REBYTE *src, REBINT len) /* ** Create a string series from the given bytes. ** Source is always latin-1 valid. Result is always 8bit. ** ***********************************************************************/ { REBSER *dst; if (len < 0) len = LEN_BYTES(src); dst = Make_Binary(len); memcpy(STR_DATA(dst), src, len); SERIES_TAIL(dst) = len; STR_TERM(dst); return dst; }
*/ REBSER *Encode_UTF8_String(void *src, REBCNT len, REBFLG uni, REBFLG opts) /* ** Do all the details to encode a string as UTF8. ** No_copy means do not make a copy. ** Result can be a shared buffer! ** ***********************************************************************/ { REBSER *ser = BUF_FORM; // a shared buffer REBCNT size; REBYTE *cp; REBFLG ccr = GET_FLAG(opts, ENC_OPT_CRLF); if (uni) { REBUNI *up = (REBUNI*)src; size = Length_As_UTF8(up, len, TRUE, (REBOOL)ccr); cp = Reset_Buffer(ser, size + (GET_FLAG(opts, ENC_OPT_BOM) ? 3 : 0)); UNUSED(cp); Encode_UTF8(Reset_Buffer(ser, size), size, up, &len, TRUE, ccr); } else { REBYTE *bp = (REBYTE*)src; if (Is_Not_ASCII(bp, len)) { size = Length_As_UTF8((REBUNI*)bp, len, FALSE, (REBOOL)ccr); cp = Reset_Buffer(ser, size + (GET_FLAG(opts, ENC_OPT_BOM) ? 3 : 0)); Encode_UTF8(cp, size, bp, &len, FALSE, ccr); } else if (GET_FLAG(opts, ENC_OPT_NO_COPY)) return 0; else return Copy_Bytes(bp, len); } SERIES_TAIL(ser) = len; STR_TERM(ser); return Copy_Bytes(BIN_HEAD(ser), len); }
*/ void Append_Mem_Extra(REBSER *series, const REBYTE *data, REBCNT len, REBCNT extra) /* ** An optimized function for appending raw memory bytes to ** a byte-sized series. The series will be expanded if room ** is needed. A zero terminator will be added at the tail. ** The extra size will be assured in the series, but is not ** part of the appended length. (Allows adding additional bytes.) ** ***********************************************************************/ { REBCNT tail = series->tail; if ((tail + len + extra + 1) >= SERIES_REST(series)) { Expand_Series(series, tail, len+extra); // series->tail changed series->tail -= extra; } else { series->tail += len; } memcpy(series->data + tail, data, len); STR_TERM(series); }