• 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.33
/src/main/java/com/coditory/quark/uri/PercentDecoder.java
1
package com.coditory.quark.uri;
2

3
import java.nio.charset.Charset;
4

5
import static com.coditory.quark.uri.Preconditions.expectNonNull;
6
import static java.nio.charset.StandardCharsets.UTF_8;
7

8
final class PercentDecoder {
9
    private final Charset charset;
10
    private final boolean spaceAsPlus;
11

12
    private PercentDecoder(boolean spaceAsPlus, Charset charset) {
1✔
13
        this.spaceAsPlus = spaceAsPlus;
1✔
14
        this.charset = expectNonNull(charset, "charset");
1✔
15
    }
1✔
16

17
    String decode(String text) {
18
        StringBuilder dst = new StringBuilder();
1✔
19
        decode(text, dst);
1✔
20
        return dst.toString();
1✔
21
    }
22

23
    boolean decode(String text, StringBuilder dst) {
24
        return decode(text, dst, charset);
1✔
25
    }
26

27
    boolean decode(String text, StringBuilder dst, Charset charset) {
28
        expectNonNull(dst, "dst");
1✔
29
        expectNonNull(text, "text");
1✔
30
        expectNonNull(charset, "charset");
1✔
31
        boolean needToChange = false;
1✔
32
        int length = text.length();
1✔
33
        StringBuilder sb = new StringBuilder(length > 500 ? length / 2 : length);
1✔
34
        int i = 0;
1✔
35
        byte[] bytes = null;
1✔
36
        while (i < length) {
1✔
37
            char c = text.charAt(i);
1✔
38
            switch (c) {
1✔
39
                case '+' -> {
40
                    if (!spaceAsPlus) {
1✔
41
                        sb.append('+');
1✔
42
                    } else {
43
                        sb.append(' ');
1✔
44
                        needToChange = true;
1✔
45
                    }
46
                    i++;
1✔
47
                }
1✔
48
                case '%' -> {
49
                    try {
50
                        if (bytes == null) {
1✔
51
                            bytes = new byte[(length - i) / 3];
1✔
52
                        }
53
                        int pos = 0;
1✔
54
                        while ((i + 2) < length && c == '%') {
1✔
55
                            int v = Integer.parseInt(text, i + 1, i + 3, 16);
1✔
56
                            if (v < 0) {
1✔
57
                                throw new IllegalArgumentException("Illegal hex characters in escape (%) pattern - negative value");
×
58
                            }
59
                            bytes[pos++] = (byte) v;
1✔
60
                            i += 3;
1✔
61
                            if (i < length) {
1✔
62
                                c = text.charAt(i);
1✔
63
                            }
64
                        }
1✔
65
                        if (i < length && c == '%') {
1✔
66
                            throw new IllegalArgumentException("Incomplete trailing escape (%) pattern");
×
67
                        }
68
                        sb.append(new String(bytes, 0, pos, charset));
1✔
69
                    } catch (NumberFormatException e) {
×
70
                        throw new IllegalArgumentException("Illegal hex characters in escape (%) pattern - " + e.getMessage());
×
71
                    }
1✔
72
                    needToChange = true;
1✔
73
                }
1✔
74
                default -> {
75
                    sb.append(c);
1✔
76
                    i++;
1✔
77
                }
78
            }
79
        }
1✔
80
        dst.append(sb);
1✔
81
        return needToChange;
1✔
82
    }
83

84
    static PercentDecoderBuilder builder() {
85
        return new PercentDecoderBuilder();
1✔
86
    }
87

88
    static class PercentDecoderBuilder {
1✔
89
        private boolean spaceAsPlus = false;
1✔
90
        private Charset charset = UTF_8;
1✔
91

92
        public PercentDecoderBuilder spaceAsPlus(boolean spaceAsPlus) {
93
            this.spaceAsPlus = spaceAsPlus;
1✔
94
            return this;
1✔
95
        }
96

97
        public PercentDecoderBuilder charset(Charset charset) {
98
            expectNonNull(charset, "charset");
1✔
99
            this.charset = charset;
1✔
100
            return this;
1✔
101
        }
102

103
        public PercentDecoder build() {
104
            return new PercentDecoder(spaceAsPlus, charset);
1✔
105
        }
106
    }
107
}
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