*/ void Expand_Hash(REBSER *ser) /* ** Expand hash series. Clear it but set its tail. ** ***********************************************************************/ { REBSER oser; REBSER *nser; REBINT pnum; pnum = Get_Hash_Prime(ser->tail+1); if (!pnum) Trap_Num(RE_SIZE_LIMIT, ser->tail+1); nser = Make_Series(pnum+1, SERIES_WIDE(ser), TRUE); LABEL_SERIES(nser, "hash series"); oser = *ser; *ser = *nser; ser->info = oser.info; *nser = oser; Clear_Series(ser); ser->tail = pnum; Free_Series(nser); }
*/ REBSER *Make_Unicode(REBCNT length) /* ** Make a unicode string series. Used for internal strings. ** Add 1 extra for terminator. ** ***********************************************************************/ { REBSER *series = Make_Series(length + 1, sizeof(REBUNI), MKS_NONE); LABEL_SERIES(series, "make unicode"); // !!! Clients seem to have different expectations of if `length` is // total capacity (and the binary should be empty) or actually is // specifically being preallocated at a fixed length. Until this // is straightened out, terminate for both possibilities. UNI_HEAD(series)[length] = 0; TERM_SEQUENCE(series); return series; }
*/ REBSER *Make_Binary(REBCNT length) /* ** Make a binary string series. For byte, C, and UTF8 strings. ** Add 1 extra for terminator. ** ***********************************************************************/ { REBSER *series = Make_Series(length + 1, sizeof(REBYTE), MKS_NONE); LABEL_SERIES(series, "make binary"); // !!! Clients seem to have different expectations of if `length` is // total capacity (and the binary should be empty) or actually is // specifically being preallocated at a fixed length. Until this // is straightened out, terminate for both possibilities. BIN_DATA(series)[length] = 0; TERM_SEQUENCE(series); return series; }
*/ static void Insert_Gobs(REBGOB *gob, REBVAL *arg, REBCNT index, REBCNT len, REBFLG change) /* ** Insert one or more gobs into a pane at the given index. ** If index >= tail, an append occurs. Each gob has its parent ** gob field set. (Call Detach_Gobs() before inserting.) ** ***********************************************************************/ { REBGOB **ptr; REBCNT n, count; REBVAL *val, *sarg; REBINT i; // Verify they are gobs: sarg = arg; for (n = count = 0; n < len; n++, val++) { val = arg++; if (IS_WORD(val)) val = Get_Var(val); if (IS_GOB(val)) { count++; if (GOB_PARENT(VAL_GOB(val))) { // Check if inserting into same parent: i = -1; if (GOB_PARENT(VAL_GOB(val)) == gob) { i = Find_Gob(gob, VAL_GOB(val)); if (i > 0 && i == (REBINT)index-1) { // a no-op SET_GOB_STATE(VAL_GOB(val), GOBS_NEW); return; } } Detach_Gob(VAL_GOB(val)); if ((REBINT)index > i) index--; } } } arg = sarg; // Create or expand the pane series: if (!GOB_PANE(gob)) { GOB_PANE(gob) = Make_Series(count, sizeof(REBGOB*), 0); LABEL_SERIES(GOB_PANE(gob), "gob pane"); GOB_TAIL(gob) = count; index = 0; } else { if (change) { if (index + count > GOB_TAIL(gob)) { EXPAND_SERIES_TAIL(GOB_PANE(gob), index + count - GOB_TAIL(gob)); } } else { Expand_Series(GOB_PANE(gob), index, count); if (index >= GOB_TAIL(gob)) index = GOB_TAIL(gob)-1; } } ptr = GOB_SKIP(gob, index); for (n = 0; n < len; n++) { val = arg++; if (IS_WORD(val)) val = Get_Var(val); if (IS_GOB(val)) { if GOB_PARENT(VAL_GOB(val)) Trap_Temp(); *ptr++ = VAL_GOB(val); GOB_PARENT(VAL_GOB(val)) = gob; SET_GOB_STATE(VAL_GOB(val), GOBS_NEW); } } }