aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/old/vlib/net/http/chunked/dechunk.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/old/vlib/net/http/chunked/dechunk.v')
-rw-r--r--v_windows/v/old/vlib/net/http/chunked/dechunk.v72
1 files changed, 72 insertions, 0 deletions
diff --git a/v_windows/v/old/vlib/net/http/chunked/dechunk.v b/v_windows/v/old/vlib/net/http/chunked/dechunk.v
new file mode 100644
index 0000000..0e82586
--- /dev/null
+++ b/v_windows/v/old/vlib/net/http/chunked/dechunk.v
@@ -0,0 +1,72 @@
+module chunked
+
+import strings
+// See: https://en.wikipedia.org/wiki/Chunked_transfer_encoding
+// /////////////////////////////////////////////////////////////
+// The chunk size is transferred as a hexadecimal number
+// followed by \r\n as a line separator,
+// followed by a chunk of data of the given size.
+// The end is marked with a chunk with size 0.
+
+struct ChunkScanner {
+mut:
+ pos int
+ text string
+}
+
+fn (mut s ChunkScanner) read_chunk_size() int {
+ mut n := 0
+ for {
+ if s.pos >= s.text.len {
+ break
+ }
+ c := s.text[s.pos]
+ if !c.is_hex_digit() {
+ break
+ }
+ n = n << 4
+ n += int(unhex(c))
+ s.pos++
+ }
+ return n
+}
+
+fn unhex(c byte) byte {
+ if `0` <= c && c <= `9` {
+ return c - `0`
+ } else if `a` <= c && c <= `f` {
+ return c - `a` + 10
+ } else if `A` <= c && c <= `F` {
+ return c - `A` + 10
+ }
+ return 0
+}
+
+fn (mut s ChunkScanner) skip_crlf() {
+ s.pos += 2
+}
+
+fn (mut s ChunkScanner) read_chunk(chunksize int) string {
+ startpos := s.pos
+ s.pos += chunksize
+ return s.text[startpos..s.pos]
+}
+
+pub fn decode(text string) string {
+ mut sb := strings.new_builder(100)
+ mut cscanner := ChunkScanner{
+ pos: 0
+ text: text
+ }
+ for {
+ csize := cscanner.read_chunk_size()
+ if 0 == csize {
+ break
+ }
+ cscanner.skip_crlf()
+ sb.write_string(cscanner.read_chunk(csize))
+ cscanner.skip_crlf()
+ }
+ cscanner.skip_crlf()
+ return sb.str()
+}