<commit_before>namespace Sdk.Docker.Io {

    /**
     * Response from a socket request to a docker remote api
     */
    public class SocketResponseFactory : GLib.Object {

        public static Response create(DataInputStream stream) {
            Response response = new Response();

            try {
                extract_response_status_code(stream, response);
                stdout.printf("Response status : %d\n", response.status);

                extract_response_headers(stream, response);
                foreach (Gee.Map.Entry<string, string> header in response.headers.entries) {
                    stdout.printf("Response header : %s : %s\n", header.key, header.value);
                }

                if (stream.get_available() > 2) {
                    if (response.headers.has("Transfer-Encoding", "chunked")) {
                        extract_chunked_response_body(stream, response);
                    } else {
                        extract_known_content_lenght_response_body(stream, response);
                    }
                }

                stream.close();
                stdout.printf("Socket closed\n");

            } catch (IOError e) {
                throw e;
            }

            return response;
        }

        /**
         * Extract the response status code from the response stream
         */
        protected static void extract_response_status_code(DataInputStream stream, Response response) {

            try {
                string header_line = stream.read_line(null);

                Regex regex = new Regex("HTTP/(\\d.\\d) (\\d{3}) [a-zAZ]*");
                MatchInfo info;
                if (regex.match(header_line, 0, out info)){
                    response.status = int.parse(info.fetch(2));
                }

            } catch (RegexError e) {

            } catch (IOError e) {

            }

        }

        /**
         * Extract the response headers as a Hash table from the response stream
         */
        protected static void extract_response_headers(DataInputStream stream, Response response) {

            var headers = new Gee.HashMap<string, string>();
            string header_line;

            try {
                while ((header_line = stream.read_line(null)).strip() != "") {
                    string[] _header = header_line.split(":", 2);
                    headers.set(_header[0], _header[1].strip());
                }
            } catch (IOError e) {

            }

            response.headers = headers;
        }

        /**
         * Sync - Return the payload from response having a defined content-lenght header
         */
        private static void extract_known_content_lenght_response_body(DataInputStream stream, Response response)
        {
            string line = "";
            string payload = "";

            while (stream.get_available() > 0) {
                line = stream.read_line(null);
                payload += line.strip();
            }

            stdout.printf("Response payload : %s\n", payload);
            response.payload = payload;
        }

        /**
         * Sync - Return the payload from a chunked response
         */
        private static void extract_chunked_response_body(DataInputStream stream, Response response)
        {
            string line = "";
            string payload = "";

            int line_number = 0;
            while (true) {

                line = stream.read_line(null).strip();

                //In chunked transfer, don't consider empty lines
                if (line == "") {
                    continue;
                }

                //End of chnunked HTTP 1.1 transfert
                if (line == "0") {
                    break;
                }

                line_number++;

                //This line bear the next line size in bytes (in hex) ; it's not part of the payload
                if (1 == line_number % 2) {
                    continue;
                }

                payload += line;
            }

            stdout.printf("Response payload : %s\n", payload);
            response.payload = payload;
        }
    }
}<commit_msg>Refactor chunked and raw stream<commit_after>namespace Sdk.Docker.Io {

    /**
     * Response from a socket request to a docker remote api
     */
    public class SocketResponseFactory : GLib.Object {

        public static Response create(DataInputStream stream) {
            Response response = new Response();

            try {
                extract_response_status_code(stream, response);
                stdout.printf("Response status : %d\n", response.status);

                extract_response_headers(stream, response);
                foreach (Gee.Map.Entry<string, string> header in response.headers.entries) {
                    stdout.printf("Response header : %s : %s\n", header.key, header.value);
                }

                string line;
                string payload = "";

                while (stream.get_available() > 2) {

                    if (response.headers.has("Transfer-Encoding", "chunked")) {
                        //Reads the next chunk size. As I'm a bit lazy,I don't use them.
                        stream.read_line(null);
                    }

                    line = stream.read_line(null).strip();
                    //End of chunks
                    if (line == "0") {
                        break;
                    }

                    payload += line;
                }

                response.payload = payload;

                stream.close();
                stdout.printf("Socket closed\n");

            } catch (IOError e) {
                throw e;
            }

            return response;
        }

        /**
         * Extract the response status code from the response stream
         */
        protected static void extract_response_status_code(DataInputStream stream, Response response) {

            try {
                string header_line = stream.read_line(null);

                Regex regex = new Regex("HTTP/(\\d.\\d) (\\d{3}) [a-zAZ]*");
                MatchInfo info;
                if (regex.match(header_line, 0, out info)){
                    response.status = int.parse(info.fetch(2));
                }

            } catch (RegexError e) {

            } catch (IOError e) {

            }

        }

        /**
         * Extract the response headers as a Hash table from the response stream
         */
        protected static void extract_response_headers(DataInputStream stream, Response response) {

            var headers = new Gee.HashMap<string, string>();
            string header_line;

            try {
                while ((header_line = stream.read_line(null)).strip() != "") {
                    string[] _header = header_line.split(":", 2);
                    headers.set(_header[0], _header[1].strip());
                }
            } catch (IOError e) {

            }

            response.headers = headers;
        }
    }
}
{'fraction_non_alphanumeric': 0.09853755501916797, 'fraction_numerical': 0.003123668891097544, 'mean_word_length': 1.3378692333222701, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3217769', 'n_tokens_mistral': 1793, 'n_tokens_neox': 1629, 'n_words': 440}