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

bblanchon / ArduinoStreamUtils / 9791005483

04 Jul 2024 08:26AM UTC coverage: 98.054% (+1.5%) from 96.597%
9791005483

push

github

bblanchon
Test trailers

907 of 925 relevant lines covered (98.05%)

1479.68 hits per line

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

92.86
/src/StreamUtils/Policies/ChunkDecodingPolicy.hpp
1
// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
2
// Copyright Benoit Blanchon 2019-2024
3
// MIT License
4

5
#pragma once
6

7
#include <Client.h>
8
#include <assert.h>
9

10
namespace StreamUtils {
11

12
class ChunkDecodingPolicy {
13
  enum class State {
14
    Size,
15
    Extensions,
16
    StartCrLf,
17
    EndCrLf,
18
    Body,
19
    Error,
20
  };
21

22
 public:
23
  int available(Stream &target) {
120✔
24
    if (!isInChunkBody(target))
120✔
25
      return 0;
48✔
26
    return min(target.available(), remaining_);
72✔
27
  }
28

29
  int read(Stream &target) {
906✔
30
    if (!isInChunkBody(target))
906✔
31
      return -1;
141✔
32
    int c = target.read();
765✔
33
    if (c >= 0)
765✔
34
      decreaseRemaining(1);
765✔
35
    return c;
765✔
36
  }
37

38
  int peek(Stream &target) {
60✔
39
    if (!isInChunkBody(target))
60✔
40
      return -1;
24✔
41
    return target.peek();
36✔
42
  }
43

44
  size_t readBytes(Stream &target, char *buffer, size_t size) {
27✔
45
    if (!isInChunkBody(target))
27✔
46
      return 0;
×
47
    size_t n = target.readBytes(buffer, min(size, remaining_));
27✔
48
    decreaseRemaining(n);
27✔
49
    return n;
27✔
50
  }
51

52
  int read(Client &target, uint8_t *buffer, size_t size) {
53
    return readBytes(target, reinterpret_cast<char *>(buffer), size);
54
  }
55

56
 private:
57
  bool isInChunkBody(Stream &target) {
1,113✔
58
    while (state_ != State::Error && state_ != State::Body &&
3,990✔
59
           target.available()) {
1,533✔
60
      state_ = injestNext(target);
1,344✔
61
    }
62
    return state_ == State::Body;
1,113✔
63
  }
64

65
  State injestNext(Stream &target) {
1,344✔
66
    int c = target.read();
1,344✔
67
    switch (state_) {
1,344✔
68
      case State::Size:
396✔
69
        if (c >= '0' && c <= '9')
396✔
70
          return appendSizeHexDigit(c - '0');
144✔
71
        else if (c >= 'A' && c <= 'F')
252✔
72
          return appendSizeHexDigit(c - 'A' + 10);
24✔
73
        else if (c >= 'a' && c <= 'f')
228✔
74
          return appendSizeHexDigit(c - 'a' + 10);
36✔
75
        else if (c == '\r')
192✔
76
          return State::StartCrLf;
132✔
77
        else if (c == ' ' || c == '\t' || c == ';')
60✔
78
          return State::Extensions;
48✔
79
        else
80
          return State::Error;
12✔
81

82
      case State::Extensions:
408✔
83
        if (c == '\r')
408✔
84
          return State::StartCrLf;
48✔
85
        else
86
          return State::Extensions;
360✔
87

88
      case State::StartCrLf:
180✔
89
        if (c == '\n') {
180✔
90
          if (remaining_ == 0)
180✔
91
            return State::EndCrLf;
36✔
92
          else
93
            return State::Body;
144✔
94
        } else
95
          return State::Error;
×
96

97
      case State::EndCrLf:
360✔
98
        if (c == '\r')
360✔
99
          return State::EndCrLf;
180✔
100
        else if (c == '\n')
180✔
101
          return State::Size;
180✔
102
        else
103
          return State::Error;
×
104

105
      default:
×
106
        assert(false);
×
107
        return State::Error;
108
    }
109
  }
110

111
  State appendSizeHexDigit(uint8_t digit) {
204✔
112
    remaining_ = remaining_ * 16 + digit;
204✔
113
    return State::Size;
204✔
114
  }
115

116
  void decreaseRemaining(size_t n) {
792✔
117
    assert(remaining_ >= n);
792✔
118
    remaining_ -= n;
792✔
119
    if (remaining_ == 0)
792✔
120
      state_ = State::EndCrLf;
144✔
121
  }
792✔
122

123
  size_t min(size_t a, size_t b) {
99✔
124
    return a < b ? a : b;
99✔
125
  }
126

127
  size_t remaining_ = 0;
128
  State state_ = State::Size;
129
};
130

131
}  // namespace StreamUtils
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

© 2026 Coveralls, Inc