From 925c2044f3d17c4c712a786cbc790d6809fa2fec Mon Sep 17 00:00:00 2001 From: Vinetwigs Date: Sat, 11 Jun 2022 12:57:19 +0200 Subject: [PATCH] - v1.2.0 --- .gitignore | 2 +- CHANGELOG.md | 33 +++++++ README.md | 103 +++++++++++++------ go.mod | 6 ++ go.sum | 25 +++++ stres.go | 247 ++++++++++++++++++++++++---------------------- stres_test.go | 4 +- types/json.go | 19 ++++ types/strategy.go | 26 +++++ types/toml.go | 25 +++++ types/types.go | 41 ++++++++ types/watson.go | 17 ++++ types/xml.go | 17 ++++ types/yaml.go | 19 ++++ 14 files changed, 436 insertions(+), 148 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 types/json.go create mode 100644 types/strategy.go create mode 100644 types/toml.go create mode 100644 types/types.go create mode 100644 types/watson.go create mode 100644 types/xml.go create mode 100644 types/yaml.go diff --git a/.gitignore b/.gitignore index e1858e9..ce2b8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ main.go -strings/strings.xml \ No newline at end of file +strings \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a0f3bb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.2.0] - 2022-06-11 + +### Added + +- Support for [JSON file format](https://www.json.org/json-en.html) +- Support for [YAML file format](https://yaml.org/) +- Support for [TOML file format](https://toml.io/en/) +- Support for [WATSON file format](https://github.com/genkami/watson) + +- SetResourceType function + +- FileType enum + +### Changed + +- CreateXMLFile function is now CreateResourceFile and takes a FileType parameter +- DeleteResourceFile function is now DeleteResourceFile +- LoadValues function now takes a FileType parameter + +## [1.1.0] - 2022-06-06 + +### Added + +- Support for XML file format + +- CreateXMLFile, DeleteXMLFile, LoadValues, NewString, NewStringArray, NewQuantityString, SetFewThreshold, GetString, GetStringArray, GetQuantityString functions \ No newline at end of file diff --git a/README.md b/README.md index d38e0f1..a8c79e6 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,39 @@

