• 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	"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}
143