ci: fix warnings/errors due to the vfmt change

pull/6623/head
Delyan Angelov 2020-10-15 16:17:52 +03:00
parent 50a2b033b7
commit 31ef921ef2
33 changed files with 466 additions and 570 deletions

View File

@ -27,5 +27,4 @@ fn main() {
exit(1) exit(1)
} }
*/ */
} }

View File

@ -11,13 +11,19 @@ const (
base_os = 'linux' base_os = 'linux'
os_names = ['linux', 'macos', 'windows'] os_names = ['linux', 'macos', 'windows']
skip_modules = [ skip_modules = [
'builtin.bare', 'builtin.js', 'builtin.bare',
'strconv', 'strconv.ftoa', 'hash', 'strings', 'builtin.js',
'strconv',
'strconv.ftoa',
'hash',
'strings',
'crypto.rand', 'crypto.rand',
'os.bare', 'os2', 'os.bare',
'picohttpparser', 'picoev', 'os2',
'picohttpparser',
'picoev',
'szip', 'szip',
'v.eval' 'v.eval',
] ]
) )
@ -44,7 +50,7 @@ fn main() {
} }
for mname in app.modules { for mname in app.modules {
if !app.is_verbose { if !app.is_verbose {
eprintln('Checking module: ${mname} ...') eprintln('Checking module: $mname ...')
} }
api_base := app.gen_api_for_module_in_os(mname, base_os) api_base := app.gen_api_for_module_in_os(mname, base_os)
for oname in os_names { for oname in os_names {
@ -85,7 +91,7 @@ fn all_vlib_modules() []string {
return modules return modules
} }
fn (app App) gen_api_for_module_in_os(mod_name, os_name string) string { fn (app App) gen_api_for_module_in_os(mod_name string, os_name string) string {
if app.is_verbose { if app.is_verbose {
eprintln('Checking module: ${mod_name:-30} for OS: ${os_name:-10} ...') eprintln('Checking module: ${mod_name:-30} for OS: ${os_name:-10} ...')
} }
@ -102,7 +108,7 @@ fn (app App) gen_api_for_module_in_os(mod_name, os_name string) string {
fn_signature := s.stringify(b.table, mod_name) fn_signature := s.stringify(b.table, mod_name)
fn_mod := s.modname() fn_mod := s.modname()
if fn_mod == mod_name { if fn_mod == mod_name {
fline := '${fn_mod}: $fn_signature' fline := '$fn_mod: $fn_signature'
res << fline res << fline
} }
} }
@ -113,10 +119,10 @@ fn (app App) gen_api_for_module_in_os(mod_name, os_name string) string {
return res.join('\n') return res.join('\n')
} }
fn (mut app App) compare_api(api_base, api_os, mod_name, os_base, os_target string) { fn (mut app App) compare_api(api_base string, api_os string, mod_name string, os_base string, os_target string) {
res := util.color_compare_strings(app.diff_cmd, api_base, api_os) res := util.color_compare_strings(app.diff_cmd, api_base, api_os)
if res.len > 0 { if res.len > 0 {
summary := 'Different APIs found for module: `${mod_name}`, between OS base: `${os_base}` and OS: `${os_target}`' summary := 'Different APIs found for module: `$mod_name`, between OS base: `$os_base` and OS: `$os_target`'
eprintln(term.header(summary, '-')) eprintln(term.header(summary, '-'))
eprintln(res) eprintln(res)
eprintln(term.h_divider('-')) eprintln(term.h_divider('-'))

View File

@ -15,5 +15,4 @@ fn foo${i}() {
} }
// println('fn main() {foo1()} ') // println('fn main() {foo1()} ')
println('fn main() { println("1m DONE") } ') println('fn main() { println("1m DONE") } ')
} }

View File

@ -364,7 +364,7 @@ fn (mut gen_vc GenVC) purge_repos() {
} }
// check if file size is too short // check if file size is too short
fn (mut gen_vc GenVC) assert_file_exists_and_is_not_too_short(f, emsg string) { fn (mut gen_vc GenVC) assert_file_exists_and_is_not_too_short(f string, emsg string) {
if !os.exists(f) { if !os.exists(f) {
gen_vc.logger.error('$err_msg_build: $emsg .') gen_vc.logger.error('$err_msg_build: $emsg .')
gen_vc.gen_error = true gen_vc.gen_error = true

View File

@ -39,12 +39,12 @@ pub fn line_to_timestamp_and_commit(line string) (int, string) {
return parts[0].int(), parts[1] return parts[0].int(), parts[1]
} }
pub fn normalized_workpath_for_commit(workdir, commit string) string { pub fn normalized_workpath_for_commit(workdir string, commit string) string {
nc := 'v_at_' + commit.replace('^', '_').replace('-', '_').replace('/', '_') nc := 'v_at_' + commit.replace('^', '_').replace('-', '_').replace('/', '_')
return os.real_path(workdir + os.path_separator + nc) return os.real_path(workdir + os.path_separator + nc)
} }
pub fn prepare_vc_source(vcdir, cdir, commit string) (string, string) { pub fn prepare_vc_source(vcdir string, cdir string, commit string) (string, string) {
scripting.chdir(cdir) scripting.chdir(cdir)
// Building a historic v with the latest vc is not always possible ... // Building a historic v with the latest vc is not always possible ...
// It is more likely, that the vc *at the time of the v commit*, // It is more likely, that the vc *at the time of the v commit*,
@ -62,7 +62,7 @@ pub fn prepare_vc_source(vcdir, cdir, commit string) (string, string) {
return v_commithash, vccommit_before return v_commithash, vccommit_before
} }
pub fn clone_or_pull(remote_git_url, local_worktree_path string) { pub fn clone_or_pull(remote_git_url string, local_worktree_path string) {
// NB: after clone_or_pull, the current repo branch is === HEAD === master // NB: after clone_or_pull, the current repo branch is === HEAD === master
if os.is_dir(local_worktree_path) && os.is_dir(os.join_path(local_worktree_path, '.git')) { if os.is_dir(local_worktree_path) && os.is_dir(os.join_path(local_worktree_path, '.git')) {
// Already existing ... Just pulling in this case is faster usually. // Already existing ... Just pulling in this case is faster usually.

View File

@ -64,7 +64,7 @@ fn (c Context) compare_versions() {
} }
} }
fn (c &Context) prepare_v(cdir, commit string) { fn (c &Context) prepare_v(cdir string, commit string) {
mut cc := os.getenv('CC') mut cc := os.getenv('CC')
if cc == '' { if cc == '' {
cc = 'cc' cc = 'cc'

View File

@ -19,6 +19,7 @@ mut:
timings []int timings []int
atiming Aints atiming Aints
} }
struct Context { struct Context {
mut: mut:
count int count int
@ -42,8 +43,11 @@ mut:
average f64 average f64
stddev f64 stddev f64
} }
fn new_aints(vals []int) Aints { fn new_aints(vals []int) Aints {
mut res := Aints{ values: vals } mut res := Aints{
values: vals
}
mut sum := i64(0) mut sum := i64(0)
mut imin := math.max_i32 mut imin := math.max_i32
mut imax := -math.max_i32 mut imax := -math.max_i32
@ -70,13 +74,18 @@ fn new_aints(vals []int) Aints {
res.stddev = math.sqrt(devsum / f64(vals.len)) res.stddev = math.sqrt(devsum / f64(vals.len))
return res return res
} }
fn (a Aints) str() string { return util.bold('${a.average:9.3f}') + 'ms ± σ: ${a.stddev:-5.1f}ms, min max: ${a.imin}ms ${a.imax}ms' }
fn (a Aints) str() string {
return util.bold('${a.average:9.3f}') +
'ms ± σ: ${a.stddev:-5.1f}ms, min max: ${a.imin}ms ${a.imax}ms'
}
const ( const (
max_fail_percent = 100000 max_fail_percent = 100000
max_time = 60 * 1000 // ms max_time = 60 * 1000 // ms
performance_regression_label = 'Performance regression detected, failing since ' performance_regression_label = 'Performance regression detected, failing since '
) )
fn main() { fn main() {
mut context := Context{} mut context := Context{}
context.parse_options() context.parse_options()
@ -132,7 +141,9 @@ fn (mut context Context) run() {
for i in 1 .. context.warmup + 1 { for i in 1 .. context.warmup + 1 {
print('\r warming up run: ${i:4}/${context.warmup:-4} for ${cmd:-50s} took ${duration:6} ms ...') print('\r warming up run: ${i:4}/${context.warmup:-4} for ${cmd:-50s} took ${duration:6} ms ...')
mut sw := time.new_stopwatch({}) mut sw := time.new_stopwatch({})
os.exec(cmd) or { continue } os.exec(cmd) or {
continue
}
duration = int(sw.elapsed().milliseconds()) duration = int(sw.elapsed().milliseconds())
} }
run_warmups++ run_warmups++
@ -142,7 +153,7 @@ fn (mut context Context) run() {
avg := f64(sum) / f64(i) avg := f64(sum) / f64(i)
print('\rAverage: ${avg:9.3f}ms | run: ${i:4}/${context.count:-4} | took ${duration:6} ms') print('\rAverage: ${avg:9.3f}ms | run: ${i:4}/${context.count:-4} | took ${duration:6} ms')
if context.show_output { if context.show_output {
print(' | result: ${oldres:-s}') print(' | result: ${oldres:s}')
} }
mut sw := time.new_stopwatch({}) mut sw := time.new_stopwatch({})
res := scripting.exec(cmd) or { res := scripting.exec(cmd) or {
@ -153,7 +164,8 @@ fn (mut context Context) run() {
eprintln('${i:10} non 0 exit code for cmd: $cmd') eprintln('${i:10} non 0 exit code for cmd: $cmd')
continue continue
} }
context.results[icmd].outputs << res.output.trim_right('\r\n').replace('\r\n', '\n').split("\n") context.results[icmd].outputs <<
res.output.trim_right('\r\n').replace('\r\n', '\n').split('\n')
context.results[icmd].timings << duration context.results[icmd].timings << duration
sum += duration sum += duration
runs++ runs++
@ -165,7 +177,7 @@ fn (mut context Context) run() {
context.results[icmd].atiming = new_aints(context.results[icmd].timings) context.results[icmd].atiming = new_aints(context.results[icmd].timings)
context.clear_line() context.clear_line()
print('\r') print('\r')
mut m := map[string][]int mut m := map[string][]int{}
for o in context.results[icmd].outputs { for o in context.results[icmd].outputs {
x := o.split(':') x := o.split(':')
if x.len > 1 { if x.len > 1 {
@ -183,7 +195,7 @@ fn (mut context Context) run() {
} }
// merge current raw results to the previous ones // merge current raw results to the previous ones
old_oms := context.results[icmd].oms old_oms := context.results[icmd].oms
mut new_oms := map[string][]int mut new_oms := map[string][]int{}
for k, v in m { for k, v in m {
if old_oms[k].len == 0 { if old_oms[k].len == 0 {
new_oms[k] = v new_oms[k] = v
@ -205,8 +217,9 @@ fn (mut context Context) run() {
context.results[icmd].summary = new_full_summary context.results[icmd].summary = new_full_summary
} }
} }
fn (mut context Context) show_diff_summary() { fn (mut context Context) show_diff_summary() {
context.results.sort_with_compare(fn (a, b &CmdResult) int { context.results.sort_with_compare(fn (a &CmdResult, b &CmdResult) int {
if a.atiming.average < b.atiming.average { if a.atiming.average < b.atiming.average {
return -1 return -1
} }
@ -224,7 +237,7 @@ fn (mut context Context) show_diff_summary() {
if r.icmd == 0 { if r.icmd == 0 {
first_cmd_percentage = cpercent first_cmd_percentage = cpercent
} }
println(' ${first_marker}${(i+1):3} | ${cpercent:6.1f}% slower | ${r.cmd:-55s} | ${r.atiming}') println(' $first_marker${(i+1):3} | ${cpercent:6.1f}% slower | ${r.cmd:-55s} | $r.atiming')
} }
$if debugcontext ? { $if debugcontext ? {
println('context: $context') println('context: $context')
@ -232,7 +245,7 @@ fn (mut context Context) show_diff_summary() {
eprintln('base: $base | context.fail_on_maxtime: $context.fail_on_maxtime') eprintln('base: $base | context.fail_on_maxtime: $context.fail_on_maxtime')
if int(base) > context.fail_on_maxtime { if int(base) > context.fail_on_maxtime {
print(performance_regression_label) print(performance_regression_label)
println('average time: ${base:6.1f} ms > ${context.fail_on_maxtime} ms threshold.') println('average time: ${base:6.1f} ms > $context.fail_on_maxtime ms threshold.')
exit(2) exit(2)
} }
if context.fail_on_regress_percent == max_fail_percent || context.results.len < 2 { if context.fail_on_regress_percent == max_fail_percent || context.results.len < 2 {

View File

@ -20,29 +20,26 @@ mut:
fn (context Context) header() string { fn (context Context) header() string {
mut header_s := '' mut header_s := ''
header_s += 'module ${context.module_name}\n' header_s += 'module $context.module_name\n'
header_s += '\n' header_s += '\n'
allfiles := context.files.join(' ') allfiles := context.files.join(' ')
mut options := []string{} mut options := []string{}
if context.prefix.len > 0 { if context.prefix.len > 0 {
options << '-p ${context.prefix}' options << '-p $context.prefix'
} }
if context.module_name.len > 0 { if context.module_name.len > 0 {
options << '-m ${context.module_name}' options << '-m $context.module_name'
} }
if context.write_file.len > 0 { if context.write_file.len > 0 {
options << '-w ${context.write_file}' options << '-w $context.write_file'
} }
soptions := options.join(' ') soptions := options.join(' ')
header_s += '// File generated by:\n' header_s += '// File generated by:\n'
header_s += '// v bin2v ${allfiles} ${soptions}\n' header_s += '// v bin2v $allfiles $soptions\n'
header_s += '// Please, do not edit this file.\n' header_s += '// Please, do not edit this file.\n'
header_s += '// Your changes may be overwritten.\n' header_s += '// Your changes may be overwritten.\n'
header_s += '\n' header_s += '\n'
header_s += 'const (\n' header_s += 'const (\n'
return header_s return header_s
} }
@ -54,14 +51,14 @@ fn (context Context) file2v(file string) string {
mut sb := strings.new_builder(1000) mut sb := strings.new_builder(1000)
fname := os.file_name(file) fname := os.file_name(file)
fname_no_dots := fname.replace('.', '_') fname_no_dots := fname.replace('.', '_')
byte_name := '${context.prefix}${fname_no_dots}'.to_lower() byte_name := '$context.prefix$fname_no_dots'.to_lower()
fbytes := os.read_bytes(file) or { fbytes := os.read_bytes(file) or {
eprintln('Error: $err') eprintln('Error: $err')
return '' return ''
} }
fbyte := fbytes[0] fbyte := fbytes[0]
sb.write(' ${byte_name}_len = ${fbytes.len}\n') sb.write(' ${byte_name}_len = $fbytes.len\n')
sb.write(' ${byte_name} = [ byte(${fbyte}), \n ') sb.write(' $byte_name = [ byte($fbyte), \n ')
for i := 1; i < fbytes.len; i++ { for i := 1; i < fbytes.len; i++ {
b := int(fbytes[i]).str() b := int(fbytes[i]).str()
sb.write('${b:4s}, ') sb.write('${b:4s}, ')
@ -71,7 +68,6 @@ fn (context Context) file2v(file string) string {
} }
sb.write('\n]!!\n') sb.write('\n]!!\n')
sb.write('\n') sb.write('\n')
return sb.str() return sb.str()
} }
@ -100,19 +96,19 @@ fn main() {
exit(0) exit(0)
} }
context.files = real_files context.files = real_files
if !context.write_file.ends_with('.v') { if !context.write_file.ends_with('.v') {
context.write_file += '.v' context.write_file += '.v'
} }
if context.write_file.len > 0 { if context.write_file.len > 0 {
mut out_file := os.create(context.write_file) or { panic(err) } mut out_file := os.create(context.write_file) or {
panic(err)
}
out_file.write(context.header()) out_file.write(context.header())
for file in real_files { for file in real_files {
out_file.write(context.file2v(file)) out_file.write(context.file2v(file))
} }
out_file.write(context.footer()) out_file.write(context.footer())
} } else {
else {
println(context.header()) println(context.header())
for file in real_files { for file in real_files {
println(context.file2v(file)) println(context.file2v(file))

View File

@ -9,7 +9,8 @@ fn main() {
args_string := args[1..].join(' ') args_string := args[1..].join(' ')
skips := []string{} skips := []string{}
util.ensure_modules_for_all_tools_are_installed('-v' in args) util.ensure_modules_for_all_tools_are_installed('-v' in args)
if testing.v_build_failing_skipped(args_string.all_before('build-tools'), 'cmd/tools', skips) { if testing.v_build_failing_skipped(args_string.all_before('build-tools'), 'cmd/tools',
skips) {
exit(1) exit(1)
} }
} }

View File

@ -19,7 +19,7 @@ fn cerror(e string) {
eprintln('\nerror: $e') eprintln('\nerror: $e')
} }
fn vmod_content(name, desc string) string { fn vmod_content(name string, desc string) string {
return [ return [
'Module {', 'Module {',
" name: '$name'", " name: '$name'",

View File

@ -207,7 +207,7 @@ fn handle_http_connection(mut con net.Socket, ctx &VdocHttpServerContext) {
send_http_response(mut con, 200, ctx.content_type, ctx.docs[filename]) send_http_response(mut con, 200, ctx.content_type, ctx.docs[filename])
} }
fn send_http_response(mut con net.Socket, http_code int, content_type, html string) { fn send_http_response(mut con net.Socket, http_code int, content_type string, html string) {
content_length := html.len.str() content_length := html.len.str()
shttp_code := http_code.str() shttp_code := http_code.str()
mut http_response := strings.new_builder(20000) mut http_response := strings.new_builder(20000)
@ -230,7 +230,7 @@ fn send_http_response(mut con net.Socket, http_code int, content_type, html stri
} }
} }
fn get_src_link(repo_url, file_name string, line_nr int) string { fn get_src_link(repo_url string, file_name string, line_nr int) string {
mut url := urllib.parse(repo_url) or { mut url := urllib.parse(repo_url) or {
return '' return ''
} }
@ -516,10 +516,13 @@ fn (cfg DocConfig) gen_html(idx int) string {
} }
return html_content.replace('{{ title }}', dcs.head.name).replace('{{ head_name }}', return html_content.replace('{{ title }}', dcs.head.name).replace('{{ head_name }}',
header_name).replace('{{ version }}', version).replace('{{ light_icon }}', cfg.assets['light_icon']).replace('{{ dark_icon }}', header_name).replace('{{ version }}', version).replace('{{ light_icon }}', cfg.assets['light_icon']).replace('{{ dark_icon }}',
cfg.assets['dark_icon']).replace('{{ menu_icon }}', cfg.assets['menu_icon']).replace('{{ head_assets }}', if cfg.inline_assets { cfg.assets['dark_icon']).replace('{{ menu_icon }}', cfg.assets['menu_icon']).replace('{{ head_assets }}',
'\n <style>'+ cfg.assets['doc_css'] + '</style>\n <style>'+ cfg.assets['normalize_css'] +'</style>' if cfg.inline_assets {
'\n <style>' + cfg.assets['doc_css'] + '</style>\n <style>' + cfg.assets['normalize_css'] +
'</style>'
} else { } else {
'\n <link rel="stylesheet" href="'+cfg.assets['doc_css']+'" />\n <link rel="stylesheet" href="'+cfg.assets['normalize_css']+'" />' '\n <link rel="stylesheet" href="' + cfg.assets['doc_css'] + '" />\n <link rel="stylesheet" href="' +
cfg.assets['normalize_css'] + '" />'
}).replace('{{ toc_links }}', if cfg.is_multi || cfg.docs.len > 1 { }).replace('{{ toc_links }}', if cfg.is_multi || cfg.docs.len > 1 {
toc2.str() toc2.str()
} else { } else {
@ -622,7 +625,6 @@ fn (cfg DocConfig) render_parallel() {
vjobs := runtime.nr_jobs() vjobs := runtime.nr_jobs()
mut work := sync.new_channel<ParallelDoc>(cfg.docs.len) mut work := sync.new_channel<ParallelDoc>(cfg.docs.len)
mut wg := sync.new_waitgroup() mut wg := sync.new_waitgroup()
for i in 0 .. cfg.docs.len { for i in 0 .. cfg.docs.len {
p_doc := ParallelDoc{cfg.docs[i], i} p_doc := ParallelDoc{cfg.docs[i], i}
work.push(&p_doc) work.push(&p_doc)
@ -637,7 +639,6 @@ fn (cfg DocConfig) render_parallel() {
fn (cfg DocConfig) render() map[string]string { fn (cfg DocConfig) render() map[string]string {
mut docs := map[string]string{} mut docs := map[string]string{}
for i, doc in cfg.docs { for i, doc in cfg.docs {
name, output := cfg.render_doc(doc, i) name, output := cfg.render_doc(doc, i)
docs[name] = output.trim_space() docs[name] = output.trim_space()
@ -649,12 +650,12 @@ fn (cfg DocConfig) render() map[string]string {
fn (mut cfg DocConfig) render_static() { fn (mut cfg DocConfig) render_static() {
if cfg.output_type == .html { if cfg.output_type == .html {
cfg.assets = { cfg.assets = {
'doc_css': cfg.get_resource(css_js_assets[0], true), 'doc_css': cfg.get_resource(css_js_assets[0], true)
'normalize_css': cfg.get_resource(css_js_assets[1], true), 'normalize_css': cfg.get_resource(css_js_assets[1], true)
'doc_js': cfg.get_resource(css_js_assets[2], !cfg.serve_http), 'doc_js': cfg.get_resource(css_js_assets[2], !cfg.serve_http)
'light_icon': cfg.get_resource('light.svg', true), 'light_icon': cfg.get_resource('light.svg', true)
'dark_icon': cfg.get_resource('dark.svg', true), 'dark_icon': cfg.get_resource('dark.svg', true)
'menu_icon': cfg.get_resource('menu.svg', true), 'menu_icon': cfg.get_resource('menu.svg', true)
'arrow_icon': cfg.get_resource('arrow.svg', true) 'arrow_icon': cfg.get_resource('arrow.svg', true)
} }
} }

View File

@ -1,5 +1,4 @@
import os import os
import term
import time import time
import v.util import v.util
import runtime import runtime
@ -130,7 +129,7 @@ fn (mut a App) line(label string, value string) {
a.println('$label: ${util.bold(value)}') a.println('$label: ${util.bold(value)}')
} }
fn (app &App) parse(config, sep string) map[string]string { fn (app &App) parse(config string, sep string) map[string]string {
mut m := map[string]string mut m := map[string]string
for line in config.split_into_lines() { for line in config.split_into_lines() {
sline := line.trim_space() sline := line.trim_space()

View File

@ -187,7 +187,7 @@ fn print_compiler_options(compiler_params &pref.Preferences) {
eprintln(' is_script: $compiler_params.is_script ') eprintln(' is_script: $compiler_params.is_script ')
} }
fn (foptions &FormatOptions) post_process_file(file, formatted_file_path string) { fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path string) {
if formatted_file_path.len == 0 { if formatted_file_path.len == 0 {
return return
} }

View File

@ -1,87 +0,0 @@
module main
/*
QTODO
import os
import flag
import strings
import compiler
import v.pref
const (
tool_version = '0.0.1'
tool_description = ' Extracts the function names declared in a v file.'
)
fn f_to_string(fmod string, f compiler.Fn) ?string {
svisibility := if f.is_public {
'public'
}else{
'private'
}
if fmod != f.v_fn_module() { return none }
if fmod == 'builtin' {
return '$svisibility\t' + f.v_fn_name()
}
return '$svisibility\t' + f.v_fn_module() + '.' + f.v_fn_name()
}
fn analyze_v_file(file string) {
println('')
hash := strings.repeat(`#`, (76 - file.len) / 2)
println('$hash $file $hash')
// main work:
mut pref := &pref.Preferences{
path: file
}
pref.fill_with_defaults()
mut v := compiler.new_v(pref)
v.add_v_files_to_compile()
for f in v.files { v.parse(f, .decl) }
fi := v.get_file_parser_index( file ) or { panic(err) }
fmod := v.parsers[fi].mod
// output:
mut fns :=[]string
for _, f in v.table.fns {
fname := f_to_string(fmod, f) or { continue }
fns << fname
}
fns.sort()
for f in fns { println(f) }
}
fn main(){
toolexe := os.executable()
compiler.set_vroot_folder(os.dir(os.dir(os.dir(toolexe))))
mut fp := flag.new_flag_parser(os.args)
fp.application(os.file_name(toolexe))
fp.version( tool_version )
fp.description( tool_description )
fp.arguments_description('FILE.v/FOLDER [FILE.v/FOLDER]...')
fp.limit_free_args_to_at_least(1)
fp.skip_executable()
show_help:=fp.bool('help', `h`, false, 'Show this help screen\n')
if( show_help ){
println( fp.usage() )
exit(0)
}
mut files := []string{}
locations := fp.finalize() or { eprintln('Error: ' + err) exit(1) }
for xloc in locations {
loc := os.real_path(xloc)
xfiles := if os.is_dir(loc){ os.walk_ext(loc,'.v') } else { [loc] }
filtered_files := xfiles.filter(!it.ends_with('_js.v'))
files << filtered_files
}
for file in files {
analyze_v_file(file)
}
}
*/
fn main() {}

View File

@ -12,7 +12,8 @@ import v.vmod
const ( const (
default_vpm_server_urls = ['https://vpm.vlang.io'] default_vpm_server_urls = ['https://vpm.vlang.io']
valid_vpm_commands = ['help', 'search', 'install', 'update', 'upgrade', 'outdated', 'list', 'remove'] valid_vpm_commands = ['help', 'search', 'install', 'update', 'upgrade', 'outdated',
'list', 'remove']
excluded_dirs = ['cache', 'vlib'] excluded_dirs = ['cache', 'vlib']
supported_vcs_systems = ['git', 'hg'] supported_vcs_systems = ['git', 'hg']
supported_vcs_folders = ['.git', '.hg'] supported_vcs_folders = ['.git', '.hg']
@ -281,7 +282,9 @@ fn get_outdated() ?[]string {
} }
fn vpm_upgrade() { fn vpm_upgrade() {
outdated := get_outdated() or { exit(1) } outdated := get_outdated() or {
exit(1)
}
if outdated.len > 0 { if outdated.len > 0 {
vpm_update(outdated) vpm_update(outdated)
} else { } else {
@ -290,7 +293,9 @@ fn vpm_upgrade() {
} }
fn vpm_outdated() { fn vpm_outdated() {
outdated := get_outdated() or { exit(1) } outdated := get_outdated() or {
exit(1)
}
if outdated.len > 0 { if outdated.len > 0 {
println('Outdated modules:') println('Outdated modules:')
for m in outdated { for m in outdated {
@ -452,7 +457,7 @@ fn get_all_modules() []string {
return modules return modules
} }
fn resolve_dependencies(name, module_path string, module_names []string) { fn resolve_dependencies(name string, module_path string, module_names []string) {
vmod_path := os.join_path(module_path, 'v.mod') vmod_path := os.join_path(module_path, 'v.mod')
if !os.exists(vmod_path) { if !os.exists(vmod_path) {
return return

View File

@ -95,7 +95,7 @@ fn repl_help() {
') ')
} }
fn run_repl(workdir, vrepl_prefix string) { fn run_repl(workdir string, vrepl_prefix string) {
if !is_stdin_a_pipe { if !is_stdin_a_pipe {
println(util.full_v_version(false)) println(util.full_v_version(false))
println('Use Ctrl-C or `exit` to exit, or `help` to see other available commands') println('Use Ctrl-C or `exit` to exit, or `help` to see other available commands')

View File

@ -8,15 +8,15 @@ fn main() {
vroot := os.dir(vexe) vroot := os.dir(vexe)
os.chdir(vroot) os.chdir(vroot)
os.setenv('VCOLORS', 'always', true) os.setenv('VCOLORS', 'always', true)
self_idx := os.args.index('self') self_idx := os.args.index('self')
args := os.args[1..self_idx] args := os.args[1..self_idx]
args_str := args.join(' ') args_str := args.join(' ')
options := if args.len > 0 { '($args_str)' } else { '' } options := if args.len > 0 { '($args_str)' } else { '' }
println('V self compiling ${options}...') println('V self compiling ${options}...')
cmd := '$vexe -o v2 $args_str cmd/v' cmd := '$vexe -o v2 $args_str cmd/v'
result := os.exec(cmd) or { panic(err) } result := os.exec(cmd) or {
panic(err)
}
if result.exit_code != 0 { if result.exit_code != 0 {
mut err := 'Permission denied' mut err := 'Permission denied'
if !result.output.contains('Permission denied') { if !result.output.contains('Permission denied') {
@ -28,11 +28,9 @@ fn main() {
if result.output.len > 0 { if result.output.len > 0 {
println(result.output.trim_space()) println(result.output.trim_space())
} }
v_file := if os.user_os() == 'windows' { 'v.exe' } else { 'v' } v_file := if os.user_os() == 'windows' { 'v.exe' } else { 'v' }
v2_file := if os.user_os() == 'windows' { 'v2.exe' } else { 'v2' } v2_file := if os.user_os() == 'windows' { 'v2.exe' } else { 'v2' }
bak_file := if os.user_os() == 'windows' { 'v_old.exe' } else { 'v_old' } bak_file := if os.user_os() == 'windows' { 'v_old.exe' } else { 'v_old' }
if os.exists(bak_file) { if os.exists(bak_file) {
os.rm(bak_file) os.rm(bak_file)
} }

View File

@ -8,19 +8,16 @@ fn main() {
println('Setup freetype...') println('Setup freetype...')
vroot := os.dir(pref.vexe_path()) vroot := os.dir(pref.vexe_path())
os.chdir(vroot) os.chdir(vroot)
if os.is_dir('./thirdparty/freetype') { if os.is_dir('./thirdparty/freetype') {
println('Thirdparty "freetype" is already installed.') println('Thirdparty "freetype" is already installed.')
} } else {
else {
s := os.exec('git clone --depth=1 https://github.com/ubawurinna/freetype-windows-binaries ./thirdparty/freetype/') or { s := os.exec('git clone --depth=1 https://github.com/ubawurinna/freetype-windows-binaries ./thirdparty/freetype/') or {
panic(err) panic(err)
} }
println(s.output) println(s.output)
println('Thirdparty "freetype" installed successfully.') println('Thirdparty "freetype" installed successfully.')
} }
} } $else {
$else {
println('It is only for Windows to setup thirdparty "freetype".') println('It is only for Windows to setup thirdparty "freetype".')
} }
} }

View File

@ -7,7 +7,6 @@ $if windows {
#flag -lUser32 #flag -lUser32
} }
} }
fn main() { fn main() {
vexe := pref.vexe_path() vexe := pref.vexe_path()
$if windows { $if windows {
@ -45,18 +44,14 @@ fn setup_symlink_windows(vexe string){
// Create a symlink in a new local folder (.\.bin\.v.exe) // Create a symlink in a new local folder (.\.bin\.v.exe)
// Puts `v` in %PATH% without polluting it with anything else (like make.bat). // Puts `v` in %PATH% without polluting it with anything else (like make.bat).
// This will make `v` available on cmd.exe, PowerShell, and MinGW(MSYS)/WSL/Cygwin // This will make `v` available on cmd.exe, PowerShell, and MinGW(MSYS)/WSL/Cygwin
vdir := os.real_path(os.dir(vexe)) vdir := os.real_path(os.dir(vexe))
vsymlinkdir := os.join_path(vdir, '.bin') vsymlinkdir := os.join_path(vdir, '.bin')
mut vsymlink := os.join_path(vsymlinkdir, 'v.exe') mut vsymlink := os.join_path(vsymlinkdir, 'v.exe')
if !os.exists(vsymlinkdir) { if !os.exists(vsymlinkdir) {
os.mkdir_all(vsymlinkdir) // will panic if fails os.mkdir_all(vsymlinkdir) // will panic if fails
} else { } else {
os.rm(vsymlink) os.rm(vsymlink)
} }
// try to create a native symlink at .\.bin\v.exe // try to create a native symlink at .\.bin\v.exe
os.symlink(vsymlink, vexe) or { os.symlink(vsymlink, vexe) or {
// typically only fails if you're on a network drive (VirtualBox) // typically only fails if you're on a network drive (VirtualBox)
@ -67,15 +62,12 @@ fn setup_symlink_windows(vexe string){
if os.exists(vsymlink) { if os.exists(vsymlink) {
os.rm(vsymlink) os.rm(vsymlink)
} }
os.write_file(vsymlink, '@echo off\n${vexe} %*') os.write_file(vsymlink, '@echo off\n$vexe %*')
} }
if !os.exists(vsymlink) { if !os.exists(vsymlink) {
warn_and_exit('Could not create $vsymlink') warn_and_exit('Could not create $vsymlink')
} }
print('Symlink $vsymlink to $vexe created.\n\nChecking system %PATH%...') print('Symlink $vsymlink to $vexe created.\n\nChecking system %PATH%...')
reg_sys_env_handle := get_reg_sys_env_handle() or { reg_sys_env_handle := get_reg_sys_env_handle() or {
warn_and_exit(err) warn_and_exit(err)
return return
@ -84,10 +76,10 @@ fn setup_symlink_windows(vexe string){
// defer { // defer {
// C.RegCloseKey(reg_sys_env_handle) // C.RegCloseKey(reg_sys_env_handle)
// } // }
// if the above succeeded, and we cannot get the value, it may simply be empty // if the above succeeded, and we cannot get the value, it may simply be empty
sys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or { '' } sys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or {
''
}
current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator')) current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator'))
mut new_paths := [vsymlinkdir] mut new_paths := [vsymlinkdir]
for p in current_sys_paths { for p in current_sys_paths {
@ -95,13 +87,10 @@ fn setup_symlink_windows(vexe string){
new_paths << p new_paths << p
} }
} }
new_sys_env_path := new_paths.join(';') new_sys_env_path := new_paths.join(';')
if new_sys_env_path == sys_env_path { if new_sys_env_path == sys_env_path {
println('configured.') println('configured.')
} } else {
else {
print('not configured.\nAdding symlink directory to system %PATH%...') print('not configured.\nAdding symlink directory to system %PATH%...')
set_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or { set_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or {
warn_and_exit(err) warn_and_exit(err)
@ -110,7 +99,6 @@ fn setup_symlink_windows(vexe string){
} }
println('done.') println('done.')
} }
print('Letting running process know to update their Environment...') print('Letting running process know to update their Environment...')
send_setting_change_msg('Environment') or { send_setting_change_msg('Environment') or {
eprintln('\n' + err) eprintln('\n' + err)
@ -118,7 +106,6 @@ fn setup_symlink_windows(vexe string){
C.RegCloseKey(reg_sys_env_handle) C.RegCloseKey(reg_sys_env_handle)
return return
} }
C.RegCloseKey(reg_sys_env_handle) C.RegCloseKey(reg_sys_env_handle)
println('finished.\n\nNote: restart your shell/IDE to load the new %PATH%.') println('finished.\n\nNote: restart your shell/IDE to load the new %PATH%.')
println('After restarting your shell/IDE, give `v version` a try in another dir!') println('After restarting your shell/IDE, give `v version` a try in another dir!')
@ -153,7 +140,6 @@ fn get_reg_value(reg_env_key voidptr, key string) ?string {
if C.RegQueryValueEx(reg_env_key, key.to_wide(), 0, 0, reg_value, &reg_value_size) != 0 { if C.RegQueryValueEx(reg_env_key, key.to_wide(), 0, 0, reg_value, &reg_value_size) != 0 {
return error('Unable to get registry value for "$key", try rerunning as an Administrator') return error('Unable to get registry value for "$key", try rerunning as an Administrator')
} }
return string_from_wide(reg_value) return string_from_wide(reg_value)
} }
return error('not on windows') return error('not on windows')
@ -165,7 +151,6 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
if C.RegSetValueEx(reg_key, key.to_wide(), 0, 1, value.to_wide(), 4095) != 0 { if C.RegSetValueEx(reg_key, key.to_wide(), 0, 1, value.to_wide(), 4095) != 0 {
return error('Unable to set registry value for "$key", are you running as an Administrator?') return error('Unable to set registry value for "$key", are you running as an Administrator?')
} }
return true return true
} }
return error('not on windows') return error('not on windows')
@ -175,7 +160,8 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
// letting them know that the system environment has changed and should be reloaded // letting them know that the system environment has changed and should be reloaded
fn send_setting_change_msg(message_data string) ?bool { fn send_setting_change_msg(message_data string) ?bool {
$if windows { $if windows {
if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) == 0 { if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) ==
0 {
return error('Could not broadcast WM_SETTINGCHANGE') return error('Could not broadcast WM_SETTINGCHANGE')
} }
return true return true

View File

@ -18,17 +18,14 @@ fn main() {
println('') println('')
return return
} }
args_to_executable := args[1..] args_to_executable := args[1..]
args_before := cmdline.options_before(args_to_executable, ['test']) args_before := cmdline.options_before(args_to_executable, ['test'])
args_after := cmdline.options_after(args_to_executable, ['test']) args_after := cmdline.options_after(args_to_executable, ['test'])
if args_after.join(' ') == 'v' { if args_after.join(' ') == 'v' {
eprintln('`v test v` has been deprecated.') eprintln('`v test v` has been deprecated.')
eprintln('Use `v test-compiler` instead.') eprintln('Use `v test-compiler` instead.')
exit(1) exit(1)
} }
mut ts := testing.new_test_session(args_before.join(' ')) mut ts := testing.new_test_session(args_before.join(' '))
for targ in args_after { for targ in args_after {
if os.exists(targ) && targ.ends_with('_test.v') { if os.exists(targ) && targ.ends_with('_test.v') {
@ -42,10 +39,8 @@ fn main() {
} }
println('Unrecognized test file $targ .') println('Unrecognized test file $targ .')
} }
testing.header('Testing...') testing.header('Testing...')
ts.test() ts.test()
println(ts.benchmark.total_message('running V _test.v files')) println(ts.benchmark.total_message('running V _test.v files'))
if ts.failed { if ts.failed {
exit(1) exit(1)

View File

@ -11,13 +11,10 @@ pub struct Flag {
} }
pub fn (f Flag) str() string { pub fn (f Flag) str() string {
return '' return '' + ' flag:\n' + ' name: $f.name\n' + ' abbr: $f.abbr\n' +
+' flag:\n' ' usag: $f.usage\n' + ' desc: $f.val_desc'
+' name: $f.name\n'
+' abbr: $f.abbr\n'
+' usag: $f.usage\n'
+' desc: $f.val_desc'
} }
pub fn (af []Flag) str() string { pub fn (af []Flag) str() string {
mut res := []string{} mut res := []string{}
res << '\n []Flag = [' res << '\n []Flag = ['
@ -27,17 +24,16 @@ pub fn (af []Flag) str() string {
res << ' ]' res << ' ]'
return res.join('\n') return res.join('\n')
} }
// //
pub struct FlagParser { pub struct FlagParser {
pub mut: pub mut:
args []string // the arguments to be parsed args []string // the arguments to be parsed
max_free_args int max_free_args int
flags []Flag // registered flags flags []Flag // registered flags
application_name string application_name string
application_version string application_version string
application_description string application_description string
min_free_args int min_free_args int
args_description string args_description string
} }
@ -52,7 +48,10 @@ pub const (
// create a new flag set for parsing command line arguments // create a new flag set for parsing command line arguments
// TODO use INT_MAX some how // TODO use INT_MAX some how
pub fn new_flag_parser(args []string) &FlagParser { pub fn new_flag_parser(args []string) &FlagParser {
return &FlagParser{args: args.clone(), max_free_args: max_args_number} return &FlagParser{
args: args.clone()
max_free_args: max_args_number
}
} }
// change the application name to be used in 'usage' output // change the application name to be used in 'usage' output
@ -78,9 +77,9 @@ pub fn (mut fs FlagParser) skip_executable() {
// private helper to register a flag // private helper to register a flag
fn (mut fs FlagParser) add_flag(name string, abbr byte, usage string, desc string) { fn (mut fs FlagParser) add_flag(name string, abbr byte, usage string, desc string) {
fs.flags << Flag{ fs.flags << Flag{
name: name, name: name
abbr: abbr, abbr: abbr
usage: usage, usage: usage
val_desc: desc val_desc: desc
} }
} }
@ -336,7 +335,7 @@ pub fn (mut fs FlagParser) limit_free_args_to_exactly(n int) {
// this will cause an error in finalize() if free args are out of range // this will cause an error in finalize() if free args are out of range
// (min, ..., max) // (min, ..., max)
pub fn (mut fs FlagParser) limit_free_args(min, max int) { pub fn (mut fs FlagParser) limit_free_args(min int, max int) {
if min > max { if min > max {
panic('flag.limit_free_args expect min < max, got $min >= $max') panic('flag.limit_free_args expect min < max, got $min >= $max')
} }
@ -350,27 +349,25 @@ pub fn (mut fs FlagParser) arguments_description(description string){
// collect all given information and // collect all given information and
pub fn (fs FlagParser) usage() string { pub fn (fs FlagParser) usage() string {
positive_min_arg := (fs.min_free_args > 0) positive_min_arg := (fs.min_free_args > 0)
positive_max_arg := (fs.max_free_args > 0 && fs.max_free_args != max_args_number) positive_max_arg := (fs.max_free_args > 0 && fs.max_free_args != max_args_number)
no_arguments := (fs.min_free_args == 0 && fs.max_free_args == 0) no_arguments := (fs.min_free_args == 0 && fs.max_free_args == 0)
mut adesc := if fs.args_description.len > 0 { fs.args_description } else { '[ARGS]' } mut adesc := if fs.args_description.len > 0 { fs.args_description } else { '[ARGS]' }
if no_arguments { adesc = '' } if no_arguments {
adesc = ''
}
mut use := '' mut use := ''
if fs.application_version != '' { if fs.application_version != '' {
use += '$fs.application_name $fs.application_version\n' use += '$fs.application_name $fs.application_version\n'
use += '$underline\n' use += '$underline\n'
} }
use += 'Usage: ${fs.application_name} [options] $adesc\n' use += 'Usage: $fs.application_name [options] $adesc\n'
use += '\n' use += '\n'
if fs.application_description != '' { if fs.application_description != '' {
use += 'Description:\n' use += 'Description:\n'
use += '$fs.application_description' use += '$fs.application_description'
use += '\n\n' use += '\n\n'
} }
// show a message about the [ARGS]: // show a message about the [ARGS]:
if positive_min_arg || positive_max_arg || no_arguments { if positive_min_arg || positive_max_arg || no_arguments {
if no_arguments { if no_arguments {
@ -378,8 +375,12 @@ pub fn (fs FlagParser) usage() string {
goto end_of_arguments_handling goto end_of_arguments_handling
} }
mut s := []string{} mut s := []string{}
if positive_min_arg { s << 'at least $fs.min_free_args' } if positive_min_arg {
if positive_max_arg { s << 'at most $fs.max_free_args' } s << 'at least $fs.min_free_args'
}
if positive_max_arg {
s << 'at most $fs.max_free_args'
}
if positive_min_arg && positive_max_arg && fs.min_free_args == fs.max_free_args { if positive_min_arg && positive_max_arg && fs.min_free_args == fs.max_free_args {
s = ['exactly $fs.min_free_args'] s = ['exactly $fs.min_free_args']
} }
@ -387,32 +388,30 @@ pub fn (fs FlagParser) usage() string {
use += 'The arguments should be $sargs in number.\n\n' use += 'The arguments should be $sargs in number.\n\n'
} }
end_of_arguments_handling: end_of_arguments_handling:
if fs.flags.len > 0 { if fs.flags.len > 0 {
use += 'Options:\n' use += 'Options:\n'
for f in fs.flags { for f in fs.flags {
mut onames := []string{} mut onames := []string{}
if f.abbr != 0 { if f.abbr != 0 {
onames << '-${f.abbr.str()}' onames << '-$f.abbr.str()'
} }
if f.name != '' { if f.name != '' {
if !f.val_desc.contains('<bool>') { if !f.val_desc.contains('<bool>') {
onames << '--${f.name} $f.val_desc' onames << '--$f.name $f.val_desc'
} else { } else {
onames << '--${f.name}' onames << '--$f.name'
} }
} }
option_names := ' ' + onames.join(', ') option_names := ' ' + onames.join(', ')
mut xspace := '' mut xspace := ''
if option_names.len > space.len - 2 { if option_names.len > space.len - 2 {
xspace = '\n${space}' xspace = '\n$space'
} else { } else {
xspace = space[option_names.len..] xspace = space[option_names.len..]
} }
use += '${option_names}${xspace}${f.usage}\n' use += '$option_names$xspace$f.usage\n'
} }
} }
return use return use
} }
@ -426,14 +425,14 @@ pub fn (fs FlagParser) usage() string {
pub fn (fs FlagParser) finalize() ?[]string { pub fn (fs FlagParser) finalize() ?[]string {
for a in fs.args { for a in fs.args {
if a.len >= 2 && a[..2] == '--' { if a.len >= 2 && a[..2] == '--' {
return error('Unknown argument \'${a[2..]}\'') return error("Unknown argument \'${a[2..]}\'")
} }
} }
if fs.args.len < fs.min_free_args && fs.min_free_args > 0 { if fs.args.len < fs.min_free_args && fs.min_free_args > 0 {
return error('Expected at least ${fs.min_free_args} arguments, but given $fs.args.len') return error('Expected at least $fs.min_free_args arguments, but given $fs.args.len')
} }
if fs.args.len > fs.max_free_args && fs.max_free_args > 0 { if fs.args.len > fs.max_free_args && fs.max_free_args > 0 {
return error('Expected at most ${fs.max_free_args} arguments, but given $fs.args.len') return error('Expected at most $fs.max_free_args arguments, but given $fs.args.len')
} }
if fs.args.len > 0 && fs.max_free_args == 0 && fs.min_free_args == 0 { if fs.args.len > 0 && fs.max_free_args == 0 && fs.min_free_args == 0 {
return error('Expected no arguments, but given $fs.args.len') return error('Expected no arguments, but given $fs.args.len')

View File

@ -355,7 +355,7 @@ fn test_single_dash() {
fn test_optional_flags() { fn test_optional_flags() {
mut fp := flag.new_flag_parser(['-a', '10', '-b']) mut fp := flag.new_flag_parser(['-a', '10', '-b'])
a := fp.int_opt('some-flag', `a`, '') or { fp.int_opt('some-flag', `a`, '') or {
assert false assert false
return return
} }

View File

@ -10,7 +10,7 @@ const (
is_used = openssl.is_used is_used = openssl.is_used
) )
fn (req &Request) ssl_do(port int, method Method, host_name, path string) ?Response { fn (req &Request) ssl_do(port int, method Method, host_name string, path string) ?Response {
// ssl_method := C.SSLv23_method() // ssl_method := C.SSLv23_method()
ssl_method := C.TLSv1_2_method() ssl_method := C.TLSv1_2_method()
ctx := C.SSL_CTX_new(ssl_method) ctx := C.SSL_CTX_new(ssl_method)

View File

@ -5,7 +5,7 @@ module http
import os import os
pub fn download_file(url, out string) bool { pub fn download_file(url string, out string) bool {
$if debug_http? { $if debug_http? {
println('download file url=$url out=$out') println('download file url=$url out=$out')
} }

View File

@ -13,7 +13,7 @@ mut:
cb DownloadFn cb DownloadFn
} }
*/ */
fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) { fn download_cb(ptr voidptr, size size_t, nmemb size_t, userp voidptr) {
/* /*
mut data := &DownloadStruct(userp) mut data := &DownloadStruct(userp)
written := C.fwrite(ptr, size, nmemb, data.stream) written := C.fwrite(ptr, size, nmemb, data.stream)
@ -24,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()) { pub fn download_file_with_progress(url string, out string, cb DownloadFn, cb_finished fn()) {
/* /*
curl := C.curl_easy_init() curl := C.curl_easy_init()
if isnil(curl) { if isnil(curl) {

View File

@ -47,14 +47,13 @@ pub:
status_code int status_code int
} }
pub fn new_request(method Method, url_, data string) ?Request { pub fn new_request(method Method, url_ string, data string) ?Request {
url := if method == .get { url_ + '?' + data } else { url_ } url := if method == .get { url_ + '?' + data } else { url_ }
// println('new req() method=$method url="$url" dta="$data"') // println('new req() method=$method url="$url" dta="$data"')
return Request{ return Request{
method: method method: method
url: url url: url
data: data data: data /*
/*
headers: { headers: {
'Accept-Encoding': 'compress' 'Accept-Encoding': 'compress'
} }
@ -75,7 +74,7 @@ pub fn get(url string) ?Response {
return fetch_with_method(.get, url, FetchConfig{}) return fetch_with_method(.get, url, FetchConfig{})
} }
pub fn post(url, data string) ?Response { pub fn post(url string, data string) ?Response {
return fetch_with_method(.post, url, { return fetch_with_method(.post, url, {
data: data data: data
headers: { headers: {
@ -84,7 +83,7 @@ pub fn post(url, data string) ?Response {
}) })
} }
pub fn post_json(url, data string) ?Response { pub fn post_json(url string, data string) ?Response {
return fetch_with_method(.post, url, { return fetch_with_method(.post, url, {
data: data data: data
headers: { headers: {
@ -102,7 +101,7 @@ pub fn post_form(url string, data map[string]string) ?Response {
}) })
} }
pub fn put(url, data string) ?Response { pub fn put(url string, data string) ?Response {
return fetch_with_method(.put, url, { return fetch_with_method(.put, url, {
data: data data: data
headers: { headers: {
@ -111,7 +110,7 @@ pub fn put(url, data string) ?Response {
}) })
} }
pub fn patch(url, data string) ?Response { pub fn patch(url string, data string) ?Response {
return fetch_with_method(.patch, url, { return fetch_with_method(.patch, url, {
data: data data: data
headers: { headers: {
@ -133,7 +132,7 @@ pub fn fetch(_url string, config FetchConfig) ?Response {
return error('http.fetch: empty url') return error('http.fetch: empty url')
} }
url := build_url_from_fetch(_url, config) or { url := build_url_from_fetch(_url, config) or {
return error('http.fetch: invalid url ${_url}') return error('http.fetch: invalid url $_url')
} }
data := config.data data := config.data
req := Request{ req := Request{
@ -184,7 +183,7 @@ fn build_url_from_fetch(_url string, config FetchConfig) ?string {
} }
mut pieces := []string{} mut pieces := []string{}
for key in params.keys() { for key in params.keys() {
pieces << '${key}=${params[key]}' pieces << '$key=${params[key]}'
} }
mut query := pieces.join('&') mut query := pieces.join('&')
if url.raw_query.len > 1 { if url.raw_query.len > 1 {
@ -195,19 +194,15 @@ fn build_url_from_fetch(_url string, config FetchConfig) ?string {
} }
fn (mut req Request) free() { fn (mut req Request) free() {
unsafe { unsafe {req.headers.free()}
req.headers.free()
}
} }
fn (mut resp Response) free() { fn (mut resp Response) free() {
unsafe { unsafe {resp.headers.free()}
resp.headers.free()
}
} }
// add_header adds the key and value of an HTTP request header // add_header adds the key and value of an HTTP request header
pub fn (mut req Request) add_header(key, val string) { pub fn (mut req Request) add_header(key string, val string) {
req.headers[key] = val req.headers[key] = val
} }
@ -229,7 +224,7 @@ pub fn parse_headers(lines []string) map[string]string {
// do will send the HTTP request and returns `http.Response` as soon as the response is recevied // do will send the HTTP request and returns `http.Response` as soon as the response is recevied
pub fn (req &Request) do() ?Response { pub fn (req &Request) do() ?Response {
mut url := urllib.parse(req.url) or { mut url := urllib.parse(req.url) or {
return error('http.Request.do: invalid url ${req.url}') return error('http.Request.do: invalid url $req.url')
} }
mut rurl := url mut rurl := url
mut resp := Response{} mut resp := Response{}
@ -264,7 +259,7 @@ fn (req &Request) method_and_url_to_response(method Method, url urllib.URL) ?Res
host_name := url.hostname() host_name := url.hostname()
scheme := url.scheme scheme := url.scheme
p := url.path.trim_left('/') p := url.path.trim_left('/')
path := if url.query().len > 0 { '/$p?${url.query().encode()}' } else { '/$p' } path := if url.query().len > 0 { '/$p?$url.query().encode()' } else { '/$p' }
mut nport := url.port().int() mut nport := url.port().int()
if nport == 0 { if nport == 0 {
if scheme == 'http' { if scheme == 'http' {
@ -322,7 +317,6 @@ fn parse_response(resp string) Response {
// if h.contains('Content-Type') { // if h.contains('Content-Type') {
// continue // continue
// } // }
mut key := h[..pos] mut key := h[..pos]
lkey := key.to_lower() lkey := key.to_lower()
val := h[pos + 2..] val := h[pos + 2..]
@ -346,7 +340,7 @@ fn parse_response(resp string) Response {
} }
} }
fn (req &Request) build_request_headers(method Method, host_name, path string) string { fn (req &Request) build_request_headers(method Method, host_name string, path string) string {
ua := req.user_agent ua := req.user_agent
mut uheaders := []string{} mut uheaders := []string{}
if 'Host' !in req.headers { if 'Host' !in req.headers {
@ -356,17 +350,16 @@ fn (req &Request) build_request_headers(method Method, host_name, path string) s
uheaders << 'User-Agent: $ua\r\n' uheaders << 'User-Agent: $ua\r\n'
} }
if req.data.len > 0 && 'Content-Length' !in req.headers { if req.data.len > 0 && 'Content-Length' !in req.headers {
uheaders << 'Content-Length: ${req.data.len}\r\n' uheaders << 'Content-Length: $req.data.len\r\n'
} }
for key, val in req.headers { for key, val in req.headers {
if key == 'Cookie' { if key == 'Cookie' {
continue continue
} }
uheaders << '${key}: ${val}\r\n' uheaders << '$key: $val\r\n'
} }
uheaders << req.build_request_cookies_header() uheaders << req.build_request_cookies_header()
return '$method $path HTTP/1.1\r\n' + uheaders.join('') + 'Connection: close\r\n\r\n' + return '$method $path HTTP/1.1\r\n' + uheaders.join('') + 'Connection: close\r\n\r\n' + req.data
req.data
} }
fn (req &Request) build_request_cookies_header() string { fn (req &Request) build_request_cookies_header() string {
@ -399,13 +392,12 @@ pub fn escape(s string) string {
panic('http.escape() was replaced with http.escape_url()') panic('http.escape() was replaced with http.escape_url()')
} }
fn (req &Request) http_do(port int, method Method, host_name, path string) ?Response { fn (req &Request) http_do(port int, method Method, host_name string, path string) ?Response {
rbuffer := [bufsize]byte{} rbuffer := [bufsize]byte{}
mut sb := strings.new_builder(100) mut sb := strings.new_builder(100)
s := req.build_request_headers(method, host_name, path) s := req.build_request_headers(method, host_name, path)
client := net.dial(host_name, port) ? client := net.dial(host_name, port) ?
client.send(s.str, s.len) or { client.send(s.str, s.len) or { }
}
for { for {
readbytes := client.crecv(rbuffer, bufsize) readbytes := client.crecv(rbuffer, bufsize)
if readbytes < 0 { if readbytes < 0 {
@ -416,8 +408,7 @@ fn (req &Request) http_do(port int, method Method, host_name, path string) ?Resp
} }
sb.write(tos(rbuffer, readbytes)) sb.write(tos(rbuffer, readbytes))
} }
client.close() or { client.close() or { }
}
return parse_response(sb.str()) return parse_response(sb.str())
} }

View File

@ -1,26 +1,34 @@
import net.http import net.http
fn test_http_get() { fn test_http_get() {
$if !network ? { return } $if !network ? {
return
}
assert http.get_text('https://vlang.io/version') == '0.1.5' assert http.get_text('https://vlang.io/version') == '0.1.5'
println('http ok') println('http ok')
} }
fn test_http_get_from_vlang_utc_now() { fn test_http_get_from_vlang_utc_now() {
$if !network ? { return } $if !network ? {
return
}
urls := ['http://vlang.io/utc_now', 'https://vlang.io/utc_now'] urls := ['http://vlang.io/utc_now', 'https://vlang.io/utc_now']
for url in urls { for url in urls {
println('Test getting current time from $url by http.get') println('Test getting current time from $url by http.get')
res := http.get(url) or { panic(err) } res := http.get(url) or {
panic(err)
}
assert 200 == res.status_code assert 200 == res.status_code
assert res.text.len > 0 assert res.text.len > 0
assert res.text.int() > 1566403696 assert res.text.int() > 1566403696
println('Current time is: ${res.text.int()}') println('Current time is: $res.text.int()')
} }
} }
fn test_public_servers() { fn test_public_servers() {
$if !network ? { return } $if !network ? {
return
}
urls := [ urls := [
'http://github.com/robots.txt', 'http://github.com/robots.txt',
'http://google.com/robots.txt', 'http://google.com/robots.txt',
@ -31,18 +39,24 @@ fn test_public_servers() {
] ]
for url in urls { for url in urls {
println('Testing http.get on public url: $url ') println('Testing http.get on public url: $url ')
res := http.get( url ) or { panic(err) } res := http.get(url) or {
panic(err)
}
assert 200 == res.status_code assert 200 == res.status_code
assert res.text.len > 0 assert res.text.len > 0
} }
} }
fn test_relative_redirects() { fn test_relative_redirects() {
$if !network ? { return } $if !network ? {
$else { return } // tempfix periodic: httpbin relative redirects are broken return
res := http.get('https://httpbin.org/relative-redirect/3?abc=xyz') or { panic(err) } } $else {
return
} // tempfix periodic: httpbin relative redirects are broken
res := http.get('https://httpbin.org/relative-redirect/3?abc=xyz') or {
panic(err)
}
assert 200 == res.status_code assert 200 == res.status_code
assert res.text.len > 0 assert res.text.len > 0
assert res.text.contains('"abc": "xyz"') assert res.text.contains('"abc": "xyz"')
} }

View File

@ -75,12 +75,12 @@ fn C.inet_ntop(af int, src voidptr, dst charptr, dst_size int) charptr
fn C.getpeername(sockfd int, addr &C.sockaddr_in, addrsize &int) int fn C.getpeername(sockfd int, addr &C.sockaddr_in, addrsize &int) int
// create socket // create socket
pub fn new_socket(family, typ, proto int) ?Socket { pub fn new_socket(family int, typ int, proto int) ?Socket {
sockfd := C.socket(family, typ, proto) sockfd := C.socket(family, typ, proto)
one := 1 one := 1
// This is needed so that there are no problems with reusing the // This is needed so that there are no problems with reusing the
// same port after the application exits. // same port after the application exits.
C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, sizeof(int)) C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, sizeof(voidptr))
if sockfd == -1 { if sockfd == -1 {
return error('net.socket: failed') return error('net.socket: failed')
} }
@ -98,8 +98,8 @@ pub fn socket_udp() ?Socket {
} }
// set socket options // set socket options
pub fn (s Socket) setsockopt(level, optname int, optvalue &int) ?int { pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int {
res := C.setsockopt(s.sockfd, level, optname, optvalue, sizeof(&int)) res := C.setsockopt(s.sockfd, level, optname, optvalue, sizeof(int))
if res < 0 { if res < 0 {
return error('net.setsocketopt: failed with $res') return error('net.setsocketopt: failed with $res')
} }

View File

@ -25,7 +25,7 @@ const (
err_msg_parse = 'parse: failed parsing url' err_msg_parse = 'parse: failed parsing url'
) )
fn error_msg(message, val string) string { fn error_msg(message string, val string) string {
mut msg := 'net.urllib.$message' mut msg := 'net.urllib.$message'
if val != '' { if val != '' {
msg = '$msg ($val)' msg = '$msg ($val)'
@ -53,7 +53,8 @@ fn should_escape(c byte, mode EncodingMode) bool {
// we could possibly allow, and parse will reject them if we // we could possibly allow, and parse will reject them if we
// escape them (because hosts can`t use %-encoding for // escape them (because hosts can`t use %-encoding for
// ASCII bytes). // ASCII bytes).
if c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] { if c in
[`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
return false return false
} }
} }
@ -100,11 +101,11 @@ fn should_escape(c byte, mode EncodingMode) bool {
// everything, so escape nothing. // everything, so escape nothing.
return false return false
} }
else { else {}
}} }
}
else {}
} }
else {
}}
if mode == .encode_fragment { if mode == .encode_fragment {
// RFC 3986 §2.2 allows not escaping sub-delims. A subset of sub-delims are // 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 // included in reserved from RFC 2396 §2.2. The remaining sub-delims do not
@ -113,11 +114,9 @@ fn should_escape(c byte, mode EncodingMode) bool {
// escape single quote to avoid breaking callers that had previously assumed that // escape single quote to avoid breaking callers that had previously assumed that
// single quotes would be escaped. See issue #19917. // single quotes would be escaped. See issue #19917.
match c { match c {
`!`, `(`, `)`, `*` { `!`, `(`, `)`, `*` { return false }
return false else {}
} }
else {
}}
} }
// Everything else must be escaped. // Everything else must be escaped.
return true return true
@ -194,11 +193,14 @@ fn unescape(s_ string, mode EncodingMode) ?string {
i++ i++
} }
else { else {
if (mode == .encode_host || mode == .encode_zone) && s[i] < 0x80 && should_escape(s[i], mode) { if (mode == .encode_host ||
mode == .encode_zone) &&
s[i] < 0x80 && should_escape(s[i], mode) {
error(error_msg('unescape: invalid character in host name', s[i..i + 1])) error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
} }
i++ i++
}} }
}
} }
if n == 0 && !has_plus { if n == 0 && !has_plus {
return s return s
@ -214,14 +216,14 @@ fn unescape(s_ string, mode EncodingMode) ?string {
`+` { `+` {
if mode == .encode_query_component { if mode == .encode_query_component {
t.write(' ') t.write(' ')
} } else {
else {
t.write('+') t.write('+')
} }
} }
else { else {
t.write(s[i].str()) t.write(s[i].str())
}} }
}
} }
return t.str() return t.str()
} }
@ -247,8 +249,7 @@ fn escape(s string, mode EncodingMode) string {
if should_escape(c, mode) { if should_escape(c, mode) {
if c == ` ` && mode == .encode_query_component { if c == ` ` && mode == .encode_query_component {
space_count++ space_count++
} } else {
else {
hex_count++ hex_count++
} }
} }
@ -261,8 +262,7 @@ fn escape(s string, mode EncodingMode) string {
required := s.len + 2 * hex_count required := s.len + 2 * hex_count
if required <= buf.len { if required <= buf.len {
t = buf[..required] t = buf[..required]
} } else {
else {
t = []byte{len: (required)} t = []byte{len: (required)}
} }
if hex_count == 0 { if hex_count == 0 {
@ -281,14 +281,12 @@ fn escape(s string, mode EncodingMode) string {
if c1 == ` ` && mode == .encode_query_component { if c1 == ` ` && mode == .encode_query_component {
t[j] = `+` t[j] = `+`
j++ j++
} } else if should_escape(c1, mode) {
else if should_escape(c1, mode) {
t[j] = `%` t[j] = `%`
t[j + 1] = upperhex[c1 >> 4] t[j + 1] = upperhex[c1 >> 4]
t[j + 2] = upperhex[c1 & 15] t[j + 2] = upperhex[c1 & 15]
j += 3 j += 3
} } else {
else {
t[j] = s[i] t[j] = s[i]
j++ j++
} }
@ -345,9 +343,8 @@ pub fn user(username string) &Userinfo {
// ``is NOT RECOMMENDED, because the passing of authentication // ``is NOT RECOMMENDED, because the passing of authentication
// information in clear text (such as URI) has proven to be a // information in clear text (such as URI) has proven to be a
// security risk in almost every case where it has been used.'' // security risk in almost every case where it has been used.''
fn user_password(username, password string) &Userinfo { fn user_password(username string, password string) &Userinfo {
return &Userinfo{ return &Userinfo{username, password, true}
username,password,true}
} }
// The Userinfo type is an immutable encapsulation of username and // The Userinfo type is an immutable encapsulation of username and
@ -386,19 +383,16 @@ fn split_by_scheme(rawurl string) ?[]string {
c := rawurl[i] c := rawurl[i]
if (`a` <= c && c <= `z`) || (`A` <= c && c <= `Z`) { if (`a` <= c && c <= `z`) || (`A` <= c && c <= `Z`) {
// do nothing // do nothing
} } else if (`0` <= c && c <= `9`) || (c == `+` || c == `-` || c == `.`) {
else if (`0` <= c && c <= `9`) || (c == `+` || c == `-` || c == `.`) {
if i == 0 { if i == 0 {
return ['', rawurl] return ['', rawurl]
} }
} } else if c == `:` {
else if c == `:` {
if i == 0 { if i == 0 {
return error(error_msg('split_by_scheme: missing protocol scheme', '')) return error(error_msg('split_by_scheme: missing protocol scheme', ''))
} }
return [rawurl[..i], rawurl[i + 1..]] return [rawurl[..i], rawurl[i + 1..]]
} } else {
else {
// we have encountered an invalid character, // we have encountered an invalid character,
// so there is no valid scheme // so there is no valid scheme
return ['', rawurl] return ['', rawurl]
@ -487,8 +481,7 @@ fn parse_url(rawurl string, via_request bool) ?URL {
if rest.ends_with('?') && !rest[..1].contains('?') { if rest.ends_with('?') && !rest[..1].contains('?') {
url.force_query = true url.force_query = true
rest = rest[..rest.len - 1] rest = rest[..rest.len - 1]
} } else {
else {
r, raw_query := split(rest, `?`, true) r, raw_query := split(rest, `?`, true)
rest = r rest = r
url.raw_query = raw_query url.raw_query = raw_query
@ -516,7 +509,8 @@ fn parse_url(rawurl string, via_request bool) ?URL {
} }
if colon >= 0 && (slash < 0 || colon < slash) { if colon >= 0 && (slash < 0 || colon < slash) {
// First path segment has colon. Not allowed in relative URL. // First path segment has colon. Not allowed in relative URL.
return error(error_msg('parse_url: first path segment in URL cannot contain colon', '')) 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('//') { if ((url.scheme != '' || !via_request) && !rest.starts_with('///')) && rest.starts_with('//') {
@ -548,8 +542,7 @@ fn parse_authority(authority string) ?ParseAuthorityRes {
if i < 0 { if i < 0 {
h := parse_host(authority) ? h := parse_host(authority) ?
host = h host = h
} } else {
else {
h := parse_host(authority[i + 1..]) ? h := parse_host(authority[i + 1..]) ?
host = h host = h
} }
@ -567,8 +560,7 @@ fn parse_authority(authority string) ?ParseAuthorityRes {
u := unescape(userinfo, .encode_user_password) ? u := unescape(userinfo, .encode_user_password) ?
userinfo = u userinfo = u
zuser = user(userinfo) zuser = user(userinfo)
} } else {
else {
mut username, mut password := split(userinfo, `:`, true) mut username, mut password := split(userinfo, `:`, true)
u := unescape(username, .encode_user_password) ? u := unescape(username, .encode_user_password) ?
username = u username = u
@ -593,7 +585,8 @@ fn parse_host(host string) ?string {
} }
mut colon_port := host[i + 1..] mut colon_port := host[i + 1..]
if !valid_optional_port(colon_port) { if !valid_optional_port(colon_port) {
return error(error_msg('parse_host: invalid port $colon_port after host ', '')) return error(error_msg('parse_host: invalid port $colon_port after host ',
''))
} }
// RFC 6874 defines that %25 (%-encoded percent) introduces // RFC 6874 defines that %25 (%-encoded percent) introduces
// the zone identifier, and the zone identifier can use basically // the zone identifier, and the zone identifier can use basically
@ -616,7 +609,8 @@ fn parse_host(host string) ?string {
if idx := host.last_index(':') { if idx := host.last_index(':') {
colon_port = host[idx..] colon_port = host[idx..]
if !valid_optional_port(colon_port) { if !valid_optional_port(colon_port) {
return error(error_msg('parse_host: invalid port $colon_port after host ', '')) return error(error_msg('parse_host: invalid port $colon_port after host ',
''))
} }
} }
} }
@ -627,6 +621,7 @@ fn parse_host(host string) ?string {
// host = h // host = h
// return host // return host
} }
// set_path sets the path and raw_path fields of the URL based on the provided // 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 // escaped path p. It maintains the invariant that raw_path is only specified
// when it differs from the default encoding of the path. // when it differs from the default encoding of the path.
@ -642,8 +637,7 @@ pub fn (mut u URL) set_path(p string) ?bool {
if p == escp { if p == escp {
// Default encoding is fine. // Default encoding is fine.
u.raw_path = '' u.raw_path = ''
} } else {
else {
u.raw_path = p u.raw_path = p
} }
return true return true
@ -695,7 +689,8 @@ fn valid_encoded_path(s string) bool {
if should_escape(s[i], .encode_path) { if should_escape(s[i], .encode_path) {
return false return false
} }
}} }
}
} }
return true return true
} }
@ -746,8 +741,7 @@ pub fn (u URL) str() string {
} }
if u.opaque != '' { if u.opaque != '' {
buf.write(u.opaque) buf.write(u.opaque)
} } else {
else {
if u.scheme != '' || u.host != '' || (u.user != 0 && !u.user.empty()) { if u.scheme != '' || u.host != '' || (u.user != 0 && !u.user.empty()) {
if u.host != '' || u.path != '' || !u.user.empty() { if u.host != '' || u.path != '' || !u.user.empty() {
buf.write('//') buf.write('//')
@ -825,8 +819,7 @@ fn parse_query_values(mut m Values, query string) ?bool {
if i >= 0 { if i >= 0 {
q = key[i + 1..] q = key[i + 1..]
key = key[..i] key = key[..i]
} } else {
else {
q = '' q = ''
} }
if key == '' { if key == '' {
@ -885,18 +878,16 @@ pub fn (v Values) encode() string {
// resolve_path applies special path segments from refs and applies // resolve_path applies special path segments from refs and applies
// them to base, per RFC 3986. // them to base, per RFC 3986.
fn resolve_path(base, ref string) string { fn resolve_path(base string, ref string) string {
mut full := '' mut full := ''
if ref == '' { if ref == '' {
full = base full = base
} } else if ref[0] != `/` {
else if ref[0] != `/` {
i := base.last_index('/') or { i := base.last_index('/') or {
-1 -1
} }
full = base[..i + 1] + ref full = base[..i + 1] + ref
} } else {
else {
full = ref full = ref
} }
if full == '' { if full == '' {
@ -916,7 +907,8 @@ fn resolve_path(base, ref string) string {
} }
else { else {
dst << elem dst << elem
}} }
}
} }
last := src[src.len - 1] last := src[src.len - 1]
if last == '.' || last == '..' { if last == '.' || last == '..' {
@ -994,8 +986,7 @@ pub fn (u &URL) request_uri() string {
if result == '' { if result == '' {
result = '/' result = '/'
} }
} } else {
else {
if result.starts_with('//') { if result.starts_with('//') {
result = u.scheme + ':' + result result = u.scheme + ':' + result
} }
@ -1059,12 +1050,9 @@ pub fn valid_userinfo(s string) bool {
continue continue
} }
match r { match r {
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` { `-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` { continue }
continue else { return false }
} }
else {
return false
}}
} }
return true return true
} }
@ -1083,11 +1071,9 @@ fn string_contains_ctl_byte(s string) bool {
pub fn ishex(c byte) bool { pub fn ishex(c byte) bool {
if `0` <= c && c <= `9` { if `0` <= c && c <= `9` {
return true return true
} } else if `a` <= c && c <= `f` {
else if `a` <= c && c <= `f` {
return true return true
} } else if `A` <= c && c <= `F` {
else if `A` <= c && c <= `F` {
return true return true
} }
return false return false
@ -1096,11 +1082,9 @@ pub fn ishex(c byte) bool {
fn unhex(c byte) byte { fn unhex(c byte) byte {
if `0` <= c && c <= `9` { if `0` <= c && c <= `9` {
return c - `0` return c - `0`
} } else if `a` <= c && c <= `f` {
else if `a` <= c && c <= `f` {
return c - `a` + 10 return c - `a` + 10
} } else if `A` <= c && c <= `F` {
else if `A` <= c && c <= `F` {
return c - `A` + 10 return c - `A` + 10
} }
return 0 return 0

View File

@ -20,7 +20,7 @@ pub mut:
// values.encode() will return the encoded data // values.encode() will return the encoded data
pub fn new_values() Values { pub fn new_values() Values {
return Values{ return Values{
data: map[string]Value data: map[string]Value{}
} }
} }
@ -61,7 +61,7 @@ pub fn (v &Values) get_all(key string) []string {
// set sets the key to value. It replaces any existing // set sets the key to value. It replaces any existing
// values. // values.
pub fn (mut v Values) set(key, value string) { pub fn (mut v Values) set(key string, value string) {
mut a := v.data[key] mut a := v.data[key]
a.data = [value] a.data = [value]
v.data[key] = a v.data[key] = a
@ -70,7 +70,7 @@ pub fn (mut v Values) set(key, value string) {
// add adds the value to key. It appends to any existing // add adds the value to key. It appends to any existing
// values associated with key. // values associated with key.
pub fn (mut v Values) add(key, value string) { pub fn (mut v Values) add(key string, value string) {
mut a := v.data[key] mut a := v.data[key]
if a.data.len == 0 { if a.data.len == 0 {
a.data = [] a.data = []

View File

@ -191,13 +191,13 @@ pub fn (mut nodes []DocNode) sort_by_category() {
nodes.sort_with_compare(compare_nodes_by_category) nodes.sort_with_compare(compare_nodes_by_category)
} }
fn compare_nodes_by_name(a, b &DocNode) int { fn compare_nodes_by_name(a &DocNode, b &DocNode) int {
al := a.name.to_lower() al := a.name.to_lower()
bl := b.name.to_lower() bl := b.name.to_lower()
return compare_strings(al, bl) return compare_strings(al, bl)
} }
fn compare_nodes_by_category(a, b &DocNode) int { fn compare_nodes_by_category(a &DocNode, b &DocNode) int {
al := a.attrs['category'] al := a.attrs['category']
bl := b.attrs['category'] bl := b.attrs['category']
return compare_strings(al, bl) return compare_strings(al, bl)
@ -217,7 +217,7 @@ pub fn (nodes []DocNode) find_children_of(parent string) []DocNode {
return nodes.find_nodes_with_attr('parent', parent) return nodes.find_nodes_with_attr('parent', parent)
} }
pub fn (nodes []DocNode) find_nodes_with_attr(attr_name, value string) []DocNode { pub fn (nodes []DocNode) find_nodes_with_attr(attr_name string, value string) []DocNode {
mut subgroup := []DocNode{} mut subgroup := []DocNode{}
if attr_name.len == 0 { if attr_name.len == 0 {
return subgroup return subgroup
@ -509,7 +509,7 @@ fn (mut d Doc) generate() ?Doc {
return *d return *d
} }
pub fn generate_from_pos(input_path, filename string, pos int) ?Doc { pub fn generate_from_pos(input_path string, filename string, pos int) ?Doc {
mut doc := new(input_path) mut doc := new(input_path)
doc.pub_only = false doc.pub_only = false
doc.with_comments = true doc.with_comments = true
@ -519,7 +519,7 @@ pub fn generate_from_pos(input_path, filename string, pos int) ?Doc {
return doc.generate() return doc.generate()
} }
pub fn generate(input_path string, pub_only, with_comments bool) ?Doc { pub fn generate(input_path string, pub_only bool, with_comments bool) ?Doc {
mut doc := new(input_path) mut doc := new(input_path)
doc.pub_only = pub_only doc.pub_only = pub_only
doc.with_comments = with_comments doc.with_comments = with_comments