aboutsummaryrefslogtreecommitdiffstats
path: root/vespajlib/src/main/java/com/yahoo/text/PositionedString.java
blob: aca0b7d1259a8daca26d8e74e8ae68ee483d0441 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.text;

/**
 * A string which has a current position.
 * Useful for writing simple single-pass parsers.
 *
 * @author bratseth
 */
public class PositionedString {

    private final String s;
    private int p;

    /**
     * Creates this from a given string.
     */
    public PositionedString(String string) {
        this.s=string;
    }

    /** The complete string value of this */
    public String string() { return s; }

    /** The current position into this string */
    public int position() { return p; }

    /** Assigns the current position in the string  */
    public void setPosition(int position) { p=position; }

    /**
     * Consumes the character at this position.
     * <br>Precondition: The character at this position is c.
     * <br>Postcondition: The position is increased by 1
     *
     * @param c the expected character at this
     * @throws IllegalArgumentException if the character at this position is not c
     */
    public void consume(char c) {
        if (s.charAt(p++)!=c)
            throw new IllegalArgumentException("Expected '" + c + "' " + at(p -1));
    }

    /**
     * Consumes zero or more whitespace characters starting at the current position
     */
    public void consumeSpaces() {
        while (Character.isWhitespace(s.charAt(p)))
            p++;
    }

    /**
     * Advances the position by 1 if the character at the current position is c.
     * Does nothing otherwise.
     *
     * @return whether this consumed a c at the current position, or if it did nothing
     */
    public boolean consumeOptional(char c) {
        if (s.charAt(p)!=c) return false;
        p++;
        return true;
    }

    /**
     * Returns whether the character at the current position is c.
     */
    public boolean peek(char c) {
        return s.charAt(p)==c;
    }

    /**
     * Returns the position of the next occurrence of c,
     * or -1 if there are no occurrences of c in the string after the current position.
     */
    public int indexOf(char c) {
        return s.indexOf(c,p);
    }

    /** Adds n to the current position */
    public void skip(int n) {
        p = p +n;
    }

    /**
     * Sets the position of this to the next occurrence of c after the current position.
     *
     * @param c the char to move the position to
     * @return the substring between the current position and the new position at c
     * @throws IllegalArgumentException if there was no occurrence of c after the current position
     */
    public String consumeTo(char c) {
        int nextC=indexOf(c);
        if (nextC<0)
            throw new IllegalArgumentException("Expected a string terminated by '" + c + "' " + at());
        String value=substring(nextC);
        p=nextC;
        return  value;
    }

    /**
     * Returns the substring between the current position and <code>position</code>
     * and advances the current position to <code>position</code>
     */
    public String consumeToPosition(int position) {
        String consumed=substring(position);
        p=position;
        return consumed;
    }

    /** Returns a substring of this from the current position to the end argument */
    public String substring(int end) {
        return string().substring(position(),end);
    }

    /** Returns the substring of this string from the current position to the end */
    public String substring() {
        return string().substring(position());
    }

    /** Returns a textual description of the current position, useful for appending to error messages. */
    public String at() {
        return at(p);
    }

    /** Returns a textual description of a given position, useful for appending to error messages. */
    public String at(int position) {
        return "starting at position " + position + " but was '" + s.charAt(position) + "'";
    }

    /** Returns the string */
    @Override
    public String toString() {
        return s;
    }

}