1// Copyright 2023 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4// 5// This executable for a given ICU implementation (from a hardcoded set) 6// collects performance, memory and actual data for comparison in a simple internal format 7 8package main 9 10import ( 11 "flag" 12 "fmt" 13 "os" 14 "path/filepath" 15 "strconv" 16 "strings" 17 18 "go.skia.org/skia/tools/unicode_comparison/go/bridge" 19 "go.skia.org/skia/tools/unicode_comparison/go/helpers" 20) 21 22func createEmptyFile(name string) error { 23 d := []byte("") 24 return os.WriteFile(name, d, 0644) 25} 26 27func walkRecursively(input string, output string) error { 28 err := filepath.Walk(input, 29 func(inputPath string, info os.FileInfo, err error) error { 30 if err != nil { 31 fmt.Println(err) 32 return err 33 } 34 if info.IsDir() { 35 outputPath := strings.Replace(inputPath, input, output, 1) 36 fmt.Printf("%s -> %s\n", inputPath, outputPath) 37 err := os.MkdirAll(outputPath, os.ModePerm) 38 helpers.Check(err) 39 } else { 40 outputPath := strings.Replace(inputPath, input, output, 1) 41 if err := writeInfo(inputPath, outputPath); err != nil { 42 fmt.Println(err) 43 return err 44 } 45 } 46 return nil 47 }) 48 return err 49} 50 51func writeInfo(inputPath string, outputPath string) error { 52 53 // Read file 54 fileContent, err := os.ReadFile(inputPath) 55 helpers.Check(err) 56 57 // Convert []byte to string 58 text := string(fileContent) 59 60 // Initialize file 61 time := bridge.PerfComputeCodeunitFlags(text) 62 63 outputFile, err := os.Create(outputPath) 64 helpers.Check(err) 65 66 // Collect info 67 line := fmt.Sprintf("%.2f", time) 68 _, err = outputFile.WriteString(line + "\n0.0\n") 69 helpers.Check(err) 70 71 graphemes := "" 72 softBreaks := "" 73 hardBreaks := "" 74 whitespaces := "" 75 words := "" 76 controls := "" 77 78 graphemesCount := 0 79 softBreaksCount := 0 80 hardBreaksCount := 0 81 whitespacesCount := 0 82 wordsCount := 0 83 controlsCount := 0 84 for i := 0; i <= len(fileContent); i++ { 85 flags := bridge.GetFlags(i) 86 str := bridge.FlagsToString(flags) 87 pos := strconv.Itoa(i) 88 if strings.Contains(str, "G") { 89 graphemes += " " 90 graphemes += pos 91 graphemesCount += 1 92 } 93 if strings.Contains(str, "S") { 94 softBreaks += " " 95 softBreaks += pos 96 softBreaksCount += 1 97 } 98 if strings.Contains(str, "H") { 99 hardBreaks += " " 100 hardBreaks += pos 101 hardBreaksCount += 1 102 } 103 if strings.Contains(str, "W") { 104 whitespaces += " " 105 whitespaces += pos 106 whitespacesCount += 1 107 } 108 if strings.Contains(str, "D") { 109 words += " " 110 words += pos 111 wordsCount += 1 112 } 113 if strings.Contains(str, "C") { 114 controls += " " 115 controls += pos 116 controlsCount += 1 117 } 118 } 119 120 _, err = outputFile.WriteString(strconv.Itoa(graphemesCount) + graphemes + "\n") 121 helpers.Check(err) 122 123 _, err = outputFile.WriteString(strconv.Itoa(softBreaksCount) + softBreaks + "\n") 124 helpers.Check(err) 125 126 _, err = outputFile.WriteString(strconv.Itoa(hardBreaksCount) + hardBreaks + "\n") 127 helpers.Check(err) 128 129 _, err = outputFile.WriteString(strconv.Itoa(whitespacesCount) + whitespaces + "\n") 130 helpers.Check(err) 131 132 _, err = outputFile.WriteString(strconv.Itoa(wordsCount) + words + "\n") 133 helpers.Check(err) 134 135 _, err = outputFile.WriteString(strconv.Itoa(controlsCount) + controls + "\n") 136 helpers.Check(err) 137 138 outputFile.Close() 139 140 return nil 141} 142 143func main() { 144 var ( 145 root = flag.String("root", "~/datasets", "Folder (pages will be under <Folder>/input") 146 impl = flag.String("impl", "", "Unicode Implementation") 147 ) 148 flag.Parse() 149 150 *root = helpers.ExpandPath(*root) 151 input := filepath.Join(*root, "input") 152 output := filepath.Join(*root, "output", *impl) 153 if *root == "" { 154 fmt.Println("Must set --root") 155 flag.PrintDefaults() 156 } else if *impl == "" { 157 fmt.Println("Must set --impl") 158 flag.PrintDefaults() 159 } 160 if !bridge.InitUnicode(*impl) { 161 return 162 } 163 err := walkRecursively(input, output) 164 defer bridge.CleanupUnicode() 165 166 if err != nil { 167 fmt.Println(err) 168 } 169} 170