Shift register for string

I have the ability to write characters to a string, and read a character by its index from the string. The last thing you need is to make a shift register for characters. Maybe it can be done with “accumulate string”, change the C++ code a little. When the line is full, and a new character appears, all previous characters are displaced. (The first disappeared, the second became the first, the third became the second…). Thank you all in advance!

It is not very efficient, but you can use gweimer/utils/queue-buffer. You need one node for each character you want to store. utils-example-queue shows example to provide both FIFO like you want & FILO stack implementation.

You can run each queue-buffer MEM output to an nth-input node to select the character you want from the queue.

1 Like

Thank you very much for your reply. This is a good solution, but in my case the length of the string can increase to 10 or even 40 characters. So I’m looking for something that won’t make the program bulky. What else do you recommend?

I don’t know how robust this code is, but it seems to work. I copied the accumulating-string node, added input-byte IDX, output-byte OUT, and output-byte POP. I called it string-queue

replace code with this:

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_OUT>(ctx, 0);
            emitValue<output_POP>(ctx, 0);

        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 = getValue<input_CHAR>(ctx);
            if (cursor < &buff[cap]) {
            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)]);

OUT is the value for IDX in array (0 if IDX is bigger than current array size) This is zero-based, so if CAP is 5, the highest IDX is 4.
POP is the last byte pushed off to make room for the next input char.

The FULL output pin could be changed from pulse to boolean. RST code should add emit to force it to zero if this is done.

There is an off-by-one error in above code that causes string buffer to over-flow. I have fixed it in the copy I added to gweimer/utils — XOD v0.3.0. Included is utils-example-string-queue I used for testing the node.

There is still a problem with this node. I don’t know if I’m doing something wrong, or I’ve found a bug in XOD. It appears that output-string does not update if the new string is empty. When you reset node, internal state and other pins update correctly, but STR pin will show old string until next push when it updates with the new 1-byte string.

I also changed the FULL pin to a boolean so it is easy to determine if you have a partial string or you will loose a value if you push again. If you want a pulse like accumulate-string, you should be able to copy the node & change pin type without changing any other code.

1 Like

Hey there,
I can see that you are looking for help with implementing a shift register for strings in XOD. You might try breaking down your problem into smaller steps. First, consider how you’ll represent the string internally, perhaps as an array of characters. Then, design the logic to shift these characters through the register. If you encounter any specific hurdles or need clarification on certain aspects, feel free to ask!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.