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