From acf010749387f6a42216f481eb71a0d25983fa5c Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 28 Mar 2024 18:26:30 +0300 Subject: [PATCH] builtin: str.last_index(); pref: hide-auto-str; --- examples/quadtree_demo/quadtree_demo.v | 1 - vlib/builtin/builtin.c.v | 3 ++ vlib/builtin/js/string.js.v | 15 ++++--- vlib/builtin/string.v | 18 ++++----- vlib/gg/draw.c.v | 1 + vlib/gg/image.c.v | 54 +++++++++++++------------- vlib/gg/text_rendering.c.v | 1 + vlib/net/http/download.v | 14 +++++++ vlib/orm/README.md | 7 +++- vlib/os/os.v | 6 +-- vlib/v/checker/checker.v | 2 +- vlib/v/gen/c/auto_str_methods.v | 5 +++ vlib/v/pref/pref.c.v | 4 ++ 13 files changed, 82 insertions(+), 49 deletions(-) diff --git a/examples/quadtree_demo/quadtree_demo.v b/examples/quadtree_demo/quadtree_demo.v index 9a1e40ab11..c8bcd1755f 100644 --- a/examples/quadtree_demo/quadtree_demo.v +++ b/examples/quadtree_demo/quadtree_demo.v @@ -118,7 +118,6 @@ fn main() { bg_color: gx.white width: win_width height: win_height - use_ortho: true create_window: true window_title: 'Quadtree Demo' frame_fn: frame diff --git a/vlib/builtin/builtin.c.v b/vlib/builtin/builtin.c.v index a55da377b6..81afa2ec84 100644 --- a/vlib/builtin/builtin.c.v +++ b/vlib/builtin/builtin.c.v @@ -269,6 +269,9 @@ pub fn println(s string) { println('println(NIL)') return } + $if noprintln ? { + return + } $if android && !termux { C.android_print(C.stdout, c'%.*s\n', s.len, s.str) return diff --git a/vlib/builtin/js/string.js.v b/vlib/builtin/js/string.js.v index 6bf61cf563..c632ee5e58 100644 --- a/vlib/builtin/js/string.js.v +++ b/vlib/builtin/js/string.js.v @@ -750,7 +750,14 @@ fn (s string) index_last_(p string) int { } // index_last returns the position of the first character of the *last* occurrence of the `needle` string in `s`. +@[deprecated: 'use `.last_index(needle string)` instead'] pub fn (s string) index_last(needle string) ?int { + return s.last_index(needle) +} + +// last_index returns the position of the first character of the *last* occurrence of the `needle` string in `s`. +@[inline] +pub fn (s string) last_index(needle string) ?int { idx := s.index_last_(needle) if idx == -1 { return none @@ -758,14 +765,6 @@ pub fn (s string) index_last(needle string) ?int { return idx } -// last_index returns the position of the first character of the *last* occurrence of the `needle` string in `s`. -@[deprecated: 'use `.index_last(needle string)` instead'] -@[deprecated_after: '2023-12-18'] -@[inline] -pub fn (s string) last_index(needle string) ?int { - return s.index_last(needle) -} - pub fn (s string) trim_space() string { res := '' #res.str = s.str.trim() diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 361381514b..0989dc0932 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -1090,7 +1090,7 @@ pub fn (s string) substr(start int, _end int) string { end := if _end == max_int { s.len } else { _end } // max_int $if !no_bounds_checking { if start > end || start > s.len || end > s.len || start < 0 || end < 0 { - panic('substr(${start}, ${end}) out of bounds (len=${s.len})') + panic('substr(${start}, ${end}) out of bounds (len=${s.len}) s="${s}"') } } len := end - start @@ -1223,7 +1223,15 @@ pub fn (s string) index(p string) ?int { } // index_last returns the position of the first character of the *last* occurrence of the `needle` string in `s`. +@[deprecated: 'use `.last_index(needle string)` instead'] +@[deprecated_after: '2024-03-27'] pub fn (s string) index_last(needle string) ?int { + return s.last_index(needle) +} + +// last_index returns the position of the first character of the *last* occurrence of the `needle` string in `s`. +@[inline] +pub fn (s string) last_index(needle string) ?int { idx := s.index_last_(needle) if idx == -1 { return none @@ -1231,14 +1239,6 @@ pub fn (s string) index_last(needle string) ?int { return idx } -// last_index returns the position of the first character of the *last* occurrence of the `needle` string in `s`. -@[deprecated: 'use `.index_last(needle string)` instead'] -@[deprecated_after: '2023-12-18'] -@[inline] -pub fn (s string) last_index(needle string) ?int { - return s.index_last(needle) -} - // index_kmp does KMP search. @[direct_array_access; manualfree] fn (s string) index_kmp(p string) int { diff --git a/vlib/gg/draw.c.v b/vlib/gg/draw.c.v index 2f06f04ffc..b9cf0eb87a 100644 --- a/vlib/gg/draw.c.v +++ b/vlib/gg/draw.c.v @@ -54,6 +54,7 @@ pub fn (ctx &Context) draw_line(x f32, y f32, x2 f32, y2 f32, c gx.Color) { $if macos { if ctx.native_rendering { // Make the line more clear on hi dpi screens: draw a rectangle + // TODO this is broken if the line's x1 != x2 mut width := math.abs(x2 - x) mut height := math.abs(y2 - y) if width == 0 { diff --git a/vlib/gg/image.c.v b/vlib/gg/image.c.v index 3fda0882ac..e6cf685376 100644 --- a/vlib/gg/image.c.v +++ b/vlib/gg/image.c.v @@ -291,9 +291,9 @@ pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) { if config.img_id > 0 { img = &ctx.image_cache[config.img_id] } else { - //$if !noggverbose ? { - eprintln('gg: failed to get image to draw natively') - //} + $if !noggverbose ? { + eprintln('gg: failed to get image to draw natively') + } return } } @@ -301,31 +301,33 @@ pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) { eprintln('gg: draw_image() bad img id ${img.id} (img cache len = ${ctx.image_cache.len})') return } - if ctx.native_rendering { - if img.width == 0 { - println('w=0') - return - } - if !os.exists(img.path) { - println('not exist path') - return - } - x := config.img_rect.x - y := config.img_rect.y - width := if config.img_rect.width == 0 { - f32(img.width) - } else { - config.img_rect.width - } - height := if config.img_rect.height == 0 { - f32(img.height) - } else { - config.img_rect.height - } - C.darwin_draw_image(x, ctx.height - (y + config.img_rect.height), - width, height, img) + if img.width == 0 { + println('w=0') return } + if !os.exists(img.path) { + println('not exist path') + return + } + x := config.img_rect.x + y := config.img_rect.y + width := if config.img_rect.width == 0 { + // Calculate the width by dividing it by the height ratio. + // e.g. the original image is 100x100, we're drawing 0x20. Find the ratio (5) + // by dividing the height 100 by 20, and then divide the width by 5. + f32(img.width / (img.height / config.img_rect.height)) + } else { + config.img_rect.width + } + height := if config.img_rect.height == 0 { + // Same as above. + f32(img.height / (img.width / config.img_rect.width)) + } else { + config.img_rect.height + } + C.darwin_draw_image(x, ctx.height - (y + config.img_rect.height), width, + height, img) + return } } } diff --git a/vlib/gg/text_rendering.c.v b/vlib/gg/text_rendering.c.v index 05c284405c..57fc802e93 100644 --- a/vlib/gg/text_rendering.c.v +++ b/vlib/gg/text_rendering.c.v @@ -186,6 +186,7 @@ pub fn (ctx &Context) draw_text(x int, y int, text_ string, cfg gx.TextCfg) { if ctx.native_rendering { if cfg.align == gx.align_right { width := ctx.text_width(text_) + // println('draw text ctx.height = ${ctx.height}') C.darwin_draw_string(x - width, ctx.height - y, text_, cfg) } else { C.darwin_draw_string(x, ctx.height - y, text_, cfg) diff --git a/vlib/net/http/download.v b/vlib/net/http/download.v index c58c15dd46..510f30f14c 100644 --- a/vlib/net/http/download.v +++ b/vlib/net/http/download.v @@ -25,3 +25,17 @@ pub fn download_file(url string, out_file_path string) ! { // type DownloadChunkFn = fn (written int) // type DownloadFinishedFn = fn () // pub fn download_file_with_progress(url string, out_file_path string, cb_chunk DownloadChunkFn, cb_finished DownloadFinishedFn) + +pub fn download_file_with_cookies(url string, out_file_path string, cookies map[string]string) ! { + $if debug_http ? { + println('http.download_file url=${url} out_file_path=${out_file_path}') + } + s := fetch(method: .get, url: url, cookies: cookies) or { return err } + if s.status() != .ok { + return error('received http code ${s.status_code}') + } + $if debug_http ? { + println('http.download_file saving ${s.body.len} bytes') + } + os.write_file(out_file_path, s.body)! +} diff --git a/vlib/orm/README.md b/vlib/orm/README.md index bb70672e55..1a141fedce 100644 --- a/vlib/orm/README.md +++ b/vlib/orm/README.md @@ -81,17 +81,22 @@ foo := Foo{ ] } -sql db { +foo_id := sql db { insert foo into Foo }! ``` +If the `id` field is marked as `serial` and `primary`, the insert expression +returns the database ID of the newly added object. Getting an ID of a newly +added DB row is often useful. + When inserting, `[sql: serial]` fields, and fields with a `[default: 'raw_sql']` attribute are not sent to the database when the value being sent is the default for the V struct field (e.g., 0 int, or an empty string). This allows the database to insert default values for auto-increment fields and where you have specified a default. + ### Update ```v ignore diff --git a/vlib/os/os.v b/vlib/os/os.v index 3ac5a12dd4..6ee1f77ebc 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -274,7 +274,7 @@ pub fn dir(opath string) string { } other_separator := if path_separator == '/' { '\\' } else { '/' } path := opath.replace(other_separator, path_separator) - pos := path.index_last(path_separator) or { return '.' } + pos := path.last_index(path_separator) or { return '.' } if pos == 0 && path_separator == '/' { return '/' } @@ -296,10 +296,10 @@ pub fn base(opath string) string { } if path.ends_with(path_separator) { path2 := path[..path.len - 1] - pos := path2.index_last(path_separator) or { return path2.clone() } + pos := path2.last_index(path_separator) or { return path2.clone() } return path2[pos + 1..] } - pos := path.index_last(path_separator) or { return path.clone() } + pos := path.last_index(path_separator) or { return path.clone() } return path[pos + 1..] } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9752ea16ae..e03af5b938 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -484,7 +484,7 @@ fn (mut c Checker) check_valid_snake_case(name string, identifier string, pos to } fn stripped_name(name string) string { - idx := name.index_last('.') or { -1 } + idx := name.last_index('.') or { -1 } return name[(idx + 1)..] } diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 9f8fd13bf9..31d5828e9c 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -928,6 +928,11 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin } } } + // -hide-auto-str hides potential sensitive struct data from resulting binary files + if g.pref.hide_auto_str { + fn_body.writeln('\tstring res = { .str ="str() used with -hide-auto-str", .len=30 }; return res;') + return + } fn_body.writeln('\tstring res = str_intp( ${(info.fields.len - field_skips.len) * 4 + 3}, _MOV((StrIntpData[]){') fn_body.writeln('\t\t{_SLIT("${clean_struct_v_type_name}{\\n"), 0, {.d_c=0}},') diff --git a/vlib/v/pref/pref.c.v b/vlib/v/pref/pref.c.v index 4ef4e06a5b..b720edabf5 100644 --- a/vlib/v/pref/pref.c.v +++ b/vlib/v/pref/pref.c.v @@ -141,6 +141,7 @@ pub mut: profile_fns []string // when set, profiling will be off by default, but inside these functions (and what they call) it will be on. translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc obfuscate bool // `v -obf program.v`, renames functions to "f_XXX" + hide_auto_str bool // `v -hide-auto-str program.v`, doesn't generate str() with struct data // Note: passing -cg instead of -g will set is_vlines to false and is_debug to true, thus making v generate cleaner C files, // which are sometimes easier to debug / inspect manually than the .tmp.c files by plain -g (when/if v line number generation breaks). sanitize bool // use Clang's new "-fsanitize" option @@ -642,6 +643,9 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin '-obf', '-obfuscate' { res.obfuscate = true } + '-hide-auto-str' { + res.hide_auto_str = true + } '-translated' { res.translated = true res.gc_mode = .no_gc // no gc in c2v'ed code, at least for now