From 848cd3cb3e674dbd392d324f8bd80b16242eeb16 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 22 Dec 2019 01:41:42 +0300 Subject: [PATCH] run vfmt on http, net, sync, strconv --- examples/news_fetcher.v | 24 ++- vlib/compiler/vfmt.v | 5 +- vlib/http/backend_nix.v | 51 ++++- vlib/http/chunked/dechunk.v | 41 ++-- vlib/http/download.v | 8 +- vlib/http/download_nix.v | 13 +- vlib/http/http.v | 97 +++++---- vlib/http/http_client.v | 26 ++- vlib/json/json_primitives.v | 20 +- vlib/net/init_nix.v | 4 +- vlib/net/net.v | 5 +- vlib/net/socket.v | 172 +++++++++------ vlib/net/urllib/urllib.v | 409 ++++++++++++++++++------------------ vlib/net/urllib/values.v | 2 +- vlib/os/os.v | 20 +- vlib/strconv/atof.v | 5 +- vlib/sync/sync_nix.v | 15 +- vlib/sync/waitgroup.v | 10 +- 18 files changed, 523 insertions(+), 404 deletions(-) diff --git a/examples/news_fetcher.v b/examples/news_fetcher.v index 5b390a62ff..b287e19e89 100644 --- a/examples/news_fetcher.v +++ b/examples/news_fetcher.v @@ -1,7 +1,6 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - import http import json import sync @@ -12,15 +11,15 @@ const ( struct Story { title string - url string + url string } struct Fetcher { mut: - mu &sync.Mutex - ids []int - cursor int - wg &sync.WaitGroup + mu &sync.Mutex + ids []int + cursor int + wg &sync.WaitGroup } fn (f mut Fetcher) fetch() { @@ -37,7 +36,7 @@ fn (f mut Fetcher) fetch() { println('failed to fetch data from /v0/item/${id}.json') exit(1) } - story := json.decode(Story, resp.text) or { + story := json.decode(Story,resp.text) or { println('failed to decode a story') exit(1) } @@ -52,22 +51,25 @@ fn main() { println('failed to fetch data from /v0/topstories.json') return } - mut ids := json.decode([]int, resp.text) or { + mut ids := json.decode([]int,resp.text) or { println('failed to decode topstories.json') return } if ids.len > 10 { // ids = ids[:10] mut tmp := [0].repeat(10) - for i := 0 ; i < 10 ; i++ { + for i := 0; i < 10; i++ { tmp[i] = ids[i] } ids = tmp } - wg := sync.new_waitgroup() mtx := sync.new_mutex() - mut fetcher := &Fetcher{ids: ids mu: 0 wg: 0} + mut fetcher := &Fetcher{ + ids: ids + mu: 0 + wg: 0 + } fetcher.mu = &mtx fetcher.wg = &wg fetcher.wg.add(ids.len) diff --git a/vlib/compiler/vfmt.v b/vlib/compiler/vfmt.v index b4782253ac..dd4cfdeaff 100644 --- a/vlib/compiler/vfmt.v +++ b/vlib/compiler/vfmt.v @@ -181,9 +181,10 @@ fn (p mut Parser) fnext() { comment := comment_token.lit // Newline before the comment, but not between two // comments, // and not right after `{`, there's already a newline there - if i > 0 && p.tokens[i-1].tok != .line_comment && + if i > 0 && ((p.tokens[i-1].tok != .line_comment && p.tokens[i-1].tok != .lcbr && - comment_token.line_nr > p.tokens[i-1].line_nr { + comment_token.line_nr > p.tokens[i-1].line_nr) || + p.tokens[i-1].tok == .hash) { // TODO not sure why this is needed, newline wasn't added after a hash p.fgen_nl() } if i > 0 && p.tokens[i-1].tok == .rcbr && p.scanner.fmt_indent == 0 { diff --git a/vlib/http/backend_nix.v b/vlib/http/backend_nix.v index 2467d1830f..de3de89835 100644 --- a/vlib/http/backend_nix.v +++ b/vlib/http/backend_nix.v @@ -1,18 +1,15 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module http import strings - // On linux, prefer a localy build openssl, because it is // much more likely for it to be newer, than the system // openssl from libssl-dev. If there is no local openssl, // the next flag is harmless, since it will still use the // (older) system openssl. #flag linux -I/usr/local/include/openssl -L/usr/local/lib - #flag -l ssl -l crypto // MacPorts #flag darwin -I/opt/local/include @@ -20,40 +17,74 @@ import strings // Brew #flag darwin -I/usr/local/opt/openssl/include #flag darwin -L/usr/local/opt/openssl/lib - #include - struct C.SSL { - } fn C.SSL_library_init() + + fn C.TLSv1_2_method() voidptr + + fn C.SSL_CTX_set_options() + + fn C.SSL_CTX_new() voidptr + + fn C.SSL_CTX_set_verify_depth() + + fn C.SSL_CTX_load_verify_locations() int + + fn C.BIO_new_ssl_connect() voidptr + + fn C.BIO_set_conn_hostname() int + + fn C.BIO_get_ssl() + + fn C.SSL_set_cipher_list() int + + fn C.BIO_do_connect() int + + fn C.BIO_do_handshake() int + + fn C.SSL_get_peer_certificate() int + + fn C.SSL_get_verify_result() int + + fn C.SSL_set_tlsext_host_name() int + + fn C.BIO_puts() + + fn C.BIO_read() + + fn C.BIO_free_all() + + fn C.SSL_CTX_free() + fn init() int { C.SSL_library_init() return 1 } fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { - //ssl_method := C.SSLv23_method() + // ssl_method := C.SSLv23_method() ssl_method := C.TLSv1_2_method() if isnil(method) { } @@ -89,13 +120,13 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { res = C.BIO_do_handshake(web) C.SSL_get_peer_certificate(ssl) res = C.SSL_get_verify_result(ssl) - /////// + // ///// s := req.build_request_headers(method, host_name, path) C.BIO_puts(web, s.str) mut sb := strings.new_builder(100) for { buff := [1536]byte - len := int(C.BIO_read(web, buff, 1536) ) + len := int(C.BIO_read(web, buff, 1536)) if len > 0 { sb.write(tos(buff, len)) } @@ -109,6 +140,6 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { if !isnil(ctx) { C.SSL_CTX_free(ctx) } - return parse_response(sb.str()) } + diff --git a/vlib/http/chunked/dechunk.v b/vlib/http/chunked/dechunk.v index 1eb0796d9c..b51f956a55 100644 --- a/vlib/http/chunked/dechunk.v +++ b/vlib/http/chunked/dechunk.v @@ -1,27 +1,29 @@ 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, +// ///////////////////////////////////////////////////////////// +// 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 + pos int text string } fn (s mut ChunkScanner) read_chunk_size() int { mut n := 0 for { - if s.pos >= s.text.len { break } + if s.pos >= s.text.len { + break + } c := s.text[s.pos] - if !c.is_hex_digit() { break } - n = n << 4 + if !c.is_hex_digit() { + break + } + n = n<<4 n += int(unhex(c)) s.pos++ } @@ -29,9 +31,15 @@ fn (s mut ChunkScanner) read_chunk_size() int { } 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 } + 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 } @@ -47,17 +55,20 @@ fn (s mut ChunkScanner) read_chunk(chunksize int) string { pub fn decode(text string) string { mut sb := strings.new_builder(100) - mut cscanner := ChunkScanner { + mut cscanner := ChunkScanner{ pos: 0 text: text } for { csize := cscanner.read_chunk_size() - if 0 == csize { break } + if 0 == csize { + break + } cscanner.skip_crlf() - sb.write( cscanner.read_chunk(csize) ) + sb.write(cscanner.read_chunk(csize)) cscanner.skip_crlf() } cscanner.skip_crlf() return sb.str() } + diff --git a/vlib/http/download.v b/vlib/http/download.v index 6df47df9dd..e24ccfdc1b 100644 --- a/vlib/http/download.v +++ b/vlib/http/download.v @@ -1,14 +1,16 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module http import os pub fn download_file(url, out string) bool { - s := http.get(url) or { return false } + s := http.get(url) or { + return false + } os.write_file(out, s.text) return true - //download_file_with_progress(url, out, empty, empty) + // download_file_with_progress(url, out, empty, empty) } + diff --git a/vlib/http/download_nix.v b/vlib/http/download_nix.v index 0500c84c48..2ed18bd5a7 100644 --- a/vlib/http/download_nix.v +++ b/vlib/http/download_nix.v @@ -1,12 +1,9 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module http -type downloadfn fn (written int) -type download_finished_fn fn () - +type downloadfn fn(written int)type download_finished_fn fn() /* struct DownloadStruct { mut: @@ -15,9 +12,8 @@ mut: cb downloadfn } */ - -fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) { -/* +fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) { + /* mut data := &DownloadStruct(userp) written := C.fwrite(ptr, size, nmemb, data.stream) data.written += written @@ -28,7 +24,7 @@ fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) { } pub fn download_file_with_progress(url, out string, cb downloadfn, cb_finished fn()) { -/* + /* curl := C.curl_easy_init() if isnil(curl) { return @@ -52,6 +48,5 @@ pub fn download_file_with_progress(url, out string, cb downloadfn, cb_finished f } fn empty() { - } diff --git a/vlib/http/http.v b/vlib/http/http.v index c8ee40410f..e1aec9bd91 100644 --- a/vlib/http/http.v +++ b/vlib/http/http.v @@ -1,7 +1,6 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module http import net.urllib @@ -13,19 +12,19 @@ const ( pub struct Request { pub: - headers map[string]string - method string + headers map[string]string + method string // cookies map[string]string - h string - cmd string - typ string // GET POST - data string - url string - verbose bool + h string + cmd string + typ string // GET POST + data string + url string + verbose bool user_agent string mut: - user_ptr voidptr - ws_func voidptr + user_ptr voidptr + ws_func voidptr } pub struct Response { @@ -67,7 +66,7 @@ pub fn new_request(typ, _url, _data string) ?Request { url = '$url?$data' data = '' } - return Request { + return Request{ typ: typ url: url data: data @@ -79,7 +78,9 @@ pub fn new_request(typ, _url, _data string) ?Request { } pub fn get_text(url string) string { - resp := get(url) or { return '' } + resp := get(url) or { + return '' + } return resp.text } @@ -116,18 +117,29 @@ pub fn (req &Request) do() ?Response { if req.typ == 'POST' { // req.headers << 'Content-Type: application/x-www-form-urlencoded' } - url := urllib.parse(req.url) or { return error('http.request.do: invalid URL "$req.url"') } + url := urllib.parse(req.url) or { + return error('http.request.do: invalid URL "$req.url"') + } mut rurl := url - mut resp := Response{} + mut resp := Response{ + } mut no_redirects := 0 for { - if no_redirects == max_redirects { return error('http.request.do: maximum number of redirects reached ($max_redirects)') } - qresp := req.method_and_url_to_response( req.typ, rurl ) or { return error(err) } + if no_redirects == max_redirects { + return error('http.request.do: maximum number of redirects reached ($max_redirects)') + } + qresp := req.method_and_url_to_response(req.typ, rurl) or { + return error(err) + } resp = qresp - if ! (resp.status_code in [301, 302, 303, 307, 308]) { break } + if !(resp.status_code in [301, 302, 303, 307, 308]) { + break + } // follow any redirects redirect_url := resp.headers['Location'] - qrurl := urllib.parse( redirect_url ) or { return error('http.request.do: invalid URL in redirect "$redirect_url"') } + qrurl := urllib.parse(redirect_url) or { + return error('http.request.do: invalid URL in redirect "$redirect_url"') + } rurl = qrurl no_redirects++ } @@ -141,19 +153,24 @@ fn (req &Request) method_and_url_to_response(method string, url net_dot_urllib.U path := if url.query().size > 0 { '/$p?${url.query().encode()}' } else { '/$p' } mut nport := url.port().int() if nport == 0 { - if scheme == 'http' { nport = 80 } - if scheme == 'https' { nport = 443 } + if scheme == 'http' { + nport = 80 + } + if scheme == 'https' { + nport = 443 + } } - //println('fetch $method, $scheme, $host_name, $nport, $path ') + // println('fetch $method, $scheme, $host_name, $nport, $path ') if scheme == 'https' { - //println('ssl_do( $nport, $method, $host_name, $path )') - res := req.ssl_do( nport, method, host_name, path ) or { + // println('ssl_do( $nport, $method, $host_name, $path )') + res := req.ssl_do(nport, method, host_name, path) or { return error(err) } return res - } else if scheme == 'http' { - //println('http_do( $nport, $method, $host_name, $path )') - res := req.http_do(nport, method, host_name, path ) or { + } + else if scheme == 'http' { + // println('http_do( $nport, $method, $host_name, $path )') + res := req.http_do(nport, method, host_name, path) or { return error(err) } return res @@ -175,7 +192,7 @@ fn parse_response(resp string) Response { mut i := 1 for { old_pos := nl_pos - nl_pos = resp.index_after('\n', nl_pos+1) + nl_pos = resp.index_after('\n', nl_pos + 1) if nl_pos == -1 { break } @@ -189,19 +206,17 @@ fn parse_response(resp string) Response { pos := h.index(':') or { continue } - //if h.contains('Content-Type') { - //continue - //} + // if h.contains('Content-Type') { + // continue + // } key := h[..pos] - val := h[pos+2..] + val := h[pos + 2..] headers[key] = val.trim_space() } - if headers['Transfer-Encoding'] == 'chunked' { - text = chunked.decode( text ) + text = chunked.decode(text) } - - return Response { + return Response{ status_code: status_code headers: headers text: text @@ -217,12 +232,7 @@ fn (req &Request) build_request_headers(method, host_name, path string) string { if req.data.len > 0 { uheaders << 'Content-Length: ${req.data.len}\r\n' } - return '$method $path HTTP/1.1\r\n' + - 'Host: $host_name\r\n' + - 'User-Agent: $ua\r\n' + - uheaders.join('') + - 'Connection: close\r\n\r\n' + - req.data + return '$method $path HTTP/1.1\r\n' + 'Host: $host_name\r\n' + 'User-Agent: $ua\r\n' + uheaders.join('') + 'Connection: close\r\n\r\n' + req.data } pub fn unescape_url(s string) string { @@ -241,4 +251,5 @@ pub fn escape(s string) string { panic('http.escape() was replaced with http.escape_url()') } -type wsfn fn (s string, ptr voidptr) +type wsfn fn(s string, ptr voidptr) + diff --git a/vlib/http/http_client.v b/vlib/http/http_client.v index 8cfed88451..4ca8878cb5 100644 --- a/vlib/http/http_client.v +++ b/vlib/http/http_client.v @@ -8,15 +8,23 @@ fn (req &Request) http_do(port int, method, host_name, path string) ?Response { rbuffer := [512]byte mut sb := strings.new_builder(100) s := req.build_request_headers(method, host_name, path) - - client := net.dial( host_name, port) or { return error(err) } - client.send( s.str, s.len ) or {} - for { - readbytes := client.crecv( rbuffer, bufsize ) - if readbytes < 0 { return error('http.request.http_do: error reading response. readbytes=$readbytes') } - if readbytes == 0 { break } - sb.write( tos(rbuffer, readbytes) ) + client := net.dial(host_name, port) or { + return error(err) + } + client.send(s.str, s.len) or { + } + for { + readbytes := client.crecv(rbuffer, bufsize) + if readbytes < 0 { + return error('http.request.http_do: error reading response. readbytes=$readbytes') + } + if readbytes == 0 { + break + } + sb.write(tos(rbuffer, readbytes)) + } + client.close() or { } - client.close() or {} return parse_response(sb.str()) } + diff --git a/vlib/json/json_primitives.v b/vlib/json/json_primitives.v index 8b1897f48f..3e19872a48 100644 --- a/vlib/json/json_primitives.v +++ b/vlib/json/json_primitives.v @@ -1,13 +1,11 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module json #flag -I @VROOT/thirdparty/cJSON #flag @VROOT/thirdparty/cJSON/cJSON.o #include "cJSON.h" - struct C.cJSON { valueint int valuedouble f32 @@ -39,7 +37,7 @@ fn jsdecode_i64(root &C.cJSON) i64 { if isnil(root) { return i64(0) } - return i64(root.valuedouble) //i64 is double in C + return i64(root.valuedouble) // i64 is double in C } fn jsdecode_byte(root &C.cJSON) byte { @@ -84,7 +82,6 @@ fn jsdecode_f64(root &C.cJSON) f64 { return f64(root.valuedouble) } - fn jsdecode_string(root &C.cJSON) string { if isnil(root) { return '' @@ -94,16 +91,27 @@ fn jsdecode_string(root &C.cJSON) string { } // println('jsdecode string valuestring="$root.valuestring"') // return tos(root.valuestring, _strlen(root.valuestring)) - return tos_clone(root.valuestring)// , _strlen(root.valuestring)) + return tos_clone(root.valuestring) // , _strlen(root.valuestring)) } fn C.cJSON_IsTrue() bool + + fn C.cJSON_CreateNumber() &C.cJSON + + fn C.cJSON_CreateBool() &C.cJSON + + fn C.cJSON_CreateString() &C.cJSON + + fn C.cJSON_Parse() &C.cJSON + + fn C.cJSON_PrintUnformatted() byteptr + fn jsdecode_bool(root &C.cJSON) bool { if isnil(root) { return false @@ -161,7 +169,6 @@ fn jsencode_string(val string) &C.cJSON { return C.cJSON_CreateString(clone.str) // return C.cJSON_CreateString2(val.str, val.len) } - // /////////////////////// // user := decode_User(json_parse(js_string_var)) fn json_parse(s string) &C.cJSON { @@ -178,3 +185,4 @@ fn json_print(json &C.cJSON) string { // fn json_array_for_each(val, root &C.cJSON) { // #cJSON_ArrayForEach (val ,root) // } + diff --git a/vlib/net/init_nix.v b/vlib/net/init_nix.v index 7e511b4f03..adf58c43bf 100644 --- a/vlib/net/init_nix.v +++ b/vlib/net/init_nix.v @@ -5,11 +5,11 @@ module net #include #include #include - fn error_code() int { - return C.errno + return C.errno } pub const ( MSG_NOSIGNAL = 0x4000 ) + diff --git a/vlib/net/net.v b/vlib/net/net.v index 97534d6078..c9544675cb 100644 --- a/vlib/net/net.v +++ b/vlib/net/net.v @@ -1,16 +1,15 @@ module net fn C.gethostname() int - // hostname returns the host name reported by the kernel. pub fn hostname() ?string { - mut name := [256]byte + mut name := [256]byte // https://www.ietf.org/rfc/rfc1035.txt // The host name is returned as a null-terminated string. res := C.gethostname(&name, 256) if res != 0 { return error('net.hostname: failed with $res') } - return tos_clone(name) + return tos_clone(name) } diff --git a/vlib/net/socket.v b/vlib/net/socket.v index 44d541c7fe..c216a31bdf 100644 --- a/vlib/net/socket.v +++ b/vlib/net/socket.v @@ -6,11 +6,10 @@ pub struct Socket { pub: sockfd int family int - _type int - proto int + _type int + proto int } - struct C.in_addr { mut: s_addr int @@ -19,52 +18,82 @@ mut: struct C.sockaddr_in { mut: sin_family int - sin_port int - sin_addr C.in_addr + sin_port int + sin_addr C.in_addr } struct C.addrinfo { mut: - ai_family int - ai_socktype int - ai_flags int - ai_protocol int - ai_addrlen int - ai_addr voidptr + ai_family int + ai_socktype int + ai_flags int + ai_protocol int + ai_addrlen int + ai_addr voidptr ai_canonname voidptr - ai_next voidptr + ai_next voidptr } -struct C.sockaddr_storage {} -fn C.socket() int -fn C.setsockopt() int -fn C.htonl() int -fn C.htons() int -fn C.bind() int -fn C.listen() int -fn C.accept() int -fn C.getaddrinfo() int -fn C.connect() int -fn C.send() int -fn C.recv() int -fn C.read() int -fn C.shutdown() int -fn C.close() int -fn C.ntohs() int -fn C.getsockname() int +struct C.sockaddr_storage { +} +fn C.socket() int + + +fn C.setsockopt() int + + +fn C.htonl() int + + +fn C.htons() int + + +fn C.bind() int + + +fn C.listen() int + + +fn C.accept() int + + +fn C.getaddrinfo() int + + +fn C.connect() int + + +fn C.send() int + + +fn C.recv() int + + +fn C.read() int + + +fn C.shutdown() int + + +fn C.close() int + + +fn C.ntohs() int + + +fn C.getsockname() int // create socket pub fn new_socket(family int, _type int, proto int) ?Socket { - sockfd := C.socket(family, _type, proto) - one:=1 + one := 1 // This is needed so that there are no problems with reusing the // same port after the application exits. C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, sizeof(int)) if sockfd == 0 { return error('net.socket: failed') } - s := Socket { + s := Socket{ sockfd: sockfd family: family _type: _type @@ -88,7 +117,8 @@ pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int { // bind socket to port pub fn (s Socket) bind(port int) ?int { - mut addr := C.sockaddr_in{} + mut addr := C.sockaddr_in{ + } addr.sin_family = s.family addr.sin_port = C.htons(port) addr.sin_addr.s_addr = C.htonl(C.INADDR_ANY) @@ -148,13 +178,14 @@ pub fn (s Socket) accept() ?Socket { $if debug { println('accept()') } - addr := C.sockaddr_storage{} + addr := C.sockaddr_storage{ + } size := 128 // sizeof(sockaddr_storage) sockfd := C.accept(s.sockfd, &addr, &size) if sockfd < 0 { return error('net.accept: failed with $sockfd') } - c := Socket { + c := Socket{ sockfd: sockfd family: s.family _type: s._type @@ -165,7 +196,8 @@ pub fn (s Socket) accept() ?Socket { // connect to given addrress and port pub fn (s Socket) connect(address string, port int) ?int { - mut hints := C.addrinfo{} + mut hints := C.addrinfo{ + } hints.ai_family = s.family hints.ai_socktype = s._type hints.ai_flags = C.AI_PASSIVE @@ -174,8 +206,6 @@ pub fn (s Socket) connect(address string, port int) ?int { hints.ai_canonname = C.NULL hints.ai_addr = C.NULL hints.ai_next = C.NULL - - info := &C.addrinfo(0) sport := '$port' info_res := C.getaddrinfo(address.str, sport.str, &hints, &info) @@ -208,9 +238,13 @@ pub fn (s Socket) send(buf byteptr, len int) ?int { mut dlen := len for { sbytes := C.send(s.sockfd, dptr, dlen, MSG_NOSIGNAL) - if sbytes < 0 { return error('net.send: failed with $sbytes') } + if sbytes < 0 { + return error('net.send: failed with $sbytes') + } dlen -= sbytes - if dlen <= 0 { break } + if dlen <= 0 { + break + } dptr += sbytes } return len @@ -218,23 +252,24 @@ pub fn (s Socket) send(buf byteptr, len int) ?int { // send string data to socket (when you have a v string) pub fn (s Socket) send_string(sdata string) ?int { - return s.send( sdata.str, sdata.len ) + return s.send(sdata.str, sdata.len) } // receive string data from socket -pub fn (s Socket) recv(bufsize int) (byteptr, int) { +pub fn (s Socket) recv(bufsize int) (byteptr,int) { buf := malloc(bufsize) res := C.recv(s.sockfd, buf, bufsize, 0) - return buf, res + return buf,res } // TODO: remove cread/2 and crecv/2 when the Go net interface is done -pub fn (s Socket) cread( buffer byteptr, buffersize int ) int { +pub fn (s Socket) cread(buffer byteptr, buffersize int) int { return C.read(s.sockfd, buffer, buffersize) } + // Receive a message from the socket, and place it in a preallocated buffer buf, // with maximum message size bufsize. Returns the length of the received message. -pub fn (s Socket) crecv( buffer byteptr, buffersize int ) int { +pub fn (s Socket) crecv(buffer byteptr, buffersize int) int { return C.recv(s.sockfd, buffer, buffersize, 0) } @@ -243,27 +278,23 @@ pub fn (s Socket) close() ?int { mut shutdown_res := 0 $if windows { shutdown_res = C.shutdown(s.sockfd, C.SD_BOTH) - } - $else { + } $else { shutdown_res = C.shutdown(s.sockfd, C.SHUT_RDWR) } // TODO: should shutdown throw an error? close will // continue even if shutdown failed -// if shutdown_res < 0 { -// return error('net.close: shutdown failed with $shutdown_res') -// } - + // if shutdown_res < 0 { + // return error('net.close: shutdown failed with $shutdown_res') + // } mut res := 0 $if windows { res = C.closesocket(s.sockfd) - } - $else { + } $else { res = C.close(s.sockfd) } if res < 0 { return error('net.close: failed with $res') } - return 0 } @@ -272,12 +303,13 @@ pub const ( MAX_READ = 400 MSG_PEEK = 0x02 ) - // write - write a string with CRLF after it over the socket s pub fn (s Socket) write(str string) ?int { line := '$str$CRLF' res := C.send(s.sockfd, line.str, line.len, MSG_NOSIGNAL) - if res < 0 { return error('net.write: failed with $res') } + if res < 0 { + return error('net.write: failed with $res') + } return res } @@ -287,9 +319,13 @@ pub fn (s Socket) read_line() string { mut res := '' // The final result, including the ending \n. for { mut line := '' // The current line. Can be a partial without \n in it. - n := C.recv(s.sockfd, buf, MAX_READ-1, MSG_PEEK) - if n == -1 { return res } - if n == 0 { return res } + n := C.recv(s.sockfd, buf, MAX_READ - 1, MSG_PEEK) + if n == -1 { + return res + } + if n == 0 { + return res + } buf[n] = `\0` mut eol_idx := -1 for i := 0; i < n; i++ { @@ -298,7 +334,7 @@ pub fn (s Socket) read_line() string { // Ensure that tos_clone(buf) later, // will return *only* the first line (including \n), // and ignore the rest - buf[i+1] = `\0` + buf[i + 1] = `\0` break } } @@ -309,7 +345,7 @@ pub fn (s Socket) read_line() string { // Ensure that the block till the first \n (including it) // is removed from the socket's receive queue, so that it does // not get read again. - C.recv(s.sockfd, buf, eol_idx+1, 0) + C.recv(s.sockfd, buf, eol_idx + 1, 0) res += line break } @@ -327,19 +363,23 @@ pub fn (s Socket) read_all() string { mut buf := [MAX_READ]byte // where C.recv will store the network data mut res := '' // The final result, including the ending \n. for { - n := C.recv(s.sockfd, buf, MAX_READ-1, 0) - if n == -1 { return res } - if n == 0 { return res } + n := C.recv(s.sockfd, buf, MAX_READ - 1, 0) + if n == -1 { + return res + } + if n == 0 { + return res + } res += tos_clone(buf) } return res } pub fn (s Socket) get_port() int { - mut addr := C.sockaddr_in {} + mut addr := C.sockaddr_in{ + } size := 16 // sizeof(sockaddr_in) C.getsockname(s.sockfd, &addr, &size) return C.ntohs(addr.sin_port) } - diff --git a/vlib/net/urllib/urllib.v b/vlib/net/urllib/urllib.v index ebcc011717..189f9171cd 100644 --- a/vlib/net/urllib/urllib.v +++ b/vlib/net/urllib/urllib.v @@ -1,14 +1,11 @@ // urllib parses URLs and implements query escaping. - // See RFC 3986. This module generally follows RFC 3986, except where // it deviates for compatibility reasons. - // Based off: https://github.com/golang/go/blob/master/src/net/url/url.go // Last commit: https://github.com/golang/go/commit/fe2ed5054176935d4adcf13e891715ccf2ee3cce // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. - module urllib import strings @@ -25,12 +22,14 @@ enum EncodingMode { const ( err_msg_escape = 'unescape: invalid URL escape' - err_msg_parse = 'parse: failed parsing url' + err_msg_parse = 'parse: failed parsing url' ) fn error_msg(message, val string) string { mut msg := 'net.urllib.$message' - if val != '' { msg = '$msg ($val)' } + if val != '' { + msg = '$msg ($val)' + } return msg } @@ -44,10 +43,9 @@ fn should_escape(c byte, mode EncodingMode) bool { if (`a` <= c && c <= `z`) || (`A` <= c && c <= `Z`) || (`0` <= c && c <= `9`) { return false } - if mode == .encode_host || mode == .encode_zone { // §3.2.2 host allows - // sub-delims = `!` / `$` / `&` / ``` / `(` / `)` / `*` / `+` / `,` / `;` / `=` + // sub-delims = `!` / `$` / `&` / ``` / `(` / `)` / `*` / `+` / `,` / `;` / `=` // as part of reg-name. // We add : because we include :port as part of host. // We add [ ] because we include [ipv6]:port as part of host. @@ -55,59 +53,58 @@ fn should_escape(c byte, mode EncodingMode) bool { // we could possibly allow, and parse will reject them if we // escape them (because hosts can`t use %-encoding for // ASCII bytes). - if c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, - `:`, `[`, `]`, `<`, `>`, `"`] - { + if c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] { return false } } - match c { - `-`, `_`, `.`, `~` { // §2.3 Unreserved characters (mark) + `-`, `_`, `.`, `~` { + // §2.3 Unreserved characters (mark) return false } - - `$`, `&`, `+`, `,`, `/`, `:`, `;`, `=`, `?`, `@` { // §2.2 Reserved characters (reserved) - // Different sections of the URL allow a few of - // the reserved characters to appear unescaped. - match mode { - .encode_path { // §3.3 - // The RFC allows : @ & = + $ but saves / ; , for assigning - // meaning to individual path segments. This package - // only manipulates the path as a whole, so we allow those - // last three as well. That leaves only ? to escape. - return c == `?` + `$`, `&`, `+`, `,`, `/`, `:`, `;`, `=`, `?`, `@` { + // §2.2 Reserved characters (reserved) + // Different sections of the URL allow a few of + // the reserved characters to appear unescaped. + match mode { + .encode_path { + // §3.3 + // The RFC allows : @ & = + $ but saves / ; , for assigning + // meaning to individual path segments. This package + // only manipulates the path as a whole, so we allow those + // last three as well. That leaves only ? to escape. + return c == `?` + } + .encode_path_segment { + // §3.3 + // The RFC allows : @ & = + $ but saves / ; , for assigning + // meaning to individual path segments. + return c == `/` || c == `;` || c == `,` || c == `?` + } + .encode_user_password { + // §3.2.1 + // The RFC allows `;`, `:`, `&`, `=`, `+`, `$`, and `,` in + // userinfo, so we must escape only `@`, `/`, and `?`. + // The parsing of userinfo treats `:` as special so we must escape + // that too. + return c == `@` || c == `/` || c == `?` || c == `:` + } + .encode_query_component { + // §3.4 + // The RFC reserves (so we must escape) everything. + return true + } + .encode_fragment { + // §4.1 + // The RFC text is silent but the grammar allows + // everything, so escape nothing. + return false + } + else { + }} } - - .encode_path_segment { // §3.3 - // The RFC allows : @ & = + $ but saves / ; , for assigning - // meaning to individual path segments. - return c == `/` || c == `;` || c == `,` || c == `?` - } - - .encode_user_password { // §3.2.1 - // The RFC allows `;`, `:`, `&`, `=`, `+`, `$`, and `,` in - // userinfo, so we must escape only `@`, `/`, and `?`. - // The parsing of userinfo treats `:` as special so we must escape - // that too. - return c == `@` || c == `/` || c == `?` || c == `:` - } - - .encode_query_component { // §3.4 - // The RFC reserves (so we must escape) everything. - return true - } - - .encode_fragment { // §4.1 - // The RFC text is silent but the grammar allows - // everything, so escape nothing. - return false - } - else {} - } - } else {} - } - + else { + }} if mode == .encode_fragment { // RFC 3986 §2.2 allows not escaping sub-delims. A subset of sub-delims are // included in reserved from RFC 2396 §2.2. The remaining sub-delims do not @@ -116,13 +113,12 @@ fn should_escape(c byte, mode EncodingMode) bool { // escape single quote to avoid breaking callers that had previously assumed that // single quotes would be escaped. See issue #19917. match c { - `!`, `(`, `)`, `*`{ + `!`, `(`, `)`, `*` { return false } - else {} - } + else { + }} } - // Everything else must be escaped. return true } @@ -154,7 +150,7 @@ fn unescape(s_ string, mode EncodingMode) ?string { // Count %, check that they're well-formed. mut n := 0 mut has_plus := false - for i := 0; i < s.len; { + for i := 0; i < s.len; { x := s[i] match x { `%` { @@ -162,7 +158,7 @@ fn unescape(s_ string, mode EncodingMode) ?string { break } n++ - if i+2 >= s.len || !ishex(s[i+1]) || !ishex(s[i+2]) { + if i + 2 >= s.len || !ishex(s[i + 1]) || !ishex(s[i + 2]) { s = s[i..] if s.len > 3 { s = s[..3] @@ -175,8 +171,8 @@ fn unescape(s_ string, mode EncodingMode) ?string { // But https://tools.ietf.org/html/rfc6874#section-2 // introduces %25 being allowed to escape a percent sign // in IPv6 scoped-address literals. Yay. - if mode == .encode_host && unhex(s[i+1]) < 8 && s[i..i+3] != '%25' { - return error(error_msg(err_msg_escape, s[i..i+3])) + if mode == .encode_host && unhex(s[i + 1]) < 8 && s[i..i + 3] != '%25' { + return error(error_msg(err_msg_escape, s[i..i + 3])) } if mode == .encode_zone { // RFC 6874 says basically 'anything goes' for zone identifiers @@ -186,47 +182,46 @@ fn unescape(s_ string, mode EncodingMode) ?string { // That is, you can use escaping in the zone identifier but not // to introduce bytes you couldn't just write directly. // But Windows puts spaces here! Yay. - v := (unhex(s[i+1])<>4] - t[j+2] = upperhex[c1&15] + t[j + 1] = upperhex[c1>>4] + t[j + 2] = upperhex[c1 & 15] j += 3 - } else { + } + else { t[j] = s[i] j++ } } - return string(t, t.len) + return string(t,t.len) } // A URL represents a parsed URL (technically, a URI reference). // // The general form represented is: // -// [scheme:][//[userinfo@]host][/]path[?query][#fragment] +// [scheme:][//[userinfo@]host][/]path[?query][#fragment] // // URLs that do not start with a slash after the scheme are interpreted as: // -// scheme:opaque[?query][#fragment] +// scheme:opaque[?query][#fragment] // // Note that the path field is stored in decoded form: /%47%6f%2f becomes /Go/. // A consequence is that it is impossible to tell which slashes in the path were @@ -323,22 +317,21 @@ fn escape(s string, mode EncodingMode) string { pub struct URL { pub mut: scheme string - opaque string // encoded opaque data + opaque string // encoded opaque data user &Userinfo // username and password information - host string // host or host:port - path string // path (relative paths may omit leading slash) - raw_path string // encoded path hint (see escaped_path method) - force_query bool // append a query ('?') even if raw_query is empty - raw_query string // encoded query values, without '?' - fragment string // fragment for references, without '#' + host string // host or host:port + path string // path (relative paths may omit leading slash) + raw_path string // encoded path hint (see escaped_path method) + force_query bool // append a query ('?') even if raw_query is empty + raw_query string // encoded query values, without '?' + fragment string // fragment for references, without '#' } - // user returns a Userinfo containing the provided username // and no password set. pub fn user(username string) &Userinfo { return &Userinfo{ - username: username, - password: '', + username: username + password: '' password_set: false } } @@ -352,7 +345,8 @@ pub fn user(username string) &Userinfo { // information in clear text (such as URI) has proven to be a // security risk in almost every case where it has been used.'' fn user_password(username, password string) &Userinfo { - return &Userinfo{username, password, true} + return &Userinfo{ + username,password,true} } // The Userinfo type is an immutable encapsulation of username and @@ -401,7 +395,7 @@ fn split_by_scheme(rawurl string) ?[]string { if i == 0 { return error(error_msg('split_by_scheme: missing protocol scheme', '')) } - return [rawurl[..i], rawurl[i+1..]] + return [rawurl[..i], rawurl[i + 1..]] } else { // we have encountered an invalid character, @@ -422,15 +416,15 @@ fn get_scheme(rawurl string) ?string { // split slices s into two substrings separated by the first occurence of // sep. If cutc is true then sep is included with the second substring. // If sep does not occur in s then s and the empty string is returned. -fn split(s string, sep byte, cutc bool) (string, string) { +fn split(s string, sep byte, cutc bool) (string,string) { i := s.index_byte(sep) if i < 0 { - return s, '' + return s,'' } if cutc { - return s[..i], s[i+1..] + return s[..i],s[i + 1..] } - return s[..i], s[i..] + return s[..i],s[i..] } // parse parses rawurl into a URL structure. @@ -441,7 +435,7 @@ fn split(s string, sep byte, cutc bool) (string, string) { // error, due to parsing ambiguities. pub fn parse(rawurl string) ?URL { // Cut off #frag - u, frag := split(rawurl, `#`, true) + u,frag := split(rawurl, `#`, true) mut url := parse_url(u, false) or { return error(error_msg(err_msg_parse, u)) } @@ -472,17 +466,16 @@ fn parse_url(rawurl string, via_request bool) ?URL { if string_contains_ctl_byte(rawurl) { return error(error_msg('parse_url: invalid control character in URL', rawurl)) } - if rawurl == '' && via_request { return error(error_msg('parse_url: empty URL', rawurl)) } - mut url := URL{user:0} - + mut url := URL{ + user: 0 + } if rawurl == '*' { url.path = '*' return url } - // Split off possible leading 'http:', 'mailto:', etc. // Cannot contain escaped characters. p := split_by_scheme(rawurl) or { @@ -491,17 +484,16 @@ fn parse_url(rawurl string, via_request bool) ?URL { url.scheme = p[0] mut rest := p[1] url.scheme = url.scheme.to_lower() - // if rest.ends_with('?') && strings.count(rest, '?') == 1 { if rest.ends_with('?') && !rest[..1].contains('?') { url.force_query = true - rest = rest[..rest.len-1] - } else { - r, raw_query := split(rest, `?`, true) + rest = rest[..rest.len - 1] + } + else { + r,raw_query := split(rest, `?`, true) rest = r url.raw_query = raw_query } - if !rest.starts_with('/') { if url.scheme != '' { // We consider rootless paths per RFC 3986 as opaque. @@ -511,23 +503,25 @@ fn parse_url(rawurl string, via_request bool) ?URL { if via_request { return error(error_msg('parse_url: invalid URI for request', '')) } - // Avoid confusion with malformed schemes, like cache_object:foo/bar. // See golang.org/issue/16822. // // RFC 3986, §3.3: // In addition, a URI reference (Section 4.1) may be a relative-path reference, // in which case the first path segment cannot contain a colon (':') character. - colon := rest.index(':') or { return error('there should be a : in the URL') } - slash := rest.index('/') or { return error('there should be a / in the URL') } + colon := rest.index(':') or { + return error('there should be a : in the URL') + } + slash := rest.index('/') or { + return error('there should be a / in the URL') + } if colon >= 0 && (slash < 0 || colon < slash) { // First path segment has colon. Not allowed in relative URL. return error(error_msg('parse_url: first path segment in URL cannot contain colon', '')) } } - if ((url.scheme != '' || !via_request) && !rest.starts_with('///')) && rest.starts_with('//') { - authority, r := split(rest[2..], `/`, false) + authority,r := split(rest[2..], `/`, false) rest = r a := parse_authority(authority) or { return error(err) @@ -551,7 +545,9 @@ struct ParseAuthorityRes { } fn parse_authority(authority string) ?ParseAuthorityRes { - i := authority.last_index('@') or { -1 } + i := authority.last_index('@') or { + -1 + } mut host := '' mut zuser := user('') if i < 0 { @@ -559,14 +555,18 @@ fn parse_authority(authority string) ?ParseAuthorityRes { return error(err) } host = h - } else { - h := parse_host(authority[i+1..]) or { + } + else { + h := parse_host(authority[i + 1..]) or { return error(err) } host = h } if i < 0 { - return ParseAuthorityRes{host: host, user: zuser} + return ParseAuthorityRes{ + host: host + user: zuser + } } mut userinfo := authority[..i] if !valid_userinfo(userinfo) { @@ -578,8 +578,9 @@ fn parse_authority(authority string) ?ParseAuthorityRes { } userinfo = u zuser = user(userinfo) - } else { - mut username, mut password := split(userinfo, `:`, true) + } + else { + mut username,mut password := split(userinfo, `:`, true) u := unescape(username, .encode_user_password) or { return error(err) } @@ -603,20 +604,19 @@ fn parse_host(host string) ?string { // parse an IP-Literal in RFC 3986 and RFC 6874. // E.g., '[fe80::1]', '[fe80::1%25en0]', '[fe80::1]:80'. mut i := host.last_index(']') or { - return error(error_msg('parse_host: missing \']\' in host', '')) + return error(error_msg("parse_host: missing \']\' in host", '')) } - mut colon_port := host[i+1..] + mut colon_port := host[i + 1..] if !valid_optional_port(colon_port) { return error(error_msg('parse_host: invalid port $colon_port after host ', '')) } - // RFC 6874 defines that %25 (%-encoded percent) introduces // the zone identifier, and the zone identifier can use basically // any %-encoding it likes. That's different from the host, which // can only %-encode non-ASCII bytes. // We do impose some restrictions on the zone, to avoid stupidity // like newlines. - if zone := host[..i].index('%25') { + if zone:=host[..i].index('%25'){ host1 := unescape(host[..zone], .encode_host) or { return err } @@ -628,7 +628,7 @@ fn parse_host(host string) ?string { } return host1 + host2 + host3 } - if idx := host.last_index(':') { + if idx:=host.last_index(':'){ colon_port = host[idx..] if !valid_optional_port(colon_port) { return error(error_msg('parse_host: invalid port $colon_port after host ', '')) @@ -639,10 +639,9 @@ fn parse_host(host string) ?string { return err } return h - //host = h - //return host + // host = h + // return host } - // set_path sets the path and raw_path fields of the URL based on the provided // escaped path p. It maintains the invariant that raw_path is only specified // when it differs from the default encoding of the path. @@ -660,7 +659,8 @@ fn (u mut URL) set_path(p string) ?bool { if p == escp { // Default encoding is fine. u.raw_path = '' - } else { + } + else { u.raw_path = p } return true @@ -677,7 +677,9 @@ fn (u mut URL) set_path(p string) ?bool { // reading u.raw_path directly. fn (u &URL) escaped_path() string { if u.raw_path != '' && valid_encoded_path(u.raw_path) { - unescape(u.raw_path, .encode_path) or { return '' } + unescape(u.raw_path, .encode_path) or { + return '' + } return u.raw_path } if u.path == '*' { @@ -705,12 +707,12 @@ fn valid_encoded_path(s string) bool { } `%` { // ok - percent encoded, will decode - } else { + } + else { if should_escape(s[i], .encode_path) { return false } - } - } + }} } return true } @@ -735,8 +737,8 @@ fn valid_optional_port(port string) bool { // str reassembles the URL into a valid URL string. // The general form of the result is one of: // -// scheme:opaque?query#fragment -// scheme://userinfo@host/path?query#fragment +// scheme:opaque?query#fragment +// scheme://userinfo@host/path?query#fragment // // If u.opaque is non-empty, String uses the first form; // otherwise it uses the second form. @@ -744,15 +746,15 @@ fn valid_optional_port(port string) bool { // To obtain the path, String uses u.escaped_path(). // // In the second form, the following rules apply: -// - if u.scheme is empty, scheme: is omitted. -// - if u.user is nil, userinfo@ is omitted. -// - if u.host is empty, host/ is omitted. -// - if u.scheme and u.host are empty and u.user is nil, -// the entire scheme://userinfo@host/ is omitted. -// - if u.host is non-empty and u.path begins with a /, -// the form host/path does not add its own /. -// - if u.raw_query is empty, ?query is omitted. -// - if u.fragment is empty, #fragment is omitted. +// - if u.scheme is empty, scheme: is omitted. +// - if u.user is nil, userinfo@ is omitted. +// - if u.host is empty, host/ is omitted. +// - if u.scheme and u.host are empty and u.user is nil, +// the entire scheme://userinfo@host/ is omitted. +// - if u.host is non-empty and u.path begins with a /, +// the form host/path does not add its own /. +// - if u.raw_query is empty, ?query is omitted. +// - if u.fragment is empty, #fragment is omitted. pub fn (u &URL) str() string { mut buf := strings.new_builder(200) if u.scheme != '' { @@ -761,7 +763,8 @@ pub fn (u &URL) str() string { } if u.opaque != '' { buf.write(u.opaque) - } else { + } + else { if u.scheme != '' || u.host != '' || !u.user.empty() { if u.host != '' || u.path != '' || !u.user.empty() { buf.write('//') @@ -807,8 +810,6 @@ pub fn (u &URL) str() string { // It is typically used for query parameters and form values. // Unlike in the http.Header map, the keys in a Values map // are case-sensitive. - - // parseQuery parses the URL-encoded query string and returns // a map listing the values specified for each key. // parseQuery always returns a non-nil map containing all the @@ -841,18 +842,19 @@ fn parse_query_values(m mut Values, query string) ?bool { mut key := q mut i := key.index_any('&;') if i >= 0 { - q = key[i+1..] + q = key[i + 1..] key = key[..i] - } else { + } + else { q = '' } if key == '' { continue } mut value := '' - if idx := key.index('=') { + if idx:=key.index('='){ i = idx - value = key[i+1..] + value = key[i + 1..] key = key[..i] } k := query_unescape(key) or { @@ -860,7 +862,6 @@ fn parse_query_values(m mut Values, query string) ?bool { continue } key = k - v := query_unescape(value) or { had_error = true continue @@ -907,10 +908,14 @@ fn resolve_path(base, ref string) string { mut full := '' if ref == '' { full = base - } else if ref[0] != `/` { - i := base.last_index('/') or { -1 } - full = base[..i+1] + ref - } else { + } + else if ref[0] != `/` { + i := base.last_index('/') or { + -1 + } + full = base[..i + 1] + ref + } + else { full = ref } if full == '' { @@ -925,17 +930,17 @@ fn resolve_path(base, ref string) string { } '..' { if dst.len > 0 { - dst = dst[..dst.len-1] + dst = dst[..dst.len - 1] } - } else { - dst << elem } - } + else { + dst << elem + }} } - last := src[src.len-1] + last := src[src.len - 1] if last == '.' || last == '..' { // Add final slash to the joined path. - dst << '' + dst << '' } return '/' + dst.join('/').trim_left('/') } @@ -971,7 +976,9 @@ pub fn (u &URL) resolve_reference(ref &URL) ?URL { // The 'absoluteURI' or 'net_path' cases. // We can ignore the error from set_path since we know we provided a // validly-escaped path. - url.set_path(resolve_path(ref.escaped_path(), '')) or {return error(err)} + url.set_path(resolve_path(ref.escaped_path(), '')) or { + return error(err) + } return url } if ref.opaque != '' { @@ -989,7 +996,9 @@ pub fn (u &URL) resolve_reference(ref &URL) ?URL { // The 'abs_path' or 'rel_path' cases. url.host = u.host url.user = u.user - url.set_path(resolve_path(u.escaped_path(), ref.escaped_path())) or { return error(err) } + url.set_path(resolve_path(u.escaped_path(), ref.escaped_path())) or { + return error(err) + } return url } @@ -1010,7 +1019,8 @@ pub fn (u &URL) request_uri() string { if result == '' { result = '/' } - } else { + } + else { if result.starts_with('//') { result = u.scheme + ':' + result } @@ -1026,43 +1036,40 @@ pub fn (u &URL) request_uri() string { // If the result is enclosed in square brackets, as literal IPv6 addresses are, // the square brackets are removed from the result. pub fn (u &URL) hostname() string { - host, _ := split_host_port(u.host) + host,_ := split_host_port(u.host) return host } // port returns the port part of u.host, without the leading colon. // If u.host doesn't contain a port, port returns an empty string. pub fn (u &URL) port() string { - _, port := split_host_port(u.host) + _,port := split_host_port(u.host) return port } // split_host_port separates host and port. If the port is not valid, it returns // the entire input as host, and it doesn't check the validity of the host. // Per RFC 3986, it requires ports to be numeric. -fn split_host_port(hostport string) (string, string) { +fn split_host_port(hostport string) (string,string) { mut host := hostport mut port := '' - colon := host.last_index_byte(`:`) if colon != -1 && valid_optional_port(host[colon..]) { - port = host[colon+1..] + port = host[colon + 1..] host = host[..colon] } - if host.starts_with('[') && host.ends_with(']') { - host = host[1..host.len-1] + host = host[1..host.len - 1] } - - return host, port + return host,port } // valid_userinfo reports whether s is a valid userinfo string per RFC 3986 // Section 3.2.1: -// userinfo = *( unreserved / pct-encoded / sub-delims / ':' ) -// unreserved = ALPHA / DIGIT / '-' / '.' / '_' / '~' -// sub-delims = '!' / '$' / '&' / ''' / '(' / ')' -// / '*' / '+' / ',' / ';' / '=' +// userinfo = *( unreserved / pct-encoded / sub-delims / ':' ) +// unreserved = ALPHA / DIGIT / '-' / '.' / '_' / '~' +// sub-delims = '!' / '$' / '&' / ''' / '(' / ')' +// / '*' / '+' / ',' / ';' / '=' // // It doesn't validate pct-encoded. The caller does that via fn unescape. pub fn valid_userinfo(s string) bool { @@ -1077,13 +1084,12 @@ pub fn valid_userinfo(s string) bool { continue } match r { - `-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, - `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` { - continue - } else { - return false - } - } + `-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` { + continue + } + else { + return false + }} } return true } @@ -1102,9 +1108,11 @@ fn string_contains_ctl_byte(s string) bool { pub fn ishex(c byte) bool { if `0` <= c && c <= `9` { return true - } else if `a` <= c && c <= `f` { + } + else if `a` <= c && c <= `f` { return true - } else if `A` <= c && c <= `F` { + } + else if `A` <= c && c <= `F` { return true } return false @@ -1113,10 +1121,13 @@ pub fn ishex(c byte) bool { fn unhex(c byte) byte { if `0` <= c && c <= `9` { return c - `0` - } else if `a` <= c && c <= `f` { + } + else if `a` <= c && c <= `f` { return c - `a` + 10 - } else if `A` <= c && c <= `F` { + } + else if `A` <= c && c <= `F` { return c - `A` + 10 } return 0 } + diff --git a/vlib/net/urllib/values.v b/vlib/net/urllib/values.v index 49c66dc735..3f94a94e3a 100644 --- a/vlib/net/urllib/values.v +++ b/vlib/net/urllib/values.v @@ -1,7 +1,6 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module urllib struct Value { @@ -86,3 +85,4 @@ pub fn (v mut Values) del(key string) { v.data.delete(key) v.size = v.data.size } + diff --git a/vlib/os/os.v b/vlib/os/os.v index 5ae373af80..be3fea02f9 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -178,7 +178,7 @@ pub fn cp_r(osource_path, odest_path string, overwrite bool) ?bool { return error('Destination file path already exist') } } - os.cp(source_path, adjasted_path)or{ + os.cp(source_path, adjasted_path) or { return error(err) } return true @@ -186,18 +186,18 @@ pub fn cp_r(osource_path, odest_path string, overwrite bool) ?bool { if !os.is_dir(dest_path) { return error('Destination path is not a valid directory') } - files := os.ls(source_path)or{ + files := os.ls(source_path) or { return error(err) } for file in files { sp := filepath.join(source_path,file) dp := filepath.join(dest_path,file) if os.is_dir(sp) { - os.mkdir(dp)or{ + os.mkdir(dp) or { panic(err) } } - cp_r(sp, dp, overwrite)or{ + cp_r(sp, dp, overwrite) or { os.rmdir(dp) panic(err) } @@ -208,7 +208,7 @@ pub fn cp_r(osource_path, odest_path string, overwrite bool) ?bool { // mv_by_cp first copies the source file, and if it is copied successfully, deletes the source file. // mv_by_cp may be used when you are not sure that the source and target are on the same mount/partition. pub fn mv_by_cp(source string, target string) ?bool { - os.cp(source, target)or{ + os.cp(source, target) or { return error(err) } os.rm(source) @@ -259,7 +259,7 @@ pub fn read_lines(path string) ?[]string { } fn read_ulines(path string) ?[]ustring { - lines := read_lines(path)or{ + lines := read_lines(path) or { return err } // mut ulines := new_array(0, lines.len, sizeof(ustring)) @@ -768,7 +768,7 @@ pub fn home_dir() string { // write_file writes `text` data to a file in `path`. pub fn write_file(path, text string) { - mut f := os.create(path)or{ + mut f := os.create(path) or { return } f.write(text) @@ -966,7 +966,7 @@ pub fn walk_ext(path, ext string) []string { if !os.is_dir(path) { return [] } - mut files := os.ls(path)or{ + mut files := os.ls(path) or { panic(err) } mut res := []string @@ -992,7 +992,7 @@ pub fn walk(path string, fnc fn(path string)) { if !os.is_dir(path) { return } - mut files := os.ls(path)or{ + mut files := os.ls(path) or { panic(err) } for file in files { @@ -1072,7 +1072,7 @@ pub fn mkdir_all(path string) { for subdir in path.split(os.path_separator) { p += subdir + os.path_separator if !os.is_dir(p) { - os.mkdir(p)or{ + os.mkdir(p) or { panic(err) } } diff --git a/vlib/strconv/atof.v b/vlib/strconv/atof.v index d6c9ed6525..96c5736561 100644 --- a/vlib/strconv/atof.v +++ b/vlib/strconv/atof.v @@ -489,7 +489,6 @@ fn converter(pn mut PrepNumber) u64 { } s1 = s1 & check_round_mask s0 = u32(0) - // recheck normalization if s2 & (mask28<> 8) // C.printf("mantissa after rounding : %08x%08x%08x binexp: %d \n", s2,s1,s0,binexp) // C.printf("Tmp result: %016x\n",tmp) @@ -518,7 +516,8 @@ fn converter(pn mut PrepNumber) u64 { else if binexp < 1 { if pn.negative { result = DOUBLE_MINUS_ZERO - } else { + } + else { result = DOUBLE_PLUS_ZERO } } diff --git a/vlib/sync/sync_nix.v b/vlib/sync/sync_nix.v index e00263edc3..3d225a55a5 100644 --- a/vlib/sync/sync_nix.v +++ b/vlib/sync/sync_nix.v @@ -1,24 +1,25 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module sync #include - fn C.pthread_mutex_init() + + fn C.pthread_mutex_lock() + + fn C.pthread_mutex_unlock() - - -//[init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function. +// [init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function. pub struct Mutex { mutex C.pthread_mutex_t } pub fn new_mutex() Mutex { - m := Mutex{} - C.pthread_mutex_init( &m.mutex, C.NULL) + m := Mutex{ + } + C.pthread_mutex_init(&m.mutex, C.NULL) return m } diff --git a/vlib/sync/waitgroup.v b/vlib/sync/waitgroup.v index 193ef16c69..f7a624db72 100644 --- a/vlib/sync/waitgroup.v +++ b/vlib/sync/waitgroup.v @@ -1,18 +1,17 @@ // Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - module sync - -//[init_with=new_waitgroup] // TODO: implement support for init_with struct attribute, and disallow WaitGroup{} from outside the sync.new_waitgroup() function. +// [init_with=new_waitgroup] // TODO: implement support for init_with struct attribute, and disallow WaitGroup{} from outside the sync.new_waitgroup() function. pub struct WaitGroup { mut: - mu Mutex + mu Mutex active int } pub fn new_waitgroup() WaitGroup { - mut w := WaitGroup{} + mut w := WaitGroup{ + } w.mu = sync.new_mutex() return w } @@ -41,3 +40,4 @@ pub fn (wg &WaitGroup) wait() { } } } +