readline

greensnakeru/sollartrack/readline

No description
readline
@/readline
CHARbyte
A new character to be pushed to the end of the string line
PUSHpulse
Push new character
RSTpulse
Empty the accumulated string line and start over
readline
LINE
DONE
CHAR
PUSH
RST
DONEpulse
Fires on a new accumulated line
LINEstring
Accumulated line
To use the node in your project you should have the greensnakeru/sollartrack 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

/*
 * A list constructor based on double buffering technique. The front buffer
 * is immutable and read-only while an algorithm constructs a new list
 * behind the scenes using the back buffer.
 *
 * Once the back buffer is ready, the algorithm swaps the buffers and starts
 * over: now the buffer that used to be on back plays the role of front buffer
 * and vice versa.
 *
 * Use this class to accumulate some sparse stream of items into a list when
 * presenting an intermediate result to consumers is unacceptable, the
 * consumers will sDoubleBufferee the latest “published” result instead.
 *
 * `CAP` defines the maximal length of the list (in items). An instance of
 * double buffer consumes 2xCAP memory to hold two buffers at a time.
 */

template<size_t CAP>
class DoubleBuffer {
  public:
    DoubleBuffer()
            : _active_buff0(false)
    { }

    void eraseBackBuffer(){
        memset(backBuffer(), '\0', CAP);
    }

    void swap(){
        _active_buff0 = !_active_buff0;
    }

    char* backBuffer() {
        return _active_buff0 ? _buff1 : _buff0;
    }

    const char* frontBuffer() const {
        return _active_buff0 ? _buff0 : _buff1;
    }

  private:
    char _buff0[CAP];
    char _buff1[CAP];
    bool _active_buff0;
};


struct State {
    char* cursor;
    CStringView view;
    DoubleBuffer<16> mbuf;
};

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx);

    if (isSettingUp()) {
        state->view = CStringView(state->mbuf.frontBuffer());
    }
    if (isInputDirty<input_RST>(ctx)){
        state->mbuf.eraseBackBuffer();
        state->cursor = state->mbuf.backBuffer();
    }

    if (isInputDirty<input_PUSH>(ctx)) {
        if (getValue<input_CHAR>(ctx) == '\n'){
             state->mbuf.swap();
            emitValue<output_LINE>(ctx, XString(&state->view));
            emitValue<output_DONE>(ctx,1);
        }
        if (getValue<input_CHAR>(ctx) != '\r'){
            *state->cursor = getValue<input_CHAR>(ctx);
            state->cursor++;
        }
    }
}