-## Table of Contents +## Table of contents + + * [References](#references) + * [Prerequisites](#prerequisites) + * [Installing](#installing) + + [Install module](#install-module) + + [Import in your project](#import-in-your-project) +- [Documentation](#documentation) + * [Types](#types) + + [Plural](#plural) + + [PluralItem](#pluralitem) + + [Item](#item) + + [StringArray](#stringarray) + + [String](#string) + + [Nesting](#nesting) + * [CreateResourceFile](#createresourcefile) + * [DeleteResourceFile](#deleteresourcefile) + * [LoadValues](#loadvalues) + * [SetResourceType](#setresourcetype) + * [NewString](#newstring) + * [NewStringArray](#newstringarray) + * [NewQuantityString](#newquantitystring) + * [SetFewThreshold](#setfewthreshold) + * [GetString](#getstring) + * [GetArrayString](#getarraystring) + * [GetQuantityString](#getquantitystring) +- [Contributors](#contributors) -[TOC] ### References * [Android Studio string resources](https://developer.android.com/guide/topics/resources/string-resource) +* [CHANGELOG](./CHANGELOG.md) [Back to top](#table-of-contents) @@ -53,9 +79,9 @@ import("github.com/Vinetwigs/stres") ```go type Plural struct { - XMLName xml.Name `xml:"plurals"` - Name string `xml:"name,attr"` - Items []*PluralItem `xml:"item"` + XMLName xml.Name `xml:"plurals" json:"plurals" yaml:"plurals" toml:"plurals" watson:"plurals"` + Name string `xml:"name,attr" json:"name" yaml:"name" toml:"name" watson:"name"` + Items []*PluralItem `xml:"item" json:"items" yaml:"items,flow" toml:"items,multiline" watson:"items"` } ``` @@ -65,9 +91,9 @@ type Plural struct { ```go type PluralItem struct { - XMLName xml.Name `xml:"item"` - Quantity string `xml:"quantity,attr"` - Value string `xml:",innerxml"` + XMLName xml.Name `xml:"item" json:"item" yaml:"item" toml:"item" watson:"item"` + Quantity string `xml:"quantity,attr" json:"quantity" yaml:"quantity" toml:"quantity" watson:"quantity"` + Value string `xml:",innerxml" json:"value" yaml:"value" toml:"value" watson:"value"` } ``` @@ -77,8 +103,8 @@ type PluralItem struct { ```go type Item struct { - XMLName xml.Name `xml:"item"` - Value string `xml:",innerxml"` + XMLName xml.Name `xml:"item" json:"item" yaml:"item" toml:"item" watson:"item"` + Value string `xml:",innerxml" json:"value" yaml:"value" toml:"value" watson:"value"` } ``` @@ -88,9 +114,9 @@ type Item struct { ```go type StringArray struct { - XMLName xml.Name `xml:"string-array"` - Name string `xml:"name,attr"` - Items []*Item `xml:"item"` + XMLName xml.Name `xml:"string-array" json:"string-array" yaml:"string-array" toml:"string-array" watson:"string-array"` + Name string `xml:"name,attr" json:"name" yaml:"name" toml:"name" watson:"name"` + Items []*Item `xml:"item" json:"items" yaml:"items,flow" toml:"items,multiline" watson:"items"` } ``` @@ -100,9 +126,9 @@ type StringArray struct { ```go type String struct { - XMLName xml.Name `xml:"string"` - Name string `xml:"name,attr"` - Value string `xml:",innerxml"` + XMLName xml.Name `xml:"string" json:"string" yaml:"string" toml:"string" watson:"string"` + Name string `xml:"name,attr" json:"name" yaml:"name" toml:"name" watson:"name"` + Value string `xml:",innerxml" json:"value" yaml:"value" toml:"value" watson:"value"` } ``` @@ -112,38 +138,57 @@ type String struct { ```go type Nesting struct { - XMLName xml.Name `xml:"resources"` - Strings []*String `xml:"string"` - StringsArray []*StringArray `xml:"string-array"` - Plurals []*Plural `xml:"plurals"` + XMLName xml.Name `xml:"resources" json:"resources" yaml:"resources" toml:"resources" watson:"resources"` + Strings []*String `xml:"string" json:"string" yaml:"string,flow" toml:"string,multiline" watson:"string"` + StringsArray []*StringArray `xml:"string-array" json:"string-array" yaml:"string-array,flow" toml:"string-array,multiline" watson:"string-array"` + Plurals []*Plural `xml:"plurals" json:"plurals" yaml:"plurals,flow" toml:"plurals,multiline" watson:"plurals"` } ``` [Back to top](#table-of-contents) -### CreateXMLFile -*Creates strings.xml file in "strings" directory, throws an error otherwise.* +### CreateResourceFile +*Creates strings resource file in "strings" directory, throws an error otherwise. Takes a FileType parameter to specify strings file format.* -`file, err := stres.CreateXMLFile()` +`file, err := stres.CreateXMLFile()` + +| Parameter | Type | Description | +|-----------|--------|---------------------------------------| +| t | types.FileType | enum value to specify file format | [Back to top](#table-of-contents) -### DeleteXMLFile -*Deletes XML file if exists, throws an error otherwise.* +### DeleteResourceFile +*Deletes resource file if exists, throws an error otherwise. Uses setted resource file extension.* `err := stres.DeleteXMLFile()` [Back to top](#table-of-contents) ### LoadValues -*Loads values from strings.xml file into internal dictionaries. Needs to be invoked only one time (but before getting strings values).* +*Loads values from strings file into internal dictionaries. Needs to be invoked only one time (but before getting strings values).Takes a FileType parameter to specify strings file format.* `err := stres.LoadValues()` [Back to top](#table-of-contents) +| Parameter | Type | Description | +|-----------|--------|---------------------------------------| +| t | types.FileType | enum value to specify file format | + +### SetResourceType +*Used to specify string file extension. If t is a wrong FileType, sets resource type to XML by default.* + +`stres.SetResourceType(stres.WATSON)` + +| Parameter | Type | Description | +|-----------|--------|---------------------------------------| +| t | types.FileType | enum value to specify file format | + +[Back to top](#table-of-contents) + ### NewString -*Adds a new string resource to XML file. Throws an error if the chosen name is already inserted or it is an empty string. Used for programmatic insertion (manual insertion recommended).* +*Adds a new string resource to resource file. Throws an error if the chosen name is already inserted or it is an empty string. Used for programmatic insertion (manual insertion recommended).* `String, err := stres.NewString("name", "value")` @@ -158,7 +203,7 @@ Returns String instance and error. [Back to top](#table-of-contents) ### NewStringArray -*Adds a new string-array resource to XML file. Throws an error if the chosen name is already inserted or it is an empty string. Used for programmatic insertion (manual insertion recommended).* +*Adds a new string-array resource to resource file. Throws an error if the chosen name is already inserted or it is an empty string. Used for programmatic insertion (manual insertion recommended).* `strArr, err := stres.NewStringArray("name", []string{"value1","value2",...})` @@ -172,7 +217,7 @@ Returns StringArray instance and error. [Back to top](#table-of-contents) ### NewQuantityString -*Adds a new quantity string resource to XML file. Throws an error if the chosen name is already inserted or it is an empty string. The function uses only the first 5 values in the array. The first value is assigned to "zero" quantity. The second value is assigned to "one" quantity. The third value is assigned to "two" quantity. The fourth value is assigned to "few" quantity. The fifth value is assigned to "more" quantity. Used for programmatic insertion (manual insertion recommended).* +*Adds a new quantity string resource to resource file. Throws an error if the chosen name is already inserted or it is an empty string. The function uses only the first 5 values in the array. The first value is assigned to "zero" quantity. The second value is assigned to "one" quantity. The third value is assigned to "two" quantity. The fourth value is assigned to "few" quantity. The fifth value is assigned to "more" quantity. Used for programmatic insertion (manual insertion recommended).* `qntStr, err := stres.NewQuantityString("name", []string{"zero","one", "two", ...})` diff --git a/go.mod b/go.mod index 47193d8..dbf1d25 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,9 @@ module github.com/Vinetwigs/stres go 1.17 + +require gopkg.in/yaml.v3 v3.0.1 + +require github.com/pelletier/go-toml/v2 v2.0.2 + +require github.com/genkami/watson v1.0.0 diff --git a/go.sum b/go.sum index e69de29..1444e94 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,25 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/genkami/watson v1.0.0 h1:wnitYUtaR8GWNQhvJ/VCoqOrC12iRRvtWlff9IKVJmI= +github.com/genkami/watson v1.0.0/go.mod h1:h0pRN42xxvCHX/Oyopf4AxtAv4z0+51qRN+K6UxF70g= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= +github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/vmihailenco/msgpack/v5 v5.2.0/go.mod h1:fEM7KuHcnm0GvDCztRpw9hV0PuoO2ciTismP6vjggcM= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/stres.go b/stres.go index eac9ccb..0be6fa5 100644 --- a/stres.go +++ b/stres.go @@ -1,22 +1,35 @@ package stres import ( - "encoding/xml" "errors" + "fmt" "io/ioutil" "os" "strings" + + "github.com/Vinetwigs/stres/types" ) +var fileType types.FileType +var encDec = types.EncoderDecoder{} + var quantityValues = [...]string{"zero", "one", "two", "few", "many"} var data []byte var string_entries map[string]string = make(map[string]string) -var string_array_entries map[string]StringArray = make(map[string]StringArray) -var plural_string_entries map[string]Plural = make(map[string]Plural) +var string_array_entries map[string]types.StringArray = make(map[string]types.StringArray) +var plural_string_entries map[string]types.Plural = make(map[string]types.Plural) var few_threshold = 20 +const ( + XML types.FileType = "xml" + YAML types.FileType = "yml" + JSON types.FileType = "json" + TOML types.FileType = "toml" + WATSON types.FileType = "watson" +) + var ( ErrorEmptyStringName error = errors.New("stres: string name can't be empty") ErrorEmptyStringArrayName error = errors.New("stres: string-array name can't be empty") @@ -31,56 +44,23 @@ var ( ErrorQuantityStringEmptyValues error = errors.New("stres: provided empty array to quantity string creationg") ) -type Plural struct { - XMLName xml.Name `xml:"plurals"` - Name string `xml:"name,attr"` - Items []*PluralItem `xml:"item"` -} - -type PluralItem struct { - XMLName xml.Name `xml:"item"` - Quantity string `xml:"quantity,attr"` - Value string `xml:",innerxml"` -} - -type Item struct { - XMLName xml.Name `xml:"item"` - Value string `xml:",innerxml"` -} - -type StringArray struct { - XMLName xml.Name `xml:"string-array"` - Name string `xml:"name,attr"` - Items []*Item `xml:"item"` -} - -type String struct { - XMLName xml.Name `xml:"string"` - Name string `xml:"name,attr"` - Value string `xml:",innerxml"` -} - -type Nesting struct { - XMLName xml.Name `xml:"resources"` - Strings []*String `xml:"string"` - StringsArray []*StringArray `xml:"string-array"` - Plurals []*Plural `xml:"plurals"` -} - /* - Loads values from strings.xml file into internal dictionaries. + Loads values from strings file into internal dictionaries. Needs to be invoked only one time (but before getting strings values). + Takes a FileType parameter to specify strings file format. */ -func LoadValues() error { +func LoadValues(t types.FileType) error { + SetResourceType(t) + var err error - n := &Nesting{} + n := &types.Nesting{} - data, err = readXMLBytes("./strings/strings.xml") + data, err = readBytes(strings.Join([]string{"./strings/strings.", string(t)}, "")) if err != nil { return err } - err = decodeXML(data, &n) + err = encDec.Decode(data, &n) if err != nil { return err } @@ -104,12 +84,51 @@ func LoadValues() error { } /* - Creates strings.xml file in "strings" directory, throws an error otherwise. + Used to specify string file extension. If t is a wrong FileType, sets resource type to XML by default. */ -func CreateXMLFile() (*os.File, error) { + +func SetResourceType(t types.FileType) { + switch t { + case "xml": + xmlED := &types.XMLStrategy{} + encDec.SetStrategy(xmlED) + fileType = XML + case "json": + jsonED := &types.JSONStrategy{} + encDec.SetStrategy(jsonED) + fileType = JSON + case "yml": + yamlED := &types.YAMLStrategy{} + encDec.SetStrategy(yamlED) + fileType = YAML + case "toml": + tomlED := &types.TOMLStrategy{} + encDec.SetStrategy(tomlED) + fileType = TOML + case "watson": + watsonED := &types.WatsonStrategy{} + encDec.SetStrategy(watsonED) + fileType = WATSON + default: + xmlED := &types.XMLStrategy{} + encDec.SetStrategy(xmlED) + fileType = XML + } +} + +/* + Creates strings resource file in "strings" directory, throws an error otherwise. + Takes a FileType parameter to specify strings file format. +*/ +func CreateResourceFile(t types.FileType) (*os.File, error) { + + fileType = t + + SetResourceType(t) + os.Mkdir("strings", os.ModePerm) - file, err := os.Create("strings/strings.xml") + file, err := os.Create("strings/strings." + string(fileType)) if err != nil { return nil, err } @@ -123,10 +142,11 @@ func CreateXMLFile() (*os.File, error) { } /* - Deletes XML file if exists, throws an error otherwise. + Deletes resource file if exists, throws an error otherwise. + Uses setted resource file extension. */ -func DeleteXMLFile() error { - err := os.Remove("strings/strings.xml") +func DeleteResourceFile() error { + err := os.Remove("strings/strings." + string(fileType)) if err != nil { return err } @@ -140,70 +160,77 @@ func DeleteXMLFile() error { } /* - Adds a new string resource to XML file. Throws an error if the chosen name is already inserted or it is an empty string. + Adds a new string resource to resource file. Throws an error if the chosen name is already inserted or it is an empty string. */ -func NewString(name, value string) (String, error) { +func NewString(name, value string) (types.String, error) { if strings.TrimSpace(name) == "" { - return *new(String), ErrorEmptyStringName + return *new(types.String), ErrorEmptyStringName } if isDuplicateString(name) { - return *new(String), ErrorDuplicateStringName + return *new(types.String), ErrorDuplicateStringName } string_entries[name] = value var err error - s := String{ - XMLName: xml.Name{}, - Name: name, - Value: value, + s := types.String{ + Name: name, + Value: value, } - n := &Nesting{} + n := &types.Nesting{} - data, err = readXMLBytes("./strings/strings.xml") + data, err = readBytes(strings.Join([]string{"./strings/strings.", string(fileType)}, "")) if err != nil { - return *new(String), err + return *new(types.String), err } - err = decodeXML(data, &n) + err = encDec.Decode(data, &n) if err != nil { - return *new(String), err + return *new(types.String), err } n.Strings = append(n.Strings, &s) - data, err = encodeXML(n) + data, err = encDec.Encode(n) + + for i := 0; i < len(data); i++ { + fmt.Printf("%+v, ", data[i]) + if i%10 == 0 { + println() + } + } + println() + if err != nil { - return *new(String), err + return *new(types.String), err } - err = writeXMLBytes("strings/strings.xml", data) + err = writeBytes(strings.Join([]string{"./strings/strings.", string(fileType)}, ""), data) if err != nil { - return *new(String), err + return *new(types.String), err } return s, nil } /* - Adds a new string-array resource to XML file. Throws an error if the chosen name is already inserted or it is an empty string. + Adds a new string-array resource to resource file. Throws an error if the chosen name is already inserted or it is an empty string. */ -func NewStringArray(name string, values []string) (StringArray, error) { +func NewStringArray(name string, values []string) (types.StringArray, error) { if strings.TrimSpace(name) == "" { - return *new(StringArray), ErrorEmptyStringArrayName + return *new(types.StringArray), ErrorEmptyStringArrayName } if isDuplicateStringArray(name) { - return *new(StringArray), ErrorDuplicateStringArrayName + return *new(types.StringArray), ErrorDuplicateStringArrayName } - sa := &StringArray{Name: name} + sa := &types.StringArray{Name: name} for i := 0; i < len(values); i++ { - item := &Item{ - XMLName: xml.Name{}, - Value: values[i], + item := &types.Item{ + Value: values[i], } sa.Items = append(sa.Items, item) } @@ -212,34 +239,34 @@ func NewStringArray(name string, values []string) (StringArray, error) { var err error - n := &Nesting{} + n := &types.Nesting{} - data, err = readXMLBytes("./strings/strings.xml") + data, err = readBytes("./strings/strings." + string(fileType)) if err != nil { - return *new(StringArray), err + return *new(types.StringArray), err } - err = decodeXML(data, &n) + err = encDec.Decode(data, &n) if err != nil { - return *new(StringArray), err + return *new(types.StringArray), err } n.StringsArray = append(n.StringsArray, sa) - data, err = encodeXML(n) + data, err = encDec.Encode(n) if err != nil { - return *new(StringArray), err + return *new(types.StringArray), err } - err = writeXMLBytes("strings/strings.xml", data) + err = writeBytes("strings/strings."+string(fileType), data) if err != nil { - return *new(StringArray), err + return *new(types.StringArray), err } return *sa, nil } /* - Adds a new quantity string resource to XML file. + Adds a new quantity string resource to resource file. Throws an error if the chosen name is already inserted or it is an empty string. The function uses only the first 5 values in the array. The first values is assigned to "zero" quantity. @@ -248,23 +275,22 @@ func NewStringArray(name string, values []string) (StringArray, error) { The fourth values is assigned to "few" quantity. The fifth values is assigned to "more" quantity. */ -func NewQuantityString(name string, values []string) (Plural, error) { +func NewQuantityString(name string, values []string) (types.Plural, error) { if strings.TrimSpace(name) == "" { - return *new(Plural), ErrorEmptyStringArrayName + return *new(types.Plural), ErrorEmptyStringArrayName } if len(values) == 0 { - return *new(Plural), ErrorQuantityStringEmptyValues + return *new(types.Plural), ErrorQuantityStringEmptyValues } if isDuplicateQuantityString(name) { - return *new(Plural), ErrorDuplicateQuantityStringName + return *new(types.Plural), ErrorDuplicateQuantityStringName } - pl := &Plural{Name: name} + pl := &types.Plural{Name: name} for i := 0; i < len(values) && i < 5; i++ { - item := &PluralItem{ - XMLName: xml.Name{}, + item := &types.PluralItem{ Quantity: quantityValues[i], Value: values[i], } @@ -275,27 +301,27 @@ func NewQuantityString(name string, values []string) (Plural, error) { var err error - n := &Nesting{} + n := &types.Nesting{} - data, err = readXMLBytes("./strings/strings.xml") + data, err = readBytes("./strings/strings." + string(fileType)) if err != nil { - return *new(Plural), err + return *new(types.Plural), err } - err = decodeXML(data, &n) + err = encDec.Decode(data, &n) if err != nil { - return *new(Plural), err + return *new(types.Plural), err } n.Plurals = append(n.Plurals, pl) - data, err = encodeXML(n) + data, err = encDec.Encode(n) if err != nil { - return *new(Plural), err + return *new(types.Plural), err } - err = writeXMLBytes("strings/strings.xml", data) + err = writeBytes("strings/strings."+string(fileType), data) if err != nil { - return *new(Plural), err + return *new(types.Plural), err } return *pl, nil @@ -403,23 +429,14 @@ func GetQuantityString(name string, count int) string { } } -func readXMLBytes(path string) ([]byte, error) { - d, err := ioutil.ReadFile("./strings/strings.xml") +func readBytes(path string) ([]byte, error) { + d, err := ioutil.ReadFile(path) if err != nil { return *new([]byte), err } return d, nil } -func decodeXML(data []byte, v interface{}) error { - if len(data) == 0 { - v = &Nesting{} - return nil - } - - return xml.Unmarshal(data, v) -} - func isDuplicateString(name string) bool { if _, ok := string_entries[name]; ok { return true @@ -441,10 +458,6 @@ func isDuplicateQuantityString(name string) bool { return false } -func encodeXML(n *Nesting) ([]byte, error) { - return xml.MarshalIndent(n, "", "\t") -} - -func writeXMLBytes(path string, data []byte) error { +func writeBytes(path string, data []byte) error { return os.WriteFile(path, data, 0666) } diff --git a/stres_test.go b/stres_test.go index f00fb27..20b163d 100644 --- a/stres_test.go +++ b/stres_test.go @@ -4,6 +4,8 @@ import ( "encoding/xml" "reflect" "testing" + + "github.com/Vinetwigs/stres/types" ) func TestNewString(t *testing.T) { @@ -14,7 +16,7 @@ func TestNewString(t *testing.T) { tests := []struct { name string args args - want String + want types.String wantErr bool }{ { diff --git a/types/json.go b/types/json.go new file mode 100644 index 0000000..9df28a3 --- /dev/null +++ b/types/json.go @@ -0,0 +1,19 @@ +package types + +import ( + "encoding/json" +) + +type JSONStrategy struct{} + +func (j *JSONStrategy) encode(n *Nesting) ([]byte, error) { + return json.MarshalIndent(n, "", "\t") +} + +func (j *JSONStrategy) decode(data []byte, v interface{}) error { + if len(data) == 0 { + return nil + } + + return json.Unmarshal(data, v) +} diff --git a/types/strategy.go b/types/strategy.go new file mode 100644 index 0000000..7a58d5b --- /dev/null +++ b/types/strategy.go @@ -0,0 +1,26 @@ +package types + +type StrategyAlgo interface { + decode(data []byte, v interface{}) error + encode(n *Nesting) ([]byte, error) +} + +type EncoderDecoder struct { + strategy StrategyAlgo +} + +func (e *EncoderDecoder) SetStrategy(s StrategyAlgo) { + e.strategy = s +} + +func (e *EncoderDecoder) GetStrategy() StrategyAlgo { + return e.strategy +} + +func (e *EncoderDecoder) Encode(n *Nesting) ([]byte, error) { + return e.strategy.encode(n) +} + +func (e *EncoderDecoder) Decode(data []byte, v interface{}) error { + return e.strategy.decode(data, v) +} diff --git a/types/toml.go b/types/toml.go new file mode 100644 index 0000000..e1d3a99 --- /dev/null +++ b/types/toml.go @@ -0,0 +1,25 @@ +package types + +import ( + "bytes" + + "github.com/pelletier/go-toml/v2" +) + +type TOMLStrategy struct{} + +func (t *TOMLStrategy) encode(n *Nesting) ([]byte, error) { + buf := bytes.Buffer{} + enc := toml.NewEncoder(&buf) + enc.SetIndentTables(true) + err := enc.Encode(n) + return buf.Bytes(), err +} + +func (t *TOMLStrategy) decode(data []byte, v interface{}) error { + if len(data) == 0 { + return nil + } + + return toml.Unmarshal(data, v) +} diff --git a/types/types.go b/types/types.go new file mode 100644 index 0000000..ba947c9 --- /dev/null +++ b/types/types.go @@ -0,0 +1,41 @@ +package types + +import "encoding/xml" + +type FileType string + +type Plural struct { + XMLName xml.Name `xml:"plurals" json:"plurals" yaml:"plurals" toml:"plurals" watson:"plurals"` + Name string `xml:"name,attr" json:"name" yaml:"name" toml:"name" watson:"name"` + Items []*PluralItem `xml:"item" json:"items" yaml:"items,flow" toml:"items,multiline" watson:"items"` +} + +type PluralItem struct { + XMLName xml.Name `xml:"item" json:"item" yaml:"item" toml:"item" watson:"item"` + Quantity string `xml:"quantity,attr" json:"quantity" yaml:"quantity" toml:"quantity" watson:"quantity"` + Value string `xml:",innerxml" json:"value" yaml:"value" toml:"value" watson:"value"` +} + +type Item struct { + XMLName xml.Name `xml:"item" json:"item" yaml:"item" toml:"item" watson:"item"` + Value string `xml:",innerxml" json:"value" yaml:"value" toml:"value" watson:"value"` +} + +type StringArray struct { + XMLName xml.Name `xml:"string-array" json:"string-array" yaml:"string-array" toml:"string-array" watson:"string-array"` + Name string `xml:"name,attr" json:"name" yaml:"name" toml:"name" watson:"name"` + Items []*Item `xml:"item" json:"items" yaml:"items,flow" toml:"items,multiline" watson:"items"` +} + +type String struct { + XMLName xml.Name `xml:"string" json:"string" yaml:"string" toml:"string" watson:"string"` + Name string `xml:"name,attr" json:"name" yaml:"name" toml:"name" watson:"name"` + Value string `xml:",innerxml" json:"value" yaml:"value" toml:"value" watson:"value"` +} + +type Nesting struct { + XMLName xml.Name `xml:"resources" json:"resources" yaml:"resources" toml:"resources" watson:"resources"` + Strings []*String `xml:"string" json:"string" yaml:"string,flow" toml:"string,multiline" watson:"string"` + StringsArray []*StringArray `xml:"string-array" json:"string-array" yaml:"string-array,flow" toml:"string-array,multiline" watson:"string-array"` + Plurals []*Plural `xml:"plurals" json:"plurals" yaml:"plurals,flow" toml:"plurals,multiline" watson:"plurals"` +} diff --git a/types/watson.go b/types/watson.go new file mode 100644 index 0000000..cc800ae --- /dev/null +++ b/types/watson.go @@ -0,0 +1,17 @@ +package types + +import "github.com/genkami/watson" + +type WatsonStrategy struct{} + +func (w *WatsonStrategy) encode(n *Nesting) ([]byte, error) { + return watson.Marshal(n) +} + +func (w *WatsonStrategy) decode(data []byte, v interface{}) error { + if len(data) == 0 { + return nil + } + + return watson.Unmarshal(data, v) +} diff --git a/types/xml.go b/types/xml.go new file mode 100644 index 0000000..74a82f5 --- /dev/null +++ b/types/xml.go @@ -0,0 +1,17 @@ +package types + +import "encoding/xml" + +type XMLStrategy struct{} + +func (x *XMLStrategy) encode(n *Nesting) ([]byte, error) { + return xml.MarshalIndent(n, "", "\t") +} + +func (x *XMLStrategy) decode(data []byte, v interface{}) error { + if len(data) == 0 { + return nil + } + + return xml.Unmarshal(data, v) +} diff --git a/types/yaml.go b/types/yaml.go new file mode 100644 index 0000000..2b4b785 --- /dev/null +++ b/types/yaml.go @@ -0,0 +1,19 @@ +package types + +import ( + yaml "gopkg.in/yaml.v3" +) + +type YAMLStrategy struct{} + +func (y *YAMLStrategy) encode(n *Nesting) ([]byte, error) { + return yaml.Marshal(n) +} + +func (y *YAMLStrategy) decode(data []byte, v interface{}) error { + if len(data) == 0 { + return nil + } + + return yaml.Unmarshal(data, v) +}