From 148cffb77a5119e64f4fbf89e78389f3a1299d46 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 16 Aug 2014 02:10:01 -0700 Subject: [PATCH 1/3] Add -restrict option; restrict symbol generation to JSON file Fixes go-gl/glow#42 --- README.md | 1 + example.json | 11 +++++++++++ main.go | 34 ++++++++++++++++++++++++++++++++++ package.go | 25 +++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 example.json diff --git a/README.md b/README.md index f44d171..0609c47 100644 --- a/README.md +++ b/README.md @@ -61,5 +61,6 @@ A few notes about the flags to `generate`: - `version`: The API version to generate. The `all` pseudo-version includes all functions and enumerations for the specified API. - `profile`: For `gl` packages with version 3.2 or higher, `core` or `compatibility` ([explanation](http://www.opengl.org/wiki/Core_And_Compatibility_in_Contexts)). - `addext`: A regular expression describing which extensions to include. `.*` by default, including everything. +- `restrict`: A JSON file that explicitly lists what enumerations / functions that Glow should generate (see example.json). - `remext`: A regular expression describing which extensions to exclude. Empty by default, excluding nothing. Takes precedence over explicitly added regular expressions. - `lenientInit`: Flag to disable strict function availability checks at `Init` time. By default if any non-extension function pointer cannot be loaded then initialization fails; when this flag is set initialization will succeed with missing functions. Note that on some platforms unavailable functions will load successfully even but fail upon invocation so check against the OpenGL context what is supported. diff --git a/example.json b/example.json new file mode 100644 index 0000000..109e67b --- /dev/null +++ b/example.json @@ -0,0 +1,11 @@ +{ + "Enums": [ + "GL_CCW", + "GL_COLOR_ATTACHMENT0", + "GL_COMPRESSED_RGB" + ], + "Functions": [ + "glBindTextures", + "glBindVertexArray" + ] +} diff --git a/main.go b/main.go index 6f60ddd..5350883 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( + "encoding/json" "flag" "fmt" "io/ioutil" @@ -61,6 +62,7 @@ func generate(name string, args []string) { profile := flags.String("profile", "", "API profile to generate (e.g., core)") addext := flags.String("addext", ".*", "Regular expression of extensions to include (e.g., .*)") remext := flags.String("remext", "$^", "Regular expression of extensions to exclude (e.g., .*)") + restrict := flags.String("restrict", "", "JSON file of symbols to restrict symbol generation") lenientInit := flags.Bool("lenientInit", false, "When true missing functions do not fail Init") flags.Parse(args) @@ -97,6 +99,9 @@ func generate(name string, args []string) { pkg = spec.ToPackage(packageSpec) pkg.SpecRev = rev docs.AddDocs(pkg) + if len(*restrict) > 0 { + performRestriction(pkg, *restrict) + } if err := pkg.GeneratePackage(); err != nil { log.Fatal("error generating package:", err) } @@ -109,6 +114,35 @@ func generate(name string, args []string) { log.Println("generated package in", pkg.Dir()) } +// Converts a slice string into a simple lookup map. +func lookupMap(s []string) map[string]struct{} { + lookup := make(map[string]struct{}, len(s)) + for _, str := range s { + lookup[str] = struct{}{} + } + return lookup +} + +type jsonRestriction struct { + Enums []string + Functions []string +} + +// Reads the given JSON file path into jsonRestriction and filters the package +// accordingly. +func performRestriction(pkg *Package, jsonPath string) { + data, err := ioutil.ReadFile(jsonPath) + if err != nil { + log.Fatal("error reading JSON restriction file:", err) + } + var r jsonRestriction + err = json.Unmarshal(data, &r) + if err != nil { + log.Fatal("error parsing JSON restriction file:", err) + } + pkg.Filter(lookupMap(r.Enums), lookupMap(r.Functions)) +} + func parseSpecifications(xmlDir string) ([]*Specification, string) { specDir := filepath.Join(xmlDir, "spec") specFiles, err := ioutil.ReadDir(specDir) diff --git a/package.go b/package.go index f0076bc..605d054 100644 --- a/package.go +++ b/package.go @@ -109,6 +109,31 @@ func (pkg *Package) HasRequiredFunctions() bool { return false } +// Filter removes any enums, or functions found in this package that are not +// listed in the given lookup maps. If either of the maps has a length of zero, +// filtering does not occur for that type (e.g. all functions are left intact). +func (pkg *Package) Filter(enums, functions map[string]struct{}) { + if len(enums) > 0 { + // Remove any enum not listed in the enums lookup map. + for name := range pkg.Enums { + _, valid := enums[name] + if !valid { + delete(pkg.Enums, name) + } + } + } + + if len(functions) > 0 { + // Remove any function not listed in the functions lookup map. + for name := range pkg.Functions { + _, valid := functions[name] + if !valid { + delete(pkg.Functions, name) + } + } + } +} + // This package's directory (relative to $GOPATH). const pkgDir = "src/github.com/go-gl/glow" From 812d8a439445b06420201cb563e18784c7475b1c Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 17 Aug 2014 15:51:29 -0700 Subject: [PATCH 2/3] Move error check for json.Unmarshal onto single line. --- main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.go b/main.go index 5350883..6911b77 100644 --- a/main.go +++ b/main.go @@ -136,8 +136,7 @@ func performRestriction(pkg *Package, jsonPath string) { log.Fatal("error reading JSON restriction file:", err) } var r jsonRestriction - err = json.Unmarshal(data, &r) - if err != nil { + if err = json.Unmarshal(data, &r); err != nil { log.Fatal("error parsing JSON restriction file:", err) } pkg.Filter(lookupMap(r.Enums), lookupMap(r.Functions)) From 0c88c0b7c800db07e972da0d91ac77b3976a3b32 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 17 Aug 2014 15:56:50 -0700 Subject: [PATCH 3/3] Represent set as map[string]bool instead of map[string]struct{}. --- main.go | 6 +++--- package.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 6911b77..cb83b3d 100644 --- a/main.go +++ b/main.go @@ -115,10 +115,10 @@ func generate(name string, args []string) { } // Converts a slice string into a simple lookup map. -func lookupMap(s []string) map[string]struct{} { - lookup := make(map[string]struct{}, len(s)) +func lookupMap(s []string) map[string]bool { + lookup := make(map[string]bool, len(s)) for _, str := range s { - lookup[str] = struct{}{} + lookup[str] = true } return lookup } diff --git a/package.go b/package.go index 605d054..b725fcf 100644 --- a/package.go +++ b/package.go @@ -112,7 +112,7 @@ func (pkg *Package) HasRequiredFunctions() bool { // Filter removes any enums, or functions found in this package that are not // listed in the given lookup maps. If either of the maps has a length of zero, // filtering does not occur for that type (e.g. all functions are left intact). -func (pkg *Package) Filter(enums, functions map[string]struct{}) { +func (pkg *Package) Filter(enums, functions map[string]bool) { if len(enums) > 0 { // Remove any enum not listed in the enums lookup map. for name := range pkg.Enums {