shift-string

nazarijtipusak080/accumulate-and-read-character-string/shift-string

Generated from gweimer/utils/string-queue. This is a character accumulator in the form of "NUMBER", which after filling with the number of characters specified in "CAP" switches to SHIFT-STRING mode.
shift-string
@/shift-string
Generated from gweimer/utils/string-queue. This is a character accumulator in the form of "NUMBER", which after filling with the number of characters specified in "CAP" switches to SHIFT-STRING mode.
CAPnumber
The capacity of the string buffer. Defines the maximum length. Must be a constant value. Any changes during program execution will be ignored.
CHARnumber
A new character to be pushed to the end of the string
PUSHpulse
Push new character
RSTpulse
Empty the accumulated string and start over
IDXbyte
Display IDX character of string. This is 0-based, so range is 0 - (CAP-1)
shift-string
CAP
CHAR
PUSH
RST
IDX
STR
UPD
FULL
OUT
POP
POPnumber
Last character popped of front of string to make room for next CHAR
OUTnumber
IDX character in string (0 if IDX is larger than current size of string)
FULLboolean
True once string is at capacity
UPDpulse
Pulses when resulting string is updated
STRstring
String that is accumulated so far
To use the node in your project you should have the nazarijtipusak080/accumulate-and-read-character-string library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.

C++ implementation

node {
    char* buff;
    char* cursor;
    size_t cap;
    CStringView view;

    void evaluate(Context ctx) {
        if (isSettingUp()) {
            // save initial cap to ignore possiple input changes during program execution
            cap = getValue<input_CAP>(ctx);
            buff = new char[cap + 1]; // +1 to make room for terminal '\0'
            view = CStringView(buff);
        }

        if (isSettingUp() || isInputDirty<input_RST>(ctx)) {
            memset(buff, '\0', cap + 1);
            cursor = buff;
            emitValue<output_FULL>(ctx, 0);
            emitValue<output_OUT>(ctx, 0);
            emitValue<output_POP>(ctx, 0);
            emitValue<output_STR>(ctx, XString(&view));
            emitValue<output_UPD>(ctx, 1);
        }

        if (isInputDirty<input_PUSH>(ctx)) {
            if (cursor >= &buff[cap]) {
                emitValue<output_FULL>(ctx, 1);
                emitValue<output_POP>(ctx, buff[0]);
                for (auto i=0; i < cap; i++) {
                    buff[i] = buff[i+1];
                }
                cursor = &buff[cap-1];
            }

            *cursor = getValue<input_CHAR>(ctx);
            if (cursor < &buff[cap]) {
                cursor++;
            }
            emitValue<output_STR>(ctx, XString(&view));
            emitValue<output_UPD>(ctx, 1);
        }

        if (isInputDirty<input_IDX>(ctx) || isInputDirty<input_PUSH>(ctx)) {
            emitValue<output_OUT>(ctx, buff[getValue<input_IDX>(ctx)]);
        }
    }
}