<commit_before>package com.github.davidmoten.rx2.internal.flowable;

import com.github.davidmoten.guavamini.annotations.VisibleForTesting;

/**
 * Enables a forward-only iteration of string values split by a delimiter across
 * a linked list of strings.
 */
public final class DelimitedStringLinkedList {

    private final String delimiter;

    private Node head;
    private Node tail;
    private int headPosition;
    private Node searchNode;
    private int searchPosition;
    private int nextLength;
    private boolean added;

    public DelimitedStringLinkedList(String delimiter) {
        this.delimiter = delimiter;
    }

    @VisibleForTesting
    int searchPosition() {
        return searchPosition;
    }

    private static final class Node {
        final String value;
        Node next;

        Node(String value, Node next) {
            this.value = value;
            this.next = next;
        }

        @Override
        public String toString() {
            return "Node [value=" + value + ", next=" + next + "]";
        }
    }

    public boolean addCalled() {
        return added;
    }

    public void add(String s) {
        added = true;
        if (s.length() == 0) {
            return;
        }
        if (head == null) {
            head = new Node(s, null);
            tail = head;
            headPosition = 0;
            searchPosition = 0;
            searchNode = head;
            nextLength = 0;
        } else {
            Node node = new Node(s, null);
            tail.next = node;
            tail = node;
            if (searchNode == null) {
                searchNode = node;
                searchPosition = 0;
            }
        }
    }

    public String remaining() {
        if (head == null) {
            return null;
        } else {
            StringBuilder b = new StringBuilder();
            Node n = head;
            do {
                if (n == head) {
                    b.append(n.value.substring(headPosition, n.value.length()));
                } else {
                    b.append(n.value);
                }
                n = n.next;
            } while (n != null);
            return b.toString();
        }
    }

    public String next() {
        while (searchNode != null) {
            if (searchNode.value.charAt(searchPosition) == delimiter.charAt(0)) {
                Node nd = searchNode;
                int pos = searchPosition + 1;
                int j = 1;
                while (j < delimiter.length()) {
                    if (pos == nd.value.length()) {
                        if (nd.next == null) {
                            break;
                        }
                        nd = nd.next;
                        pos = 0;
                    }
                    if (nd.value.charAt(pos) != delimiter.charAt(j)) {
                        break;
                    }
                    j++;
                    pos++;
                }
                boolean found = j == delimiter.length();
                if (found) {
                    // at this point (nd, pos) is the location of the end of
                    // next + delimiter
                    // (node, position) is at next + 1

                    // extract string
                    StringBuilder b = new StringBuilder(nextLength);
                    Node n = head;
                    while (true) {
                        if (n == searchNode && n == head) {
                            b.append(n.value.substring(headPosition, searchPosition));
                            break;
                        } else if (n == head) {
                            b.append(n.value.substring(headPosition, n.value.length()));
                        } else if (n == searchNode) {
                            b.append(n.value.substring(0, searchPosition));
                            break;
                        } else {
                            b.append(n.value);
                        }
                        n = n.next;<commit_msg>perf improvements on SplitSimple<commit_after>package com.github.davidmoten.rx2.internal.flowable;

import com.github.davidmoten.guavamini.annotations.VisibleForTesting;

/**
 * Enables a forward-only iteration of string values split by a delimiter across
 * a linked list of strings.
 */
public final class DelimitedStringLinkedList {

    private final String delimiter;
    private final StringBuilder b = new StringBuilder();

    private Node head;
    private Node tail;
    private int headPosition;
    private Node searchNode;
    private int searchPosition;
    private int nextLength;
    private boolean added;
    

    public DelimitedStringLinkedList(String delimiter) {
        this.delimiter = delimiter;
    }

    @VisibleForTesting
    int searchPosition() {
        return searchPosition;
    }

    private static final class Node {
        final String value;
        Node next;

        Node(String value, Node next) {
            this.value = value;
            this.next = next;
        }

        @Override
        public String toString() {
            return "Node [value=" + value + ", next=" + next + "]";
        }
    }

    public boolean addCalled() {
        return added;
    }

    public void add(String s) {
        added = true;
        if (s.length() == 0) {
            return;
        }
        if (head == null) {
            head = new Node(s, null);
            tail = head;
            headPosition = 0;
            searchPosition = 0;
            searchNode = head;
            nextLength = 0;
        } else {
            Node node = new Node(s, null);
            tail.next = node;
            tail = node;
            if (searchNode == null) {
                searchNode = node;
                searchPosition = 0;
            }
        }
    }

    public String remaining() {
        if (head == null) {
            return null;
        } else {
            StringBuilder b = new StringBuilder();
            Node n = head;
            do {
                if (n == head) {
                    b.append(n.value.substring(headPosition, n.value.length()));
                } else {
                    b.append(n.value);
                }
                n = n.next;
            } while (n != null);
            return b.toString();
        }
    }

    public String next() {
        while (searchNode != null) {
            if (searchNode.value.charAt(searchPosition) == delimiter.charAt(0)) {
                Node nd = searchNode;
                int pos = searchPosition + 1;
                int j = 1;
                while (j < delimiter.length()) {
                    if (pos == nd.value.length()) {
                        if (nd.next == null) {
                            break;
                        }
                        nd = nd.next;
                        pos = 0;
                    }
                    if (nd.value.charAt(pos) != delimiter.charAt(j)) {
                        break;
                    }
                    j++;
                    pos++;
                }
                boolean found = j == delimiter.length();
                if (found) {
                    // at this point (nd, pos) is the location of the end of
                    // next + delimiter
                    // (node, position) is at next + 1

                    // extract string
                    b.setLength(0);
                    b.ensureCapacity(nextLength);
                    Node n = head;
                    while (true) {
                        if (n == searchNode && n == head) {
                            b.append(n.value.substring(headPosition, searchPosition));
                            break;
                        } else if (n == head) {
                            b.append(n.value.substring(headPosition, n.value.length()));
                        } else if (n == searchNode) {
                            b.append(n.value.substring(0, searchPosition));
                            break;
                        } else {
                            b.append(n.value);
                        }
                        n = n.next;
{'fraction_non_alphanumeric': 0.09476003917727718, 'fraction_numerical': 0.0030607247796278158, 'mean_word_length': 1.0791550012725883, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1699199', 'n_tokens_mistral': 2071, 'n_tokens_neox': 1954, 'n_words': 544}