• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

coditory / quark-uri / #3

pending completion
#3

push

github-actions

ogesaku
init

1212 of 1212 new or added lines in 21 files covered. (100.0%)

926 of 1212 relevant lines covered (76.4%)

0.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.15
/src/main/java/com/coditory/quark/uri/PercentEncoder.java
1
package com.coditory.quark.uri;
2

3
import java.io.CharArrayWriter;
4
import java.nio.charset.Charset;
5
import java.util.BitSet;
6

7
import static com.coditory.quark.uri.BitSets.unmodifiableBitSet;
8
import static com.coditory.quark.uri.Preconditions.expectNonNull;
9
import static com.coditory.quark.uri.UriRfcCharacters.URI_UNRESERVED;
10
import static java.nio.charset.StandardCharsets.UTF_8;
11

12
final class PercentEncoder {
13
    private static final int CASE_DIFF = ('a' - 'A');
14
    private final boolean spaceAsPlus;
15
    private final Charset charset;
16
    private final BitSet safeCharacters;
17

18
    private PercentEncoder(BitSet safeCharacters, boolean spaceAsPlus, Charset charset) {
1✔
19
        this.spaceAsPlus = spaceAsPlus;
1✔
20
        this.charset = expectNonNull(charset, "charset");
1✔
21
        this.safeCharacters = expectNonNull(safeCharacters, "safeCharacters");
1✔
22
    }
1✔
23

24
    String encode(String text) {
25
        StringBuilder dst = new StringBuilder();
1✔
26
        encode(text, dst);
1✔
27
        return dst.toString();
1✔
28
    }
29

30
    boolean encode(String text, StringBuilder dst) {
31
        return encode(text, dst, charset);
1✔
32
    }
33

34
    boolean encode(String text, StringBuilder dst, Charset charset) {
35
        expectNonNull(dst, "dst");
1✔
36
        expectNonNull(text, "text");
1✔
37
        expectNonNull(charset, "charset");
1✔
38
        boolean needToChange = false;
1✔
39
        StringBuilder out = new StringBuilder(text.length());
1✔
40
        CharArrayWriter charArrayWriter = new CharArrayWriter();
1✔
41

42
        for (int i = 0; i < text.length(); ) {
1✔
43
            int cp = text.codePointAt(i);
1✔
44
            if (cp == ' ' && spaceAsPlus) {
1✔
45
                out.append('+');
1✔
46
                needToChange = true;
1✔
47
                i++;
1✔
48
            } else if (safeCharacters.get(cp) && (cp != '+' || !spaceAsPlus)) {
1✔
49
                out.appendCodePoint(cp);
1✔
50
                i += Character.charCount(cp);
1✔
51
            } else {
52
                do {
53
                    char c = text.charAt(i);
1✔
54
                    charArrayWriter.write(c);
1✔
55
                    if (c >= 0xD800 && c <= 0xDBFF) {
1✔
56
                        if ((i + 1) < text.length()) {
1✔
57
                            char d = text.charAt(i + 1);
1✔
58
                            if (d >= 0xDC00 && d <= 0xDFFF) {
1✔
59
                                charArrayWriter.write(d);
1✔
60
                                i++;
1✔
61
                            }
62
                        }
63
                    }
64
                    i++;
1✔
65
                } while (i < text.length() && !safeCharacters.get(text.codePointAt(i)));
1✔
66
                charArrayWriter.flush();
1✔
67
                byte[] bytes = new String(charArrayWriter.toCharArray())
1✔
68
                        .getBytes(charset);
1✔
69
                for (byte aByte : bytes) {
1✔
70
                    out.append('%');
1✔
71
                    char c = Character.forDigit((aByte >> 4) & 0xF, 16);
1✔
72
                    if (Character.isLetter(c)) {
1✔
73
                        c -= CASE_DIFF;
1✔
74
                    }
75
                    out.append(c);
1✔
76
                    c = Character.forDigit(aByte & 0xF, 16);
1✔
77
                    if (Character.isLetter(c)) {
1✔
78
                        c -= CASE_DIFF;
1✔
79
                    }
80
                    out.append(c);
1✔
81
                }
82
                charArrayWriter.reset();
1✔
83
                needToChange = true;
1✔
84
            }
85
        }
1✔
86
        dst.append(out);
1✔
87
        return needToChange;
1✔
88
    }
89

90
    static PercentEncoderBuilder builder() {
91
        return new PercentEncoderBuilder();
1✔
92
    }
93

94
    static class PercentEncoderBuilder {
1✔
95
        private BitSet safeCharacters = BitSets.of(URI_UNRESERVED);
1✔
96
        private boolean spaceAsPlus = false;
1✔
97
        private Charset charset = UTF_8;
1✔
98

99
        PercentEncoderBuilder addSafeCharacters(String safeCharacters) {
100
            expectNonNull(safeCharacters, "safeCharacters");
×
101
            return safeCharacters(BitSets.of(safeCharacters));
×
102
        }
103

104
        PercentEncoderBuilder safeCharactersAsUriUnreserved() {
105
            return safeCharacters(URI_UNRESERVED);
×
106
        }
107

108
        PercentEncoderBuilder safeCharacters(BitSet safeCharacters) {
109
            expectNonNull(safeCharacters, "safeCharacters");
1✔
110
            this.safeCharacters = unmodifiableBitSet(safeCharacters);
1✔
111
            return this;
1✔
112
        }
113

114
        PercentEncoderBuilder safeCharacters(String safeCharacters) {
115
            expectNonNull(safeCharacters, "safeCharacters");
×
116
            return safeCharacters(BitSets.of(safeCharacters));
×
117
        }
118

119
        PercentEncoderBuilder spaceAsPlus(boolean spaceAsPlus) {
120
            this.spaceAsPlus = spaceAsPlus;
1✔
121
            return this;
1✔
122
        }
123

124
        PercentEncoderBuilder charset(Charset charset) {
125
            expectNonNull(charset, "charset");
1✔
126
            this.charset = charset;
1✔
127
            return this;
1✔
128
        }
129

130
        PercentEncoder build() {
131
            if (spaceAsPlus) {
1✔
132
                safeCharacters = BitSets.set(safeCharacters, '+', false);
1✔
133
            }
134
            return new PercentEncoder(safeCharacters, spaceAsPlus, charset);
1✔
135
        }
136
    }
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc