b71a28d3c0
support new types for import * tests pass * missing file * bug fixes
485 lines
11 KiB
Go
485 lines
11 KiB
Go
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build ingore
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"go/format"
|
|
"io/ioutil"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"text/scanner"
|
|
)
|
|
|
|
type Type struct {
|
|
TypeName string
|
|
FileName string
|
|
FileData []byte
|
|
TypeList []string
|
|
TypeCommentMap map[string]string
|
|
TagTypeMap map[string][]string
|
|
TagNumMap map[string][]int
|
|
TagIFDMap map[string]string
|
|
TagIngoreMap map[string]bool
|
|
MapCode string
|
|
}
|
|
|
|
func main() {
|
|
var types = []Type{
|
|
Type{
|
|
TypeName: "TiffType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "ImageType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "DataType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
|
|
Type{
|
|
TypeName: "TagValue_NewSubfileType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagValue_SubfileType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagValue_CompressionType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagValue_PhotometricType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagValue_PredictorType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagValue_ResolutionUnitType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "TagValue_SampleFormatType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
|
|
Type{
|
|
TypeName: "ExifIFD_TagType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "GPSIFD_TagType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
Type{
|
|
TypeName: "InteroperabilityIFD_TagType",
|
|
FileName: "tiff_types.go",
|
|
},
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
fmt.Fprintf(&buf, `
|
|
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Auto generated by gen_helper.go, DO NOT EDIT!!!
|
|
|
|
package tiff
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
`[1:])
|
|
|
|
for _, v := range types {
|
|
v.Init()
|
|
v.GenMapCode()
|
|
|
|
fmt.Fprintf(&buf, "%s\n", v.MapCode)
|
|
}
|
|
|
|
data, err := format.Source(buf.Bytes())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = ioutil.WriteFile("z_tiff_types_string.go", data, 0644)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func (p *Type) Init() {
|
|
if p.TypeCommentMap == nil {
|
|
p.TypeCommentMap = make(map[string]string)
|
|
}
|
|
if p.TagTypeMap == nil {
|
|
p.TagTypeMap = make(map[string][]string)
|
|
}
|
|
if p.TagNumMap == nil {
|
|
p.TagNumMap = make(map[string][]int)
|
|
}
|
|
if p.TagIFDMap == nil {
|
|
p.TagIFDMap = make(map[string]string)
|
|
}
|
|
if p.TagIngoreMap == nil {
|
|
p.TagIngoreMap = make(map[string]bool)
|
|
}
|
|
|
|
data, err := ioutil.ReadFile(p.FileName)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
p.FileData = data
|
|
|
|
var s scanner.Scanner
|
|
s.Init(bytes.NewReader(p.FileData))
|
|
|
|
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
|
|
if tok&scanner.ScanIdents != 0 {
|
|
if strings.HasPrefix(s.TokenText(), p.TypeName+"_") {
|
|
typeName := s.TokenText()
|
|
if _, ok := p.TypeCommentMap[typeName]; !ok {
|
|
comment, _, _ := bufio.NewReader(bytes.NewReader(p.FileData[s.Pos().Offset:])).ReadLine()
|
|
if idx := bytes.Index(comment, []byte("//")); idx >= 0 {
|
|
comment = comment[idx:]
|
|
} else {
|
|
comment = nil
|
|
}
|
|
p.TypeList = append(p.TypeList, typeName)
|
|
p.TypeCommentMap[typeName] = string(comment)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if p.TypeName == "TagType" {
|
|
p.parseTagComment()
|
|
}
|
|
}
|
|
|
|
func (p *Type) parseTagComment() {
|
|
if p.TypeName != "TagType" {
|
|
return
|
|
}
|
|
// Type(A/B/C/*), Num(1/*), Required, # comment
|
|
for typeName, comment := range p.TypeCommentMap {
|
|
if strings.HasPrefix(comment, "//") {
|
|
comment = strings.TrimSpace(comment[len("//"):])
|
|
}
|
|
if idx := strings.Index(comment, "#"); idx >= 0 {
|
|
comment = comment[:idx]
|
|
}
|
|
comment = strings.TrimSpace(comment)
|
|
|
|
if strings.Contains(comment, "TagType_ExifIFD") {
|
|
p.TagIFDMap[typeName] = "TagType_ExifIFD"
|
|
}
|
|
if strings.Contains(comment, "TagType_GPSIFD") {
|
|
p.TagIFDMap[typeName] = "TagType_GPSIFD"
|
|
}
|
|
if strings.Contains(comment, "TagType_InteroperabilityIFD") {
|
|
p.TagIFDMap[typeName] = "TagType_InteroperabilityIFD"
|
|
}
|
|
|
|
if strings.Contains(comment, "ingore") {
|
|
p.TagIngoreMap[typeName] = true
|
|
continue
|
|
}
|
|
if comment == "" {
|
|
continue
|
|
}
|
|
|
|
ss := strings.Split(comment, ",")
|
|
if len(ss) > 0 {
|
|
var types []string
|
|
for _, dataType := range strings.Split(strings.TrimSpace(ss[0]), "/") {
|
|
switch dataType {
|
|
case "BYTE":
|
|
types = append(types, "DataType_Byte")
|
|
case "ASCII":
|
|
types = append(types, "DataType_ASCII")
|
|
case "SHORT":
|
|
types = append(types, "DataType_Short")
|
|
case "LONG":
|
|
types = append(types, "DataType_Long")
|
|
case "RATIONAL":
|
|
types = append(types, "DataType_Rational")
|
|
case "SBYTE":
|
|
types = append(types, "DataType_SByte")
|
|
case "UNDEFINED":
|
|
types = append(types, "DataType_Undefined")
|
|
case "SSHORT":
|
|
types = append(types, "DataType_SShort")
|
|
case "SLONG":
|
|
types = append(types, "DataType_SLong")
|
|
case "SRATIONAL":
|
|
types = append(types, "DataType_SRational")
|
|
case "FLOAT":
|
|
types = append(types, "DataType_Float")
|
|
case "DOUBLE":
|
|
types = append(types, "DataType_Double")
|
|
case "IFD":
|
|
types = append(types, "DataType_IFD")
|
|
case "UNICODE":
|
|
types = append(types, "DataType_Unicode")
|
|
case "COMPLEX":
|
|
types = append(types, "DataType_Complex")
|
|
case "LONG8":
|
|
types = append(types, "DataType_Long8")
|
|
case "SLONG8":
|
|
types = append(types, "DataType_SLong8")
|
|
case "IFD8":
|
|
types = append(types, "DataType_IFD8")
|
|
}
|
|
}
|
|
p.TagTypeMap[typeName] = types
|
|
}
|
|
if len(ss) > 1 {
|
|
var nums []int
|
|
for _, numName := range strings.Split(strings.TrimSpace(ss[1]), "/") {
|
|
if v, err := strconv.Atoi(numName); err == nil {
|
|
nums = append(nums, v)
|
|
}
|
|
}
|
|
p.TagNumMap[typeName] = nums
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *Type) GenMapCode() {
|
|
var buf bytes.Buffer
|
|
fmt.Fprintf(&buf, "var _%sTable = map[%s]string {\n", p.TypeName, p.TypeName)
|
|
for _, s := range p.TypeList {
|
|
if _, ok := p.TagIFDMap[s]; ok {
|
|
continue
|
|
}
|
|
fmt.Fprintf(&buf, "\t%s: `%s`, %s\n", s, s, p.TypeCommentMap[s])
|
|
}
|
|
fmt.Fprintf(&buf, "}\n")
|
|
|
|
if p.TypeName == "TagType" && len(p.TagTypeMap) > 0 {
|
|
fmt.Fprintf(&buf, "\nvar _TagType_TypesTable = map[TagType][]DataType {\n")
|
|
for _, s := range p.TypeList {
|
|
if _, ok := p.TagIFDMap[s]; ok {
|
|
continue
|
|
}
|
|
if v, ok := p.TagTypeMap[s]; ok && len(v) > 0 {
|
|
fmt.Fprintf(&buf, "%s: []DataType{ ", s)
|
|
for j := 0; j < len(v); j++ {
|
|
fmt.Fprintf(&buf, `%s, `, v[j])
|
|
}
|
|
fmt.Fprintf(&buf, "},\n")
|
|
}
|
|
}
|
|
fmt.Fprintf(&buf, "}\n")
|
|
|
|
}
|
|
if p.TypeName == "TagType" && len(p.TagNumMap) > 0 {
|
|
fmt.Fprintf(&buf, "\nvar _TagType_NumsTable = map[TagType][]int {\n")
|
|
for _, s := range p.TypeList {
|
|
if _, ok := p.TagIFDMap[s]; ok {
|
|
continue
|
|
}
|
|
if v, ok := p.TagNumMap[s]; ok && len(v) > 0 {
|
|
fmt.Fprintf(&buf, "%s: []int{ ", s)
|
|
for j := 0; j < len(v); j++ {
|
|
fmt.Fprintf(&buf, `%d, `, v[j])
|
|
}
|
|
fmt.Fprintf(&buf, "},\n")
|
|
}
|
|
}
|
|
fmt.Fprintf(&buf, "}\n")
|
|
}
|
|
|
|
if p.TypeName == "TagType" {
|
|
fmt.Fprintf(&buf, "\ntype TagGetter interface {\n")
|
|
for _, s := range p.TypeList {
|
|
if _, ok := p.TagIFDMap[s]; ok {
|
|
continue
|
|
}
|
|
if _, ingore := p.TagIngoreMap[s]; !ingore {
|
|
fmt.Fprintf(&buf, "Get%s() (value %s, ok bool)\n", s[len("TagType_"):], p.getValueType(s))
|
|
}
|
|
}
|
|
fmt.Fprintf(&buf, "\n")
|
|
fmt.Fprintf(&buf, "GetUnknown(tag TagType) (value []byte, ok bool)\n")
|
|
fmt.Fprintf(&buf, "\n")
|
|
fmt.Fprintf(&buf, "private()\n")
|
|
fmt.Fprintf(&buf, "}\n")
|
|
|
|
fmt.Fprintf(&buf, "\ntype TagSetter interface {\n")
|
|
for _, s := range p.TypeList {
|
|
if _, ok := p.TagIFDMap[s]; ok {
|
|
continue
|
|
}
|
|
if _, ingore := p.TagIngoreMap[s]; !ingore {
|
|
fmt.Fprintf(&buf, "Set%s(value %s) (ok bool)\n", s[len("TagType_"):], p.getValueType(s))
|
|
}
|
|
}
|
|
fmt.Fprintf(&buf, "\n")
|
|
fmt.Fprintf(&buf, "SetUnknown(tag TagType, value interface{}) (ok bool)\n")
|
|
fmt.Fprintf(&buf, "\n")
|
|
fmt.Fprintf(&buf, "private()\n")
|
|
fmt.Fprintf(&buf, "}\n")
|
|
}
|
|
|
|
fmt.Fprintf(&buf, `
|
|
func (p %s) String() string {
|
|
if name, ok := _%sTable[p]; ok {
|
|
return name
|
|
}
|
|
return fmt.Sprintf("%s_Unknown(%%d)", uint16(p))
|
|
}
|
|
`,
|
|
p.TypeName,
|
|
p.TypeName,
|
|
p.TypeName,
|
|
)
|
|
|
|
p.MapCode = buf.String()
|
|
}
|
|
|
|
func (p *Type) getValueType(typeName string) string {
|
|
switch typeName {
|
|
case "TagType_Compression":
|
|
return "TagValue_CompressionType"
|
|
case "TagType_PhotometricInterpretation":
|
|
return "TagValue_PhotometricType"
|
|
case "TagType_Predictor":
|
|
return "TagValue_PredictorType"
|
|
case "TagType_ResolutionUnit":
|
|
return "TagValue_ResolutionUnitType"
|
|
case "TagType_ColorMap":
|
|
return "[][3]uint16"
|
|
case "TagType_SMinSampleValue", "TagType_SMaxSampleValue":
|
|
return "[]float64"
|
|
case "TagType_DateTime":
|
|
return "time.Time"
|
|
}
|
|
switch types, _ := p.TagTypeMap[typeName]; {
|
|
case p.isIntType(types):
|
|
if p.isOnlyOneValue(p.TagNumMap[typeName]) {
|
|
return `int64`
|
|
} else {
|
|
return `[]int64`
|
|
}
|
|
case p.isFloatType(types):
|
|
if p.isOnlyOneValue(p.TagNumMap[typeName]) {
|
|
return `float64`
|
|
} else {
|
|
return `[]float64`
|
|
}
|
|
case p.isRationalType(types):
|
|
if p.isOnlyOneValue(p.TagNumMap[typeName]) {
|
|
return `[2]int64`
|
|
} else {
|
|
return `[][2]int64`
|
|
}
|
|
case p.isComplexType(types):
|
|
if p.isOnlyOneValue(p.TagNumMap[typeName]) {
|
|
return `complex128`
|
|
} else {
|
|
return `[]complex128`
|
|
}
|
|
case p.isStringType(types):
|
|
return `string`
|
|
case p.isUndefinedType(types):
|
|
return `[]byte`
|
|
default:
|
|
return `[]byte`
|
|
}
|
|
}
|
|
|
|
func (p *Type) isOnlyOneValue(nums []int) bool {
|
|
return len(nums) == 1 && nums[0] == 1
|
|
}
|
|
|
|
func (p *Type) isIntType(dataTypes []string) bool {
|
|
if len(dataTypes) == 0 {
|
|
return false
|
|
}
|
|
for _, s := range dataTypes {
|
|
switch s {
|
|
case "DataType_Byte", "DataType_Short", "DataType_Long", "DataType_Long8":
|
|
case "DataType_SByte", "DataType_SShort", "DataType_SLong", "DataType_SLong8":
|
|
case "DataType_IFD", "DataType_IFD8":
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func (p *Type) isFloatType(dataTypes []string) bool {
|
|
if len(dataTypes) == 0 {
|
|
return false
|
|
}
|
|
for _, s := range dataTypes {
|
|
if s != "DataType_Float" && s != "DataType_Double" {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func (p *Type) isRationalType(dataTypes []string) bool {
|
|
if len(dataTypes) == 0 {
|
|
return false
|
|
}
|
|
for _, s := range dataTypes {
|
|
if s != "DataType_Rational" && s != "DataType_SRational" {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func (p *Type) isComplexType(dataTypes []string) bool {
|
|
if len(dataTypes) == 0 {
|
|
return false
|
|
}
|
|
for _, s := range dataTypes {
|
|
if s != "DataType_Complex" {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func (p *Type) isStringType(dataTypes []string) bool {
|
|
if len(dataTypes) == 0 {
|
|
return false
|
|
}
|
|
for _, s := range dataTypes {
|
|
if s != "DataType_ASCII" && s != "DataType_Unicode" {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func (p *Type) isUndefinedType(dataTypes []string) bool {
|
|
if len(dataTypes) == 0 {
|
|
return true
|
|
}
|
|
for _, s := range dataTypes {
|
|
if s == "DataType_Undefined" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|