aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/cmd/tools/vbin2v.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/cmd/tools/vbin2v.v')
-rw-r--r--v_windows/v/cmd/tools/vbin2v.v146
1 files changed, 146 insertions, 0 deletions
diff --git a/v_windows/v/cmd/tools/vbin2v.v b/v_windows/v/cmd/tools/vbin2v.v
new file mode 100644
index 0000000..c1ab6e0
--- /dev/null
+++ b/v_windows/v/cmd/tools/vbin2v.v
@@ -0,0 +1,146 @@
+module main
+
+import os
+import flag
+import strings
+
+const (
+ tool_version = '0.0.4'
+ tool_description = 'Converts a list of arbitrary files into a single v module file.'
+)
+
+struct Context {
+mut:
+ files []string
+ prefix string
+ show_help bool
+ module_name string
+ write_file string
+}
+
+fn (context Context) header() string {
+ mut header_s := ''
+ header_s += 'module $context.module_name\n'
+ header_s += '\n'
+ allfiles := context.files.join(' ')
+ mut options := []string{}
+ if context.prefix.len > 0 {
+ options << '-p $context.prefix'
+ }
+ if context.module_name.len > 0 {
+ options << '-m $context.module_name'
+ }
+ if context.write_file.len > 0 {
+ options << '-w $context.write_file'
+ }
+ soptions := options.join(' ')
+ header_s += '// File generated by:\n'
+ header_s += '// v bin2v $allfiles $soptions\n'
+ header_s += '// Please, do not edit this file.\n'
+ header_s += '// Your changes may be overwritten.\n'
+ header_s += 'const (\n'
+ return header_s
+}
+
+fn (context Context) footer() string {
+ return ')\n'
+}
+
+fn (context Context) file2v(bname string, fbytes []byte, bn_max int) string {
+ mut sb := strings.new_builder(1000)
+ bn_diff_len := bn_max - bname.len
+ sb.write_string('\t${bname}_len' + ' '.repeat(bn_diff_len - 4) + ' = $fbytes.len\n')
+ fbyte := fbytes[0]
+ bnmae_line := '\t$bname' + ' '.repeat(bn_diff_len) + ' = [byte($fbyte), '
+ sb.write_string(bnmae_line)
+ mut line_len := bnmae_line.len + 3
+ for i := 1; i < fbytes.len; i++ {
+ b := int(fbytes[i]).str()
+ if line_len > 94 {
+ sb.go_back(1)
+ sb.write_string('\n\t\t')
+ line_len = 8
+ }
+ if i == fbytes.len - 1 {
+ sb.write_string(b)
+ line_len += b.len
+ } else {
+ sb.write_string('$b, ')
+ line_len += b.len + 2
+ }
+ }
+ sb.write_string(']!\n')
+ return sb.str()
+}
+
+fn (context Context) bname_and_bytes(file string) ?(string, []byte) {
+ fname := os.file_name(file)
+ fname_escaped := fname.replace_each(['.', '_', '-', '_'])
+ byte_name := '$context.prefix$fname_escaped'.to_lower()
+ fbytes := os.read_bytes(file) or { return error('Error: $err.msg') }
+ return byte_name, fbytes
+}
+
+fn (context Context) max_bname_len(bnames []string) int {
+ mut max := 0
+ for n in bnames {
+ if n.len > max {
+ max = n.len
+ }
+ }
+ // Add 4 to max due to "_len" suffix
+ return max + 4
+}
+
+fn main() {
+ mut context := Context{}
+ mut fp := flag.new_flag_parser(os.args[1..])
+ fp.application('v bin2v')
+ fp.version(tool_version)
+ fp.description(tool_description)
+ fp.arguments_description('FILE [FILE]...')
+ context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
+ context.module_name = fp.string('module', `m`, 'binary', 'Name of the generated module.')
+ context.prefix = fp.string('prefix', `p`, '', 'A prefix put before each resource name.')
+ context.write_file = fp.string('write', `w`, '', 'Write directly to a file with the given name.')
+ if context.show_help {
+ println(fp.usage())
+ exit(0)
+ }
+ files := fp.finalize() or {
+ eprintln('Error: $err.msg')
+ exit(1)
+ }
+ real_files := files.filter(it != 'bin2v')
+ if real_files.len == 0 {
+ println(fp.usage())
+ exit(0)
+ }
+ context.files = real_files
+ if context.write_file != '' && os.file_ext(context.write_file) !in ['.vv', '.v'] {
+ context.write_file += '.v'
+ }
+ mut file_byte_map := map[string][]byte{}
+ for file in real_files {
+ bname, fbytes := context.bname_and_bytes(file) or {
+ eprintln(err.msg)
+ exit(1)
+ }
+ file_byte_map[bname] = fbytes
+ }
+ max_bname := context.max_bname_len(file_byte_map.keys())
+ if context.write_file.len > 0 {
+ mut out_file := os.create(context.write_file) ?
+ out_file.write_string(context.header()) ?
+ for bname, fbytes in file_byte_map {
+ out_file.write_string(context.file2v(bname, fbytes, max_bname)) ?
+ }
+ out_file.write_string(context.footer()) ?
+ } else {
+ print(context.header())
+ for bname, fbytes in file_byte_map {
+ print(context.file2v(bname, fbytes, max_bname))
+ }
+ print(context.footer())
+ }
+}