embed_test_data.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (c) 2017, Google Inc.
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. // embed_test_data generates a C++ source file which exports a function,
  15. // GetTestData, which looks up the specified data files.
  16. package main
  17. import (
  18. "bytes"
  19. "fmt"
  20. "io/ioutil"
  21. "os"
  22. )
  23. func quote(in []byte) string {
  24. var buf bytes.Buffer
  25. buf.WriteByte('"')
  26. for _, b := range in {
  27. switch b {
  28. case '\a':
  29. buf.WriteString(`\a`)
  30. case '\b':
  31. buf.WriteString(`\b`)
  32. case '\f':
  33. buf.WriteString(`\f`)
  34. case '\n':
  35. buf.WriteString(`\n`)
  36. case '\r':
  37. buf.WriteString(`\r`)
  38. case '\t':
  39. buf.WriteString(`\t`)
  40. case '\v':
  41. buf.WriteString(`\v`)
  42. case '"':
  43. buf.WriteString(`\"`)
  44. case '\\':
  45. buf.WriteString(`\\`)
  46. default:
  47. // printable ascii code [32, 126]
  48. if 32 <= b && b <= 126 {
  49. buf.WriteByte(b)
  50. } else {
  51. fmt.Fprintf(&buf, "\\x%02x", b)
  52. }
  53. }
  54. }
  55. buf.WriteByte('"')
  56. return buf.String()
  57. }
  58. func main() {
  59. fmt.Printf(`/* Copyright (c) 2017, Google Inc.
  60. *
  61. * Permission to use, copy, modify, and/or distribute this software for any
  62. * purpose with or without fee is hereby granted, provided that the above
  63. * copyright notice and this permission notice appear in all copies.
  64. *
  65. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  66. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  67. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  68. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  69. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  70. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  71. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  72. /* This file is generated by:
  73. `)
  74. fmt.Printf(" * go run util/embed_test_data.go")
  75. for _, arg := range os.Args[1:] {
  76. fmt.Printf(" \\\n * %s", arg)
  77. }
  78. fmt.Printf(" */\n")
  79. fmt.Printf(`
  80. /* clang-format off */
  81. #include <stdlib.h>
  82. #include <string.h>
  83. #include <algorithm>
  84. #include <string>
  85. `)
  86. // MSVC limits the length of string constants, so we emit an array of
  87. // them and concatenate at runtime. We could also use a single array
  88. // literal, but this is less compact.
  89. const chunkSize = 8192
  90. for i, arg := range os.Args[1:] {
  91. data, err := ioutil.ReadFile(arg)
  92. if err != nil {
  93. fmt.Fprintf(os.Stderr, "Error reading %s: %s.\n", arg, err)
  94. os.Exit(1)
  95. }
  96. fmt.Printf("static const size_t kLen%d = %d;\n\n", i, len(data))
  97. fmt.Printf("static const char *kData%d[] = {\n", i)
  98. for len(data) > 0 {
  99. chunk := chunkSize
  100. if chunk > len(data) {
  101. chunk = len(data)
  102. }
  103. fmt.Printf(" %s,\n", quote(data[:chunk]))
  104. data = data[chunk:]
  105. }
  106. fmt.Printf("};\n")
  107. }
  108. fmt.Printf(`static std::string AssembleString(const char **data, size_t len) {
  109. std::string ret;
  110. for (size_t i = 0; i < len; i += %d) {
  111. size_t chunk = std::min(static_cast<size_t>(%d), len - i);
  112. ret.append(data[i / %d], chunk);
  113. }
  114. return ret;
  115. }
  116. /* Silence -Wmissing-declarations. */
  117. std::string GetTestData(const char *path);
  118. std::string GetTestData(const char *path) {
  119. `, chunkSize, chunkSize, chunkSize)
  120. for i, arg := range os.Args[1:] {
  121. fmt.Printf(" if (strcmp(path, %s) == 0) {\n", quote([]byte(arg)))
  122. fmt.Printf(" return AssembleString(kData%d, kLen%d);\n", i, i)
  123. fmt.Printf(" }\n")
  124. }
  125. fmt.Printf(` fprintf(stderr, "File not embedded: %%s.\n", path);
  126. abort();
  127. }
  128. `)
  129. }