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