diff --git a/core/handlers/v2/simulation_handler_test.go b/core/handlers/v2/simulation_handler_test.go index c5bc20d64..454ee35d6 100644 --- a/core/handlers/v2/simulation_handler_test.go +++ b/core/handlers/v2/simulation_handler_test.go @@ -385,7 +385,7 @@ func TestSimulationHandler_Put_ReturnsErrorIfJsonDoesntMatchSchema_MissingDataKe Expect(err).To(BeNil()) Expect(response.Result().StatusCode).To(Equal(400)) - Expect(errorView.Error).To(Equal("Invalid v3 simulation: [Error for : data is required]")) + Expect(errorView.Error).To(Equal("Invalid v3 simulation: [Error for <(root)>: data is required]")) } func TestSimulationHandler_Put_ReturnsErrorIfJsonDoesntMatchSchema_EmptyObject(t *testing.T) { diff --git a/core/handlers/v2/simulation_views_test.go b/core/handlers/v2/simulation_views_test.go index dd7f90eae..e7ed0e4ee 100644 --- a/core/handlers/v2/simulation_views_test.go +++ b/core/handlers/v2/simulation_views_test.go @@ -251,7 +251,7 @@ func Test_NewSimulationViewFromRequestBody_WontCreateSimulationFromInvalidV1Simu }`)) Expect(err).ToNot(BeNil()) - Expect(err.Error()).To(Equal("Invalid v1 simulation: [Error for : request is required; Error for : response is required]")) + Expect(err.Error()).To(Equal("Invalid v1 simulation: [Error for : request is required; Error for : response is required]")) Expect(simulation).ToNot(BeNil()) Expect(simulation.RequestResponsePairs).To(HaveLen(0)) diff --git a/go.mod b/go.mod index 6300fc1f8..596362607 100644 --- a/go.mod +++ b/go.mod @@ -5,73 +5,74 @@ go 1.22.10 require ( github.com/ChrisTrenkamp/xsel v0.9.16 github.com/SpectoLabs/goproxy v0.0.0-20240717215706-55e01f38b2c9 - github.com/SpectoLabs/goproxy/ext v0.0.0-20220724222243-c982a2c966ae + github.com/SpectoLabs/goproxy/ext v0.0.0-20240717215706-55e01f38b2c9 github.com/SpectoLabs/goxml2json v0.0.0-20240121223617-8e03292c14ea github.com/SpectoLabs/raymond v2.0.3-0.20240827093205-07f3a7bebd7d+incompatible github.com/antonholmquist/jason v1.0.1-0.20160829104012-962e09b85496 - github.com/beevik/etree v1.1.0 - github.com/boltdb/bolt v1.2.1-0.20160424201119-d97499360d1e - github.com/brianvoe/gofakeit/v6 v6.19.0 - github.com/codegangsta/negroni v0.1.1-0.20160503152438-24bf3506bb5e - github.com/dghubble/sling v1.2.0 - github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 + github.com/beevik/etree v1.4.1 + github.com/boltdb/bolt v1.3.1 + github.com/brianvoe/gofakeit/v6 v6.28.0 + github.com/codegangsta/negroni v1.0.0 + github.com/dghubble/sling v1.4.2 + github.com/dsnet/compress v0.0.1 github.com/go-zoo/bone v1.3.0 github.com/golang-jwt/jwt/v4 v4.5.1 - github.com/gorilla/mux v0.0.0-20160502175624-9c19ed558d5d - github.com/gorilla/websocket v1.4.2 - github.com/hashicorp/golang-lru v0.5.1 - github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 + github.com/gorilla/mux v1.8.1 + github.com/gorilla/websocket v1.5.3 + github.com/hashicorp/golang-lru v1.0.2 + github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0 github.com/jackwakefield/gopac v1.0.3-0.20180823145755-c4d2e0b9a672 - github.com/kardianos/osext v0.0.0-20151222153229-29ae4ffbc9a6 - github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 - github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a - github.com/onsi/ginkgo v1.16.4 - github.com/onsi/gomega v1.36.0 - github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 - github.com/phayes/freeport v0.0.0-20141201041908-e7681b376149 - github.com/rakyll/statik v0.1.1-0.20160322004535-2940084503a4 - github.com/rcrowley/go-metrics v0.0.0-20160226052904-eeba7bd0dd01 - github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 + github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 + github.com/mitchellh/go-homedir v1.1.0 + github.com/olekukonko/tablewriter v0.0.5 + github.com/onsi/ginkgo v1.16.5 + github.com/onsi/gomega v1.36.1 + github.com/pborman/uuid v1.2.1 + github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 + github.com/rakyll/statik v0.1.7 + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 + github.com/ryanuber/go-glob v1.0.0 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v0.0.0-20160517171929-f36824430130 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v0.0.0-20160508180713-d8a428b8a306 - github.com/tdewolff/minify/v2 v2.12.4 - github.com/xeipuuv/gojsonschema v0.0.0-20170225172124-ff0417f4272e - golang.org/x/crypto v0.29.0 - gonum.org/v1/gonum v0.7.0 + github.com/tdewolff/minify/v2 v2.21.2 + github.com/xeipuuv/gojsonschema v1.2.0 + golang.org/x/crypto v0.30.0 + gonum.org/v1/gonum v0.15.1 gopkg.in/yaml.v2 v2.4.0 - k8s.io/client-go v0.26.1 + k8s.io/client-go v0.31.3 ) require ( - github.com/BurntSushi/toml v1.2.1 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/aymerick/raymond v2.0.2+incompatible // indirect - github.com/corpix/uarand v0.0.0-20170903190822-2b8494104d86 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/corpix/uarand v0.2.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/goccmack/goutil v1.2.3 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 // indirect - github.com/gorilla/context v0.0.0-20160422134237-a8d44e7d8e4d // indirect - github.com/hashicorp/hcl v0.0.0-20160426221300-9a905a34e628 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/magiconair/properties v1.7.0 // indirect - github.com/mattn/go-runewidth v0.0.1 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.9 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/nxadm/tail v1.4.8 // indirect + github.com/nxadm/tail v1.4.11 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d // indirect - github.com/spf13/cast v0.0.0-20160314192028-27b586b42e29 // indirect - github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 // indirect - github.com/tdewolff/parse/v2 v2.6.4 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35 // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c // indirect - golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 // indirect - golang.org/x/net v0.31.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect - golang.org/x/text v0.20.0 // indirect - gonum.org/v1/netlib v0.0.0-20200317120129-c5a04cffd98a // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/robertkrimen/otto v0.5.1 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/tdewolff/parse/v2 v2.7.19 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 9b5dab9ef..e642821a7 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,11 @@ -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ChrisTrenkamp/xsel v0.9.16 h1:/rEkJMh14TEibqfY2fhG2r/UYCMr3aa0bufsG31IBjg= github.com/ChrisTrenkamp/xsel v0.9.16/go.mod h1:fDW9sVs8fwuiDmskzqybrIJ/RsI+vIspxe8G0AVg/+w= github.com/SpectoLabs/goproxy v0.0.0-20240717215706-55e01f38b2c9 h1:KLYZMZu6prwwPmCalgoE+ah7FxANPjMH9kERMN9TMfc= github.com/SpectoLabs/goproxy v0.0.0-20240717215706-55e01f38b2c9/go.mod h1:43+j4Hye/DLXHbJHM0O5dcwOkQp7zGCgDKTq6nzGXQM= -github.com/SpectoLabs/goproxy/ext v0.0.0-20220724222243-c982a2c966ae h1:3Qfw4yZArPnqymR+G9sHRNBXHbrtj84wXaj6+EGkBjs= -github.com/SpectoLabs/goproxy/ext v0.0.0-20220724222243-c982a2c966ae/go.mod h1:rnDN1CpKP9iJXwxRtnvM7d5wdPHQY0K5NkHeXWPlQ+o= +github.com/SpectoLabs/goproxy/ext v0.0.0-20240717215706-55e01f38b2c9 h1:O+R4cM+z0ftgq4SS3shT9x7JqCFvmQSKk0K8eATiDyE= +github.com/SpectoLabs/goproxy/ext v0.0.0-20240717215706-55e01f38b2c9/go.mod h1:itUI83WK8YFpzCbT9MsnCOWcvLUB2SaqXCrU8vwze5E= github.com/SpectoLabs/goxml2json v0.0.0-20240121223617-8e03292c14ea h1:VAu3xT0OShIqnm4K3TdPpxCd3k4uyXq/H6W76ueIWf0= github.com/SpectoLabs/goxml2json v0.0.0-20240121223617-8e03292c14ea/go.mod h1:P8Yk6l9gKxTfgnJeXVEQKCH7nGgvhNdeLs0zVs2h2KM= github.com/SpectoLabs/raymond v2.0.3-0.20240827093205-07f3a7bebd7d+incompatible h1:WQc9MpeneDjPv0utx7P5RmXPLfyWpbqXb+LiHK+hZxg= @@ -16,33 +15,36 @@ github.com/antonholmquist/jason v1.0.1-0.20160829104012-962e09b85496 h1:dESITduf github.com/antonholmquist/jason v1.0.1-0.20160829104012-962e09b85496/go.mod h1:+GxMEKI0Va2U8h3os6oiUAetHAlGMvxjdpAH/9uvUMA= github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= -github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= +github.com/beevik/etree v1.4.1 h1:PmQJDDYahBGNKDcpdX8uPy1xRCwoCGVUiW669MEirVI= +github.com/beevik/etree v1.4.1/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs= github.com/bitly/go-simplejson v0.5.1 h1:xgwPbetQScXt1gh9BmoJ6j9JMr3TElvuIyjR8pgdoow= github.com/bitly/go-simplejson v0.5.1/go.mod h1:YOPVLzCfwK14b4Sff3oP1AmGhI9T9Vsg84etUnlyp+Q= -github.com/boltdb/bolt v1.2.1-0.20160424201119-d97499360d1e h1:ZjpTXDvUplNMT6aktSoMffTkAGIQJGNGPQW/xL4kPwA= -github.com/boltdb/bolt v1.2.1-0.20160424201119-d97499360d1e/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/brianvoe/gofakeit/v6 v6.19.0 h1:g+yJ+meWVEsAmR+bV4mNM/eXI0N+0pZ3D+Mi+G5+YQo= -github.com/brianvoe/gofakeit/v6 v6.19.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= -github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= -github.com/codegangsta/negroni v0.1.1-0.20160503152438-24bf3506bb5e h1:2Ic1pGNC0EZvHLeWg8N2x3SDWACFj9PKRD4nqSoJzPA= -github.com/codegangsta/negroni v0.1.1-0.20160503152438-24bf3506bb5e/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= -github.com/corpix/uarand v0.0.0-20170903190822-2b8494104d86 h1:kRNlij/Yv/baHnXYdNqr+8ch5tLYAWS/VRaJ2ZvFgu0= -github.com/corpix/uarand v0.0.0-20170903190822-2b8494104d86/go.mod h1:JSm890tOkDN+M1jqN8pUGDKnzJrsVbJwSMHBY4zwz7M= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= +github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY= +github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= +github.com/corpix/uarand v0.2.0 h1:U98xXwud/AVuCpkpgfPF7J5TQgr7R5tqT8VZP5KWbzE= +github.com/corpix/uarand v0.2.0/go.mod h1:/3Z1QIqWkDIhf6XWn/08/uMHoQ8JUoTIKc2iPchBOmM= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dghubble/sling v1.2.0 h1:PYGS9ofwbV9nfhB1kYjB1vtXshMxlp2oQxTMMXVJ5pE= -github.com/dghubble/sling v1.2.0/go.mod h1:ZcPRuLm0qrcULW2gOrjXrAWgf76sahqSyxXyVOvkunE= -github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= -github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 h1:eX+pdPPlD279OWgdx7f6KqIRSONuK7egk+jDx7OM3Ac= -github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76/go.mod h1:KjxHHirfLaw19iGT70HvVjHQsL1vq1SRQB4yOsAfy2s= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dghubble/sling v1.4.2 h1:vs1HIGBbSl2SEALyU+irpYFLZMfc49Fp+jYryFebQjM= +github.com/dghubble/sling v1.4.2/go.mod h1:o0arCOz0HwfqYQJLrRtqunaWOn4X6jxE/6ORKRpVTD4= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= @@ -67,103 +69,122 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 h1:oERTZ1buOUYlpmKaqlO5fYmz8cZ1rYu5DieJzF4ZVmU= -github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/gorilla/context v0.0.0-20160422134237-a8d44e7d8e4d h1:BuwODXV4sNFjaSRNixz/sbmD1g/F3poPtHWxYTZE3C8= -github.com/gorilla/context v0.0.0-20160422134237-a8d44e7d8e4d/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v0.0.0-20160502175624-9c19ed558d5d h1:AegJdPZEQ6uNJobPN8BiOYffHTAyJyTlyhO7Hn33SHY= -github.com/gorilla/mux v0.0.0-20160502175624-9c19ed558d5d/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v0.0.0-20160426221300-9a905a34e628 h1:79lPy9LYAtihGQvcubOdkAol0FbhRAJ2BjXbiy8jDvM= -github.com/hashicorp/hcl v0.0.0-20160426221300-9a905a34e628/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0 h1:ufr2e4uIgz/Ft0RPudkFMyVrp77buvTFxqoDvwNGVSk= +github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackwakefield/gopac v1.0.3-0.20180823145755-c4d2e0b9a672 h1:8gMw+o9GKWC1Ml6pUbcdy3E1Nydvh6wasZiXmqKvYP4= github.com/jackwakefield/gopac v1.0.3-0.20180823145755-c4d2e0b9a672/go.mod h1:yR1sfJXcndScUFYPx7Xqxj7bkNlCWw9AMmuJFMHLXm8= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kardianos/osext v0.0.0-20151222153229-29ae4ffbc9a6 h1:yZAE+xNuc/2gmWV+s5UAb43LYLZQiqyngl6IUCQGJg0= -github.com/kardianos/osext v0.0.0-20151222153229-29ae4ffbc9a6/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= -github.com/magiconair/properties v1.7.0 h1:8Oygzd+nhiSWfp2XOwattyfEt36Q/F/99zQJy4axKdg= -github.com/magiconair/properties v1.7.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= -github.com/mattn/go-runewidth v0.0.1 h1:+EiaBVXhogb1Klb4tRJ7hYnuGK6PkKOZlK04D/GMOqk= -github.com/mattn/go-runewidth v0.0.1/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk= -github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a h1:m6hB6GkmZ/suOSKZM7yx3Yt+7iZ9HNfzacCykJqgXA8= -github.com/olekukonko/tablewriter v0.0.0-20170128050532-febf2d34b54a/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= -github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= -github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 h1:/CPgDYrfeK2LMK6xcUhvI17yO9SlpAdDIJGkhDEgO8A= -github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= -github.com/phayes/freeport v0.0.0-20141201041908-e7681b376149 h1:nU4ri+KRaSg4fOlRbGqaEHZ6tU84ZnrjHCqqq0em+VQ= -github.com/phayes/freeport v0.0.0-20141201041908-e7681b376149/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= +github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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/rakyll/statik v0.1.1-0.20160322004535-2940084503a4 h1:6UhUengh0GxTWyOCh8Qzam8cXzSgtrQD5dIMbo8qVqI= -github.com/rakyll/statik v0.1.1-0.20160322004535-2940084503a4/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= -github.com/rcrowley/go-metrics v0.0.0-20160226052904-eeba7bd0dd01 h1:XCHS0IhcFEQoiyKtFqXFRXgLKjcxOuyCDeeXPNb0T7o= -github.com/rcrowley/go-metrics v0.0.0-20160226052904-eeba7bd0dd01/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4= -github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= -github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= -github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE= -github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robertkrimen/otto v0.5.1 h1:avDI4ToRk8k1hppLdYFTuuzND41n37vPGJU7547dGf0= +github.com/robertkrimen/otto v0.5.1/go.mod h1:bS433I4Q9p+E5pZLu7r17vP6FkE6/wLxBdmKjoqJXF8= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cast v0.0.0-20160314192028-27b586b42e29 h1:Lgc6pP3ludnufG3ehP2WboB0IIKxlizm8NvXsI0/Z58= -github.com/spf13/cast v0.0.0-20160314192028-27b586b42e29/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.0-20160517171929-f36824430130 h1:FgjZIXM8t7/smwWZySOMSXVyrIACwJNdHMGvpdhXGCc= -github.com/spf13/cobra v0.0.0-20160517171929-f36824430130/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 h1:evyGXhHMrxKBDkdlSPv9HMWV2o53o+Ibhm28BGc0450= -github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v0.0.0-20160508180713-d8a428b8a306 h1:fvXBhJjS/jLG2A5yTggvllwqmgL4P6n6M9BKw1PIFmY= github.com/spf13/viper v0.0.0-20160508180713-d8a428b8a306/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/tdewolff/minify/v2 v2.12.4 h1:kejsHQMM17n6/gwdw53qsi6lg0TGddZADVyQOz1KMdE= -github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk= -github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZycQ= -github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= -github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM= -github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= -github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35 h1:0TnXeVP6mx+A4CBf8cQVkQfkhyGBQCmJcT4g6zKzm7M= -github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c h1:XZWnr3bsDQWAZg4Ne+cPoXRPILrNlPNQfxBuwLl43is= -github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20170225172124-ff0417f4272e h1:vhu5zToI4Rj62MgHj/UrrrM8RqNtKoCZUx8ARkpyzKA= -github.com/xeipuuv/gojsonschema v0.0.0-20170225172124-ff0417f4272e/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.21.2 h1:VfTvmGVtBYhMTlUAeHtXM7XOsW0JT/6uMwUPPqgUs9k= +github.com/tdewolff/minify/v2 v2.21.2/go.mod h1:Olje3eHdBnrMjINKffDsil/3NV98Iv7MhWf7556WQVg= +github.com/tdewolff/parse/v2 v2.7.19 h1:7Ljh26yj+gdLFEq/7q9LT4SYyKtwQX4ocNrj45UCePg= +github.com/tdewolff/parse/v2 v2.7.19/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -171,21 +192,18 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -195,8 +213,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -204,7 +222,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -214,51 +231,48 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw= -gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM= +gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= +gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20200317120129-c5a04cffd98a h1:y158/g9tKwBGw9gnNENlUIi9NTJCoiQg2RFB1gr9atQ= -gonum.org/v1/netlib v0.0.0-20200317120129-c5a04cffd98a/go.mod h1:6EVtvAMWMjOBOsTVX0xrjO4A6ULtEgWtAWHzqxDWdJs= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -268,8 +282,9 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -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/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= @@ -283,11 +298,6 @@ 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= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= -modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= -modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= -modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/vendor/github.com/BurntSushi/toml/README.md b/vendor/github.com/BurntSushi/toml/README.md index 3651cfa96..639e6c399 100644 --- a/vendor/github.com/BurntSushi/toml/README.md +++ b/vendor/github.com/BurntSushi/toml/README.md @@ -9,7 +9,7 @@ See the [releases page](https://github.com/BurntSushi/toml/releases) for a changelog; this information is also in the git tag annotations (e.g. `git show v0.4.0`). -This library requires Go 1.13 or newer; add it to your go.mod with: +This library requires Go 1.18 or newer; add it to your go.mod with: % go get github.com/BurntSushi/toml@latest diff --git a/vendor/github.com/BurntSushi/toml/decode.go b/vendor/github.com/BurntSushi/toml/decode.go index 0ca1dc4fe..7aaf462c9 100644 --- a/vendor/github.com/BurntSushi/toml/decode.go +++ b/vendor/github.com/BurntSushi/toml/decode.go @@ -6,7 +6,7 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" + "io/fs" "math" "os" "reflect" @@ -18,13 +18,13 @@ import ( // Unmarshaler is the interface implemented by objects that can unmarshal a // TOML description of themselves. type Unmarshaler interface { - UnmarshalTOML(interface{}) error + UnmarshalTOML(any) error } // Unmarshal decodes the contents of data in TOML format into a pointer v. // // See [Decoder] for a description of the decoding process. -func Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v any) error { _, err := NewDecoder(bytes.NewReader(data)).Decode(v) return err } @@ -32,12 +32,12 @@ func Unmarshal(data []byte, v interface{}) error { // Decode the TOML data in to the pointer v. // // See [Decoder] for a description of the decoding process. -func Decode(data string, v interface{}) (MetaData, error) { +func Decode(data string, v any) (MetaData, error) { return NewDecoder(strings.NewReader(data)).Decode(v) } // DecodeFile reads the contents of a file and decodes it with [Decode]. -func DecodeFile(path string, v interface{}) (MetaData, error) { +func DecodeFile(path string, v any) (MetaData, error) { fp, err := os.Open(path) if err != nil { return MetaData{}, err @@ -46,6 +46,17 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { return NewDecoder(fp).Decode(v) } +// DecodeFS reads the contents of a file from [fs.FS] and decodes it with +// [Decode]. +func DecodeFS(fsys fs.FS, path string, v any) (MetaData, error) { + fp, err := fsys.Open(path) + if err != nil { + return MetaData{}, err + } + defer fp.Close() + return NewDecoder(fp).Decode(v) +} + // Primitive is a TOML value that hasn't been decoded into a Go value. // // This type can be used for any value, which will cause decoding to be delayed. @@ -58,7 +69,7 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { // overhead of reflection. They can be useful when you don't know the exact type // of TOML data until runtime. type Primitive struct { - undecoded interface{} + undecoded any context Key } @@ -91,7 +102,7 @@ const ( // UnmarshalText method. See the Unmarshaler example for a demonstration with // email addresses. // -// ### Key mapping +// # Key mapping // // TOML keys can map to either keys in a Go map or field names in a Go struct. // The special `toml` struct tag can be used to map TOML keys to struct fields @@ -122,7 +133,7 @@ var ( ) // Decode TOML data in to the pointer `v`. -func (dec *Decoder) Decode(v interface{}) (MetaData, error) { +func (dec *Decoder) Decode(v any) (MetaData, error) { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr { s := "%q" @@ -136,8 +147,8 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v)) } - // Check if this is a supported type: struct, map, interface{}, or something - // that implements UnmarshalTOML or UnmarshalText. + // Check if this is a supported type: struct, map, any, or something that + // implements UnmarshalTOML or UnmarshalText. rv = indirect(rv) rt := rv.Type() if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map && @@ -148,7 +159,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { // TODO: parser should read from io.Reader? Or at the very least, make it // read from []byte rather than string - data, err := ioutil.ReadAll(dec.r) + data, err := io.ReadAll(dec.r) if err != nil { return MetaData{}, err } @@ -179,7 +190,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { // will only reflect keys that were decoded. Namely, any keys hidden behind a // Primitive will be considered undecoded. Executing this method will update the // undecoded keys in the meta data. (See the example.) -func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { +func (md *MetaData) PrimitiveDecode(primValue Primitive, v any) error { md.context = primValue.context defer func() { md.context = nil }() return md.unify(primValue.undecoded, rvalue(v)) @@ -190,7 +201,7 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { // // Any type mismatch produces an error. Finding a type that we don't know // how to handle produces an unsupported type error. -func (md *MetaData) unify(data interface{}, rv reflect.Value) error { +func (md *MetaData) unify(data any, rv reflect.Value) error { // Special case. Look for a `Primitive` value. // TODO: #76 would make this superfluous after implemented. if rv.Type() == primitiveType { @@ -207,7 +218,11 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { rvi := rv.Interface() if v, ok := rvi.(Unmarshaler); ok { - return v.UnmarshalTOML(data) + err := v.UnmarshalTOML(data) + if err != nil { + return md.parseErr(err) + } + return nil } if v, ok := rvi.(encoding.TextUnmarshaler); ok { return md.unifyText(data, v) @@ -227,14 +242,6 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return md.unifyInt(data, rv) } switch k { - case reflect.Ptr: - elem := reflect.New(rv.Type().Elem()) - err := md.unify(data, reflect.Indirect(elem)) - if err != nil { - return err - } - rv.Set(elem) - return nil case reflect.Struct: return md.unifyStruct(data, rv) case reflect.Map: @@ -248,7 +255,7 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { case reflect.Bool: return md.unifyBool(data, rv) case reflect.Interface: - if rv.NumMethod() > 0 { // Only support empty interfaces are supported. + if rv.NumMethod() > 0 { /// Only empty interfaces are supported. return md.e("unsupported type %s", rv.Type()) } return md.unifyAnything(data, rv) @@ -258,14 +265,13 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return md.e("unsupported type %s", rv.Kind()) } -func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { - tmap, ok := mapping.(map[string]interface{}) +func (md *MetaData) unifyStruct(mapping any, rv reflect.Value) error { + tmap, ok := mapping.(map[string]any) if !ok { if mapping == nil { return nil } - return md.e("type mismatch for %s: expected table but found %T", - rv.Type().String(), mapping) + return md.e("type mismatch for %s: expected table but found %s", rv.Type().String(), fmtType(mapping)) } for key, datum := range tmap { @@ -304,14 +310,14 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { +func (md *MetaData) unifyMap(mapping any, rv reflect.Value) error { keyType := rv.Type().Key().Kind() if keyType != reflect.String && keyType != reflect.Interface { return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)", keyType, rv.Type()) } - tmap, ok := mapping.(map[string]interface{}) + tmap, ok := mapping.(map[string]any) if !ok { if tmap == nil { return nil @@ -347,7 +353,7 @@ func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyArray(data any, rv reflect.Value) error { datav := reflect.ValueOf(data) if datav.Kind() != reflect.Slice { if !datav.IsValid() { @@ -361,7 +367,7 @@ func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { return md.unifySliceArray(datav, rv) } -func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifySlice(data any, rv reflect.Value) error { datav := reflect.ValueOf(data) if datav.Kind() != reflect.Slice { if !datav.IsValid() { @@ -388,7 +394,7 @@ func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { return nil } -func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyString(data any, rv reflect.Value) error { _, ok := rv.Interface().(json.Number) if ok { if i, ok := data.(int64); ok { @@ -408,7 +414,7 @@ func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { return md.badtype("string", data) } -func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyFloat64(data any, rv reflect.Value) error { rvk := rv.Kind() if num, ok := data.(float64); ok { @@ -429,7 +435,7 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { if num, ok := data.(int64); ok { if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) || (rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) { - return md.parseErr(errParseRange{i: num, size: rvk.String()}) + return md.parseErr(errUnsafeFloat{i: num, size: rvk.String()}) } rv.SetFloat(float64(num)) return nil @@ -438,7 +444,7 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { return md.badtype("float", data) } -func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyInt(data any, rv reflect.Value) error { _, ok := rv.Interface().(time.Duration) if ok { // Parse as string duration, and fall back to regular integer parsing @@ -481,7 +487,7 @@ func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { return nil } -func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyBool(data any, rv reflect.Value) error { if b, ok := data.(bool); ok { rv.SetBool(b) return nil @@ -489,12 +495,12 @@ func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { return md.badtype("boolean", data) } -func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { +func (md *MetaData) unifyAnything(data any, rv reflect.Value) error { rv.Set(reflect.ValueOf(data)) return nil } -func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error { +func (md *MetaData) unifyText(data any, v encoding.TextUnmarshaler) error { var s string switch sdata := data.(type) { case Marshaler: @@ -523,13 +529,13 @@ func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) erro return md.badtype("primitive (string-like)", data) } if err := v.UnmarshalText([]byte(s)); err != nil { - return err + return md.parseErr(err) } return nil } -func (md *MetaData) badtype(dst string, data interface{}) error { - return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst) +func (md *MetaData) badtype(dst string, data any) error { + return md.e("incompatible types: TOML value has type %s; destination has type %s", fmtType(data), dst) } func (md *MetaData) parseErr(err error) error { @@ -543,7 +549,7 @@ func (md *MetaData) parseErr(err error) error { } } -func (md *MetaData) e(format string, args ...interface{}) error { +func (md *MetaData) e(format string, args ...any) error { f := "toml: " if len(md.context) > 0 { f = fmt.Sprintf("toml: (last key %q): ", md.context) @@ -556,7 +562,7 @@ func (md *MetaData) e(format string, args ...interface{}) error { } // rvalue returns a reflect.Value of `v`. All pointers are resolved. -func rvalue(v interface{}) reflect.Value { +func rvalue(v any) reflect.Value { return indirect(reflect.ValueOf(v)) } @@ -600,3 +606,8 @@ func isUnifiable(rv reflect.Value) bool { } return false } + +// fmt %T with "interface {}" replaced with "any", which is far more readable. +func fmtType(t any) string { + return strings.ReplaceAll(fmt.Sprintf("%T", t), "interface {}", "any") +} diff --git a/vendor/github.com/BurntSushi/toml/decode_go116.go b/vendor/github.com/BurntSushi/toml/decode_go116.go deleted file mode 100644 index 086d0b686..000000000 --- a/vendor/github.com/BurntSushi/toml/decode_go116.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build go1.16 -// +build go1.16 - -package toml - -import ( - "io/fs" -) - -// DecodeFS reads the contents of a file from [fs.FS] and decodes it with -// [Decode]. -func DecodeFS(fsys fs.FS, path string, v interface{}) (MetaData, error) { - fp, err := fsys.Open(path) - if err != nil { - return MetaData{}, err - } - defer fp.Close() - return NewDecoder(fp).Decode(v) -} diff --git a/vendor/github.com/BurntSushi/toml/deprecated.go b/vendor/github.com/BurntSushi/toml/deprecated.go index c6af3f239..155709a80 100644 --- a/vendor/github.com/BurntSushi/toml/deprecated.go +++ b/vendor/github.com/BurntSushi/toml/deprecated.go @@ -5,17 +5,25 @@ import ( "io" ) +// TextMarshaler is an alias for encoding.TextMarshaler. +// // Deprecated: use encoding.TextMarshaler type TextMarshaler encoding.TextMarshaler +// TextUnmarshaler is an alias for encoding.TextUnmarshaler. +// // Deprecated: use encoding.TextUnmarshaler type TextUnmarshaler encoding.TextUnmarshaler +// DecodeReader is an alias for NewDecoder(r).Decode(v). +// +// Deprecated: use NewDecoder(reader).Decode(&value). +func DecodeReader(r io.Reader, v any) (MetaData, error) { return NewDecoder(r).Decode(v) } + +// PrimitiveDecode is an alias for MetaData.PrimitiveDecode(). +// // Deprecated: use MetaData.PrimitiveDecode. -func PrimitiveDecode(primValue Primitive, v interface{}) error { +func PrimitiveDecode(primValue Primitive, v any) error { md := MetaData{decoded: make(map[string]struct{})} return md.unify(primValue.undecoded, rvalue(v)) } - -// Deprecated: use NewDecoder(reader).Decode(&value). -func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) } diff --git a/vendor/github.com/BurntSushi/toml/doc.go b/vendor/github.com/BurntSushi/toml/doc.go index 81a7c0fe9..82c90a905 100644 --- a/vendor/github.com/BurntSushi/toml/doc.go +++ b/vendor/github.com/BurntSushi/toml/doc.go @@ -2,9 +2,6 @@ // // This package supports TOML v1.0.0, as specified at https://toml.io // -// There is also support for delaying decoding with the Primitive type, and -// querying the set of keys in a TOML document with the MetaData type. -// // The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator, // and can be used to verify if TOML document is valid. It can also be used to // print the type of each key. diff --git a/vendor/github.com/BurntSushi/toml/encode.go b/vendor/github.com/BurntSushi/toml/encode.go index 930e1d521..73366c0d9 100644 --- a/vendor/github.com/BurntSushi/toml/encode.go +++ b/vendor/github.com/BurntSushi/toml/encode.go @@ -2,6 +2,7 @@ package toml import ( "bufio" + "bytes" "encoding" "encoding/json" "errors" @@ -76,6 +77,17 @@ type Marshaler interface { MarshalTOML() ([]byte, error) } +// Marshal returns a TOML representation of the Go value. +// +// See [Encoder] for a description of the encoding process. +func Marshal(v any) ([]byte, error) { + buff := new(bytes.Buffer) + if err := NewEncoder(buff).Encode(v); err != nil { + return nil, err + } + return buff.Bytes(), nil +} + // Encoder encodes a Go to a TOML document. // // The mapping between Go values and TOML values should be precisely the same as @@ -115,28 +127,24 @@ type Marshaler interface { // NOTE: only exported keys are encoded due to the use of reflection. Unexported // keys are silently discarded. type Encoder struct { - // String to use for a single indentation level; default is two spaces. - Indent string - + Indent string // string for a single indentation level; default is two spaces. + hasWritten bool // written any output to w yet? w *bufio.Writer - hasWritten bool // written any output to w yet? } // NewEncoder create a new Encoder. func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - w: bufio.NewWriter(w), - Indent: " ", - } + return &Encoder{w: bufio.NewWriter(w), Indent: " "} } // Encode writes a TOML representation of the Go value to the [Encoder]'s writer. // // An error is returned if the value given cannot be encoded to a valid TOML // document. -func (enc *Encoder) Encode(v interface{}) error { +func (enc *Encoder) Encode(v any) error { rv := eindirect(reflect.ValueOf(v)) - if err := enc.safeEncode(Key([]string{}), rv); err != nil { + err := enc.safeEncode(Key([]string{}), rv) + if err != nil { return err } return enc.w.Flush() @@ -279,18 +287,30 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Float32: f := rv.Float() if math.IsNaN(f) { + if math.Signbit(f) { + enc.wf("-") + } enc.wf("nan") } else if math.IsInf(f, 0) { - enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)]) + if math.Signbit(f) { + enc.wf("-") + } + enc.wf("inf") } else { enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 32))) } case reflect.Float64: f := rv.Float() if math.IsNaN(f) { + if math.Signbit(f) { + enc.wf("-") + } enc.wf("nan") } else if math.IsInf(f, 0) { - enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)]) + if math.Signbit(f) { + enc.wf("-") + } + enc.wf("inf") } else { enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 64))) } @@ -303,7 +323,7 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Interface: enc.eElement(rv.Elem()) default: - encPanic(fmt.Errorf("unexpected type: %T", rv.Interface())) + encPanic(fmt.Errorf("unexpected type: %s", fmtType(rv.Interface()))) } } @@ -457,6 +477,16 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { frv := eindirect(rv.Field(i)) + if is32Bit { + // Copy so it works correct on 32bit archs; not clear why this + // is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4 + // This also works fine on 64bit, but 32bit archs are somewhat + // rare and this is a wee bit faster. + copyStart := make([]int, len(start)) + copy(copyStart, start) + start = copyStart + } + // Treat anonymous struct fields with tag names as though they are // not anonymous, like encoding/json does. // @@ -471,17 +501,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { if typeIsTable(tomlTypeOfGo(frv)) { fieldsSub = append(fieldsSub, append(start, f.Index...)) } else { - // Copy so it works correct on 32bit archs; not clear why this - // is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4 - // This also works fine on 64bit, but 32bit archs are somewhat - // rare and this is a wee bit faster. - if is32Bit { - copyStart := make([]int, len(start)) - copy(copyStart, start) - fieldsDirect = append(fieldsDirect, append(copyStart, f.Index...)) - } else { - fieldsDirect = append(fieldsDirect, append(start, f.Index...)) - } + fieldsDirect = append(fieldsDirect, append(start, f.Index...)) } } } @@ -490,24 +510,27 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { writeFields := func(fields [][]int) { for _, fieldIndex := range fields { fieldType := rt.FieldByIndex(fieldIndex) - fieldVal := eindirect(rv.FieldByIndex(fieldIndex)) + fieldVal := rv.FieldByIndex(fieldIndex) - if isNil(fieldVal) { /// Don't write anything for nil fields. + opts := getOptions(fieldType.Tag) + if opts.skip { + continue + } + if opts.omitempty && isEmpty(fieldVal) { continue } - opts := getOptions(fieldType.Tag) - if opts.skip { + fieldVal = eindirect(fieldVal) + + if isNil(fieldVal) { /// Don't write anything for nil fields. continue } + keyName := fieldType.Name if opts.name != "" { keyName = opts.name } - if opts.omitempty && enc.isEmpty(fieldVal) { - continue - } if opts.omitzero && isZero(fieldVal) { continue } @@ -649,7 +672,7 @@ func isZero(rv reflect.Value) bool { return false } -func (enc *Encoder) isEmpty(rv reflect.Value) bool { +func isEmpty(rv reflect.Value) bool { switch rv.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.String: return rv.Len() == 0 @@ -664,13 +687,15 @@ func (enc *Encoder) isEmpty(rv reflect.Value) bool { // type b struct{ s []string } // s := a{field: b{s: []string{"AAA"}}} for i := 0; i < rv.NumField(); i++ { - if !enc.isEmpty(rv.Field(i)) { + if !isEmpty(rv.Field(i)) { return false } } return true case reflect.Bool: return !rv.Bool() + case reflect.Ptr: + return rv.IsNil() } return false } @@ -693,8 +718,11 @@ func (enc *Encoder) newline() { // v v v v vv // key = {k = 1, k2 = 2} func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) { + /// Marshaler used on top-level document; call eElement() to just call + /// Marshal{TOML,Text}. if len(key) == 0 { - encPanic(errNoKey) + enc.eElement(val) + return } enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1)) enc.eElement(val) @@ -703,7 +731,7 @@ func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) { } } -func (enc *Encoder) wf(format string, v ...interface{}) { +func (enc *Encoder) wf(format string, v ...any) { _, err := fmt.Fprintf(enc.w, format, v...) if err != nil { encPanic(err) diff --git a/vendor/github.com/BurntSushi/toml/error.go b/vendor/github.com/BurntSushi/toml/error.go index f4f390e64..b45a3f45f 100644 --- a/vendor/github.com/BurntSushi/toml/error.go +++ b/vendor/github.com/BurntSushi/toml/error.go @@ -84,7 +84,7 @@ func (pe ParseError) Error() string { pe.Position.Line, pe.LastKey, msg) } -// ErrorWithUsage() returns the error with detailed location context. +// ErrorWithPosition returns the error with detailed location context. // // See the documentation on [ParseError]. func (pe ParseError) ErrorWithPosition() string { @@ -114,17 +114,26 @@ func (pe ParseError) ErrorWithPosition() string { msg, pe.Position.Line, col, col+pe.Position.Len) } if pe.Position.Line > 2 { - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, lines[pe.Position.Line-3]) + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3])) } if pe.Position.Line > 1 { - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, lines[pe.Position.Line-2]) + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, expandTab(lines[pe.Position.Line-2])) } - fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, lines[pe.Position.Line-1]) - fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col), strings.Repeat("^", pe.Position.Len)) + + /// Expand tabs, so that the ^^^s are at the correct position, but leave + /// "column 10-13" intact. Adjusting this to the visual column would be + /// better, but we don't know the tabsize of the user in their editor, which + /// can be 8, 4, 2, or something else. We can't know. So leaving it as the + /// character index is probably the "most correct". + expanded := expandTab(lines[pe.Position.Line-1]) + diff := len(expanded) - len(lines[pe.Position.Line-1]) + + fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded) + fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col+diff), strings.Repeat("^", pe.Position.Len)) return b.String() } -// ErrorWithUsage() returns the error with detailed location context and usage +// ErrorWithUsage returns the error with detailed location context and usage // guidance. // // See the documentation on [ParseError]. @@ -159,17 +168,47 @@ func (pe ParseError) column(lines []string) int { return col } +func expandTab(s string) string { + var ( + b strings.Builder + l int + fill = func(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = ' ' + } + return string(b) + } + ) + b.Grow(len(s)) + for _, r := range s { + switch r { + case '\t': + tw := 8 - l%8 + b.WriteString(fill(tw)) + l += tw + default: + b.WriteRune(r) + l += 1 + } + } + return b.String() +} + type ( errLexControl struct{ r rune } errLexEscape struct{ r rune } errLexUTF8 struct{ b byte } - errLexInvalidNum struct{ v string } - errLexInvalidDate struct{ v string } + errParseDate struct{ v string } errLexInlineTableNL struct{} errLexStringNL struct{} errParseRange struct { - i interface{} // int or float - size string // "int64", "uint16", etc. + i any // int or float + size string // "int64", "uint16", etc. + } + errUnsafeFloat struct { + i interface{} // float32 or float64 + size string // "float32" or "float64" } errParseDuration struct{ d string } ) @@ -183,18 +222,20 @@ func (e errLexEscape) Error() string { return fmt.Sprintf(`invalid escape func (e errLexEscape) Usage() string { return usageEscape } func (e errLexUTF8) Error() string { return fmt.Sprintf("invalid UTF-8 byte: 0x%02x", e.b) } func (e errLexUTF8) Usage() string { return "" } -func (e errLexInvalidNum) Error() string { return fmt.Sprintf("invalid number: %q", e.v) } -func (e errLexInvalidNum) Usage() string { return "" } -func (e errLexInvalidDate) Error() string { return fmt.Sprintf("invalid date: %q", e.v) } -func (e errLexInvalidDate) Usage() string { return "" } +func (e errParseDate) Error() string { return fmt.Sprintf("invalid datetime: %q", e.v) } +func (e errParseDate) Usage() string { return usageDate } func (e errLexInlineTableNL) Error() string { return "newlines not allowed within inline tables" } func (e errLexInlineTableNL) Usage() string { return usageInlineNewline } func (e errLexStringNL) Error() string { return "strings cannot contain newlines" } func (e errLexStringNL) Usage() string { return usageStringNewline } func (e errParseRange) Error() string { return fmt.Sprintf("%v is out of range for %s", e.i, e.size) } func (e errParseRange) Usage() string { return usageIntOverflow } -func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } -func (e errParseDuration) Usage() string { return usageDuration } +func (e errUnsafeFloat) Error() string { + return fmt.Sprintf("%v is out of the safe %s range", e.i, e.size) +} +func (e errUnsafeFloat) Usage() string { return usageUnsafeFloat } +func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } +func (e errParseDuration) Usage() string { return usageDuration } const usageEscape = ` A '\' inside a "-delimited string is interpreted as an escape character. @@ -251,19 +292,35 @@ bug in the program that uses too small of an integer. The maximum and minimum values are: size │ lowest │ highest - ───────┼────────────────┼────────── + ───────┼────────────────┼────────────── int8 │ -128 │ 127 int16 │ -32,768 │ 32,767 int32 │ -2,147,483,648 │ 2,147,483,647 int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷ uint8 │ 0 │ 255 - uint16 │ 0 │ 65535 - uint32 │ 0 │ 4294967295 + uint16 │ 0 │ 65,535 + uint32 │ 0 │ 4,294,967,295 uint64 │ 0 │ 1.8 × 10¹⁸ int refers to int32 on 32-bit systems and int64 on 64-bit systems. ` +const usageUnsafeFloat = ` +This number is outside of the "safe" range for floating point numbers; whole +(non-fractional) numbers outside the below range can not always be represented +accurately in a float, leading to some loss of accuracy. + +Explicitly mark a number as a fractional unit by adding ".0", which will incur +some loss of accuracy; for example: + + f = 2_000_000_000.0 + +Accuracy ranges: + + float32 = 16,777,215 + float64 = 9,007,199,254,740,991 +` + const usageDuration = ` A duration must be as "number", without any spaces. Valid units are: @@ -277,3 +334,23 @@ A duration must be as "number", without any spaces. Valid units are: You can combine multiple units; for example "5m10s" for 5 minutes and 10 seconds. ` + +const usageDate = ` +A TOML datetime must be in one of the following formats: + + 2006-01-02T15:04:05Z07:00 Date and time, with timezone. + 2006-01-02T15:04:05 Date and time, but without timezone. + 2006-01-02 Date without a time or timezone. + 15:04:05 Just a time, without any timezone. + +Seconds may optionally have a fraction, up to nanosecond precision: + + 15:04:05.123 + 15:04:05.856018510 +` + +// TOML 1.1: +// The seconds part in times is optional, and may be omitted: +// 2006-01-02T15:04Z07:00 +// 2006-01-02T15:04 +// 15:04 diff --git a/vendor/github.com/BurntSushi/toml/lex.go b/vendor/github.com/BurntSushi/toml/lex.go index d4d70871d..a1016d98a 100644 --- a/vendor/github.com/BurntSushi/toml/lex.go +++ b/vendor/github.com/BurntSushi/toml/lex.go @@ -17,6 +17,7 @@ const ( itemEOF itemText itemString + itemStringEsc itemRawString itemMultilineString itemRawMultilineString @@ -46,12 +47,14 @@ func (p Position) String() string { } type lexer struct { - input string - start int - pos int - line int - state stateFn - items chan item + input string + start int + pos int + line int + state stateFn + items chan item + tomlNext bool + esc bool // Allow for backing up up to 4 runes. This is necessary because TOML // contains 3-rune tokens (""" and '''). @@ -87,13 +90,14 @@ func (lx *lexer) nextItem() item { } } -func lex(input string) *lexer { +func lex(input string, tomlNext bool) *lexer { lx := &lexer{ - input: input, - state: lexTop, - items: make(chan item, 10), - stack: make([]stateFn, 0, 10), - line: 1, + input: input, + state: lexTop, + items: make(chan item, 10), + stack: make([]stateFn, 0, 10), + line: 1, + tomlNext: tomlNext, } return lx } @@ -162,7 +166,7 @@ func (lx *lexer) next() (r rune) { } r, w := utf8.DecodeRuneInString(lx.input[lx.pos:]) - if r == utf8.RuneError { + if r == utf8.RuneError && w == 1 { lx.error(errLexUTF8{lx.input[lx.pos]}) return utf8.RuneError } @@ -268,7 +272,7 @@ func (lx *lexer) errorPos(start, length int, err error) stateFn { } // errorf is like error, and creates a new error. -func (lx *lexer) errorf(format string, values ...interface{}) stateFn { +func (lx *lexer) errorf(format string, values ...any) stateFn { if lx.atEOF { pos := lx.getPos() pos.Line-- @@ -331,9 +335,7 @@ func lexTopEnd(lx *lexer) stateFn { lx.emit(itemEOF) return nil } - return lx.errorf( - "expected a top-level item to end with a newline, comment, or EOF, but got %q instead", - r) + return lx.errorf("expected a top-level item to end with a newline, comment, or EOF, but got %q instead", r) } // lexTable lexes the beginning of a table. Namely, it makes sure that @@ -408,7 +410,7 @@ func lexTableNameEnd(lx *lexer) stateFn { // Lexes only one part, e.g. only 'a' inside 'a.b'. func lexBareName(lx *lexer) stateFn { r := lx.next() - if isBareKeyChar(r) { + if isBareKeyChar(r, lx.tomlNext) { return lexBareName } lx.backup() @@ -618,6 +620,9 @@ func lexInlineTableValue(lx *lexer) stateFn { case isWhitespace(r): return lexSkip(lx, lexInlineTableValue) case isNL(r): + if lx.tomlNext { + return lexSkip(lx, lexInlineTableValue) + } return lx.errorPrevLine(errLexInlineTableNL{}) case r == '#': lx.push(lexInlineTableValue) @@ -640,6 +645,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn { case isWhitespace(r): return lexSkip(lx, lexInlineTableValueEnd) case isNL(r): + if lx.tomlNext { + return lexSkip(lx, lexInlineTableValueEnd) + } return lx.errorPrevLine(errLexInlineTableNL{}) case r == '#': lx.push(lexInlineTableValueEnd) @@ -648,6 +656,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn { lx.ignore() lx.skip(isWhitespace) if lx.peek() == '}' { + if lx.tomlNext { + return lexInlineTableValueEnd + } return lx.errorf("trailing comma not allowed in inline tables") } return lexInlineTableValue @@ -687,7 +698,12 @@ func lexString(lx *lexer) stateFn { return lexStringEscape case r == '"': lx.backup() - lx.emit(itemString) + if lx.esc { + lx.esc = false + lx.emit(itemStringEsc) + } else { + lx.emit(itemString) + } lx.next() lx.ignore() return lx.pop() @@ -737,6 +753,7 @@ func lexMultilineString(lx *lexer) stateFn { lx.backup() /// backup: don't include the """ in the item. lx.backup() lx.backup() + lx.esc = false lx.emit(itemMultilineString) lx.next() /// Read over ''' again and discard it. lx.next() @@ -770,8 +787,8 @@ func lexRawString(lx *lexer) stateFn { } } -// lexMultilineRawString consumes a raw string. Nothing can be escaped in such -// a string. It assumes that the beginning ''' has already been consumed and +// lexMultilineRawString consumes a raw string. Nothing can be escaped in such a +// string. It assumes that the beginning triple-' has already been consumed and // ignored. func lexMultilineRawString(lx *lexer) stateFn { r := lx.next() @@ -826,8 +843,14 @@ func lexMultilineStringEscape(lx *lexer) stateFn { } func lexStringEscape(lx *lexer) stateFn { + lx.esc = true r := lx.next() switch r { + case 'e': + if !lx.tomlNext { + return lx.error(errLexEscape{r}) + } + fallthrough case 'b': fallthrough case 't': @@ -846,6 +869,11 @@ func lexStringEscape(lx *lexer) stateFn { fallthrough case '\\': return lx.pop() + case 'x': + if !lx.tomlNext { + return lx.error(errLexEscape{r}) + } + return lexHexEscape case 'u': return lexShortUnicodeEscape case 'U': @@ -854,14 +882,23 @@ func lexStringEscape(lx *lexer) stateFn { return lx.error(errLexEscape{r}) } +func lexHexEscape(lx *lexer) stateFn { + var r rune + for i := 0; i < 2; i++ { + r = lx.next() + if !isHex(r) { + return lx.errorf(`expected two hexadecimal digits after '\x', but got %q instead`, lx.current()) + } + } + return lx.pop() +} + func lexShortUnicodeEscape(lx *lexer) stateFn { var r rune for i := 0; i < 4; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected four hexadecimal digits after '\u', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected four hexadecimal digits after '\u', but got %q instead`, lx.current()) } } return lx.pop() @@ -871,10 +908,8 @@ func lexLongUnicodeEscape(lx *lexer) stateFn { var r rune for i := 0; i < 8; i++ { r = lx.next() - if !isHexadecimal(r) { - return lx.errorf( - `expected eight hexadecimal digits after '\U', but got %q instead`, - lx.current()) + if !isHex(r) { + return lx.errorf(`expected eight hexadecimal digits after '\U', but got %q instead`, lx.current()) } } return lx.pop() @@ -941,7 +976,7 @@ func lexDatetime(lx *lexer) stateFn { // lexHexInteger consumes a hexadecimal integer after seeing the '0x' prefix. func lexHexInteger(lx *lexer) stateFn { r := lx.next() - if isHexadecimal(r) { + if isHex(r) { return lexHexInteger } switch r { @@ -1075,7 +1110,7 @@ func lexBaseNumberOrDate(lx *lexer) stateFn { return lexOctalInteger case 'x': r = lx.peek() - if !isHexadecimal(r) { + if !isHex(r) { lx.errorf("not a hexidecimal number: '%s%c'", lx.current(), r) } return lexHexInteger @@ -1173,7 +1208,7 @@ func (itype itemType) String() string { return "EOF" case itemText: return "Text" - case itemString, itemRawString, itemMultilineString, itemRawMultilineString: + case itemString, itemStringEsc, itemRawString, itemMultilineString, itemRawMultilineString: return "String" case itemBool: return "Bool" @@ -1206,7 +1241,7 @@ func (itype itemType) String() string { } func (item item) String() string { - return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) + return fmt.Sprintf("(%s, %s)", item.typ, item.val) } func isWhitespace(r rune) bool { return r == '\t' || r == ' ' } @@ -1222,10 +1257,23 @@ func isControl(r rune) bool { // Control characters except \t, \r, \n func isDigit(r rune) bool { return r >= '0' && r <= '9' } func isBinary(r rune) bool { return r == '0' || r == '1' } func isOctal(r rune) bool { return r >= '0' && r <= '7' } -func isHexadecimal(r rune) bool { - return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F') -} -func isBareKeyChar(r rune) bool { +func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') } +func isBareKeyChar(r rune, tomlNext bool) bool { + if tomlNext { + return (r >= 'A' && r <= 'Z') || + (r >= 'a' && r <= 'z') || + (r >= '0' && r <= '9') || + r == '_' || r == '-' || + r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) || + (r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) || + (r >= 0x037f && r <= 0x1fff) || + (r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) || + (r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) || + (r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) || + (r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) || + (r >= 0x10000 && r <= 0xeffff) + } + return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || diff --git a/vendor/github.com/BurntSushi/toml/meta.go b/vendor/github.com/BurntSushi/toml/meta.go index 71847a041..e61453730 100644 --- a/vendor/github.com/BurntSushi/toml/meta.go +++ b/vendor/github.com/BurntSushi/toml/meta.go @@ -13,7 +13,7 @@ type MetaData struct { context Key // Used only during decoding. keyInfo map[string]keyInfo - mapping map[string]interface{} + mapping map[string]any keys []Key decoded map[string]struct{} data []byte // Input file; for errors. @@ -31,12 +31,12 @@ func (md *MetaData) IsDefined(key ...string) bool { } var ( - hash map[string]interface{} + hash map[string]any ok bool - hashOrVal interface{} = md.mapping + hashOrVal any = md.mapping ) for _, k := range key { - if hash, ok = hashOrVal.(map[string]interface{}); !ok { + if hash, ok = hashOrVal.(map[string]any); !ok { return false } if hashOrVal, ok = hash[k]; !ok { @@ -94,28 +94,55 @@ func (md *MetaData) Undecoded() []Key { type Key []string func (k Key) String() string { - ss := make([]string, len(k)) - for i := range k { - ss[i] = k.maybeQuoted(i) + // This is called quite often, so it's a bit funky to make it faster. + var b strings.Builder + b.Grow(len(k) * 25) +outer: + for i, kk := range k { + if i > 0 { + b.WriteByte('.') + } + if kk == "" { + b.WriteString(`""`) + } else { + for _, r := range kk { + // "Inline" isBareKeyChar + if !((r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' || r == '-') { + b.WriteByte('"') + b.WriteString(dblQuotedReplacer.Replace(kk)) + b.WriteByte('"') + continue outer + } + } + b.WriteString(kk) + } } - return strings.Join(ss, ".") + return b.String() } func (k Key) maybeQuoted(i int) string { if k[i] == "" { return `""` } - for _, c := range k[i] { - if !isBareKeyChar(c) { - return `"` + dblQuotedReplacer.Replace(k[i]) + `"` + for _, r := range k[i] { + if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '_' || r == '-' { + continue } + return `"` + dblQuotedReplacer.Replace(k[i]) + `"` } return k[i] } +// Like append(), but only increase the cap by 1. func (k Key) add(piece string) Key { + if cap(k) > len(k) { + return append(k, piece) + } newKey := make(Key, len(k)+1) copy(newKey, k) newKey[len(k)] = piece return newKey } + +func (k Key) parent() Key { return k[:len(k)-1] } // all except the last piece. +func (k Key) last() string { return k[len(k)-1] } // last piece of this key. diff --git a/vendor/github.com/BurntSushi/toml/parse.go b/vendor/github.com/BurntSushi/toml/parse.go index d2542d6f9..11ac3108b 100644 --- a/vendor/github.com/BurntSushi/toml/parse.go +++ b/vendor/github.com/BurntSushi/toml/parse.go @@ -2,6 +2,8 @@ package toml import ( "fmt" + "math" + "os" "strconv" "strings" "time" @@ -15,12 +17,13 @@ type parser struct { context Key // Full key for the current hash in scope. currentKey string // Base key name for everything except hashes. pos Position // Current position in the TOML file. + tomlNext bool ordered []Key // List of keys in the order that they appear in the TOML data. - keyInfo map[string]keyInfo // Map keyname → info about the TOML key. - mapping map[string]interface{} // Map keyname → key value. - implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). + keyInfo map[string]keyInfo // Map keyname → info about the TOML key. + mapping map[string]any // Map keyname → key value. + implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). } type keyInfo struct { @@ -29,6 +32,8 @@ type keyInfo struct { } func parse(data string) (p *parser, err error) { + _, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110") + defer func() { if r := recover(); r != nil { if pErr, ok := r.(ParseError); ok { @@ -41,9 +46,13 @@ func parse(data string) (p *parser, err error) { }() // Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString() - // which mangles stuff. - if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { + // which mangles stuff. UTF-16 BOM isn't strictly valid, but some tools add + // it anyway. + if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16 data = data[2:] + //lint:ignore S1017 https://github.com/dominikh/go-tools/issues/1447 + } else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8 + data = data[3:] } // Examine first few bytes for NULL bytes; this probably means it's a UTF-16 @@ -64,10 +73,11 @@ func parse(data string) (p *parser, err error) { p = &parser{ keyInfo: make(map[string]keyInfo), - mapping: make(map[string]interface{}), - lx: lex(data), + mapping: make(map[string]any), + lx: lex(data, tomlNext), ordered: make([]Key, 0), implicits: make(map[string]struct{}), + tomlNext: tomlNext, } for { item := p.next() @@ -89,7 +99,7 @@ func (p *parser) panicErr(it item, err error) { }) } -func (p *parser) panicItemf(it item, format string, v ...interface{}) { +func (p *parser) panicItemf(it item, format string, v ...any) { panic(ParseError{ Message: fmt.Sprintf(format, v...), Position: it.pos, @@ -98,7 +108,7 @@ func (p *parser) panicItemf(it item, format string, v ...interface{}) { }) } -func (p *parser) panicf(format string, v ...interface{}) { +func (p *parser) panicf(format string, v ...any) { panic(ParseError{ Message: fmt.Sprintf(format, v...), Position: p.pos, @@ -131,7 +141,7 @@ func (p *parser) nextPos() item { return it } -func (p *parser) bug(format string, v ...interface{}) { +func (p *parser) bug(format string, v ...any) { panic(fmt.Sprintf("BUG: "+format+"\n\n", v...)) } @@ -186,20 +196,21 @@ func (p *parser) topLevel(item item) { p.assertEqual(itemKeyEnd, k.typ) /// The current key is the last part. - p.currentKey = key[len(key)-1] + p.currentKey = key.last() /// All the other parts (if any) are the context; need to set each part /// as implicit. - context := key[:len(key)-1] + context := key.parent() for i := range context { p.addImplicitContext(append(p.context, context[i:i+1]...)) } + p.ordered = append(p.ordered, p.context.add(p.currentKey)) /// Set value. vItem := p.next() val, typ := p.value(vItem, false) - p.set(p.currentKey, val, typ, vItem.pos) - p.ordered = append(p.ordered, p.context.add(p.currentKey)) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ, vItem.pos) /// Remove the context we added (preserving any context from [tbl] lines). p.context = outerContext @@ -214,7 +225,7 @@ func (p *parser) keyString(it item) string { switch it.typ { case itemText: return it.val - case itemString, itemMultilineString, + case itemString, itemStringEsc, itemMultilineString, itemRawString, itemRawMultilineString: s, _ := p.value(it, false) return s.(string) @@ -231,12 +242,14 @@ var datetimeRepl = strings.NewReplacer( // value translates an expected value from the lexer into a Go value wrapped // as an empty interface. -func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { +func (p *parser) value(it item, parentIsArray bool) (any, tomlType) { switch it.typ { case itemString: + return it.val, p.typeOfPrimitive(it) + case itemStringEsc: return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it) case itemMultilineString: - return p.replaceEscapes(it, stripFirstNewline(p.stripEscapedNewlines(it.val))), p.typeOfPrimitive(it) + return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it) case itemRawString: return it.val, p.typeOfPrimitive(it) case itemRawMultilineString: @@ -266,7 +279,7 @@ func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { panic("unreachable") } -func (p *parser) valueInteger(it item) (interface{}, tomlType) { +func (p *parser) valueInteger(it item) (any, tomlType) { if !numUnderscoresOK(it.val) { p.panicItemf(it, "Invalid integer %q: underscores must be surrounded by digits", it.val) } @@ -290,7 +303,7 @@ func (p *parser) valueInteger(it item) (interface{}, tomlType) { return num, p.typeOfPrimitive(it) } -func (p *parser) valueFloat(it item) (interface{}, tomlType) { +func (p *parser) valueFloat(it item) (any, tomlType) { parts := strings.FieldsFunc(it.val, func(r rune) bool { switch r { case '.', 'e', 'E': @@ -314,7 +327,9 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { p.panicItemf(it, "Invalid float %q: '.' must be followed by one or more digits", it.val) } val := strings.Replace(it.val, "_", "", -1) - if val == "+nan" || val == "-nan" { // Go doesn't support this, but TOML spec does. + signbit := false + if val == "+nan" || val == "-nan" { + signbit = val == "-nan" val = "nan" } num, err := strconv.ParseFloat(val, 64) @@ -325,20 +340,29 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { p.panicItemf(it, "Invalid float value: %q", it.val) } } + if signbit { + num = math.Copysign(num, -1) + } return num, p.typeOfPrimitive(it) } var dtTypes = []struct { fmt string zone *time.Location + next bool }{ - {time.RFC3339Nano, time.Local}, - {"2006-01-02T15:04:05.999999999", internal.LocalDatetime}, - {"2006-01-02", internal.LocalDate}, - {"15:04:05.999999999", internal.LocalTime}, + {time.RFC3339Nano, time.Local, false}, + {"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false}, + {"2006-01-02", internal.LocalDate, false}, + {"15:04:05.999999999", internal.LocalTime, false}, + + // tomlNext + {"2006-01-02T15:04Z07:00", time.Local, true}, + {"2006-01-02T15:04", internal.LocalDatetime, true}, + {"15:04", internal.LocalTime, true}, } -func (p *parser) valueDatetime(it item) (interface{}, tomlType) { +func (p *parser) valueDatetime(it item) (any, tomlType) { it.val = datetimeRepl.Replace(it.val) var ( t time.Time @@ -346,28 +370,49 @@ func (p *parser) valueDatetime(it item) (interface{}, tomlType) { err error ) for _, dt := range dtTypes { + if dt.next && !p.tomlNext { + continue + } t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone) if err == nil { + if missingLeadingZero(it.val, dt.fmt) { + p.panicErr(it, errParseDate{it.val}) + } ok = true break } } if !ok { - p.panicItemf(it, "Invalid TOML Datetime: %q.", it.val) + p.panicErr(it, errParseDate{it.val}) } return t, p.typeOfPrimitive(it) } -func (p *parser) valueArray(it item) (interface{}, tomlType) { +// Go's time.Parse() will accept numbers without a leading zero; there isn't any +// way to require it. https://github.com/golang/go/issues/29911 +// +// Depend on the fact that the separators (- and :) should always be at the same +// location. +func missingLeadingZero(d, l string) bool { + for i, c := range []byte(l) { + if c == '.' || c == 'Z' { + return false + } + if (c < '0' || c > '9') && d[i] != c { + return true + } + } + return false +} + +func (p *parser) valueArray(it item) (any, tomlType) { p.setType(p.currentKey, tomlArray, it.pos) var ( - types []tomlType - - // Initialize to a non-nil empty slice. This makes it consistent with - // how S = [] decodes into a non-nil slice inside something like struct - // { S []string }. See #338 - array = []interface{}{} + // Initialize to a non-nil slice to make it consistent with how S = [] + // decodes into a non-nil slice inside something like struct { S + // []string }. See #338 + array = make([]any, 0, 2) ) for it = p.next(); it.typ != itemArrayEnd; it = p.next() { if it.typ == itemCommentStart { @@ -377,20 +422,20 @@ func (p *parser) valueArray(it item) (interface{}, tomlType) { val, typ := p.value(it, true) array = append(array, val) - types = append(types, typ) - // XXX: types isn't used here, we need it to record the accurate type + // XXX: type isn't used here, we need it to record the accurate type // information. // // Not entirely sure how to best store this; could use "key[0]", // "key[1]" notation, or maybe store it on the Array type? + _ = typ } return array, tomlArray } -func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tomlType) { +func (p *parser) valueInlineTable(it item, parentIsArray bool) (any, tomlType) { var ( - hash = make(map[string]interface{}) + topHash = make(map[string]any) outerContext = p.context outerKey = p.currentKey ) @@ -418,19 +463,33 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom p.assertEqual(itemKeyEnd, k.typ) /// The current key is the last part. - p.currentKey = key[len(key)-1] + p.currentKey = key.last() /// All the other parts (if any) are the context; need to set each part /// as implicit. - context := key[:len(key)-1] + context := key.parent() for i := range context { p.addImplicitContext(append(p.context, context[i:i+1]...)) } + p.ordered = append(p.ordered, p.context.add(p.currentKey)) /// Set the value. val, typ := p.value(p.next(), false) - p.set(p.currentKey, val, typ, it.pos) - p.ordered = append(p.ordered, p.context.add(p.currentKey)) + p.setValue(p.currentKey, val) + p.setType(p.currentKey, typ, it.pos) + + hash := topHash + for _, c := range context { + h, ok := hash[c] + if !ok { + h = make(map[string]any) + hash[c] = h + } + hash, ok = h.(map[string]any) + if !ok { + p.panicf("%q is not a table", p.context) + } + } hash[p.currentKey] = val /// Restore context. @@ -438,7 +497,7 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom } p.context = outerContext p.currentKey = outerKey - return hash, tomlHash + return topHash, tomlHash } // numHasLeadingZero checks if this number has leading zeroes, allowing for '0', @@ -468,9 +527,9 @@ func numUnderscoresOK(s string) bool { } } - // isHexadecimal is a superset of all the permissable characters - // surrounding an underscore. - accept = isHexadecimal(r) + // isHexis a superset of all the permissable characters surrounding an + // underscore. + accept = isHex(r) } return accept } @@ -493,21 +552,19 @@ func numPeriodsOK(s string) bool { // Establishing the context also makes sure that the key isn't a duplicate, and // will create implicit hashes automatically. func (p *parser) addContext(key Key, array bool) { - var ok bool - - // Always start at the top level and drill down for our context. + /// Always start at the top level and drill down for our context. hashContext := p.mapping - keyContext := make(Key, 0) + keyContext := make(Key, 0, len(key)-1) - // We only need implicit hashes for key[0:-1] - for _, k := range key[0 : len(key)-1] { - _, ok = hashContext[k] + /// We only need implicit hashes for the parents. + for _, k := range key.parent() { + _, ok := hashContext[k] keyContext = append(keyContext, k) // No key? Make an implicit hash and move on. if !ok { p.addImplicit(keyContext) - hashContext[k] = make(map[string]interface{}) + hashContext[k] = make(map[string]any) } // If the hash context is actually an array of tables, then set @@ -516,9 +573,9 @@ func (p *parser) addContext(key Key, array bool) { // Otherwise, it better be a table, since this MUST be a key group (by // virtue of it not being the last element in a key). switch t := hashContext[k].(type) { - case []map[string]interface{}: + case []map[string]any: hashContext = t[len(t)-1] - case map[string]interface{}: + case map[string]any: hashContext = t default: p.panicf("Key '%s' was already created as a hash.", keyContext) @@ -529,40 +586,33 @@ func (p *parser) addContext(key Key, array bool) { if array { // If this is the first element for this array, then allocate a new // list of tables for it. - k := key[len(key)-1] + k := key.last() if _, ok := hashContext[k]; !ok { - hashContext[k] = make([]map[string]interface{}, 0, 4) + hashContext[k] = make([]map[string]any, 0, 4) } // Add a new table. But make sure the key hasn't already been used // for something else. - if hash, ok := hashContext[k].([]map[string]interface{}); ok { - hashContext[k] = append(hash, make(map[string]interface{})) + if hash, ok := hashContext[k].([]map[string]any); ok { + hashContext[k] = append(hash, make(map[string]any)) } else { p.panicf("Key '%s' was already created and cannot be used as an array.", key) } } else { - p.setValue(key[len(key)-1], make(map[string]interface{})) + p.setValue(key.last(), make(map[string]any)) } - p.context = append(p.context, key[len(key)-1]) -} - -// set calls setValue and setType. -func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) { - p.setValue(key, val) - p.setType(key, typ, pos) - + p.context = append(p.context, key.last()) } // setValue sets the given key to the given value in the current context. // It will make sure that the key hasn't already been defined, account for // implicit key groups. -func (p *parser) setValue(key string, value interface{}) { +func (p *parser) setValue(key string, value any) { var ( - tmpHash interface{} + tmpHash any ok bool hash = p.mapping - keyContext Key + keyContext = make(Key, 0, len(p.context)+1) ) for _, k := range p.context { keyContext = append(keyContext, k) @@ -570,11 +620,11 @@ func (p *parser) setValue(key string, value interface{}) { p.bug("Context for key '%s' has not been established.", keyContext) } switch t := tmpHash.(type) { - case []map[string]interface{}: + case []map[string]any: // The context is a table of hashes. Pick the most recent table // defined as the current hash. hash = t[len(t)-1] - case map[string]interface{}: + case map[string]any: hash = t default: p.panicf("Key '%s' has already been defined.", keyContext) @@ -601,9 +651,8 @@ func (p *parser) setValue(key string, value interface{}) { p.removeImplicit(keyContext) return } - - // Otherwise, we have a concrete key trying to override a previous - // key, which is *always* wrong. + // Otherwise, we have a concrete key trying to override a previous key, + // which is *always* wrong. p.panicf("Key '%s' has already been defined.", keyContext) } @@ -632,14 +681,11 @@ func (p *parser) setType(key string, typ tomlType, pos Position) { // Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and // "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly). -func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} } -func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) } -func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok } -func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray } -func (p *parser) addImplicitContext(key Key) { - p.addImplicit(key) - p.addContext(key, false) -} +func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} } +func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) } +func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok } +func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray } +func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) } // current returns the full key name of the current context. func (p *parser) current() string { @@ -662,114 +708,131 @@ func stripFirstNewline(s string) string { return s } -// Remove newlines inside triple-quoted strings if a line ends with "\". +// stripEscapedNewlines removes whitespace after line-ending backslashes in +// multiline strings. +// +// A line-ending backslash is an unescaped \ followed only by whitespace until +// the next newline. After a line-ending backslash, all whitespace is removed +// until the next non-whitespace character. func (p *parser) stripEscapedNewlines(s string) string { - split := strings.Split(s, "\n") - if len(split) < 1 { - return s - } - - escNL := false // Keep track of the last non-blank line was escaped. - for i, line := range split { - line = strings.TrimRight(line, " \t\r") - - if len(line) == 0 || line[len(line)-1] != '\\' { - split[i] = strings.TrimRight(split[i], "\r") - if !escNL && i != len(split)-1 { - split[i] += "\n" - } - continue + var ( + b strings.Builder + i int + ) + b.Grow(len(s)) + for { + ix := strings.Index(s[i:], `\`) + if ix < 0 { + b.WriteString(s) + return b.String() } + i += ix - escBS := true - for j := len(line) - 1; j >= 0 && line[j] == '\\'; j-- { - escBS = !escBS + if len(s) > i+1 && s[i+1] == '\\' { + // Escaped backslash. + i += 2 + continue } - if escNL { - line = strings.TrimLeft(line, " \t\r") + // Scan until the next non-whitespace. + j := i + 1 + whitespaceLoop: + for ; j < len(s); j++ { + switch s[j] { + case ' ', '\t', '\r', '\n': + default: + break whitespaceLoop + } } - escNL = !escBS - - if escBS { - split[i] += "\n" + if j == i+1 { + // Not a whitespace escape. + i++ continue } - - if i == len(split)-1 { - p.panicf("invalid escape: '\\ '") - } - - split[i] = line[:len(line)-1] // Remove \ - if len(split)-1 > i { - split[i+1] = strings.TrimLeft(split[i+1], " \t\r") + if !strings.Contains(s[i:j], "\n") { + // This is not a line-ending backslash. (It's a bad escape sequence, + // but we can let replaceEscapes catch it.) + i++ + continue } + b.WriteString(s[:i]) + s = s[j:] + i = 0 } - return strings.Join(split, "") } func (p *parser) replaceEscapes(it item, str string) string { - replaced := make([]rune, 0, len(str)) - s := []byte(str) - r := 0 - for r < len(s) { - if s[r] != '\\' { - c, size := utf8.DecodeRune(s[r:]) - r += size - replaced = append(replaced, c) + var ( + b strings.Builder + skip = 0 + ) + b.Grow(len(str)) + for i, c := range str { + if skip > 0 { + skip-- + continue + } + if c != '\\' { + b.WriteRune(c) continue } - r += 1 - if r >= len(s) { + + if i >= len(str) { p.bug("Escape sequence at end of string.") return "" } - switch s[r] { + switch str[i+1] { default: - p.bug("Expected valid escape code after \\, but got %q.", s[r]) + p.bug("Expected valid escape code after \\, but got %q.", str[i+1]) case ' ', '\t': - p.panicItemf(it, "invalid escape: '\\%c'", s[r]) + p.panicItemf(it, "invalid escape: '\\%c'", str[i+1]) case 'b': - replaced = append(replaced, rune(0x0008)) - r += 1 + b.WriteByte(0x08) + skip = 1 case 't': - replaced = append(replaced, rune(0x0009)) - r += 1 + b.WriteByte(0x09) + skip = 1 case 'n': - replaced = append(replaced, rune(0x000A)) - r += 1 + b.WriteByte(0x0a) + skip = 1 case 'f': - replaced = append(replaced, rune(0x000C)) - r += 1 + b.WriteByte(0x0c) + skip = 1 case 'r': - replaced = append(replaced, rune(0x000D)) - r += 1 + b.WriteByte(0x0d) + skip = 1 + case 'e': + if p.tomlNext { + b.WriteByte(0x1b) + skip = 1 + } case '"': - replaced = append(replaced, rune(0x0022)) - r += 1 + b.WriteByte(0x22) + skip = 1 case '\\': - replaced = append(replaced, rune(0x005C)) - r += 1 + b.WriteByte(0x5c) + skip = 1 + // The lexer guarantees the correct number of characters are present; + // don't need to check here. + case 'x': + if p.tomlNext { + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+4]) + b.WriteRune(escaped) + skip = 3 + } case 'u': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+5). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+5]) - replaced = append(replaced, escaped) - r += 5 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+6]) + b.WriteRune(escaped) + skip = 5 case 'U': - // At this point, we know we have a Unicode escape of the form - // `uXXXX` at [r, r+9). (Because the lexer guarantees this - // for us.) - escaped := p.asciiEscapeToUnicode(it, s[r+1:r+9]) - replaced = append(replaced, escaped) - r += 9 + escaped := p.asciiEscapeToUnicode(it, str[i+2:i+10]) + b.WriteRune(escaped) + skip = 9 } } - return string(replaced) + return b.String() } -func (p *parser) asciiEscapeToUnicode(it item, bs []byte) rune { - s := string(bs) +func (p *parser) asciiEscapeToUnicode(it item, s string) rune { hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) if err != nil { p.bug("Could not parse '%s' as a hexadecimal number, but the lexer claims it's OK: %s", s, err) diff --git a/vendor/github.com/BurntSushi/toml/type_fields.go b/vendor/github.com/BurntSushi/toml/type_fields.go index 254ca82e5..10c51f7ee 100644 --- a/vendor/github.com/BurntSushi/toml/type_fields.go +++ b/vendor/github.com/BurntSushi/toml/type_fields.go @@ -25,10 +25,8 @@ type field struct { // breaking ties with index sequence. type byName []field -func (x byName) Len() int { return len(x) } - +func (x byName) Len() int { return len(x) } func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - func (x byName) Less(i, j int) bool { if x[i].name != x[j].name { return x[i].name < x[j].name @@ -45,10 +43,8 @@ func (x byName) Less(i, j int) bool { // byIndex sorts field by index sequence. type byIndex []field -func (x byIndex) Len() int { return len(x) } - +func (x byIndex) Len() int { return len(x) } func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - func (x byIndex) Less(i, j int) bool { for k, xik := range x[i].index { if k >= len(x[j].index) { diff --git a/vendor/github.com/BurntSushi/toml/type_toml.go b/vendor/github.com/BurntSushi/toml/type_toml.go index 4e90d7737..1c090d331 100644 --- a/vendor/github.com/BurntSushi/toml/type_toml.go +++ b/vendor/github.com/BurntSushi/toml/type_toml.go @@ -22,13 +22,8 @@ func typeIsTable(t tomlType) bool { type tomlBaseType string -func (btype tomlBaseType) typeString() string { - return string(btype) -} - -func (btype tomlBaseType) String() string { - return btype.typeString() -} +func (btype tomlBaseType) typeString() string { return string(btype) } +func (btype tomlBaseType) String() string { return btype.typeString() } var ( tomlInteger tomlBaseType = "Integer" @@ -54,7 +49,7 @@ func (p *parser) typeOfPrimitive(lexItem item) tomlType { return tomlFloat case itemDatetime: return tomlDatetime - case itemString: + case itemString, itemStringEsc: return tomlString case itemMultilineString: return tomlString diff --git a/vendor/github.com/beevik/etree/.travis.yml b/vendor/github.com/beevik/etree/.travis.yml deleted file mode 100644 index f4cb25d47..000000000 --- a/vendor/github.com/beevik/etree/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -sudo: false - -go: - - 1.11.x - - tip - -matrix: - allow_failures: - - go: tip - -script: - - go vet ./... - - go test -v ./... diff --git a/vendor/github.com/beevik/etree/CONTRIBUTORS b/vendor/github.com/beevik/etree/CONTRIBUTORS index 03211a85e..24ab2dfba 100644 --- a/vendor/github.com/beevik/etree/CONTRIBUTORS +++ b/vendor/github.com/beevik/etree/CONTRIBUTORS @@ -8,3 +8,7 @@ Nicolas Piganeau (npiganeau) Chris Brown (ccbrown) Earncef Sequeira (earncef) Gabriel de Labachelerie (wuzuf) +Martin Dosch (mdosch) +Hugo Wetterberg (hugowetterberg) +Tobias Theel (nerzal) +Daniel Potapov (dpotapov) diff --git a/vendor/github.com/beevik/etree/LICENSE b/vendor/github.com/beevik/etree/LICENSE index 26f1f7751..4ebd85673 100644 --- a/vendor/github.com/beevik/etree/LICENSE +++ b/vendor/github.com/beevik/etree/LICENSE @@ -1,4 +1,4 @@ -Copyright 2015-2019 Brett Vickers. All rights reserved. +Copyright 2015-2024 Brett Vickers. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/vendor/github.com/beevik/etree/README.md b/vendor/github.com/beevik/etree/README.md index 08ec26b0a..98a451839 100644 --- a/vendor/github.com/beevik/etree/README.md +++ b/vendor/github.com/beevik/etree/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://travis-ci.org/beevik/etree.svg?branch=master)](https://travis-ci.org/beevik/etree) [![GoDoc](https://godoc.org/github.com/beevik/etree?status.svg)](https://godoc.org/github.com/beevik/etree) +[![Go](https://github.com/beevik/etree/actions/workflows/go.yml/badge.svg)](https://github.com/beevik/etree/actions/workflows/go.yml) etree ===== diff --git a/vendor/github.com/beevik/etree/RELEASE_NOTES.md b/vendor/github.com/beevik/etree/RELEASE_NOTES.md index ee59d7abf..e82b02dda 100644 --- a/vendor/github.com/beevik/etree/RELEASE_NOTES.md +++ b/vendor/github.com/beevik/etree/RELEASE_NOTES.md @@ -1,3 +1,75 @@ +Release 1.4.1 +============= + +**Changes** + +* Minimal go version updated to 1.21. +* Default-initialized CharsetReader causes same result as NewDocument(). +* When reading an XML document, attributes are parsed more efficiently. + +Release v1.4.0 +============== + +**New Features** + +* Add `AutoClose` option to `ReadSettings`. +* Add `ValidateInput` to `ReadSettings`. +* Add `NotNil` function to `Element`. +* Add `NextSibling` and `PrevSibling` functions to `Element`. + +Release v1.3.0 +============== + +**New Features** + +* Add support for double-quotes in filter path queries. +* Add `PreserveDuplicateAttrs` to `ReadSettings`. +* Add `ReindexChildren` to `Element`. + +Release v1.2.0 +============== + +**New Features** + +* Add the ability to write XML fragments using Token WriteTo functions. +* Add the ability to re-indent an XML element as though it were the root of + the document. +* Add a ReadSettings option to preserve CDATA blocks when reading and XML + document. + +Release v1.1.4 +============== + +**New Features** + +* Add the ability to preserve whitespace in leaf elements during indent. +* Add the ability to suppress a document-trailing newline during indent. +* Add choice of XML attribute quoting style (single-quote or double-quote). + +**Removed Features** + +* Removed the CDATA preservation change introduced in v1.1.3. It was + implemented in a way that broke the ability to process XML documents + encoded using non-UTF8 character sets. + +Release v1.1.3 +============== + +* XML reads now preserve CDATA sections instead of converting them to + standard character data. + +Release v1.1.2 +============== + +* Fixed a path parsing bug. +* The `Element.Text` function now handles comments embedded between + character data spans. + +Release v1.1.1 +============== + +* Updated go version in `go.mod` to 1.20 + Release v1.1.0 ============== diff --git a/vendor/github.com/beevik/etree/etree.go b/vendor/github.com/beevik/etree/etree.go index 9e24f9012..536e4fc2a 100644 --- a/vendor/github.com/beevik/etree/etree.go +++ b/vendor/github.com/beevik/etree/etree.go @@ -13,44 +13,94 @@ import ( "errors" "io" "os" - "sort" + "slices" "strings" ) const ( - // NoIndent is used with Indent to disable all indenting. + // NoIndent is used with the IndentSettings record to remove all + // indenting. NoIndent = -1 ) // ErrXML is returned when XML parsing fails due to incorrect formatting. var ErrXML = errors.New("etree: invalid XML format") -// ReadSettings allow for changing the default behavior of the ReadFrom* -// methods. +// cdataPrefix is used to detect CDATA text when ReadSettings.PreserveCData is +// true. +var cdataPrefix = []byte(" and '. Default: false. CanonicalAttrVal bool - // When outputting indented XML, use a carriage return and linefeed - // ("\r\n") as a new-line delimiter instead of just a linefeed ("\n"). - // This is useful on Windows-based systems. + // AttrSingleQuote causes attributes to use single quotes (attr='example') + // instead of double quotes (attr = "example") when set to true. Default: + // false. + AttrSingleQuote bool + + // UseCRLF causes the document's Indent* functions to use a carriage return + // followed by a linefeed ("\r\n") when outputting a newline. If false, + // only a linefeed is used ("\n"). Default: false. + // + // Deprecated: UseCRLF is deprecated. Use IndentSettings.UseCRLF instead. UseCRLF bool } -// newWriteSettings creates a default WriteSettings record. -func newWriteSettings() WriteSettings { - return WriteSettings{ - CanonicalEndTags: false, - CanonicalText: false, - CanonicalAttrVal: false, - UseCRLF: false, +// dup creates a duplicate of the WriteSettings object. +func (s *WriteSettings) dup() WriteSettings { + return *s +} + +// IndentSettings determine the behavior of the Document's Indent* functions. +type IndentSettings struct { + // Spaces indicates the number of spaces to insert for each level of + // indentation. Set to etree.NoIndent to remove all indentation. Ignored + // when UseTabs is true. Default: 4. + Spaces int + + // UseTabs causes tabs to be used instead of spaces when indenting. + // Default: false. + UseTabs bool + + // UseCRLF causes newlines to be written as a carriage return followed by + // a linefeed ("\r\n"). If false, only a linefeed character is output + // for a newline ("\n"). Default: false. + UseCRLF bool + + // PreserveLeafWhitespace causes indent functions to preserve whitespace + // within XML elements containing only non-CDATA character data. Default: + // false. + PreserveLeafWhitespace bool + + // SuppressTrailingWhitespace suppresses the generation of a trailing + // whitespace characters (such as newlines) at the end of the indented + // document. Default: false. + SuppressTrailingWhitespace bool +} + +// NewIndentSettings creates a default IndentSettings record. +func NewIndentSettings() *IndentSettings { + return &IndentSettings{ + Spaces: 4, + UseTabs: false, + UseCRLF: false, + PreserveLeafWhitespace: false, + SuppressTrailingWhitespace: false, } } -// A Token is an empty interface that represents an Element, CharData, -// Comment, Directive, or ProcInst. +type indentFunc func(depth int) string + +func getIndentFunc(s *IndentSettings) indentFunc { + if s.UseTabs { + if s.UseCRLF { + return func(depth int) string { return indentCRLF(depth, indentTabs) } + } else { + return func(depth int) string { return indentLF(depth, indentTabs) } + } + } else { + if s.Spaces < 0 { + return func(depth int) string { return "" } + } else if s.UseCRLF { + return func(depth int) string { return indentCRLF(depth*s.Spaces, indentSpaces) } + } else { + return func(depth int) string { return indentLF(depth*s.Spaces, indentSpaces) } + } + } +} + +// Writer is the interface that wraps the Write* functions called by each token +// type's WriteTo function. +type Writer interface { + io.StringWriter + io.ByteWriter + io.Writer +} + +// A Token is an interface type used to represent XML elements, character +// data, CDATA sections, XML comments, XML directives, and XML processing +// instructions. type Token interface { Parent() *Element Index() int + WriteTo(w Writer, s *WriteSettings) dup(parent *Element) Token setParent(parent *Element) setIndex(index int) - writeTo(w *bufio.Writer, s *WriteSettings) } -// A Document is a container holding a complete XML hierarchy. Its embedded -// element contains zero or more children, one of which is usually the root -// element. The embedded element may include other children such as -// processing instructions or BOM CharData tokens. +// A Document is a container holding a complete XML tree. +// +// A document has a single embedded element, which contains zero or more child +// tokens, one of which is usually the root element. The embedded element may +// include other children such as processing instruction tokens or character +// data tokens. The document's embedded element is never directly serialized; +// only its children are. +// +// A document also contains read and write settings, which influence the way +// the document is deserialized, serialized, and indented. type Document struct { Element ReadSettings ReadSettings @@ -112,7 +237,7 @@ type Element struct { index int // token index in parent's children } -// An Attr represents a key-value attribute of an XML element. +// An Attr represents a key-value attribute within an XML element. type Attr struct { Space, Key string // The attribute's namespace prefix and key Value string // The attribute value string @@ -123,17 +248,18 @@ type Attr struct { type charDataFlags uint8 const ( - // The CharData was created by an indent function as whitespace. + // The CharData contains only whitespace. whitespaceFlag charDataFlags = 1 << iota // The CharData contains a CDATA section. cdataFlag ) -// CharData can be used to represent character data or a CDATA section within -// an XML document. +// CharData may be used to represent simple text data or a CDATA section +// within an XML document. The Data property should never be modified +// directly; use the SetData function instead. type CharData struct { - Data string + Data string // the simple text or CDATA section content parent *Element index int flags charDataFlags @@ -141,22 +267,22 @@ type CharData struct { // A Comment represents an XML comment. type Comment struct { - Data string + Data string // the comment's text parent *Element index int } // A Directive represents an XML directive. type Directive struct { - Data string + Data string // the directive string parent *Element index int } // A ProcInst represents an XML processing instruction. type ProcInst struct { - Target string - Inst string + Target string // the processing instruction target + Inst string // the processing instruction value parent *Element index int } @@ -164,19 +290,30 @@ type ProcInst struct { // NewDocument creates an XML document without a root element. func NewDocument() *Document { return &Document{ - Element{Child: make([]Token, 0)}, - newReadSettings(), - newWriteSettings(), + Element: Element{Child: make([]Token, 0)}, } } +// NewDocumentWithRoot creates an XML document and sets the element 'e' as its +// root element. If the element 'e' is already part of another document, it is +// first removed from its existing document. +func NewDocumentWithRoot(e *Element) *Document { + d := NewDocument() + d.SetRoot(e) + return d +} + // Copy returns a recursive, deep copy of the document. func (d *Document) Copy() *Document { - return &Document{*(d.dup(nil).(*Element)), d.ReadSettings, d.WriteSettings} + return &Document{ + Element: *(d.Element.dup(nil).(*Element)), + ReadSettings: d.ReadSettings.dup(), + WriteSettings: d.WriteSettings.dup(), + } } -// Root returns the root element of the document, or nil if there is no root -// element. +// Root returns the root element of the document. It returns nil if there is +// no root element. func (d *Document) Root() *Element { for _, t := range d.Child { if c, ok := t.(*Element); ok { @@ -186,25 +323,23 @@ func (d *Document) Root() *Element { return nil } -// SetRoot replaces the document's root element with e. If the document -// already has a root when this function is called, then the document's -// original root is unbound first. If the element e is bound to another -// document (or to another element within a document), then it is unbound -// first. +// SetRoot replaces the document's root element with the element 'e'. If the +// document already has a root element when this function is called, then the +// existing root element is unbound from the document. If the element 'e' is +// part of another document, then it is unbound from the other document. func (d *Document) SetRoot(e *Element) { if e.parent != nil { e.parent.RemoveChild(e) } - p := &d.Element - e.setParent(p) - // If there is already a root element, replace it. + p := &d.Element for i, t := range p.Child { if _, ok := t.(*Element); ok { t.setParent(nil) t.setIndex(-1) p.Child[i] = e + e.setParent(p) e.setIndex(i) return } @@ -214,51 +349,104 @@ func (d *Document) SetRoot(e *Element) { p.addChild(e) } -// ReadFrom reads XML from the reader r into the document d. It returns the -// number of bytes read and any error encountered. +// ReadFrom reads XML from the reader 'r' into this document. The function +// returns the number of bytes read and any error encountered. func (d *Document) ReadFrom(r io.Reader) (n int64, err error) { + if d.ReadSettings.ValidateInput { + b, err := io.ReadAll(r) + if err != nil { + return 0, err + } + if err := validateXML(bytes.NewReader(b), d.ReadSettings); err != nil { + return 0, err + } + r = bytes.NewReader(b) + } return d.Element.readFrom(r, d.ReadSettings) } -// ReadFromFile reads XML from the string s into the document d. -func (d *Document) ReadFromFile(filename string) error { - f, err := os.Open(filename) +// ReadFromFile reads XML from a local file at path 'filepath' into this +// document. +func (d *Document) ReadFromFile(filepath string) error { + f, err := os.Open(filepath) if err != nil { return err } defer f.Close() + _, err = d.ReadFrom(f) return err } -// ReadFromBytes reads XML from the byte slice b into the document d. +// ReadFromBytes reads XML from the byte slice 'b' into the this document. func (d *Document) ReadFromBytes(b []byte) error { - _, err := d.ReadFrom(bytes.NewReader(b)) + if d.ReadSettings.ValidateInput { + if err := validateXML(bytes.NewReader(b), d.ReadSettings); err != nil { + return err + } + } + _, err := d.Element.readFrom(bytes.NewReader(b), d.ReadSettings) return err } -// ReadFromString reads XML from the string s into the document d. +// ReadFromString reads XML from the string 's' into this document. func (d *Document) ReadFromString(s string) error { - _, err := d.ReadFrom(strings.NewReader(s)) + if d.ReadSettings.ValidateInput { + if err := validateXML(strings.NewReader(s), d.ReadSettings); err != nil { + return err + } + } + _, err := d.Element.readFrom(strings.NewReader(s), d.ReadSettings) return err } -// WriteTo serializes an XML document into the writer w. It -// returns the number of bytes written and any error encountered. +// validateXML determines if the data read from the reader 'r' contains +// well-formed XML according to the rules set by the go xml package. +func validateXML(r io.Reader, settings ReadSettings) error { + dec := newDecoder(r, settings) + err := dec.Decode(new(interface{})) + if err != nil { + return err + } + + // If there are any trailing tokens after unmarshalling with Decode(), + // then the XML input didn't terminate properly. + _, err = dec.Token() + if err == io.EOF { + return nil + } + return ErrXML +} + +// newDecoder creates an XML decoder for the reader 'r' configured using +// the provided read settings. +func newDecoder(r io.Reader, settings ReadSettings) *xml.Decoder { + d := xml.NewDecoder(r) + d.CharsetReader = settings.CharsetReader + if d.CharsetReader == nil { + d.CharsetReader = defaultCharsetReader + } + d.Strict = !settings.Permissive + d.Entity = settings.Entity + d.AutoClose = settings.AutoClose + return d +} + +// WriteTo serializes the document out to the writer 'w'. The function returns +// the number of bytes written and any error encountered. func (d *Document) WriteTo(w io.Writer) (n int64, err error) { - cw := newCountWriter(w) - b := bufio.NewWriter(cw) + xw := newXmlWriter(w) + b := bufio.NewWriter(xw) for _, c := range d.Child { - c.writeTo(b, &d.WriteSettings) + c.WriteTo(b, &d.WriteSettings) } - err, n = b.Flush(), cw.bytes + err, n = b.Flush(), xw.bytes return } -// WriteToFile serializes an XML document into the file named -// filename. -func (d *Document) WriteToFile(filename string) error { - f, err := os.Create(filename) +// WriteToFile serializes the document out to the file at path 'filepath'. +func (d *Document) WriteToFile(filepath string) error { + f, err := os.Create(filepath) if err != nil { return err } @@ -267,8 +455,7 @@ func (d *Document) WriteToFile(filename string) error { return err } -// WriteToBytes serializes the XML document into a slice of -// bytes. +// WriteToBytes serializes this document into a slice of bytes. func (d *Document) WriteToBytes() (b []byte, err error) { var buf bytes.Buffer if _, err = d.WriteTo(&buf); err != nil { @@ -277,7 +464,7 @@ func (d *Document) WriteToBytes() (b []byte, err error) { return buf.Bytes(), nil } -// WriteToString serializes the XML document into a string. +// WriteToString serializes this document into a string. func (d *Document) WriteToString() (s string, err error) { var b []byte if b, err = d.WriteToBytes(); err != nil { @@ -286,41 +473,54 @@ func (d *Document) WriteToString() (s string, err error) { return string(b), nil } -type indentFunc func(depth int) string - // Indent modifies the document's element tree by inserting character data -// tokens containing newlines and indentation. The amount of indentation per -// depth level is given as spaces. Pass etree.NoIndent for spaces if you want -// no indentation at all. +// tokens containing newlines and spaces for indentation. The amount of +// indentation per depth level is given by the 'spaces' parameter. Other than +// the number of spaces, default IndentSettings are used. func (d *Document) Indent(spaces int) { - var indent indentFunc - switch { - case spaces < 0: - indent = func(depth int) string { return "" } - case d.WriteSettings.UseCRLF == true: - indent = func(depth int) string { return indentCRLF(depth*spaces, indentSpaces) } - default: - indent = func(depth int) string { return indentLF(depth*spaces, indentSpaces) } - } - d.Element.indent(0, indent) + s := NewIndentSettings() + s.Spaces = spaces + d.IndentWithSettings(s) } // IndentTabs modifies the document's element tree by inserting CharData -// tokens containing newlines and tabs for indentation. One tab is used per -// indentation level. +// tokens containing newlines and tabs for indentation. One tab is used per +// indentation level. Other than the use of tabs, default IndentSettings +// are used. func (d *Document) IndentTabs() { - var indent indentFunc - switch d.WriteSettings.UseCRLF { - case true: - indent = func(depth int) string { return indentCRLF(depth, indentTabs) } - default: - indent = func(depth int) string { return indentLF(depth, indentTabs) } + s := NewIndentSettings() + s.UseTabs = true + d.IndentWithSettings(s) +} + +// IndentWithSettings modifies the document's element tree by inserting +// character data tokens containing newlines and indentation. The behavior +// of the indentation algorithm is configured by the indent settings. +func (d *Document) IndentWithSettings(s *IndentSettings) { + // WriteSettings.UseCRLF is deprecated. Until removed from the package, it + // overrides IndentSettings.UseCRLF when true. + if d.WriteSettings.UseCRLF { + s.UseCRLF = true + } + + d.Element.indent(0, getIndentFunc(s), s) + + if s.SuppressTrailingWhitespace { + d.Element.stripTrailingWhitespace() } - d.Element.indent(0, indent) } -// NewElement creates an unparented element with the specified tag. The tag -// may be prefixed by a namespace prefix and a colon. +// Unindent modifies the document's element tree by removing character data +// tokens containing only whitespace. Other than the removal of indentation, +// default IndentSettings are used. +func (d *Document) Unindent() { + s := NewIndentSettings() + s.Spaces = NoIndent + d.IndentWithSettings(s) +} + +// NewElement creates an unparented element with the specified tag (i.e., +// name). The tag may include a namespace prefix followed by a colon. func NewElement(tag string) *Element { space, stag := spaceDecompose(tag) return newElement(space, stag, nil) @@ -345,7 +545,8 @@ func newElement(space, tag string, parent *Element) *Element { // Copy creates a recursive, deep copy of the element and all its attributes // and children. The returned element has no parent but can be parented to a -// another element using AddElement, or to a document using SetRoot. +// another element using AddChild, or added to a document with SetRoot or +// NewDocumentWithRoot. func (e *Element) Copy() *Element { return e.dup(nil).(*Element) } @@ -400,16 +601,6 @@ func (e *Element) findDefaultNamespaceURI() string { return e.parent.findDefaultNamespaceURI() } -// hasText returns true if the element has character data immediately -// folllowing the element's opening tag. -func (e *Element) hasText() bool { - if len(e.Child) == 0 { - return false - } - _, ok := e.Child[0].(*CharData) - return ok -} - // namespacePrefix returns the namespace prefix associated with the element. func (e *Element) namespacePrefix() string { return e.Space @@ -420,6 +611,15 @@ func (e *Element) name() string { return e.Tag } +// ReindexChildren recalculates the index values of the element's child +// tokens. This is necessary only if you have manually manipulated the +// element's `Child` array. +func (e *Element) ReindexChildren() { + for i := 0; i < len(e.Child); i++ { + e.Child[i].setIndex(i) + } +} + // Text returns all character data immediately following the element's opening // tag. func (e *Element) Text() string { @@ -433,8 +633,10 @@ func (e *Element) Text() string { if text == "" { text = cd.Data } else { - text = text + cd.Data + text += cd.Data } + } else if _, ok := ch.(*Comment); ok { + // ignore } else { break } @@ -470,7 +672,7 @@ func (e *Element) Tail() string { if text == "" { text = cd.Data } else { - text = text + cd.Data + text += cd.Data } } else { break @@ -548,30 +750,30 @@ func (e *Element) findTermCharDataIndex(start int) int { return len(e.Child) } -// CreateElement creates an element with the specified tag and adds it as the -// last child element of the element e. The tag may be prefixed by a namespace -// prefix and a colon. +// CreateElement creates a new element with the specified tag (i.e., name) and +// adds it as the last child token of this element. The tag may include a +// prefix followed by a colon. func (e *Element) CreateElement(tag string) *Element { space, stag := spaceDecompose(tag) return newElement(space, stag, e) } -// AddChild adds the token t as the last child of element e. If token t was -// already the child of another element, it is first removed from its current +// AddChild adds the token 't' as the last child of the element. If token 't' +// was already the child of another element, it is first removed from its // parent element. func (e *Element) AddChild(t Token) { if t.Parent() != nil { t.Parent().RemoveChild(t) } - - t.setParent(e) e.addChild(t) } -// InsertChild inserts the token t before e's existing child token ex. If ex -// is nil or ex is not a child of e, then t is added to the end of e's child -// token list. If token t was already the child of another element, it is -// first removed from its current parent element. +// InsertChild inserts the token 't' into this element's list of children just +// before the element's existing child token 'ex'. If the existing element +// 'ex' does not appear in this element's list of child tokens, then 't' is +// added to the end of this element's list of child tokens. If token 't' is +// already the child of another element, it is first removed from the other +// element's list of child tokens. // // Deprecated: InsertChild is deprecated. Use InsertChildAt instead. func (e *Element) InsertChild(ex Token, t Token) { @@ -596,10 +798,10 @@ func (e *Element) InsertChild(ex Token, t Token) { } } -// InsertChildAt inserts the token t into the element e's list of child tokens -// just before the requested index. If the index is greater than or equal to -// the length of the list of child tokens, the token t is added to the end of -// the list. +// InsertChildAt inserts the token 't' into this element's list of child +// tokens just before the requested 'index'. If the index is greater than or +// equal to the length of the list of child tokens, then the token 't' is +// added to the end of the list of child tokens. func (e *Element) InsertChildAt(index int, t Token) { if index >= len(e.Child) { e.AddChild(t) @@ -624,9 +826,9 @@ func (e *Element) InsertChildAt(index int, t Token) { } } -// RemoveChild attempts to remove the token t from element e's list of -// children. If the token t is a child of e, then it is returned. Otherwise, -// nil is returned. +// RemoveChild attempts to remove the token 't' from this element's list of +// child tokens. If the token 't' was a child of this element, then it is +// removed and returned. Otherwise, nil is returned. func (e *Element) RemoveChild(t Token) Token { if t.Parent() != e { return nil @@ -634,9 +836,9 @@ func (e *Element) RemoveChild(t Token) Token { return e.RemoveChildAt(t.Index()) } -// RemoveChildAt removes the index-th child token from the element e. The -// removed child token is returned. If the index is out of bounds, no child is -// removed and nil is returned. +// RemoveChildAt removes the child token appearing in slot 'index' of this +// element's list of child tokens. The removed child token is then returned. +// If the index is out of bounds, no child is removed and nil is returned. func (e *Element) RemoveChildAt(index int) Token { if index >= len(e.Child) { return nil @@ -652,43 +854,106 @@ func (e *Element) RemoveChildAt(index int) Token { return t } -// ReadFrom reads XML from the reader r and stores the result as a new child -// of element e. +// autoClose analyzes the stack's top element and the current token to decide +// whether the top element should be closed. +func (e *Element) autoClose(stack *stack[*Element], t xml.Token, tags []string) { + if stack.empty() { + return + } + + top := stack.peek() + + for _, tag := range tags { + if strings.EqualFold(tag, top.FullTag()) { + if e, ok := t.(xml.EndElement); !ok || + !strings.EqualFold(e.Name.Space, top.Space) || + !strings.EqualFold(e.Name.Local, top.Tag) { + stack.pop() + } + break + } + } +} + +// ReadFrom reads XML from the reader 'ri' and stores the result as a new +// child of this element. func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err error) { - r := newCountReader(ri) - dec := xml.NewDecoder(r) - dec.CharsetReader = settings.CharsetReader - dec.Strict = !settings.Permissive - dec.Entity = settings.Entity - var stack stack + var r xmlReader + var pr *xmlPeekReader + if settings.PreserveCData { + pr = newXmlPeekReader(ri) + r = pr + } else { + r = newXmlSimpleReader(ri) + } + + attrCheck := make(map[xml.Name]int) + dec := newDecoder(r, settings) + + var stack stack[*Element] stack.push(e) for { + if pr != nil { + pr.PeekPrepare(dec.InputOffset(), len(cdataPrefix)) + } + t, err := dec.RawToken() + + if settings.Permissive && settings.AutoClose != nil { + e.autoClose(&stack, t, settings.AutoClose) + } + switch { case err == io.EOF: - return r.bytes, nil + if len(stack.data) != 1 { + return r.Bytes(), ErrXML + } + return r.Bytes(), nil case err != nil: - return r.bytes, err + return r.Bytes(), err case stack.empty(): - return r.bytes, ErrXML + return r.Bytes(), ErrXML } - top := stack.peek().(*Element) + top := stack.peek() switch t := t.(type) { case xml.StartElement: e := newElement(t.Name.Space, t.Name.Local, top) - for _, a := range t.Attr { - e.createAttr(a.Name.Space, a.Name.Local, a.Value, e) + if settings.PreserveDuplicateAttrs || len(t.Attr) < 2 { + for _, a := range t.Attr { + e.addAttr(a.Name.Space, a.Name.Local, a.Value) + } + } else { + for _, a := range t.Attr { + if i, contains := attrCheck[a.Name]; contains { + e.Attr[i].Value = a.Value + } else { + attrCheck[a.Name] = e.addAttr(a.Name.Space, a.Name.Local, a.Value) + } + } + clear(attrCheck) } stack.push(e) case xml.EndElement: + if top.Tag != t.Name.Local || top.Space != t.Name.Space { + return r.Bytes(), ErrXML + } stack.pop() case xml.CharData: data := string(t) var flags charDataFlags - if isWhitespace(data) { - flags = whitespaceFlag + if pr != nil { + peekBuf := pr.PeekFinalize() + if bytes.Equal(peekBuf, cdataPrefix) { + flags = cdataFlag + } else if isWhitespace(data) { + flags = whitespaceFlag + } + } else { + if isWhitespace(data) { + flags = whitespaceFlag + } } newCharData(data, flags, top) case xml.Comment: @@ -701,9 +966,10 @@ func (e *Element) readFrom(ri io.Reader, settings ReadSettings) (n int64, err er } } -// SelectAttr finds an element attribute matching the requested key and -// returns it if found. Returns nil if no matching attribute is found. The key -// may be prefixed by a namespace prefix and a colon. +// SelectAttr finds an element attribute matching the requested 'key' and, if +// found, returns a pointer to the matching attribute. The function returns +// nil if no matching attribute is found. The key may include a namespace +// prefix followed by a colon. func (e *Element) SelectAttr(key string) *Attr { space, skey := spaceDecompose(key) for i, a := range e.Attr { @@ -714,9 +980,10 @@ func (e *Element) SelectAttr(key string) *Attr { return nil } -// SelectAttrValue finds an element attribute matching the requested key and -// returns its value if found. The key may be prefixed by a namespace prefix -// and a colon. If the key is not found, the dflt value is returned instead. +// SelectAttrValue finds an element attribute matching the requested 'key' and +// returns its value if found. If no matching attribute is found, the function +// returns the 'dflt' value instead. The key may include a namespace prefix +// followed by a colon. func (e *Element) SelectAttrValue(key, dflt string) string { space, skey := spaceDecompose(key) for _, a := range e.Attr { @@ -727,7 +994,7 @@ func (e *Element) SelectAttrValue(key, dflt string) string { return dflt } -// ChildElements returns all elements that are children of element e. +// ChildElements returns all elements that are children of this element. func (e *Element) ChildElements() []*Element { var elements []*Element for _, t := range e.Child { @@ -738,9 +1005,9 @@ func (e *Element) ChildElements() []*Element { return elements } -// SelectElement returns the first child element with the given tag. The tag -// may be prefixed by a namespace prefix and a colon. Returns nil if no -// element with a matching tag was found. +// SelectElement returns the first child element with the given 'tag' (i.e., +// name). The function returns nil if no child element matching the tag is +// found. The tag may include a namespace prefix followed by a colon. func (e *Element) SelectElement(tag string) *Element { space, stag := spaceDecompose(tag) for _, t := range e.Child { @@ -751,8 +1018,8 @@ func (e *Element) SelectElement(tag string) *Element { return nil } -// SelectElements returns a slice of all child elements with the given tag. -// The tag may be prefixed by a namespace prefix and a colon. +// SelectElements returns a slice of all child elements with the given 'tag' +// (i.e., name). The tag may include a namespace prefix followed by a colon. func (e *Element) SelectElements(tag string) []*Element { space, stag := spaceDecompose(tag) var elements []*Element @@ -764,39 +1031,58 @@ func (e *Element) SelectElements(tag string) []*Element { return elements } -// FindElement returns the first element matched by the XPath-like path -// string. Returns nil if no element is found using the path. Panics if an -// invalid path string is supplied. +// FindElement returns the first element matched by the XPath-like 'path' +// string. The function returns nil if no child element is found using the +// path. It panics if an invalid path string is supplied. func (e *Element) FindElement(path string) *Element { return e.FindElementPath(MustCompilePath(path)) } -// FindElementPath returns the first element matched by the XPath-like path -// string. Returns nil if no element is found using the path. +// FindElementPath returns the first element matched by the 'path' object. The +// function returns nil if no element is found using the path. func (e *Element) FindElementPath(path Path) *Element { p := newPather() elements := p.traverse(e, path) - switch { - case len(elements) > 0: + if len(elements) > 0 { return elements[0] - default: - return nil } + return nil } -// FindElements returns a slice of elements matched by the XPath-like path -// string. Panics if an invalid path string is supplied. +// FindElements returns a slice of elements matched by the XPath-like 'path' +// string. The function returns nil if no child element is found using the +// path. It panics if an invalid path string is supplied. func (e *Element) FindElements(path string) []*Element { return e.FindElementsPath(MustCompilePath(path)) } -// FindElementsPath returns a slice of elements matched by the Path object. +// FindElementsPath returns a slice of elements matched by the 'path' object. func (e *Element) FindElementsPath(path Path) []*Element { p := newPather() return p.traverse(e, path) } -// GetPath returns the absolute path of the element. +// NotNil returns the receiver element if it isn't nil; otherwise, it returns +// an unparented element with an empty string tag. This function simplifies +// the task of writing code to ignore not-found results from element queries. +// For example, instead of writing this: +// +// if e := doc.SelectElement("enabled"); e != nil { +// e.SetText("true") +// } +// +// You could write this: +// +// doc.SelectElement("enabled").NotNil().SetText("true") +func (e *Element) NotNil() *Element { + if e == nil { + return NewElement("") + } + return e +} + +// GetPath returns the absolute path of the element. The absolute path is the +// full path from the document's root. func (e *Element) GetPath() string { path := []string{} for seg := e; seg != nil; seg = seg.Parent() { @@ -813,9 +1099,9 @@ func (e *Element) GetPath() string { return "/" + strings.Join(path, "/") } -// GetRelativePath returns the path of the element relative to the source +// GetRelativePath returns the path of this element relative to the 'source' // element. If the two elements are not part of the same element tree, then -// GetRelativePath returns the empty string. +// the function returns the empty string. func (e *Element) GetRelativePath(source *Element) string { var path []*Element @@ -884,10 +1170,20 @@ func (e *Element) GetRelativePath(source *Element) string { return strings.Join(parts, "/") } -// indent recursively inserts proper indentation between an -// XML element's child tokens. -func (e *Element) indent(depth int, indent indentFunc) { - e.stripIndent() +// IndentWithSettings modifies the element and its child tree by inserting +// character data tokens containing newlines and indentation. The behavior of +// the indentation algorithm is configured by the indent settings. Because +// this function indents the element as if it were at the root of a document, +// it is most useful when called just before writing the element as an XML +// fragment using WriteTo. +func (e *Element) IndentWithSettings(s *IndentSettings) { + e.indent(1, getIndentFunc(s), s) +} + +// indent recursively inserts proper indentation between an XML element's +// child tokens. +func (e *Element) indent(depth int, indent indentFunc, s *IndentSettings) { + e.stripIndent(s) n := len(e.Child) if n == 0 { return @@ -915,7 +1211,7 @@ func (e *Element) indent(depth int, indent indentFunc) { // Recursively process child elements. if ce, ok := c.(*Element); ok { - ce.indent(depth+1, indent) + ce.indent(depth+1, indent, s) } } @@ -931,7 +1227,7 @@ func (e *Element) indent(depth int, indent indentFunc) { } // stripIndent removes any previously inserted indentation. -func (e *Element) stripIndent() { +func (e *Element) stripIndent(s *IndentSettings) { // Count the number of non-indent child tokens n := len(e.Child) for _, c := range e.Child { @@ -942,6 +1238,9 @@ func (e *Element) stripIndent() { if n == len(e.Child) { return } + if n == 0 && len(e.Child) == 1 && s.PreserveLeafWhitespace { + return + } // Strip out indent CharData newChild := make([]Token, n) @@ -957,6 +1256,17 @@ func (e *Element) stripIndent() { e.Child = newChild } +// stripTrailingWhitespace removes any trailing whitespace CharData tokens +// from the element's children. +func (e *Element) stripTrailingWhitespace() { + for i := len(e.Child) - 1; i >= 0; i-- { + if cd, ok := e.Child[i].(*CharData); !ok || !cd.IsWhitespace() { + e.Child = e.Child[:i+1] + return + } + } +} + // dup duplicates the element. func (e *Element) dup(parent *Element) Token { ne := &Element{ @@ -970,47 +1280,63 @@ func (e *Element) dup(parent *Element) Token { for i, t := range e.Child { ne.Child[i] = t.dup(ne) } - for i, a := range e.Attr { - ne.Attr[i] = a - } + copy(ne.Attr, e.Attr) return ne } -// Parent returns the element token's parent element, or nil if it has no -// parent. +// NextSibling returns this element's next sibling element. It returns nil if +// there is no next sibling element. +func (e *Element) NextSibling() *Element { + if e.parent == nil { + return nil + } + for i := e.index + 1; i < len(e.parent.Child); i++ { + if s, ok := e.parent.Child[i].(*Element); ok { + return s + } + } + return nil +} + +// PrevSibling returns this element's preceding sibling element. It returns +// nil if there is no preceding sibling element. +func (e *Element) PrevSibling() *Element { + if e.parent == nil { + return nil + } + for i := e.index - 1; i >= 0; i-- { + if s, ok := e.parent.Child[i].(*Element); ok { + return s + } + } + return nil +} + +// Parent returns this element's parent element. It returns nil if this +// element has no parent. func (e *Element) Parent() *Element { return e.parent } // Index returns the index of this element within its parent element's -// list of child tokens. If this element has no parent element, the index -// is -1. +// list of child tokens. If this element has no parent, then the function +// returns -1. func (e *Element) Index() int { return e.index } -// setParent replaces the element token's parent. -func (e *Element) setParent(parent *Element) { - e.parent = parent -} - -// setIndex sets the element token's index within its parent's Child slice. -func (e *Element) setIndex(index int) { - e.index = index -} - -// writeTo serializes the element to the writer w. -func (e *Element) writeTo(w *bufio.Writer, s *WriteSettings) { +// WriteTo serializes the element to the writer w. +func (e *Element) WriteTo(w Writer, s *WriteSettings) { w.WriteByte('<') w.WriteString(e.FullTag()) for _, a := range e.Attr { w.WriteByte(' ') - a.writeTo(w, s) + a.WriteTo(w, s) } if len(e.Child) > 0 { - w.WriteString(">") + w.WriteByte('>') for _, c := range e.Child { - c.writeTo(w, s) + c.WriteTo(w, s) } w.Write([]byte{'<', '/'}) w.WriteString(e.FullTag()) @@ -1026,42 +1352,58 @@ func (e *Element) writeTo(w *bufio.Writer, s *WriteSettings) { } } +// setParent replaces this element token's parent. +func (e *Element) setParent(parent *Element) { + e.parent = parent +} + +// setIndex sets this element token's index within its parent's Child slice. +func (e *Element) setIndex(index int) { + e.index = index +} + // addChild adds a child token to the element e. func (e *Element) addChild(t Token) { + t.setParent(e) t.setIndex(len(e.Child)) e.Child = append(e.Child, t) } -// CreateAttr creates an attribute and adds it to element e. The key may be -// prefixed by a namespace prefix and a colon. If an attribute with the key -// already exists, its value is replaced. +// CreateAttr creates an attribute with the specified 'key' and 'value' and +// adds it to this element. If an attribute with same key already exists on +// this element, then its value is replaced. The key may include a namespace +// prefix followed by a colon. func (e *Element) CreateAttr(key, value string) *Attr { space, skey := spaceDecompose(key) - return e.createAttr(space, skey, value, e) -} -// createAttr is a helper function that creates attributes. -func (e *Element) createAttr(space, key, value string, parent *Element) *Attr { for i, a := range e.Attr { - if space == a.Space && key == a.Key { + if space == a.Space && skey == a.Key { e.Attr[i].Value = value return &e.Attr[i] } } + + i := e.addAttr(space, skey, value) + return &e.Attr[i] +} + +// addAttr is a helper function that adds an attribute to an element. Returns +// the index of the added attribute. +func (e *Element) addAttr(space, key, value string) int { a := Attr{ Space: space, Key: key, Value: value, - element: parent, + element: e, } e.Attr = append(e.Attr, a) - return &e.Attr[len(e.Attr)-1] + return len(e.Attr) - 1 } -// RemoveAttr removes and returns a copy of the first attribute of the element -// whose key matches the given key. The key may be prefixed by a namespace -// prefix and a colon. If a matching attribute does not exist, nil is -// returned. +// RemoveAttr removes the first attribute of this element whose key matches +// 'key'. It returns a copy of the removed attribute if a match is found. If +// no match is found, it returns nil. The key may include a namespace prefix +// followed by a colon. func (e *Element) RemoveAttr(key string) *Attr { space, skey := spaceDecompose(key) for i, a := range e.Attr { @@ -1078,30 +1420,17 @@ func (e *Element) RemoveAttr(key string) *Attr { return nil } -// SortAttrs sorts the element's attributes lexicographically by key. +// SortAttrs sorts this element's attributes lexicographically by key. func (e *Element) SortAttrs() { - sort.Sort(byAttr(e.Attr)) -} - -type byAttr []Attr - -func (a byAttr) Len() int { - return len(a) -} - -func (a byAttr) Swap(i, j int) { - a[i], a[j] = a[j], a[i] -} - -func (a byAttr) Less(i, j int) bool { - sp := strings.Compare(a[i].Space, a[j].Space) - if sp == 0 { - return strings.Compare(a[i].Key, a[j].Key) < 0 - } - return sp < 0 + slices.SortFunc(e.Attr, func(a, b Attr) int { + if v := strings.Compare(a.Space, b.Space); v != 0 { + return v + } + return strings.Compare(a.Key, b.Key) + }) } -// FullKey returns the attribute a's complete key, including namespace prefix +// FullKey returns this attribute's complete key, including namespace prefix // if present. func (a *Attr) FullKey() string { if a.Space == "" { @@ -1110,22 +1439,29 @@ func (a *Attr) FullKey() string { return a.Space + ":" + a.Key } -// Element returns the element containing the attribute. +// Element returns a pointer to the element containing this attribute. func (a *Attr) Element() *Element { return a.element } -// NamespaceURI returns the XML namespace URI associated with the attribute. -// If the element is part of the XML default namespace, NamespaceURI returns -// the empty string. +// NamespaceURI returns the XML namespace URI associated with this attribute. +// The function returns the empty string if the attribute is unprefixed or +// if the attribute is part of the XML default namespace. func (a *Attr) NamespaceURI() string { - return a.element.NamespaceURI() + if a.Space == "" { + return "" + } + return a.element.findLocalNamespaceURI(a.Space) } -// writeTo serializes the attribute to the writer. -func (a *Attr) writeTo(w *bufio.Writer, s *WriteSettings) { +// WriteTo serializes the attribute to the writer. +func (a *Attr) WriteTo(w Writer, s *WriteSettings) { w.WriteString(a.FullKey()) - w.WriteString(`="`) + if s.AttrSingleQuote { + w.WriteString(`='`) + } else { + w.WriteString(`="`) + } var m escapeMode if s.CanonicalAttrVal { m = escapeCanonicalAttr @@ -1133,20 +1469,26 @@ func (a *Attr) writeTo(w *bufio.Writer, s *WriteSettings) { m = escapeNormal } escapeString(w, a.Value, m) - w.WriteByte('"') + if s.AttrSingleQuote { + w.WriteByte('\'') + } else { + w.WriteByte('"') + } } -// NewText creates a parentless CharData token containing character data. +// NewText creates an unparented CharData token containing simple text data. func NewText(text string) *CharData { return newCharData(text, 0, nil) } -// NewCData creates a parentless XML character CDATA section. +// NewCData creates an unparented XML character CDATA section with 'data' as +// its content. func NewCData(data string) *CharData { return newCharData(data, cdataFlag, nil) } -// NewCharData creates a parentless CharData token containing character data. +// NewCharData creates an unparented CharData token containing simple text +// data. // // Deprecated: NewCharData is deprecated. Instead, use NewText, which does the // same thing. @@ -1159,7 +1501,7 @@ func NewCharData(data string) *CharData { func newCharData(data string, flags charDataFlags, parent *Element) *CharData { c := &CharData{ Data: data, - parent: parent, + parent: nil, index: -1, flags: flags, } @@ -1169,75 +1511,67 @@ func newCharData(data string, flags charDataFlags, parent *Element) *CharData { return c } -// CreateText creates a CharData token containing character data and adds it -// as a child of element e. +// CreateText creates a CharData token containing simple text data and adds it +// to the end of this element's list of child tokens. func (e *Element) CreateText(text string) *CharData { return newCharData(text, 0, e) } -// CreateCData creates a CharData token containing a CDATA section and adds it -// as a child of element e. +// CreateCData creates a CharData token containing a CDATA section with 'data' +// as its content and adds it to the end of this element's list of child +// tokens. func (e *Element) CreateCData(data string) *CharData { return newCharData(data, cdataFlag, e) } -// CreateCharData creates a CharData token containing character data and adds -// it as a child of element e. +// CreateCharData creates a CharData token containing simple text data and +// adds it to the end of this element's list of child tokens. // // Deprecated: CreateCharData is deprecated. Instead, use CreateText, which // does the same thing. func (e *Element) CreateCharData(data string) *CharData { - return newCharData(data, 0, e) + return e.CreateText(data) } -// dup duplicates the character data. -func (c *CharData) dup(parent *Element) Token { - return &CharData{ - Data: c.Data, - flags: c.flags, - parent: parent, - index: c.index, +// SetData modifies the content of the CharData token. In the case of a +// CharData token containing simple text, the simple text is modified. In the +// case of a CharData token containing a CDATA section, the CDATA section's +// content is modified. +func (c *CharData) SetData(text string) { + c.Data = text + if isWhitespace(text) { + c.flags |= whitespaceFlag + } else { + c.flags &= ^whitespaceFlag } } -// IsCData returns true if the character data token is to be encoded as a -// CDATA section. +// IsCData returns true if this CharData token is contains a CDATA section. It +// returns false if the CharData token contains simple text. func (c *CharData) IsCData() bool { return (c.flags & cdataFlag) != 0 } -// IsWhitespace returns true if the character data token was created by one of -// the document Indent methods to contain only whitespace. +// IsWhitespace returns true if this CharData token contains only whitespace. func (c *CharData) IsWhitespace() bool { return (c.flags & whitespaceFlag) != 0 } -// Parent returns the character data token's parent element, or nil if it has -// no parent. +// Parent returns this CharData token's parent element, or nil if it has no +// parent. func (c *CharData) Parent() *Element { return c.parent } // Index returns the index of this CharData token within its parent element's -// list of child tokens. If this CharData token has no parent element, the -// index is -1. +// list of child tokens. If this CharData token has no parent, then the +// function returns -1. func (c *CharData) Index() int { return c.index } -// setParent replaces the character data token's parent. -func (c *CharData) setParent(parent *Element) { - c.parent = parent -} - -// setIndex sets the CharData token's index within its parent element's Child -// slice. -func (c *CharData) setIndex(index int) { - c.index = index -} - -// writeTo serializes character data to the writer. -func (c *CharData) writeTo(w *bufio.Writer, s *WriteSettings) { +// WriteTo serializes character data to the writer. +func (c *CharData) WriteTo(w Writer, s *WriteSettings) { if c.IsCData() { w.WriteString(`") +} + // setParent replaces the comment token's parent. func (c *Comment) setParent(parent *Element) { c.parent = parent @@ -1309,14 +1671,7 @@ func (c *Comment) setIndex(index int) { c.index = index } -// writeTo serialies the comment to the writer. -func (c *Comment) writeTo(w *bufio.Writer, s *WriteSettings) { - w.WriteString("") -} - -// NewDirective creates a parentless XML directive. +// NewDirective creates an unparented XML directive token. func NewDirective(data string) *Directive { return newDirective(data, nil) } @@ -1326,7 +1681,7 @@ func NewDirective(data string) *Directive { func newDirective(data string, parent *Element) *Directive { d := &Directive{ Data: data, - parent: parent, + parent: nil, index: -1, } if parent != nil { @@ -1335,8 +1690,8 @@ func newDirective(data string, parent *Element) *Directive { return d } -// CreateDirective creates an XML directive and adds it as the last child of -// element e. +// CreateDirective creates an XML directive token with the specified 'data' +// value and adds it as the last child token of this element. func (e *Element) CreateDirective(data string) *Directive { return newDirective(data, e) } @@ -1357,12 +1712,19 @@ func (d *Directive) Parent() *Element { } // Index returns the index of this Directive token within its parent element's -// list of child tokens. If this Directive token has no parent element, the -// index is -1. +// list of child tokens. If this Directive token has no parent, then the +// function returns -1. func (d *Directive) Index() int { return d.index } +// WriteTo serializes the XML directive to the writer. +func (d *Directive) WriteTo(w Writer, s *WriteSettings) { + w.WriteString("") +} + // setParent replaces the directive token's parent. func (d *Directive) setParent(parent *Element) { d.parent = parent @@ -1374,14 +1736,7 @@ func (d *Directive) setIndex(index int) { d.index = index } -// writeTo serializes the XML directive to the writer. -func (d *Directive) writeTo(w *bufio.Writer, s *WriteSettings) { - w.WriteString("") -} - -// NewProcInst creates a parentless XML processing instruction. +// NewProcInst creates an unparented XML processing instruction. func NewProcInst(target, inst string) *ProcInst { return newProcInst(target, inst, nil) } @@ -1392,7 +1747,7 @@ func newProcInst(target, inst string, parent *Element) *ProcInst { p := &ProcInst{ Target: target, Inst: inst, - parent: parent, + parent: nil, index: -1, } if parent != nil { @@ -1401,8 +1756,9 @@ func newProcInst(target, inst string, parent *Element) *ProcInst { return p } -// CreateProcInst creates a processing instruction and adds it as a child of -// element e. +// CreateProcInst creates an XML processing instruction token with the +// specified 'target' and instruction 'inst'. It is then added as the last +// child token of this element. func (e *Element) CreateProcInst(target, inst string) *ProcInst { return newProcInst(target, inst, e) } @@ -1424,12 +1780,23 @@ func (p *ProcInst) Parent() *Element { } // Index returns the index of this ProcInst token within its parent element's -// list of child tokens. If this ProcInst token has no parent element, the -// index is -1. +// list of child tokens. If this ProcInst token has no parent, then the +// function returns -1. func (p *ProcInst) Index() int { return p.index } +// WriteTo serializes the processing instruction to the writer. +func (p *ProcInst) WriteTo(w Writer, s *WriteSettings) { + w.WriteString("") +} + // setParent replaces the processing instruction token's parent. func (p *ProcInst) setParent(parent *Element) { p.parent = parent @@ -1440,14 +1807,3 @@ func (p *ProcInst) setParent(parent *Element) { func (p *ProcInst) setIndex(index int) { p.index = index } - -// writeTo serializes the processing instruction to the writer. -func (p *ProcInst) writeTo(w *bufio.Writer, s *WriteSettings) { - w.WriteString("") -} diff --git a/vendor/github.com/beevik/etree/helpers.go b/vendor/github.com/beevik/etree/helpers.go index 825e14e91..ea789b62a 100644 --- a/vendor/github.com/beevik/etree/helpers.go +++ b/vendor/github.com/beevik/etree/helpers.go @@ -5,43 +5,41 @@ package etree import ( - "bufio" "io" "strings" "unicode/utf8" ) -// A simple stack -type stack struct { - data []interface{} +type stack[E any] struct { + data []E } -func (s *stack) empty() bool { +func (s *stack[E]) empty() bool { return len(s.data) == 0 } -func (s *stack) push(value interface{}) { +func (s *stack[E]) push(value E) { s.data = append(s.data, value) } -func (s *stack) pop() interface{} { +func (s *stack[E]) pop() E { value := s.data[len(s.data)-1] - s.data[len(s.data)-1] = nil + var empty E + s.data[len(s.data)-1] = empty s.data = s.data[:len(s.data)-1] return value } -func (s *stack) peek() interface{} { +func (s *stack[E]) peek() E { return s.data[len(s.data)-1] } -// A fifo is a simple first-in-first-out queue. -type fifo struct { - data []interface{} +type queue[E any] struct { + data []E head, tail int } -func (f *fifo) add(value interface{}) { +func (f *queue[E]) add(value E) { if f.len()+1 >= len(f.data) { f.grow() } @@ -51,70 +49,190 @@ func (f *fifo) add(value interface{}) { } } -func (f *fifo) remove() interface{} { +func (f *queue[E]) remove() E { value := f.data[f.head] - f.data[f.head] = nil + var empty E + f.data[f.head] = empty if f.head++; f.head == len(f.data) { f.head = 0 } return value } -func (f *fifo) len() int { +func (f *queue[E]) len() int { if f.tail >= f.head { return f.tail - f.head } return len(f.data) - f.head + f.tail } -func (f *fifo) grow() { +func (f *queue[E]) grow() { c := len(f.data) * 2 if c == 0 { c = 4 } - buf, count := make([]interface{}, c), f.len() + buf, count := make([]E, c), f.len() if f.tail >= f.head { - copy(buf[0:count], f.data[f.head:f.tail]) + copy(buf[:count], f.data[f.head:f.tail]) } else { hindex := len(f.data) - f.head - copy(buf[0:hindex], f.data[f.head:]) + copy(buf[:hindex], f.data[f.head:]) copy(buf[hindex:count], f.data[:f.tail]) } f.data, f.head, f.tail = buf, 0, count } -// countReader implements a proxy reader that counts the number of +// xmlReader provides the interface by which an XML byte stream is +// processed and decoded. +type xmlReader interface { + Bytes() int64 + Read(p []byte) (n int, err error) +} + +// xmlSimpleReader implements a proxy reader that counts the number of // bytes read from its encapsulated reader. -type countReader struct { +type xmlSimpleReader struct { r io.Reader bytes int64 } -func newCountReader(r io.Reader) *countReader { - return &countReader{r: r} +func newXmlSimpleReader(r io.Reader) xmlReader { + return &xmlSimpleReader{r, 0} +} + +func (xr *xmlSimpleReader) Bytes() int64 { + return xr.bytes +} + +func (xr *xmlSimpleReader) Read(p []byte) (n int, err error) { + n, err = xr.r.Read(p) + xr.bytes += int64(n) + return n, err +} + +// xmlPeekReader implements a proxy reader that counts the number of +// bytes read from its encapsulated reader. It also allows the caller to +// "peek" at the previous portions of the buffer after they have been +// parsed. +type xmlPeekReader struct { + r io.Reader + bytes int64 // total bytes read by the Read function + buf []byte // internal read buffer + bufSize int // total bytes used in the read buffer + bufOffset int64 // total bytes read when buf was last filled + window []byte // current read buffer window + peekBuf []byte // buffer used to store data to be peeked at later + peekOffset int64 // total read offset of the start of the peek buffer +} + +func newXmlPeekReader(r io.Reader) *xmlPeekReader { + buf := make([]byte, 4096) + return &xmlPeekReader{ + r: r, + bytes: 0, + buf: buf, + bufSize: 0, + bufOffset: 0, + window: buf[0:0], + peekBuf: make([]byte, 0), + peekOffset: -1, + } +} + +func (xr *xmlPeekReader) Bytes() int64 { + return xr.bytes +} + +func (xr *xmlPeekReader) Read(p []byte) (n int, err error) { + if len(xr.window) == 0 { + err = xr.fill() + if err != nil { + return 0, err + } + if len(xr.window) == 0 { + return 0, nil + } + } + + if len(xr.window) < len(p) { + n = len(xr.window) + } else { + n = len(p) + } + + copy(p, xr.window) + xr.window = xr.window[n:] + xr.bytes += int64(n) + + return n, err +} + +func (xr *xmlPeekReader) PeekPrepare(offset int64, maxLen int) { + if maxLen > cap(xr.peekBuf) { + xr.peekBuf = make([]byte, 0, maxLen) + } + xr.peekBuf = xr.peekBuf[0:0] + xr.peekOffset = offset + xr.updatePeekBuf() +} + +func (xr *xmlPeekReader) PeekFinalize() []byte { + xr.updatePeekBuf() + return xr.peekBuf } -func (cr *countReader) Read(p []byte) (n int, err error) { - b, err := cr.r.Read(p) - cr.bytes += int64(b) - return b, err +func (xr *xmlPeekReader) fill() error { + xr.bufOffset = xr.bytes + xr.bufSize = 0 + n, err := xr.r.Read(xr.buf) + if err != nil { + xr.window, xr.bufSize = xr.buf[0:0], 0 + return err + } + xr.window, xr.bufSize = xr.buf[:n], n + xr.updatePeekBuf() + return nil +} + +func (xr *xmlPeekReader) updatePeekBuf() { + peekRemain := cap(xr.peekBuf) - len(xr.peekBuf) + if xr.peekOffset >= 0 && peekRemain > 0 { + rangeMin := xr.peekOffset + rangeMax := xr.peekOffset + int64(cap(xr.peekBuf)) + bufMin := xr.bufOffset + bufMax := xr.bufOffset + int64(xr.bufSize) + if rangeMin < bufMin { + rangeMin = bufMin + } + if rangeMax > bufMax { + rangeMax = bufMax + } + if rangeMax > rangeMin { + rangeMin -= xr.bufOffset + rangeMax -= xr.bufOffset + if int(rangeMax-rangeMin) > peekRemain { + rangeMax = rangeMin + int64(peekRemain) + } + xr.peekBuf = append(xr.peekBuf, xr.buf[rangeMin:rangeMax]...) + } + } } -// countWriter implements a proxy writer that counts the number of +// xmlWriter implements a proxy writer that counts the number of // bytes written by its encapsulated writer. -type countWriter struct { +type xmlWriter struct { w io.Writer bytes int64 } -func newCountWriter(w io.Writer) *countWriter { - return &countWriter{w: w} +func newXmlWriter(w io.Writer) *xmlWriter { + return &xmlWriter{w: w} } -func (cw *countWriter) Write(p []byte) (n int, err error) { - b, err := cw.w.Write(p) - cw.bytes += int64(b) - return b, err +func (xw *xmlWriter) Write(p []byte) (n int, err error) { + n, err = xw.w.Write(p) + xw.bytes += int64(n) + return n, err } // isWhitespace returns true if the byte slice contains only @@ -181,10 +299,10 @@ func indentLF(n int, source string) string { } } -// nextIndex returns the index of the next occurrence of sep in s, -// starting from offset. It returns -1 if the sep string is not found. -func nextIndex(s, sep string, offset int) int { - switch i := strings.Index(s[offset:], sep); i { +// nextIndex returns the index of the next occurrence of byte ch in s, +// starting from offset. It returns -1 if the byte is not found. +func nextIndex(s string, ch byte, offset int) int { + switch i := strings.IndexByte(s[offset:], ch); i { case -1: return -1 default: @@ -211,7 +329,7 @@ const ( ) // escapeString writes an escaped version of a string to the writer. -func escapeString(w *bufio.Writer, s string, m escapeMode) { +func escapeString(w Writer, s string, m escapeMode) { var esc []byte last := 0 for i := 0; i < len(s); { diff --git a/vendor/github.com/beevik/etree/path.go b/vendor/github.com/beevik/etree/path.go index 82db0ac55..8d6309605 100644 --- a/vendor/github.com/beevik/etree/path.go +++ b/vendor/github.com/beevik/etree/path.go @@ -19,66 +19,73 @@ be modified by one or more bracket-enclosed "filters". Selectors are used to traverse the etree from element to element, while filters are used to narrow the list of candidate elements at each node. -Although etree Path strings are similar to XPath strings -(https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more limited set -of selectors and filtering options. +Although etree Path strings are structurally and behaviorally similar to XPath +strings (https://www.w3.org/TR/1999/REC-xpath-19991116/), they have a more +limited set of selectors and filtering options. -The following selectors are supported by etree Path strings: +The following selectors are supported by etree paths: - . Select the current element. - .. Select the parent of the current element. - * Select all child elements of the current element. - / Select the root element when used at the start of a path. - // Select all descendants of the current element. - tag Select all child elements with a name matching the tag. + . Select the current element. + .. Select the parent of the current element. + * Select all child elements of the current element. + / Select the root element when used at the start of a path. + // Select all descendants of the current element. + tag Select all child elements with a name matching the tag. -The following basic filters are supported by etree Path strings: +The following basic filters are supported: - [@attrib] Keep elements with an attribute named attrib. - [@attrib='val'] Keep elements with an attribute named attrib and value matching val. - [tag] Keep elements with a child element named tag. - [tag='val'] Keep elements with a child element named tag and text matching val. - [n] Keep the n-th element, where n is a numeric index starting from 1. + [@attrib] Keep elements with an attribute named attrib. + [@attrib='val'] Keep elements with an attribute named attrib and value matching val. + [tag] Keep elements with a child element named tag. + [tag='val'] Keep elements with a child element named tag and text matching val. + [n] Keep the n-th element, where n is a numeric index starting from 1. -The following function filters are also supported: +The following function-based filters are supported: - [text()] Keep elements with non-empty text. - [text()='val'] Keep elements whose text matches val. - [local-name()='val'] Keep elements whose un-prefixed tag matches val. - [name()='val'] Keep elements whose full tag exactly matches val. - [namespace-prefix()='val'] Keep elements whose namespace prefix matches val. - [namespace-uri()='val'] Keep elements whose namespace URI matches val. + [text()] Keep elements with non-empty text. + [text()='val'] Keep elements whose text matches val. + [local-name()='val'] Keep elements whose un-prefixed tag matches val. + [name()='val'] Keep elements whose full tag exactly matches val. + [namespace-prefix()] Keep elements with non-empty namespace prefixes. + [namespace-prefix()='val'] Keep elements whose namespace prefix matches val. + [namespace-uri()] Keep elements with non-empty namespace URIs. + [namespace-uri()='val'] Keep elements whose namespace URI matches val. -Here are some examples of Path strings: +Below are some examples of etree path strings. -- Select the bookstore child element of the root element: - /bookstore +Select the bookstore child element of the root element: -- Beginning from the root element, select the title elements of all -descendant book elements having a 'category' attribute of 'WEB': - //book[@category='WEB']/title + /bookstore -- Beginning from the current element, select the first descendant -book element with a title child element containing the text 'Great -Expectations': - .//book[title='Great Expectations'][1] +Beginning from the root element, select the title elements of all descendant +book elements having a 'category' attribute of 'WEB': -- Beginning from the current element, select all child elements of -book elements with an attribute 'language' set to 'english': - ./book/*[@language='english'] + //book[@category='WEB']/title -- Beginning from the current element, select all child elements of -book elements containing the text 'special': - ./book/*[text()='special'] +Beginning from the current element, select the first descendant book element +with a title child element containing the text 'Great Expectations': -- Beginning from the current element, select all descendant book -elements whose title child element has a 'language' attribute of 'french': - .//book/title[@language='french']/.. + .//book[title='Great Expectations'][1] -- Beginning from the current element, select all book elements +Beginning from the current element, select all child elements of book elements +with an attribute 'language' set to 'english': + + ./book/*[@language='english'] + +Beginning from the current element, select all child elements of book elements +containing the text 'special': + + ./book/*[text()='special'] + +Beginning from the current element, select all descendant book elements whose +title child element has a 'language' attribute of 'french': + + .//book/title[@language='french']/.. + +Beginning from the current element, select all descendant book elements belonging to the http://www.w3.org/TR/html4/ namespace: - .//book[namespace-uri()='http://www.w3.org/TR/html4/'] + .//book[namespace-uri()='http://www.w3.org/TR/html4/'] */ type Path struct { segments []segment @@ -145,7 +152,7 @@ type filter interface { // a Path object. It collects and deduplicates all elements matching // the path query. type pather struct { - queue fifo + queue queue[node] results []*Element inResults map[*Element]bool candidates []*Element @@ -173,12 +180,12 @@ func newPather() *pather { // and filters. func (p *pather) traverse(e *Element, path Path) []*Element { for p.queue.add(node{e, path.segments}); p.queue.len() > 0; { - p.eval(p.queue.remove().(node)) + p.eval(p.queue.remove()) } return p.results } -// eval evalutes the current path node by applying the remaining +// eval evaluates the current path node by applying the remaining // path's selector rules against the node's element. func (p *pather) eval(n node) { p.candidates = p.candidates[0:0] @@ -210,7 +217,7 @@ type compiler struct { func (c *compiler) parsePath(path string) []segment { // If path ends with //, fix it if strings.HasSuffix(path, "//") { - path = path + "*" + path += "*" } var segments []segment @@ -232,15 +239,20 @@ func (c *compiler) parsePath(path string) []segment { } func splitPath(path string) []string { - pieces := make([]string, 0) + var pieces []string start := 0 inquote := false + var quote byte for i := 0; i+1 <= len(path); i++ { - if path[i] == '\'' { - inquote = !inquote - } else if path[i] == '/' && !inquote { - pieces = append(pieces, path[start:i]) - start = i + 1 + if !inquote { + if path[i] == '\'' || path[i] == '"' { + inquote, quote = true, path[i] + } else if path[i] == '/' { + pieces = append(pieces, path[start:i]) + start = i + 1 + } + } else if path[i] == quote { + inquote = false } } return append(pieces, path[start:]) @@ -255,7 +267,7 @@ func (c *compiler) parseSegment(path string) segment { } for i := 1; i < len(pieces); i++ { fpath := pieces[i] - if fpath[len(fpath)-1] != ']' { + if len(fpath) == 0 || fpath[len(fpath)-1] != ']' { c.err = ErrPath("path has invalid filter [brackets].") break } @@ -280,15 +292,12 @@ func (c *compiler) parseSelector(path string) selector { } } -var fnTable = map[string]struct { - hasFn func(e *Element) bool - getValFn func(e *Element) string -}{ - "local-name": {nil, (*Element).name}, - "name": {nil, (*Element).FullTag}, - "namespace-prefix": {nil, (*Element).namespacePrefix}, - "namespace-uri": {nil, (*Element).NamespaceURI}, - "text": {(*Element).hasText, (*Element).Text}, +var fnTable = map[string]func(e *Element) string{ + "local-name": (*Element).name, + "name": (*Element).FullTag, + "namespace-prefix": (*Element).namespacePrefix, + "namespace-uri": (*Element).NamespaceURI, + "text": (*Element).Text, } // parseFilter parses a path filter contained within [brackets]. @@ -298,30 +307,34 @@ func (c *compiler) parseFilter(path string) filter { return nil } - // Filter contains [@attr='val'], [fn()='val'], or [tag='val']? - eqindex := strings.Index(path, "='") - if eqindex >= 0 { - rindex := nextIndex(path, "'", eqindex+2) - if rindex != len(path)-1 { - c.err = ErrPath("path has mismatched filter quotes.") - return nil - } - - key := path[:eqindex] - value := path[eqindex+2 : rindex] + // Filter contains [@attr='val'], [@attr="val"], [fn()='val'], + // [fn()="val"], [tag='val'] or [tag="val"]? + eqindex := strings.IndexByte(path, '=') + if eqindex >= 0 && eqindex+1 < len(path) { + quote := path[eqindex+1] + if quote == '\'' || quote == '"' { + rindex := nextIndex(path, quote, eqindex+2) + if rindex != len(path)-1 { + c.err = ErrPath("path has mismatched filter quotes.") + return nil + } - switch { - case key[0] == '@': - return newFilterAttrVal(key[1:], value) - case strings.HasSuffix(key, "()"): - fn := key[:len(key)-2] - if t, ok := fnTable[fn]; ok && t.getValFn != nil { - return newFilterFuncVal(t.getValFn, value) + key := path[:eqindex] + value := path[eqindex+2 : rindex] + + switch { + case key[0] == '@': + return newFilterAttrVal(key[1:], value) + case strings.HasSuffix(key, "()"): + name := key[:len(key)-2] + if fn, ok := fnTable[name]; ok { + return newFilterFuncVal(fn, value) + } + c.err = ErrPath("path has unknown function " + name) + return nil + default: + return newFilterChildText(key, value) } - c.err = ErrPath("path has unknown function " + fn) - return nil - default: - return newFilterChildText(key, value) } } @@ -330,11 +343,11 @@ func (c *compiler) parseFilter(path string) filter { case path[0] == '@': return newFilterAttr(path[1:]) case strings.HasSuffix(path, "()"): - fn := path[:len(path)-2] - if t, ok := fnTable[fn]; ok && t.hasFn != nil { - return newFilterFunc(t.hasFn) + name := path[:len(path)-2] + if fn, ok := fnTable[name]; ok { + return newFilterFunc(fn) } - c.err = ErrPath("path has unknown function " + fn) + c.err = ErrPath("path has unknown function " + name) return nil case isInteger(path): pos, _ := strconv.Atoi(path) @@ -393,9 +406,9 @@ func (s *selectChildren) apply(e *Element, p *pather) { type selectDescendants struct{} func (s *selectDescendants) apply(e *Element, p *pather) { - var queue fifo + var queue queue[*Element] for queue.add(e); queue.len() > 0; { - e := queue.remove().(*Element) + e := queue.remove() p.candidates = append(p.candidates, e) for _, c := range e.Child { if c, ok := c.(*Element); ok { @@ -496,16 +509,16 @@ func (f *filterAttrVal) apply(p *pather) { // filterFunc filters the candidate list for elements satisfying a custom // boolean function. type filterFunc struct { - fn func(e *Element) bool + fn func(e *Element) string } -func newFilterFunc(fn func(e *Element) bool) *filterFunc { +func newFilterFunc(fn func(e *Element) string) *filterFunc { return &filterFunc{fn} } func (f *filterFunc) apply(p *pather) { for _, c := range p.candidates { - if f.fn(c) { + if f.fn(c) != "" { p.scratch = append(p.scratch, c) } } diff --git a/vendor/github.com/boltdb/bolt/README.md b/vendor/github.com/boltdb/bolt/README.md index 4c9312c08..7d43a15b2 100644 --- a/vendor/github.com/boltdb/bolt/README.md +++ b/vendor/github.com/boltdb/bolt/README.md @@ -1,4 +1,4 @@ -Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.0-green.svg) +Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.2.1-green.svg) ==== Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas] @@ -15,11 +15,11 @@ and setting values. That's it. ## Project Status -Bolt is stable and the API is fixed. Full unit test coverage and randomized -black box testing are used to ensure database consistency and thread safety. -Bolt is currently in high-load production environments serving databases as -large as 1TB. Many companies such as Shopify and Heroku use Bolt-backed -services every day. +Bolt is stable, the API is fixed, and the file format is fixed. Full unit +test coverage and randomized black box testing are used to ensure database +consistency and thread safety. Bolt is currently used in high-load production +environments serving databases as large as 1TB. Many companies such as +Shopify and Heroku use Bolt-backed services every day. ## Table of Contents @@ -209,7 +209,7 @@ and then safely close your transaction if an error is returned. This is the recommended way to use Bolt transactions. However, sometimes you may want to manually start and end your transactions. -You can use the `Tx.Begin()` function directly but **please** be sure to close +You can use the `DB.Begin()` function directly but **please** be sure to close the transaction. ```go @@ -313,7 +313,7 @@ func (s *Store) CreateUser(u *User) error { // Generate ID for the user. // This returns an error only if the Tx is closed or not writeable. // That can't happen in an Update() call so I ignore the error check. - id, _ = b.NextSequence() + id, _ := b.NextSequence() u.ID = int(id) // Marshal user data into bytes. @@ -395,7 +395,7 @@ db.View(func(tx *bolt.Tx) error { c := tx.Bucket([]byte("MyBucket")).Cursor() prefix := []byte("1234") - for k, v := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, v = c.Next() { + for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { fmt.Printf("key=%s, value=%s\n", k, v) } @@ -448,6 +448,10 @@ db.View(func(tx *bolt.Tx) error { }) ``` +Please note that keys and values in `ForEach()` are only valid while +the transaction is open. If you need to use a key or value outside of +the transaction, you must use `copy()` to copy it to another byte +slice. ### Nested buckets @@ -460,6 +464,55 @@ func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) func (*Bucket) DeleteBucket(key []byte) error ``` +Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings. + +```go + +// createUser creates a new user in the given account. +func createUser(accountID int, u *User) error { + // Start the transaction. + tx, err := db.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + // Retrieve the root bucket for the account. + // Assume this has already been created when the account was set up. + root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10))) + + // Setup the users bucket. + bkt, err := root.CreateBucketIfNotExists([]byte("USERS")) + if err != nil { + return err + } + + // Generate an ID for the new user. + userID, err := bkt.NextSequence() + if err != nil { + return err + } + u.ID = userID + + // Marshal and save the encoded user. + if buf, err := json.Marshal(u); err != nil { + return err + } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil { + return err + } + + // Commit the transaction. + if err := tx.Commit(); err != nil { + return err + } + + return nil +} + +``` + + + ### Database backups @@ -557,7 +610,7 @@ if err != nil { Bolt is able to run on mobile devices by leveraging the binding feature of the [gomobile](https://github.com/golang/mobile) tool. Create a struct that will contain your database logic and a reference to a `*bolt.DB` with a initializing -contstructor that takes in a filepath where the database file will be stored. +constructor that takes in a filepath where the database file will be stored. Neither Android nor iOS require extra permissions or cleanup from using this method. ```go @@ -715,6 +768,9 @@ Here are a few things to note when evaluating and using Bolt: can be reused by a new page or can be unmapped from virtual memory and you'll see an `unexpected fault address` panic when accessing it. +* Bolt uses an exclusive write lock on the database file so it cannot be + shared by multiple processes. + * Be careful when using `Bucket.FillPercent`. Setting a high fill percent for buckets that have random inserts will cause your database to have very poor page utilization. @@ -807,6 +863,7 @@ them via pull request. Below is a list of public, open source projects that use Bolt: +* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. * [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. * [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside. * [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. @@ -825,7 +882,6 @@ Below is a list of public, open source projects that use Bolt: * [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. * [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. * [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. -* [SkyDB](https://github.com/skydb/sky) - Behavioral analytics database. * [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. * [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. * [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. @@ -842,7 +898,19 @@ Below is a list of public, open source projects that use Bolt: * [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. * [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. * [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. -* [Storm](https://github.com/asdine/storm) - A simple ORM around BoltDB. +* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB. * [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. +* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings. +* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. +* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. +* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development. +* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains +* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal. +* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. +* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. +* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies +* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB +* [Ponzu CMS](https://ponzu-cms.org) - Headless CMS + automatic JSON API with auto-HTTPS, HTTP/2 Server Push, and flexible server framework. If you are using Bolt in a project please send a pull request to add it to the list. diff --git a/vendor/github.com/boltdb/bolt/bolt_386.go b/vendor/github.com/boltdb/bolt/bolt_386.go index e659bfb91..820d533c1 100644 --- a/vendor/github.com/boltdb/bolt/bolt_386.go +++ b/vendor/github.com/boltdb/bolt/bolt_386.go @@ -5,3 +5,6 @@ const maxMapSize = 0x7FFFFFFF // 2GB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_amd64.go b/vendor/github.com/boltdb/bolt/bolt_amd64.go index cca6b7eb7..98fafdb47 100644 --- a/vendor/github.com/boltdb/bolt/bolt_amd64.go +++ b/vendor/github.com/boltdb/bolt/bolt_amd64.go @@ -5,3 +5,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_arm.go b/vendor/github.com/boltdb/bolt/bolt_arm.go index e659bfb91..7e5cb4b94 100644 --- a/vendor/github.com/boltdb/bolt/bolt_arm.go +++ b/vendor/github.com/boltdb/bolt/bolt_arm.go @@ -1,7 +1,28 @@ package bolt +import "unsafe" + // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0x7FFFFFFF // 2GB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned bool + +func init() { + // Simple check to see whether this arch handles unaligned load/stores + // correctly. + + // ARM9 and older devices require load/stores to be from/to aligned + // addresses. If not, the lower 2 bits are cleared and that address is + // read in a jumbled up order. + + // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html + + raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11} + val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2)) + + brokenUnaligned = val != 0x11222211 +} diff --git a/vendor/github.com/boltdb/bolt/bolt_arm64.go b/vendor/github.com/boltdb/bolt/bolt_arm64.go index 6d2309352..b26d84f91 100644 --- a/vendor/github.com/boltdb/bolt/bolt_arm64.go +++ b/vendor/github.com/boltdb/bolt/bolt_arm64.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64.go b/vendor/github.com/boltdb/bolt/bolt_ppc64.go index 2dc6be02e..9331d9771 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc64.go +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go index 8351e129f..8c143bc5d 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_s390x.go b/vendor/github.com/boltdb/bolt/bolt_s390x.go index f4dd26bbb..d7c39af92 100644 --- a/vendor/github.com/boltdb/bolt/bolt_s390x.go +++ b/vendor/github.com/boltdb/bolt/bolt_s390x.go @@ -7,3 +7,6 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_windows.go b/vendor/github.com/boltdb/bolt/bolt_windows.go index d538e6afd..b00fb0720 100644 --- a/vendor/github.com/boltdb/bolt/bolt_windows.go +++ b/vendor/github.com/boltdb/bolt/bolt_windows.go @@ -89,7 +89,7 @@ func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) erro func funlock(db *DB) error { err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{}) db.lockfile.Close() - os.Remove(db.path+lockExt) + os.Remove(db.path + lockExt) return err } diff --git a/vendor/github.com/boltdb/bolt/bucket.go b/vendor/github.com/boltdb/bolt/bucket.go index d2f8c524e..0c5bf2746 100644 --- a/vendor/github.com/boltdb/bolt/bucket.go +++ b/vendor/github.com/boltdb/bolt/bucket.go @@ -130,9 +130,17 @@ func (b *Bucket) Bucket(name []byte) *Bucket { func (b *Bucket) openBucket(value []byte) *Bucket { var child = newBucket(b.tx) + // If unaligned load/stores are broken on this arch and value is + // unaligned simply clone to an aligned byte array. + unaligned := brokenUnaligned && uintptr(unsafe.Pointer(&value[0]))&3 != 0 + + if unaligned { + value = cloneBytes(value) + } + // If this is a writable transaction then we need to copy the bucket entry. // Read-only transactions can point directly at the mmap entry. - if b.tx.writable { + if b.tx.writable && !unaligned { child.bucket = &bucket{} *child.bucket = *(*bucket)(unsafe.Pointer(&value[0])) } else { @@ -167,9 +175,8 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { if bytes.Equal(key, k) { if (flags & bucketLeafFlag) != 0 { return nil, ErrBucketExists - } else { - return nil, ErrIncompatibleValue } + return nil, ErrIncompatibleValue } // Create empty, inline bucket. @@ -329,6 +336,28 @@ func (b *Bucket) Delete(key []byte) error { return nil } +// Sequence returns the current integer for the bucket without incrementing it. +func (b *Bucket) Sequence() uint64 { return b.bucket.sequence } + +// SetSequence updates the sequence number for the bucket. +func (b *Bucket) SetSequence(v uint64) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Materialize the root node if it hasn't been already so that the + // bucket will be saved during commit. + if b.rootNode == nil { + _ = b.node(b.root, nil) + } + + // Increment and return the sequence. + b.bucket.sequence = v + return nil +} + // NextSequence returns an autoincrementing integer for the bucket. func (b *Bucket) NextSequence() (uint64, error) { if b.tx.db == nil { diff --git a/vendor/github.com/boltdb/bolt/db.go b/vendor/github.com/boltdb/bolt/db.go index 1223493ca..f352ff14f 100644 --- a/vendor/github.com/boltdb/bolt/db.go +++ b/vendor/github.com/boltdb/bolt/db.go @@ -552,7 +552,10 @@ func (db *DB) removeTx(tx *Tx) { // Remove the transaction. for i, t := range db.txs { if t == tx { - db.txs = append(db.txs[:i], db.txs[i+1:]...) + last := len(db.txs) - 1 + db.txs[i] = db.txs[last] + db.txs[last] = nil + db.txs = db.txs[:last] break } } @@ -952,7 +955,7 @@ func (s *Stats) Sub(other *Stats) Stats { diff.PendingPageN = s.PendingPageN diff.FreeAlloc = s.FreeAlloc diff.FreelistInuse = s.FreelistInuse - diff.TxN = other.TxN - s.TxN + diff.TxN = s.TxN - other.TxN diff.TxStats = s.TxStats.Sub(&other.TxStats) return diff } diff --git a/vendor/github.com/boltdb/bolt/freelist.go b/vendor/github.com/boltdb/bolt/freelist.go index 0161948fc..aba48f58c 100644 --- a/vendor/github.com/boltdb/bolt/freelist.go +++ b/vendor/github.com/boltdb/bolt/freelist.go @@ -24,7 +24,12 @@ func newFreelist() *freelist { // size returns the size of the page after serialization. func (f *freelist) size() int { - return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * f.count()) + n := f.count() + if n >= 0xFFFF { + // The first element will be used to store the count. See freelist.write. + n++ + } + return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n) } // count returns count of pages on the freelist @@ -46,16 +51,15 @@ func (f *freelist) pending_count() int { return count } -// all returns a list of all free ids and all pending ids in one sorted list. -func (f *freelist) all() []pgid { - m := make(pgids, 0) - +// copyall copies into dst a list of all free ids and all pending ids in one sorted list. +// f.count returns the minimum length required for dst. +func (f *freelist) copyall(dst []pgid) { + m := make(pgids, 0, f.pending_count()) for _, list := range f.pending { m = append(m, list...) } - sort.Sort(m) - return pgids(f.ids).merge(m) + mergepgids(dst, f.ids, m) } // allocate returns the starting page id of a contiguous list of pages of a given size. @@ -166,12 +170,16 @@ func (f *freelist) read(p *page) { } // Copy the list of page ids from the freelist. - ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] - f.ids = make([]pgid, len(ids)) - copy(f.ids, ids) + if count == 0 { + f.ids = nil + } else { + ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] + f.ids = make([]pgid, len(ids)) + copy(f.ids, ids) - // Make sure they're sorted. - sort.Sort(pgids(f.ids)) + // Make sure they're sorted. + sort.Sort(pgids(f.ids)) + } // Rebuild the page cache. f.reindex() @@ -182,20 +190,22 @@ func (f *freelist) read(p *page) { // become free. func (f *freelist) write(p *page) error { // Combine the old free pgids and pgids waiting on an open transaction. - ids := f.all() // Update the header flag. p.flags |= freelistPageFlag // The page.count can only hold up to 64k elements so if we overflow that // number then we handle it by putting the size in the first element. - if len(ids) < 0xFFFF { - p.count = uint16(len(ids)) - copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids) + lenids := f.count() + if lenids == 0 { + p.count = uint16(lenids) + } else if lenids < 0xFFFF { + p.count = uint16(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:]) } else { p.count = 0xFFFF - ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(len(ids)) - copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:], ids) + ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:]) } return nil @@ -230,7 +240,7 @@ func (f *freelist) reload(p *page) { // reindex rebuilds the free cache based on available and pending free lists. func (f *freelist) reindex() { - f.cache = make(map[pgid]bool) + f.cache = make(map[pgid]bool, len(f.ids)) for _, id := range f.ids { f.cache[id] = true } diff --git a/vendor/github.com/boltdb/bolt/node.go b/vendor/github.com/boltdb/bolt/node.go index e9d64af81..159318b22 100644 --- a/vendor/github.com/boltdb/bolt/node.go +++ b/vendor/github.com/boltdb/bolt/node.go @@ -201,6 +201,11 @@ func (n *node) write(p *page) { } p.count = uint16(len(n.inodes)) + // Stop here if there are no items to write. + if p.count == 0 { + return + } + // Loop over each item and write it to the page. b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):] for i, item := range n.inodes { diff --git a/vendor/github.com/boltdb/bolt/page.go b/vendor/github.com/boltdb/bolt/page.go index 4a555286a..cde403ae8 100644 --- a/vendor/github.com/boltdb/bolt/page.go +++ b/vendor/github.com/boltdb/bolt/page.go @@ -62,6 +62,9 @@ func (p *page) leafPageElement(index uint16) *leafPageElement { // leafPageElements retrieves a list of leaf nodes. func (p *page) leafPageElements() []leafPageElement { + if p.count == 0 { + return nil + } return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:] } @@ -72,6 +75,9 @@ func (p *page) branchPageElement(index uint16) *branchPageElement { // branchPageElements retrieves a list of branch nodes. func (p *page) branchPageElements() []branchPageElement { + if p.count == 0 { + return nil + } return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:] } @@ -139,12 +145,33 @@ func (a pgids) merge(b pgids) pgids { // Return the opposite slice if one is nil. if len(a) == 0 { return b - } else if len(b) == 0 { + } + if len(b) == 0 { return a } + merged := make(pgids, len(a)+len(b)) + mergepgids(merged, a, b) + return merged +} + +// mergepgids copies the sorted union of a and b into dst. +// If dst is too small, it panics. +func mergepgids(dst, a, b pgids) { + if len(dst) < len(a)+len(b) { + panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b))) + } + // Copy in the opposite slice if one is nil. + if len(a) == 0 { + copy(dst, b) + return + } + if len(b) == 0 { + copy(dst, a) + return + } - // Create a list to hold all elements from both lists. - merged := make(pgids, 0, len(a)+len(b)) + // Merged will hold all elements from both lists. + merged := dst[:0] // Assign lead to the slice with a lower starting value, follow to the higher value. lead, follow := a, b @@ -166,7 +193,5 @@ func (a pgids) merge(b pgids) pgids { } // Append what's left in follow. - merged = append(merged, follow...) - - return merged + _ = append(merged, follow...) } diff --git a/vendor/github.com/boltdb/bolt/tx.go b/vendor/github.com/boltdb/bolt/tx.go index 1cfb4cde8..6700308a2 100644 --- a/vendor/github.com/boltdb/bolt/tx.go +++ b/vendor/github.com/boltdb/bolt/tx.go @@ -381,7 +381,9 @@ func (tx *Tx) Check() <-chan error { func (tx *Tx) check(ch chan error) { // Check if any pages are double freed. freed := make(map[pgid]bool) - for _, id := range tx.db.freelist.all() { + all := make([]pgid, tx.db.freelist.count()) + tx.db.freelist.copyall(all) + for _, id := range all { if freed[id] { ch <- fmt.Errorf("page %d: already freed", id) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md b/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md index f4b911072..2568ecf0b 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md +++ b/vendor/github.com/brianvoe/gofakeit/v6/BENCHMARKS.md @@ -1,176 +1,458 @@ go test -bench=. -benchmem -goos: darwin -goarch: amd64 -pkg: github.com/brianvoe/gofakeit +goos: linux +goarch: amd64 +pkg: github.com/brianvoe/gofakeit/v6 +cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz Table generated with tablesgenerator.com/markdown_tables -| Benchmark | Ops | CPU | MEM | MEM alloc | -|---------------------------------|-----------|-------------|------------|--------------| -| BenchmarkAddress-16 | 797298 | 1649 ns/op | 248 B/op | 7 allocs/op | -| BenchmarkStreet-16 | 1987233 | 601 ns/op | 62 B/op | 3 allocs/op | -| BenchmarkStreetNumber-16 | 4808812 | 252 ns/op | 36 B/op | 2 allocs/op | -| BenchmarkStreetPrefix-16 | 12750800 | 83.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkStreetName-16 | 14026328 | 81.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkStreetSuffix-16 | 13836478 | 81.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCity-16 | 4617508 | 245 ns/op | 15 B/op | 1 allocs/op | -| BenchmarkState-16 | 12095868 | 86.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkStateAbr-16 | 13337152 | 83.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkZip-16 | 6264339 | 201 ns/op | 5 B/op | 1 allocs/op | -| BenchmarkCountry-16 | 12378775 | 85.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCountryAbr-16 | 12770610 | 86.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLatitude-16 | 30935530 | 32.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLongitude-16 | 35305698 | 32.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLatitudeInRange-16 | 35285907 | 34.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLongitudeInRange-16 | 29716158 | 34.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPetName-16 | 15559858 | 69.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAnimal-16 | 15493616 | 71.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAnimalType-16 | 15802927 | 72.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFarmAnimal-16 | 13610484 | 81.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCat-16 | 14966256 | 76.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDog-16 | 12833390 | 88.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUsername-16 | 5720742 | 220 ns/op | 16 B/op | 2 allocs/op | -| BenchmarkPassword-16 | 2016339 | 593 ns/op | 304 B/op | 6 allocs/op | -| BenchmarkBeerName-16 | 15339746 | 72.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerStyle-16 | 12902784 | 86.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerHop-16 | 15131584 | 71.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerYeast-16 | 14747238 | 73.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerMalt-16 | 14982421 | 78.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBeerIbu-16 | 20595496 | 53.4 ns/op | 8 B/op | 1 allocs/op | -| BenchmarkBeerAlcohol-16 | 3921880 | 299 ns/op | 40 B/op | 3 allocs/op | -| BenchmarkBeerBlg-16 | 4150712 | 300 ns/op | 48 B/op | 3 allocs/op | -| BenchmarkCar-16 | 1996923 | 597 ns/op | 96 B/op | 1 allocs/op | -| BenchmarkCarType-16 | 17076163 | 65.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarFuelType-16 | 14844217 | 73.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarTransmissionType-16 | 16047379 | 68.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarMaker-16 | 14501310 | 76.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCarModel-16 | 12503469 | 87.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkColor-16 | 14812000 | 75.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSafeColor-16 | 17647850 | 66.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHexColor-16 | 3710928 | 326 ns/op | 24 B/op | 3 allocs/op | -| BenchmarkRGBColor-16 | 12641104 | 83.3 ns/op | 32 B/op | 1 allocs/op | -| BenchmarkCompany-16 | 17277220 | 67.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCompanySuffix-16 | 17099479 | 60.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBuzzWord-16 | 15963231 | 68.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBS-16 | 15149085 | 71.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkJob-16 | 3203989 | 383 ns/op | 64 B/op | 1 allocs/op | -| BenchmarkJobTitle-16 | 15232904 | 70.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkJobDescriptor-16 | 15603652 | 69.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkJobLevel-16 | 14281743 | 77.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmoji-16 | 15016417 | 75.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiDescription-16 | 14764699 | 76.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiCategory-16 | 13463936 | 78.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiAlias-16 | 12291789 | 87.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkEmojiTag-16 | 13451284 | 82.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFileMimeType-16 | 16654501 | 67.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFileExtension-16 | 13656126 | 73.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFruit-16 | 15039096 | 74.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkVegetable-16 | 14397543 | 76.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBreakfast-16 | 5960095 | 181 ns/op | 35 B/op | 1 allocs/op | -| BenchmarkLunch-16 | 6350367 | 189 ns/op | 37 B/op | 1 allocs/op | -| BenchmarkDinner-16 | 6245412 | 177 ns/op | 37 B/op | 1 allocs/op | -| BenchmarkSnack-16 | 5891965 | 192 ns/op | 36 B/op | 1 allocs/op | -| BenchmarkDessert-16 | 6603031 | 186 ns/op | 34 B/op | 2 allocs/op | -| BenchmarkGamertag-16 | 3237366 | 352 ns/op | 36 B/op | 3 allocs/op | -| BenchmarkGenerate-16 | 457622 | 2652 ns/op | 916 B/op | 23 allocs/op | -| BenchmarkMap-16 | 290334 | 4145 ns/op | 1082 B/op | 16 allocs/op | -| BenchmarkHackerPhrase-16 | 200760 | 5623 ns/op | 2909 B/op | 37 allocs/op | -| BenchmarkHackerAbbreviation-16 | 15939142 | 71.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerAdjective-16 | 14837203 | 70.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerNoun-16 | 14633212 | 72.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerVerb-16 | 13376676 | 82.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHackerIngverb-16 | 14869647 | 72.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkReplaceWithNumbers-16 | 4214044 | 287 ns/op | 32 B/op | 1 allocs/op | -| BenchmarkHipsterWord-16 | 14753112 | 71.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHipsterSentence-16 | 871815 | 1396 ns/op | 305 B/op | 3 allocs/op | -| BenchmarkHipsterParagraph-16 | 42579 | 28624 ns/op | 10560 B/op | 48 allocs/op | -| BenchmarkImageURL-16 | 10556988 | 121 ns/op | 38 B/op | 3 allocs/op | -| BenchmarkDomainName-16 | 2852584 | 428 ns/op | 53 B/op | 2 allocs/op | -| BenchmarkDomainSuffix-16 | 15614646 | 70.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkURL-16 | 1128352 | 1056 ns/op | 189 B/op | 4 allocs/op | -| BenchmarkHTTPMethod-16 | 15604741 | 72.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkIPv4Address-16 | 3539780 | 332 ns/op | 48 B/op | 5 allocs/op | -| BenchmarkIPv6Address-16 | 2419968 | 490 ns/op | 96 B/op | 7 allocs/op | -| BenchmarkMacAddress-16 | 2003596 | 619 ns/op | 79 B/op | 6 allocs/op | -| BenchmarkHTTPStatusCode-16 | 22232200 | 50.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHTTPStatusCodeSimple-16 | 21198192 | 48.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLogLevel-16 | 13729278 | 78.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUserAgent-16 | 1000000 | 1044 ns/op | 300 B/op | 5 allocs/op | -| BenchmarkChromeUserAgent-16 | 1591886 | 783 ns/op | 188 B/op | 5 allocs/op | -| BenchmarkFirefoxUserAgent-16 | 742941 | 1400 ns/op | 362 B/op | 6 allocs/op | -| BenchmarkSafariUserAgent-16 | 930159 | 1306 ns/op | 551 B/op | 7 allocs/op | -| BenchmarkOperaUserAgent-16 | 1454205 | 829 ns/op | 216 B/op | 5 allocs/op | -| BenchmarkLanguage-16 | 15265677 | 71.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLanguageAbbreviation-16 | 16144437 | 68.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkProgrammingLanguage-16 | 16125788 | 71.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkProgrammingLanguageBest-16 | 1000000000 | 0.229 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkBool-16 | 79448815 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUUID-16 | 11553009 | 106 ns/op | 48 B/op | 1 allocs/op | -| BenchmarkNumber-16 | 59585859 | 17.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint8-16 | 79947612 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint16-16 | 79249844 | 15.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint32-16 | 81112372 | 14.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkUint64-16 | 50800922 | 20.5 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt8-16 | 66494482 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt16-16 | 79505629 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt32-16 | 79967979 | 15.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkInt64-16 | 60566858 | 19.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat32-16 | 84251548 | 14.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat32Range-16 | 80528571 | 14.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat64-16 | 94149510 | 12.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkFloat64Range-16 | 94346104 | 12.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkShuffleInts-16 | 9075564 | 130 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCurrency-16 | 11273227 | 115 ns/op | 32 B/op | 1 allocs/op | -| BenchmarkCurrencyShort-16 | 15565836 | 72.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCurrencyLong-16 | 15420937 | 71.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPrice-16 | 80781411 | 15.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCreditCard-16 | 1637452 | 751 ns/op | 88 B/op | 4 allocs/op | -| BenchmarkCreditCardType-16 | 17678868 | 64.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkCreditCardNumber-16 | 3361524 | 349 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkCreditCardNumberLuhn-16 | 279769 | 3620 ns/op | 160 B/op | 10 allocs/op | -| BenchmarkCreditCardExp-16 | 7523824 | 150 ns/op | 5 B/op | 1 allocs/op | -| BenchmarkCreditCardCvv-16 | 15185973 | 73.6 ns/op | 3 B/op | 1 allocs/op | -| BenchmarkName-16 | 5436148 | 215 ns/op | 17 B/op | 1 allocs/op | -| BenchmarkFirstName-16 | 14362125 | 72.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLastName-16 | 15530926 | 72.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNamePrefix-16 | 18074462 | 66.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNameSuffix-16 | 14657012 | 73.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSSN-16 | 18693813 | 68.9 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkGender-16 | 72023787 | 15.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPerson-16 | 282908 | 4377 ns/op | 752 B/op | 24 allocs/op | -| BenchmarkContact-16 | 1369327 | 911 ns/op | 146 B/op | 6 allocs/op | -| BenchmarkPhone-16 | 6015615 | 204 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkPhoneFormatted-16 | 3928914 | 296 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkEmail-16 | 1901041 | 653 ns/op | 98 B/op | 4 allocs/op | -| BenchmarkLetter-16 | 65959573 | 17.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDigit-16 | 58815334 | 17.4 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNumerify-16 | 5526314 | 207 ns/op | 16 B/op | 1 allocs/op | -| BenchmarkLexify-16 | 9712312 | 129 ns/op | 8 B/op | 1 allocs/op | -| BenchmarkShuffleStrings-16 | 8997901 | 119 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDate-16 | 5949220 | 194 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDateRange-16 | 7122076 | 166 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkMonth-16 | 56979296 | 19.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkDay-16 | 61808844 | 17.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkWeekDay-16 | 62598561 | 19.3 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkYear-16 | 14533374 | 76.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkHour-16 | 62130793 | 17.0 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkMinute-16 | 66836017 | 17.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSecond-16 | 69860632 | 17.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNanoSecond-16 | 66957362 | 17.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZone-16 | 13841594 | 78.7 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZoneFull-16 | 12788362 | 89.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZoneAbv-16 | 14413452 | 77.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkTimeZoneOffset-16 | 10699014 | 103 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkNoun-16 | 15025992 | 74.6 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkVerb-16 | 13394044 | 82.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAdverb-16 | 13968967 | 78.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkPreposition-16 | 14575834 | 81.1 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkAdjective-16 | 13957762 | 82.9 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkWord-16 | 11083752 | 98.2 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkSentence-16 | 647954 | 1642 ns/op | 251 B/op | 2 allocs/op | -| BenchmarkParagraph-16 | 34026 | 35489 ns/op | 9587 B/op | 47 allocs/op | -| BenchmarkLoremIpsumWord-16 | 15156211 | 70.8 ns/op | 0 B/op | 0 allocs/op | -| BenchmarkLoremIpsumSentence-16 | 908371 | 1293 ns/op | 229 B/op | 2 allocs/op | -| BenchmarkLoremIpsumParagraph-16 | 41920 | 27860 ns/op | 9214 B/op | 45 allocs/op | -| BenchmarkQuestion-16 | 1000000 | 1152 ns/op | 315 B/op | 4 allocs/op | -| BenchmarkQuote-16 | 924054 | 1263 ns/op | 268 B/op | 3 allocs/op | -| BenchmarkPhrase-16 | 11034157 | 94.6 ns/op | 0 B/op | 0 allocs/op | \ No newline at end of file +| Benchmark | Ops | CPU | MEM | MEM alloc | +|--------------------------------------------------|------------|------------------|----------------|-------------------| +| BenchmarkAddress/package-8 | 1270872 | 940.1 ns/op | 197 B/op | 5 allocs/op | +| BenchmarkAddress/Faker_math-8 | 1238563 | 1042 ns/op | 197 B/op | 5 allocs/op | +| BenchmarkAddress/Faker_crypto-8 | 139857 | 7862 ns/op | 197 B/op | 5 allocs/op | +| BenchmarkStreet/package-8 | 2955518 | 422.6 ns/op | 26 B/op | 2 allocs/op | +| BenchmarkStreet/Faker_math-8 | 3027224 | 427.3 ns/op | 26 B/op | 2 allocs/op | +| BenchmarkStreet/Faker_crypto-8 | 352165 | 3559 ns/op | 26 B/op | 2 allocs/op | +| BenchmarkStreetNumber/package-8 | 6842211 | 149.2 ns/op | 4 B/op | 1 allocs/op | +| BenchmarkStreetNumber/Faker_math-8 | 6924288 | 158.8 ns/op | 4 B/op | 1 allocs/op | +| BenchmarkStreetNumber/Faker_crypto-8 | 549988 | 1900 ns/op | 4 B/op | 1 allocs/op | +| BenchmarkStreetPrefix/package-8 | 18441643 | 74.12 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetPrefix/Faker_math-8 | 17888110 | 67.51 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetPrefix/Faker_crypto-8 | 2650390 | 458.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetName/package-8 | 18799832 | 62.90 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetName/Faker_math-8 | 16124620 | 63.57 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetName/Faker_crypto-8 | 2873138 | 428.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetSuffix/package-8 | 17192164 | 72.19 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetSuffix/Faker_math-8 | 16545355 | 65.44 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStreetSuffix/Faker_crypto-8 | 2986934 | 450.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCity/package-8 | 18553683 | 64.93 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCity/Faker_math-8 | 17648109 | 63.77 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCity/Faker_crypto-8 | 2567427 | 470.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkState/package-8 | 18262387 | 66.25 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkState/Faker_math-8 | 16690209 | 73.21 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkState/Faker_crypto-8 | 2599795 | 401.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStateAbr/package-8 | 17492332 | 63.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStateAbr/Faker_math-8 | 18612169 | 64.82 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkStateAbr/Faker_crypto-8 | 2821579 | 460.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkZip/package-8 | 7573238 | 157.1 ns/op | 5 B/op | 1 allocs/op | +| BenchmarkZip/Faker_math-8 | 6644562 | 163.4 ns/op | 5 B/op | 1 allocs/op | +| BenchmarkZip/Faker_crypto-8 | 484525 | 2470 ns/op | 5 B/op | 1 allocs/op | +| BenchmarkCountry/package-8 | 15623450 | 65.65 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountry/Faker_math-8 | 17786485 | 76.22 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountry/Faker_crypto-8 | 3002818 | 400.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountryAbr/package-8 | 17296935 | 66.75 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountryAbr/Faker_math-8 | 17862819 | 67.41 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCountryAbr/Faker_crypto-8 | 2931120 | 426.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitude/package-8 | 46248466 | 26.11 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitude/Faker_math-8 | 46120956 | 26.00 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitude/Faker_crypto-8 | 3512108 | 366.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitude/package-8 | 47443129 | 24.03 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitude/Faker_math-8 | 46691144 | 24.64 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitude/Faker_crypto-8 | 3501789 | 365.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitudeInRange/package-8 | 44125588 | 26.96 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitudeInRange/Faker_math-8 | 40113348 | 27.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLatitudeInRange/Faker_crypto-8 | 3227358 | 378.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitudeInRange/package-8 | 38948743 | 32.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitudeInRange/Faker_math-8 | 36491187 | 27.86 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLongitudeInRange/Faker_crypto-8 | 3004773 | 350.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkPetName/package-8 | 23445927 | 60.81 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkPetName/Faker_math-8 | 23982228 | 53.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkPetName/Faker_crypto-8 | 2681886 | 458.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimal/package-8 | 23230071 | 55.13 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimal/Faker_math-8 | 21923606 | 53.10 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimal/Faker_crypto-8 | 2680177 | 411.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimalType/package-8 | 18826995 | 53.45 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimalType/Faker_math-8 | 22170756 | 63.39 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAnimalType/Faker_crypto-8 | 2780270 | 399.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFarmAnimal/package-8 | 18548028 | 64.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFarmAnimal/Faker_math-8 | 17291526 | 62.47 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFarmAnimal/Faker_crypto-8 | 2543520 | 409.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCat/package-8 | 21213028 | 68.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCat/Faker_math-8 | 19973062 | 58.74 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCat/Faker_crypto-8 | 2985601 | 405.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDog/package-8 | 16995627 | 68.15 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDog/Faker_math-8 | 17296502 | 81.35 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDog/Faker_crypto-8 | 2530860 | 433.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBird/package-8 | 14445968 | 81.31 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBird/Faker_math-8 | 14545851 | 82.69 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBird/Faker_crypto-8 | 2892721 | 420.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkAppName/package-8 | 2799828 | 438.6 ns/op | 25 B/op | 1 allocs/op | +| BenchmarkAppName/Faker_math-8 | 2784135 | 431.1 ns/op | 25 B/op | 1 allocs/op | +| BenchmarkAppName/Faker_crypto-8 | 611072 | 1923 ns/op | 25 B/op | 1 allocs/op | +| BenchmarkAppVersion/package-8 | 7552165 | 154.1 ns/op | 7 B/op | 1 allocs/op | +| BenchmarkAppVersion/Faker_math-8 | 8020767 | 156.6 ns/op | 7 B/op | 1 allocs/op | +| BenchmarkAppVersion/Faker_crypto-8 | 875899 | 1209 ns/op | 7 B/op | 1 allocs/op | +| BenchmarkAppAuthor/package-8 | 9596493 | 119.7 ns/op | 8 B/op | 0 allocs/op | +| BenchmarkAppAuthor/Faker_math-8 | 10068729 | 121.0 ns/op | 8 B/op | 0 allocs/op | +| BenchmarkAppAuthor/Faker_crypto-8 | 1212542 | 983.7 ns/op | 8 B/op | 0 allocs/op | +| BenchmarkUsername/package-8 | 6687600 | 174.6 ns/op | 16 B/op | 2 allocs/op | +| BenchmarkUsername/Faker_math-8 | 7233685 | 173.3 ns/op | 16 B/op | 2 allocs/op | +| BenchmarkUsername/Faker_crypto-8 | 616884 | 2166 ns/op | 16 B/op | 2 allocs/op | +| BenchmarkPassword/package-8 | 2966407 | 401.0 ns/op | 336 B/op | 6 allocs/op | +| BenchmarkPassword/Faker_math-8 | 3080845 | 399.8 ns/op | 336 B/op | 6 allocs/op | +| BenchmarkPassword/Faker_crypto-8 | 182074 | 5963 ns/op | 336 B/op | 6 allocs/op | +| BenchmarkBeerName/package-8 | 23768442 | 53.26 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerName/Faker_math-8 | 22010898 | 63.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerName/Faker_crypto-8 | 2569424 | 392.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerStyle/package-8 | 17567354 | 69.64 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerStyle/Faker_math-8 | 16695721 | 80.73 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerStyle/Faker_crypto-8 | 2710214 | 407.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerHop/package-8 | 20877854 | 56.43 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerHop/Faker_math-8 | 22603234 | 65.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerHop/Faker_crypto-8 | 2618493 | 419.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerYeast/package-8 | 20738073 | 67.89 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerYeast/Faker_math-8 | 21325231 | 67.34 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerYeast/Faker_crypto-8 | 3042529 | 399.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerMalt/package-8 | 15756969 | 65.67 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerMalt/Faker_math-8 | 18026910 | 71.42 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerMalt/Faker_crypto-8 | 2949741 | 429.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBeerIbu/package-8 | 32683443 | 35.57 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkBeerIbu/Faker_math-8 | 29983339 | 36.03 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkBeerIbu/Faker_crypto-8 | 3094896 | 386.6 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkBeerAlcohol/package-8 | 4744302 | 243.6 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkBeerAlcohol/Faker_math-8 | 4718923 | 252.0 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkBeerAlcohol/Faker_crypto-8 | 1952740 | 656.0 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkBeerBlg/package-8 | 4086861 | 270.6 ns/op | 40 B/op | 3 allocs/op | +| BenchmarkBeerBlg/Faker_math-8 | 4488897 | 259.5 ns/op | 40 B/op | 3 allocs/op | +| BenchmarkBeerBlg/Faker_crypto-8 | 1865367 | 646.7 ns/op | 40 B/op | 3 allocs/op | +| BenchmarkCar/package-8 | 2800782 | 400.5 ns/op | 96 B/op | 1 allocs/op | +| BenchmarkCar/Faker_math-8 | 2938509 | 396.5 ns/op | 96 B/op | 1 allocs/op | +| BenchmarkCar/Faker_crypto-8 | 461906 | 2590 ns/op | 96 B/op | 1 allocs/op | +| BenchmarkCarType/package-8 | 23655384 | 51.72 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarType/Faker_math-8 | 25902462 | 50.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarType/Faker_crypto-8 | 3035287 | 455.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarFuelType/package-8 | 18750069 | 63.80 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarFuelType/Faker_math-8 | 18858705 | 63.15 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarFuelType/Faker_crypto-8 | 3028026 | 387.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarTransmissionType/package-8 | 22570701 | 54.01 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarTransmissionType/Faker_math-8 | 21484246 | 64.27 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarTransmissionType/Faker_crypto-8 | 3061364 | 387.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarMaker/package-8 | 17628445 | 68.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarMaker/Faker_math-8 | 21573310 | 64.19 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarMaker/Faker_crypto-8 | 2688284 | 475.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarModel/package-8 | 18500498 | 73.43 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarModel/Faker_math-8 | 16116993 | 66.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCarModel/Faker_crypto-8 | 2487638 | 440.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityActor/package-8 | 18712833 | 74.12 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityActor/Faker_math-8 | 18564168 | 68.96 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityActor/Faker_crypto-8 | 2593150 | 415.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityBusiness/package-8 | 18721152 | 68.98 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityBusiness/Faker_math-8 | 16916186 | 70.66 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebrityBusiness/Faker_crypto-8 | 2578786 | 407.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebritySport/package-8 | 16716724 | 87.51 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebritySport/Faker_math-8 | 16602294 | 86.41 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCelebritySport/Faker_crypto-8 | 2919696 | 419.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkColor/package-8 | 17871778 | 62.28 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkColor/Faker_math-8 | 21601353 | 62.63 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkColor/Faker_crypto-8 | 3040459 | 463.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkNiceColors/package-8 | 81438092 | 14.86 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkNiceColors/Faker_math-8 | 75775309 | 18.52 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkNiceColors/Faker_crypto-8 | 3450939 | 353.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSafeColor/package-8 | 22775230 | 53.52 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSafeColor/Faker_math-8 | 24526308 | 59.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSafeColor/Faker_crypto-8 | 3103851 | 413.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHexColor/package-8 | 4640522 | 255.2 ns/op | 24 B/op | 3 allocs/op | +| BenchmarkHexColor/Faker_math-8 | 4723542 | 257.2 ns/op | 24 B/op | 3 allocs/op | +| BenchmarkHexColor/Faker_crypto-8 | 283828 | 4447 ns/op | 24 B/op | 3 allocs/op | +| BenchmarkRGBColor/package-8 | 19721971 | 59.64 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkRGBColor/Faker_math-8 | 18808492 | 67.35 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkRGBColor/Faker_crypto-8 | 1000000 | 1066 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkCompany/package-8 | 22072651 | 48.06 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompany/Faker_math-8 | 22528284 | 53.94 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompany/Faker_crypto-8 | 2690668 | 402.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompanySuffix/package-8 | 28169413 | 48.00 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompanySuffix/Faker_math-8 | 20685153 | 52.20 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCompanySuffix/Faker_crypto-8 | 3018765 | 418.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBuzzWord/package-8 | 24238677 | 54.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBuzzWord/Faker_math-8 | 22195419 | 52.30 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBuzzWord/Faker_crypto-8 | 2840428 | 392.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBS/package-8 | 23481436 | 56.33 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBS/Faker_math-8 | 23195737 | 65.66 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBS/Faker_crypto-8 | 3027972 | 419.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJob/package-8 | 4432520 | 253.5 ns/op | 64 B/op | 1 allocs/op | +| BenchmarkJob/Faker_math-8 | 4513154 | 253.7 ns/op | 64 B/op | 1 allocs/op | +| BenchmarkJob/Faker_crypto-8 | 686028 | 1716 ns/op | 64 B/op | 1 allocs/op | +| BenchmarkJobTitle/package-8 | 20079558 | 54.21 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobTitle/Faker_math-8 | 21871627 | 54.86 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobTitle/Faker_crypto-8 | 3017896 | 413.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobDescriptor/package-8 | 21579855 | 53.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobDescriptor/Faker_math-8 | 24638751 | 55.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobDescriptor/Faker_crypto-8 | 2984810 | 415.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobLevel/package-8 | 18311070 | 59.35 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobLevel/Faker_math-8 | 17051210 | 59.53 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkJobLevel/Faker_crypto-8 | 2991106 | 426.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCSVLookup100-8 | 1468 | 780852 ns/op | 437416 B/op | 5933 allocs/op | +| BenchmarkCSVLookup1000-8 | 151 | 7853471 ns/op | 4224820 B/op | 59612 allocs/op | +| BenchmarkCSVLookup10000-8 | 14 | 78165009 ns/op | 41208010 B/op | 597842 allocs/op | +| BenchmarkCSVLookup100000-8 | 2 | 768800840 ns/op | 437275164 B/op | 5980461 allocs/op | +| BenchmarkEmoji/package-8 | 22212386 | 54.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmoji/Faker_math-8 | 21471013 | 51.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmoji/Faker_crypto-8 | 3036081 | 458.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiDescription/package-8 | 18250413 | 57.08 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiDescription/Faker_math-8 | 21924381 | 57.58 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiDescription/Faker_crypto-8 | 2837050 | 387.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiCategory/package-8 | 21270252 | 55.87 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiCategory/Faker_math-8 | 21421813 | 59.59 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiCategory/Faker_crypto-8 | 2635878 | 491.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiAlias/package-8 | 18760875 | 68.20 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiAlias/Faker_math-8 | 16918242 | 67.60 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiAlias/Faker_crypto-8 | 2854717 | 488.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiTag/package-8 | 19953885 | 65.43 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiTag/Faker_math-8 | 18220396 | 72.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkEmojiTag/Faker_crypto-8 | 2802847 | 426.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkError/package-8 | 1547610 | 786.6 ns/op | 279 B/op | 8 allocs/op | +| BenchmarkError/Faker_math-8 | 1504578 | 794.1 ns/op | 279 B/op | 8 allocs/op | +| BenchmarkError/Faker_crypto-8 | 800712 | 1476 ns/op | 279 B/op | 8 allocs/op | +| BenchmarkErrorObject/package-8 | 6054552 | 190.3 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkErrorObject/Faker_math-8 | 5968180 | 190.3 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkErrorObject/Faker_crypto-8 | 2088008 | 618.0 ns/op | 32 B/op | 3 allocs/op | +| BenchmarkErrorDatabase/package-8 | 5275713 | 212.8 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorDatabase/Faker_math-8 | 5407803 | 217.3 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorDatabase/Faker_crypto-8 | 2005333 | 628.7 ns/op | 63 B/op | 3 allocs/op | +| BenchmarkErrorGRPC/package-8 | 5700810 | 202.9 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorGRPC/Faker_math-8 | 5907589 | 202.5 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorGRPC/Faker_crypto-8 | 2027650 | 643.3 ns/op | 64 B/op | 3 allocs/op | +| BenchmarkErrorHTTP/package-8 | 3182026 | 321.6 ns/op | 157 B/op | 4 allocs/op | +| BenchmarkErrorHTTP/Faker_math-8 | 3667356 | 314.9 ns/op | 157 B/op | 4 allocs/op | +| BenchmarkErrorHTTP/Faker_crypto-8 | 1590696 | 720.2 ns/op | 157 B/op | 4 allocs/op | +| BenchmarkErrorHTTPClient/package-8 | 5745494 | 204.0 ns/op | 52 B/op | 3 allocs/op | +| BenchmarkErrorHTTPClient/Faker_math-8 | 5549187 | 212.8 ns/op | 52 B/op | 3 allocs/op | +| BenchmarkErrorHTTPClient/Faker_crypto-8 | 2011905 | 596.7 ns/op | 52 B/op | 3 allocs/op | +| BenchmarkErrorHTTPServer/package-8 | 5466012 | 214.7 ns/op | 59 B/op | 3 allocs/op | +| BenchmarkErrorHTTPServer/Faker_math-8 | 5542838 | 207.3 ns/op | 59 B/op | 3 allocs/op | +| BenchmarkErrorHTTPServer/Faker_crypto-8 | 1939080 | 633.9 ns/op | 59 B/op | 3 allocs/op | +| BenchmarkErrorRuntime/package-8 | 4245986 | 263.4 ns/op | 150 B/op | 3 allocs/op | +| BenchmarkErrorRuntime/Faker_math-8 | 4355534 | 263.1 ns/op | 150 B/op | 3 allocs/op | +| BenchmarkErrorRuntime/Faker_crypto-8 | 1782044 | 651.4 ns/op | 150 B/op | 3 allocs/op | +| BenchmarkErrorValidation/package-8 | 1659858 | 715.7 ns/op | 268 B/op | 7 allocs/op | +| BenchmarkErrorValidation/Faker_math-8 | 1690849 | 716.4 ns/op | 268 B/op | 7 allocs/op | +| BenchmarkErrorValidation/Faker_crypto-8 | 883600 | 1348 ns/op | 268 B/op | 7 allocs/op | +| BenchmarkFileMimeType/package-8 | 18005230 | 56.88 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileMimeType/Faker_math-8 | 21229381 | 54.62 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileMimeType/Faker_crypto-8 | 2605701 | 462.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileExtension/package-8 | 19272264 | 73.07 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileExtension/Faker_math-8 | 20149288 | 60.79 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFileExtension/Faker_crypto-8 | 2627210 | 423.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkCusip/package-8 | 5402995 | 224.9 ns/op | 24 B/op | 2 allocs/op | +| BenchmarkCusip/Faker_math-8 | 5367218 | 221.1 ns/op | 24 B/op | 2 allocs/op | +| BenchmarkCusip/Faker_crypto-8 | 363460 | 2967 ns/op | 24 B/op | 2 allocs/op | +| BenchmarkIsin/package-8 | 1742368 | 701.4 ns/op | 533 B/op | 8 allocs/op | +| BenchmarkIsin/Faker_math-8 | 1653408 | 715.5 ns/op | 533 B/op | 8 allocs/op | +| BenchmarkIsin/Faker_crypto-8 | 330396 | 3583 ns/op | 533 B/op | 8 allocs/op | +| BenchmarkFruit/package-8 | 21421066 | 55.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFruit/Faker_math-8 | 22680361 | 55.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkFruit/Faker_crypto-8 | 2914611 | 486.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkVegetable/package-8 | 21113413 | 56.44 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkVegetable/Faker_math-8 | 21101716 | 60.98 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkVegetable/Faker_crypto-8 | 2811384 | 467.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBreakfast/package-8 | 8954784 | 127.7 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkBreakfast/Faker_math-8 | 9430814 | 128.8 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkBreakfast/Faker_crypto-8 | 2132481 | 496.5 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkLunch/package-8 | 8934501 | 125.9 ns/op | 34 B/op | 1 allocs/op | +| BenchmarkLunch/Faker_math-8 | 8668546 | 128.9 ns/op | 34 B/op | 1 allocs/op | +| BenchmarkLunch/Faker_crypto-8 | 2216348 | 518.3 ns/op | 34 B/op | 1 allocs/op | +| BenchmarkDinner/package-8 | 9317936 | 125.2 ns/op | 36 B/op | 1 allocs/op | +| BenchmarkDinner/Faker_math-8 | 9023473 | 126.3 ns/op | 36 B/op | 1 allocs/op | +| BenchmarkDinner/Faker_crypto-8 | 2435984 | 518.9 ns/op | 36 B/op | 1 allocs/op | +| BenchmarkDrink/package-8 | 7698025 | 143.4 ns/op | 7 B/op | 2 allocs/op | +| BenchmarkDrink/Faker_math-8 | 8096294 | 139.8 ns/op | 7 B/op | 2 allocs/op | +| BenchmarkDrink/Faker_crypto-8 | 2247427 | 536.2 ns/op | 7 B/op | 2 allocs/op | +| BenchmarkSnack/package-8 | 8109601 | 149.2 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkSnack/Faker_math-8 | 7993006 | 150.5 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkSnack/Faker_crypto-8 | 2214736 | 535.7 ns/op | 32 B/op | 1 allocs/op | +| BenchmarkDessert/package-8 | 8295364 | 133.9 ns/op | 31 B/op | 2 allocs/op | +| BenchmarkDessert/Faker_math-8 | 8610325 | 134.1 ns/op | 31 B/op | 2 allocs/op | +| BenchmarkDessert/Faker_crypto-8 | 2205777 | 507.4 ns/op | 31 B/op | 2 allocs/op | +| BenchmarkGamertag/package-8 | 2111506 | 544.8 ns/op | 83 B/op | 5 allocs/op | +| BenchmarkGamertag/Faker_math-8 | 2203573 | 551.4 ns/op | 83 B/op | 5 allocs/op | +| BenchmarkGamertag/Faker_crypto-8 | 487366 | 2428 ns/op | 83 B/op | 5 allocs/op | +| BenchmarkDice/package-8 | 43259642 | 26.58 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkDice/Faker_math-8 | 42908084 | 26.84 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkDice/Faker_crypto-8 | 2953483 | 395.5 ns/op | 8 B/op | 1 allocs/op | +| BenchmarkGenerate/package-8 | 383122 | 2767 ns/op | 1139 B/op | 29 allocs/op | +| BenchmarkGenerate/Complex-8 | 135508 | 8555 ns/op | 4440 B/op | 80 allocs/op | +| BenchmarkGenerate/Faker_math-8 | 377151 | 2817 ns/op | 1139 B/op | 29 allocs/op | +| BenchmarkGenerate/Faker_crypto-8 | 152226 | 7234 ns/op | 1139 B/op | 29 allocs/op | +| BenchmarkRegex/package-8 | 628683 | 1922 ns/op | 1632 B/op | 27 allocs/op | +| BenchmarkRegex/Faker_math-8 | 591548 | 1940 ns/op | 1632 B/op | 27 allocs/op | +| BenchmarkRegex/Faker_crypto-8 | 616701 | 1934 ns/op | 1632 B/op | 27 allocs/op | +| BenchmarkRegexEmail/package-8 | 174812 | 6607 ns/op | 4084 B/op | 90 allocs/op | +| BenchmarkRegexEmail/Faker_math-8 | 174512 | 6619 ns/op | 4084 B/op | 90 allocs/op | +| BenchmarkRegexEmail/Faker_crypto-8 | 62312 | 18793 ns/op | 4083 B/op | 90 allocs/op | +| BenchmarkMap/package-8 | 318559 | 3275 ns/op | 1113 B/op | 16 allocs/op | +| BenchmarkMap/Faker_math-8 | 315990 | 3319 ns/op | 1113 B/op | 16 allocs/op | +| BenchmarkMap/Faker_crypto-8 | 46202 | 23997 ns/op | 1115 B/op | 16 allocs/op | +| BenchmarkHackerPhrase/package-8 | 155998 | 7191 ns/op | 3004 B/op | 50 allocs/op | +| BenchmarkHackerPhrase/Faker_math-8 | 154675 | 7305 ns/op | 3008 B/op | 50 allocs/op | +| BenchmarkHackerPhrase/Faker_crypto-8 | 109282 | 10268 ns/op | 3007 B/op | 50 allocs/op | +| BenchmarkHackerAbbreviation/package-8 | 21881574 | 57.57 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAbbreviation/Faker_math-8 | 18534495 | 59.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAbbreviation/Faker_crypto-8 | 2607735 | 401.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAdjective/package-8 | 24286845 | 55.74 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAdjective/Faker_math-8 | 22684101 | 55.22 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerAdjective/Faker_crypto-8 | 2953530 | 490.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerNoun/package-8 | 22554241 | 55.35 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerNoun/Faker_math-8 | 18360708 | 56.78 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerNoun/Faker_crypto-8 | 2823256 | 464.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerVerb/package-8 | 19236123 | 65.49 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerVerb/Faker_math-8 | 18090754 | 68.18 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackerVerb/Faker_crypto-8 | 2880181 | 439.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackeringVerb/package-8 | 19090326 | 71.74 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackeringVerb/Faker_math-8 | 19048659 | 63.31 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHackeringVerb/Faker_crypto-8 | 3020748 | 404.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkReplaceWithNumbers-8 | 162931 | 7098 ns/op | 32 B/op | 2 allocs/op | +| BenchmarkHipsterWord/package-8 | 24059244 | 54.69 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHipsterWord/Faker_math-8 | 21708511 | 52.98 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHipsterWord/Faker_crypto-8 | 2870858 | 396.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHipsterSentence/package-8 | 1278764 | 927.7 ns/op | 288 B/op | 3 allocs/op | +| BenchmarkHipsterSentence/Faker_math-8 | 1287939 | 955.0 ns/op | 288 B/op | 3 allocs/op | +| BenchmarkHipsterSentence/Faker_crypto-8 | 237703 | 4595 ns/op | 288 B/op | 3 allocs/op | +| BenchmarkHipsterParagraph/package-8 | 57895 | 18466 ns/op | 10521 B/op | 48 allocs/op | +| BenchmarkHipsterParagraph/Faker_math-8 | 61772 | 19188 ns/op | 10520 B/op | 48 allocs/op | +| BenchmarkHipsterParagraph/Faker_crypto-8 | 12978 | 91733 ns/op | 10522 B/op | 48 allocs/op | +| BenchmarkInputName/package-8 | 15728428 | 74.49 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkInputName/Faker_math-8 | 13243030 | 89.75 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkInputName/Faker_crypto-8 | 2736225 | 478.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkSvg/package-8 | 172828 | 7906 ns/op | 8871 B/op | 52 allocs/op | +| BenchmarkSvg/Faker_math-8 | 161821 | 6754 ns/op | 8875 B/op | 52 allocs/op | +| BenchmarkSvg/Faker_crypto-8 | 29023 | 40910 ns/op | 8862 B/op | 52 allocs/op | +| BenchmarkImageURL/package-8 | 11692422 | 94.34 ns/op | 38 B/op | 3 allocs/op | +| BenchmarkImageURL/Faker_math-8 | 11451087 | 91.39 ns/op | 38 B/op | 3 allocs/op | +| BenchmarkImageURL/Faker_crypto-8 | 12107578 | 92.30 ns/op | 38 B/op | 3 allocs/op | +| BenchmarkImage/package-8 | 50 | 20495942 ns/op | 2457673 B/op | 307202 allocs/op | +| BenchmarkImage/Faker_math-8 | 51 | 20349126 ns/op | 2457780 B/op | 307202 allocs/op | +| BenchmarkImage/Faker_crypto-8 | 3 | 393591549 ns/op | 2457685 B/op | 307202 allocs/op | +| BenchmarkImageJpeg/package-8 | 31 | 32857846 ns/op | 2982318 B/op | 307214 allocs/op | +| BenchmarkImageJpeg/Faker_math-8 | 34 | 31873165 ns/op | 2982479 B/op | 307214 allocs/op | +| BenchmarkImageJpeg/Faker_crypto-8 | 3 | 387670345 ns/op | 2982357 B/op | 307215 allocs/op | +| BenchmarkImagePng/package-8 | 16 | 65425256 ns/op | 5899024 B/op | 307270 allocs/op | +| BenchmarkImagePng/Faker_math-8 | 18 | 67804235 ns/op | 5899314 B/op | 307270 allocs/op | +| BenchmarkImagePng/Faker_crypto-8 | 3 | 396378778 ns/op | 5899005 B/op | 307270 allocs/op | +| BenchmarkDomainName/package-8 | 2344912 | 505.6 ns/op | 95 B/op | 5 allocs/op | +| BenchmarkDomainName/Faker_math-8 | 2265744 | 512.5 ns/op | 95 B/op | 5 allocs/op | +| BenchmarkDomainName/Faker_crypto-8 | 639775 | 1788 ns/op | 95 B/op | 5 allocs/op | +| BenchmarkDomainSuffix/package-8 | 19431498 | 59.95 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDomainSuffix/Faker_math-8 | 20097267 | 59.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkDomainSuffix/Faker_crypto-8 | 2498906 | 437.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkURL/package-8 | 1000000 | 1155 ns/op | 277 B/op | 10 allocs/op | +| BenchmarkURL/Faker_math-8 | 1000000 | 1165 ns/op | 277 B/op | 10 allocs/op | +| BenchmarkURL/Faker_crypto-8 | 275793 | 4371 ns/op | 276 B/op | 10 allocs/op | +| BenchmarkHTTPMethod/package-8 | 17651594 | 59.20 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPMethod/Faker_math-8 | 20081227 | 61.28 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPMethod/Faker_crypto-8 | 2844322 | 460.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkIPv4Address/package-8 | 5215255 | 229.2 ns/op | 16 B/op | 1 allocs/op | +| BenchmarkIPv4Address/Faker_math-8 | 4852905 | 224.9 ns/op | 16 B/op | 1 allocs/op | +| BenchmarkIPv4Address/Faker_crypto-8 | 670951 | 1827 ns/op | 16 B/op | 1 allocs/op | +| BenchmarkIPv6Address/package-8 | 2312482 | 510.0 ns/op | 111 B/op | 8 allocs/op | +| BenchmarkIPv6Address/Faker_math-8 | 2261472 | 521.2 ns/op | 111 B/op | 8 allocs/op | +| BenchmarkIPv6Address/Faker_crypto-8 | 338601 | 3623 ns/op | 111 B/op | 8 allocs/op | +| BenchmarkMacAddress/package-8 | 2809762 | 426.2 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkMacAddress/Faker_math-8 | 2863842 | 425.5 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkMacAddress/Faker_crypto-8 | 376604 | 2688 ns/op | 24 B/op | 1 allocs/op | +| BenchmarkHTTPStatusCode/package-8 | 13488582 | 88.27 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCode/Faker_math-8 | 14188726 | 73.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCode/Faker_crypto-8 | 2497014 | 463.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCodeSimple/package-8 | 17822486 | 81.54 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCodeSimple/Faker_math-8 | 16282341 | 70.72 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkHTTPStatusCodeSimple/Faker_crypto-8 | 2360576 | 451.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLogLevel/package-8 | 19343472 | 67.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLogLevel/Faker_math-8 | 19445798 | 61.84 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLogLevel/Faker_crypto-8 | 2296162 | 468.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkUserAgent/package-8 | 1503814 | 813.9 ns/op | 297 B/op | 5 allocs/op | +| BenchmarkUserAgent/Faker_math-8 | 1462177 | 803.6 ns/op | 298 B/op | 5 allocs/op | +| BenchmarkUserAgent/Faker_crypto-8 | 181178 | 6157 ns/op | 298 B/op | 5 allocs/op | +| BenchmarkChromeUserAgent/package-8 | 1911201 | 596.8 ns/op | 184 B/op | 5 allocs/op | +| BenchmarkChromeUserAgent/Faker_math-8 | 1969712 | 598.1 ns/op | 184 B/op | 5 allocs/op | +| BenchmarkChromeUserAgent/Faker_crypto-8 | 264816 | 4433 ns/op | 184 B/op | 5 allocs/op | +| BenchmarkFirefoxUserAgent/package-8 | 1000000 | 1043 ns/op | 362 B/op | 6 allocs/op | +| BenchmarkFirefoxUserAgent/Faker_math-8 | 1000000 | 1054 ns/op | 362 B/op | 6 allocs/op | +| BenchmarkFirefoxUserAgent/Faker_crypto-8 | 166128 | 7646 ns/op | 362 B/op | 6 allocs/op | +| BenchmarkSafariUserAgent/package-8 | 1000000 | 1022 ns/op | 551 B/op | 7 allocs/op | +| BenchmarkSafariUserAgent/Faker_math-8 | 1000000 | 1017 ns/op | 551 B/op | 7 allocs/op | +| BenchmarkSafariUserAgent/Faker_crypto-8 | 146463 | 7525 ns/op | 551 B/op | 7 allocs/op | +| BenchmarkOperaUserAgent/package-8 | 1844185 | 643.8 ns/op | 212 B/op | 5 allocs/op | +| BenchmarkOperaUserAgent/Faker_math-8 | 1805168 | 654.3 ns/op | 212 B/op | 5 allocs/op | +| BenchmarkOperaUserAgent/Faker_crypto-8 | 219927 | 5257 ns/op | 212 B/op | 5 allocs/op | +| BenchmarkJSONLookup100-8 | 894 | 1194698 ns/op | 537673 B/op | 8141 allocs/op | +| BenchmarkJSONLookup1000-8 | 91 | 12099728 ns/op | 5616708 B/op | 81606 allocs/op | +| BenchmarkJSONLookup10000-8 | 8 | 128144166 ns/op | 62638763 B/op | 817708 allocs/op | +| BenchmarkJSONLookup100000-8 | 1 | 1324756016 ns/op | 616116744 B/op | 8179136 allocs/op | +| BenchmarkLanguage/package-8 | 20946056 | 68.53 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguage/Faker_math-8 | 16884613 | 61.06 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguage/Faker_crypto-8 | 2889944 | 442.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageAbbreviation/package-8 | 20782443 | 53.79 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageAbbreviation/Faker_math-8 | 17936367 | 56.26 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageAbbreviation/Faker_crypto-8 | 2630406 | 423.8 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageBCP/package-8 | 19858063 | 59.00 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageBCP/Faker_math-8 | 20712447 | 60.02 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLanguageBCP/Faker_crypto-8 | 2654044 | 469.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguage/package-8 | 17849598 | 58.34 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguage/Faker_math-8 | 20090289 | 70.59 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguage/Faker_crypto-8 | 2628798 | 424.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguageBest/package-8 | 1000000000 | 0.4044 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguageBest/Faker_math-8 | 1000000000 | 0.2975 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkProgrammingLanguageBest/Faker_crypto-8 | 1000000000 | 0.2543 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLoremIpsumWord-8 | 22434632 | 54.96 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkLoremIpsumSentence-8 | 1000000 | 1038 ns/op | 219 B/op | 2 allocs/op | +| BenchmarkLoremIpsumParagraph-8 | 59320 | 19442 ns/op | 8479 B/op | 40 allocs/op | +| BenchmarkMinecraftOre/package-8 | 14624242 | 90.01 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftOre/Faker_math-8 | 16379578 | 86.91 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftOre/Faker_crypto-8 | 2757652 | 477.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWood/package-8 | 15815132 | 83.23 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWood/Faker_math-8 | 14872902 | 75.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWood/Faker_crypto-8 | 2524514 | 514.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorTier/package-8 | 15296107 | 78.58 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorTier/Faker_math-8 | 14341870 | 86.33 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorTier/Faker_crypto-8 | 2344278 | 473.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorPart/package-8 | 16863422 | 82.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorPart/Faker_math-8 | 14052031 | 76.92 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftArmorPart/Faker_crypto-8 | 2770314 | 474.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeapon/package-8 | 15759004 | 77.42 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeapon/Faker_math-8 | 15945940 | 81.48 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeapon/Faker_crypto-8 | 2254436 | 464.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftTool/package-8 | 15887787 | 76.39 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftTool/Faker_math-8 | 14269508 | 91.01 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftTool/Faker_crypto-8 | 2718507 | 525.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftDye/package-8 | 16131942 | 71.06 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftDye/Faker_math-8 | 16802478 | 73.40 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftDye/Faker_crypto-8 | 2584966 | 476.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftFood/package-8 | 14680048 | 87.15 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftFood/Faker_math-8 | 13558227 | 86.71 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftFood/Faker_crypto-8 | 2329946 | 435.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftAnimal/package-8 | 15871832 | 85.92 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftAnimal/Faker_math-8 | 12411510 | 83.88 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftAnimal/Faker_crypto-8 | 2528960 | 441.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerJob/package-8 | 13549438 | 80.41 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerJob/Faker_math-8 | 13769702 | 104.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerJob/Faker_crypto-8 | 2397300 | 452.2 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerStation/package-8 | 15069139 | 93.65 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerStation/Faker_math-8 | 15468883 | 82.27 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerStation/Faker_crypto-8 | 2469778 | 453.9 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerLevel/package-8 | 13468396 | 102.1 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerLevel/Faker_math-8 | 14354506 | 92.55 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftVillagerLevel/Faker_crypto-8 | 2416441 | 544.5 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobPassive/package-8 | 13299806 | 84.84 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobPassive/Faker_math-8 | 14181126 | 87.18 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobPassive/Faker_crypto-8 | 2539264 | 510.0 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobNeutral/package-8 | 11043175 | 110.7 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobNeutral/Faker_math-8 | 13059249 | 99.36 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobNeutral/Faker_crypto-8 | 2394342 | 544.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobHostile/package-8 | 13963809 | 95.66 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobHostile/Faker_math-8 | 15182318 | 96.90 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobHostile/Faker_crypto-8 | 2204600 | 538.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobBoss/package-8 | 12737437 | 89.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobBoss/Faker_math-8 | 13494093 | 90.65 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftMobBoss/Faker_crypto-8 | 2671172 | 461.3 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftBiome/package-8 | 13233918 | 81.47 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftBiome/Faker_math-8 | 16109408 | 85.68 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftBiome/Faker_crypto-8 | 2205704 | 499.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeather/package-8 | 13371518 | 79.93 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeather/Faker_math-8 | 14987182 | 80.69 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkMinecraftWeather/Faker_crypto-8 | 2373735 | 473.6 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBool/package-8 | 75772935 | 15.03 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBool/Faker_math-8 | 76893664 | 19.04 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkBool/Faker_crypto-8 | 3141634 | 376.4 ns/op | 0 B/op | 0 allocs/op | +| BenchmarkUUID/package-8 | 9382911 | 115.3 ns/op | 64 B/op | 2 allocs/op | +| BenchmarkUUID/Faker_math-8 | 9492183 | 114.1 ns/op | 64 B/op | 2 allocs/op | +| BenchmarkUUID/Faker_crypto-8 | 1000000 | 1039 ns/op | 64 B/op | 2 allocs/op | +| BenchmarkShuffleAnySlice/package-8 | 2234314 | 511.5 ns/op | 24 B/op | 1 allocs/op | \ No newline at end of file diff --git a/vendor/github.com/brianvoe/gofakeit/v6/README.md b/vendor/github.com/brianvoe/gofakeit/v6/README.md index 122b2331c..b42992d1d 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/README.md +++ b/vendor/github.com/brianvoe/gofakeit/v6/README.md @@ -1,24 +1,35 @@ ![alt text](https://raw.githubusercontent.com/brianvoe/gofakeit/master/logo.png) -# Gofakeit [![Go Report Card](https://goreportcard.com/badge/github.com/brianvoe/gofakeit)](https://goreportcard.com/report/github.com/brianvoe/gofakeit) ![Test](https://github.com/brianvoe/gofakeit/workflows/Test/badge.svg?branch=master) [![codecov.io](https://codecov.io/github/brianvoe/gofakeit/branch/master/graph/badge.svg)](https://codecov.io/github/brianvoe/gofakeit) [![GoDoc](https://godoc.org/github.com/brianvoe/gofakeit/v6?status.svg)](https://godoc.org/github.com/brianvoe/gofakeit/v6) [![license](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/brianvoe/gofakeit/master/LICENSE.txt) +# Gofakeit [![Go Report Card](https://goreportcard.com/badge/github.com/brianvoe/gofakeit)](https://goreportcard.com/report/github.com/brianvoe/gofakeit) ![Test](https://github.com/brianvoe/gofakeit/workflows/Test/badge.svg?branch=master) [![GoDoc](https://godoc.org/github.com/brianvoe/gofakeit/v6?status.svg)](https://godoc.org/github.com/brianvoe/gofakeit/v6) [![license](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/brianvoe/gofakeit/master/LICENSE.txt) Random data generator written in go +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G0R5EJT) + Buy Me A Coffee ## Features -- [160+ Functions!!!](#functions) +- [310+ Functions!!!](#functions) - [Random Sources](#random-sources) - [Global Rand](#global-rand-set) - [Struct Generator](#struct) - [Custom Functions](#custom-functions) +- [Templates](#templates) - [Http Server](https://github.com/brianvoe/gofakeit/tree/master/cmd/gofakeitserver) - [Command Line Tool](https://github.com/brianvoe/gofakeit/tree/master/cmd/gofakeit) - Zero dependencies - [Benchmarks](https://github.com/brianvoe/gofakeit/blob/master/BENCHMARKS.md) - [Issue](https://github.com/brianvoe/gofakeit/issues) +## Contributors + +Thank you to all our Gofakeit contributors! + + + + + ## Installation ```go @@ -101,7 +112,7 @@ gofakeit.SetGlobalFaker(faker) ## Struct Gofakeit can generate random data for struct fields. For the most part it covers all the basic type -as well as some non basic like time.Time. +as well as some non-basic like time.Time. Struct fields can also use tags to more specifically generate data for that field type. @@ -110,20 +121,22 @@ import "github.com/brianvoe/gofakeit/v6" // Create structs with random injected data type Foo struct { - Str string - Int int - Pointer *int - Name string `fake:"{firstname}"` // Any available function all lowercase - Sentence string `fake:"{sentence:3}"` // Can call with parameters - RandStr string `fake:"{randomstring:[hello,world]}"` - Number string `fake:"{number:1,10}"` // Comma separated for multiple values - Regex string `fake:"{regex:[abcdef]{5}}"` // Generate string from regex - Map map[string]int `fakesize:"2"` - Array []string `fakesize:"2"` - Bar Bar - Skip *string `fake:"skip"` // Set to "skip" to not generate data for - Created time.Time // Can take in a fake tag as well as a format tag - CreatedFormat time.Time `fake:"{year}-{month}-{day}" format:"2006-01-02"` + Str string + Int int + Pointer *int + Name string `fake:"{firstname}"` // Any available function all lowercase + Sentence string `fake:"{sentence:3}"` // Can call with parameters + RandStr string `fake:"{randomstring:[hello,world]}"` + Number string `fake:"{number:1,10}"` // Comma separated for multiple values + Regex string `fake:"{regex:[abcdef]{5}}"` // Generate string from regex + Map map[string]int `fakesize:"2"` + Array []string `fakesize:"2"` + ArrayRange []string `fakesize:"2,6"` + Bar Bar + Skip *string `fake:"skip"` // Set to "skip" to not generate data for + SkipAlt *string `fake:"-"` // Set to "-" to not generate data for + Created time.Time // Can take in a fake tag as well as a format tag + CreatedFormat time.Time `fake:"{year}-{month}-{day}" format:"2006-01-02"` } type Bar struct { @@ -157,12 +170,53 @@ fmt.Println(f.Created.String()) // 1908-12-07 04:14:25.685339029 +0000 UTC // bool, string, // array, pointers, map // time.Time // If setting time you can also set a format tag -// Nested Struct Fields and Embeded Fields +// Nested Struct Fields and Embedded Fields +``` + +## Fakeable types + +It is possible to extend a struct by implementing the `Fakeable` interface +in order to control the generation. + +For example, this is useful when it is not possible to modify the struct that you want to fake by adding struct tags to a field but you still need to be able to control the generation process. + +```go +// Custom string that you want to generate your own data for +// or just return a static value +type CustomString string + +func (c *CustomString) Fake(faker *gofakeit.Faker) (any, error) { + return CustomString("my custom string") +} + +// Imagine a CustomTime type that is needed to support a custom JSON Marshaler +type CustomTime time.Time + +func (c *CustomTime) Fake(faker *gofakeit.Faker) (any, error) { + return CustomTime(time.Now()) +} + +func (c *CustomTime) MarshalJSON() ([]byte, error) { + //... +} + +// This is the struct that we cannot modify to add struct tags +type NotModifiable struct { + Token string + Value CustomString + Creation *CustomTime +} + +var f NotModifiable +gofakeit.Struct(&f) +fmt.Printf("%s", f.Token) // yvqqdH +fmt.Printf("%s", f.Value) // my custom string +fmt.Printf("%s", f.Creation) // 2023-04-02 23:00:00 +0000 UTC m=+0.000000001 ``` ## Custom Functions -In a lot of sitations you may need to use your own random function usage for your specific needs. +In a lot of situations you may need to use your own random function usage for your specific needs. If you would like to extend the usage of struct tags, generate function, available usages in the gofakeit server or gofakeit command sub packages. You can do so via the AddFuncLookup. Each function has their own lookup, if @@ -170,33 +224,33 @@ you need more reference examples you can look at each files lookups. ```go // Simple -gofakeit.AddFuncLookup("friendname", Info{ +gofakeit.AddFuncLookup("friendname", gofakeit.Info{ Category: "custom", Description: "Random friend name", Example: "bill", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { - return RandomString([]string{"bill", "bob", "sally"}), nil + Generate: func(r *rand.Rand, m *gofakeit.MapParams, info *gofakeit.Info) (any, error) { + return gofakeit.RandomString([]string{"bill", "bob", "sally"}), nil }, }) // With Params -gofakeit.AddFuncLookup("jumbleword", Info{ +gofakeit.AddFuncLookup("jumbleword", gofakeit.Info{ Category: "jumbleword", - Description: "Take a word and jumple it up", + Description: "Take a word and jumble it up", Example: "loredlowlh", Output: "string", - Params: []Param{ + Params: []gofakeit.Param{ {Field: "word", Type: "string", Description: "Word you want to jumble"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *gofakeit.MapParams, info *gofakeit.Info) (any, error) { word, err := info.GetString(m, "word") if err != nil { return nil, err } split := strings.Split(word, "") - ShuffleStrings(split) + gofakeit.ShuffleStrings(split) return strings.Join(split, ""), nil }, }) @@ -212,19 +266,125 @@ fmt.Printf("%s", f.FriendName) // bill fmt.Printf("%s", f.JumbleWord) // loredlowlh ``` +## Templates + +Generate custom outputs using golang's template engine [https://pkg.go.dev/text/template](https://pkg.go.dev/text/template). + +We have added all the available functions to the template engine as well as some additional ones that are useful for template building. + +Additional Available Functions +```go +- ToUpper(s string) string // Make string upper case +- ToLower(s string) string // Make string lower case +- ToString(s any) // Convert to string +- ToDate(s string) time.Time // Convert string to date +- SpliceAny(args ...any) []any // Build a slice of anys, used with Weighted +- SpliceString(args ...string) []string // Build a slice of strings, used with Teams and RandomString +- SpliceUInt(args ...uint) []uint // Build a slice of uint, used with Dice and RandomUint +- SpliceInt(args ...int) []int // Build a slice of int, used with RandomInt +``` + +
+ Unavailable Gofakeit functions + +```go +// Any functions that dont have a return value +- AnythingThatReturnsVoid(): void + +// Not available to use in templates +- Template(co *TemplateOptions) ([]byte, error) +- RandomMapKey(mapI any) any +``` +
+ + +### Example Usages + +```go +import "github.com/brianvoe/gofakeit/v6" + +func main() { + // Accessing the Lines variable from within the template. + template := ` + Subject: {{RandomString (SliceString "Greetings" "Hello" "Hi")}} + + Dear {{LastName}}, + + {{RandomString (SliceString "Greetings!" "Hello there!" "Hi, how are you?")}} + + {{Paragraph 1 5 10 "\n\n"}} + + {{RandomString (SliceString "Warm regards" "Best wishes" "Sincerely")}} + {{$person:=Person}} + {{$person.FirstName}} {{$person.LastName}} + {{$person.Email}} + {{$person.Phone}} + ` + + value, err := gofakeit.Template(template, &TemplateOptions{Data: 5}) + + if err != nil { + fmt.Println(err) + } + + fmt.Println(string(value)) +} +``` + +Output: +```text +Subject: Hello + +Dear Krajcik, + +Greetings! + +Quia voluptatem voluptatem voluptatem. Quia voluptatem voluptatem voluptatem. Quia voluptatem voluptatem voluptatem. + +Warm regards +Kaitlyn Krajcik +kaitlynkrajcik@krajcik +570-245-7485 +``` + ## Functions All functions also exist as methods on the Faker struct ### File +Passing `nil` to `CSV`, `JSON` or `XML` will auto generate data using default values. + ```go +CSV(co *CSVOptions) ([]byte, error) JSON(jo *JSONOptions) ([]byte, error) XML(xo *XMLOptions) ([]byte, error) FileExtension() string FileMimeType() string ``` +### Template + +Passing `nil` will auto generate data using default values. + +```go +Template(co *TemplateOptions) (string, error) +Markdown(co *MarkdownOptions) (string, error) +EmailText(co *EmailOptions) (string, error) +FixedWidth(co *FixedWidthOptions) (string, error) +``` + +### Product + +```go +Product() *ProductInfo +ProductName() string +ProductDescription() string +ProductCategory() string +ProductFeature() string +ProductMaterial() string +``` + ### Person ```go @@ -233,6 +393,7 @@ Name() string NamePrefix() string NameSuffix() string FirstName() string +MiddleName() string LastName() string Gender() string SSN() string @@ -247,9 +408,9 @@ Teams(peopleArray []string, teamsArray []string) map[string][]string ### Generate ```go -Struct(v interface{}) -Slice(v interface{}) -Map() map[string]interface{} +Struct(v any) +Slice(v any) +Map() map[string]any Generate(value string) string Regex(value string) string ``` @@ -315,9 +476,8 @@ CarTransmissionType() string ### Words -#### Noun - ```go +// Nouns Noun() string NounCommon() string NounConcrete() string @@ -327,20 +487,14 @@ NounCollectiveAnimal() string NounCollectiveThing() string NounCountable() string NounUncountable() string -``` - -#### Verb -```go +// Verbs Verb() string VerbAction() string VerbLinking() string VerbHelping() string -``` -#### Adverb - -```go +// Adverbs Adverb() string AdverbManner() string AdverbDegree() string @@ -349,20 +503,14 @@ AdverbTimeDefinite() string AdverbTimeIndefinite() string AdverbFrequencyDefinite() string AdverbFrequencyIndefinite() string -``` - -#### Proposition -```go +// Propositions Preposition() string PrepositionSimple() string PrepositionDouble() string PrepositionCompound() string -``` - -#### Adjective -```go +// Adjectives Adjective() string AdjectiveDescriptive() string AdjectiveQuantitative() string @@ -371,24 +519,18 @@ AdjectiveDemonstrative() string AdjectivePossessive() string AdjectiveInterrogative() string AdjectiveIndefinite() string -``` -#### Pronoun - -```go +// Pronouns Pronoun() string PronounPersonal() string PronounObject() string -PronounPosessive() string +PronounPossessive() string PronounReflective() string PronounDemonstrative() string PronounInterrogative() string PronounRelative() string -``` -#### Connective - -```go +// Connectives Connective() string ConnectiveTime() string ConnectiveComparative() string @@ -396,17 +538,11 @@ ConnectiveComplaint() string ConnectiveListing() string ConnectiveCasual() string ConnectiveExamplify() string -``` - -#### Word -```go +// Words Word() string -``` - -#### Sentences -```go +// Sentences Sentence(wordCount int) string Paragraph(paragraphCount int, sentenceCount int, wordCount int, separator string) string LoremIpsumWord() string @@ -434,9 +570,10 @@ Dessert() string ```go Bool() bool UUID() string +Weighted(options []any, weights []float32) (any, error) FlipACoin() string -RandomMapKey(mapI interface{}) interface{} -ShuffleAnySlice(v interface{}) +RandomMapKey(mapI any) any +ShuffleAnySlice(v any) ``` ### Colors @@ -446,6 +583,16 @@ Color() string HexColor() string RGBColor() []int SafeColor() string +NiceColors() string +``` + +### Images + +```go +ImageURL(width int, height int) string +Image(width int, height int) *img.RGBA +ImageJpeg(width int, height int) []byte +ImagePng(width int, height int) []byte ``` ### Internet @@ -469,10 +616,19 @@ OperaUserAgent() string SafariUserAgent() string ``` +### HTML + +```go +InputName() string +Svg(options *SVGOptions) string +``` + ### Date/Time ```go Date() time.Time +PastDate() time.Time +FutureDate() time.Time DateRange(start, end time.Time) time.Time NanoSecond() int Second() int @@ -508,10 +664,18 @@ BitcoinAddress() string BitcoinPrivateKey() string ``` +### Finance + +```go +Cusip() string +Isin() string +``` + ### Company ```go BS() string +Blurb() string BuzzWord() string Company() string CompanySuffix() string @@ -519,6 +683,7 @@ Job() *JobInfo JobDescriptor() string JobLevel() string JobTitle() string +Slogan() string ``` ### Hacker @@ -557,6 +722,7 @@ AnimalType() string FarmAnimal() string Cat() string Dog() string +Bird() string ``` ### Emoji @@ -647,3 +813,39 @@ MinecraftMobBoss() string MinecraftBiome() string MinecraftWeather() string ``` + +### Book + +```go +Book() *BookInfo +BookTitle() string +BookAuthor() string +BookGenre() string +``` + +### Movie + +```go +Movie() *MovieInfo +MovieName() string +MovieGenre() string +``` + +### Error + +```go +Error() error +ErrorDatabase() error +ErrorGRPC() error +ErrorHTTP() error +ErrorHTTPClient() error +ErrorHTTPServer() error +ErrorInput() error +ErrorRuntime() error +``` + +### School + +```go +School() string +``` diff --git a/vendor/github.com/brianvoe/gofakeit/v6/address.go b/vendor/github.com/brianvoe/gofakeit/v6/address.go index 6a6b36f78..3c8bc96fe 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/address.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/address.go @@ -52,9 +52,9 @@ func street(r *rand.Rand) string { var street = "" switch randInt := randIntRange(r, 1, 2); randInt { case 1: - street = streetNumber(r) + " " + streetPrefix(r) + " " + streetName(r) + " " + streetSuffix(r) + street = streetNumber(r) + " " + streetPrefix(r) + " " + streetName(r) + streetSuffix(r) case 2: - street = streetNumber(r) + " " + streetName(r) + " " + streetSuffix(r) + street = streetNumber(r) + " " + streetName(r) + streetSuffix(r) } return street @@ -198,20 +198,20 @@ func addAddressLookup() { AddFuncLookup("address", Info{ Display: "Address", Category: "address", - Description: "Random set of address info", + Description: "Residential location including street, city, state, country and postal code", Example: `{ - address: "364 East Rapidsborough, Rutherfordstad, New Jersey 36906", - street: "364 East Rapidsborough", - city: "Rutherfordstad", - state: "New Jersey", - zip: "36906", - country: "South Africa", - latitude: "23.058758", - longitude: "89.022594" - }`, - Output: "map[string]interface", + "address": "364 Unionsville, Norfolk, Ohio 99536", + "street": "364 Unionsville", + "city": "Norfolk", + "state": "Ohio", + "zip": "99536", + "country": "Lesotho", + "latitude": 88.792592, + "longitude": 174.504681 +}`, + Output: "map[string]any", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return address(r), nil }, }) @@ -219,10 +219,10 @@ func addAddressLookup() { AddFuncLookup("city", Info{ Display: "City", Category: "address", - Description: "Random city", + Description: "Part of a country with significant population, often a central hub for culture and commerce", Example: "Marcelside", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return city(r), nil }, }) @@ -230,10 +230,10 @@ func addAddressLookup() { AddFuncLookup("country", Info{ Display: "Country", Category: "address", - Description: "Random country", + Description: "Nation with its own government and defined territory", Example: "United States of America", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return country(r), nil }, }) @@ -241,10 +241,10 @@ func addAddressLookup() { AddFuncLookup("countryabr", Info{ Display: "Country Abbreviation", Category: "address", - Description: "Random 2 digit country abbreviation", + Description: "Shortened 2-letter form of a country's name", Example: "US", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return countryAbr(r), nil }, }) @@ -252,10 +252,10 @@ func addAddressLookup() { AddFuncLookup("state", Info{ Display: "State", Category: "address", - Description: "Random state", + Description: "Governmental division within a country, often having its own laws and government", Example: "Illinois", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return state(r), nil }, }) @@ -263,10 +263,10 @@ func addAddressLookup() { AddFuncLookup("stateabr", Info{ Display: "State Abbreviation", Category: "address", - Description: "Random 2 digit state abbreviation", + Description: "Shortened 2-letter form of a country's state", Example: "IL", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return stateAbr(r), nil }, }) @@ -274,10 +274,10 @@ func addAddressLookup() { AddFuncLookup("street", Info{ Display: "Street", Category: "address", - Description: "Random full street", + Description: "Public road in a city or town, typically with houses and buildings on each side", Example: "364 East Rapidsborough", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return street(r), nil }, }) @@ -285,10 +285,10 @@ func addAddressLookup() { AddFuncLookup("streetname", Info{ Display: "Street Name", Category: "address", - Description: "Random street name", + Description: "Name given to a specific road or street", Example: "View", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetName(r), nil }, }) @@ -296,10 +296,10 @@ func addAddressLookup() { AddFuncLookup("streetnumber", Info{ Display: "Street Number", Category: "address", - Description: "Random street number", + Description: "Numerical identifier assigned to a street", Example: "13645", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetNumber(r), nil }, }) @@ -307,10 +307,10 @@ func addAddressLookup() { AddFuncLookup("streetprefix", Info{ Display: "Street Prefix", Category: "address", - Description: "Random street prefix", + Description: "Directional or descriptive term preceding a street name, like 'East' or 'Main'", Example: "Lake", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetPrefix(r), nil }, }) @@ -318,10 +318,10 @@ func addAddressLookup() { AddFuncLookup("streetsuffix", Info{ Display: "Street Suffix", Category: "address", - Description: "Random street suffix", + Description: "Designation at the end of a street name indicating type, like 'Avenue' or 'Street'", Example: "land", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return streetSuffix(r), nil }, }) @@ -329,10 +329,10 @@ func addAddressLookup() { AddFuncLookup("zip", Info{ Display: "Zip", Category: "address", - Description: "Random street zip", + Description: "Numerical code for postal address sorting, specific to a geographic area", Example: "13645", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return zip(r), nil }, }) @@ -340,10 +340,10 @@ func addAddressLookup() { AddFuncLookup("latitude", Info{ Display: "Latitude", Category: "address", - Description: "Random latitude", + Description: "Geographic coordinate specifying north-south position on Earth's surface", Example: "-73.534056", Output: "float", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return latitude(r), nil }, }) @@ -351,14 +351,14 @@ func addAddressLookup() { AddFuncLookup("latituderange", Info{ Display: "Latitude Range", Category: "address", - Description: "Random latitude between given range", + Description: "Latitude number between the given range (default min=0, max=90)", Example: "22.921026", Output: "float", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Default: "0", Description: "Minimum range"}, {Field: "max", Display: "Max", Type: "float", Default: "90", Description: "Maximum range"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err @@ -381,10 +381,10 @@ func addAddressLookup() { AddFuncLookup("longitude", Info{ Display: "Longitude", Category: "address", - Description: "Random longitude", + Description: "Geographic coordinate indicating east-west position on Earth's surface", Example: "-147.068112", Output: "float", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return longitude(r), nil }, }) @@ -392,14 +392,14 @@ func addAddressLookup() { AddFuncLookup("longituderange", Info{ Display: "Longitude Range", Category: "address", - Description: "Random longitude between given range", + Description: "Longitude number between the given range (default min=0, max=180)", Example: "-8.170450", Output: "float", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Default: "0", Description: "Minimum range"}, {Field: "max", Display: "Max", Type: "float", Default: "180", Description: "Maximum range"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/animal.go b/vendor/github.com/brianvoe/gofakeit/v6/animal.go index fd30b5f00..56772ea98 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/animal.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/animal.go @@ -86,14 +86,28 @@ func dog(r *rand.Rand) string { return getRandValue(r, []string{"animal", "dog"}) } +// Bird will return a random bird species +func Bird() string { + return bird(globalFaker.Rand) +} + +// Bird will return a random bird species +func (f *Faker) Bird() string { + return bird(f.Rand) +} + +func bird(r *rand.Rand) string { + return getRandValue(r, []string{"animal", "bird"}) +} + func addAnimalLookup() { AddFuncLookup("petname", Info{ Display: "Pet Name", Category: "animal", - Description: "Random pet name", + Description: "Affectionate nickname given to a pet", Example: "Ozzy Pawsborne", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return petName(r), nil }, }) @@ -101,10 +115,10 @@ func addAnimalLookup() { AddFuncLookup("animal", Info{ Display: "Animal", Category: "animal", - Description: "Random animal", + Description: "Living creature with the ability to move, eat, and interact with its environment", Example: "elk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return animal(r), nil }, }) @@ -112,10 +126,10 @@ func addAnimalLookup() { AddFuncLookup("animaltype", Info{ Display: "Animal Type", Category: "animal", - Description: "Random animal type", + Description: "Type of animal, such as mammals, birds, reptiles, etc.", Example: "amphibians", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return animalType(r), nil }, }) @@ -123,10 +137,10 @@ func addAnimalLookup() { AddFuncLookup("farmanimal", Info{ Display: "Farm Animal", Category: "animal", - Description: "Random farm animal", + Description: "Animal name commonly found on a farm", Example: "Chicken", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return farmAnimal(r), nil }, }) @@ -134,10 +148,10 @@ func addAnimalLookup() { AddFuncLookup("cat", Info{ Display: "Cat", Category: "animal", - Description: "Random cat type", + Description: "Various breeds that define different cats", Example: "Chausie", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return cat(r), nil }, }) @@ -145,11 +159,22 @@ func addAnimalLookup() { AddFuncLookup("dog", Info{ Display: "Dog", Category: "animal", - Description: "Random dog type", + Description: "Various breeds that define different dogs", Example: "Norwich Terrier", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return dog(r), nil }, }) + + AddFuncLookup("bird", Info{ + Display: "Bird", + Category: "animal", + Description: "Distinct species of birds", + Example: "goose", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return bird(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/app.go b/vendor/github.com/brianvoe/gofakeit/v6/app.go index 195d4b4df..172c81798 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/app.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/app.go @@ -65,10 +65,10 @@ func addAppLookup() { AddFuncLookup("appname", Info{ Display: "App Name", Category: "app", - Description: "Random app name", + Description: "Software program designed for a specific purpose or task on a computer or mobile device", Example: "Parkrespond", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return appName(r), nil }, }) @@ -76,10 +76,10 @@ func addAppLookup() { AddFuncLookup("appversion", Info{ Display: "App Version", Category: "app", - Description: "Random app version", + Description: "Particular release of an application in Semantic Versioning format", Example: "1.12.14", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return appVersion(r), nil }, }) @@ -87,10 +87,10 @@ func addAppLookup() { AddFuncLookup("appauthor", Info{ Display: "App Author", Category: "app", - Description: "Random app author", + Description: "Person or group creating and developing an application", Example: "Qado Energy, Inc.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return appAuthor(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/auth.go b/vendor/github.com/brianvoe/gofakeit/v6/auth.go index ab7631eeb..ae86e3d11 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/auth.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/auth.go @@ -33,45 +33,56 @@ func password(r *rand.Rand, lower bool, upper bool, numeric bool, special bool, if num < 5 { num = 5 } - i := 0 - b := make([]byte, num) - var passString string + // Setup weights + items := make([]any, 0) + weights := make([]float32, 0) if lower { - passString += lowerStr - b[i] = lowerStr[r.Int63()%int64(len(lowerStr))] - i++ + items = append(items, "lower") + weights = append(weights, 4) } if upper { - passString += upperStr - b[i] = upperStr[r.Int63()%int64(len(upperStr))] - i++ + items = append(items, "upper") + weights = append(weights, 4) } if numeric { - passString += numericStr - b[i] = numericStr[r.Int63()%int64(len(numericStr))] - i++ + items = append(items, "numeric") + weights = append(weights, 3) } if special { - passString += specialStr - b[i] = specialStr[r.Int63()%int64(len(specialStr))] - i++ + items = append(items, "special") + weights = append(weights, 2) } if space { - passString += spaceStr - b[i] = spaceStr[r.Int63()%int64(len(spaceStr))] - i++ + items = append(items, "space") + weights = append(weights, 1) } - // Set default if empty - if passString == "" { - passString = lowerStr + numericStr + // If no items are selected then default to lower, upper, numeric + if len(items) == 0 { + items = append(items, "lower", "upper", "numeric") + weights = append(weights, 4, 4, 3) } - // Loop through and add it up - for i <= num-1 { - b[i] = passString[r.Int63()%int64(len(passString))] - i++ + // Create byte slice + b := make([]byte, num) + + for i := 0; i <= num-1; i++ { + // Run weighted + weight, _ := weighted(r, items, weights) + + switch weight.(string) { + case "lower": + b[i] = lowerStr[r.Int63()%int64(len(lowerStr))] + case "upper": + b[i] = upperStr[r.Int63()%int64(len(upperStr))] + case "numeric": + b[i] = numericStr[r.Int63()%int64(len(numericStr))] + case "special": + b[i] = specialSafeStr[r.Int63()%int64(len(specialSafeStr))] + case "space": + b[i] = spaceStr[r.Int63()%int64(len(spaceStr))] + } } // Shuffle bytes @@ -80,6 +91,14 @@ func password(r *rand.Rand, lower bool, upper bool, numeric bool, special bool, b[i], b[j] = b[j], b[i] } + // Replace first or last character if it's a space, and other options are available + if b[0] == ' ' { + b[0] = password(r, lower, upper, numeric, special, false, 1)[0] + } + if b[len(b)-1] == ' ' { + b[len(b)-1] = password(r, lower, upper, numeric, special, false, 1)[0] + } + return string(b) } @@ -87,10 +106,10 @@ func addAuthLookup() { AddFuncLookup("username", Info{ Display: "Username", Category: "auth", - Description: "Generates a random username", + Description: "Unique identifier assigned to a user for accessing an account or system", Example: "Daniel1364", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return username(r), nil }, }) @@ -98,7 +117,7 @@ func addAuthLookup() { AddFuncLookup("password", Info{ Display: "Password", Category: "auth", - Description: "Generates a random password", + Description: "Secret word or phrase used to authenticate access to a system or account", Example: "EEP+wwpk 4lU-eHNXlJZ4n K9%v&TZ9e", Output: "string", Params: []Param{ @@ -109,7 +128,7 @@ func addAuthLookup() { {Field: "space", Display: "Space", Type: "bool", Default: "false", Description: "Whether or not to add spaces"}, {Field: "length", Display: "Length", Type: "int", Default: "12", Description: "Number of characters in password"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { lower, err := info.GetBool(m, "lower") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/beer.go b/vendor/github.com/brianvoe/gofakeit/v6/beer.go index d245fcbe3..292ae6803 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/beer.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/beer.go @@ -121,10 +121,10 @@ func addBeerLookup() { AddFuncLookup("beername", Info{ Display: "Beer Name", Category: "beer", - Description: "Random beer name", + Description: "Specific brand or variety of beer", Example: "Duvel", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerName(r), nil }, }) @@ -132,10 +132,10 @@ func addBeerLookup() { AddFuncLookup("beerstyle", Info{ Display: "Beer Style", Category: "beer", - Description: "Random beer style", + Description: "Distinct characteristics and flavors of beer", Example: "European Amber Lager", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerStyle(r), nil }, }) @@ -143,10 +143,10 @@ func addBeerLookup() { AddFuncLookup("beerhop", Info{ Display: "Beer Hop", Category: "beer", - Description: "Random beer hop type", + Description: "The flower used in brewing to add flavor, aroma, and bitterness to beer", Example: "Glacier", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerHop(r), nil }, }) @@ -154,10 +154,10 @@ func addBeerLookup() { AddFuncLookup("beeryeast", Info{ Display: "Beer Yeast", Category: "beer", - Description: "Random beer yeast value", + Description: "Microorganism used in brewing to ferment sugars, producing alcohol and carbonation in beer", Example: "1388 - Belgian Strong Ale", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerYeast(r), nil }, }) @@ -165,10 +165,10 @@ func addBeerLookup() { AddFuncLookup("beermalt", Info{ Display: "Beer Malt", Category: "beer", - Description: "Random beer malt", + Description: "Processed barley or other grains, provides sugars for fermentation and flavor to beer", Example: "Munich", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerMalt(r), nil }, }) @@ -176,10 +176,10 @@ func addBeerLookup() { AddFuncLookup("beeralcohol", Info{ Display: "Beer Alcohol", Category: "beer", - Description: "Random alcohol percentage", + Description: "Measures the alcohol content in beer", Example: "2.7%", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerAlcohol(r), nil }, }) @@ -187,10 +187,10 @@ func addBeerLookup() { AddFuncLookup("beeribu", Info{ Display: "Beer IBU", Category: "beer", - Description: "Random beer ibu", + Description: "Scale measuring bitterness of beer from hops", Example: "29 IBU", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerIbu(r), nil }, }) @@ -198,10 +198,10 @@ func addBeerLookup() { AddFuncLookup("beerblg", Info{ Display: "Beer BLG", Category: "beer", - Description: "Random beer blg", + Description: "Scale indicating the concentration of extract in worts", Example: "6.4°Blg", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return beerBlg(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/book.go b/vendor/github.com/brianvoe/gofakeit/v6/book.go new file mode 100644 index 000000000..e2059dcf7 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/book.go @@ -0,0 +1,90 @@ +package gofakeit + +import "math/rand" + +func BookTitle() string { return bookTitle(globalFaker.Rand) } + +func (f *Faker) BookTitle() string { return bookTitle(f.Rand) } + +func bookTitle(r *rand.Rand) string { return getRandValue(r, []string{"book", "title"}) } + +func BookAuthor() string { return bookAuthor(globalFaker.Rand) } + +func (f *Faker) BookAuthor() string { return bookAuthor(f.Rand) } + +func bookAuthor(r *rand.Rand) string { return getRandValue(r, []string{"book", "author"}) } + +func BookGenre() string { return bookGenre(globalFaker.Rand) } + +func (f *Faker) BookGenre() string { return bookGenre(f.Rand) } + +func bookGenre(r *rand.Rand) string { return getRandValue(r, []string{"book", "genre"}) } + +type BookInfo struct { + Title string `json:"title" xml:"name"` + Author string `json:"author" xml:"author"` + Genre string `json:"genre" xml:"genre"` +} + +func Book() *BookInfo { return book(globalFaker.Rand) } + +func (f *Faker) Book() *BookInfo { return book(f.Rand) } + +func book(r *rand.Rand) *BookInfo { + return &BookInfo{ + Title: bookTitle(r), + Author: bookAuthor(r), + Genre: bookGenre(r), + } +} + +func addBookLookup() { + AddFuncLookup("book", Info{ + Display: "Book", + Category: "book", + Description: "Written or printed work consisting of pages bound together, covering various subjects or stories", + Example: `{ + "title": "Anna Karenina", + "author": "Toni Morrison", + "genre": "Thriller" +}`, + Output: "map[string]string", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return book(r), nil + }, + }) + + AddFuncLookup("booktitle", Info{ + Display: "Title", + Category: "book", + Description: "The specific name given to a book", + Example: "Hamlet", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return bookTitle(r), nil + }, + }) + + AddFuncLookup("bookauthor", Info{ + Display: "Author", + Category: "book", + Description: "The individual who wrote or created the content of a book", + Example: "Mark Twain", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return bookAuthor(r), nil + }, + }) + + AddFuncLookup("bookgenre", Info{ + Display: "Genre", + Category: "book", + Description: "Category or type of book defined by its content, style, or form", + Example: "Adventure", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return bookGenre(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/car.go b/vendor/github.com/brianvoe/gofakeit/v6/car.go index 8b0581600..983e2576c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/car.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/car.go @@ -75,11 +75,18 @@ func addCarLookup() { AddFuncLookup("car", Info{ Display: "Car", Category: "car", - Description: "Random car set of data", - Output: "map[string]interface", + Description: "Wheeled motor vehicle used for transportation", + Example: `{ + "type": "Passenger car mini", + "fuel": "Gasoline", + "transmission": "Automatic", + "brand": "Fiat", + "model": "Freestyle Fwd", + "year": 1991 +}`, + Output: "map[string]any", ContentType: "application/json", - Example: `{type: "Passenger car mini", fuel: "Gasoline", transmission: "Automatic", brand: "Fiat", model: "Freestyle Fwd", year: "1972"}`, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return car(r), nil }, }) @@ -87,10 +94,10 @@ func addCarLookup() { AddFuncLookup("cartype", Info{ Display: "Car Type", Category: "car", - Description: "Random car type", + Description: "Classification of cars based on size, use, or body style", Example: "Passenger car mini", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carType(r), nil }, }) @@ -98,10 +105,10 @@ func addCarLookup() { AddFuncLookup("carfueltype", Info{ Display: "Car Fuel Type", Category: "car", - Description: "Random car fuel type", + Description: "Type of energy source a car uses", Example: "CNG", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carFuelType(r), nil }, }) @@ -109,10 +116,10 @@ func addCarLookup() { AddFuncLookup("cartransmissiontype", Info{ Display: "Car Transmission Type", Category: "car", - Description: "Random car transmission type", + Description: "Mechanism a car uses to transmit power from the engine to the wheels", Example: "Manual", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carTransmissionType(r), nil }, }) @@ -120,10 +127,10 @@ func addCarLookup() { AddFuncLookup("carmaker", Info{ Display: "Car Maker", Category: "car", - Description: "Random car maker", + Description: "Company or brand that manufactures and designs cars", Example: "Nissan", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carMaker(r), nil }, }) @@ -131,10 +138,10 @@ func addCarLookup() { AddFuncLookup("carmodel", Info{ Display: "Car Model", Category: "car", - Description: "Random car model", + Description: "Specific design or version of a car produced by a manufacturer", Example: "Aveo", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return carModel(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go b/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go index 36a0c8336..d7400f80a 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/celebrity.go @@ -32,10 +32,10 @@ func addCelebrityLookup() { AddFuncLookup("celebrityactor", Info{ Display: "Celebrity Actor", Category: "celebrity", - Description: "Random celebrity actor", + Description: "Famous person known for acting in films, television, or theater", Example: "Brad Pitt", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return celebrityActor(r), nil }, }) @@ -43,10 +43,10 @@ func addCelebrityLookup() { AddFuncLookup("celebritybusiness", Info{ Display: "Celebrity Business", Category: "celebrity", - Description: "Random celebrity business person", + Description: "High-profile individual known for significant achievements in business or entrepreneurship", Example: "Elon Musk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return celebrityBusiness(r), nil }, }) @@ -54,10 +54,10 @@ func addCelebrityLookup() { AddFuncLookup("celebritysport", Info{ Display: "Celebrity Sport", Category: "celebrity", - Description: "Random celebrity sport person", + Description: "Famous athlete known for achievements in a particular sport", Example: "Michael Phelps", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return celebritySport(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/color.go b/vendor/github.com/brianvoe/gofakeit/v6/color.go index 8e46e9594..dce7db5f3 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/color.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/color.go @@ -1,6 +1,10 @@ package gofakeit -import "math/rand" +import ( + "math/rand" + + "github.com/brianvoe/gofakeit/v6/data" +) // Color will generate a random color string func Color() string { return color(globalFaker.Rand) } @@ -10,6 +14,16 @@ func (f *Faker) Color() string { return color(f.Rand) } func color(r *rand.Rand) string { return getRandValue(r, []string{"color", "full"}) } +// NiceColor will generate a random safe color string +func NiceColors() []string { return niceColors(globalFaker.Rand) } + +// NiceColor will generate a random safe color string +func (f *Faker) NiceColors() []string { return niceColors(f.Rand) } + +func niceColors(r *rand.Rand) []string { + return data.ColorsNice[randIntRange(r, 0, len(data.ColorsNice)-1)] +} + // SafeColor will generate a random safe color string func SafeColor() string { return safeColor(globalFaker.Rand) } @@ -48,10 +62,22 @@ func addColorLookup() { AddFuncLookup("color", Info{ Display: "Color", Category: "color", - Description: "Random color", + Description: "Hue seen by the eye, returns the name of the color like red or blue", Example: "MediumOrchid", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return color(r), nil + }, + }) + + AddFuncLookup("nicecolors", Info{ + Display: "Nice Colors", + Category: "color", + Description: "Attractive and appealing combinations of colors, returns an list of color hex codes", + Example: `["#cfffdd","#b4dec1","#5c5863","#a85163","#ff1f4c"]`, + Output: "[]string", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return color(r), nil }, }) @@ -59,10 +85,10 @@ func addColorLookup() { AddFuncLookup("safecolor", Info{ Display: "Safe Color", Category: "color", - Description: "Random safe color", + Description: "Colors displayed consistently on different web browsers and devices", Example: "black", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return safeColor(r), nil }, }) @@ -70,10 +96,10 @@ func addColorLookup() { AddFuncLookup("hexcolor", Info{ Display: "Hex Color", Category: "color", - Description: "Random hex color", + Description: "Six-digit code representing a color in the color model", Example: "#a99fb4", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexColor(r), nil }, }) @@ -81,10 +107,11 @@ func addColorLookup() { AddFuncLookup("rgbcolor", Info{ Display: "RGB Color", Category: "color", - Description: "Random rgb color", - Example: "[152 23 53]", - Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Description: "Color defined by red, green, and blue light values", + Example: "[85, 224, 195]", + Output: "[]int", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return rgbColor(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/company.go b/vendor/github.com/brianvoe/gofakeit/v6/company.go index 32a328346..ea8af6ca0 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/company.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/company.go @@ -18,6 +18,13 @@ func (f *Faker) CompanySuffix() string { return companySuffix(f.Rand) } func companySuffix(r *rand.Rand) string { return getRandValue(r, []string{"company", "suffix"}) } +// Blurb will generate a random company blurb string +func Blurb() string { return blurb(globalFaker.Rand) } + +func (f *Faker) Blurb() string { return blurb(f.Rand) } + +func blurb(r *rand.Rand) string { return getRandValue(r, []string{"company", "blurb"}) } + // BuzzWord will generate a random company buzz word string func BuzzWord() string { return buzzWord(globalFaker.Rand) } @@ -81,14 +88,38 @@ func (f *Faker) JobLevel() string { return jobLevel(f.Rand) } func jobLevel(r *rand.Rand) string { return getRandValue(r, []string{"job", "level"}) } +// Slogan will generate a random company slogan +func Slogan() string { return slogan(globalFaker.Rand) } + +// Slogan will generate a random company slogan +func (f *Faker) Slogan() string { return slogan(f.Rand) } + +// Slogan will generate a random company slogan +func slogan(r *rand.Rand) string { + slogan := "" + var sloganStyle = number(r, 0, 2) + switch sloganStyle { + // Noun. Buzzword! + case 0: + slogan = getRandValue(r, []string{"company", "blurb"}) + ". " + getRandValue(r, []string{"company", "buzzwords"}) + "!" + // Buzzword Noun, Buzzword Noun. + case 1: + slogan = getRandValue(r, []string{"company", "buzzwords"}) + " " + getRandValue(r, []string{"company", "blurb"}) + ", " + getRandValue(r, []string{"company", "buzzwords"}) + " " + getRandValue(r, []string{"company", "blurb"}) + "." + // Buzzword bs Noun, Buzzword. + case 2: + slogan = getRandValue(r, []string{"company", "buzzwords"}) + " " + getRandValue(r, []string{"company", "bs"}) + " " + getRandValue(r, []string{"company", "blurb"}) + ", " + getRandValue(r, []string{"company", "buzzwords"}) + "." + } + return slogan +} + func addCompanyLookup() { AddFuncLookup("company", Info{ Display: "Company", Category: "company", - Description: "Random company name", + Description: "Designated official name of a business or organization", Example: "Moen, Pagac and Wuckert", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return company(r), nil }, }) @@ -96,10 +127,10 @@ func addCompanyLookup() { AddFuncLookup("companysuffix", Info{ Display: "Company Suffix", Category: "company", - Description: "Random company name suffix", + Description: "Suffix at the end of a company name, indicating business structure, like 'Inc.' or 'LLC'", Example: "Inc", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return companySuffix(r), nil }, }) @@ -110,18 +141,29 @@ func addCompanyLookup() { Description: "Random bs company word", Example: "front-end", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return bs(r), nil }, }) + AddFuncLookup("blurb", Info{ + Display: "Blurb", + Category: "company", + Description: "Brief description or summary of a company's purpose, products, or services", + Example: "word", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return blurb(r), nil + }, + }) + AddFuncLookup("buzzword", Info{ Display: "Buzzword", Category: "company", - Description: "Random company buzzwords", + Description: "Trendy or overused term often used in business to sound impressive", Example: "disintermediate", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return buzzWord(r), nil }, }) @@ -129,10 +171,16 @@ func addCompanyLookup() { AddFuncLookup("job", Info{ Display: "Job", Category: "company", - Description: "Random job data set", - Example: `{company: "Moen, Pagac and Wuckert", title: "Director", descriptor: "Central", level: "Assurance"}`, + Description: "Position or role in employment, involving specific tasks and responsibilities", + Example: `{ + "company": "ClearHealthCosts", + "title": "Agent", + "descriptor": "Future", + "level": "Tactics" +}`, Output: "map[string]string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return job(r), nil }, }) @@ -140,10 +188,10 @@ func addCompanyLookup() { AddFuncLookup("jobtitle", Info{ Display: "Job Title", Category: "company", - Description: "Random job title", + Description: "Specific title for a position or role within a company or organization", Example: "Director", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return jobTitle(r), nil }, }) @@ -151,10 +199,10 @@ func addCompanyLookup() { AddFuncLookup("jobdescriptor", Info{ Display: "Job Descriptor", Category: "company", - Description: "Random job descriptor", + Description: "Word used to describe the duties, requirements, and nature of a job", Example: "Central", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return jobDescriptor(r), nil }, }) @@ -165,8 +213,19 @@ func addCompanyLookup() { Description: "Random job level", Example: "Assurance", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return jobLevel(r), nil }, }) + + AddFuncLookup("slogan", Info{ + Display: "Slogan", + Category: "company", + Description: "Catchphrase or motto used by a company to represent its brand or values", + Example: "Universal seamless Focus, interactive.", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return slogan(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/csv.go b/vendor/github.com/brianvoe/gofakeit/v6/csv.go index 0057d5d7e..6a2310ef6 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/csv.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/csv.go @@ -13,18 +13,28 @@ import ( // CSVOptions defines values needed for csv generation type CSVOptions struct { - Delimiter string `json:"delimiter" xml:"delimiter"` - RowCount int `json:"row_count" xml:"row_count"` - Fields []Field `json:"fields" xml:"fields"` + Delimiter string `json:"delimiter" xml:"delimiter" fake:"{randomstring:[,,tab]}"` + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } // CSV generates an object or an array of objects in json format -func CSV(co *CSVOptions) ([]byte, error) { return csvFunc(globalFaker.Rand, co) } +// A nil CSVOptions returns a randomly structured CSV. +func CSV(co *CSVOptions) ([]byte, error) { return csvFunc(globalFaker, co) } // CSV generates an object or an array of objects in json format -func (f *Faker) CSV(co *CSVOptions) ([]byte, error) { return csvFunc(f.Rand, co) } +// A nil CSVOptions returns a randomly structured CSV. +func (f *Faker) CSV(co *CSVOptions) ([]byte, error) { return csvFunc(f, co) } + +func csvFunc(f *Faker, co *CSVOptions) ([]byte, error) { + if co == nil { + // We didn't get a CSVOptions, so create a new random one + err := f.Struct(&co) + if err != nil { + return nil, err + } + } -func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { // Check delimiter if co.Delimiter == "" { co.Delimiter = "," @@ -32,7 +42,7 @@ func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { if strings.ToLower(co.Delimiter) == "tab" { co.Delimiter = "\t" } - if co.Delimiter != "," && co.Delimiter != "\t" { + if co.Delimiter != "," && co.Delimiter != "\t" && co.Delimiter != ";" { return nil, errors.New("invalid delimiter type") } @@ -61,7 +71,7 @@ func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { for i := 1; i < co.RowCount+1; i++ { vr := make([]string, len(co.Fields)) - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for ii, field := range co.Fields { if field.Function == "autoincrement" { vr[ii] = fmt.Sprintf("%d", i) @@ -74,14 +84,14 @@ func csvFunc(r *rand.Rand, co *CSVOptions) ([]byte, error) { return nil, errors.New("invalid function, " + field.Function + " does not exist") } - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } if _, ok := value.([]byte); ok { // If it's a slice of bytes or struct, unmarshal it into an interface - var v interface{} + var v any if err := json.Unmarshal(value.([]byte), &v); err != nil { return nil, err } @@ -119,22 +129,26 @@ func addFileCSVLookup() { AddFuncLookup("csv", Info{ Display: "CSV", Category: "file", - Description: "Generates array of rows in csv format", - Example: ` - id,first_name,last_name,password - 1,Markus,Moen,Dc0VYXjkWABx - 2,Osborne,Hilll,XPJ9OVNbs5lm - `, + Description: "Individual lines or data entries within a CSV (Comma-Separated Values) format", + Example: `id,first_name,last_name,password +1,Markus,Moen,Dc0VYXjkWABx +2,Osborne,Hilll,XPJ9OVNbs5lm`, Output: "[]byte", ContentType: "text/csv", Params: []Param{ + {Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows"}, {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function"}, - {Field: "delimiter", Display: "Delimiter", Type: "string", Default: ",", Description: "Separator in between row values"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { co := CSVOptions{} + delimiter, err := info.GetString(m, "delimiter") + if err != nil { + return nil, err + } + co.Delimiter = delimiter + rowcount, err := info.GetInt(m, "rowcount") if err != nil { return nil, err @@ -159,13 +173,8 @@ func addFileCSVLookup() { } } - delimiter, err := info.GetString(m, "delimiter") - if err != nil { - return nil, err - } - co.Delimiter = delimiter - - csvOut, err := csvFunc(r, &co) + f := &Faker{Rand: r} + csvOut, err := csvFunc(f, &co) if err != nil { return nil, err } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/address.go b/vendor/github.com/brianvoe/gofakeit/v6/data/address.go index 64c7fd511..98d88e821 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/address.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/address.go @@ -6,7 +6,7 @@ var Address = map[string][]string{ "street_prefix": {"North", "East", "West", "South", "New", "Lake", "Port"}, "street_name": {"Alley", "Avenue", "Branch", "Bridge", "Brook", "Brooks", "Burg", "Burgs", "Bypass", "Camp", "Canyon", "Cape", "Causeway", "Center", "Centers", "Circle", "Circles", "Cliff", "Cliffs", "Club", "Common", "Corner", "Corners", "Course", "Court", "Courts", "Cove", "Coves", "Creek", "Crescent", "Crest", "Crossing", "Crossroad", "Curve", "Dale", "Dam", "Divide", "Drive", "Drive", "Drives", "Estate", "Estates", "Expressway", "Extension", "Extensions", "Fall", "Falls", "Ferry", "Field", "Fields", "Flat", "Flats", "Ford", "Fords", "Forest", "Forge", "Forges", "Fork", "Forks", "Fort", "Freeway", "Garden", "Gardens", "Gateway", "Glen", "Glens", "Green", "Greens", "Grove", "Groves", "Harbor", "Harbors", "Haven", "Heights", "Highway", "Hill", "Hills", "Hollow", "Inlet", "Inlet", "Island", "Island", "Islands", "Islands", "Isle", "Isle", "Junction", "Junctions", "Key", "Keys", "Knoll", "Knolls", "Lake", "Lakes", "Land", "Landing", "Lane", "Light", "Lights", "Loaf", "Lock", "Locks", "Locks", "Lodge", "Lodge", "Loop", "Mall", "Manor", "Manors", "Meadow", "Meadows", "Mews", "Mill", "Mills", "Mission", "Mission", "Motorway", "Mount", "Mountain", "Mountain", "Mountains", "Mountains", "Neck", "Orchard", "Oval", "Overpass", "Park", "Parks", "Parkway", "Parkways", "Pass", "Passage", "Path", "Pike", "Pine", "Pines", "Place", "Plain", "Plains", "Plains", "Plaza", "Plaza", "Point", "Points", "Port", "Port", "Ports", "Ports", "Prairie", "Prairie", "Radial", "Ramp", "Ranch", "Rapid", "Rapids", "Rest", "Ridge", "Ridges", "River", "Road", "Road", "Roads", "Roads", "Route", "Row", "Rue", "Run", "Shoal", "Shoals", "Shore", "Shores", "Skyway", "Spring", "Springs", "Springs", "Spur", "Spurs", "Square", "Square", "Squares", "Squares", "Station", "Station", "Stravenue", "Stravenue", "Stream", "Stream", "Street", "Street", "Streets", "Summit", "Summit", "Terrace", "Throughway", "Trace", "Track", "Trafficway", "Trail", "Trail", "Tunnel", "Tunnel", "Turnpike", "Turnpike", "Underpass", "Union", "Unions", "Valley", "Valleys", "Via", "Viaduct", "View", "Views", "Village", "Village", "Villages", "Ville", "Vista", "Vista", "Walk", "Walks", "Wall", "Way", "Ways", "Well", "Wells"}, "street_suffix": {"town", "ton", "land", "ville", "berg", "burgh", "borough", "bury", "view", "port", "mouth", "stad", "furt", "chester", "mouth", "fort", "haven", "side", "shire"}, - "city": {"New York City", "Los Angeles", "Chicago", "Houston", "Philadelphia", "Phoenix", "San Antonio", "San Diego", "Dallas", "San Jose", "Austin", "Jacksonville", "Indianapolis", "San Francisco", "Columbus", "Fort Worth", "Charlotte", "Detroit", "El Paso", "Memphis", "Boston", "Seattle", "Denver", "Washington", "Nashville-Davidson", "Baltimore", "Louisville/Jefferson", "Portland", "Oklahoma ", "Milwaukee", "Las Vegas", "Albuquerque", "Tucson", "Fresno", "Sacramento", "Long Beach", "Kansas ", "Mesa", "Virginia Beach", "Atlanta", "Colorado Springs", "Raleigh", "Omaha", "Miami", "Oakland", "Tulsa", "Minneapolis", "Cleveland", "Wichita", "Arlington", "New Orleans", "Bakersfield", "Tampa", "Honolulu", "Anaheim", "Aurora", "Santa Ana", "St. Louis", "Riverside", "Corpus Christi", "Pittsburgh", "Lexington-Fayette", "Stockton", "Cincinnati", "St. Paul", "Toledo", "Newark", "Greensboro", "Plano", "Henderson", "Lincoln", "Buffalo", "Fort Wayne", "Jersey ", "Chula Vista", "Orlando", "St. Petersburg", "Norfolk", "Chandler", "Laredo", "Madison", "Durham", "Lubbock", "Winston-Salem", "Garland", "Glendale", "Hialeah", "Reno", "Baton Rouge", "Irvine", "Chesapeake", "Irving", "Scottsdale", "North Las Vegas", "Fremont", "San Bernardino", "Boise", "Birmingham"}, + "city": {"New York City", "Los Angeles", "Chicago", "Houston", "Philadelphia", "Phoenix", "San Antonio", "San Diego", "Dallas", "San Jose", "Austin", "Jacksonville", "Indianapolis", "San Francisco", "Columbus", "Fort Worth", "Charlotte", "Detroit", "El Paso", "Memphis", "Boston", "Seattle", "Denver", "Washington", "Nashville-Davidson", "Baltimore", "Louisville/Jefferson", "Portland", "Oklahoma", "Milwaukee", "Las Vegas", "Albuquerque", "Tucson", "Fresno", "Sacramento", "Long Beach", "Kansas", "Mesa", "Virginia Beach", "Atlanta", "Colorado Springs", "Raleigh", "Omaha", "Miami", "Oakland", "Tulsa", "Minneapolis", "Cleveland", "Wichita", "Arlington", "New Orleans", "Bakersfield", "Tampa", "Honolulu", "Anaheim", "Aurora", "Santa Ana", "St. Louis", "Riverside", "Corpus Christi", "Pittsburgh", "Lexington-Fayette", "Stockton", "Cincinnati", "St. Paul", "Toledo", "Newark", "Greensboro", "Plano", "Henderson", "Lincoln", "Buffalo", "Fort Wayne", "Jersey", "Chula Vista", "Orlando", "St. Petersburg", "Norfolk", "Chandler", "Laredo", "Madison", "Durham", "Lubbock", "Winston-Salem", "Garland", "Glendale", "Hialeah", "Reno", "Baton Rouge", "Irvine", "Chesapeake", "Irving", "Scottsdale", "North Las Vegas", "Fremont", "San Bernardino", "Boise", "Birmingham"}, "state": {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"}, "state_abr": {"AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "AE", "AA", "AP"}, "zip": {"#####"}, diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go b/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go index ef68c1891..2e3793744 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/animals.go @@ -8,4 +8,5 @@ var Animal = map[string][]string{ "farm": {"Chicken", "Cow", "Donkey", "Duck", "Goat", "Goose", "Horse", "Llama", "Pig", "Sheep", "Turkey"}, "cat": {"Abyssinian", "Aegean", "American Bobtail", "American Curl", "American Shorthair", "American Wirehair", "Arabian Mau", "Asian", "Asian Semi-longhair", "Australian Mist", "Balinese", "Bambino", "Bengal", "Birman", "Bombay", "Brazilian Shorthair", "British Longhair", "British Semipi-longhair", "British Shorthair", "Burmese", "Burmilla", "California Spangled", "Chantilly-Tiffany", "Chartreux", "Chausie", "Cheetoh", "Colorpoint Shorthair", "Cornish Rex", "Cymric, or Manx Longhair", "Cyprus", "Devon Rex", "Donskoy, or Don Sphynx", "Dragon Li", "Dwarf cat, or Dwelf", "Egyptian Mau", "European Shorthair", "Exotic Shorthair", "Foldex Cat", "German Rex", "Havana Brown", "Highlander", "Himalayan, or Colorpoint Persian", "Japanese Bobtail", "Javanese", "Khao Manee", "Korat", "Korean Bobtail", "Korn Ja", "Kurilian Bobtail", "Kurilian Bobtail, or Kuril Islands Bobtail", "LaPerm", "Lykoi", "Maine Coon", "Manx", "Mekong Bobtail", "Minskin", "Munchkin", "Napoleon", "Nebelung", "Norwegian Forest Cat", "Ocicat", "Ojos Azules", "Oregon Rex", "Oriental Bicolor", "Oriental Longhair", "Oriental Shorthair", "Persian", "Peterbald", "Pixie-bob", "Raas", "Ragamuffin", "Ragdoll", "Russian Blue", "Russian White, Black and Tabby", "Sam Sawet", "Savannah", "Scottish Fold", "Selkirk Rex", "Serengeti", "Serrade petit", "Siamese", "Siberian", "Singapura", "Snowshoe", "Sokoke", "Somali", "Sphynx", "Suphalak", "Thai", "Tonkinese", "Toyger", "Turkish Angora", "Turkish Van", "Ukrainian Levkoy"}, "dog": {"Affenpinscher", "African", "Airedale", "Akita", "Appenzeller", "Basenji", "Beagle", "Bluetick", "Borzoi", "Bouvier", "Boxer", "Brabancon", "Briard", "Boston Bulldog", "French Bulldog", "Staffordshire Bullterrier", "Cairn", "Chihuahua", "Chow", "Clumber", "Border Collie", "Coonhound", "Cardigan Corgi", "Dachshund", "Great Dane", "Scottish Deerhound", "Dhole", "Dingo", "Doberman", "Norwegian Elkhound", "Entlebucher", "Eskimo", "Germanshepherd", "Italian Greyhound", "Groenendael", "Ibizan Hound", "Afghan Hound", "Basset Hound", "Blood Hound", "English Hound", "Walker Hound", "Husky", "Keeshond", "Kelpie", "Komondor", "Kuvasz", "Labrador", "Leonberg", "Lhasa", "Malamute", "Malinois", "Maltese", "Bull Mastiff", "Tibetan Mastiff", "Mexicanhairless", "Bernese Mountain", "Swiss Mountain", "Newfoundland", "Otterhound", "Papillon", "Pekinese", "Pembroke", "Miniature Pinscher", "German Pointer", "Pomeranian", "Miniature Poodle", "Standard Poodle", "Toy Poodle", "Pug", "Pyrenees", "Redbone", "Chesapeake Retriever", "Curly Retriever", "Flatcoated Retriever", "Golden Retriever", "Rhodesian Ridgeback", "Rottweiler", "Saluki", "Samoyed", "Schipperke", "Giant Schnauzer", "Miniature Schnauzer", "English Setter", "Gordon Setter", "Irish Setter", "English Sheepdog", "Shetland Sheepdog", "Shiba", "Shihtzu", "Blenheim Spaniel", "Brittany Spaniel", "Cocker Spaniel", "Irish Spaniel", "Japanese Spaniel", "Sussex Spaniel", "Welsh Spaniel", "English Springer", "Stbernard", "American Terrier", "Australian Terrier", "Bedlington Terrier", "Border Terrier", "Dandie Terrier", "Fox Terrier", "Irish Terrier", "Kerryblue Terrier", "Lakeland Terrier", "Norfolk Terrier", "Norwich Terrier", "Patterdale Terrier", "Rat Terrier", "Scottish Terrier", "Sealyham Terrier", "Silky Terrier", "Tibetan Terrier", "Toy Terrier", "Westhighland Terrier", "Wheaten Terrier", "Yorkshire Terrier", "Vizsla", "Weimaraner", "Whippet", "Irish Wolfhound"}, + "bird": {"albatross", "bluejay", "canary", "cardinal", "chicken", "crow", "dove", "duck", "eagle", "emu", "falcon", "flamingo", "goose", "hornbill", "hummingbird", "ibis", "jay", "kingfisher", "lovebird", "mynah", "nightingale", "oriole", "ostrich", "owl", "parrot", "peacock", "penguin", "quail", "rooster", "sparrow", "swan", "thrush", "toucan", "vulture", "woodpecker", "yellow warbler"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/book.go b/vendor/github.com/brianvoe/gofakeit/v6/data/book.go new file mode 100644 index 000000000..ec3e5d849 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/book.go @@ -0,0 +1,101 @@ +package data + +var Books = map[string][]string{ + "title": { + "Anna Karenina", + "Beloved", + "Blindness", + "Bostan", + "Buddenbrooks", + "Crime and Punishment", + "Don Quijote De La Mancha", + "Fairy tales", + "Faust", + "Gulliver's Travels", + "Gypsy Ballads", + "Hamlet", + "Harry potter and the sorcerer's stone", + "King Lear", + "Leaves of Grass", + "Lolita", + "Madame Bovary", + "Memoirs of Hadrian", + "Metamorphoses", + "Moby Dick", + "Nineteen Eighty-Four", + "Odyssey", + "Oedipus the King", + "One Hundred Years of Solitude", + "One Thousand and One Nights", + "Othello", + "Pippi Longstocking", + "Pride and Prejudice", + "Romeo & Juliet", + "Sherlock Holmes", + "Sons and Lovers", + "The Adventures of Huckleberry Finn", + "The Book Of Job", + "The Brothers Karamazov", + "The Golden Notebook", + "The Idiot", + "The Old Man and the Sea", + "The Stranger", + "Things Fall Apart", + "Ulysses", + "War and Peace", + "Wuthering Heights", + "Zorba the Greek", + }, + "author": { + "Albert Camus", + "Astrid Lindgren", + "Charles Dickens", + "D. H. Lawrence", + "Edgar Allan Poe", + "Emily Brontë", + "Ernest Hemingway", + "Franz Kafka", + "Fyodor Dostoevsky", + "George Orwell", + "Hans Christian Andersen", + "Homer", + "James Joyce", + "Jane Austen", + "Johann Wolfgang von Goethe", + "Jorge Luis Borges", + "Joanne K. Rowling", + "Leo Tolstoy", + "Marcel Proust", + "Mark Twain", + "Paul Celan", + "Salman Rushdie", + "Sophocles", + "Thomas Mann", + "Toni Morrison", + "Vladimir Nabokov", + "William Faulkner", + "William Shakespeare", + "Yasunari Kawabata", + }, + "genre": { + "Adventure", + "Comic", + "Crime", + "Erotic", + "Fiction", + "Fantasy", + "Historical", + "Horror", + "Magic", + "Mystery", + "Philosophical", + "Political", + "Romance", + "Saga", + "Satire", + "Science", + "Speculative", + "Thriller", + "Urban", + }, +} \ No newline at end of file diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/car.go b/vendor/github.com/brianvoe/gofakeit/v6/data/car.go index c144fee8a..8754b1220 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/car.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/car.go @@ -6,5 +6,5 @@ var Car = map[string][]string{ "fuel_type": {"Gasoline", "Methanol", "Ethanol", "Diesel", "LPG", "CNG", "Electric"}, "transmission_type": {"Manual", "Automatic"}, "maker": {"Alfa Romeo", "Aston Martin", "Audi", "Bentley", "Benz", "BMW", "Bugatti", "Cadillac", "Chevrolet", "Chrysler", "Citroen", "Corvette", "DAF", "Dacia", "Daewoo", "Daihatsu", "Datsun", "De Lorean", "Dino", "Dodge", "Farboud", "Ferrari", "Fiat", "Ford", "Honda", "Hummer", "Hyundai", "Jaguar", "Jeep", "KIA", "Koenigsegg", "Lada", "Lamborghini", "Lancia", "Land Rover", "Lexus", "Ligier", "Lincoln", "Lotus", "Martini", "Maserati", "Maybach", "Mazda", "McLaren", "Mercedes", "Mercedes-Benz", "Mini", "Mitsubishi", "Nissan", "Noble", "Opel", "Peugeot", "Pontiac", "Porsche", "Renault", "Rolls-Royce", "Rover", "Saab", "Seat", "Skoda", "Smart", "Spyker", "Subaru", "Suzuki", "Toyota", "Tesla", "Vauxhall", "Volkswagen", "Volvo"}, - "model": {"Db9 Coupe", "Db9 Coupe Manual", "Db9 Volante", "V12 Vanquish S", "V8 Vantage", "A3", "A4", "A4 Avant Quattro", "A4 Cabriolet", "A4 Cabriolet Quattro", "A4 Quattro", "A6", "A6 Avant Quattro", "A6 Quattro", "A8 L", "Gti", "Passat", "S4", "S4 Avant", "S4 Cabriolet", "Tt Coupe", "Tt Roadster", "Bentley Arnage", "Continental Flying Spur", "Continental Gt", " 325ci Convertible", " 325i", " 325xi", " 325xi Sport Wagon", " 330ci Convertible", " 330i", " 330xi", " 525i", " 525xi", " 530i", " 530xi", " 530xi Sport Wagon", " 550i", " 650ci", " 650ci Convertible", " 750li", " 760li", " M3", " M3 Convertible", " M5", " M6", " Mini Cooper", " Mini Cooper Convertible", " Mini Cooper S", " Mini Cooper S Convertible", " X3", " X5", " X5 4.8is", " Z4 3.0 Si Coupe", " Z4 3.0i", " Z4 3.0si", " Z4 M Roadster", "Veyron", "300c/srt-8", "Caravan 2wd", "Charger", "Commander 4wd", "Crossfire Roadster", "Dakota Pickup 2wd", "Dakota Pickup 4wd", "Durango 2wd", "Durango 4wd", "Grand Cherokee 2wd", "Grand Cherokee 4wd", "Liberty/cherokee 2wd", "Liberty/cherokee 4wd", "Pacifica 2wd", "Pacifica Awd", "Pt Cruiser", "Ram 1500 Pickup 2wd", "Ram 1500 Pickup 4wd", "Sebring 4-dr", "Stratus 4-dr", "Town & Country 2wd", "Viper Convertible", "Wrangler/tj 4wd", "F430", "Ferrari 612 Scaglietti", "Ferrari F141", "B4000 4wd", "Crown Victoria Police", "E150 Club Wagon", "E150 Econoline 2wd", "Escape 4wd", "Escape Fwd", "Escape Hybrid 4wd", "Escape Hybrid Fwd", "Expedition 2wd", "Explorer 2wd", "Explorer 4wd", "F150 Ffv 2wd", "F150 Ffv 4wd", "F150 Pickup 2wd", "F150 Pickup 4wd", "Five Hundred Awd", "Focus Fwd", "Focus Station Wag", "Freestar Wagon Fwd", "Freestyle Awd", "Freestyle Fwd", "Grand Marquis", "Gt 2wd", "Ls", "Mark Lt", "Milan", "Monterey Wagon Fwd", "Mountaineer 4wd", "Mustang", "Navigator 2wd", "Ranger Pickup 2wd", "Ranger Pickup 4wd", "Taurus", "Taurus Ethanol Ffv", "Thunderbird", "Town Car", "Zephyr", "B9 Tribeca Awd", "Baja Awd", "Forester Awd", "Impreza Awd", "Impreza Wgn/outback Spt Awd", "Legacy Awd", "Legacy Wagon Awd", "Outback Awd", "Outback Wagon Awd", "9-3 Convertible", "9-3 Sport Sedan", "9-5 Sedan", "C15 Silverado Hybrid 2wd", "C1500 Silverado 2wd", "C1500 Suburban 2wd", "C1500 Tahoe 2wd", "C1500 Yukon 2wd", "Cobalt", "Colorado 2wd", "Colorado 4wd", "Colorado Cab Chassis Inc 2wd", "Colorado Crew Cab 2wd", "Colorado Crew Cab 4wd", "Corvette", "Cts", "Dts", "Envoy 2wd", "Envoy Xl 4wd", "Equinox Awd", "Equinox Fwd", "Escalade 2wd", "Escalade Esv Awd", "G15/25chev Van 2wd Conv", "G1500/2500 Chevy Express 2wd", "G1500/2500 Chevy Van 2wd", "G6", "G6 Gt/gtp Convertible", "Grand Prix", "Gto", "H3 4wd", "Hhr Fwd", "I-280 2wd Ext Cab", "Impala", "K15 Silverado Hybrid 4wd", "K1500 Avalanche 4wd", "K1500 Silverado 4wd", "K1500 Tahoe 4wd", "Lacrosse/allure", "Limousine", "Malibu", "Montana Sv6 Awd", "Monte Carlo", "Rendezvous Awd", "Rendezvous Fwd", "Solstice", "Srx 2wd", "Srx Awd", "Ssr Pickup 2wd", "Sts", "Sts Awd", "Terraza Fwd", "Trailblazer 2wd", "Trailblazer 4wd", "Trailblazer Awd", "Trailblazer Ext 4wd", "Uplander Fwd", "Vue Awd", "Vue Fwd", "Xlr", "Aveo", "Forenza", "Forenza Wagon", "Verona", "Accord", "Accord Hybrid", "Civic", "Civic Hybrid", "Cr-v 4wd", "Element 2wd", "Element 4wd", "Insight", "Mdx 4wd", "Odyssey 2wd", "Pilot 2wd", "Pilot 4wd", "Ridgeline 4wd", "Rl", "Rsx", "S2000", "Tl", "Tsx", "Accent", "Azera", "Elantra", "Santafe 2wd", "Santafe 4wd", "Sonata", "Tiburon", "Tucson 2wd", "Tucson 4wd", "S-type 3.0 Litre", "S-type 4.2 Litre", "S-type R", "Vdp Lwb", "Xj8", "Xk8 Convertible", "Xkr Convertible", "X-type", "X-type Sport Brake", "Amanti", "Optima", "Optima(ms)", "Rio", "Sedona", "Sorento 2wd", "Sorento 4wd", "Spectra(ld)", "Sportage 2wd", "Sportage 4wd", "L-140/715 Gallardo", "L-147/148 Murcielago", "Lr3", "Range Rover", "Range Rover Sport", "Elise/exige", "Coupe Cambiocorsa/gt/g-sport", "Quattroporte", "Mazda 3", "Mazda 5", "Mazda 6", "Mazda 6 Sport Wagon", "Mazda Rx-8", "Mpv", "Mx-5", "C230", "C280", "C280 4matic", "C350", "C350 4matic", "C55 Amg", "Cl65 Amg", "Clk350", "Clk350 (cabriolet)", "Clk55 Amg (cabriolet)", "Cls500", "Cls55 Amg", "E320 Cdi", "E350", "E350 (wagon)", "E350 4matic", "E350 4matic (wagon)", "E500", "E55 Amg", "E55 Amg (wagon)", "Maybach 57s", "Maybach 62", "Ml350", "Ml500", "R350", "R500", "S350", "S430", "Sl500", "Sl600", "Sl65 Amg", "Slk280", "Slk350", "Slr", "Eclipse", "Endeavor 2wd", "Endeavor 4wd", "Galant", "Lancer", "Lancer Evolution", "Lancer Sportback", "Montero", "Outlander 2wd", "Outlander 4wd", "Vibe", "350z", "350z Roadster", "Altima", "Armada 2wd", "Armada 4wd", "Frontier 2wd", "Frontier V6-2wd", "Frontier V6-4wd", "Fx35 Awd", "Fx35 Rwd", "Fx45 Awd", "G35", "M35", "M35x", "M45", "Maxima", "Murano Awd", "Murano Fwd", "Pathfinder 2wd", "Pathfinder 4wd", "Q45", "Q45 Sport", "Quest", "Qx56 4wd", "Sentra", "Titan 2wd", "Titan 4wd", "Xterra 2wd", "Xterra 4wd", "Boxster", "Boxster S", "Carrera 2 Coupe", "Cayenne", "Cayenne S", "Cayenne Turbo", "Cayman S", "Phantom", "F150 Supercrew 4wd", "C8 Spyder", "Aerio", "Aerio Sx", "Aerio Sx Awd", "Grand Vitara Xl-7", "Grand Vitara Xl-7 4wd", "Grand Vitara Xv6", "Grand Vitara Xv6 Awd", "4runner 2wd", "4runner 4wd", "Avalon", "Camry", "Camry Solara", "Camry Solara Convertible", "Corolla", "Corolla Matrix", "Es 330", "Gs 300 4wd", "Gs 300/gs 430", "Gx 470", "Highlander 2wd", "Highlander 4wd", "Highlander Hybrid 2wd", "Highlander Hybrid 4wd", "Is 250", "Is 250 Awd", "Is 350", "Ls 430", "Lx 470", "Prius", "Rav4 2wd", "Rav4 4wd", "Rx 330 2wd", "Rx 330 4wd", "Rx 400h 4wd", "Sc 430", "Scion Tc", "Scion Xa", "Scion Xb", "Sequoia 2wd", "Sequoia 4wd", "Sienna 2wd", "Sienna 4wd", "Toyota Tacoma 2wd", "Toyota Tacoma 4wd", "Toyota Tundra 2wd", "Toyota Tundra 4wd", "Yaris", "A3 Quattro", "Golf", "Jetta", "New Beetle", "New Beetle Convertible", "Passat Wagon 4motion", "Phaeton", "Rabbit", "Touareg", "Tt Coupe Quattro", "Tt Roadster Quattro", "C70 Convertible", "S40 Awd", "S40 Fwd", "S60 Awd", "S60 Fwd", "S60 R Awd", "S80 Fwd", "V50 Awd", "V70 Fwd", "V70 R Awd", "Xc 70 Awd", "Xc 90 Awd", "Xc 90 Fwd"}, + "model": {"Db9 Coupe", "Db9 Coupe Manual", "Db9 Volante", "V12 Vanquish S", "V8 Vantage", "A3", "A4", "A4 Avant Quattro", "A4 Cabriolet", "A4 Cabriolet Quattro", "A4 Quattro", "A6", "A6 Avant Quattro", "A6 Quattro", "A8 L", "Gti", "Passat", "S4", "S4 Avant", "S4 Cabriolet", "Tt Coupe", "Tt Roadster", "Bentley Arnage", "Continental Flying Spur", "Continental Gt", "325ci Convertible", "325i", "325xi", "325xi Sport Wagon", "330ci Convertible", "330i", "330xi", "525i", "525xi", "530i", "530xi", "530xi Sport Wagon", "550i", "650ci", "650ci Convertible", "750li", "760li", "M3", "M3 Convertible", "M5", "M6", "Mini Cooper", "Mini Cooper Convertible", "Mini Cooper S", "Mini Cooper S Convertible", "X3", "X5", "X5 4.8is", "Z4 3.0 Si Coupe", "Z4 3.0i", "Z4 3.0si", "Z4 M Roadster", "Veyron", "300c/srt-8", "Caravan 2wd", "Charger", "Commander 4wd", "Crossfire Roadster", "Dakota Pickup 2wd", "Dakota Pickup 4wd", "Durango 2wd", "Durango 4wd", "Grand Cherokee 2wd", "Grand Cherokee 4wd", "Liberty/cherokee 2wd", "Liberty/cherokee 4wd", "Pacifica 2wd", "Pacifica Awd", "Pt Cruiser", "Ram 1500 Pickup 2wd", "Ram 1500 Pickup 4wd", "Sebring 4-dr", "Stratus 4-dr", "Town & Country 2wd", "Viper Convertible", "Wrangler/tj 4wd", "F430", "Ferrari 612 Scaglietti", "Ferrari F141", "B4000 4wd", "Crown Victoria Police", "E150 Club Wagon", "E150 Econoline 2wd", "Escape 4wd", "Escape Fwd", "Escape Hybrid 4wd", "Escape Hybrid Fwd", "Expedition 2wd", "Explorer 2wd", "Explorer 4wd", "F150 Ffv 2wd", "F150 Ffv 4wd", "F150 Pickup 2wd", "F150 Pickup 4wd", "Five Hundred Awd", "Focus Fwd", "Focus Station Wag", "Freestar Wagon Fwd", "Freestyle Awd", "Freestyle Fwd", "Grand Marquis", "Gt 2wd", "Ls", "Mark Lt", "Milan", "Monterey Wagon Fwd", "Mountaineer 4wd", "Mustang", "Navigator 2wd", "Ranger Pickup 2wd", "Ranger Pickup 4wd", "Taurus", "Taurus Ethanol Ffv", "Thunderbird", "Town Car", "Zephyr", "B9 Tribeca Awd", "Baja Awd", "Forester Awd", "Impreza Awd", "Impreza Wgn/outback Spt Awd", "Legacy Awd", "Legacy Wagon Awd", "Outback Awd", "Outback Wagon Awd", "9-3 Convertible", "9-3 Sport Sedan", "9-5 Sedan", "C15 Silverado Hybrid 2wd", "C1500 Silverado 2wd", "C1500 Suburban 2wd", "C1500 Tahoe 2wd", "C1500 Yukon 2wd", "Cobalt", "Colorado 2wd", "Colorado 4wd", "Colorado Cab Chassis Inc 2wd", "Colorado Crew Cab 2wd", "Colorado Crew Cab 4wd", "Corvette", "Cts", "Dts", "Envoy 2wd", "Envoy Xl 4wd", "Equinox Awd", "Equinox Fwd", "Escalade 2wd", "Escalade Esv Awd", "G15/25chev Van 2wd Conv", "G1500/2500 Chevy Express 2wd", "G1500/2500 Chevy Van 2wd", "G6", "G6 Gt/gtp Convertible", "Grand Prix", "Gto", "H3 4wd", "Hhr Fwd", "I-280 2wd Ext Cab", "Impala", "K15 Silverado Hybrid 4wd", "K1500 Avalanche 4wd", "K1500 Silverado 4wd", "K1500 Tahoe 4wd", "Lacrosse/allure", "Limousine", "Malibu", "Montana Sv6 Awd", "Monte Carlo", "Rendezvous Awd", "Rendezvous Fwd", "Solstice", "Srx 2wd", "Srx Awd", "Ssr Pickup 2wd", "Sts", "Sts Awd", "Terraza Fwd", "Trailblazer 2wd", "Trailblazer 4wd", "Trailblazer Awd", "Trailblazer Ext 4wd", "Uplander Fwd", "Vue Awd", "Vue Fwd", "Xlr", "Aveo", "Forenza", "Forenza Wagon", "Verona", "Accord", "Accord Hybrid", "Civic", "Civic Hybrid", "Cr-v 4wd", "Element 2wd", "Element 4wd", "Insight", "Mdx 4wd", "Odyssey 2wd", "Pilot 2wd", "Pilot 4wd", "Ridgeline 4wd", "Rl", "Rsx", "S2000", "Tl", "Tsx", "Accent", "Azera", "Elantra", "Santafe 2wd", "Santafe 4wd", "Sonata", "Tiburon", "Tucson 2wd", "Tucson 4wd", "S-type 3.0 Litre", "S-type 4.2 Litre", "S-type R", "Vdp Lwb", "Xj8", "Xk8 Convertible", "Xkr Convertible", "X-type", "X-type Sport Brake", "Amanti", "Optima", "Optima(ms)", "Rio", "Sedona", "Sorento 2wd", "Sorento 4wd", "Spectra(ld)", "Sportage 2wd", "Sportage 4wd", "L-140/715 Gallardo", "L-147/148 Murcielago", "Lr3", "Range Rover", "Range Rover Sport", "Elise/exige", "Coupe Cambiocorsa/gt/g-sport", "Quattroporte", "Mazda 3", "Mazda 5", "Mazda 6", "Mazda 6 Sport Wagon", "Mazda Rx-8", "Mpv", "Mx-5", "C230", "C280", "C280 4matic", "C350", "C350 4matic", "C55 Amg", "Cl65 Amg", "Clk350", "Clk350 (cabriolet)", "Clk55 Amg (cabriolet)", "Cls500", "Cls55 Amg", "E320 Cdi", "E350", "E350 (wagon)", "E350 4matic", "E350 4matic (wagon)", "E500", "E55 Amg", "E55 Amg (wagon)", "Maybach 57s", "Maybach 62", "Ml350", "Ml500", "R350", "R500", "S350", "S430", "Sl500", "Sl600", "Sl65 Amg", "Slk280", "Slk350", "Slr", "Eclipse", "Endeavor 2wd", "Endeavor 4wd", "Galant", "Lancer", "Lancer Evolution", "Lancer Sportback", "Montero", "Outlander 2wd", "Outlander 4wd", "Vibe", "350z", "350z Roadster", "Altima", "Armada 2wd", "Armada 4wd", "Frontier 2wd", "Frontier V6-2wd", "Frontier V6-4wd", "Fx35 Awd", "Fx35 Rwd", "Fx45 Awd", "G35", "M35", "M35x", "M45", "Maxima", "Murano Awd", "Murano Fwd", "Pathfinder 2wd", "Pathfinder 4wd", "Q45", "Q45 Sport", "Quest", "Qx56 4wd", "Sentra", "Titan 2wd", "Titan 4wd", "Xterra 2wd", "Xterra 4wd", "Boxster", "Boxster S", "Carrera 2 Coupe", "Cayenne", "Cayenne S", "Cayenne Turbo", "Cayman S", "Phantom", "F150 Supercrew 4wd", "C8 Spyder", "Aerio", "Aerio Sx", "Aerio Sx Awd", "Grand Vitara Xl-7", "Grand Vitara Xl-7 4wd", "Grand Vitara Xv6", "Grand Vitara Xv6 Awd", "4runner 2wd", "4runner 4wd", "Avalon", "Camry", "Camry Solara", "Camry Solara Convertible", "Corolla", "Corolla Matrix", "Es 330", "Gs 300 4wd", "Gs 300/gs 430", "Gx 470", "Highlander 2wd", "Highlander 4wd", "Highlander Hybrid 2wd", "Highlander Hybrid 4wd", "Is 250", "Is 250 Awd", "Is 350", "Ls 430", "Lx 470", "Prius", "Rav4 2wd", "Rav4 4wd", "Rx 330 2wd", "Rx 330 4wd", "Rx 400h 4wd", "Sc 430", "Scion Tc", "Scion Xa", "Scion Xb", "Sequoia 2wd", "Sequoia 4wd", "Sienna 2wd", "Sienna 4wd", "Toyota Tacoma 2wd", "Toyota Tacoma 4wd", "Toyota Tundra 2wd", "Toyota Tundra 4wd", "Yaris", "A3 Quattro", "Golf", "Jetta", "New Beetle", "New Beetle Convertible", "Passat Wagon 4motion", "Phaeton", "Rabbit", "Touareg", "Tt Coupe Quattro", "Tt Roadster Quattro", "C70 Convertible", "S40 Awd", "S40 Fwd", "S60 Awd", "S60 Fwd", "S60 R Awd", "S80 Fwd", "V50 Awd", "V70 Fwd", "V70 R Awd", "Xc 70 Awd", "Xc 90 Awd", "Xc 90 Fwd"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go b/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go index 597c99d56..ae4fcffd8 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/celebrity.go @@ -3,5 +3,5 @@ package data var Celebrity = map[string][]string{ "actor": {"Arnold Schwarzenegger", "Jim Carrey", "Emma Watson", "Robert Downey Jr.", "Daniel Radcliffe", "Chris Evans", "Leonardo DiCaprio", "Tom Cruise", "Brad Pitt", "Charles Chaplin", "Morgan Freeman", "Tom Hanks", "Hugh Jackman", "Matt Damon", "Sylvester Stallone", "Will Smith", "Clint Eastwood", "Cameron Diaz", "George Clooney", "Steven Spielberg", "Harrison Ford", "Robert De Niro", "Al Pacino", "Robert Downey Jr.", "Russell Crowe", "Liam Neeson", "Kate Winslet", "Mark Wahlberg", "Natalie Portman", "Pierce Brosnan", "Sean Connery", "Orlando Bloom", "Dwayne Johnson", "Jackie Chan", "Angelina Jolie", "Adam Sandler", "Scarlett Johansson", "Heath Ledger", "Anne Hathaway", "Jessica Alba", "Edward Norton", "Keira Knightley", "Bradley Cooper", "Will Ferrell", "Julia Roberts", "Nicolas Cage", "Daniel Craig", "Keanu Reeves", "Ian McKellen", "Halle Berry", "Bruce Willis", "Ben Stiller", "Tommy Lee Jones", "Antonio Banderas", "Denzel Washington", "Steve Carell", "Shia LaBeouf", "Megan Fox", "James Franco", "Mel Gibson", "Vin Diesel", "Tim Allen", "Robin Williams", "Kevin Spacey", "Jason Biggs", "Seann William Scott", "Jean-Claude Van Damme", "Zach Galifianakis", "Owen Wilson", "Christian Bale", "Peter Jackson", "Sandra Bullock", "Bruce Lee", "Drew Barrymore", "Macaulay Culkin", "Jack Nicholson", "Bill Murray", "Sigourney Weaver", "Jake Gyllenhaal", "Jason Statham", "Jet Li", "Kate Beckinsale", "Rowan Atkinson", "Marlon Brando", "John Travolta", "Channing Tatum", "Ben Affleck", "Shah Rukh Khan", "Jennifer Aniston", "Emma Stone", "Chris Hemsworth", "James McAvoy", "James Cameron", "Amitabh Bachchan", "Brendan Fraser", "Rachel McAdams", "Tom Hiddleston", "Aamir Khan"}, "business": {"Elon Musk", "Steve Jobs", "Jeff Bezos", "Bill Gates", "Mark Zuckerberg", "Sundar Pichai", "Walt Disney", "Warren Buffett", "Mukesh Ambani", "P. T. Barnum", "Colonel Sanders", "Ray Kroc", "Richard Branson", "Henry Ford", "Larry Page", "Steve Wozniak", "Ratan Tata", "John D. Rockefeller", "Madam C. J. Walker", "Tim Cook", "Andrew Carnegie", "Paul Allen", "Bobby Flay", "J. P. Morgan", "Satya Nadella", "Dhirubhai Ambani", "Carlos Slim", "Ross Perot", "Jamie Oliver", "Jack Ma", "Larry Ellison", "Sam Walton", "Sheryl Sandberg", "Marco Pierre White", "Indra Nooyi", "David Rockefeller", "Steve Ballmer", "Beyonce Knowles", "N. R. Narayana Murthy", "Mark Wahlberg", "Cameron Diaz", "Sergey Brin", "Howard Hughes", "Jessica Alba", "Dustin Moskovitz", "Eva Mendes", "Amancio Ortega Gaona", "Fred Trump", "Jamsetji Tata", "Kate Hudson", "Martha Stewart", "Peter Jones", "Marco Polo", "Susan Wojcicki", "Oskar Schindler", "Elizabeth Hurley", "Sean Combs", "Kate Spade", "Vincent McMahon", "David Chang", "Coco Chanel", "Vera Wang", "Arianna Huffington", "John McAfee", "Dany Garcia", "Richard Attenborough", "Donatella Versace", "Chris Hughes", "Alexis Ohanian", "J. Paul Getty", "Sharon Osbourne", "Bob Iger", "Kate Walsh", "Chris Gardner", "Jessica Simpson", "Guy Fieri", "Joy Mangano", "Wolfgang Puck", "Christie Brinkley", "Tom Steyer", "Evan Spiegel", "Hugh Hefner", "Preity Zinta", "Shane McMahon", "Salt Bae", "Mario Batali", "Bernard Arnault", "Michael Bloomberg", "Portia de Rossi", "Kevin O'Leary", "Roman Abramovich", "Jamie Dimon", "Rob Dyrdek", "Emeril Lagasse", "Kat Von D", "Karlie Kloss", "Antoni Porowski", "Edmond James de Rothschild", "Mitt Romney", "Aristotle Onassis", "Richard Benjamin Harrison", "Ben Bernanke", "Mark Cuban", "William Randolph Hearst", "Nate Robinson", "Alan Shepard", "Christina Anstead", "Laurene Powell Jobs", "Adam Weitsman", "Gladys Knight", "Gary Vaynerchuk", "Robert Kraft", "John Paul DeJoria", "Lori Greiner", "Carly Fiorina", "Lakshmi Mittal", "Jerry Jones", "Meg Whitman", "Azim Premji", "Lisa Vanderpump", "Dana White", "Russell Simmons", "Jennifer Flavin", "Harry Hamlin", "Conrad Hilton", "Prescott Bush", "Alvaro Morte", "Shigeru Miyamoto", "Phil Knight", "Jack Dorsey", "Barbara Bush", "Lee Iacocca", "Ma Huateng", "Rick Harrison", "Drew Scott", "Jawed Karim", "Daymond John", "Jaclyn Smith", "Maryse Ouellet", "Allegra Versace"}, - "sport": {"Pele", "Usain Bolt", "Muhammad Ali", "Carl Lewis", "Jesse Owens", "Sir Donald Bradman", "Billie Jean King", "Eddy Merckx", "Jackie Joyner-Kersee", "Lionel Messi", "Babe Didrikson Zaharias", "Michael Jordan", "Larisa Latynina", "Diego Maradona", "Serena Williams", "Babe Ruth", "Roger Federer", "Martina Navratilova", "Michael Phelps", "Lottie Dod", "Sachin Tendulkar", "Johan Cruyff", "Tiger Woods ", "Sonja Henie", "Aryton Senna", "Nadia Comaneci", "Sergei Bubka", "Emil Zatopek", "Manny Pacquiao", "Imran Khan", "Jackie Robinson", "Shane Warne", "Dhyan Chand", "Fred Perry", "Lin Dan", "Abebe Bikila", "Clara Hughes", "Jan-Ove Waldner", "Bobby Moore", "Bjorn Borg ", "Karch Kiraly", "Bradley Wiggins", "Seve Ballesteros", "David Beckham", "Michael Schumacher", "Greg Lemond", "Mia Hamm", "Jacques Anquetil", "Jack Nicklaus", "Steve Davis", "John McEnroe", "Monica Seles", "Magic Johnson", "Joe DiMaggio", "Roger Bannister", "Mo Farah", "Mark Spitz", "Chris Evert", "Al Oerter", "Jimmy Connors", "Michael Johnson", "Ian Botham ", "Jim Thorpe", "Sir Steve Redgrave", "Steffi Graf", "Sebastian Coe", "Hicham El Guerrouj", "Eric Liddell", "W.G Grace", "Kenenisa Bekele", "Bernard Hinault ", "Bob Beamon", "Paavo Nurmi", "David Campese", "Kelly Slater", "Haile Gebreselassie", "Rafael Nadal", "Brian Lara", "Chris Hoy", "Serge Blanco", "Cristiano Ronaldo", "Sir Gary Sobers", "Andy Murray", "George Best", "Sir Viv Richards", "Fausto Coppi", "Eusebio", "Rod Laver", "Grete Waitz", "Margaret Smith Court", "Tegla Laroupe", "Fanny Blankers-Koen", "Asbel Kiprop", "Lewis Hamilton", "C.B.Fry", "Annika Sörenstam", "Wilma Rudolph", "Alberta Tomba", "Bo Jackson"}, + "sport": {"Pele", "Usain Bolt", "Muhammad Ali", "Carl Lewis", "Jesse Owens", "Sir Donald Bradman", "Billie Jean King", "Eddy Merckx", "Jackie Joyner-Kersee", "Lionel Messi", "Babe Didrikson Zaharias", "Michael Jordan", "Larisa Latynina", "Diego Maradona", "Serena Williams", "Babe Ruth", "Roger Federer", "Martina Navratilova", "Michael Phelps", "Lottie Dod", "Sachin Tendulkar", "Johan Cruyff", "Tiger Woods", "Sonja Henie", "Aryton Senna", "Nadia Comaneci", "Sergei Bubka", "Emil Zatopek", "Manny Pacquiao", "Imran Khan", "Jackie Robinson", "Shane Warne", "Dhyan Chand", "Fred Perry", "Lin Dan", "Abebe Bikila", "Clara Hughes", "Jan-Ove Waldner", "Bobby Moore", "Bjorn Borg", "Karch Kiraly", "Bradley Wiggins", "Seve Ballesteros", "David Beckham", "Michael Schumacher", "Greg Lemond", "Mia Hamm", "Jacques Anquetil", "Jack Nicklaus", "Steve Davis", "John McEnroe", "Monica Seles", "Magic Johnson", "Joe DiMaggio", "Roger Bannister", "Mo Farah", "Mark Spitz", "Chris Evert", "Al Oerter", "Jimmy Connors", "Michael Johnson", "Ian Botham", "Jim Thorpe", "Sir Steve Redgrave", "Steffi Graf", "Sebastian Coe", "Hicham El Guerrouj", "Eric Liddell", "W.G Grace", "Kenenisa Bekele", "Bernard Hinault", "Bob Beamon", "Paavo Nurmi", "David Campese", "Kelly Slater", "Haile Gebreselassie", "Rafael Nadal", "Brian Lara", "Chris Hoy", "Serge Blanco", "Cristiano Ronaldo", "Sir Gary Sobers", "Andy Murray", "George Best", "Sir Viv Richards", "Fausto Coppi", "Eusebio", "Rod Laver", "Grete Waitz", "Margaret Smith Court", "Tegla Laroupe", "Fanny Blankers-Koen", "Asbel Kiprop", "Lewis Hamilton", "C.B.Fry", "Annika Sörenstam", "Wilma Rudolph", "Alberta Tomba", "Bo Jackson"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go b/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go index 3aca817d6..96761aad2 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/colors.go @@ -3,5 +3,108 @@ package data // Colors consists of color information var Colors = map[string][]string{ "safe": {"black", "maroon", "green", "navy", "olive", "purple", "teal", "lime", "blue", "silver", "gray", "yellow", "fuchsia", "aqua", "white"}, - "full": {"AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenRod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "Darkorange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "GoldenRod", "Gray", "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed ", "Indigo ", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenRodYellow", "LightGray", "LightGreen", "LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquaMarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenRod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen"}, + "full": {"AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenRod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "Darkorange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "GoldenRod", "Gray", "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed", "Indigo", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenRodYellow", "LightGray", "LightGreen", "LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquaMarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenRod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen"}, +} + +var ColorsNice = [][]string{ + {"#69d2e7", "#a7dbd8", "#e0e4cc", "#f38630", "#fa6900"}, + {"#fe4365", "#fc9d9a", "#f9cdad", "#c8c8a9", "#83af9b"}, + {"#ecd078", "#d95b43", "#c02942", "#542437", "#53777a"}, + {"#556270", "#4ecdc4", "#c7f464", "#ff6b6b", "#c44d58"}, + {"#774f38", "#e08e79", "#f1d4af", "#ece5ce", "#c5e0dc"}, + {"#e8ddcb", "#cdb380", "#036564", "#033649", "#031634"}, + {"#490a3d", "#bd1550", "#e97f02", "#f8ca00", "#8a9b0f"}, + {"#594f4f", "#547980", "#45ada8", "#9de0ad", "#e5fcc2"}, + {"#00a0b0", "#6a4a3c", "#cc333f", "#eb6841", "#edc951"}, + {"#e94e77", "#d68189", "#c6a49a", "#c6e5d9", "#f4ead5"}, + {"#3fb8af", "#7fc7af", "#dad8a7", "#ff9e9d", "#ff3d7f"}, + {"#d9ceb2", "#948c75", "#d5ded9", "#7a6a53", "#99b2b7"}, + {"#ffffff", "#cbe86b", "#f2e9e1", "#1c140d", "#cbe86b"}, + {"#efffcd", "#dce9be", "#555152", "#2e2633", "#99173c"}, + {"#343838", "#005f6b", "#008c9e", "#00b4cc", "#00dffc"}, + {"#413e4a", "#73626e", "#b38184", "#f0b49e", "#f7e4be"}, + {"#ff4e50", "#fc913a", "#f9d423", "#ede574", "#e1f5c4"}, + {"#99b898", "#fecea8", "#ff847c", "#e84a5f", "#2a363b"}, + {"#655643", "#80bca3", "#f6f7bd", "#e6ac27", "#bf4d28"}, + {"#00a8c6", "#40c0cb", "#f9f2e7", "#aee239", "#8fbe00"}, + {"#351330", "#424254", "#64908a", "#e8caa4", "#cc2a41"}, + {"#554236", "#f77825", "#d3ce3d", "#f1efa5", "#60b99a"}, + {"#5d4157", "#838689", "#a8caba", "#cad7b2", "#ebe3aa"}, + {"#8c2318", "#5e8c6a", "#88a65e", "#bfb35a", "#f2c45a"}, + {"#fad089", "#ff9c5b", "#f5634a", "#ed303c", "#3b8183"}, + {"#ff4242", "#f4fad2", "#d4ee5e", "#e1edb9", "#f0f2eb"}, + {"#f8b195", "#f67280", "#c06c84", "#6c5b7b", "#355c7d"}, + {"#d1e751", "#ffffff", "#000000", "#4dbce9", "#26ade4"}, + {"#1b676b", "#519548", "#88c425", "#bef202", "#eafde6"}, + {"#5e412f", "#fcebb6", "#78c0a8", "#f07818", "#f0a830"}, + {"#bcbdac", "#cfbe27", "#f27435", "#f02475", "#3b2d38"}, + {"#452632", "#91204d", "#e4844a", "#e8bf56", "#e2f7ce"}, + {"#eee6ab", "#c5bc8e", "#696758", "#45484b", "#36393b"}, + {"#f0d8a8", "#3d1c00", "#86b8b1", "#f2d694", "#fa2a00"}, + {"#2a044a", "#0b2e59", "#0d6759", "#7ab317", "#a0c55f"}, + {"#f04155", "#ff823a", "#f2f26f", "#fff7bd", "#95cfb7"}, + {"#b9d7d9", "#668284", "#2a2829", "#493736", "#7b3b3b"}, + {"#bbbb88", "#ccc68d", "#eedd99", "#eec290", "#eeaa88"}, + {"#b3cc57", "#ecf081", "#ffbe40", "#ef746f", "#ab3e5b"}, + {"#a3a948", "#edb92e", "#f85931", "#ce1836", "#009989"}, + {"#300030", "#480048", "#601848", "#c04848", "#f07241"}, + {"#67917a", "#170409", "#b8af03", "#ccbf82", "#e33258"}, + {"#aab3ab", "#c4cbb7", "#ebefc9", "#eee0b7", "#e8caaf"}, + {"#e8d5b7", "#0e2430", "#fc3a51", "#f5b349", "#e8d5b9"}, + {"#ab526b", "#bca297", "#c5ceae", "#f0e2a4", "#f4ebc3"}, + {"#607848", "#789048", "#c0d860", "#f0f0d8", "#604848"}, + {"#b6d8c0", "#c8d9bf", "#dadabd", "#ecdbbc", "#fedcba"}, + {"#a8e6ce", "#dcedc2", "#ffd3b5", "#ffaaa6", "#ff8c94"}, + {"#3e4147", "#fffedf", "#dfba69", "#5a2e2e", "#2a2c31"}, + {"#fc354c", "#29221f", "#13747d", "#0abfbc", "#fcf7c5"}, + {"#cc0c39", "#e6781e", "#c8cf02", "#f8fcc1", "#1693a7"}, + {"#1c2130", "#028f76", "#b3e099", "#ffeaad", "#d14334"}, + {"#a7c5bd", "#e5ddcb", "#eb7b59", "#cf4647", "#524656"}, + {"#dad6ca", "#1bb0ce", "#4f8699", "#6a5e72", "#563444"}, + {"#5c323e", "#a82743", "#e15e32", "#c0d23e", "#e5f04c"}, + {"#edebe6", "#d6e1c7", "#94c7b6", "#403b33", "#d3643b"}, + {"#fdf1cc", "#c6d6b8", "#987f69", "#e3ad40", "#fcd036"}, + {"#230f2b", "#f21d41", "#ebebbc", "#bce3c5", "#82b3ae"}, + {"#b9d3b0", "#81bda4", "#b28774", "#f88f79", "#f6aa93"}, + {"#3a111c", "#574951", "#83988e", "#bcdea5", "#e6f9bc"}, + {"#5e3929", "#cd8c52", "#b7d1a3", "#dee8be", "#fcf7d3"}, + {"#1c0113", "#6b0103", "#a30006", "#c21a01", "#f03c02"}, + {"#000000", "#9f111b", "#b11623", "#292c37", "#cccccc"}, + {"#382f32", "#ffeaf2", "#fcd9e5", "#fbc5d8", "#f1396d"}, + {"#e3dfba", "#c8d6bf", "#93ccc6", "#6cbdb5", "#1a1f1e"}, + {"#f6f6f6", "#e8e8e8", "#333333", "#990100", "#b90504"}, + {"#1b325f", "#9cc4e4", "#e9f2f9", "#3a89c9", "#f26c4f"}, + {"#a1dbb2", "#fee5ad", "#faca66", "#f7a541", "#f45d4c"}, + {"#c1b398", "#605951", "#fbeec2", "#61a6ab", "#accec0"}, + {"#5e9fa3", "#dcd1b4", "#fab87f", "#f87e7b", "#b05574"}, + {"#951f2b", "#f5f4d7", "#e0dfb1", "#a5a36c", "#535233"}, + {"#8dccad", "#988864", "#fea6a2", "#f9d6ac", "#ffe9af"}, + {"#2d2d29", "#215a6d", "#3ca2a2", "#92c7a3", "#dfece6"}, + {"#413d3d", "#040004", "#c8ff00", "#fa023c", "#4b000f"}, + {"#eff3cd", "#b2d5ba", "#61ada0", "#248f8d", "#605063"}, + {"#ffefd3", "#fffee4", "#d0ecea", "#9fd6d2", "#8b7a5e"}, + {"#cfffdd", "#b4dec1", "#5c5863", "#a85163", "#ff1f4c"}, + {"#9dc9ac", "#fffec7", "#f56218", "#ff9d2e", "#919167"}, + {"#4e395d", "#827085", "#8ebe94", "#ccfc8e", "#dc5b3e"}, + {"#a8a7a7", "#cc527a", "#e8175d", "#474747", "#363636"}, + {"#f8edd1", "#d88a8a", "#474843", "#9d9d93", "#c5cfc6"}, + {"#046d8b", "#309292", "#2fb8ac", "#93a42a", "#ecbe13"}, + {"#f38a8a", "#55443d", "#a0cab5", "#cde9ca", "#f1edd0"}, + {"#a70267", "#f10c49", "#fb6b41", "#f6d86b", "#339194"}, + {"#ff003c", "#ff8a00", "#fabe28", "#88c100", "#00c176"}, + {"#ffedbf", "#f7803c", "#f54828", "#2e0d23", "#f8e4c1"}, + {"#4e4d4a", "#353432", "#94ba65", "#2790b0", "#2b4e72"}, + {"#0ca5b0", "#4e3f30", "#fefeeb", "#f8f4e4", "#a5b3aa"}, + {"#4d3b3b", "#de6262", "#ffb88c", "#ffd0b3", "#f5e0d3"}, + {"#fffbb7", "#a6f6af", "#66b6ab", "#5b7c8d", "#4f2958"}, + {"#edf6ee", "#d1c089", "#b3204d", "#412e28", "#151101"}, + {"#9d7e79", "#ccac95", "#9a947c", "#748b83", "#5b756c"}, + {"#fcfef5", "#e9ffe1", "#cdcfb7", "#d6e6c3", "#fafbe3"}, + {"#9cddc8", "#bfd8ad", "#ddd9ab", "#f7af63", "#633d2e"}, + {"#30261c", "#403831", "#36544f", "#1f5f61", "#0b8185"}, + {"#aaff00", "#ffaa00", "#ff00aa", "#aa00ff", "#00aaff"}, + {"#d1313d", "#e5625c", "#f9bf76", "#8eb2c5", "#615375"}, + {"#ffe181", "#eee9e5", "#fad3b2", "#ffba7f", "#ff9c97"}, + {"#73c8a9", "#dee1b6", "#e1b866", "#bd5532", "#373b44"}, + {"#805841", "#dcf7f3", "#fffcdd", "#ffd8d8", "#f5a2a2"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/company.go b/vendor/github.com/brianvoe/gofakeit/v6/data/company.go index 858a1a464..43b6a2dc9 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/company.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/company.go @@ -6,4 +6,5 @@ var Company = map[string][]string{ "suffix": {"Inc", "and Sons", "LLC", "Group"}, "buzzwords": {"Adaptive", "Advanced", "Ameliorated", "Assimilated", "Automated", "Balanced", "Business-focused", "Centralized", "Cloned", "Compatible", "Configurable", "Cross-group", "Cross-platform", "Customer-focused", "Customizable", "De-engineered", "Decentralized", "Devolved", "Digitized", "Distributed", "Diverse", "Down-sized", "Enhanced", "Enterprise-wide", "Ergonomic", "Exclusive", "Expanded", "Extended", "Face to face", "Focused", "Front-line", "Fully-configurable", "Function-based", "Fundamental", "Future-proofed", "Grass-roots", "Horizontal", "Implemented", "Innovative", "Integrated", "Intuitive", "Inverse", "Managed", "Mandatory", "Monitored", "Multi-channelled", "Multi-lateral", "Multi-layered", "Multi-tiered", "Networked", "Object-based", "Open-architected", "Open-source", "Operative", "Optimized", "Optional", "Organic", "Organized", "Persevering", "Persistent", "Phased", "Polarised", "Pre-emptive", "Proactive", "Profit-focused", "Profound", "Programmable", "Progressive", "Public-key", "Quality-focused", "Re-contextualized", "Re-engineered", "Reactive", "Realigned", "Reduced", "Reverse-engineered", "Right-sized", "Robust", "Seamless", "Secured", "Self-enabling", "Sharable", "Stand-alone", "Streamlined", "Switchable", "Synchronised", "Synergistic", "Synergized", "Team-oriented", "Total", "Triple-buffered", "Universal", "Up-sized", "Upgradable", "User-centric", "User-friendly", "Versatile", "Virtual", "Vision-oriented", "Visionary", "24 hour", "24/7", "3rd generation", "4th generation", "5th generation", "6th generation", "actuating", "analyzing", "asymmetric", "asynchronous", "attitude-oriented", "background", "bandwidth-monitored", "bi-directional", "bifurcated", "bottom-line", "clear-thinking", "client-driven", "client-server", "coherent", "cohesive", "composite", "content-based", "context-sensitive", "contextually-based", "dedicated", "demand-driven", "didactic", "directional", "discrete", "disintermediate", "dynamic", "eco-centric", "empowering", "encompassing", "even-keeled", "executive", "explicit", "exuding", "fault-tolerant", "foreground", "fresh-thinking", "full-range", "global", "grid-enabled", "heuristic", "high-level", "holistic", "homogeneous", "human-resource", "hybrid", "impactful", "incremental", "intangible", "interactive", "intermediate", "leading edge", "local", "logistical", "maximized", "methodical", "mission-critical", "mobile", "modular", "motivating", "multi-state", "multi-tasking", "multimedia", "national", "needs-based", "neutral", "next generation", "non-volatile", "object-oriented", "optimal", "optimizing", "radical", "real-time", "reciprocal", "regional", "responsive", "scalable", "secondary", "solution-oriented", "stable", "static", "system-worthy", "systematic", "systemic", "tangible", "tertiary", "transitional", "uniform", "upward-trending", "user-facing", "value-added", "web-enabled", "well-modulated", "zero administration", "zero defect", "zero tolerance", "Graphic Interface", "Graphical User Interface", "ability", "access", "adapter", "algorithm", "alliance", "analyzer", "application", "approach", "architecture", "archive", "array", "artificial intelligence", "attitude", "benchmark", "budgetary management", "capability", "capacity", "challenge", "circuit", "collaboration", "complexity", "concept", "conglomeration", "contingency", "core", "customer loyalty", "data-warehouse", "database", "definition", "emulation", "encoding", "encryption", "extranet", "firmware", "flexibility", "focus group", "forecast", "frame", "framework", "function", "functionalities", "groupware", "hardware", "help-desk", "hierarchy", "hub", "implementation", "info-mediaries", "infrastructure", "initiative", "installation", "instruction set", "interface", "internet solution", "intranet", "knowledge base", "knowledge user", "leverage", "local area network", "matrices", "matrix", "methodology", "middleware", "migration", "model", "moderator", "monitoring", "moratorium", "neural-net", "open architecture", "open system", "orchestration", "paradigm", "parallelism", "policy", "portal", "pricing structure", "process improvement", "product", "productivity", "project", "projection", "protocol", "secured line", "service-desk", "software", "solution", "standardization", "strategy", "structure", "success", "superstructure", "support", "synergy", "system engine", "task-force", "throughput", "time-frame", "toolset", "utilisation", "website", "workforce"}, "bs": {"aggregate", "architect", "benchmark", "brand", "cultivate", "deliver", "deploy", "disintermediate", "drive", "e-enable", "embrace", "empower", "enable", "engage", "engineer", "enhance", "envisioneer", "evolve", "expedite", "exploit", "extend", "facilitate", "generate", "grow", "harness", "implement", "incentivize", "incubate", "innovate", "integrate", "iterate", "leverage", "matrix", "maximize", "mesh", "monetize", "morph", "optimize", "orchestrate", "productize", "recontextualize", "redefine", "reintermediate", "reinvent", "repurpose", "revolutionize", "scale", "seize", "strategize", "streamline", "syndicate", "synergize", "synthesize", "target", "transform", "transition", "unleash", "utilize", "visualize", "whiteboard", "24-365", "24-7", "B2B", "B2C", "back-end", "best-of-breed", "bleeding-edge", "bricks-and-clicks", "clicks-and-mortar", "collaborative", "compelling", "cross-media", "cross-platform", "customized", "cutting-edge", "distributed", "dot-com", "dynamic", "e-business", "efficient", "end-to-end", "enterprise", "extensible", "frictionless", "front-end", "global", "granular", "holistic", "impactful", "innovative", "integrated", "interactive", "intuitive", "killer", "leading-edge", "magnetic", "mission-critical", "next-generation", "one-to-one", "open-source", "out-of-the-box", "plug-and-play", "proactive", "real-time", "revolutionary", "rich", "robust", "scalable", "seamless", "sexy", "sticky", "strategic", "synergistic", "transparent", "turn-key", "ubiquitous", "user-centric", "value-added", "vertical", "viral", "virtual", "visionary", "web-enabled", "wireless", "world-class", "ROI", "action-items", "applications", "architectures", "bandwidth", "channels", "communities", "content", "convergence", "deliverables", "e-business", "e-commerce", "e-markets", "e-services", "e-tailers", "experiences", "eyeballs", "functionalities", "infomediaries", "infrastructures", "initiatives", "interfaces", "markets", "methodologies", "metrics", "mindshare", "models", "networks", "niches", "paradigms", "partnerships", "platforms", "portals", "relationships", "schemas", "solutions", "supply-chains", "synergies", "systems", "technologies", "users", "vortals", "web services", "web-readiness"}, + "blurb": {"Advancement", "Advantage", "Ambition", "Balance", "Belief", "Benefits", "Care", "Challenge", "Change", "Choice", "Commitment", "Comfort", "Connection", "Consistency", "Creativity", "Dedication", "Discovery", "Diversity", "Dream", "Dreams", "Drive", "Ease", "Efficiency", "Empowerment", "Endurance", "Energy", "Engagement", "Environment", "Enterprise", "Excellence", "Exclusivity", "Experience", "Exploration", "Expression", "Family", "Flexibility", "Focus", "Freedom", "Future", "Future", "Growth", "Harmony", "Health", "Heart", "History", "Home", "Honesty", "Hope", "Impact", "Innovation", "Inspiration", "Integrity", "Joy", "Journey", "Knowledge", "Leadership", "Legacy", "Life", "Luxury", "Money", "Motivation", "Optimism", "Partnership", "Passion", "Peace", "People", "Performance", "Perseverance", "Pleasure", "Power", "Pride", "Progress", "Promise", "Quality", "Quality", "Reliability", "Resilience", "Respect", "Revolution", "Safety", "Service", "Simplicity", "Solutions", "Solidarity", "Strength", "Style", "Success", "Sustainability", "Taste", "Teamwork", "Technology", "Time", "Transformation", "Trust", "Unity", "Value", "Versatility", "Vision", "Wellness", "World"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/data.go b/vendor/github.com/brianvoe/gofakeit/v6/data/data.go index 6e1701bea..51a4f496b 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/data.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/data.go @@ -26,6 +26,12 @@ var Data = map[string]map[string][]string{ "food": Food, "minecraft": Minecraft, "celebrity": Celebrity, + "error": Error, + "html": Html, + "book": Books, + "movie": Movies, + "school": School, + "product": Product, } func List() map[string][]string { diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/errors.go b/vendor/github.com/brianvoe/gofakeit/v6/data/errors.go new file mode 100644 index 000000000..75647cf81 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/errors.go @@ -0,0 +1,122 @@ +package data + +var Error = map[string][]string{ + "object": { + "argument", + "buffer", + "connection", + "database", + "header", + "hostname", + "method", + "object", + "parameter", + "pointer", + "port", + "protocol", + "request", + "response", + "server", + "service", + "signature", + "tag", + "undefined", + "url", + "uri", + "variable", + }, + "generic": { + "error", + "syntax error", + "requested {errorobject} is unavailable", + "failed to {hackerverb} {errorobject}", + "expected {errorobject} is undefined", + "[object Object]", + "no such variable", + "{errorobject} not initialized", + "variable assigned before declaration", + }, + "database": { + "sql error", + "database connection error", + "table does not exist", + "unique key constraint", + "table migration failed", + "bad connection", + "destination pointer is nil", + }, + "grpc": { + "connection refused", + "connection closed", + "connection is shut down", + "client protocol error", + }, + "http": { + "cross-origin-resource-policy error", + "feature not supported", + "trailer header without chunked transfer encoding", + "no multipart boundary param in Content-Type", + "request Content-Type isn't multipart/form-data", + "header too long", + "entity body too short", + "missing ContentLength in HEAD response", + "named cookie not present", + "invalid method", + "connection has been hijacked", + "request method or response status code does not allow body", + "wrote more than the declared Content-Length", + "{httpmethod} not allowed", + }, + "http_client": { // 400s + "bad request", // 400 + "unauthorized", // 401 + "payment required", // 402 + "forbidden", // 403 + "not found", // 404 + "method not allowed", // 405 + "not acceptable", // 406 + "proxy authentication required", // 407 + "request timeout", // 408 + "conflict", // 409 + "gone", // 410 + "length required", // 411 + "precondition failed", // 412 + "payload too large", // 413 + "URI too long", // 414 + "unsupported media type", // 415 + "range not satisfiable", // 416 + "expectation failed", // 417 + "im a teapot", // 418 + }, + "http_server": { // 500s + "internal server error", // 500 + "not implemented", // 501 + "bad gateway", // 502 + "service unavailable", // 503 + "gateway timeout", // 504 + "http version not supported", // 505 + "variant also negotiates", // 506 + "insufficient storage", // 507 + "loop detected", // 508 + "not extended", // 510 + "network authentication required", // 511 + }, + "runtime": { + "panic: runtime error: invalid memory address or nil pointer dereference", + "address out of bounds", + "undefined has no such property 'length'", + "not enough arguments", + "expected 2 arguments, got 3", + }, + "validation": { + "invalid format", + "missing required field", + "{inputname} is required", + "{inputname} max length exceeded", + "{inputname} must be at exactly 16 characters", + "{inputname} must be at exactly 32 bytes", + "failed to parse {inputname}", + "date is in the past", + "payment details cannot be verified", + }, +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go b/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go index a29e438f8..08a5f86ad 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/hacker.go @@ -5,7 +5,7 @@ var Hacker = map[string][]string{ "abbreviation": {"TCP", "HTTP", "SDD", "RAM", "GB", "CSS", "SSL", "AGP", "SQL", "FTP", "PCI", "AI", "ADP", "RSS", "XML", "EXE", "COM", "HDD", "THX", "SMTP", "SMS", "USB", "PNG", "SAS", "IB", "SCSI", "JSON", "XSS", "JBOD"}, "adjective": {"auxiliary", "primary", "back-end", "digital", "open-source", "virtual", "cross-platform", "redundant", "online", "haptic", "multi-byte", "bluetooth", "wireless", "1080p", "neural", "optical", "solid state", "mobile"}, "noun": {"driver", "protocol", "bandwidth", "panel", "microchip", "program", "port", "card", "array", "interface", "system", "sensor", "firewall", "hard drive", "pixel", "alarm", "feed", "monitor", "application", "transmitter", "bus", "circuit", "capacitor", "matrix"}, - "verb": {"back up", "bypass", "hack", "override", "compress", "copy", "navigate", "index", "connect", "generate", "quantify", "calculate", "synthesize", "input", "transmit", "program", "reboot", "parse"}, + "verb": {"back up", "bypass", "hack", "override", "compress", "copy", "navigate", "index", "connect", "generate", "quantify", "calculate", "synthesize", "input", "transmit", "program", "reboot", "parse", "read", "write", "load", "render", "validate", "verify", "sign", "decrypt", "encrypt", "construct", "deconstruct", "compile", "transpile", "bundle", "lock", "unlock", "buffer", "format"}, "ingverb": {"backing up", "bypassing", "hacking", "overriding", "compressing", "copying", "navigating", "indexing", "connecting", "generating", "quantifying", "calculating", "synthesizing", "transmitting", "programming", "parsing"}, "phrase": { "If we {hackerverb} the {hackernoun}, we can get to the {hackerabbreviation} {hackernoun} through the {hackeradjective} {hackerabbreviation} {hackernoun}!", diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/html.go b/vendor/github.com/brianvoe/gofakeit/v6/data/html.go new file mode 100644 index 000000000..5787edd8a --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/html.go @@ -0,0 +1,7 @@ +package data + +// Html consists of various html information +var Html = map[string][]string{ + "svg": {"rect", "circle", "ellipse", "line", "polyline", "polygon"}, + "input_name": {"title", "first_name", "last_name", "suffix", "address", "postal_code", "city", "state", "country", "date_of_birth", "card_number", "description", "message", "status"}, +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/movie.go b/vendor/github.com/brianvoe/gofakeit/v6/data/movie.go new file mode 100644 index 000000000..9a381ac11 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/movie.go @@ -0,0 +1,130 @@ +package data + +// From IMDB - Top 250 Movies subset to 100 +var Movies = map[string][]string{ + "name": { + "12 Years a Slave", + "1917", + "2001: A Space Odyssey", + "3 Idiots", + "A Beautiful Mind", + "A Clockwork Orange", + "Alien", + "American Beauty", + "American History X", + "Apocalypse Now", + "Avengers: Infinity War", + "Back to the Future", + "Batman Begins", + "Ben-Hur", + "Blade Runner", + "Casablanca", + "Casino", + "Catch Me If You Can", + "Das Leben der Anderen", + "Dead Poets Society", + "Die Hard", + "Django Unchained", + "Fight Club", + "Finding Nemo", + "Forrest Gump", + "Full Metal Jacket", + "Gandhi", + "Gladiator", + "Gone with the Wind", + "Good Will Hunting", + "Goodfellas", + "Green Book", + "Groundhog Day", + "Harry Potter and the Deathly Hallows - Part 2", + "Heat", + "Inception", + "Indiana Jones and the Last Crusade", + "Inglourious Basterds", + "Interstellar", + "Into the Wild", + "Intouchables", + "Joker", + "Judgment at Nuremberg", + "Jurassic Park", + "Kill Bill: Vol. 1", + "L.A. Confidential", + "La vita è bella", + "Lock, Stock and Two Smoking Barrels", + "Léon", + "Mad Max: Fury Road", + "Memento", + "Million Dollar Baby", + "Monsters, Inc.", + "Monty Python and the Holy Grail", + "No Country for Old Men", + "Once Upon a Time in America", + "One Flew Over the Cuckoo's Nest", + "Pirates of the Caribbean: The Curse of the Black Pearl", + "Platoon", + "Prisoners", + "Psycho", + "Pulp Fiction", + "Raiders of the Lost Ark", + "Ratatouille", + "Reservoir Dogs", + "Rocky", + "Saving Private Ryan", + "Scarface", + "Schindler's List", + "Se7en", + "Sherlock Jr.", + "Shutter Island", + "Snatch", + "Spider-Man: No Way Home", + "Star Wars: Episode VI - Return of the Jedi", + "Taxi Driver", + "Terminator 2: Judgment Day", + "The Big Lebowski", + "The Dark Knight", + "The Departed", + "The Empire Strikes Back", + "The Godfather", + "The Green Mile", + "The Lion King", + "The Lord of the Rings: The Fellowship of the Ring", + "The Matrix", + "The Pianist", + "The Prestige", + "The Shawshank Redemption", + "The Terminator", + "The Usual Suspects", + "The Wolf of Wall Street", + "Top Gun: Maverick", + "Toy Story", + "Unforgiven", + "Up", + "V for Vendetta", + "WALL·E", + "Warrior", + "Whiplash", + }, + "genre": { + "Action", + "Adventure", + "Animation", + "Biography", + "Comedy", + "Crime", + "Drama", + "Family", + "Fantasy", + "Film-Noir", + "History", + "Horror", + "Music", + "Musical", + "Mystery", + "Romance", + "Sci-Fi", + "Sport", + "Thriller", + "War", + "Western", + }, +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/person.go b/vendor/github.com/brianvoe/gofakeit/v6/data/person.go index 0930c65e4..8f65a16bf 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/person.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/person.go @@ -5,6 +5,7 @@ var Person = map[string][]string{ "prefix": {"Mr.", "Mrs.", "Ms.", "Miss", "Dr."}, "suffix": {"Jr.", "Sr.", "I", "II", "III", "IV", "V", "MD", "DDS", "PhD", "DVM"}, "first": {"Aaliyah", "Aaron", "Abagail", "Abbey", "Abbie", "Abbigail", "Abby", "Abdiel", "Abdul", "Abdullah", "Abe", "Abel", "Abelardo", "Abigail", "Abigale", "Abigayle", "Abner", "Abraham", "Ada", "Adah", "Adalberto", "Adaline", "Adam", "Adan", "Addie", "Addison", "Adela", "Adelbert", "Adele", "Adelia", "Adeline", "Adell", "Adella", "Adelle", "Aditya", "Adolf", "Adolfo", "Adolph", "Adolphus", "Adonis", "Adrain", "Adrian", "Adriana", "Adrianna", "Adriel", "Adrien", "Adrienne", "Afton", "Aglae", "Agnes", "Agustin", "Agustina", "Ahmad", "Ahmed", "Aida", "Aidan", "Aiden", "Aileen", "Aimee", "Aisha", "Aiyana", "Akeem", "Al", "Alaina", "Alan", "Alana", "Alanis", "Alanna", "Alayna", "Alba", "Albert", "Alberta", "Albertha", "Alberto", "Albin", "Albina", "Alda", "Alden", "Alec", "Aleen", "Alejandra", "Alejandrin", "Alek", "Alena", "Alene", "Alessandra", "Alessandro", "Alessia", "Aletha", "Alex", "Alexa", "Alexander", "Alexandra", "Alexandre", "Alexandrea", "Alexandria", "Alexandrine", "Alexandro", "Alexane", "Alexanne", "Alexie", "Alexis", "Alexys", "Alexzander", "Alf", "Alfonso", "Alfonzo", "Alford", "Alfred", "Alfreda", "Alfredo", "Ali", "Alia", "Alice", "Alicia", "Alisa", "Alisha", "Alison", "Alivia", "Aliya", "Aliyah", "Aliza", "Alize", "Allan", "Allen", "Allene", "Allie", "Allison", "Ally", "Alphonso", "Alta", "Althea", "Alva", "Alvah", "Alvena", "Alvera", "Alverta", "Alvina", "Alvis", "Alyce", "Alycia", "Alysa", "Alysha", "Alyson", "Alysson", "Amalia", "Amanda", "Amani", "Amara", "Amari", "Amaya", "Amber", "Ambrose", "Amelia", "Amelie", "Amely", "America", "Americo", "Amie", "Amina", "Amir", "Amira", "Amiya", "Amos", "Amparo", "Amy", "Amya", "Ana", "Anabel", "Anabelle", "Anahi", "Anais", "Anastacio", "Anastasia", "Anderson", "Andre", "Andreane", "Andreanne", "Andres", "Andrew", "Andy", "Angel", "Angela", "Angelica", "Angelina", "Angeline", "Angelita", "Angelo", "Angie", "Angus", "Anibal", "Anika", "Anissa", "Anita", "Aniya", "Aniyah", "Anjali", "Anna", "Annabel", "Annabell", "Annabelle", "Annalise", "Annamae", "Annamarie", "Anne", "Annetta", "Annette", "Annie", "Ansel", "Ansley", "Anthony", "Antoinette", "Antone", "Antonetta", "Antonette", "Antonia", "Antonietta", "Antonina", "Antonio", "Antwan", "Antwon", "Anya", "April", "Ara", "Araceli", "Aracely", "Arch", "Archibald", "Ardella", "Arden", "Ardith", "Arely", "Ari", "Ariane", "Arianna", "Aric", "Ariel", "Arielle", "Arjun", "Arlene", "Arlie", "Arlo", "Armand", "Armando", "Armani", "Arnaldo", "Arne", "Arno", "Arnold", "Arnoldo", "Arnulfo", "Aron", "Art", "Arthur", "Arturo", "Arvel", "Arvid", "Arvilla", "Aryanna", "Asa", "Asha", "Ashlee", "Ashleigh", "Ashley", "Ashly", "Ashlynn", "Ashton", "Ashtyn", "Asia", "Assunta", "Astrid", "Athena", "Aubree", "Aubrey", "Audie", "Audra", "Audreanne", "Audrey", "August", "Augusta", "Augustine", "Augustus", "Aurelia", "Aurelie", "Aurelio", "Aurore", "Austen", "Austin", "Austyn", "Autumn", "Ava", "Avery", "Avis", "Axel", "Ayana", "Ayden", "Ayla", "Aylin", "Baby", "Bailee", "Bailey", "Barbara", "Barney", "Baron", "Barrett", "Barry", "Bart", "Bartholome", "Barton", "Baylee", "Beatrice", "Beau", "Beaulah", "Bell", "Bella", "Belle", "Ben", "Benedict", "Benjamin", "Bennett", "Bennie", "Benny", "Benton", "Berenice", "Bernadette", "Bernadine", "Bernard", "Bernardo", "Berneice", "Bernhard", "Bernice", "Bernie", "Berniece", "Bernita", "Berry", "Bert", "Berta", "Bertha", "Bertram", "Bertrand", "Beryl", "Bessie", "Beth", "Bethany", "Bethel", "Betsy", "Bette", "Bettie", "Betty", "Bettye", "Beulah", "Beverly", "Bianka", "Bill", "Billie", "Billy", "Birdie", "Blair", "Blaise", "Blake", "Blanca", "Blanche", "Blaze", "Bo", "Bobbie", "Bobby", "Bonita", "Bonnie", "Boris", "Boyd", "Brad", "Braden", "Bradford", "Bradley", "Bradly", "Brady", "Braeden", "Brain", "Brandi", "Brando", "Brandon", "Brandt", "Brandy", "Brandyn", "Brannon", "Branson", "Brant", "Braulio", "Braxton", "Brayan", "Breana", "Breanna", "Breanne", "Brenda", "Brendan", "Brenden", "Brendon", "Brenna", "Brennan", "Brennon", "Brent", "Bret", "Brett", "Bria", "Brian", "Briana", "Brianne", "Brice", "Bridget", "Bridgette", "Bridie", "Brielle", "Brigitte", "Brionna", "Brisa", "Britney", "Brittany", "Brock", "Broderick", "Brody", "Brook", "Brooke", "Brooklyn", "Brooks", "Brown", "Bruce", "Bryana", "Bryce", "Brycen", "Bryon", "Buck", "Bud", "Buddy", "Buford", "Bulah", "Burdette", "Burley", "Burnice", "Buster", "Cade", "Caden", "Caesar", "Caitlyn", "Cale", "Caleb", "Caleigh", "Cali", "Calista", "Callie", "Camden", "Cameron", "Camila", "Camilla", "Camille", "Camren", "Camron", "Camryn", "Camylle", "Candace", "Candelario", "Candice", "Candida", "Candido", "Cara", "Carey", "Carissa", "Carlee", "Carleton", "Carley", "Carli", "Carlie", "Carlo", "Carlos", "Carlotta", "Carmel", "Carmela", "Carmella", "Carmelo", "Carmen", "Carmine", "Carol", "Carolanne", "Carole", "Carolina", "Caroline", "Carolyn", "Carolyne", "Carrie", "Carroll", "Carson", "Carter", "Cary", "Casandra", "Casey", "Casimer", "Casimir", "Casper", "Cassandra", "Cassandre", "Cassidy", "Cassie", "Catalina", "Caterina", "Catharine", "Catherine", "Cathrine", "Cathryn", "Cathy", "Cayla", "Ceasar", "Cecelia", "Cecil", "Cecile", "Cecilia", "Cedrick", "Celestine", "Celestino", "Celia", "Celine", "Cesar", "Chad", "Chadd", "Chadrick", "Chaim", "Chance", "Chandler", "Chanel", "Chanelle", "Charity", "Charlene", "Charles", "Charley", "Charlie", "Charlotte", "Chase", "Chasity", "Chauncey", "Chaya", "Chaz", "Chelsea", "Chelsey", "Chelsie", "Chesley", "Chester", "Chet", "Cheyanne", "Cheyenne", "Chloe", "Chris", "Christ", "Christa", "Christelle", "Christian", "Christiana", "Christina", "Christine", "Christop", "Christophe", "Christopher", "Christy", "Chyna", "Ciara", "Cicero", "Cielo", "Cierra", "Cindy", "Citlalli", "Clair", "Claire", "Clara", "Clarabelle", "Clare", "Clarissa", "Clark", "Claud", "Claude", "Claudia", "Claudie", "Claudine", "Clay", "Clemens", "Clement", "Clementina", "Clementine", "Clemmie", "Cleo", "Cleora", "Cleta", "Cletus", "Cleve", "Cleveland", "Clifford", "Clifton", "Clint", "Clinton", "Clotilde", "Clovis", "Cloyd", "Clyde", "Coby", "Cody", "Colby", "Cole", "Coleman", "Colin", "Colleen", "Collin", "Colt", "Colten", "Colton", "Columbus", "Concepcion", "Conner", "Connie", "Connor", "Conor", "Conrad", "Constance", "Constantin", "Consuelo", "Cooper", "Cora", "Coralie", "Corbin", "Cordelia", "Cordell", "Cordia", "Cordie", "Corene", "Corine", "Cornelius", "Cornell", "Corrine", "Cortez", "Cortney", "Cory", "Coty", "Courtney", "Coy", "Craig", "Crawford", "Creola", "Cristal", "Cristian", "Cristina", "Cristobal", "Cristopher", "Cruz", "Crystal", "Crystel", "Cullen", "Curt", "Curtis", "Cydney", "Cynthia", "Cyril", "Cyrus", "Dagmar", "Dahlia", "Daija", "Daisha", "Daisy", "Dakota", "Dale", "Dallas", "Dallin", "Dalton", "Damaris", "Dameon", "Damian", "Damien", "Damion", "Damon", "Dan", "Dana", "Dandre", "Dane", "Dangelo", "Dangelo", "Danial", "Daniela", "Daniella", "Danielle", "Danika", "Dannie", "Danny", "Dante", "Danyka", "Daphne", "Daphnee", "Daphney", "Darby", "Daren", "Darian", "Dariana", "Darien", "Dario", "Darion", "Darius", "Darlene", "Daron", "Darrel", "Darrell", "Darren", "Darrick", "Darrin", "Darrion", "Darron", "Darryl", "Darwin", "Daryl", "Dashawn", "Dasia", "Dave", "David", "Davin", "Davion", "Davon", "Davonte", "Dawn", "Dawson", "Dax", "Dayana", "Dayna", "Dayne", "Dayton", "Dean", "Deangelo", "Deanna", "Deborah", "Declan", "Dedric", "Dedrick", "Dee", "Deion", "Deja", "Dejah", "Dejon", "Dejuan", "Delaney", "Delbert", "Delfina", "Delia", "Delilah", "Dell", "Della", "Delmer", "Delores", "Delpha", "Delphia", "Delphine", "Delta", "Demarco", "Demarcus", "Demario", "Demetris", "Demetrius", "Demond", "Dena", "Denis", "Dennis", "Deon", "Deondre", "Deontae", "Deonte", "Dereck", "Derek", "Derick", "Deron", "Derrick", "Deshaun", "Deshawn", "Desiree", "Desmond", "Dessie", "Destany", "Destin", "Destinee", "Destiney", "Destini", "Destiny", "Devan", "Devante", "Deven", "Devin", "Devon", "Devonte", "Devyn", "Dewayne", "Dewitt", "Dexter", "Diamond", "Diana", "Dianna", "Diego", "Dillan", "Dillon", "Dimitri", "Dina", "Dino", "Dion", "Dixie", "Dock", "Dolly", "Dolores", "Domenic", "Domenica", "Domenick", "Domenico", "Domingo", "Dominic", "Dominique", "Don", "Donald", "Donato", "Donavon", "Donna", "Donnell", "Donnie", "Donny", "Dora", "Dorcas", "Dorian", "Doris", "Dorothea", "Dorothy", "Dorris", "Dortha", "Dorthy", "Doug", "Douglas", "Dovie", "Doyle", "Drake", "Drew", "Duane", "Dudley", "Dulce", "Duncan", "Durward", "Dustin", "Dusty", "Dwight", "Dylan", "Earl", "Earlene", "Earline", "Earnest", "Earnestine", "Easter", "Easton", "Ebba", "Ebony", "Ed", "Eda", "Edd", "Eddie", "Eden", "Edgar", "Edgardo", "Edison", "Edmond", "Edmund", "Edna", "Eduardo", "Edward", "Edwardo", "Edwin", "Edwina", "Edyth", "Edythe", "Effie", "Efrain", "Efren", "Eileen", "Einar", "Eino", "Eladio", "Elaina", "Elbert", "Elda", "Eldon", "Eldora", "Eldred", "Eldridge", "Eleanora", "Eleanore", "Eleazar", "Electa", "Elena", "Elenor", "Elenora", "Eleonore", "Elfrieda", "Eli", "Elian", "Eliane", "Elias", "Eliezer", "Elijah", "Elinor", "Elinore", "Elisa", "Elisabeth", "Elise", "Eliseo", "Elisha", "Elissa", "Eliza", "Elizabeth", "Ella", "Ellen", "Ellie", "Elliot", "Elliott", "Ellis", "Ellsworth", "Elmer", "Elmira", "Elmo", "Elmore", "Elna", "Elnora", "Elody", "Eloisa", "Eloise", "Elouise", "Eloy", "Elroy", "Elsa", "Else", "Elsie", "Elta", "Elton", "Elva", "Elvera", "Elvie", "Elvis", "Elwin", "Elwyn", "Elyse", "Elyssa", "Elza", "Emanuel", "Emelia", "Emelie", "Emely", "Emerald", "Emerson", "Emery", "Emie", "Emil", "Emile", "Emilia", "Emiliano", "Emilie", "Emilio", "Emily", "Emma", "Emmalee", "Emmanuel", "Emmanuelle", "Emmet", "Emmett", "Emmie", "Emmitt", "Emmy", "Emory", "Ena", "Enid", "Enoch", "Enola", "Enos", "Enrico", "Enrique", "Ephraim", "Era", "Eriberto", "Eric", "Erica", "Erich", "Erick", "Ericka", "Erik", "Erika", "Erin", "Erling", "Erna", "Ernest", "Ernestina", "Ernestine", "Ernesto", "Ernie", "Ervin", "Erwin", "Eryn", "Esmeralda", "Esperanza", "Esta", "Esteban", "Estefania", "Estel", "Estell", "Estella", "Estelle", "Estevan", "Esther", "Estrella", "Etha", "Ethan", "Ethel", "Ethelyn", "Ethyl", "Ettie", "Eudora", "Eugene", "Eugenia", "Eula", "Eulah", "Eulalia", "Euna", "Eunice", "Eusebio", "Eva", "Evalyn", "Evan", "Evangeline", "Evans", "Eve", "Eveline", "Evelyn", "Everardo", "Everett", "Everette", "Evert", "Evie", "Ewald", "Ewell", "Ezekiel", "Ezequiel", "Ezra", "Fabian", "Fabiola", "Fae", "Fannie", "Fanny", "Fatima", "Faustino", "Fausto", "Favian", "Fay", "Faye", "Federico", "Felicia", "Felicita", "Felicity", "Felipa", "Felipe", "Felix", "Felton", "Fermin", "Fern", "Fernando", "Ferne", "Fidel", "Filiberto", "Filomena", "Finn", "Fiona", "Flavie", "Flavio", "Fleta", "Fletcher", "Flo", "Florence", "Florencio", "Florian", "Florida", "Florine", "Flossie", "Floy", "Floyd", "Ford", "Forest", "Forrest", "Foster", "Frances", "Francesca", "Francesco", "Francis", "Francisca", "Francisco", "Franco", "Frank", "Frankie", "Franz", "Fred", "Freda", "Freddie", "Freddy", "Frederic", "Frederick", "Frederik", "Frederique", "Fredrick", "Fredy", "Freeda", "Freeman", "Freida", "Frida", "Frieda", "Friedrich", "Fritz", "Furman", "Gabe", "Gabriel", "Gabriella", "Gabrielle", "Gaetano", "Gage", "Gail", "Gardner", "Garett", "Garfield", "Garland", "Garnet", "Garnett", "Garret", "Garrett", "Garrick", "Garrison", "Garry", "Garth", "Gaston", "Gavin", "Gay", "Gayle", "Gaylord", "Gene", "General", "Genesis", "Genevieve", "Gennaro", "Genoveva", "Geo", "Geoffrey", "George", "Georgette", "Georgiana", "Georgianna", "Geovanni", "Geovanny", "Geovany", "Gerald", "Geraldine", "Gerard", "Gerardo", "Gerda", "Gerhard", "Germaine", "German", "Gerry", "Gerson", "Gertrude", "Gia", "Gianni", "Gideon", "Gilbert", "Gilberto", "Gilda", "Giles", "Gillian", "Gina", "Gino", "Giovani", "Giovanna", "Giovanni", "Giovanny", "Gisselle", "Giuseppe", "Gladyce", "Gladys", "Glen", "Glenda", "Glenna", "Glennie", "Gloria", "Godfrey", "Golda", "Golden", "Gonzalo", "Gordon", "Grace", "Gracie", "Graciela", "Grady", "Graham", "Grant", "Granville", "Grayce", "Grayson", "Green", "Greg", "Gregg", "Gregoria", "Gregorio", "Gregory", "Greta", "Gretchen", "Greyson", "Griffin", "Grover", "Guadalupe", "Gudrun", "Guido", "Guillermo", "Guiseppe", "Gunnar", "Gunner", "Gus", "Gussie", "Gust", "Gustave", "Guy", "Gwen", "Gwendolyn", "Hadley", "Hailee", "Hailey", "Hailie", "Hal", "Haleigh", "Haley", "Halie", "Halle", "Hallie", "Hank", "Hanna", "Hannah", "Hans", "Hardy", "Harley", "Harmon", "Harmony", "Harold", "Harrison", "Harry", "Harvey", "Haskell", "Hassan", "Hassie", "Hattie", "Haven", "Hayden", "Haylee", "Hayley", "Haylie", "Hazel", "Hazle", "Heath", "Heather", "Heaven", "Heber", "Hector", "Heidi", "Helen", "Helena", "Helene", "Helga", "Hellen", "Helmer", "Heloise", "Henderson", "Henri", "Henriette", "Henry", "Herbert", "Herman", "Hermann", "Hermina", "Herminia", "Herminio", "Hershel", "Herta", "Hertha", "Hester", "Hettie", "Hilario", "Hilbert", "Hilda", "Hildegard", "Hillard", "Hillary", "Hilma", "Hilton", "Hipolito", "Hiram", "Hobart", "Holden", "Hollie", "Hollis", "Holly", "Hope", "Horace", "Horacio", "Hortense", "Hosea", "Houston", "Howard", "Howell", "Hoyt", "Hubert", "Hudson", "Hugh", "Hulda", "Humberto", "Hunter", "Hyman", "Ian", "Ibrahim", "Icie", "Ida", "Idell", "Idella", "Ignacio", "Ignatius", "Ike", "Ila", "Ilene", "Iliana", "Ima", "Imani", "Imelda", "Immanuel", "Imogene", "Ines", "Irma", "Irving", "Irwin", "Isaac", "Isabel", "Isabell", "Isabella", "Isabelle", "Isac", "Isadore", "Isai", "Isaiah", "Isaias", "Isidro", "Ismael", "Isobel", "Isom", "Israel", "Issac", "Itzel", "Iva", "Ivah", "Ivory", "Ivy", "Izabella", "Izaiah", "Jabari", "Jace", "Jacey", "Jacinthe", "Jacinto", "Jack", "Jackeline", "Jackie", "Jacklyn", "Jackson", "Jacky", "Jaclyn", "Jacquelyn", "Jacques", "Jacynthe", "Jada", "Jade", "Jaden", "Jadon", "Jadyn", "Jaeden", "Jaida", "Jaiden", "Jailyn", "Jaime", "Jairo", "Jakayla", "Jake", "Jakob", "Jaleel", "Jalen", "Jalon", "Jalyn", "Jamaal", "Jamal", "Jamar", "Jamarcus", "Jamel", "Jameson", "Jamey", "Jamie", "Jamil", "Jamir", "Jamison", "Jammie", "Jan", "Jana", "Janae", "Jane", "Janelle", "Janessa", "Janet", "Janice", "Janick", "Janie", "Janis", "Janiya", "Jannie", "Jany", "Jaquan", "Jaquelin", "Jaqueline", "Jared", "Jaren", "Jarod", "Jaron", "Jarred", "Jarrell", "Jarret", "Jarrett", "Jarrod", "Jarvis", "Jasen", "Jasmin", "Jason", "Jasper", "Jaunita", "Javier", "Javon", "Javonte", "Jay", "Jayce", "Jaycee", "Jayda", "Jayde", "Jayden", "Jaydon", "Jaylan", "Jaylen", "Jaylin", "Jaylon", "Jayme", "Jayne", "Jayson", "Jazlyn", "Jazmin", "Jazmyn", "Jazmyne", "Jean", "Jeanette", "Jeanie", "Jeanne", "Jed", "Jedediah", "Jedidiah", "Jeff", "Jefferey", "Jeffery", "Jeffrey", "Jeffry", "Jena", "Jenifer", "Jennie", "Jennifer", "Jennings", "Jennyfer", "Jensen", "Jerad", "Jerald", "Jeramie", "Jeramy", "Jerel", "Jeremie", "Jeremy", "Jermain", "Jermaine", "Jermey", "Jerod", "Jerome", "Jeromy", "Jerrell", "Jerrod", "Jerrold", "Jerry", "Jess", "Jesse", "Jessica", "Jessie", "Jessika", "Jessy", "Jessyca", "Jesus", "Jett", "Jettie", "Jevon", "Jewel", "Jewell", "Jillian", "Jimmie", "Jimmy", "Jo", "Joan", "Joana", "Joanie", "Joanne", "Joannie", "Joanny", "Joany", "Joaquin", "Jocelyn", "Jodie", "Jody", "Joe", "Joel", "Joelle", "Joesph", "Joey", "Johan", "Johann", "Johanna", "Johathan", "John", "Johnathan", "Johnathon", "Johnnie", "Johnny", "Johnpaul", "Johnson", "Jolie", "Jon", "Jonas", "Jonatan", "Jonathan", "Jonathon", "Jordan", "Jordane", "Jordi", "Jordon", "Jordy", "Jordyn", "Jorge", "Jose", "Josefa", "Josefina", "Joseph", "Josephine", "Josh", "Joshua", "Joshuah", "Josiah", "Josiane", "Josianne", "Josie", "Josue", "Jovan", "Jovani", "Jovanny", "Jovany", "Joy", "Joyce", "Juana", "Juanita", "Judah", "Judd", "Jude", "Judge", "Judson", "Judy", "Jules", "Julia", "Julian", "Juliana", "Julianne", "Julie", "Julien", "Juliet", "Julio", "Julius", "June", "Junior", "Junius", "Justen", "Justice", "Justina", "Justine", "Juston", "Justus", "Justyn", "Juvenal", "Juwan", "Kacey", "Kaci", "Kacie", "Kade", "Kaden", "Kadin", "Kaela", "Kaelyn", "Kaia", "Kailee", "Kailey", "Kailyn", "Kaitlin", "Kaitlyn", "Kale", "Kaleb", "Kaleigh", "Kaley", "Kali", "Kallie", "Kameron", "Kamille", "Kamren", "Kamron", "Kamryn", "Kane", "Kara", "Kareem", "Karelle", "Karen", "Kari", "Kariane", "Karianne", "Karina", "Karine", "Karl", "Karlee", "Karley", "Karli", "Karlie", "Karolann", "Karson", "Kasandra", "Kasey", "Kassandra", "Katarina", "Katelin", "Katelyn", "Katelynn", "Katharina", "Katherine", "Katheryn", "Kathleen", "Kathlyn", "Kathryn", "Kathryne", "Katlyn", "Katlynn", "Katrina", "Katrine", "Kattie", "Kavon", "Kay", "Kaya", "Kaycee", "Kayden", "Kayla", "Kaylah", "Kaylee", "Kayleigh", "Kayley", "Kayli", "Kaylie", "Kaylin", "Keagan", "Keanu", "Keara", "Keaton", "Keegan", "Keeley", "Keely", "Keenan", "Keira", "Keith", "Kellen", "Kelley", "Kelli", "Kellie", "Kelly", "Kelsi", "Kelsie", "Kelton", "Kelvin", "Ken", "Kendall", "Kendra", "Kendrick", "Kenna", "Kennedi", "Kennedy", "Kenneth", "Kennith", "Kenny", "Kenton", "Kenya", "Kenyatta", "Kenyon", "Keon", "Keshaun", "Keshawn", "Keven", "Kevin", "Kevon", "Keyon", "Keyshawn", "Khalid", "Khalil", "Kian", "Kiana", "Kianna", "Kiara", "Kiarra", "Kiel", "Kiera", "Kieran", "Kiley", "Kim", "Kimberly", "King", "Kip", "Kira", "Kirk", "Kirsten", "Kirstin", "Kitty", "Kobe", "Koby", "Kody", "Kolby", "Kole", "Korbin", "Korey", "Kory", "Kraig", "Kris", "Krista", "Kristian", "Kristin", "Kristina", "Kristofer", "Kristoffer", "Kristopher", "Kristy", "Krystal", "Krystel", "Krystina", "Kurt", "Kurtis", "Kyla", "Kyle", "Kylee", "Kyleigh", "Kyler", "Kylie", "Kyra", "Lacey", "Lacy", "Ladarius", "Lafayette", "Laila", "Laisha", "Lamar", "Lambert", "Lamont", "Lance", "Landen", "Lane", "Laney", "Larissa", "Laron", "Larry", "Larue", "Laura", "Laurel", "Lauren", "Laurence", "Lauretta", "Lauriane", "Laurianne", "Laurie", "Laurine", "Laury", "Lauryn", "Lavada", "Lavern", "Laverna", "Laverne", "Lavina", "Lavinia", "Lavon", "Lavonne", "Lawrence", "Lawson", "Layla", "Layne", "Lazaro", "Lea", "Leann", "Leanna", "Leanne", "Leatha", "Leda", "Lee", "Leif", "Leila", "Leilani", "Lela", "Lelah", "Leland", "Lelia", "Lempi", "Lemuel", "Lenna", "Lennie", "Lenny", "Lenora", "Lenore", "Leo", "Leola", "Leon", "Leonard", "Leonardo", "Leone", "Leonel", "Leonie", "Leonor", "Leonora", "Leopold", "Leopoldo", "Leora", "Lera", "Lesley", "Leslie", "Lesly", "Lessie", "Lester", "Leta", "Letha", "Letitia", "Levi", "Lew", "Lewis", "Lexi", "Lexie", "Lexus", "Lia", "Liam", "Liana", "Libbie", "Libby", "Lila", "Lilian", "Liliana", "Liliane", "Lilla", "Lillian", "Lilliana", "Lillie", "Lilly", "Lily", "Lilyan", "Lina", "Lincoln", "Linda", "Lindsay", "Lindsey", "Linnea", "Linnie", "Linwood", "Lionel", "Lisa", "Lisandro", "Lisette", "Litzy", "Liza", "Lizeth", "Lizzie", "Llewellyn", "Lloyd", "Logan", "Lois", "Lola", "Lolita", "Loma", "Lon", "London", "Lonie", "Lonnie", "Lonny", "Lonzo", "Lora", "Loraine", "Loren", "Lorena", "Lorenz", "Lorenza", "Lorenzo", "Lori", "Lorine", "Lorna", "Lottie", "Lou", "Louie", "Louisa", "Lourdes", "Louvenia", "Lowell", "Loy", "Loyal", "Loyce", "Lucas", "Luciano", "Lucie", "Lucienne", "Lucile", "Lucinda", "Lucio", "Lucious", "Lucius", "Lucy", "Ludie", "Ludwig", "Lue", "Luella", "Luigi", "Luis", "Luisa", "Lukas", "Lula", "Lulu", "Luna", "Lupe", "Lura", "Lurline", "Luther", "Luz", "Lyda", "Lydia", "Lyla", "Lynn", "Lyric", "Lysanne", "Mabel", "Mabelle", "Mable", "Mac", "Macey", "Maci", "Macie", "Mack", "Mackenzie", "Macy", "Madaline", "Madalyn", "Maddison", "Madeline", "Madelyn", "Madelynn", "Madge", "Madie", "Madilyn", "Madisen", "Madison", "Madisyn", "Madonna", "Madyson", "Mae", "Maegan", "Maeve", "Mafalda", "Magali", "Magdalen", "Magdalena", "Maggie", "Magnolia", "Magnus", "Maia", "Maida", "Maiya", "Major", "Makayla", "Makenna", "Makenzie", "Malachi", "Malcolm", "Malika", "Malinda", "Mallie", "Mallory", "Malvina", "Mandy", "Manley", "Manuel", "Manuela", "Mara", "Marc", "Marcel", "Marcelina", "Marcelino", "Marcella", "Marcelle", "Marcellus", "Marcelo", "Marcia", "Marco", "Marcos", "Marcus", "Margaret", "Margarete", "Margarett", "Margaretta", "Margarette", "Margarita", "Marge", "Margie", "Margot", "Margret", "Marguerite", "Maria", "Mariah", "Mariam", "Marian", "Mariana", "Mariane", "Marianna", "Marianne", "Mariano", "Maribel", "Marie", "Mariela", "Marielle", "Marietta", "Marilie", "Marilou", "Marilyne", "Marina", "Mario", "Marion", "Marisa", "Marisol", "Maritza", "Marjolaine", "Marjorie", "Marjory", "Mark", "Markus", "Marlee", "Marlen", "Marlene", "Marley", "Marlin", "Marlon", "Marques", "Marquis", "Marquise", "Marshall", "Marta", "Martin", "Martina", "Martine", "Marty", "Marvin", "Mary", "Maryam", "Maryjane", "Maryse", "Mason", "Mateo", "Mathew", "Mathias", "Mathilde", "Matilda", "Matilde", "Matt", "Matteo", "Mattie", "Maud", "Maude", "Maudie", "Maureen", "Maurice", "Mauricio", "Maurine", "Maverick", "Mavis", "Max", "Maxie", "Maxime", "Maximilian", "Maximillia", "Maximillian", "Maximo", "Maximus", "Maxine", "Maxwell", "May", "Maya", "Maybell", "Maybelle", "Maye", "Maymie", "Maynard", "Mayra", "Mazie", "Mckayla", "Mckenna", "Mckenzie", "Meagan", "Meaghan", "Meda", "Megane", "Meggie", "Meghan", "Mekhi", "Melany", "Melba", "Melisa", "Melissa", "Mellie", "Melody", "Melvin", "Melvina", "Melyna", "Melyssa", "Mercedes", "Meredith", "Merl", "Merle", "Merlin", "Merritt", "Mertie", "Mervin", "Meta", "Mia", "Micaela", "Micah", "Michael", "Michaela", "Michale", "Micheal", "Michel", "Michele", "Michelle", "Miguel", "Mikayla", "Mike", "Mikel", "Milan", "Miles", "Milford", "Miller", "Millie", "Milo", "Milton", "Mina", "Minerva", "Minnie", "Miracle", "Mireille", "Mireya", "Misael", "Missouri", "Misty", "Mitchel", "Mitchell", "Mittie", "Modesta", "Modesto", "Mohamed", "Mohammad", "Mohammed", "Moises", "Mollie", "Molly", "Mona", "Monica", "Monique", "Monroe", "Monserrat", "Monserrate", "Montana", "Monte", "Monty", "Morgan", "Moriah", "Morris", "Mortimer", "Morton", "Mose", "Moses", "Moshe", "Mossie", "Mozell", "Mozelle", "Muhammad", "Muriel", "Murl", "Murphy", "Murray", "Mustafa", "Mya", "Myah", "Mylene", "Myles", "Myra", "Myriam", "Myrl", "Myrna", "Myron", "Myrtice", "Myrtie", "Myrtis", "Myrtle", "Nadia", "Nakia", "Name", "Nannie", "Naomi", "Naomie", "Napoleon", "Narciso", "Nash", "Nasir", "Nat", "Natalia", "Natalie", "Natasha", "Nathan", "Nathanael", "Nathanial", "Nathaniel", "Nathen", "Nayeli", "Neal", "Ned", "Nedra", "Neha", "Neil", "Nelda", "Nella", "Nelle", "Nellie", "Nels", "Nelson", "Neoma", "Nestor", "Nettie", "Neva", "Newell", "Newton", "Nia", "Nicholas", "Nicholaus", "Nichole", "Nick", "Nicklaus", "Nickolas", "Nico", "Nicola", "Nicolas", "Nicole", "Nicolette", "Nigel", "Nikita", "Nikki", "Nikko", "Niko", "Nikolas", "Nils", "Nina", "Noah", "Noble", "Noe", "Noel", "Noelia", "Noemi", "Noemie", "Noemy", "Nola", "Nolan", "Nona", "Nora", "Norbert", "Norberto", "Norene", "Norma", "Norris", "Norval", "Norwood", "Nova", "Novella", "Nya", "Nyah", "Nyasia", "Obie", "Oceane", "Ocie", "Octavia", "Oda", "Odell", "Odessa", "Odie", "Ofelia", "Okey", "Ola", "Olaf", "Ole", "Olen", "Oleta", "Olga", "Olin", "Oliver", "Ollie", "Oma", "Omari", "Omer", "Ona", "Onie", "Opal", "Ophelia", "Ora", "Oral", "Oran", "Oren", "Orie", "Orin", "Orion", "Orland", "Orlando", "Orlo", "Orpha", "Orrin", "Orval", "Orville", "Osbaldo", "Osborne", "Oscar", "Osvaldo", "Oswald", "Oswaldo", "Otha", "Otho", "Otilia", "Otis", "Ottilie", "Ottis", "Otto", "Ova", "Owen", "Ozella", "Pablo", "Paige", "Palma", "Pamela", "Pansy", "Paolo", "Paris", "Parker", "Pascale", "Pasquale", "Pat", "Patience", "Patricia", "Patrick", "Patsy", "Pattie", "Paul", "Paula", "Pauline", "Paxton", "Payton", "Pearl", "Pearlie", "Pearline", "Pedro", "Peggie", "Penelope", "Percival", "Percy", "Perry", "Pete", "Peter", "Petra", "Peyton", "Philip", "Phoebe", "Phyllis", "Pierce", "Pierre", "Pietro", "Pink", "Pinkie", "Piper", "Polly", "Porter", "Precious", "Presley", "Preston", "Price", "Prince", "Princess", "Priscilla", "Providenci", "Prudence", "Queen", "Queenie", "Quentin", "Quincy", "Quinn", "Quinten", "Quinton", "Rachael", "Rachel", "Rachelle", "Rae", "Raegan", "Rafael", "Rafaela", "Raheem", "Rahsaan", "Rahul", "Raina", "Raleigh", "Ralph", "Ramiro", "Ramon", "Ramona", "Randal", "Randall", "Randi", "Randy", "Ransom", "Raoul", "Raphael", "Raphaelle", "Raquel", "Rashad", "Rashawn", "Rasheed", "Raul", "Raven", "Ray", "Raymond", "Raymundo", "Reagan", "Reanna", "Reba", "Rebeca", "Rebecca", "Rebeka", "Rebekah", "Reece", "Reed", "Reese", "Regan", "Reggie", "Reginald", "Reid", "Reilly", "Reina", "Reinhold", "Remington", "Rene", "Renee", "Ressie", "Reta", "Retha", "Retta", "Reuben", "Reva", "Rex", "Rey", "Reyes", "Reymundo", "Reyna", "Reynold", "Rhea", "Rhett", "Rhianna", "Rhiannon", "Rhoda", "Ricardo", "Richard", "Richie", "Richmond", "Rick", "Rickey", "Rickie", "Ricky", "Rico", "Rigoberto", "Riley", "Rita", "River", "Robb", "Robbie", "Robert", "Roberta", "Roberto", "Robin", "Robyn", "Rocio", "Rocky", "Rod", "Roderick", "Rodger", "Rodolfo", "Rodrick", "Rodrigo", "Roel", "Rogelio", "Roger", "Rogers", "Rolando", "Rollin", "Roma", "Romaine", "Roman", "Ron", "Ronaldo", "Ronny", "Roosevelt", "Rory", "Rosa", "Rosalee", "Rosalia", "Rosalind", "Rosalinda", "Rosalyn", "Rosamond", "Rosanna", "Rosario", "Roscoe", "Rose", "Rosella", "Roselyn", "Rosemarie", "Rosemary", "Rosendo", "Rosetta", "Rosie", "Rosina", "Roslyn", "Ross", "Rossie", "Rowan", "Rowena", "Rowland", "Roxane", "Roxanne", "Roy", "Royal", "Royce", "Rozella", "Ruben", "Rubie", "Ruby", "Rubye", "Rudolph", "Rudy", "Rupert", "Russ", "Russel", "Russell", "Rusty", "Ruth", "Ruthe", "Ruthie", "Ryan", "Ryann", "Ryder", "Rylan", "Rylee", "Ryleigh", "Ryley", "Sabina", "Sabrina", "Sabryna", "Sadie", "Sadye", "Sage", "Saige", "Sallie", "Sally", "Salma", "Salvador", "Salvatore", "Sam", "Samanta", "Samantha", "Samara", "Samir", "Sammie", "Sammy", "Samson", "Sandra", "Sandrine", "Sandy", "Sanford", "Santa", "Santiago", "Santina", "Santino", "Santos", "Sarah", "Sarai", "Sarina", "Sasha", "Saul", "Savanah", "Savanna", "Savannah", "Savion", "Scarlett", "Schuyler", "Scot", "Scottie", "Scotty", "Seamus", "Sean", "Sebastian", "Sedrick", "Selena", "Selina", "Selmer", "Serena", "Serenity", "Seth", "Shad", "Shaina", "Shakira", "Shana", "Shane", "Shanel", "Shanelle", "Shania", "Shanie", "Shaniya", "Shanna", "Shannon", "Shanny", "Shanon", "Shany", "Sharon", "Shaun", "Shawn", "Shawna", "Shaylee", "Shayna", "Shayne", "Shea", "Sheila", "Sheldon", "Shemar", "Sheridan", "Sherman", "Sherwood", "Shirley", "Shyann", "Shyanne", "Sibyl", "Sid", "Sidney", "Sienna", "Sierra", "Sigmund", "Sigrid", "Sigurd", "Silas", "Sim", "Simeon", "Simone", "Sincere", "Sister", "Skye", "Skyla", "Skylar", "Sofia", "Soledad", "Solon", "Sonia", "Sonny", "Sonya", "Sophia", "Sophie", "Spencer", "Stacey", "Stacy", "Stan", "Stanford", "Stanley", "Stanton", "Stefan", "Stefanie", "Stella", "Stephan", "Stephania", "Stephanie", "Stephany", "Stephen", "Stephon", "Sterling", "Steve", "Stevie", "Stewart", "Stone", "Stuart", "Summer", "Sunny", "Susan", "Susana", "Susanna", "Susie", "Suzanne", "Sven", "Syble", "Sydnee", "Sydney", "Sydni", "Sydnie", "Sylvan", "Sylvester", "Sylvia", "Tabitha", "Tad", "Talia", "Talon", "Tamara", "Tamia", "Tania", "Tanner", "Tanya", "Tara", "Taryn", "Tate", "Tatum", "Tatyana", "Taurean", "Tavares", "Taya", "Taylor", "Teagan", "Ted", "Telly", "Terence", "Teresa", "Terrance", "Terrell", "Terrence", "Terrill", "Terry", "Tess", "Tessie", "Tevin", "Thad", "Thaddeus", "Thalia", "Thea", "Thelma", "Theo", "Theodora", "Theodore", "Theresa", "Therese", "Theresia", "Theron", "Thomas", "Thora", "Thurman", "Tia", "Tiana", "Tianna", "Tiara", "Tierra", "Tiffany", "Tillman", "Timmothy", "Timmy", "Timothy", "Tina", "Tito", "Titus", "Tobin", "Toby", "Tod", "Tom", "Tomas", "Tomasa", "Tommie", "Toney", "Toni", "Tony", "Torey", "Torrance", "Torrey", "Toy", "Trace", "Tracey", "Tracy", "Travis", "Travon", "Tre", "Tremaine", "Tremayne", "Trent", "Trenton", "Tressa", "Tressie", "Treva", "Trever", "Trevion", "Trevor", "Trey", "Trinity", "Trisha", "Tristian", "Tristin", "Triston", "Troy", "Trudie", "Trycia", "Trystan", "Turner", "Twila", "Tyler", "Tyra", "Tyree", "Tyreek", "Tyrel", "Tyrell", "Tyrese", "Tyrique", "Tyshawn", "Tyson", "Ubaldo", "Ulices", "Ulises", "Una", "Unique", "Urban", "Uriah", "Uriel", "Ursula", "Vada", "Valentin", "Valentina", "Valentine", "Valerie", "Vallie", "Van", "Vance", "Vanessa", "Vaughn", "Veda", "Velda", "Vella", "Velma", "Velva", "Vena", "Verda", "Verdie", "Vergie", "Verla", "Verlie", "Vern", "Verna", "Verner", "Vernice", "Vernie", "Vernon", "Verona", "Veronica", "Vesta", "Vicenta", "Vicente", "Vickie", "Vicky", "Victor", "Victoria", "Vida", "Vidal", "Vilma", "Vince", "Vincent", "Vincenza", "Vincenzo", "Vinnie", "Viola", "Violet", "Violette", "Virgie", "Virgil", "Virginia", "Virginie", "Vita", "Vito", "Viva", "Vivian", "Viviane", "Vivianne", "Vivien", "Vivienne", "Vladimir", "Wade", "Waino", "Waldo", "Walker", "Wallace", "Walter", "Walton", "Wanda", "Ward", "Warren", "Watson", "Wava", "Waylon", "Wayne", "Webster", "Weldon", "Wellington", "Wendell", "Wendy", "Werner", "Westley", "Weston", "Whitney", "Wilber", "Wilbert", "Wilburn", "Wiley", "Wilford", "Wilfred", "Wilfredo", "Wilfrid", "Wilhelm", "Wilhelmine", "Will", "Willa", "Willard", "William", "Willie", "Willis", "Willow", "Willy", "Wilma", "Wilmer", "Wilson", "Wilton", "Winfield", "Winifred", "Winnifred", "Winona", "Winston", "Woodrow", "Wyatt", "Wyman", "Xander", "Xavier", "Xzavier", "Yadira", "Yasmeen", "Yasmin", "Yasmine", "Yazmin", "Yesenia", "Yessenia", "Yolanda", "Yoshiko", "Yvette", "Yvonne", "Zachariah", "Zachary", "Zachery", "Zack", "Zackary", "Zackery", "Zakary", "Zander", "Zane", "Zaria", "Zechariah", "Zelda", "Zella", "Zelma", "Zena", "Zetta", "Zion", "Zita", "Zoe", "Zoey", "Zoie", "Zoila", "Zola", "Zora", "Zula"}, + "middle": {"Abdul", "Abdullah", "Abigail", "Ada", "Adam", "Adelaide", "Adele", "Adelina", "Adrian", "Adriana", "Agnes", "Agnolo", "Ahmed", "Aida", "Aileen", "Aimee", "Akilesh", "Akio", "Alan", "Alana", "Alejandro", "Alex", "Ali", "Alice", "Alicia", "Alina", "Alison", "Alita", "Allegretta", "Alonzo", "Alyssa", "Aman", "Amara", "Amelda", "Amelia", "Amenra", "Amina", "Amir", "Amitabh", "Amy", "Ana", "Anastasia", "André", "Andrea", "Andrei", "Andrew", "Andy", "Angel", "Angela", "Anita", "Ann", "Anna", "Anne", "Annette", "Anthony", "Antioco", "Antonio", "Arduino", "Aria", "Ariana", "Ariel", "Aris", "Arjun", "Armando", "Asha", "Ashton", "Asong", "Athena", "Audrey", "August", "Aura", "Aurelia", "Austen", "Ava", "Avery", "Avril", "Badru", "Bailey", "Bakul", "Baldwin", "Bao", "Barack", "Bear", "Beatrice", "Beau", "Belinda", "Bella", "Belle", "Ben", "Benjamin", "Bertha", "Beverly", "Bharati", "Bhoja", "Bhuma", "Bianca", "Bird", "Birdie", "Bishvajit", "Bjorn", "Blair", "Blake", "Blanca", "Bliss", "Blue", "Bo", "Bobbie", "Bonnie", "Boris", "Bradley", "Brandt", "Braulia", "Breck", "Bree", "Brett", "Brianna", "Bridget", "Brie", "Brielle", "Brittany", "Brizio", "Brook", "Brooke", "Brooks", "Bruce", "Bryce", "Bryn", "Brynn", "Burke", "Cajetan", "Calvin", "Cameron", "Camilla", "Candice", "Carla", "Carlos", "Carmen", "Caroline", "Carson", "Casey", "Cash", "Cassandra", "Cassidy", "Catherine", "Cecelia", "Cecilia", "Cedric", "Celeste", "Celia", "Celso", "Chahna", "Chance", "Chander", "Chandler", "Chang", "Charles", "Charlie", "Charlotte", "Chen", "Chintak", "Chloe", "Chris", "Christine", "Chung", "Cimeron", "Cindy", "Ciprianna", "Ciro", "Claire", "Clara", "Clarissa", "Clark", "Clarke", "Claude", "Claudia", "Clay", "Clementine", "Clint", "Cody", "Cole", "Colette", "Cora", "Cordelia", "Corey", "Corinne", "Cory", "Cosme", "Courtney", "Cree", "Crew", "Cynthia", "Cyprienne", "Cyrus", "Daan", "Dada", "Daisy", "Dakota", "Dale", "Damodar", "Dan", "Dana", "Dane", "Daniel", "Danielle", "Danveer", "Daphne", "Darla", "David", "Davide", "Dawn", "Dax", "Dean", "Deborah", "Delilah", "Denise", "Denver", "Deshal", "Deshawn", "Dev", "Devin", "Dhavala", "Diana", "Diane", "Diego", "Dmitri", "Dolores", "Dolorita", "Donato", "Dong", "Donna", "Donte", "Donya", "Dora", "Doris", "Dorothy", "Drake", "Drew", "Dru", "Dylan", "Ean", "Edith", "Eduardo", "Edward", "Eila", "Eileen", "Elaine", "Elda", "Eleanor", "Elena", "Eliana", "Elias", "Elise", "Eliza", "Elizabeth", "Ella", "Elle", "Ellen", "Ellie", "Ellis", "Eloise", "Elsa", "Elsie", "Em", "Emerson", "Emery", "Emilie", "Emilio", "Emily", "Emma", "Emmett", "Enrico", "Enrique", "Epifania", "Erica", "Erik", "Erin", "Eroica", "Esperanza", "Estelle", "Esther", "Etta", "Ettore", "Eva", "Evan", "Eve", "Evelyn", "Everett", "Faith", "Farid", "Faye", "Federico", "Felicity", "Felipe", "Felix", "Fern", "Fernando", "Finley", "Finn", "Fiona", "Fitz", "Flint", "Flora", "Florence", "Flynn", "Folke", "Fonzo", "Fox", "Frances", "Francis", "Francisco", "Francois", "François", "Frank", "Frankie", "Freya", "Fumio", "Fynn", "Gabriel", "Gabriella", "Gael", "Gage", "Gail", "Gemma", "Genevieve", "George", "Georgia", "Geraldine", "Giannino", "Ginetta", "Gioia", "Giselle", "Giuseppe", "Giustino", "Glenn", "Gloria", "Glory", "Grace", "Grant", "Gray", "Greer", "Greta", "Guido", "Guillermo", "Gulshan", "Gus", "Gwen", "Gyula", "Hank", "Hannah", "Hans", "Harley", "Harper", "Harriet", "Harrison", "Harshad", "Haruki", "Hayden", "Hayes", "Haze", "Hazel", "Heath", "Heather", "Hector", "Helen", "Helena", "Henry", "Hideki", "Hidetoshi", "Himesh", "Hiro", "Hiroaki", "Hirofumi", "Hirokazu", "Hiroshi", "Hiroto", "Hiroyuki", "Holly", "Honor", "Hope", "Hugh", "Hugo", "Hunter", "Ida", "Ignacio", "Imogen", "Ingrid", "Irene", "Iris", "Isaac", "Isabel", "Isabella", "Isabelle", "Ivan", "Ivy", "Jace", "Jack", "Jacqueline", "Jade", "Jaden", "Jae", "Jai", "Jaime", "Jamal", "James", "Jamie", "Jan", "Janak", "Jane", "Janet", "Janice", "Jasmine", "Jasper", "Javier", "Jax", "Jay", "Jayden", "Jayne", "Jean", "Jeanne", "Jed", "Jenna", "Jennifer", "Jesse", "Jessica", "Jill", "Jin", "Joan", "Joanna", "João", "Jocelyn", "Jodi", "Jody", "Joe", "Joey", "Johanna", "Johar", "John", "Jolene", "Jordan", "Jorge", "Jose", "José", "Joseph", "Josephine", "Josie", "Joy", "Joyce", "Juan", "Juanita", "Judd", "Jude", "Judith", "Jules", "Julia", "Julian", "Juliana", "Julianne", "Julie", "June", "Justine", "Kael", "Kai", "Kane", "Karen", "Kate", "Katherine", "Kathleen", "Kathryn", "Katie", "Katrina", "Kay", "Kayla", "Kazuki", "Keira", "Kelly", "Kelsey", "Kendall", "Kendra", "Kennedy", "Kent", "Kenta", "Kerry", "Khaled", "Khloe", "Kiara", "Kim", "Kimberly", "Kit", "Kiyoshi", "Klaus", "Knight", "Knox", "Koen", "Koi", "Koichi", "Koji", "Kolt", "Kristen", "Kristina", "Kurt", "Kwame", "Kye", "Kylie", "Lacey", "Laine", "Lake", "Lakshman", "Lalika", "Lane", "Lark", "Lars", "Laurel", "Layne", "Lee", "Leif", "Lennon", "Leo", "Leon", "Leslie", "Liam", "Liberty", "Lilian", "Lillian", "Lillie", "Link", "Liz", "Locke", "Logan", "Lona", "Lorena", "Lorenzo", "Lou", "Louise", "Love", "Lucia", "Lucy", "Luis", "Luiz", "Luke", "Lupita", "Lux", "Luz", "Lydia", "Lynn", "Mabel", "Mac", "Mack", "Mackenzie", "Madeline", "Madison", "Madona", "Mae", "Mael", "Makoto", "Manuel", "Manuela", "Maple", "Marc", "Marco", "Margaret", "Margo", "Margot", "Maria", "Mariano", "Maricela", "Marilyn", "Mario", "Mark", "Marley", "Mars", "Marti", "Mary", "Mason", "Matthew", "Mavis", "Max", "May", "Mazie", "Mei", "Melody", "Mercy", "Merle", "Micah", "Michael", "Miguel", "Mina", "Ming", "Mohamed", "Mollie", "Monroe", "Morgan", "Muhammad", "Musetta", "Myra", "Nadine", "Naomi", "Nardo", "Nat", "Natalie", "Neal", "Neil", "Nellie", "Nerola", "Nevada", "Neve", "Nikolai", "Niles", "Noel", "Nola", "Nora", "Nuru", "Oakley", "Olive", "Oliver", "Opal", "Orazio", "Ortensa", "Ortensia", "Osamu", "Oscar", "Otto", "Pablo", "Paige", "Pancho", "Paris", "Parker", "Pat", "Patrick", "Paul", "Pauli", "Pax", "Peace", "Pearl", "Pedro", "Penelope", "Penn", "Penny", "Peter", "Petra", "Peyton", "Phoenix", "Pierce", "Pierre", "Pilar", "Porter", "Praise", "Pratap", "Presley", "Priscilla", "Quinn", "Rachanna", "Radames", "Rae", "Rafael", "Rain", "Raine", "Ramiro", "Ramon", "Ramona", "Raphael", "Raul", "Ravi", "Ray", "Rayne", "Reagan", "Reece", "Reed", "Reese", "Rei", "Reid", "Reilly", "Remy", "Ren", "Reyes", "Rhodes", "Ricardo", "Richard", "Riley", "Rita", "River", "Rivera", "Roan", "Robert", "Roberto", "Robin", "Robt", "Rodrigo", "Roma", "Romelia", "Rory", "Rosa", "Rosalee", "Rosalie", "Rosalynn", "Rosario", "Rose", "Ross", "Rowan", "Ruben", "Ruby", "Rue", "Rush", "Russell", "Ruth", "Ryan", "Saad", "Saariq", "Sade", "Sadie", "Sagara", "Sage", "Saige", "Saint", "Salvadora", "Sam", "Samir", "Samuel", "Sante", "Santiago", "Sara", "Sasha", "Satoshi", "Scott", "Sean", "Sebastian", "Sergei", "Sergio", "Seth", "Shae", "Shai", "Shane", "Shannon", "Shashi", "Shaun", "Shawn", "Shawnee", "Shay", "Shea", "Shelby", "Shin", "Sidney", "Simon", "Sky", "Skye", "Skyler", "Sol", "Sophie", "Spencer", "Star", "Starr", "Stella", "Steve", "Stevie", "Storm", "Susan", "Sven", "Sybil", "Sydney", "Tahj", "Takashi", "Takeshi", "Taryn", "Tatum", "Taylor", "Teagan", "Terry", "Tess", "Thea", "Theodore", "Thomas", "Tilly", "Timothy", "Tosca", "Trent", "Tripp", "Tristan", "Truth", "Tyler", "Tyrone", "Uberto", "Ursus", "Val", "Vandelia", "Vaughn", "Vera", "Vernon", "Verona", "Vianna", "Victoria", "Vida", "Vieda", "Vince", "Vincent", "Violet", "Virginia", "Vivian", "Vladimir", "Wade", "Wayne", "Wes", "Wesley", "West", "Whitney", "Will", "Willa", "William", "Willie", "Winston", "Winter", "Wolf", "Wren", "Wynn", "Xavier", "Yasuo", "Yoel", "Yolanda", "Yoshi", "Yoshiaki", "Yoshihiro", "Yoshiki", "Yoshinori", "Yoshio", "Yusuf", "Yutaka", "Zain", "Zane", "Zayd", "Zelda", "Zeus", "Zev", "Zhang", "Zhen", "Zola", "Zora", "Zuni"}, "last": {"Abbott", "Abernathy", "Abshire", "Adams", "Altenwerth", "Anderson", "Ankunding", "Armstrong", "Auer", "Aufderhar", "Bahringer", "Bailey", "Balistreri", "Barrows", "Bartell", "Bartoletti", "Barton", "Bashirian", "Batz", "Bauch", "Baumbach", "Bayer", "Beahan", "Beatty", "Bechtelar", "Becker", "Bednar", "Beer", "Beier", "Berge", "Bergnaum", "Bergstrom", "Bernhard", "Bernier", "Bins", "Blanda", "Blick", "Block", "Bode", "Boehm", "Bogan", "Bogisich", "Borer", "Bosco", "Botsford", "Boyer", "Boyle", "Bradtke", "Brakus", "Braun", "Breitenberg", "Brekke", "Brown", "Bruen", "Buckridge", "Carroll", "Carter", "Cartwright", "Casper", "Cassin", "Champlin", "Christiansen", "Cole", "Collier", "Collins", "Conn", "Connelly", "Conroy", "Considine", "Corkery", "Cormier", "Corwin", "Cremin", "Crist", "Crona", "Cronin", "Crooks", "Cruickshank", "Cummerata", "Cummings", "Dach", "Damore", "Daniel", "Dare", "Daugherty", "Davis", "Deckow", "Denesik", "Dibbert", "Dickens", "Dicki", "Dickinson", "Dietrich", "Donnelly", "Dooley", "Douglas", "Doyle", "DuBuque", "Durgan", "Ebert", "Effertz", "Eichmann", "Emard", "Emmerich", "Erdman", "Ernser", "Fadel", "Fahey", "Farrell", "Fay", "Feeney", "Feest", "Feil", "Ferry", "Fisher", "Flatley", "Frami", "Franecki", "Friesen", "Fritsch", "Funk", "Gaylord", "Gerhold", "Gerlach", "Gibson", "Gislason", "Gleason", "Gleichner", "Glover", "Goldner", "Goodwin", "Gorczany", "Gottlieb", "Goyette", "Grady", "Graham", "Grant", "Green", "Greenfelder", "Greenholt", "Grimes", "Gulgowski", "Gusikowski", "Gutkowski", "Gutmann", "Haag", "Hackett", "Hagenes", "Hahn", "Haley", "Halvorson", "Hamill", "Hammes", "Hand", "Hane", "Hansen", "Harber", "Harris", "Hartmann", "Harvey", "Hauck", "Hayes", "Heaney", "Heathcote", "Hegmann", "Heidenreich", "Heller", "Herman", "Hermann", "Hermiston", "Herzog", "Hessel", "Hettinger", "Hickle", "Hilll", "Hills", "Hilpert", "Hintz", "Hirthe", "Hodkiewicz", "Hoeger", "Homenick", "Hoppe", "Howe", "Howell", "Hudson", "Huel", "Huels", "Hyatt", "Jacobi", "Jacobs", "Jacobson", "Jakubowski", "Jaskolski", "Jast", "Jenkins", "Jerde", "Jewess", "Johns", "Johnson", "Johnston", "Jones", "Kassulke", "Kautzer", "Keebler", "Keeling", "Kemmer", "Kerluke", "Kertzmann", "Kessler", "Kiehn", "Kihn", "Kilback", "King", "Kirlin", "Klein", "Kling", "Klocko", "Koch", "Koelpin", "Koepp", "Kohler", "Konopelski", "Koss", "Kovacek", "Kozey", "Krajcik", "Kreiger", "Kris", "Kshlerin", "Kub", "Kuhic", "Kuhlman", "Kuhn", "Kulas", "Kunde", "Kunze", "Kuphal", "Kutch", "Kuvalis", "Labadie", "Lakin", "Lang", "Langosh", "Langworth", "Larkin", "Larson", "Leannon", "Lebsack", "Ledner", "Leffler", "Legros", "Lehner", "Lemke", "Lesch", "Leuschke", "Lind", "Lindgren", "Littel", "Little", "Lockman", "Lowe", "Lubowitz", "Lueilwitz", "Luettgen", "Lynch", "Macejkovic", "Maggio", "Mann", "Mante", "Marks", "Marquardt", "Marvin", "Mayer", "Mayert", "McClure", "McCullough", "McDermott", "McGlynn", "McKenzie", "McLaughlin", "Medhurst", "Mertz", "Metz", "Miller", "Mills", "Mitchell", "Moen", "Mohr", "Monahan", "Moore", "Morar", "Morissette", "Mosciski", "Mraz", "Mueller", "Muller", "Murazik", "Murphy", "Murray", "Nader", "Nicolas", "Nienow", "Nikolaus", "Nitzsche", "Nolan", "Oberbrunner", "Okuneva", "Olson", "Ondricka", "OReilly", "Orn", "Ortiz", "Osinski", "Pacocha", "Padberg", "Pagac", "Parisian", "Parker", "Paucek", "Pfannerstill", "Pfeffer", "Pollich", "Pouros", "Powlowski", "Predovic", "Price", "Prohaska", "Prosacco", "Purdy", "Quigley", "Quitzon", "Rath", "Ratke", "Rau", "Raynor", "Reichel", "Reichert", "Reilly", "Reinger", "Rempel", "Renner", "Reynolds", "Rice", "Rippin", "Ritchie", "Robel", "Roberts", "Rodriguez", "Rogahn", "Rohan", "Rolfson", "Romaguera", "Roob", "Rosenbaum", "Rowe", "Ruecker", "Runolfsdottir", "Runolfsson", "Runte", "Russel", "Rutherford", "Ryan", "Sanford", "Satterfield", "Sauer", "Sawayn", "Schaden", "Schaefer", "Schamberger", "Schiller", "Schimmel", "Schinner", "Schmeler", "Schmidt", "Schmitt", "Schneider", "Schoen", "Schowalter", "Schroeder", "Schulist", "Schultz", "Schumm", "Schuppe", "Schuster", "Senger", "Shanahan", "Shields", "Simonis", "Sipes", "Skiles", "Smith", "Smitham", "Spencer", "Spinka", "Sporer", "Stamm", "Stanton", "Stark", "Stehr", "Steuber", "Stiedemann", "Stokes", "Stoltenberg", "Stracke", "Streich", "Stroman", "Strosin", "Swaniawski", "Swift", "Terry", "Thiel", "Thompson", "Tillman", "Torp", "Torphy", "Towne", "Toy", "Trantow", "Tremblay", "Treutel", "Tromp", "Turcotte", "Turner", "Ullrich", "Upton", "Vandervort", "Veum", "Volkman", "Von", "VonRueden", "Waelchi", "Walker", "Walsh", "Walter", "Ward", "Waters", "Watsica", "Weber", "Wehner", "Weimann", "Weissnat", "Welch", "West", "White", "Wiegand", "Wilderman", "Wilkinson", "Will", "Williamson", "Willms", "Windler", "Wintheiser", "Wisoky", "Wisozk", "Witting", "Wiza", "Wolf", "Wolff", "Wuckert", "Wunsch", "Wyman", "Yost", "Yundt", "Zboncak", "Zemlak", "Ziemann", "Zieme", "Zulauf"}, "hobby": {"3D printing", "Acrobatics", "Acting", "Amateur radio", "Animation", "Aquascaping", "Astrology", "Astronomy", "Baking", "Baton twirling", "Blogging", "Building", "Board/tabletop games", "Book discussion clubs", "Book restoration", "Bowling", "Brazilian jiu-jitsu", "Breadmaking", "Bullet journaling", "Cabaret", "Calligraphy", "Candle making", "Candy making", "Car fixing & building", "Card games", "Cheesemaking", "Cleaning", "Clothesmaking", "Coffee roasting", "Collecting", "Coloring", "Computer programming", "Confectionery", "Cooking", "Cosplaying", "Couponing", "Craft", "Creative writing", "Crocheting", "Cross-stitch", "Crossword puzzles", "Cryptography", "Cue sports", "Dance", "Digital arts", "Distro Hopping", "DJing", "Do it yourself", "Drama", "Drawing", "Drink mixing", "Drinking", "Electronic games", "Electronics", "Embroidery", "Experimenting", "Fantasy sports", "Fashion", "Fashion design", "Fishkeeping", "Filmmaking", "Flower arranging", "Fly tying", "Foreign language learning", "Furniture building", "Gaming", "Genealogy", "Gingerbread house making", "Glassblowing", "Graphic design", "Gunsmithing", "Gymnastics", "Hacking", "Herp keeping", "Home improvement", "Homebrewing", "Houseplant care", "Hula hooping", "Humor", "Hydroponics", "Ice skating", "Jewelry making", "Jigsaw puzzles", "Journaling", "Juggling", "Karaoke", "Karate", "Kendama", "Knife making", "Knitting", "Knot tying", "Kombucha brewing", "Lace making", "Lapidary", "Leather crafting", "Lego building", "Lock picking", "Listening to music", "Listening to podcasts", "Machining", "Macrame", "Magic", "Makeup", "Mazes (indoor/outdoor)", "Metalworking", "Model building", "Model engineering", "Nail art", "Needlepoint", "Origami", "Painting", "Palmistry", "Pet adoption & fostering", "Philately", "Photography", "Practical jokes", "Pressed flower craft", "Playing musical instruments", "Poi", "Pottery", "Powerlifting", "Puzzles", "Quilling", "Quilting", "Quizzes", "Radio-controlled model", "Rail transport modeling", "Rapping", "Reading", "Refinishing", "Reiki", "Robot combat", "Rubik's Cube", "Scrapbooking", "Sculpting", "Sewing", "Shoemaking", "Singing", "Sketching", "Skipping rope", "Slot car", "Soapmaking", "Social media", "Spreadsheets", "Stand-up comedy", "Stamp collecting", "Table tennis", "Tarot", "Taxidermy", "Thrifting", "Video editing", "Video game developing", "Video gaming", "Watching movies", "Watching television", "Videography", "Virtual reality", "Waxing", "Weaving", "Weight training", "Welding", "Whittling", "Wikipedia editing", "Winemaking", "Wood carving", "Woodworking", "Worldbuilding", "Writing", "Word searches", "Yo-yoing", "Yoga", "Zumba", "Amusement park visiting", "Air sports", "Airsoft", "Amateur geology", "Archery", "Astronomy", "Backpacking", "Badminton", "BASE jumping", "Baseball", "Basketball", "Beekeeping", "Birdwatching", "Blacksmithing", "BMX", "Board sports", "Bodybuilding", "Bonsai", "Butterfly watching", "Bus riding", "Camping", "Canoeing", "Canyoning", "Car riding", "Caving", "Composting", "Cycling", "Dowsing", "Driving", "Farming", "Fishing", "Flag football", "Flower growing", "Flying", "Flying disc", "Foraging", "Fossicking", "Freestyle football", "Gardening", "Geocaching", "Ghost hunting", "Gold prospecting", "Graffiti", "Handball", "Herbalism", "Herping", "High-power rocketry", "Hiking", "Hobby horsing", "Hobby tunneling", "Hooping", "Horseback riding", "Hunting", "Inline skating", "Jogging", "Jumping rope", "Kayaking", "Kite flying", "Kitesurfing", "Lacrosse", "LARPing", "Letterboxing", "Longboarding", "Martial arts", "Metal detecting", "Meteorology", "Motor sports", "Mountain biking", "Mountaineering", "Museum visiting", "Mushroom hunting", "Netball", "Nordic skating", "Orienteering", "Paintball", "Parkour", "Photography", "Podcast hosting", "Polo", "Public transport riding", "Rafting", "Railway journeys", "Rappelling", "Road biking", "Rock climbing", "Roller skating", "Rugby", "Running", "Radio-controlled model", "Sailing", "Sand art", "Scouting", "Scuba diving", "Sculling", "Shooting", "Shopping", "Shuffleboard", "Skateboarding", "Skiing", "Skimboarding", "Skydiving", "Slacklining", "Snowboarding", "Snowmobiling", "Snowshoeing", "Soccer", "Stone skipping", "Sun bathing", "Surfing", "Survivalism", "Swimming", "Taekwondo", "Tai chi", "Tennis", "Topiary", "Tourism", "Thru-hiking", "Trade fair visiting", "Travel", "Urban exploration", "Vacation", "Vegetable farming", "Videography", "Vehicle restoration", "Walking", "Water sports", "Astronomy", "Biology", "Chemistry", "Electrochemistry", "Physics", "Psychology", "Sports science", "Geography", "History", "Mathematics", "Railway studies", "Action figure", "Antiquing", "Ant-keeping", "Art collecting", "Book collecting", "Button collecting", "Cartophily", "Coin collecting", "Comic book collecting", "Deltiology", "Die-cast toy", "Digital hoarding", "Dolls", "Element collecting", "Ephemera collecting", "Fusilately", "Knife collecting", "Lotology", "Movie and movie memorabilia collecting", "Fingerprint collecting", "Perfume", "Phillumeny", "Radio-controlled model", "Rail transport modelling", "Record collecting", "Rock tumbling", "Scutelliphily", "Shoes", "Slot car", "Sports memorabilia", "Stamp collecting", "Stuffed toy collecting", "Tea bag collecting", "Ticket collecting", "Toys", "Transit map collecting", "Video game collecting", "Vintage cars", "Vintage clothing", "Vinyl Records", "Antiquities", "Auto audiophilia", "Flower collecting and pressing", "Fossil hunting", "Insect collecting", "Magnet fishing", "Metal detecting", "Mineral collecting", "Rock balancing", "Sea glass collecting", "Seashell collecting", "Stone collecting", "Animal fancy", "Axe throwing", "Backgammon", "Badminton", "Baton twirling", "Beauty pageants", "Billiards", "Bowling", "Boxing", "Bridge", "Checkers (draughts)", "Cheerleading", "Chess", "Color guard", "Cribbage", "Curling", "Dancing", "Darts", "Debate", "Dominoes", "Eating", "Esports", "Fencing", "Go", "Gymnastics", "Ice hockey", "Ice skating", "Judo", "Jujitsu", "Kabaddi", "Knowledge/word games", "Laser tag", "Longboarding", "Mahjong", "Marbles", "Martial arts", "Model United Nations", "Poker", "Pool", "Role-playing games", "Shogi", "Slot car racing", "Speedcubing", "Sport stacking", "Table football", "Table tennis", "Volleyball", "Weightlifting", "Wrestling", "Airsoft", "Archery", "Association football", "Australian rules football", "Auto racing", "Baseball", "Beach volleyball", "Breakdancing", "Climbing", "Cricket", "Croquet", "Cycling", "Disc golf", "Dog sport", "Equestrianism", "Exhibition drill", "Field hockey", "Figure skating", "Fishing", "Footbag", "Frisbee", "Golfing", "Handball", "Horseback riding", "Horseshoes", "Iceboat racing", "Jukskei", "Kart racing", "Knife throwing", "Lacrosse", "Longboarding", "Long-distance running", "Marching band", "Model aircraft", "Orienteering", "Pickleball", "Quidditch", "Race walking", "Racquetball", "Radio-controlled car racing", "Roller derby", "Rugby league football", "Sculling", "Shooting sport", "Skateboarding", "Skiing", "Sled dog racing", "Softball", "Speed skating", "Squash", "Surfing", "Swimming", "Table tennis", "Tennis", "Tennis polo", "Tether car", "Tour skating", "Tourism", "Trapshooting", "Triathlon", "Ultimate frisbee", "Volleyball", "Water polo", "Fishkeeping", "Learning", "Meditation", "Microscopy", "Reading", "Research", "Shortwave listening", "Audiophile", "Aircraft spotting", "Amateur astronomy", "Birdwatching", "Bus spotting", "Geocaching", "Gongoozling", "Herping", "Hiking", "Meteorology", "Photography", "Satellite watching", "Trainspotting", "Whale watching"}, "phone": {"###-###-####", "(###)###-####", "1-###-###-####", "###.###.####"}, diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/product.go b/vendor/github.com/brianvoe/gofakeit/v6/data/product.go new file mode 100644 index 000000000..127d66554 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/product.go @@ -0,0 +1,64 @@ +package data + +var Product = map[string][]string{ + "category": { + "electronics", "clothing", "home appliances", "furniture", + "automotive parts", "beauty and personal care", "books", "sports equipment", + "toys and games", "outdoor gear", "pet supplies", "kitchenware", + "health and wellness", "tools and hardware", "office supplies", + "baby products", "jewelry", "home decor", "musical instruments", + "fitness equipment", "mobile phones", "computer accessories", "cameras and photography", + "gardening supplies", "bedding and linens", "food and groceries", "party supplies", + "craft and diy supplies", "camping gear", "watches", "luggage and travel accessories", + "board games", "art supplies", "stationery", "bath and shower products", + "sunglasses", "educational toys", "headphones and earbuds", "sneakers and athletic shoes", + "coffee and tea products", "bicycles and accessories", "cookware", "cosmetics", + "home improvement", "pet food", "laptop bags and cases", "home security systems", + "musical accessories", "skincare products", "smart home devices", + }, + + "adjective": { + "bold", "swift", "pure", "smart", "fresh", + "cool", "sharp", "zen", "bright", "quick", + "robust", "sleek", "versatile", "innovative", "compact", + "luxe", "modular", "precision", "stream", + }, + + "name": { + "phone", "laptop", "tablet", "watch", "camera", + "headphones", "speaker", "drone", "car", "bike", + "appliance", "gadget", "tool", "toy", "game", + "computer", "console", "smartwatch", "fitness tracker", "smart home device", + "robot", "router", "television", "smart speaker", "vr headset", + "earbuds", "printer", "mouse", "keyboard", "monitor", + "microwave", "blender", "vacuum", "fan", "toaster", + "clock", "lamp", "shaver", "scale", "thermometer", + "fridge", "oven", "mixer", "iron", "hair dryer", + "fan", "scale", "thermostat", "router", "lightbulb", + }, + + "feature": { + "wireless", "smart", "eco-friendly", "advanced", "compact", + "high-performance", "energy-efficient", "portable", "durable", "stylish", + "touchscreen", "water-resistant", "noise-canceling", "voice-controlled", "ultra-lightweight", + "multi-functional", "user-friendly", "fast-charging", "biometric", "gps-enabled", + }, + + "material": { + "titanium", "carbon", "alloy", "bamboo", "leather", + "glass", "ceramic", "aluminum", "stainless", "wood", + "plastic", "rubber", "silicon", "fabric", "paper", + "gold", "silver", "brass", "copper", "bronze", + "chrome", "marble", "granite", "porcelain", "plexiglass", + "quartz", "felt", "suede", + }, + + "suffix": { + "tech", "pro", "x", "plus", "elite", + "spark", "nexus", "nova", "fusion", "sync", + "edge", "boost", "max", "link", "prime", + "zoom", "pulse", "dash", "connect", "blaze", + "quantum", "spark", "vertex", "core", "flux", + "turbo", "shift", "wave", "matrix", + }, +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/school.go b/vendor/github.com/brianvoe/gofakeit/v6/data/school.go new file mode 100644 index 000000000..a9772d634 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/school.go @@ -0,0 +1,56 @@ +package data + +// School type and names +var School = map[string][]string{ + "type": {"Elementary School", "Middle School", "University", "High School", "Kindergarten", "Academy", "College", "Institute"}, + "isPrivate": {"Private", "State"}, + "name": {"Maplewood", + "Pineville", + "Riverside", + "Willowbrook", + "Crestwood", + "Sunset", + "Greenfield", + "Oakwood", + "Willowbrook", + "Hawthorn", + "Brookside", + "Pleasant View", + "Crescent Valley", + "Sycamore", + "Springfield", + "Meadowbrook", + "Greenwood", + "Riverbend", + "Valley Forge", + "Ridgeview", + "Cottonwood", + "Cedarwood", + "Golden Oak", + "Stonebridge", + "Harborview", + "Windsor", + "Northbrook", + "Sunset", + "Redwood Valley", + "Liberty", + "Washington Central", + "Franklin", + "Jefferson", + "Lincoln Park", + "Madison", + "Roosevelt", + "Westwood", + "Central Lakeside", + "Fairview", + "Heritage Hills", + "Kingsbridge", + "Harrisonville", + "Valley View", + "Hillside", + "Northridge", + "Brooklyn Heights", + "Oakridge", + "Countryside", + }, +} \ No newline at end of file diff --git a/vendor/github.com/brianvoe/gofakeit/v6/data/word.go b/vendor/github.com/brianvoe/gofakeit/v6/data/word.go index 3dfc66f42..87b48dc88 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/data/word.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/data/word.go @@ -27,6 +27,7 @@ var Word = map[string][]string{ "noun_collective_thing": {"wad", "pair", "album", "string", "anthology", "reel", "outfit", "fleet", "comb", "archipelago", "quiver", "bale", "packet", "hedge", "basket", "orchard", "batch", "library", "battery", "set", "harvest", "block", "forest", "book", "group", "bouquet", "collection", "bowl", "stack", "bunch", "hand", "bundle", "catalog", "shower", "ream", "chest", "heap", "range", "cluster", "pack", "hail", "cloud", "galaxy", "sheaf", "clump"}, "noun_countable": {"camp", "hospital", "shirt", "sock", "plant", "cup", "fork", "spoon", "plate", "straw", "town", "box", "bird", "father", "answer", "egg", "purse", "mirror", "mistake", "toilet", "toothbrush", "shower", "towel", "pool", "corner", "card", "lawn", "city", "egg", "yard", "burger", "kilometer", "mile", "father", "film", "actor", "issue", "machine", "liter", "room", "station", "journey", "castle", "hour", "finger", "boy", "book", "year", "second", "son", "month", "group", "hall", "cat", "week", "picture", "day", "village", "effect", "baby", "weekend", "class", "meal", "river", "grade", "bush", "desk", "stream", "method", "brother", "sister", "factory", "aunt", "bush", "program", "uncle", "ball", "cousin", "wall", "grandmother", "cup", "grandfather", "week", "school", "shirt", "child", "king", "road", "judge", "bridge", "car", "line", "book", "eye", "teacher", "foot", "party", "face", "day", "chest", "handle", "week", "hotel", "eye", "animal", "doctor", "adult", "village", "key", "bird", "bank", "program", "idea", "gun", "card", "brother", "dress", "room", "door", "mouth", "club", "game", "ring", "project", "sister", "road", "coat", "account", "group", "cigarette", "farm", "river", "college", "computer", "walk", "corner", "cat", "head", "street", "election", "country", "chair", "crowd", "cup", "plant", "farm", "handle", "model", "book", "message", "battle", "pen", "pencil", "elephant", "carrot", "onion", "garden", "country", "engine", "bill", "apple", "noun", "club", "crowd", "window", "field", "friend", "verb", "class", "flower", "seed", "lake", "plant", "animal", "ocean", "whale", "fish", "stream", "cloud", "couch", "steak", "problem", "light", "door", "room", "painting", "shop", "apartment", "candle", "adult", "building", "plan", "page", "ball", "game", "animal", "apartment", "box", "thought", "walk", "lady", "bottle", "article", "game", "kettle", "car", "house", "hoses", "orange", "phone", "app", "window", "door", "dollar", "foot", "cent", "library", "cat", "bed", "pound", "gate", "tomatoes", "gun", "holiday", "woman", "job", "shock", "salary", "tax", "coat", "scooter", "dog", "problem", "field", "answer", "ear", "camp", "case", "road", "woman", "product", "bridge", "man", "dream", "idea", "scheme", "invention", "cigarette", "mother", "friend", "chapter", "computer", "dream", "father", "child", "motor", "deskpath", "factory", "park", "newspaper", "hat", "dream", "table", "kitchen", "student", "captain", "doctor", "bus", "neck", "class", "list", "member", "chest", "valley", "product", "horse", "captain", "star", "hour", "page", "bus", "girl", "month", "child", "house", "boy", "bill", "kitchen", "chapter", "boat", "hand", "dress", "table", "wall", "chair", "train", "minute", "magazine", "bus", "party", "bird", "lake", "job", "nation", "bike", "election", "hand", "box", "beach", "address", "project", "task", "park", "face", "college", "bell", "plane", "store", "hall", "accident", "daughter", "ship", "candy", "smile", "city", "island", "case", "spot", "film", "husband", "artist", "tour", "bag", "boat", "driver", "office", "chair", "path", "dog", "bag", "finger", "apartment", "garden", "heart", "year", "engine", "girl", "day", "castle", "plane", "ring", "brother", "edge", "picture", "meeting", "tent", "dog", "hat", "head", "bottle", "hill"}, "noun_uncountable": {"accommodation", "advertising", "air", "aid", "advice", "anger", "art", "assistance", "bread", "business", "butter", "calm", "cash", "chaos", "cheese", "childhood", "clothing", "coffee", "content", "corruption", "courage", "currency", "damage", "danger", "darkness", "data", "determination", "economics", "education", "electricity", "employment", "energy", "entertainment", "enthusiasm", "equipment", "evidence", "failure", "fame", "fire", "flour", "food", "freedom", "friendship", "fuel", "furniture", "fun", "genetics", "gold", "grammar", "guilt", "hair", "happiness", "harm", "health", "heat", "help", "homework", "honesty", "hospitality", "housework", "humour", "imagination", "importance", "information", "innocence", "intelligence", "jealousy", "juice", "justice", "kindness", "knowledge", "labour", "lack", "laughter", "leisure", "literature", "litter", "logic", "love", "luck", "magic", "management", "metal", "milk", "money", "motherhood", "motivation", "music", "nature", "news", "nutrition", "obesity", "oil", "old age", "oxygen", "paper", "patience", "permission", "pollution", "poverty", "power", "pride", "production", "progress", "pronunciation", "publicity", "punctuation", "quality", "quantity", "racism", "rain", "relaxation", "research", "respect", "rice", "room (space)", "rubbish", "safety", "salt", "sand", "seafood", "shopping", "silence", "smoke", "snow", "software", "soup", "speed", "spelling", "stress", "sugar", "sunshine", "tea", "tennis", "time", "tolerance", "trade", "traffic", "transportation", "travel", "trust", "understanding", "unemployment", "usage", "violence", "vision", "warmth", "water", "wealth", "weather", "weight", "welfare", "wheat", "width", "wildlife", "wisdom", "wood", "work", "yoga", "youth"}, + "noun_determiner": {"the", "a", "an", "this", "that", "these", "those", "my", "your", "his", "her", "its", "our", "their", "some", "any", "each", "every", "certain"}, //"noun_proper": {}, // This refers to an actual person(John Doe), place(Chipotle, Tennessee) // Verbs @@ -71,9 +72,12 @@ var Word = map[string][]string{ // Connectives "connective_time": {"after a while", "afterwards", "at once", "at this moment", "at this point", "before that", "finally", "first", "here", "in the end", "lastly", "later on", "meanwhile", "next", "next time", "now", "on another occasion", "previously", "since", "soon", "straightaway", "then", "until then", "when", "whenever", "while"}, - "connective_comparitive": {"additionally", "also", "as well", "even", "furthermore", "in addition", "indeed", "let alone", "moreover", "not only", "alternatively", "anyway", "but", "by contrast", "differs from", "elsewhere", "even so", "however", "in contrast", "in fact", "in other respects", "in spite of this", "in that respect", "instead", "nevertheless", "on the contrary", "on the other hand", "rather", "though", "whereas", "yet", "after all", "anyway", "besides", "moreover"}, + "connective_comparative": {"additionally", "also", "as well", "even", "furthermore", "in addition", "indeed", "let alone", "moreover", "not only", "alternatively", "anyway", "but", "by contrast", "differs from", "elsewhere", "even so", "however", "in contrast", "in fact", "in other respects", "in spite of this", "in that respect", "instead", "nevertheless", "on the contrary", "on the other hand", "rather", "though", "whereas", "yet", "after all", "anyway", "besides", "moreover"}, "connective_complaint": {"besides", "e.g.", "for example", "for instance", "i.e.", "in other words", "in that", "that is to say"}, "connective_listing": {"firstly", "secondly", "first of all", "finally", "lastly", "for one thing", "for another", "in the first place", "to begin with", "next", "in summation", "to conclude"}, "connective_casual": {"accordingly", "all the same", "an effect of", "an outcome of", "an upshot of", "as a consequence of", "as a result of", "because", "caused by", "consequently", "despite this", "even though", "hence", "however", "in that case", "moreover", "nevertheless", "otherwise", "so", "so as", "stemmed from", "still", "then", "therefore", "though", "under the circumstances", "yet"}, "connective_examplify": {"accordingly", "as a result", "as exemplified by", "consequently", "for example", "for instance", "for one thing", "including", "provided that", "since", "so", "such as", "then", "therefore", "these include", "through", "unless", "without"}, + + // Misc + "interjection": {"wow", "hey", "oops", "ouch", "yay", "aha", "eek", "huh", "hmm", "whoa", "yikes", "phew", "gee", "alas", "bravo"}, } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/emoji.go b/vendor/github.com/brianvoe/gofakeit/v6/emoji.go index f40f630f9..5eb4372ec 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/emoji.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/emoji.go @@ -46,10 +46,10 @@ func addEmojiLookup() { AddFuncLookup("emoji", Info{ Display: "Emoji", Category: "emoji", - Description: "Random emoji", + Description: "Digital symbol expressing feelings or ideas in text messages and online chats", Example: "🤣", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emoji(r), nil }, }) @@ -57,10 +57,10 @@ func addEmojiLookup() { AddFuncLookup("emojidescription", Info{ Display: "Emoji Description", Category: "emoji", - Description: "Random emoji description", + Description: "Brief explanation of the meaning or emotion conveyed by an emoji", Example: "face vomiting", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiDescription(r), nil }, }) @@ -68,10 +68,10 @@ func addEmojiLookup() { AddFuncLookup("emojicategory", Info{ Display: "Emoji Category", Category: "emoji", - Description: "Random emoji category", + Description: "Group or classification of emojis based on their common theme or use, like 'smileys' or 'animals'", Example: "Smileys & Emotion", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiCategory(r), nil }, }) @@ -79,10 +79,10 @@ func addEmojiLookup() { AddFuncLookup("emojialias", Info{ Display: "Emoji Alias", Category: "emoji", - Description: "Random emoji alias", + Description: "Alternative name or keyword used to represent a specific emoji in text or code", Example: "smile", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiAlias(r), nil }, }) @@ -90,10 +90,10 @@ func addEmojiLookup() { AddFuncLookup("emojitag", Info{ Display: "Emoji Tag", Category: "emoji", - Description: "Random emoji tag", + Description: "Label or keyword associated with an emoji to categorize or search for it easily", Example: "happy", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return emojiTag(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/error.go b/vendor/github.com/brianvoe/gofakeit/v6/error.go new file mode 100644 index 000000000..b31d7725d --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/error.go @@ -0,0 +1,233 @@ +package gofakeit + +import ( + "errors" + "math/rand" +) + +// Error will return a random generic error +func Error() error { + return err(globalFaker.Rand) +} + +// Error will return a random generic error +func (f *Faker) Error() error { + return err(f.Rand) +} + +func err(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "generic"}))) +} + +// ErrorObject will return a random error object word +func ErrorObject() error { + return errorObject(globalFaker.Rand) +} + +// ErrorObject will return a random error object word +func (f *Faker) ErrorObject() error { + return errorObject(f.Rand) +} + +func errorObject(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "object"}))) +} + +// ErrorDatabase will return a random database error +func ErrorDatabase() error { + return errorDatabase(globalFaker.Rand) +} + +// ErrorDatabase will return a random database error +func (f *Faker) ErrorDatabase() error { + return errorDatabase(f.Rand) +} + +func errorDatabase(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "database"}))) +} + +// ErrorGRPC will return a random gRPC error +func ErrorGRPC() error { + return errorGRPC(globalFaker.Rand) +} + +// ErrorGRPC will return a random gRPC error +func (f *Faker) ErrorGRPC() error { + return errorGRPC(f.Rand) +} + +func errorGRPC(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "grpc"}))) +} + +// ErrorHTTP will return a random HTTP error +func ErrorHTTP() error { + return errorHTTP(globalFaker.Rand) +} + +// ErrorHTTP will return a random HTTP error +func (f *Faker) ErrorHTTP() error { + return errorHTTP(f.Rand) +} + +func errorHTTP(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "http"}))) +} + +// ErrorHTTPClient will return a random HTTP client error response (400-418) +func ErrorHTTPClient() error { + return errorHTTPClient(globalFaker.Rand) +} + +// ErrorHTTPClient will return a random HTTP client error response (400-418) +func (f *Faker) ErrorHTTPClient() error { + return errorHTTPClient(f.Rand) +} + +func errorHTTPClient(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "http_client"}))) +} + +// ErrorHTTPServer will return a random HTTP server error response (500-511) +func ErrorHTTPServer() error { + return errorHTTPServer(globalFaker.Rand) +} + +// ErrorHTTPServer will return a random HTTP server error response (500-511) +func (f *Faker) ErrorHTTPServer() error { + return errorHTTPServer(f.Rand) +} + +func errorHTTPServer(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "http_server"}))) +} + +// ErrorRuntime will return a random runtime error +func ErrorRuntime() error { + return errorRuntime(globalFaker.Rand) +} + +// ErrorRuntime will return a random runtime error +func (f *Faker) ErrorRuntime() error { + return errorRuntime(f.Rand) +} + +func errorRuntime(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "runtime"}))) +} + +// ErrorValidation will return a random validation error +func ErrorValidation() error { + return errorValidation(globalFaker.Rand) +} + +// ErrorValidation will return a random validation error +func (f *Faker) ErrorValidation() error { + return errorValidation(f.Rand) +} + +func errorValidation(r *rand.Rand) error { + return errors.New(generate(r, getRandValue(r, []string{"error", "validation"}))) +} + +func addErrorLookup() { + AddFuncLookup("error", Info{ + Display: "Error", + Category: "error", + Description: "Message displayed by a computer or software when a problem or mistake is encountered", + Example: "syntax error", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return err(r), nil + }, + }) + + AddFuncLookup("errorobject", Info{ + Display: "Error object word", + Category: "error", + Description: "Various categories conveying details about encountered errors", + Example: "protocol", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorObject(r), nil + }, + }) + + AddFuncLookup("errordatabase", Info{ + Display: "Database error", + Category: "error", + Description: "A problem or issue encountered while accessing or managing a database", + Example: "sql error", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorDatabase(r), nil + }, + }) + + AddFuncLookup("errorgrpc", Info{ + Display: "gRPC error", + Category: "error", + Description: "Communication failure in the high-performance, open-source universal RPC framework", + Example: "client protocol error", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorGRPC(r), nil + }, + }) + + AddFuncLookup("errorhttp", Info{ + Display: "HTTP error", + Category: "error", + Description: "A problem with a web http request", + Example: "invalid method", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorHTTP(r), nil + }, + }) + + AddFuncLookup("errorhttpclient", Info{ + Display: "HTTP client error", + Category: "error", + Description: "Failure or issue occurring within a client software that sends requests to web servers", + Example: "request timeout", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorHTTPClient(r), nil + }, + }) + + AddFuncLookup("errorhttpserver", Info{ + Display: "HTTP server error", + Category: "error", + Description: "Failure or issue occurring within a server software that recieves requests from clients", + Example: "internal server error", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorHTTPServer(r), nil + }, + }) + + AddFuncLookup("errorruntime", Info{ + Display: "Runtime error", + Category: "error", + Description: "Malfunction occuring during program execution, often causing abrupt termination or unexpected behavior", + Example: "address out of bounds", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorRuntime(r), nil + }, + }) + + AddFuncLookup("errorvalidation", Info{ + Display: "Validation error", + Category: "error", + Description: "Occurs when input data fails to meet required criteria or format specifications", + Example: "missing required field", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return errorValidation(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/fakeable.go b/vendor/github.com/brianvoe/gofakeit/v6/fakeable.go new file mode 100644 index 000000000..1089fc380 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/fakeable.go @@ -0,0 +1,83 @@ +package gofakeit + +import ( + "errors" + "fmt" + "reflect" +) + +// Fakeable is an interface that can be implemented by a type to provide a custom fake value. +type Fakeable interface { + // Fake returns a fake value for the type. + Fake(faker *Faker) (any, error) +} + +func isFakeable(t reflect.Type) bool { + fakeableTyp := reflect.TypeOf((*Fakeable)(nil)).Elem() + + return t.Implements(fakeableTyp) || reflect.PtrTo(t).Implements(fakeableTyp) +} + +func callFake(faker *Faker, v reflect.Value, possibleKinds ...reflect.Kind) (any, error) { + f, ok := v.Addr().Interface().(Fakeable) + if !ok { + return nil, errors.New("not a Fakeable type") + } + + fakedValue, err := f.Fake(faker) + if err != nil { + return nil, fmt.Errorf("error calling Fake: %w", err) + } + k := reflect.TypeOf(fakedValue).Kind() + if !containsKind(possibleKinds, k) { + return nil, fmt.Errorf("returned value kind %q is not amongst the valid ones: %v", k, possibleKinds) + } + + switch k { + case reflect.String: + return reflect.ValueOf(fakedValue).String(), nil + case reflect.Bool: + return reflect.ValueOf(fakedValue).Bool(), nil + case reflect.Int: + return int(reflect.ValueOf(fakedValue).Int()), nil + case reflect.Int8: + return int8(reflect.ValueOf(fakedValue).Int()), nil + case reflect.Int16: + return int16(reflect.ValueOf(fakedValue).Int()), nil + case reflect.Int32: + return int32(reflect.ValueOf(fakedValue).Int()), nil + case reflect.Int64: + return int64(reflect.ValueOf(fakedValue).Int()), nil + case reflect.Uint: + return uint(reflect.ValueOf(fakedValue).Uint()), nil + case reflect.Uint8: + return uint8(reflect.ValueOf(fakedValue).Uint()), nil + case reflect.Uint16: + return uint16(reflect.ValueOf(fakedValue).Uint()), nil + case reflect.Uint32: + return uint32(reflect.ValueOf(fakedValue).Uint()), nil + case reflect.Uint64: + return uint64(reflect.ValueOf(fakedValue).Uint()), nil + case reflect.Float32: + return float32(reflect.ValueOf(fakedValue).Float()), nil + case reflect.Float64: + return float64(reflect.ValueOf(fakedValue).Float()), nil + case reflect.Slice: + return reflect.ValueOf(fakedValue).Interface(), nil + case reflect.Map: + return reflect.ValueOf(fakedValue).Interface(), nil + case reflect.Struct: + return reflect.ValueOf(fakedValue).Interface(), nil + default: + return nil, fmt.Errorf("unsupported type %q", k) + } +} + +func containsKind(possibleKinds []reflect.Kind, kind reflect.Kind) bool { + for _, k := range possibleKinds { + if k == kind { + return true + } + } + return false +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/file.go b/vendor/github.com/brianvoe/gofakeit/v6/file.go index 05ebc50d9..3812021e1 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/file.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/file.go @@ -22,10 +22,10 @@ func addFileLookup() { AddFuncLookup("fileextension", Info{ Display: "File Extension", Category: "file", - Description: "Random file extension", + Description: "Suffix appended to a filename indicating its format or type", Example: "nes", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return fileExtension(r), nil }, }) @@ -33,10 +33,10 @@ func addFileLookup() { AddFuncLookup("filemimetype", Info{ Display: "File Mime Type", Category: "file", - Description: "Random file mime type", + Description: "Defines file format and nature for browsers and email clients using standardized identifiers", Example: "application/json", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return fileMimeType(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/finance.go b/vendor/github.com/brianvoe/gofakeit/v6/finance.go new file mode 100644 index 000000000..a46907a62 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/finance.go @@ -0,0 +1,128 @@ +package gofakeit + +import ( + "math/rand" + "strconv" + "unicode" +) + +const cusipStr = upperStr + numericStr + +// CUSIP +func Cusip() string { + return cusip(globalFaker.Rand) +} + +func (f *Faker) Cusip() string { + return cusip(f.Rand) +} + +func cusip(r *rand.Rand) string { + cusipBytes := make([]byte, 8) + for i := 0; i < len(cusipBytes); i++ { + cusipBytes[i] = byte(cusipStr[r.Intn(len(cusipStr))]) + } + + baseCusip := string(cusipBytes) + + chkDigit := cusipChecksumDigit(baseCusip) + return baseCusip + chkDigit +} + +// ISIN +func Isin() string { + return isin(globalFaker.Rand) +} + +func (f *Faker) Isin() string { + return isin(f.Rand) +} + +func isin(r *rand.Rand) string { + countryCode := CountryAbr() + nsin := cusip(r) + isinChkDig := isinChecksumDigit(countryCode + nsin) + return countryCode + nsin + isinChkDig +} + +// cusipChecksumDigit returns the checksum digit for a CUSIP +func cusipChecksumDigit(cusip string) string { + sum := 0 + for i, c := range cusip { + v := 0 + if unicode.IsDigit(c) { + v = int(c - '0') + } + if unicode.IsLetter(c) { + //0-indexed ordinal position of Letter + 10 + v = int(c-'A') + 10 + } + if i%2 != 0 { + // Multiply odd digits by two + v = v * 2 + } + + sum = sum + int(v/10) + v%10 + } + + return strconv.Itoa((10 - (sum % 10)) % 10) +} + +// isinChecksumDigit returns the checksum digit for an ISIN +func isinChecksumDigit(isin string) string { + isinDigits := make([]int, 0) + for _, c := range isin { + if unicode.IsLetter(c) { + letterVal := int(c) - 55 + // Each digit is added as a separate value + isinDigits = append(isinDigits, letterVal/10) + isinDigits = append(isinDigits, letterVal%10) + } + if unicode.IsDigit(c) { + isinDigits = append(isinDigits, int(c-'0')) + } + } + + oddSum := 0 + evenSum := 0 + + // Take the per digit sum of the digitized ISIN, doubling even indexed digits + for i, d := range isinDigits { + if i%2 == 0 { + elem := 2 * d + if elem > 9 { + // If the element now has two digits, sum those digits + elem = (elem % 10) + (elem / 10) + } + evenSum += elem + } else { + oddSum += d + } + } + + return strconv.Itoa((10 - (oddSum+evenSum)%10) % 10) +} + +// Lookup Adds +func addFinanceLookup() { + AddFuncLookup("cusip", Info{ + Display: "CUSIP", + Category: "finance", + Description: "Unique identifier for securities, especially bonds, in the United States and Canada", + Example: "38259P508", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return cusip(r), nil + }, + }) + AddFuncLookup("isin", Info{ + Display: "ISIN", + Category: "finance", + Description: "International standard code for uniquely identifying securities worldwide", + Example: "CVLRQCZBXQ97", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return isin(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/food.go b/vendor/github.com/brianvoe/gofakeit/v6/food.go index a8b7e7c9f..ae1bb2fd6 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/food.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/food.go @@ -91,10 +91,10 @@ func addFoodLookup() { AddFuncLookup("fruit", Info{ Display: "Fruit", Category: "food", - Description: "Random fruit", + Description: "Edible plant part, typically sweet, enjoyed as a natural snack or dessert", Example: "Peach", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return fruit(r), nil }, }) @@ -102,10 +102,10 @@ func addFoodLookup() { AddFuncLookup("vegetable", Info{ Display: "Vegetable", Category: "food", - Description: "Random vegetable", + Description: "Edible plant or part of a plant, often used in savory cooking or salads", Example: "Amaranth Leaves", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return vegetable(r), nil }, }) @@ -113,10 +113,10 @@ func addFoodLookup() { AddFuncLookup("breakfast", Info{ Display: "Breakfast", Category: "food", - Description: "Random breakfast", + Description: "First meal of the day, typically eaten in the morning", Example: "Blueberry banana happy face pancakes", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return breakfast(r), nil }, }) @@ -124,10 +124,10 @@ func addFoodLookup() { AddFuncLookup("lunch", Info{ Display: "Lunch", Category: "food", - Description: "Random lunch", + Description: "Midday meal, often lighter than dinner, eaten around noon", Example: "No bake hersheys bar pie", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return lunch(r), nil }, }) @@ -135,10 +135,10 @@ func addFoodLookup() { AddFuncLookup("dinner", Info{ Display: "Dinner", Category: "food", - Description: "Random dinner", + Description: "Evening meal, typically the day's main and most substantial meal", Example: "Wild addicting dip", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return dinner(r), nil }, }) @@ -146,10 +146,10 @@ func addFoodLookup() { AddFuncLookup("drink", Info{ Display: "Drink", Category: "food", - Description: "Random drink", + Description: "Liquid consumed for hydration, pleasure, or nutritional benefits", Example: "Soda", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return drink(r), nil }, }) @@ -158,9 +158,9 @@ func addFoodLookup() { Display: "Snack", Category: "food", Description: "Random snack", - Example: "Hoisin marinated wing pieces", + Example: "Small, quick food item eaten between meals", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return snack(r), nil }, }) @@ -168,10 +168,10 @@ func addFoodLookup() { AddFuncLookup("dessert", Info{ Display: "Dessert", Category: "food", - Description: "Random dessert", + Description: "Sweet treat often enjoyed after a meal", Example: "French napoleons", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return dessert(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/game.go b/vendor/github.com/brianvoe/gofakeit/v6/game.go index aedd95026..5c1bc3691 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/game.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/game.go @@ -67,10 +67,10 @@ func addGameLookup() { AddFuncLookup("gamertag", Info{ Display: "Gamertag", Category: "game", - Description: "Random gamertag", + Description: "User-selected online username or alias used for identification in games", Example: "footinterpret63", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return gamertag(r), nil }, }) @@ -78,14 +78,14 @@ func addGameLookup() { AddFuncLookup("dice", Info{ Display: "Dice", Category: "game", - Description: "Random dice outputs", - Example: "footinterpret63", + Description: "Small, cube-shaped objects used in games of chance for random outcomes", + Example: "[5, 2, 3]", Output: "[]uint", Params: []Param{ {Field: "numdice", Display: "Number of Dice", Type: "uint", Default: "1", Description: "Number of dice to roll"}, {Field: "sides", Display: "Number of Sides", Type: "[]uint", Default: "[6]", Description: "Number of sides on each dice"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { numDice, err := info.GetUint(m, "numdice") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/generate.go b/vendor/github.com/brianvoe/gofakeit/v6/generate.go index 4f6043121..342a3a594 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/generate.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/generate.go @@ -1,6 +1,7 @@ package gofakeit import ( + "encoding/json" "errors" "fmt" "math" @@ -46,6 +47,11 @@ func generate(r *rand.Rand, dataVal string) string { dataVal = replaceWithNumbers(r, dataVal) dataVal = replaceWithLetters(r, dataVal) + // Check if string has any replaceable values + if !strings.Contains(dataVal, "{") && !strings.Contains(dataVal, "}") { + return dataVal + } + // Variables to identify the index in which it exists startCurly := -1 startCurlyIgnore := []int{} @@ -146,22 +152,147 @@ func generate(r *rand.Rand, dataVal string) string { return dataVal } +// FixedWidthOptions defines values needed for csv generation +type FixedWidthOptions struct { + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` +} + +// FixedWidth generates an table of random data in fixed width format +// A nil FixedWidthOptions returns a randomly structured FixedWidth. +func FixedWidth(co *FixedWidthOptions) (string, error) { return fixeWidthFunc(globalFaker.Rand, co) } + +// FixedWidth generates an table of random data in fixed width format +// A nil FixedWidthOptions returns a randomly structured FixedWidth. +func (f *Faker) FixedWidth(co *FixedWidthOptions) (string, error) { return fixeWidthFunc(f.Rand, co) } + +// Function to generate a fixed width document +func fixeWidthFunc(r *rand.Rand, co *FixedWidthOptions) (string, error) { + // If we didn't get FixedWidthOptions, create a new random one + if co == nil { + co = &FixedWidthOptions{} + } + + // Make sure you set a row count + if co.RowCount <= 0 { + co.RowCount = r.Intn(10) + 1 + } + + // Check fields + if len(co.Fields) <= 0 { + // Create random fields + co.Fields = []Field{ + {Name: "Name", Function: "{firstname} {lastname}"}, + {Name: "Email", Function: "email"}, + {Name: "Password", Function: "password", Params: MapParams{"special": {"false"}, "space": {"false"}}}, + } + } + + data := [][]string{} + hasHeader := false + + // Loop through fields, generate data and add to data array + for _, field := range co.Fields { + // Start new row + row := []string{} + + // Add name to first value + if field.Name != "" { + hasHeader = true + } + row = append(row, field.Name) + + // Get function + funcInfo := GetFuncLookup(field.Function) + var value any + if funcInfo == nil { + // Try to run the function through generate + for i := 0; i < co.RowCount; i++ { + row = append(row, generate(r, field.Function)) + } + } else { + // Generate function value + var err error + for i := 0; i < co.RowCount; i++ { + value, err = funcInfo.Generate(r, &field.Params, funcInfo) + if err != nil { + value = "" + } + + // Add value to row + row = append(row, anyToString(value)) + } + } + + // Add row to data + data = append(data, row) + } + + var result strings.Builder + + // Calculate column widths + colWidths := make([]int, len(data)) + for i, row := range data { + for _, value := range row { + width := len(value) + 5 + if width > colWidths[i] { + colWidths[i] = width + } + } + } + + // Append table rows to the string, excluding the entire row if the first value is empty + for i := 0; i < len(data[0]); i++ { + if !hasHeader && i == 0 { + continue // Skip the entire column if the first value is empty + } + + var resultRow strings.Builder + for j, row := range data { + resultRow.WriteString(fmt.Sprintf("%-*s", colWidths[j], row[i])) + } + + // Trim trailing spaces + result.WriteString(strings.TrimRight(resultRow.String(), " ")) + + // Only add new line if not the last row + if i != len(data[0])-1 { + result.WriteString("\n") + } + } + + return result.String(), nil +} + // Regex will generate a string based upon a RE2 syntax func Regex(regexStr string) string { return regex(globalFaker.Rand, regexStr) } // Regex will generate a string based upon a RE2 syntax func (f *Faker) Regex(regexStr string) string { return regex(f.Rand, regexStr) } -func regex(r *rand.Rand, regexStr string) string { +func regex(r *rand.Rand, regexStr string) (gen string) { re, err := syntax.Parse(regexStr, syntax.Perl) if err != nil { return "Could not parse regex string" } - return regexGenerate(r, re) + // Panic catch + defer func() { + if r := recover(); r != nil { + gen = fmt.Sprint(r) + return + + } + }() + + return regexGenerate(r, re, len(regexStr)*100) } -func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { +func regexGenerate(ra *rand.Rand, re *syntax.Regexp, limit int) string { + if limit <= 0 { + panic("Length limit reached when generating output") + } + op := re.Op switch op { case syntax.OpNoMatch: // matches no strings @@ -226,12 +357,12 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { case syntax.OpWordBoundary: // matches word boundary `\b` case syntax.OpNoWordBoundary: // matches word non-boundary `\B` case syntax.OpCapture: // capturing subexpression with index Cap, optional name Name - return regexGenerate(ra, re.Sub0[0]) + return regexGenerate(ra, re.Sub0[0], limit) case syntax.OpStar: // matches Sub[0] zero or more times var b strings.Builder for i := 0; i < number(ra, 0, 10); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() @@ -239,7 +370,7 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { var b strings.Builder for i := 0; i < number(ra, 1, 10); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() @@ -247,7 +378,7 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { var b strings.Builder for i := 0; i < number(ra, 0, 1); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() @@ -260,31 +391,31 @@ func regexGenerate(ra *rand.Rand, re *syntax.Regexp) string { } for i := 0; i < re.Min || i < (re.Min+count); i++ { for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } } return b.String() case syntax.OpConcat: // matches concatenation of Subs var b strings.Builder for _, rs := range re.Sub { - b.WriteString(regexGenerate(ra, rs)) + b.WriteString(regexGenerate(ra, rs, limit-b.Len())) } return b.String() case syntax.OpAlternate: // matches alternation of Subs - return regexGenerate(ra, re.Sub[number(ra, 0, len(re.Sub)-1)]) + return regexGenerate(ra, re.Sub[number(ra, 0, len(re.Sub)-1)], limit) } return "" } // Map will generate a random set of map data -func Map() map[string]interface{} { return mapFunc(globalFaker.Rand) } +func Map() map[string]any { return mapFunc(globalFaker.Rand) } // Map will generate a random set of map data -func (f *Faker) Map() map[string]interface{} { return mapFunc(f.Rand) } +func (f *Faker) Map() map[string]any { return mapFunc(f.Rand) } -func mapFunc(r *rand.Rand) map[string]interface{} { - m := map[string]interface{}{} +func mapFunc(r *rand.Rand) map[string]any { + m := map[string]any{} randWordType := func() string { s := randomString(r, []string{"lorem", "bs", "job", "name", "address"}) @@ -321,7 +452,7 @@ func mapFunc(r *rand.Rand) map[string]interface{} { case "slice": m[word(r)] = randSlice() case "map": - mm := map[string]interface{}{} + mm := map[string]any{} tt := randomString(r, []string{"string", "int", "float", "slice"}) switch tt { case "string": @@ -350,7 +481,7 @@ func addGenerateLookup() { Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "String value to generate from"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -358,23 +489,72 @@ func addGenerateLookup() { // Limit the length of the string passed if len(str) > 1000 { - return nil, errors.New("string length is too large. Limit to 1000 characters") + return nil, errors.New("string length is too large. limit to 1000 characters") } return generate(r, str), nil }, }) + AddFuncLookup("fixed_width", Info{ + Display: "Fixed Width", + Category: "generate", + Description: "Fixed width rows of output data based on input fields", + Example: `Name Email Password Age +Markus Moen sylvanmraz@murphy.net 6VlvH6qqXc7g 13 +Alayna Wuckert santinostanton@carroll.biz g7sLrS0gEwLO 46 +Lura Lockman zacherykuhic@feil.name S8gV7Z64KlHG 12`, + Output: "[]byte", + ContentType: "text/plain", + Params: []Param{ + {Field: "rowcount", Display: "Row Count", Type: "int", Default: "10", Description: "Number of rows"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields name, function and params"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + co := FixedWidthOptions{} + + rowCount, err := info.GetInt(m, "rowcount") + if err != nil { + return nil, err + } + + co.RowCount = rowCount + + fields, _ := info.GetStringArray(m, "fields") + + // Check to make sure fields has length + if len(fields) > 0 { + co.Fields = make([]Field, len(fields)) + for i, f := range fields { + // Unmarshal fields string into fields array + err = json.Unmarshal([]byte(f), &co.Fields[i]) + if err != nil { + return nil, err + } + } + } else { + return nil, errors.New("missing fields") + } + + out, err := fixeWidthFunc(r, &co) + if err != nil { + return nil, err + } + + return out, nil + }, + }) + AddFuncLookup("regex", Info{ Display: "Regex", Category: "generate", - Description: "Random string generated from regex RE2 syntax string", + Description: "Pattern-matching tool used in text processing to search and manipulate strings", Example: "[abcdef]{5} - affec", Output: "string", Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "Regex RE2 syntax string"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -382,7 +562,7 @@ func addGenerateLookup() { // Limit the length of the string passed if len(str) > 500 { - return nil, errors.New("string length is too large. Limit to 500 characters") + return nil, errors.New("string length is too large. limit to 500 characters") } return regex(r, str), nil @@ -392,11 +572,17 @@ func addGenerateLookup() { AddFuncLookup("map", Info{ Display: "Map", Category: "generate", - Description: "Random map of generated data", - Example: `map[consult:respond context:9285735]`, - Output: "map[string]interface{}", + Description: "Data structure that stores key-value pairs", + Example: `{ + "software": 7518355, + "that": ["despite", "pack", "whereas", "recently", "there", "anyone", "time", "read"], + "use": 683598, + "whom": "innovate", + "yourselves": 1987784 +}`, + Output: "map[string]any", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return mapFunc(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/hacker.go b/vendor/github.com/brianvoe/gofakeit/v6/hacker.go index 07ce8fdd8..393c558ec 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/hacker.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/hacker.go @@ -71,10 +71,10 @@ func addHackerLookup() { AddFuncLookup("hackerphrase", Info{ Display: "Hacker Phrase", Category: "hacker", - Description: "Random hacker phrase", + Description: "Informal jargon and slang used in the hacking and cybersecurity community", Example: "If we calculate the program, we can get to the AI pixel through the redundant XSS matrix!", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerPhrase(r), nil }, }) @@ -82,10 +82,10 @@ func addHackerLookup() { AddFuncLookup("hackerabbreviation", Info{ Display: "Hacker Abbreviation", Category: "hacker", - Description: "Random hacker abbreviation", + Description: "Abbreviations and acronyms commonly used in the hacking and cybersecurity community", Example: "ADP", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerAbbreviation(r), nil }, }) @@ -93,10 +93,10 @@ func addHackerLookup() { AddFuncLookup("hackeradjective", Info{ Display: "Hacker Adjective", Category: "hacker", - Description: "Random hacker adjective", + Description: "Adjectives describing terms often associated with hackers and cybersecurity experts", Example: "wireless", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerAdjective(r), nil }, }) @@ -104,10 +104,10 @@ func addHackerLookup() { AddFuncLookup("hackernoun", Info{ Display: "Hacker Noun", Category: "hacker", - Description: "Random hacker noun", + Description: "Noun representing an element, tool, or concept within the realm of hacking and cybersecurity", Example: "driver", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerNoun(r), nil }, }) @@ -115,10 +115,10 @@ func addHackerLookup() { AddFuncLookup("hackerverb", Info{ Display: "Hacker Verb", Category: "hacker", - Description: "Random hacker verb", + Description: "Verbs associated with actions and activities in the field of hacking and cybersecurity", Example: "synthesize", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackerVerb(r), nil }, }) @@ -126,10 +126,10 @@ func addHackerLookup() { AddFuncLookup("hackeringverb", Info{ Display: "Hackering Verb", Category: "hacker", - Description: "Random hackering verb", + Description: "Verb describing actions and activities related to hacking, often involving computer systems and security", Example: "connecting", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hackeringVerb(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/helpers.go b/vendor/github.com/brianvoe/gofakeit/v6/helpers.go index d0212f97e..3dcf849b7 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/helpers.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/helpers.go @@ -3,6 +3,8 @@ package gofakeit import ( crand "crypto/rand" "encoding/binary" + "encoding/json" + "fmt" "math" "math/rand" "reflect" @@ -15,7 +17,8 @@ import ( const lowerStr = "abcdefghijklmnopqrstuvwxyz" const upperStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" const numericStr = "0123456789" -const specialStr = "!@#$%&*+-_=?:;,.|(){}<>" +const specialStr = "@#$%&?|!(){}<>=*+-_:;,." +const specialSafeStr = "@#$&?!-_*." const spaceStr = " " const allStr = lowerStr + upperStr + numericStr + specialStr + spaceStr const vowels = "aeiou" @@ -223,7 +226,7 @@ func equalSliceInt(a, b []int) bool { return true } -func equalSliceInterface(a, b []interface{}) bool { +func equalSliceInterface(a, b []any) bool { sizeA, sizeB := len(a), len(b) if sizeA != sizeB { return false @@ -246,6 +249,28 @@ func stringInSlice(a string, list []string) bool { return false } +func anyToString(a any) string { + if a == nil { + return "" + } + + // If it's a slice of bytes or struct, unmarshal it into an interface + if bytes, ok := a.([]byte); ok { + return string(bytes) + } + + // If it's a struct, map, or slice, convert to JSON + switch reflect.TypeOf(a).Kind() { + case reflect.Struct, reflect.Map, reflect.Slice: + b, err := json.Marshal(a) + if err == nil { + return string(b) + } + } + + return fmt.Sprintf("%v", a) +} + // Title returns a copy of the string s with all Unicode letters that begin words // mapped to their Unicode title case func title(s string) string { diff --git a/vendor/github.com/brianvoe/gofakeit/v6/hipster.go b/vendor/github.com/brianvoe/gofakeit/v6/hipster.go index 4421f5c5d..0369f17e1 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/hipster.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/hipster.go @@ -49,10 +49,10 @@ func addHipsterLookup() { AddFuncLookup("hipsterword", Info{ Display: "Hipster Word", Category: "hipster", - Description: "Random hipster word", + Description: "Trendy and unconventional vocabulary used by hipsters to express unique cultural preferences", Example: "microdosing", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hipsterWord(r), nil }, }) @@ -60,13 +60,13 @@ func addHipsterLookup() { AddFuncLookup("hipstersentence", Info{ Display: "Hipster Sentence", Category: "hipster", - Description: "Random hipster sentence", + Description: "Sentence showcasing the use of trendy and unconventional vocabulary associated with hipster culture", Example: "Microdosing roof chia echo pickled.", Output: "string", Params: []Param{ {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { wordCount, err := info.GetInt(m, "wordcount") if err != nil { return nil, err @@ -82,16 +82,20 @@ func addHipsterLookup() { AddFuncLookup("hipsterparagraph", Info{ Display: "Hipster Paragraph", Category: "hipster", - Description: "Random hipster paragraph", - Example: "Microdosing roof chia echo pickled meditation cold-pressed raw denim fingerstache normcore sriracha pork belly. Wolf try-hard pop-up blog tilde hashtag health butcher waistcoat paleo portland vinegar. Microdosing sartorial blue bottle slow-carb freegan five dollar toast you probably haven't heard of them asymmetrical chia farm-to-table narwhal banjo. Gluten-free blog authentic literally synth vinyl meh ethical health fixie banh mi Yuccie. Try-hard drinking squid seitan cray VHS echo chillwave hammock kombucha food truck sustainable.
Pug bushwick hella tote bag cliche direct trade waistcoat yr waistcoat knausgaard pour-over master. Pitchfork jean shorts franzen flexitarian distillery hella meggings austin knausgaard crucifix wolf heirloom. Crucifix food truck you probably haven't heard of them trust fund fixie gentrify pitchfork stumptown mlkshk umami chambray blue bottle. 3 wolf moon swag +1 biodiesel knausgaard semiotics taxidermy meh artisan hoodie +1 blue bottle. Fashion axe forage mixtape Thundercats pork belly whatever 90's beard selfies chambray cred mlkshk.
Shabby chic typewriter VHS readymade lo-fi bitters PBR&B gentrify lomo raw denim freegan put a bird on it. Raw denim cliche dreamcatcher pug fixie park trust fund migas fingerstache sriracha +1 mustache. Tilde shoreditch kickstarter franzen dreamcatcher green juice mustache neutra polaroid stumptown organic schlitz. Flexitarian ramps chicharrones kogi lo-fi mustache tilde forage street church-key williamsburg taxidermy. Chia mustache plaid mumblecore squid slow-carb disrupt Thundercats goth shoreditch master direct trade.", - Output: "string", + Description: "Paragraph showcasing the use of trendy and unconventional vocabulary associated with hipster culture", + Example: `Microdosing roof chia echo pickled meditation cold-pressed raw denim fingerstache normcore sriracha pork belly. Wolf try-hard pop-up blog tilde hashtag health butcher waistcoat paleo portland vinegar. Microdosing sartorial blue bottle slow-carb freegan five dollar toast you probably haven't heard of them asymmetrical chia farm-to-table narwhal banjo. Gluten-free blog authentic literally synth vinyl meh ethical health fixie banh mi Yuccie. Try-hard drinking squid seitan cray VHS echo chillwave hammock kombucha food truck sustainable. + +Pug bushwick hella tote bag cliche direct trade waistcoat yr waistcoat knausgaard pour-over master. Pitchfork jean shorts franzen flexitarian distillery hella meggings austin knausgaard crucifix wolf heirloom. Crucifix food truck you probably haven't heard of them trust fund fixie gentrify pitchfork stumptown mlkshk umami chambray blue bottle. 3 wolf moon swag +1 biodiesel knausgaard semiotics taxidermy meh artisan hoodie +1 blue bottle. Fashion axe forage mixtape Thundercats pork belly whatever 90's beard selfies chambray cred mlkshk. + +Shabby chic typewriter VHS readymade lo-fi bitters PBR&B gentrify lomo raw denim freegan put a bird on it. Raw denim cliche dreamcatcher pug fixie park trust fund migas fingerstache sriracha +1 mustache. Tilde shoreditch kickstarter franzen dreamcatcher green juice mustache neutra polaroid stumptown organic schlitz. Flexitarian ramps chicharrones kogi lo-fi mustache tilde forage street church-key williamsburg taxidermy. Chia mustache plaid mumblecore squid slow-carb disrupt Thundercats goth shoreditch master direct trade.`, + Output: "string", Params: []Param{ {Field: "paragraphcount", Display: "Paragraph Count", Type: "int", Default: "2", Description: "Number of paragraphs"}, {Field: "sentencecount", Display: "Sentence Count", Type: "int", Default: "2", Description: "Number of sentences in a paragraph"}, {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, {Field: "paragraphseparator", Display: "Paragraph Separator", Type: "string", Default: "
", Description: "String value to add between paragraphs"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { paragraphCount, err := info.GetInt(m, "paragraphcount") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/html.go b/vendor/github.com/brianvoe/gofakeit/v6/html.go new file mode 100644 index 000000000..a047617ab --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/html.go @@ -0,0 +1,175 @@ +package gofakeit + +import ( + "errors" + "math/rand" + "strconv" + "strings" + + "github.com/brianvoe/gofakeit/v6/data" +) + +// InputName will return a random input field name +func InputName() string { + return inputName(globalFaker.Rand) +} + +// InputName will return a random input field name +func (f *Faker) InputName() string { + return inputName(f.Rand) +} + +func inputName(r *rand.Rand) string { + return getRandValue(r, []string{"html", "input_name"}) +} + +type SVGOptions struct { + Height int + Width int + Type string + Colors []string +} + +// Generate a random svg generator +func Svg(options *SVGOptions) string { return svg(globalFaker.Rand, options) } + +// Generate a random svg generator +func (f *Faker) Svg(options *SVGOptions) string { return svg(f.Rand, options) } + +func svg(r *rand.Rand, options *SVGOptions) string { + // If options is nil, set it to empty struct + if options == nil { + options = &SVGOptions{} + } + + // If options height and weight is not set, set it to random number between 100 and 500 + if options.Width == 0 { + options.Width = number(r, 100, 500) + } + widthStr := strconv.Itoa(options.Width) + if options.Height == 0 { + options.Height = number(r, 100, 500) + } + heightStr := strconv.Itoa(options.Height) + + // Check if type is set, if not set to random type + if options.Type == "" { + options.Type = randomString(r, data.GetSubData("html", "svg")) + } + + // If the colors are not set, set it to a set of nice colors + if len(options.Colors) == 0 { + options.Colors = niceColors(r) + } + + // Start svg string + svgStr := `` + + // Add a rect for the background + svgStr += `` + + // Add a random number of shapes + for i := 0; i < number(r, 10, 20); i++ { + // Add a random shape + switch options.Type { + case "rect": + svgStr += `` + case "circle": + svgStr += `` + case "ellipse": + svgStr += `` + case "line": + svgStr += `` + case "polyline": + svgStr += `` + case "polygon": + svgStr += `` + } + } + + // End svg string + svgStr += `` + + return svgStr +} + +func addHtmlLookup() { + AddFuncLookup("inputname", Info{ + Display: "Input Name", + Category: "html", + Description: "Attribute used to define the name of an input element in web forms", + Example: "first_name", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return inputName(r), nil + }, + }) + + AddFuncLookup("svg", Info{ + Display: "Image SVG", + Category: "html", + Description: "Scalable Vector Graphics used to display vector images in web content", + Example: ` + + +`, + Output: "string", + ContentType: "image/svg+xml", + Params: []Param{ + {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Width in px"}, + {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Height in px"}, + {Field: "type", Display: "Type", Type: "string", Optional: true, Options: data.GetSubData("html", "svg"), Description: "Sub child element type"}, + {Field: "colors", Display: "Colors", Type: "[]string", Optional: true, Description: "Hex or RGB array of colors to use"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + // Setup new options + options := SVGOptions{} + var err error + + options.Width, err = info.GetInt(m, "width") + if err != nil { + return nil, err + } + if options.Width < 10 || options.Width >= 1000 { + return nil, errors.New("invalid image width, must be greater than 10, less than 1000") + } + + options.Height, err = info.GetInt(m, "height") + if err != nil { + return nil, err + } + if options.Height < 10 || options.Height >= 1000 { + return nil, errors.New("invalid image height, must be greater than 10, less than 1000") + } + + options.Type, err = info.GetString(m, "type") + svgData := data.GetSubData("html", "svg") + if err != nil { + return nil, err + } + + // If type is empty, set with random type + if options.Type == "" { + options.Type = randomString(r, svgData) + } + + // If not in date html svg type array, return error + if !stringInSlice(options.Type, svgData) { + return nil, errors.New("invalid svg type, must be one of " + strings.Join(svgData, ",")) + } + + // Get colors + options.Colors, err = info.GetStringArray(m, "colors") + if err != nil { + return nil, err + } + + // If colors is empty, set with random colors + if len(options.Colors) == 0 { + options.Colors = niceColors(r) + } + + return svg(r, &options), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/image.go b/vendor/github.com/brianvoe/gofakeit/v6/image.go index a820a4222..e7c40dd87 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/image.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/image.go @@ -71,14 +71,14 @@ func addImageLookup() { AddFuncLookup("imageurl", Info{ Display: "Image URL", Category: "image", - Description: "Random image url", + Description: "Web address pointing to an image file that can be accessed and displayed online", Example: "https://picsum.photos/500/500", Output: "string", Params: []Param{ {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Image width in px"}, {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Image height in px"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { width, err := info.GetInt(m, "width") if err != nil { return nil, err @@ -102,7 +102,7 @@ func addImageLookup() { AddFuncLookup("imagejpeg", Info{ Display: "Image JPEG", Category: "image", - Description: "Random jpeg image", + Description: "Image file format known for its efficient compression and compatibility", Example: "file.jpeg - bytes", Output: "[]byte", ContentType: "image/jpeg", @@ -110,7 +110,7 @@ func addImageLookup() { {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Image width in px"}, {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Image height in px"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { width, err := info.GetInt(m, "width") if err != nil { return nil, err @@ -134,7 +134,7 @@ func addImageLookup() { AddFuncLookup("imagepng", Info{ Display: "Image PNG", Category: "image", - Description: "Random png image", + Description: "Image file format known for its lossless compression and support for transparency", Example: "file.png - bytes", Output: "[]byte", ContentType: "image/png", @@ -142,7 +142,7 @@ func addImageLookup() { {Field: "width", Display: "Width", Type: "int", Default: "500", Description: "Image width in px"}, {Field: "height", Display: "Height", Type: "int", Default: "500", Description: "Image height in px"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { width, err := info.GetInt(m, "width") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/internet.go b/vendor/github.com/brianvoe/gofakeit/v6/internet.go index 1cc207b37..a0fcd9bb4 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/internet.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/internet.go @@ -266,10 +266,10 @@ func addInternetLookup() { AddFuncLookup("url", Info{ Display: "URL", Category: "internet", - Description: "Random url", + Description: "Web address that specifies the location of a resource on the internet", Example: "http://www.principalproductize.biz/target", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return url(r), nil }, }) @@ -277,10 +277,10 @@ func addInternetLookup() { AddFuncLookup("domainname", Info{ Display: "Domain Name", Category: "internet", - Description: "Random domain name", + Description: "Human-readable web address used to identify websites on the internet", Example: "centraltarget.biz", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return domainName(r), nil }, }) @@ -288,10 +288,10 @@ func addInternetLookup() { AddFuncLookup("domainsuffix", Info{ Display: "Domain Suffix", Category: "internet", - Description: "Random domain suffix", + Description: "The part of a domain name that comes after the last dot, indicating its type or purpose", Example: "org", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return domainSuffix(r), nil }, }) @@ -299,10 +299,10 @@ func addInternetLookup() { AddFuncLookup("ipv4address", Info{ Display: "IPv4 Address", Category: "internet", - Description: "Random ip address v4", + Description: "Numerical label assigned to devices on a network for identification and communication", Example: "222.83.191.222", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return ipv4Address(r), nil }, }) @@ -310,10 +310,10 @@ func addInternetLookup() { AddFuncLookup("ipv6address", Info{ Display: "IPv6 Address", Category: "internet", - Description: "Random ip address v6", + Description: "Numerical label assigned to devices on a network, providing a larger address space than IPv4 for internet communication", Example: "2001:cafe:8898:ee17:bc35:9064:5866:d019", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return ipv6Address(r), nil }, }) @@ -321,10 +321,10 @@ func addInternetLookup() { AddFuncLookup("httpmethod", Info{ Display: "HTTP Method", Category: "internet", - Description: "Random http method", + Description: "Verb used in HTTP requests to specify the desired action to be performed on a resource", Example: "HEAD", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpMethod(r), nil }, }) @@ -332,10 +332,10 @@ func addInternetLookup() { AddFuncLookup("loglevel", Info{ Display: "Log Level", Category: "internet", - Description: "Random log level", + Description: "Classification used in logging to indicate the severity or priority of a log entry", Example: "error", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return logLevel(r, ""), nil }, }) @@ -343,10 +343,10 @@ func addInternetLookup() { AddFuncLookup("useragent", Info{ Display: "User Agent", Category: "internet", - Description: "Random browser user agent", + Description: "String sent by a web browser to identify itself when requesting web content", Example: "Mozilla/5.0 (Windows NT 5.0) AppleWebKit/5362 (KHTML, like Gecko) Chrome/37.0.834.0 Mobile Safari/5362", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return userAgent(r), nil }, }) @@ -354,10 +354,10 @@ func addInternetLookup() { AddFuncLookup("chromeuseragent", Info{ Display: "Chrome User Agent", Category: "internet", - Description: "Random chrome user agent", + Description: "The specific identification string sent by the Google Chrome web browser when making requests on the internet", Example: "Mozilla/5.0 (X11; Linux i686) AppleWebKit/5312 (KHTML, like Gecko) Chrome/39.0.836.0 Mobile Safari/5312", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return chromeUserAgent(r), nil }, }) @@ -365,10 +365,10 @@ func addInternetLookup() { AddFuncLookup("firefoxuseragent", Info{ Display: "Firefox User Agent", Category: "internet", - Description: "Random browser user agent", + Description: "The specific identification string sent by the Firefox web browser when making requests on the internet", Example: "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_8_3 rv:7.0) Gecko/1900-07-01 Firefox/37.0", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return firefoxUserAgent(r), nil }, }) @@ -376,10 +376,10 @@ func addInternetLookup() { AddFuncLookup("operauseragent", Info{ Display: "Opera User Agent", Category: "internet", - Description: "Random browser user agent", + Description: "The specific identification string sent by the Opera web browser when making requests on the internet", Example: "Opera/8.39 (Macintosh; U; PPC Mac OS X 10_8_7; en-US) Presto/2.9.335 Version/10.00", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return operaUserAgent(r), nil }, }) @@ -387,10 +387,10 @@ func addInternetLookup() { AddFuncLookup("safariuseragent", Info{ Display: "Safari User Agent", Category: "internet", - Description: "Random safari user agent", + Description: "The specific identification string sent by the Safari web browser when making requests on the internet", Example: "Mozilla/5.0 (iPad; CPU OS 8_3_2 like Mac OS X; en-US) AppleWebKit/531.15.6 (KHTML, like Gecko) Version/4.0.5 Mobile/8B120 Safari/6531.15.6", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return safariUserAgent(r), nil }, }) @@ -401,7 +401,7 @@ func addInternetLookup() { Description: "Random http status code", Example: "200", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpStatusCode(r), nil }, }) @@ -409,10 +409,10 @@ func addInternetLookup() { AddFuncLookup("httpstatuscodesimple", Info{ Display: "HTTP Status Code Simple", Category: "internet", - Description: "Random http status code within more general usage codes", + Description: "Three-digit number returned by a web server to indicate the outcome of an HTTP request", Example: "404", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpStatusCodeSimple(r), nil }, }) @@ -420,11 +420,22 @@ func addInternetLookup() { AddFuncLookup("httpversion", Info{ Display: "HTTP Version", Category: "internet", - Description: "Random http version", + Description: "Number indicating the version of the HTTP protocol used for communication between a client and a server", Example: "HTTP/1.1", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return httpVersion(r), nil }, }) + + AddFuncLookup("macaddress", Info{ + Display: "MAC Address", + Category: "internet", + Description: "Unique identifier assigned to network interfaces, often used in Ethernet networks", + Example: "cb:ce:06:94:22:e9", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return macAddress(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/json.go b/vendor/github.com/brianvoe/gofakeit/v6/json.go index b284fed61..8edf5b458 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/json.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/json.go @@ -4,20 +4,23 @@ import ( "bytes" "encoding/json" "errors" + "fmt" "math/rand" + "reflect" + "strconv" ) // JSONOptions defines values needed for json generation type JSONOptions struct { - Type string `json:"type" xml:"type"` // array or object - RowCount int `json:"row_count" xml:"row_count"` - Fields []Field `json:"fields" xml:"fields"` + Type string `json:"type" xml:"type" fake:"{randomstring:[array,object]}"` // array or object + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` Indent bool `json:"indent" xml:"indent"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } type jsonKeyVal struct { Key string - Value interface{} + Value any } type jsonOrderedKeyVal []*jsonKeyVal @@ -54,14 +57,24 @@ func (okv jsonOrderedKeyVal) MarshalJSON() ([]byte, error) { return buf.Bytes(), nil } -// JSON generates an object or an array of objects in json format -func JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(globalFaker.Rand, jo) } +// JSON generates an object or an array of objects in json format. +// A nil JSONOptions returns a randomly structured JSON. +func JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(globalFaker, jo) } -// JSON generates an object or an array of objects in json format -func (f *Faker) JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(f.Rand, jo) } +// JSON generates an object or an array of objects in json format. +// A nil JSONOptions returns a randomly structured JSON. +func (f *Faker) JSON(jo *JSONOptions) ([]byte, error) { return jsonFunc(f, jo) } // JSON generates an object or an array of objects in json format -func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { +func jsonFunc(f *Faker, jo *JSONOptions) ([]byte, error) { + if jo == nil { + // We didn't get a JSONOptions, so create a new random one + err := f.Struct(&jo) + if err != nil { + return nil, err + } + } + // Check to make sure they passed in a type if jo.Type != "array" && jo.Type != "object" { return nil, errors.New("invalid type, must be array or object") @@ -74,7 +87,7 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { if jo.Type == "object" { v := make(jsonOrderedKeyVal, len(jo.Fields)) - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for i, field := range jo.Fields { if field.Function == "autoincrement" { // Object only has one @@ -89,14 +102,14 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { } // Call function value - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } if _, ok := value.([]byte); ok { // If it's a slice, unmarshal it into an interface - var val interface{} + var val any err := json.Unmarshal(value.([]byte), &val) if err != nil { return nil, err @@ -129,7 +142,7 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { for i := 0; i < int(jo.RowCount); i++ { vr := make(jsonOrderedKeyVal, len(jo.Fields)) - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for ii, field := range jo.Fields { if field.Function == "autoincrement" { vr[ii] = &jsonKeyVal{Key: field.Name, Value: i + 1} // +1 because index starts with 0 @@ -143,14 +156,14 @@ func jsonFunc(r *rand.Rand, jo *JSONOptions) ([]byte, error) { } // Call function value - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } if _, ok := value.([]byte); ok { // If it's a slice, unmarshal it into an interface - var val interface{} + var val any err := json.Unmarshal(value.([]byte), &val) if err != nil { return nil, err @@ -181,21 +194,21 @@ func addFileJSONLookup() { AddFuncLookup("json", Info{ Display: "JSON", Category: "file", - Description: "Generates an object or an array of objects in json format", + Description: "Format for structured data interchange used in programming, returns an object or an array of objects", Example: `[ - { "id": 1, "first_name": "Markus", "last_name": "Moen" }, - { "id": 2, "first_name": "Alayna", "last_name": "Wuckert" }, - { "id": 3, "first_name": "Lura", "last_name": "Lockman" } + { "first_name": "Markus", "last_name": "Moen", "password": "Dc0VYXjkWABx" }, + { "first_name": "Osborne", "last_name": "Hilll", "password": "XPJ9OVNbs5lm" }, + { "first_name": "Mertie", "last_name": "Halvorson", "password": "eyl3bhwfV8wA" } ]`, Output: "[]byte", ContentType: "application/json", Params: []Param{ {Field: "type", Display: "Type", Type: "string", Default: "object", Options: []string{"object", "array"}, Description: "Type of JSON, object or array"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows in JSON array"}, - {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, {Field: "indent", Display: "Indent", Type: "bool", Default: "false", Description: "Whether or not to add indents and newlines"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { jo := JSONOptions{} typ, err := info.GetString(m, "type") @@ -210,6 +223,12 @@ func addFileJSONLookup() { } jo.RowCount = rowcount + indent, err := info.GetBool(m, "indent") + if err != nil { + return nil, err + } + jo.Indent = indent + fieldsStr, err := info.GetStringArray(m, "fields") if err != nil { return nil, err @@ -228,13 +247,89 @@ func addFileJSONLookup() { } } - indent, err := info.GetBool(m, "indent") - if err != nil { - return nil, err - } - jo.Indent = indent - - return jsonFunc(r, &jo) + f := &Faker{Rand: r} + return jsonFunc(f, &jo) }, }) } + +// encoding/json.RawMessage is a special case of []byte +// it cannot be handled as a reflect.Array/reflect.Slice +// because it needs additional structure in the output +func rJsonRawMessage(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { + b, err := f.JSON(nil) + if err != nil { + return err + } + + v.SetBytes(b) + return nil +} + +// encoding/json.Number is a special case of string +// that represents a JSON number literal. +// It cannot be handled as a string because it needs to +// represent an integer or a floating-point number. +func rJsonNumber(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { + var ret json.Number + + var numberType string + + if tag == "" { + numberType = f.RandomString([]string{"int", "float"}) + + switch numberType { + case "int": + retInt := f.Int16() + ret = json.Number(strconv.Itoa(int(retInt))) + case "float": + retFloat := f.Float64() + ret = json.Number(strconv.FormatFloat(retFloat, 'f', -1, 64)) + } + } else { + fName, fParams := parseNameAndParamsFromTag(tag) + info := GetFuncLookup(fName) + if info == nil { + return fmt.Errorf("invalid function, %s does not exist", fName) + } + + // Parse map params + mapParams := parseMapParams(info, fParams) + + valueIface, err := info.Generate(f.Rand, mapParams, info) + if err != nil { + return err + } + + switch value := valueIface.(type) { + case int: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int8: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int16: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int32: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case int64: + ret = json.Number(strconv.FormatInt(int64(value), 10)) + case uint: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint8: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint16: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint32: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case uint64: + ret = json.Number(strconv.FormatUint(uint64(value), 10)) + case float32: + ret = json.Number(strconv.FormatFloat(float64(value), 'f', -1, 64)) + case float64: + ret = json.Number(strconv.FormatFloat(float64(value), 'f', -1, 64)) + default: + return fmt.Errorf("invalid type, %s is not a valid type for json.Number", reflect.TypeOf(value)) + } + } + v.Set(reflect.ValueOf(ret)) + return nil +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/languages.go b/vendor/github.com/brianvoe/gofakeit/v6/languages.go index bd634d570..43e0b877f 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/languages.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/languages.go @@ -48,10 +48,10 @@ func addLanguagesLookup() { AddFuncLookup("language", Info{ Display: "Language", Category: "language", - Description: "Random language", + Description: "System of communication using symbols, words, and grammar to convey meaning between individuals", Example: "Kazakh", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return language(r), nil }, }) @@ -59,10 +59,10 @@ func addLanguagesLookup() { AddFuncLookup("languageabbreviation", Info{ Display: "Language Abbreviation", Category: "language", - Description: "Random abbreviated language", + Description: "Shortened form of a language's name", Example: "kk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return languageAbbreviation(r), nil }, }) @@ -70,10 +70,10 @@ func addLanguagesLookup() { AddFuncLookup("languagebcp", Info{ Display: "Language BCP", Category: "language", - Description: "Random language BCP (Best Current Practices)", + Description: "Set of guidelines and standards for identifying and representing languages in computing and internet protocols", Example: "en-US", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return languageBCP(r), nil }, }) @@ -81,10 +81,10 @@ func addLanguagesLookup() { AddFuncLookup("programminglanguage", Info{ Display: "Programming Language", Category: "language", - Description: "Random programming language", + Description: "Formal system of instructions used to create software and perform computational tasks", Example: "Go", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return programmingLanguage(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/lookup.go b/vendor/github.com/brianvoe/gofakeit/v6/lookup.go index 633053d1c..9bb9e9d82 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/lookup.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/lookup.go @@ -21,14 +21,15 @@ type MapParamsValue []string // Info structures fields to better break down what each one generates type Info struct { - Display string `json:"display"` - Category string `json:"category"` - Description string `json:"description"` - Example string `json:"example"` - Output string `json:"output"` - ContentType string `json:"content_type"` - Params []Param `json:"params"` - Generate func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) `json:"-"` + Display string `json:"display"` + Category string `json:"category"` + Description string `json:"description"` + Example string `json:"example"` + Output string `json:"output"` + ContentType string `json:"content_type"` + Params []Param `json:"params"` + Any any `json:"any"` + Generate func(r *rand.Rand, m *MapParams, info *Info) (any, error) `json:"-"` } // Param is a breakdown of param requirements and type definition @@ -53,49 +54,74 @@ func init() { initLookup() } // init will add all the functions to MapLookups func initLookup() { - addAuthLookup() addAddressLookup() + addAnimalLookup() + addAppLookup() + addAuthLookup() addBeerLookup() + addBookLookup() addCarLookup() - addPersonLookup() - addWordGeneralLookup() - addWordNounLookup() - addWordVerbLookup() - addWordAdverbLookup() - addWordPrepositionLookup() - addWordAdjectiveLookup() - addWordPronounLookup() - addWordConnectiveLookup() - addWordPhraseLookup() - addWordSentenceLookup() - addWordGrammerLookup() - addLoremLookup() - addGenerateLookup() - addMiscLookup() + addCelebrityLookup() addColorLookup() - addInternetLookup() - addDateTimeLookup() - addPaymentLookup() addCompanyLookup() - addHackerLookup() - addHipsterLookup() - addLanguagesLookup() - addFileLookup() + addDatabaseSQLLookup() + addDateTimeLookup() + addEmojiLookup() + addErrorLookup() + addFileCSVLookup() addFileJSONLookup() + addFileLookup() addFileXMLLookup() - addFileCSVLookup() - addEmojiLookup() + addFinanceLookup() + addFoodLookup() + addGameLookup() + addGenerateLookup() + addHackerLookup() + addHipsterLookup() + addHtmlLookup() addImageLookup() + addInternetLookup() + addLanguagesLookup() + addLoremLookup() + addMinecraftLookup() + addMiscLookup() + addMovieLookup() addNumberLookup() + addPaymentLookup() + addPersonLookup() + addProductLookup() + addSchoolLookup() addStringLookup() - addAnimalLookup() - addGameLookup() - addFoodLookup() - addAppLookup() + addTemplateLookup() addWeightedLookup() - addMinecraftLookup() - addCelebrityLookup() - addDatabaseSQLLookup() + addWordAdjectiveLookup() + addWordAdverbLookup() + addWordConnectiveLookup() + addWordGeneralLookup() + addWordGrammerLookup() + addWordNounLookup() + addWordPhraseLookup() + addWordPrepositionLookup() + addWordPronounLookup() + addWordSentenceLookup() + addWordVerbLookup() + addWordCommentLookup() + addWordMiscLookup() +} + +// internalFuncLookups is the internal map array with mapping to all available data +var internalFuncLookups map[string]Info = map[string]Info{ + "fields": { + Description: "Example fields for generating csv, json, xml, etc", + Output: "gofakeit.Field", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + function, _ := GetRandomSimpleFunc(r) + return Field{ + Name: function, + Function: function, + }, nil + }, + }, } // NewMapParams will create a new MapParams @@ -133,7 +159,7 @@ func (m *MapParamsValue) UnmarshalJSON(data []byte) error { // check if the data is an array // if so, marshal it into m if data[0] == '[' { - var values []interface{} + var values []any err := json.Unmarshal(data, &values) if err != nil { return err @@ -157,7 +183,7 @@ func (m *MapParamsValue) UnmarshalJSON(data []byte) error { } // if not, then convert into a string and add it to m - var s interface{} + var s any if err := json.Unmarshal(data, &s); err != nil { return err } @@ -166,6 +192,23 @@ func (m *MapParamsValue) UnmarshalJSON(data []byte) error { return nil } +func GetRandomSimpleFunc(r *rand.Rand) (string, Info) { + // Loop through all the functions and add them to a slice + var keys []string + for k, info := range FuncLookups { + // Only grab simple functions + if info.Params == nil { + keys = append(keys, k) + } + } + + // Randomly grab a function from the slice + randomKey := randomString(r, keys) + + // Return the function name and info + return randomKey, FuncLookups[randomKey] +} + // AddFuncLookup takes a field and adds it to map func AddFuncLookup(functionName string, info Info) { if FuncLookups == nil { @@ -184,12 +227,21 @@ func AddFuncLookup(functionName string, info Info) { // GetFuncLookup will lookup func GetFuncLookup(functionName string) *Info { - info, ok := FuncLookups[functionName] - if !ok { - return nil + var info Info + var ok bool + + // Check internal functions first + info, ok = internalFuncLookups[functionName] + if ok { + return &info + } + + info, ok = FuncLookups[functionName] + if ok { + return &info } - return &info + return nil } // RemoveFuncLookup will remove a function from lookup @@ -204,6 +256,57 @@ func RemoveFuncLookup(functionName string) { lockFuncLookups.Unlock() } +// GetAny will retrieve Any field from Info +func (i *Info) GetAny(m *MapParams, field string) (any, error) { + _, value, err := i.GetField(m, field) + if err != nil { + return nil, err + } + + var anyValue any + + // Try to convert to int + valueInt, err := strconv.ParseInt(value[0], 10, 64) + if err == nil { + return int(valueInt), nil + } + + // Try to convert to float + valueFloat, err := strconv.ParseFloat(value[0], 64) + if err == nil { + return valueFloat, nil + } + + // Try to convert to boolean + valueBool, err := strconv.ParseBool(value[0]) + if err == nil { + return valueBool, nil + } + + err = json.Unmarshal([]byte(value[0]), &anyValue) + if err == nil { + return valueBool, nil + } + + return value[0], nil +} + +// GetMap will retrieve map[string]any field from data +func (i *Info) GetMap(m *MapParams, field string) (map[string]any, error) { + _, value, err := i.GetField(m, field) + if err != nil { + return nil, err + } + + var mapValue map[string]any + err = json.Unmarshal([]byte(value[0]), &mapValue) + if err != nil { + return nil, fmt.Errorf("%s field could not parse to map[string]any", field) + } + + return mapValue, nil +} + // GetField will retrieve field from data func (i *Info) GetField(m *MapParams, field string) (*Param, []string, error) { // Get param diff --git a/vendor/github.com/brianvoe/gofakeit/v6/lorem.go b/vendor/github.com/brianvoe/gofakeit/v6/lorem.go index 59290c121..bf11bce7c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/lorem.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/lorem.go @@ -45,10 +45,10 @@ func addLoremLookup() { AddFuncLookup("loremipsumword", Info{ Display: "Lorem Ipsum Word", Category: "word", - Description: "Random lorem ipsum word", + Description: "Word of the Lorem Ipsum placeholder text used in design and publishing", Example: "quia", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return loremIpsumWord(r), nil }, }) @@ -56,13 +56,13 @@ func addLoremLookup() { AddFuncLookup("loremipsumsentence", Info{ Display: "Lorem Ipsum Sentence", Category: "word", - Description: "Random lorem ipsum sentence", + Description: "Sentence of the Lorem Ipsum placeholder text used in design and publishing", Example: "Quia quae repellat consequatur quidem.", Output: "string", Params: []Param{ {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { wordCount, err := info.GetInt(m, "wordcount") if err != nil { return nil, err @@ -78,16 +78,20 @@ func addLoremLookup() { AddFuncLookup("loremipsumparagraph", Info{ Display: "Lorem Ipsum Paragraph", Category: "word", - Description: "Random lorem ipsum paragraph", - Example: "Quia quae repellat consequatur quidem nisi quo qui voluptatum accusantium quisquam amet. Quas et ut non dolorem ipsam aut enim assumenda mollitia harum ut. Dicta similique veniam nulla voluptas at excepturi non ad maxime at non. Eaque hic repellat praesentium voluptatem qui consequuntur dolor iusto autem velit aut. Fugit tempore exercitationem harum consequatur voluptatum modi minima aut eaque et et.
Aut ea voluptatem dignissimos expedita odit tempore quod aut beatae ipsam iste. Minus voluptatibus dolorem maiores eius sed nihil vel enim odio voluptatem accusamus. Natus quibusdam temporibus tenetur cumque sint necessitatibus dolorem ex ducimus iusto ex. Voluptatem neque dicta explicabo officiis et ducimus sit ut ut praesentium pariatur. Illum molestias nisi at dolore ut voluptatem accusantium et fugiat et ut.
Explicabo incidunt reprehenderit non quia dignissimos recusandae vitae soluta quia et quia. Aut veniam voluptas consequatur placeat sapiente non eveniet voluptatibus magni velit eum. Nobis vel repellendus sed est qui autem laudantium quidem quam ullam consequatur. Aut iusto ut commodi similique quae voluptatem atque qui fugiat eum aut. Quis distinctio consequatur voluptatem vel aliquid aut laborum facere officiis iure tempora.", - Output: "string", + Description: "Paragraph of the Lorem Ipsum placeholder text used in design and publishing", + Example: `Quia quae repellat consequatur quidem nisi quo qui voluptatum accusantium quisquam amet. Quas et ut non dolorem ipsam aut enim assumenda mollitia harum ut. Dicta similique veniam nulla voluptas at excepturi non ad maxime at non. Eaque hic repellat praesentium voluptatem qui consequuntur dolor iusto autem velit aut. Fugit tempore exercitationem harum consequatur voluptatum modi minima aut eaque et et. + +Aut ea voluptatem dignissimos expedita odit tempore quod aut beatae ipsam iste. Minus voluptatibus dolorem maiores eius sed nihil vel enim odio voluptatem accusamus. Natus quibusdam temporibus tenetur cumque sint necessitatibus dolorem ex ducimus iusto ex. Voluptatem neque dicta explicabo officiis et ducimus sit ut ut praesentium pariatur. Illum molestias nisi at dolore ut voluptatem accusantium et fugiat et ut. + +Explicabo incidunt reprehenderit non quia dignissimos recusandae vitae soluta quia et quia. Aut veniam voluptas consequatur placeat sapiente non eveniet voluptatibus magni velit eum. Nobis vel repellendus sed est qui autem laudantium quidem quam ullam consequatur. Aut iusto ut commodi similique quae voluptatem atque qui fugiat eum aut. Quis distinctio consequatur voluptatem vel aliquid aut laborum facere officiis iure tempora.`, + Output: "string", Params: []Param{ {Field: "paragraphcount", Display: "Paragraph Count", Type: "int", Default: "2", Description: "Number of paragraphs"}, {Field: "sentencecount", Display: "Sentence Count", Type: "int", Default: "2", Description: "Number of sentences in a paragraph"}, {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, {Field: "paragraphseparator", Display: "Paragraph Separator", Type: "string", Default: "
", Description: "String value to add between paragraphs"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { paragraphCount, err := info.GetInt(m, "paragraphcount") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go b/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go index 7697ef986..1fb740e42 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/minecraft.go @@ -170,10 +170,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftore", Info{ Display: "Minecraft ore", Category: "minecraft", - Description: "Random Minecraft ore", + Description: "Naturally occurring minerals found in the game Minecraft, used for crafting purposes", Example: "coal", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftOre(r), nil }, }) @@ -181,10 +181,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftwood", Info{ Display: "Minecraft wood", Category: "minecraft", - Description: "Random Minecraft wood", + Description: "Natural resource in Minecraft, used for crafting various items and building structures", Example: "oak", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftWood(r), nil }, }) @@ -192,10 +192,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftarmortier", Info{ Display: "Minecraft armor tier", Category: "minecraft", - Description: "Random Minecraft armor tier", + Description: "Classification system for armor sets in Minecraft, indicating their effectiveness and protection level", Example: "iron", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftArmorTier(r), nil }, }) @@ -203,10 +203,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftarmorpart", Info{ Display: "Minecraft armor part", Category: "minecraft", - Description: "Random Minecraft armor part", + Description: "Component of an armor set in Minecraft, such as a helmet, chestplate, leggings, or boots", Example: "helmet", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftArmorPart(r), nil }, }) @@ -214,10 +214,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftweapon", Info{ Display: "Minecraft weapon", Category: "minecraft", - Description: "Random Minecraft weapon", + Description: "Tools and items used in Minecraft for combat and defeating hostile mobs", Example: "bow", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftWeapon(r), nil }, }) @@ -225,10 +225,10 @@ func addMinecraftLookup() { AddFuncLookup("minecrafttool", Info{ Display: "Minecraft tool", Category: "minecraft", - Description: "Random Minecraft tool", + Description: "Items in Minecraft designed for specific tasks, including mining, digging, and building", Example: "shovel", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftTool(r), nil }, }) @@ -236,10 +236,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftdye", Info{ Display: "Minecraft dye", Category: "minecraft", - Description: "Random Minecraft dye", + Description: "Items used to change the color of various in-game objects", Example: "white", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftDye(r), nil }, }) @@ -247,10 +247,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftfood", Info{ Display: "Minecraft food", Category: "minecraft", - Description: "Random Minecraft food", + Description: "Consumable items in Minecraft that provide nourishment to the player character", Example: "apple", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftFood(r), nil }, }) @@ -258,10 +258,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftanimal", Info{ Display: "Minecraft animal", Category: "minecraft", - Description: "Random Minecraft animal", + Description: "Non-hostile creatures in Minecraft, often used for resources and farming", Example: "chicken", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftAnimal(r), nil }, }) @@ -269,10 +269,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftvillagerjob", Info{ Display: "Minecraft villager job", Category: "minecraft", - Description: "Random Minecraft villager job", + Description: "The profession or occupation assigned to a villager character in the game", Example: "farmer", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftVillagerJob(r), nil }, }) @@ -280,10 +280,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftvillagerstation", Info{ Display: "Minecraft villager station", Category: "minecraft", - Description: "Random Minecraft villager station", + Description: "Designated area or structure in Minecraft where villagers perform their job-related tasks and trading", Example: "furnace", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftVillagerStation(r), nil }, }) @@ -291,10 +291,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftvillagerlevel", Info{ Display: "Minecraft villager level", Category: "minecraft", - Description: "Random Minecraft villager level", + Description: "Measure of a villager's experience and proficiency in their assigned job or profession", Example: "master", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftVillagerLevel(r), nil }, }) @@ -302,10 +302,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobpassive", Info{ Display: "Minecraft mob passive", Category: "minecraft", - Description: "Random Minecraft mob passive", + Description: "Non-aggressive creatures in the game that do not attack players", Example: "cow", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobPassive(r), nil }, }) @@ -313,10 +313,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobneutral", Info{ Display: "Minecraft mob neutral", Category: "minecraft", - Description: "Random Minecraft mob neutral", + Description: "Creature in the game that only becomes hostile if provoked, typically defending itself when attacked", Example: "bee", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobNeutral(r), nil }, }) @@ -324,10 +324,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobhostile", Info{ Display: "Minecraft mob hostile", Category: "minecraft", - Description: "Random Minecraft mob hostile", + Description: "Aggressive creatures in the game that actively attack players when encountered", Example: "spider", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobHostile(r), nil }, }) @@ -335,10 +335,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftmobboss", Info{ Display: "Minecraft mob boss", Category: "minecraft", - Description: "Random Minecraft mob boss", + Description: "Powerful hostile creature in the game, often found in challenging dungeons or structures", Example: "ender dragon", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftMobBoss(r), nil }, }) @@ -346,10 +346,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftbiome", Info{ Display: "Minecraft biome", Category: "minecraft", - Description: "Random Minecraft biome", + Description: "Distinctive environmental regions in the game, characterized by unique terrain, vegetation, and weather", Example: "forest", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftBiome(r), nil }, }) @@ -357,10 +357,10 @@ func addMinecraftLookup() { AddFuncLookup("minecraftweather", Info{ Display: "Minecraft weather", Category: "minecraft", - Description: "Random Minecraft weather", + Description: "Atmospheric conditions in the game that include rain, thunderstorms, and clear skies, affecting gameplay and ambiance", Example: "rain", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minecraftWeather(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/misc.go b/vendor/github.com/brianvoe/gofakeit/v6/misc.go index 30a732433..aa55911e4 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/misc.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/misc.go @@ -2,7 +2,6 @@ package gofakeit import ( "encoding/hex" - "io" "math/rand" "reflect" @@ -22,13 +21,20 @@ func boolFunc(r *rand.Rand) bool { return randIntRange(r, 0, 1) == 1 } func UUID() string { return uuid(globalFaker.Rand) } // UUID (version 4) will generate a random unique identifier based upon random numbers -// Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 8-4-4-4-12 func (f *Faker) UUID() string { return uuid(f.Rand) } func uuid(r *rand.Rand) string { version := byte(4) uuid := make([]byte, 16) - io.ReadFull(r, uuid[:]) + + // Commented out due to io.ReadFull not being race condition safe + // io.ReadFull(r, uuid[:]) + + // Read 16 random bytes + for i := 0; i < 16; i++ { + uuid[i] = byte(r.Intn(256)) + } // Set version uuid[6] = (uuid[6] & 0x0f) | (version << 4) @@ -51,12 +57,12 @@ func uuid(r *rand.Rand) string { } // ShuffleAnySlice takes in a slice and outputs it in a random order -func ShuffleAnySlice(v interface{}) { shuffleAnySlice(globalFaker.Rand, v) } +func ShuffleAnySlice(v any) { shuffleAnySlice(globalFaker.Rand, v) } // ShuffleAnySlice takes in a slice and outputs it in a random order -func (f *Faker) ShuffleAnySlice(v interface{}) { shuffleAnySlice(f.Rand, v) } +func (f *Faker) ShuffleAnySlice(v any) { shuffleAnySlice(f.Rand, v) } -func shuffleAnySlice(r *rand.Rand, v interface{}) { +func shuffleAnySlice(r *rand.Rand, v any) { if v == nil { return } @@ -103,12 +109,12 @@ func flipACoin(r *rand.Rand) string { } // RandomMapKey will return a random key from a map -func RandomMapKey(mapI interface{}) interface{} { return randomMapKey(globalFaker.Rand, mapI) } +func RandomMapKey(mapI any) any { return randomMapKey(globalFaker.Rand, mapI) } // RandomMapKey will return a random key from a map -func (f *Faker) RandomMapKey(mapI interface{}) interface{} { return randomMapKey(f.Rand, mapI) } +func (f *Faker) RandomMapKey(mapI any) any { return randomMapKey(f.Rand, mapI) } -func randomMapKey(r *rand.Rand, mapI interface{}) interface{} { +func randomMapKey(r *rand.Rand, mapI any) any { keys := reflect.ValueOf(mapI).MapKeys() return keys[r.Intn(len(keys))].Interface() } @@ -130,10 +136,10 @@ func addMiscLookup() { AddFuncLookup("uuid", Info{ Display: "UUID", Category: "misc", - Description: "Random uuid", + Description: "128-bit identifier used to uniquely identify objects or entities in computer systems", Example: "590c1440-9888-45b0-bd51-a817ee07c3f2", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uuid(r), nil }, }) @@ -141,10 +147,10 @@ func addMiscLookup() { AddFuncLookup("bool", Info{ Display: "Boolean", Category: "misc", - Description: "Random boolean", + Description: "Data type that represents one of two possible values, typically true or false", Example: "true", Output: "bool", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return boolFunc(r), nil }, }) @@ -152,10 +158,10 @@ func addMiscLookup() { AddFuncLookup("flipacoin", Info{ Display: "Flip A Coin", Category: "misc", - Description: "Random Heads or Tails outcome", + Description: "Decision-making method involving the tossing of a coin to determine outcomes", Example: "Tails", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return flipACoin(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/movie.go b/vendor/github.com/brianvoe/gofakeit/v6/movie.go new file mode 100644 index 000000000..21fcbd73a --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/movie.go @@ -0,0 +1,70 @@ +package gofakeit + +import "math/rand" + +func MovieName() string { return movieName(globalFaker.Rand) } + +func (f *Faker) MovieName() string { return movieName(f.Rand) } + +func movieName(r *rand.Rand) string { return getRandValue(r, []string{"movie", "name"}) } + +func MovieGenre() string { return movieGenre(globalFaker.Rand) } + +func (f *Faker) MovieGenre() string { return movieGenre(f.Rand) } + +func movieGenre(r *rand.Rand) string { return getRandValue(r, []string{"movie", "genre"}) } + +type MovieInfo struct { + Name string `json:"name" xml:"name"` + Genre string `json:"genre" xml:"genre"` +} + +func Movie() *MovieInfo { return movie(globalFaker.Rand) } + +func (f *Faker) Movie() *MovieInfo { return movie(f.Rand) } + +func movie(r *rand.Rand) *MovieInfo { + return &MovieInfo{ + Name: movieName(r), + Genre: movieGenre(r), + } +} + +func addMovieLookup() { + AddFuncLookup("movie", Info{ + Display: "Movie", + Category: "movie", + Description: "A story told through moving pictures and sound", + Example: `{ + "name": "Psycho", + "genre": "Mystery" +}`, + Output: "map[string]string", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return movie(r), nil + }, + }) + + AddFuncLookup("moviename", Info{ + Display: "Movie Name", + Category: "movie", + Description: "Title or name of a specific film used for identification and reference", + Example: "The Matrix", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return movieName(r), nil + }, + }) + + AddFuncLookup("moviegenre", Info{ + Display: "Genre", + Category: "movie", + Description: "Category that classifies movies based on common themes, styles, and storytelling approaches", + Example: "Action", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return movieGenre(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/number.go b/vendor/github.com/brianvoe/gofakeit/v6/number.go index db6fd7675..7200a5988 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/number.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/number.go @@ -253,14 +253,14 @@ func addNumberLookup() { AddFuncLookup("number", Info{ Display: "Number", Category: "number", - Description: "Random number between given range", + Description: "Mathematical concept used for counting, measuring, and expressing quantities or values", Example: "14866", Output: "int", Params: []Param{ {Field: "min", Display: "Min", Type: "int", Default: "-2147483648", Description: "Minimum integer value"}, {Field: "max", Display: "Max", Type: "int", Default: "2147483647", Description: "Maximum integer value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetInt(m, "min") if err != nil { return nil, err @@ -278,10 +278,10 @@ func addNumberLookup() { AddFuncLookup("uint8", Info{ Display: "Uint8", Category: "number", - Description: "Random uint8 value", + Description: "Unsigned 8-bit integer, capable of representing values from 0 to 255", Example: "152", Output: "uint8", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint8Func(r), nil }, }) @@ -289,10 +289,10 @@ func addNumberLookup() { AddFuncLookup("uint16", Info{ Display: "Uint16", Category: "number", - Description: "Random uint16 value", + Description: "Unsigned 16-bit integer, capable of representing values from 0 to 65,535", Example: "34968", Output: "uint16", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint16Func(r), nil }, }) @@ -300,10 +300,10 @@ func addNumberLookup() { AddFuncLookup("uint32", Info{ Display: "Uint32", Category: "number", - Description: "Random uint32 value", + Description: "Unsigned 32-bit integer, capable of representing values from 0 to 4,294,967,295", Example: "1075055705", Output: "uint32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint32Func(r), nil }, }) @@ -311,10 +311,10 @@ func addNumberLookup() { AddFuncLookup("uint64", Info{ Display: "Uint64", Category: "number", - Description: "Random uint64 value", + Description: "Unsigned 64-bit integer, capable of representing values from 0 to 18,446,744,073,709,551,615", Example: "843730692693298265", Output: "uint64", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return uint64Func(r), nil }, }) @@ -322,14 +322,14 @@ func addNumberLookup() { AddFuncLookup("uintrange", Info{ Display: "UintRange", Category: "number", - Description: "Random uint value between given range", + Description: "Non-negative integer value between given range", Example: "1075055705", Output: "uint", Params: []Param{ {Field: "min", Display: "Min", Type: "uint", Default: "0", Description: "Minimum uint value"}, {Field: "max", Display: "Max", Type: "uint", Default: "4294967295", Description: "Maximum uint value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetUint(m, "min") if err != nil { return nil, err @@ -347,10 +347,10 @@ func addNumberLookup() { AddFuncLookup("int8", Info{ Display: "Int8", Category: "number", - Description: "Random int8 value", + Description: "Signed 8-bit integer, capable of representing values from -128 to 127", Example: "24", Output: "int8", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int8Func(r), nil }, }) @@ -358,10 +358,10 @@ func addNumberLookup() { AddFuncLookup("int16", Info{ Display: "Int16", Category: "number", - Description: "Random int16 value", + Description: "Signed 16-bit integer, capable of representing values from 32,768 to 32,767", Example: "2200", Output: "int16", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int16Func(r), nil }, }) @@ -369,10 +369,10 @@ func addNumberLookup() { AddFuncLookup("int32", Info{ Display: "Int32", Category: "number", - Description: "Random int32 value", + Description: "Signed 32-bit integer, capable of representing values from -2,147,483,648 to 2,147,483,647", Example: "-1072427943", Output: "int32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int32Func(r), nil }, }) @@ -380,10 +380,10 @@ func addNumberLookup() { AddFuncLookup("int64", Info{ Display: "Int64", Category: "number", - Description: "Random int64 value", + Description: "Signed 64-bit integer, capable of representing values from -9,223,372,036,854,775,808 to -9,223,372,036,854,775,807", Example: "-8379641344161477543", Output: "int64", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return int64Func(r), nil }, }) @@ -391,14 +391,14 @@ func addNumberLookup() { AddFuncLookup("intrange", Info{ Display: "IntRange", Category: "number", - Description: "Random int value between min and max", + Description: "Integer value between given range", Example: "-8379477543", Output: "int", Params: []Param{ {Field: "min", Display: "Min", Type: "int", Description: "Minimum int value"}, {Field: "max", Display: "Max", Type: "int", Description: "Maximum int value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetInt(m, "min") if err != nil { return nil, err @@ -416,10 +416,10 @@ func addNumberLookup() { AddFuncLookup("float32", Info{ Display: "Float32", Category: "number", - Description: "Random float32 value", + Description: "Data type representing floating-point numbers with 32 bits of precision in computing", Example: "3.1128167e+37", Output: "float32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return float32Func(r), nil }, }) @@ -427,14 +427,14 @@ func addNumberLookup() { AddFuncLookup("float32range", Info{ Display: "Float32 Range", Category: "number", - Description: "Random float32 between given range", + Description: "Float32 value between given range", Example: "914774.6", Output: "float32", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Description: "Minimum float32 value"}, {Field: "max", Display: "Max", Type: "float", Description: "Maximum float32 value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat32(m, "min") if err != nil { return nil, err @@ -452,10 +452,10 @@ func addNumberLookup() { AddFuncLookup("float64", Info{ Display: "Float64", Category: "number", - Description: "Random float64 value", + Description: "Data type representing floating-point numbers with 64 bits of precision in computing", Example: "1.644484108270445e+307", Output: "float64", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return float64Func(r), nil }, }) @@ -463,14 +463,14 @@ func addNumberLookup() { AddFuncLookup("float64range", Info{ Display: "Float64 Range", Category: "number", - Description: "Random float64 between given range", + Description: "Float64 value between given range", Example: "914774.5585333086", Output: "float64", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Description: "Minimum float64 value"}, {Field: "max", Display: "Max", Type: "float", Description: "Maximum float64 value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err @@ -488,13 +488,13 @@ func addNumberLookup() { AddFuncLookup("shuffleints", Info{ Display: "Shuffle Ints", Category: "number", - Description: "Shuffle an array of ints", + Description: "Shuffles an array of ints", Example: "1,2,3,4 => 3,1,4,2", Output: "[]int", Params: []Param{ {Field: "ints", Display: "Integers", Type: "[]int", Description: "Delimited separated integers"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ints, err := info.GetIntArray(m, "ints") if err != nil { return nil, err @@ -506,13 +506,51 @@ func addNumberLookup() { }, }) + AddFuncLookup("randomint", Info{ + Display: "Random Int", + Category: "number", + Description: "Randomly selected value from a slice of int", + Example: "-1,2,-3,4 => -3", + Output: "int", + Params: []Param{ + {Field: "ints", Display: "Integers", Type: "[]int", Description: "Delimited separated integers"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + ints, err := info.GetIntArray(m, "ints") + if err != nil { + return nil, err + } + + return randomInt(r, ints), nil + }, + }) + + AddFuncLookup("randomuint", Info{ + Display: "Random Uint", + Category: "number", + Description: "Randomly selected value from a slice of uint", + Example: "1,2,3,4 => 4", + Output: "uint", + Params: []Param{ + {Field: "uints", Display: "Unsigned Integers", Type: "[]uint", Description: "Delimited separated unsigned integers"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + uints, err := info.GetUintArray(m, "uints") + if err != nil { + return nil, err + } + + return randomUint(r, uints), nil + }, + }) + AddFuncLookup("hexuint8", Info{ Display: "HexUint8", Category: "number", - Description: "Random uint8 hex value", + Description: "Hexadecimal representation of an 8-bit unsigned integer", Example: "0x87", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 8), nil }, }) @@ -520,10 +558,10 @@ func addNumberLookup() { AddFuncLookup("hexuint16", Info{ Display: "HexUint16", Category: "number", - Description: "Random uint16 hex value", + Description: "Hexadecimal representation of an 16-bit unsigned integer", Example: "0x8754", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 16), nil }, }) @@ -531,10 +569,10 @@ func addNumberLookup() { AddFuncLookup("hexuint32", Info{ Display: "HexUint32", Category: "number", - Description: "Random uint32 hex value", + Description: "Hexadecimal representation of an 32-bit unsigned integer", Example: "0x87546957", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 32), nil }, }) @@ -542,10 +580,10 @@ func addNumberLookup() { AddFuncLookup("hexuint64", Info{ Display: "HexUint64", Category: "number", - Description: "Random uint64 hex value", + Description: "Hexadecimal representation of an 64-bit unsigned integer", Example: "0x875469578e51b5e5", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 64), nil }, }) @@ -553,10 +591,10 @@ func addNumberLookup() { AddFuncLookup("hexuint128", Info{ Display: "HexUint128", Category: "number", - Description: "Random uint128 hex value", + Description: "Hexadecimal representation of an 128-bit unsigned integer", Example: "0x875469578e51b5e56c95b64681d147a1", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 128), nil }, }) @@ -564,10 +602,10 @@ func addNumberLookup() { AddFuncLookup("hexuint256", Info{ Display: "HexUint256", Category: "number", - Description: "Random uint256 hex value", + Description: "Hexadecimal representation of an 256-bit unsigned integer", Example: "0x875469578e51b5e56c95b64681d147a12cde48a4f417231b0c486abbc263e48d", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hexUint(r, 256), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/payment.go b/vendor/github.com/brianvoe/gofakeit/v6/payment.go index b2248e8f6..dc4b0057b 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/payment.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/payment.go @@ -243,11 +243,14 @@ func addPaymentLookup() { AddFuncLookup("currency", Info{ Display: "Currency", Category: "payment", - Description: "Random currency data set", - Example: `{short: "USD", long: "United States Dollar"}`, + Description: "Medium of exchange, often in the form of paper money or coins, used for trade and transactions", + Example: `{ + "short": "IQD", + "long": "Iraq Dinar" +}`, Output: "map[string]string", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return currency(r), nil }, }) @@ -255,10 +258,10 @@ func addPaymentLookup() { AddFuncLookup("currencyshort", Info{ Display: "Currency Short", Category: "payment", - Description: "Random currency abbreviated", + Description: "Short 3-letter word used to represent a specific currency", Example: "USD", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return currencyShort(r), nil }, }) @@ -266,10 +269,10 @@ func addPaymentLookup() { AddFuncLookup("currencylong", Info{ Display: "Currency Long", Category: "payment", - Description: "Random currency", + Description: "Complete name of a specific currency used for official identification in financial transactions", Example: "United States Dollar", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return currencyLong(r), nil }, }) @@ -277,14 +280,14 @@ func addPaymentLookup() { AddFuncLookup("price", Info{ Display: "Price", Category: "payment", - Description: "Random monitary price", + Description: "The amount of money or value assigned to a product, service, or asset in a transaction", Example: "92.26", Output: "float64", Params: []Param{ {Field: "min", Display: "Min", Type: "float", Default: "0", Description: "Minimum price value"}, {Field: "max", Display: "Max", Type: "float", Default: "1000", Description: "Maximum price value"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { min, err := info.GetFloat64(m, "min") if err != nil { return nil, err @@ -302,10 +305,16 @@ func addPaymentLookup() { AddFuncLookup("creditcard", Info{ Display: "Credit Card", Category: "payment", - Description: "Random credit card data set", - Example: `{type: "Visa", number: "4136459948995369", exp: "01/21", cvv: "513"}`, - Output: "map[string]interface", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Description: "Plastic card allowing users to make purchases on credit, with payment due at a later date", + Example: `{ + "type": "UnionPay", + "number": "4364599489953698", + "exp": "02/24", + "cvv": "300" +}`, + Output: "map[string]any", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCard(r), nil }, }) @@ -313,10 +322,10 @@ func addPaymentLookup() { AddFuncLookup("creditcardtype", Info{ Display: "Credit Card Type", Category: "payment", - Description: "Random credit card type", + Description: "Classification of credit cards based on the issuing company", Example: "Visa", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCardType(r), nil }, }) @@ -324,9 +333,9 @@ func addPaymentLookup() { AddFuncLookup("creditcardnumber", Info{ Display: "Credit Card Number", Category: "payment", - Description: "Random credit card number", + Description: "Unique numerical identifier on a credit card used for making electronic payments and transactions", Example: "4136459948995369", - Output: "int", + Output: "string", Params: []Param{ { Field: "types", Display: "Types", Type: "[]string", Default: "all", @@ -336,7 +345,7 @@ func addPaymentLookup() { {Field: "bins", Display: "Bins", Type: "[]string", Optional: true, Description: "Optional list of prepended bin numbers to pick from"}, {Field: "gaps", Display: "Gaps", Type: "bool", Default: "false", Description: "Whether or not to have gaps in number"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { types, err := info.GetStringArray(m, "types") if err != nil { return nil, err @@ -368,10 +377,10 @@ func addPaymentLookup() { AddFuncLookup("creditcardexp", Info{ Display: "Credit Card Exp", Category: "payment", - Description: "Random credit card expiraction date", + Description: "Date when a credit card becomes invalid and cannot be used for transactions", Example: "01/21", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCardExp(r), nil }, }) @@ -379,10 +388,10 @@ func addPaymentLookup() { AddFuncLookup("creditcardcvv", Info{ Display: "Credit Card CVV", Category: "payment", - Description: "Random credit card number", + Description: "Three or four-digit security code on a credit card used for online and remote transactions", Example: "513", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return creditCardCvv(r), nil }, }) @@ -390,10 +399,10 @@ func addPaymentLookup() { AddFuncLookup("achrouting", Info{ Display: "ACH Routing Number", Category: "payment", - Description: "Random 9 digit ach routing number", + Description: "Unique nine-digit code used in the U.S. for identifying the bank and processing electronic transactions", Example: "513715684", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return achRouting(r), nil }, }) @@ -401,10 +410,10 @@ func addPaymentLookup() { AddFuncLookup("achaccount", Info{ Display: "ACH Account Number", Category: "payment", - Description: "Random 12 digit ach account number", + Description: "A bank account number used for Automated Clearing House transactions and electronic transfers", Example: "491527954328", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return achAccount(r), nil }, }) @@ -412,10 +421,10 @@ func addPaymentLookup() { AddFuncLookup("bitcoinaddress", Info{ Display: "Bitcoin Address", Category: "payment", - Description: "Random 26-35 characters representing a bitcoin address", + Description: "Cryptographic identifier used to receive, store, and send Bitcoin cryptocurrency in a peer-to-peer network", Example: "1lWLbxojXq6BqWX7X60VkcDIvYA", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return bitcoinAddress(r), nil }, }) @@ -423,10 +432,10 @@ func addPaymentLookup() { AddFuncLookup("bitcoinprivatekey", Info{ Display: "Bitcoin Private Key", Category: "payment", - Description: "Random 51 characters representing a bitcoin private key", + Description: "Secret, secure code that allows the owner to access and control their Bitcoin holdings", Example: "5vrbXTADWJ6sQBSYd6lLkG97jljNc0X9VPBvbVqsIH9lWOLcoqg", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return bitcoinPrivateKey(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/person.go b/vendor/github.com/brianvoe/gofakeit/v6/person.go index 569a9f873..c1fe99f33 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/person.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/person.go @@ -60,6 +60,14 @@ func (f *Faker) FirstName() string { return firstName(f.Rand) } func firstName(r *rand.Rand) string { return getRandValue(r, []string{"person", "first"}) } +// MiddleName will generate a random middle name +func MiddleName() string { return middleName(globalFaker.Rand) } + +// MiddleName will generate a random middle name +func (f *Faker) MiddleName() string { return middleName(f.Rand) } + +func middleName(r *rand.Rand) string { return getRandValue(r, []string{"person", "middle"}) } + // LastName will generate a random last name func LastName() string { return lastName(globalFaker.Rand) } @@ -201,44 +209,44 @@ func addPersonLookup() { AddFuncLookup("person", Info{ Display: "Person", Category: "person", - Description: "Random set of person info", + Description: "Personal data, like name and contact details, used for identification and communication", Example: `{ - first_name: "Markus", - last_name: "Moen", - gender: "male", - ssn: "420776036", - image: "https://picsum.photos/300/300/people", - hobby: "Swimming", - job: { - company: "Lockman and Sons", - title: "Developer", - descriptor: "Global", - level: "Brand" - }, - address: { - address: "5369 Streamville, Rossieview, Hawaii 42591", - street: "5369 Streamville", - city: "Rossieview", - state: "Hawaii", - zip: "42591", - country: "Burkina Faso", - latitude: "-6.662594491850811", - longitude: "23.921575244414612" - }, - contact: { - phone: "6136459948", - email: "carolecarroll@bosco.com" - }, - credit_card: { - type: "Visa", - number: "6536459948995369", - exp: "03/27", - cvv: "353" - } - }`, - Output: "map[string]interface", + "first_name": "Markus", + "last_name": "Moen", + "gender": "male", + "ssn": "275413589", + "image": "https://picsum.photos/208/500", + "hobby": "Lacrosse", + "job": { + "company": "Intermap Technologies", + "title": "Developer", + "descriptor": "Direct", + "level": "Paradigm" + }, + "address": { + "address": "369 North Cornerbury, Miami, North Dakota 24259", + "street": "369 North Cornerbury", + "city": "Miami", + "state": "North Dakota", + "zip": "24259", + "country": "Ghana", + "latitude": -6.662595, + "longitude": 23.921575 + }, + "contact": { + "phone": "3023202027", + "email": "lamarkoelpin@heaney.biz" + }, + "credit_card": { + "type": "Maestro", + "number": "39800889982276", + "exp": "01/29", + "cvv": "932" + } +}`, + Output: "map[string]any", ContentType: "application/json", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return person(r), nil }, }) @@ -246,10 +254,10 @@ func addPersonLookup() { AddFuncLookup("name", Info{ Display: "Name", Category: "person", - Description: "Random name", + Description: "The given and family name of an individual", Example: "Markus Moen", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return name(r), nil }, }) @@ -257,10 +265,10 @@ func addPersonLookup() { AddFuncLookup("nameprefix", Info{ Display: "Name Prefix", Category: "person", - Description: "Random name prefix", + Description: "A title or honorific added before a person's name", Example: "Mr.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return namePrefix(r), nil }, }) @@ -268,10 +276,10 @@ func addPersonLookup() { AddFuncLookup("namesuffix", Info{ Display: "Name Suffix", Category: "person", - Description: "Random name suffix", + Description: "A title or designation added after a person's name", Example: "Jr.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nameSuffix(r), nil }, }) @@ -279,21 +287,32 @@ func addPersonLookup() { AddFuncLookup("firstname", Info{ Display: "First Name", Category: "person", - Description: "Random first name", + Description: "The name given to a person at birth", Example: "Markus", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return firstName(r), nil }, }) + AddFuncLookup("middlename", Info{ + Display: "Middle Name", + Category: "person", + Description: "Name between a person's first name and last name", + Example: "Belinda", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return middleName(r), nil + }, + }) + AddFuncLookup("lastname", Info{ Display: "Last Name", Category: "person", - Description: "Random last name", + Description: "The family name or surname of an individual", Example: "Daniel", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return lastName(r), nil }, }) @@ -301,10 +320,10 @@ func addPersonLookup() { AddFuncLookup("gender", Info{ Display: "Gender", Category: "person", - Description: "Random gender", + Description: "Classification based on social and cultural norms that identifies an individual", Example: "male", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return gender(r), nil }, }) @@ -312,10 +331,10 @@ func addPersonLookup() { AddFuncLookup("ssn", Info{ Display: "SSN", Category: "person", - Description: "Random social security number", + Description: "Unique nine-digit identifier used for government and financial purposes in the United States", Example: "296446360", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return ssn(r), nil }, }) @@ -323,10 +342,10 @@ func addPersonLookup() { AddFuncLookup("hobby", Info{ Display: "Hobby", Category: "person", - Description: "Random hobby activity", + Description: "An activity pursued for leisure and pleasure", Example: "Swimming", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hobby(r), nil }, }) @@ -334,10 +353,10 @@ func addPersonLookup() { AddFuncLookup("email", Info{ Display: "Email", Category: "person", - Description: "Random email", + Description: "Electronic mail used for sending digital messages and communication over the internet", Example: "markusmoen@pagac.net", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return email(r), nil }, }) @@ -345,10 +364,10 @@ func addPersonLookup() { AddFuncLookup("phone", Info{ Display: "Phone", Category: "person", - Description: "Random phone number", + Description: "Numerical sequence used to contact individuals via telephone or mobile devices", Example: "6136459948", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phone(r), nil }, }) @@ -356,10 +375,10 @@ func addPersonLookup() { AddFuncLookup("phoneformatted", Info{ Display: "Phone Formatted", Category: "person", - Description: "Random formatted phone number", + Description: "Formatted phone number of a person", Example: "136-459-9489", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phoneFormatted(r), nil }, }) @@ -368,13 +387,29 @@ func addPersonLookup() { Display: "Teams", Category: "person", Description: "Randomly split people into teams", - Example: `{"Team 1": ["Sharon","Jeff"], "Team 2": ["Billy","Connor"]}`, + Example: `{ + "Team 1": [ + "Justin", + "Connor", + "Jeff" + ], + "Team 2": [ + "Sharon", + "Fabian", + "Billy" + ], + "Team 3": [ + "Steve", + "Robert" + ] +}`, Output: "map[string][]string", + ContentType: "application/json", Params: []Param{ {Field: "people", Display: "Strings", Type: "[]string", Description: "Array of people"}, {Field: "teams", Display: "Strings", Type: "[]string", Description: "Array of teams"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { people, err := info.GetStringArray(m, "people") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/product.go b/vendor/github.com/brianvoe/gofakeit/v6/product.go new file mode 100644 index 000000000..7483ecbec --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/product.go @@ -0,0 +1,253 @@ +package gofakeit + +import ( + "fmt" + "math/rand" + "strings" +) + +type ProductInfo struct { + Name string `json:"name" xml:"name"` + Description string `json:"description" xml:"description"` + Categories []string `json:"categories" xml:"categories"` + Price float64 `json:"price" xml:"price"` + Features []string `json:"features" xml:"features"` + Color string `json:"color" xml:"color"` + Material string `json:"material" xml:"material"` + UPC string `json:"upc" xml:"upc"` +} + +// Product will generate a random set of product information +func Product() *ProductInfo { return product(globalFaker.Rand) } + +// Product will generate a random set of product information +func (f *Faker) Product() *ProductInfo { return product(f.Rand) } + +func product(r *rand.Rand) *ProductInfo { + // Categories + categories := []string{} + weightedCategory, _ := weighted(r, []any{1, 2, 3, 4}, []float32{1, 4, 3, 4}) + + for i := 0; i < weightedCategory.(int); i++ { + categories = append(categories, productCategory(r)) + } + + // Features + features := []string{} + for i := 0; i < number(r, 1, 5); i++ { + features = append(features, productFeature(r)) + } + + product := &ProductInfo{ + Name: productName(r), + Description: productDescription(r), + Categories: categories, + Price: price(r, 3.00, 100.00), + UPC: productUPC(r), + Features: features, + Color: safeColor(r), + Material: productMaterial(r), + } + + return product +} + +// ProductName will generate a random product name +func ProductName() string { return productName(globalFaker.Rand) } + +// ProductName will generate a random product name +func (f *Faker) ProductName() string { return productName(f.Rand) } + +func productName(r *rand.Rand) string { + name := getRandValue(r, []string{"product", "name"}) + switch number(r, 0, 9) { + case 1: + // Name + Adjective + Feature + return title(fmt.Sprintf("%s %s %s", name, getRandValue(r, []string{"product", "adjective"}), productFeature(r))) + case 2: + // Adjective + Material + Name + return title(fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "adjective"}), productMaterial(r), name)) + case 3: + // Color + Name + Suffix + return title(fmt.Sprintf("%s %s %s", safeColor(r), name, getRandValue(r, []string{"product", "suffix"}))) + case 4: + // Feature + Name + Adjective + return title(fmt.Sprintf("%s %s %s", productFeature(r), name, getRandValue(r, []string{"product", "adjective"}))) + case 5: + // Material + Color + Name + return title(fmt.Sprintf("%s %s %s", productMaterial(r), safeColor(r), name)) + case 6: + // Name + Suffix + Material + return title(fmt.Sprintf("%s %s %s", name, getRandValue(r, []string{"product", "suffix"}), productMaterial(r))) + case 7: + // Adjective + Feature + Name + return title(fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "adjective"}), productFeature(r), name)) + case 8: + // Color + Material + Name + return title(fmt.Sprintf("%s %s %s", safeColor(r), productMaterial(r), name)) + case 9: + // Suffix + Adjective + Name + return title(fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "suffix"}), getRandValue(r, []string{"product", "adjective"}), name)) + } + + // case: 0 - Adjective + Name + Suffix + return title(fmt.Sprintf("%s %s %s", getRandValue(r, []string{"product", "adjective"}), name, getRandValue(r, []string{"product", "suffix"}))) +} + +// ProductDescription will generate a random product description +func ProductDescription() string { return productDescription(globalFaker.Rand) } + +// ProductDescription will generate a random product description +func (f *Faker) ProductDescription() string { return productDescription(f.Rand) } + +func productDescription(r *rand.Rand) string { + desc := []string{} + for i := 0; i < number(r, 1, 3); i++ { + desc = append(desc, sentence(r, number(r, 5, 15))) + } + + return strings.Join(desc, " ") +} + +// ProductCategory will generate a random product category +func ProductCategory() string { return productCategory(globalFaker.Rand) } + +// ProductCategory will generate a random product category +func (f *Faker) ProductCategory() string { return productCategory(f.Rand) } + +func productCategory(r *rand.Rand) string { + return getRandValue(r, []string{"product", "category"}) +} + +// ProductFeature will generate a random product feature +func ProductFeature() string { return productFeature(globalFaker.Rand) } + +// ProductFeature will generate a random product feature +func (f *Faker) ProductFeature() string { return productFeature(f.Rand) } + +func productFeature(r *rand.Rand) string { + return getRandValue(r, []string{"product", "feature"}) +} + +// ProductMaterial will generate a random product material +func ProductMaterial() string { return productMaterial(globalFaker.Rand) } + +// ProductMaterial will generate a random product material +func (f *Faker) ProductMaterial() string { return productMaterial(f.Rand) } + +func productMaterial(r *rand.Rand) string { + return getRandValue(r, []string{"product", "material"}) +} + +// ProductUPC will generate a random product UPC +func ProductUPC() string { return productUPC(globalFaker.Rand) } + +// ProductUPC will generate a random product UPC +func (f *Faker) ProductUPC() string { return productUPC(f.Rand) } + +func productUPC(r *rand.Rand) string { + // The first digit of a UPC is a fixed digit (usually 0) + upc := "0" + + // Generate the remaining 11 digits randomly + for i := 1; i < 12; i++ { + digit := number(r, 0, 9) + upc += fmt.Sprintf("%d", digit) + } + + return upc +} + +func addProductLookup() { + AddFuncLookup("product", Info{ + Display: "Product", + Category: "product", + Description: "An item created for sale or use", + Example: `{ + "name": "olive copper monitor", + "description": "Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours.", + "categories": [ + "clothing", + "tools and hardware" + ], + "price": 7.61, + "features": [ + "ultra-lightweight" + ], + "color": "navy", + "material": "brass", + "upc": "012780949980" +}`, + Output: "map[string]any", + ContentType: "application/json", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return product(r), nil + }, + }) + + AddFuncLookup("productname", Info{ + Display: "Product Name", + Category: "product", + Description: "Distinctive title or label assigned to a product for identification and marketing", + Example: "olive copper monitor", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productName(r), nil + }, + }) + + AddFuncLookup("productdescription", Info{ + Display: "Product Description", + Category: "product", + Description: "Explanation detailing the features and characteristics of a product", + Example: "Backwards caused quarterly without week it hungry thing someone him regularly. Whomever this revolt hence from his timing as quantity us these yours.", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productDescription(r), nil + }, + }) + + AddFuncLookup("productcategory", Info{ + Display: "Product Category", + Category: "product", + Description: "Classification grouping similar products based on shared characteristics or functions", + Example: "clothing", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productCategory(r), nil + }, + }) + + AddFuncLookup("productfeature", Info{ + Display: "Product Feature", + Category: "product", + Description: "Specific characteristic of a product that distinguishes it from others products", + Example: "ultra-lightweight", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productFeature(r), nil + }, + }) + + AddFuncLookup("productmaterial", Info{ + Display: "Product Material", + Category: "product", + Description: "The substance from which a product is made, influencing its appearance, durability, and properties", + Example: "brass", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productMaterial(r), nil + }, + }) + + AddFuncLookup("productupc", Info{ + Display: "Product UPC", + Category: "product", + Description: "Standardized barcode used for product identification and tracking in retail and commerce", + Example: "012780949980", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return productUPC(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/school.go b/vendor/github.com/brianvoe/gofakeit/v6/school.go new file mode 100644 index 000000000..f90daef50 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/school.go @@ -0,0 +1,28 @@ +package gofakeit + +import "math/rand" + +// School will generate a random School type +func School() string { return school(globalFaker.Rand) } + +func (f *Faker) School() string { return school(f.Rand) } + +func school(r *rand.Rand) string { + return getRandValue( + r, []string{"school", "name"}) + " " + + getRandValue(r, []string{"school", "isPrivate"}) + " " + + getRandValue(r, []string{"school", "type"}) +} + +func addSchoolLookup() { + AddFuncLookup("school", Info{ + Display: "School", + Category: "school", + Description: "An institution for formal education and learning", + Example: `Harborview State Academy`, + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return school(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/slice.go b/vendor/github.com/brianvoe/gofakeit/v6/slice.go index 5f93fa5b3..eec5e43d9 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/slice.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/slice.go @@ -1,16 +1,15 @@ package gofakeit import ( - "math/rand" "reflect" ) // Slice fills built-in types and exported fields of a struct with random data. -func Slice(v interface{}) { sliceFunc(globalFaker.Rand, v) } +func Slice(v any) { sliceFunc(globalFaker, v) } // Slice fills built-in types and exported fields of a struct with random data. -func (f *Faker) Slice(v interface{}) { sliceFunc(f.Rand, v) } +func (f *Faker) Slice(v any) { sliceFunc(f, v) } -func sliceFunc(ra *rand.Rand, v interface{}) { - r(ra, reflect.TypeOf(v), reflect.ValueOf(v), "", -1) +func sliceFunc(f *Faker, v any) { + r(f, reflect.TypeOf(v), reflect.ValueOf(v), "", -1) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/sql.go b/vendor/github.com/brianvoe/gofakeit/v6/sql.go index 9434d8350..b9918b23a 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/sql.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/sql.go @@ -90,7 +90,7 @@ func sqlFunc(r *rand.Rand, so *SQLOptions) (string, error) { } // sqlConvertType will take in a type and value and convert it to the proper SQL type -func sqlConvertType(t string, val interface{}) string { +func sqlConvertType(t string, val any) string { switch t { case "string": return `'` + fmt.Sprintf("%v", val) + `'` @@ -105,12 +105,12 @@ func addDatabaseSQLLookup() { AddFuncLookup("sql", Info{ Display: "SQL", Category: "database", - Description: "Generates an object or an array of objects in json format", + Description: "Command in SQL used to add new data records into a database table", Example: `INSERT INTO people - (id, first_name, price, age, created_at) - VALUES - (1, 'Markus', 804.92, 21, '1937-01-30 07:58:01'), - (2, 'Santino', 235.13, 40, '1964-07-07 22:25:40');`, + (id, first_name, price, age, created_at) +VALUES + (1, 'Markus', 804.92, 21, '1937-01-30 07:58:01'), + (2, 'Santino', 235.13, 40, '1964-07-07 22:25:40');`, Output: "string", ContentType: "application/sql", Params: []Param{ @@ -118,7 +118,7 @@ func addDatabaseSQLLookup() { {Field: "count", Display: "Count", Type: "int", Default: "100", Description: "Number of inserts to generate"}, {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { so := SQLOptions{} table, err := info.GetString(m, "table") diff --git a/vendor/github.com/brianvoe/gofakeit/v6/string.go b/vendor/github.com/brianvoe/gofakeit/v6/string.go index 42461c021..778772bc0 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/string.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/string.go @@ -10,10 +10,10 @@ func (f *Faker) Letter() string { return letter(f.Rand) } func letter(r *rand.Rand) string { return string(randLetter(r)) } -// LetterN will generate a random ASCII string with length N +// LetterN will generate a random ASCII string with length N. Note that this function returns a string with a length of 1 when 0 is passed. func LetterN(n uint) string { return letterN(globalFaker.Rand, n) } -// LetterN will generate a random ASCII string with length N +// LetterN will generate a random ASCII string with length N. Note that this function returns a string with a length of 1 when 0 is passed. func (f *Faker) LetterN(n uint) string { return letterN(f.Rand, n) } func letterN(r *rand.Rand, n uint) string { @@ -44,10 +44,10 @@ func (f *Faker) Digit() string { return digit(f.Rand) } func digit(r *rand.Rand) string { return string(randDigit(r)) } -// DigitN will generate a random string of length N consists of ASCII digits (note it can start with 0). +// DigitN will generate a random string of length N consists of ASCII digits. Note that the string generated can start with 0 and this function returns a string with a length of 1 when 0 is passed. func DigitN(n uint) string { return digitN(globalFaker.Rand, n) } -// DigitN will generate a random string of length N consists of ASCII digits (note it can start with 0). +// DigitN will generate a random string of length N consists of ASCII digits. Note that the string generated can start with 0 and this function returns a string with a length of 1 when 0 is passed. func (f *Faker) DigitN(n uint) string { return digitN(f.Rand, n) } func digitN(r *rand.Rand, n uint) string { @@ -123,10 +123,10 @@ func addStringLookup() { AddFuncLookup("letter", Info{ Display: "Letter", Category: "string", - Description: "Generate a single random lower case ASCII letter", + Description: "Character or symbol from the American Standard Code for Information Interchange (ASCII) character set", Example: "g", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return letter(r), nil }, }) @@ -134,13 +134,13 @@ func addStringLookup() { AddFuncLookup("lettern", Info{ Display: "LetterN", Category: "string", - Description: "Generate a random ASCII string with length N", + Description: "ASCII string with length N", Example: "gbRMaRxHki", Output: "string", Params: []Param{ {Field: "count", Display: "Count", Type: "uint", Description: "Number of digits to generate"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ui, err := info.GetUint(m, "count") if err != nil { return nil, err @@ -153,10 +153,10 @@ func addStringLookup() { AddFuncLookup("vowel", Info{ Display: "Vowel", Category: "string", - Description: "Generate a single random lower case vowel", + Description: "Speech sound produced with an open vocal tract", Example: "a", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return vowel(r), nil }, }) @@ -164,10 +164,10 @@ func addStringLookup() { AddFuncLookup("digit", Info{ Display: "Digit", Category: "string", - Description: "Generate a single ASCII digit", + Description: "Numerical symbol used to represent numbers", Example: "0", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return digit(r), nil }, }) @@ -175,13 +175,13 @@ func addStringLookup() { AddFuncLookup("digitn", Info{ Display: "DigitN", Category: "string", - Description: "Generate a random string of length N consists of ASCII digits", + Description: "string of length N consisting of ASCII digits", Example: "0136459948", Output: "string", Params: []Param{ {Field: "count", Display: "Count", Type: "uint", Description: "Number of digits to generate"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { ui, err := info.GetUint(m, "count") if err != nil { return nil, err @@ -200,7 +200,7 @@ func addStringLookup() { Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "String value to replace #'s"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -219,7 +219,7 @@ func addStringLookup() { Params: []Param{ {Field: "str", Display: "String", Type: "string", Description: "String value to replace ?'s"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { str, err := info.GetString(m, "str") if err != nil { return nil, err @@ -239,7 +239,7 @@ func addStringLookup() { Params: []Param{ {Field: "strs", Display: "Strings", Type: "[]string", Description: "Delimited separated strings"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { strs, err := info.GetStringArray(m, "strs") if err != nil { return nil, err @@ -254,13 +254,13 @@ func addStringLookup() { AddFuncLookup("randomstring", Info{ Display: "Random String", Category: "string", - Description: "Randomly grab one string from array", + Description: "Return a random string from a string array", Example: "hello,world,whats,up => world", Output: "[]string", Params: []Param{ {Field: "strs", Display: "Strings", Type: "[]string", Description: "Delimited separated strings"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { strs, err := info.GetStringArray(m, "strs") if err != nil { return nil, err diff --git a/vendor/github.com/brianvoe/gofakeit/v6/struct.go b/vendor/github.com/brianvoe/gofakeit/v6/struct.go index b192dc8b2..c587ca17d 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/struct.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/struct.go @@ -2,7 +2,7 @@ package gofakeit import ( "errors" - "math/rand" + "fmt" "reflect" "strconv" "strings" @@ -10,100 +10,134 @@ import ( ) // Struct fills in exported fields of a struct with random data -// based on the value of `fake` tag of exported fields. +// based on the value of `fake` tag of exported fields +// or with the result of a call to the Fake() method +// if the field type implements `Fakeable`. // Use `fake:"skip"` to explicitly skip an element. // All built-in types are supported, with templating support // for string types. -func Struct(v interface{}) error { return structFunc(globalFaker.Rand, v) } +func Struct(v any) error { return structFunc(globalFaker, v) } // Struct fills in exported fields of a struct with random data // based on the value of `fake` tag of exported fields. // Use `fake:"skip"` to explicitly skip an element. // All built-in types are supported, with templating support // for string types. -func (f *Faker) Struct(v interface{}) error { return structFunc(f.Rand, v) } +func (f *Faker) Struct(v any) error { return structFunc(f, v) } -func structFunc(ra *rand.Rand, v interface{}) error { - return r(ra, reflect.TypeOf(v), reflect.ValueOf(v), "", 0) +func structFunc(f *Faker, v any) error { + return r(f, reflect.TypeOf(v), reflect.ValueOf(v), "", 0) } -func r(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func r(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { + // Handle special types + + if t.PkgPath() == "encoding/json" { + // encoding/json has two special types: + // - RawMessage + // - Number + + switch t.Name() { + case "RawMessage": + return rJsonRawMessage(f, t, v, tag, size) + case "Number": + return rJsonNumber(f, t, v, tag, size) + default: + return errors.New("unknown encoding/json type: " + t.Name()) + } + } + + // Handle generic types switch t.Kind() { case reflect.Ptr: - return rPointer(ra, t, v, tag, size) + return rPointer(f, t, v, tag, size) case reflect.Struct: - return rStruct(ra, t, v, tag) + return rStruct(f, t, v, tag) case reflect.String: - return rString(ra, v, tag) + return rString(f, t, v, tag) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return rUint(ra, t, v, tag) + return rUint(f, t, v, tag) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return rInt(ra, t, v, tag) + return rInt(f, t, v, tag) case reflect.Float32, reflect.Float64: - return rFloat(ra, t, v, tag) + return rFloat(f, t, v, tag) case reflect.Bool: - return rBool(ra, v, tag) + return rBool(f, t, v, tag) case reflect.Array, reflect.Slice: - return rSlice(ra, t, v, tag, size) + return rSlice(f, t, v, tag, size) case reflect.Map: - return rMap(ra, t, v, tag, size) + return rMap(f, t, v, tag, size) } return nil } -func rCustom(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rCustom(f *Faker, t reflect.Type, v reflect.Value, tag string) error { // If tag is empty return error if tag == "" { return errors.New("tag is empty") } fName, fParams := parseNameAndParamsFromTag(tag) - // Check to see if its a replaceable lookup function - if info := GetFuncLookup(fName); info != nil { - // Parse map params - mapParams := parseMapParams(info, fParams) + info := GetFuncLookup(fName) - // Call function - fValue, err := info.Generate(ra, mapParams, info) - if err != nil { - return err - } + // Check to see if it's a replaceable lookup function + if info == nil { + return fmt.Errorf("function %q not found", tag) + } - // Create new element of expected type - field := reflect.New(reflect.TypeOf(fValue)) - field.Elem().Set(reflect.ValueOf(fValue)) + // Parse map params + mapParams := parseMapParams(info, fParams) - // Check if element is pointer if so - // grab the underlyning value - fieldElem := field.Elem() - if fieldElem.Kind() == reflect.Ptr { - fieldElem = fieldElem.Elem() - } + // Call function + fValue, err := info.Generate(f.Rand, mapParams, info) + if err != nil { + return err + } - // Check if field kind is the same as the expected type - if fieldElem.Kind() != v.Kind() { - // return error saying the field and kinds that do not match - return errors.New("field kind " + fieldElem.Kind().String() + " does not match expected kind " + v.Kind().String()) - } + // Create new element of expected type + field := reflect.New(reflect.TypeOf(fValue)) + field.Elem().Set(reflect.ValueOf(fValue)) - // Set the value - v.Set(fieldElem) + // Check if element is pointer if so + // grab the underlying value + fieldElem := field.Elem() + if fieldElem.Kind() == reflect.Ptr { + fieldElem = fieldElem.Elem() + } - // If a function is called to set the struct - // stop from going through sub fields - return nil + // Check if field kind is the same as the expected type + if fieldElem.Kind() != v.Kind() { + // return error saying the field and kinds that do not match + return errors.New("field kind " + fieldElem.Kind().String() + " does not match expected kind " + v.Kind().String()) } - return errors.New("function not found") + // Set the value + v.Set(fieldElem.Convert(v.Type())) + + // If a function is called to set the struct + // stop from going through sub fields + return nil } -func rStruct(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rStruct(f *Faker, t reflect.Type, v reflect.Value, tag string) error { // Check if tag exists, if so run custom function if t.Name() != "" && tag != "" { - return rCustom(ra, t, v, tag) + return rCustom(f, t, v, tag) } + // Check if struct is fakeable + if isFakeable(t) { + value, err := callFake(f, v, reflect.Struct) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(value)) + return nil + } + + // Loop through all the fields of the struct n := t.NumField() for i := 0; i < n; i++ { elementT := t.Field(i) @@ -111,54 +145,93 @@ func rStruct(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { fakeTag, ok := elementT.Tag.Lookup("fake") // Check whether or not to skip this field - if ok && fakeTag == "skip" { + if ok && fakeTag == "skip" || fakeTag == "-" { // Do nothing, skip it continue } - // Check to make sure you can set it or that its an embeded(anonymous) field - if elementV.CanSet() || elementT.Anonymous { - // Check if reflect type is of values we can specifically set - switch elementT.Type.String() { - case "time.Time": - err := rTime(ra, elementT, elementV, fakeTag) - if err != nil { - return err - } - continue + // Check to make sure you can set it or that it's an embedded(anonymous) field + if !elementV.CanSet() && !elementT.Anonymous { + continue + } + + // Check if reflect type is of values we can specifically set + elemStr := elementT.Type.String() + switch elemStr { + case "time.Time", "*time.Time": + // Check if element is a pointer + elemV := elementV + if elemStr == "*time.Time" { + elemV = reflect.New(elementT.Type.Elem()).Elem() } - // Check if fakesize is set - size := -1 // Set to -1 to indicate fakesize was not set - fs, ok := elementT.Tag.Lookup("fakesize") - if ok { - var err error + // Run rTime on the element + err := rTime(f, elementT, elemV, fakeTag) + if err != nil { + return err + } + + if elemStr == "*time.Time" { + elementV.Set(elemV.Addr()) + } + + continue + } + + // Check if fakesize is set + size := -1 // Set to -1 to indicate fakesize was not set + fs, ok := elementT.Tag.Lookup("fakesize") + if ok { + var err error + + // Check if size has params separated by , + if strings.Contains(fs, ",") { + sizeSplit := strings.SplitN(fs, ",", 2) + if len(sizeSplit) == 2 { + var sizeMin int + var sizeMax int + + sizeMin, err = strconv.Atoi(sizeSplit[0]) + if err != nil { + return err + } + sizeMax, err = strconv.Atoi(sizeSplit[1]) + if err != nil { + return err + } + + size = f.Rand.Intn(sizeMax-sizeMin+1) + sizeMin + } + } else { size, err = strconv.Atoi(fs) if err != nil { return err } } - err := r(ra, elementT.Type, elementV, fakeTag, size) - if err != nil { - return err - } + } + + // Recursively call r() to fill in the struct + err := r(f, elementT.Type, elementV, fakeTag, size) + if err != nil { + return err } } return nil } -func rPointer(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func rPointer(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { elemT := t.Elem() if v.IsNil() { - nv := reflect.New(elemT) - err := r(ra, elemT, nv.Elem(), tag, size) + nv := reflect.New(elemT).Elem() + err := r(f, elemT, nv, tag, size) if err != nil { return err } - v.Set(nv) + + v.Set(nv.Addr()) } else { - err := r(ra, elemT, v.Elem(), tag, size) + err := r(f, elemT, v.Elem(), tag, size) if err != nil { return err } @@ -167,7 +240,7 @@ func rPointer(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size i return nil } -func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func rSlice(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { // If you cant even set it dont even try if !v.CanSet() { return errors.New("cannot set slice") @@ -176,10 +249,18 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int // Check if tag exists, if so run custom function if t.Name() != "" && tag != "" { // Check to see if custom function works if not continue to normal loop of values - err := rCustom(ra, t, v, tag) + err := rCustom(f, t, v, tag) if err == nil { return nil } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Slice) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(value)) + return nil } // Grab original size to use if needed for sub arrays @@ -189,7 +270,7 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int // use that instead of the requested size elemLen := v.Len() if elemLen == 0 && size == -1 { - size = number(ra, 1, 10) + size = number(f.Rand, 1, 10) } else if elemLen != 0 && (size == -1 || elemLen < size) { size = elemLen } @@ -200,7 +281,7 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int // Loop through the elements length and set based upon the index for i := 0; i < size; i++ { nv := reflect.New(elemT) - err := r(ra, elemT, nv.Elem(), tag, ogSize) + err := r(f, elemT, nv.Elem(), tag, ogSize) if err != nil { return err } @@ -216,21 +297,31 @@ func rSlice(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int return nil } -func rMap(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) error { +func rMap(f *Faker, t reflect.Type, v reflect.Value, tag string, size int) error { // If you cant even set it dont even try if !v.CanSet() { return errors.New("cannot set slice") } // Check if tag exists, if so run custom function - if t.Name() != "" && tag != "" { - return rCustom(ra, t, v, tag) + if tag != "" { + return rCustom(f, t, v, tag) + } else if size > 0 { + // NOOP + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Map) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(value)) + return nil } // Set a size newSize := size if newSize == -1 { - newSize = number(ra, 1, 10) + newSize = number(f.Rand, 1, 10) } // Create new map based upon map key value type @@ -240,14 +331,14 @@ func rMap(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) for i := 0; i < newSize; i++ { // Create new key mapIndex := reflect.New(t.Key()) - err := r(ra, t.Key(), mapIndex.Elem(), "", -1) + err := r(f, t.Key(), mapIndex.Elem(), "", -1) if err != nil { return err } // Create new value mapValue := reflect.New(t.Elem()) - err = r(ra, t.Elem(), mapValue.Elem(), "", -1) + err = r(f, t.Elem(), mapValue.Elem(), "", -1) if err != nil { return err } @@ -265,116 +356,196 @@ func rMap(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string, size int) return nil } -func rString(ra *rand.Rand, v reflect.Value, tag string) error { +func rString(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - v.SetString(generate(ra, tag)) + v.SetString(generate(f.Rand, tag)) + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.String) + if err != nil { + return err + } + + valueStr, ok := value.(string) + if !ok { + return errors.New("call to Fake method did not return a string") + } + v.SetString(valueStr) } else { - v.SetString(generate(ra, strings.Repeat("?", number(ra, 4, 10)))) + v.SetString(generate(f.Rand, strings.Repeat("?", number(f.Rand, 4, 10)))) } return nil } -func rInt(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rInt(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - i, err := strconv.ParseInt(generate(ra, tag), 10, 64) + i, err := strconv.ParseInt(generate(f.Rand, tag), 10, 64) if err != nil { return err } v.SetInt(i) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64) + if err != nil { + return err + } - // If no tag or error converting to int, set with random value - switch t.Kind() { - case reflect.Int: - v.SetInt(int64Func(ra)) - case reflect.Int8: - v.SetInt(int64(int8Func(ra))) - case reflect.Int16: - v.SetInt(int64(int16Func(ra))) - case reflect.Int32: - v.SetInt(int64(int32Func(ra))) - case reflect.Int64: - v.SetInt(int64Func(ra)) + switch i := value.(type) { + case int: + v.SetInt(int64(i)) + case int8: + v.SetInt(int64(i)) + case int16: + v.SetInt(int64(i)) + case int32: + v.SetInt(int64(i)) + case int64: + v.SetInt(int64(i)) + default: + return errors.New("call to Fake method did not return an integer") + } + } else { + // If no tag or error converting to int, set with random value + switch t.Kind() { + case reflect.Int: + v.SetInt(int64Func(f.Rand)) + case reflect.Int8: + v.SetInt(int64(int8Func(f.Rand))) + case reflect.Int16: + v.SetInt(int64(int16Func(f.Rand))) + case reflect.Int32: + v.SetInt(int64(int32Func(f.Rand))) + case reflect.Int64: + v.SetInt(int64Func(f.Rand)) + } } return nil } -func rUint(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rUint(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - u, err := strconv.ParseUint(generate(ra, tag), 10, 64) + u, err := strconv.ParseUint(generate(f.Rand, tag), 10, 64) if err != nil { return err } v.SetUint(u) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64) + if err != nil { + return err + } - // If no tag or error converting to uint, set with random value - switch t.Kind() { - case reflect.Uint: - v.SetUint(uint64Func(ra)) - case reflect.Uint8: - v.SetUint(uint64(uint8Func(ra))) - case reflect.Uint16: - v.SetUint(uint64(uint16Func(ra))) - case reflect.Uint32: - v.SetUint(uint64(uint32Func(ra))) - case reflect.Uint64: - v.SetUint(uint64Func(ra)) + switch i := value.(type) { + case uint: + v.SetUint(uint64(i)) + case uint8: + v.SetUint(uint64(i)) + case uint16: + v.SetUint(uint64(i)) + case uint32: + v.SetUint(uint64(i)) + case uint64: + v.SetUint(uint64(i)) + default: + return errors.New("call to Fake method did not return an unsigned integer") + } + } else { + // If no tag or error converting to uint, set with random value + switch t.Kind() { + case reflect.Uint: + v.SetUint(uint64Func(f.Rand)) + case reflect.Uint8: + v.SetUint(uint64(uint8Func(f.Rand))) + case reflect.Uint16: + v.SetUint(uint64(uint16Func(f.Rand))) + case reflect.Uint32: + v.SetUint(uint64(uint32Func(f.Rand))) + case reflect.Uint64: + v.SetUint(uint64Func(f.Rand)) + } } return nil } -func rFloat(ra *rand.Rand, t reflect.Type, v reflect.Value, tag string) error { +func rFloat(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - f, err := strconv.ParseFloat(generate(ra, tag), 64) + f, err := strconv.ParseFloat(generate(f.Rand, tag), 64) if err != nil { return err } v.SetFloat(f) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Float32, reflect.Float64) + if err != nil { + return err + } - // If no tag or error converting to float, set with random value - switch t.Kind() { - case reflect.Float64: - v.SetFloat(float64Func(ra)) - case reflect.Float32: - v.SetFloat(float64(float32Func(ra))) + switch i := value.(type) { + case float32: + v.SetFloat(float64(i)) + case float64: + v.SetFloat(float64(i)) + default: + return errors.New("call to Fake method did not return a float") + } + } else { + // If no tag or error converting to float, set with random value + switch t.Kind() { + case reflect.Float64: + v.SetFloat(float64Func(f.Rand)) + case reflect.Float32: + v.SetFloat(float64(float32Func(f.Rand))) + } } return nil } -func rBool(ra *rand.Rand, v reflect.Value, tag string) error { +func rBool(f *Faker, t reflect.Type, v reflect.Value, tag string) error { if tag != "" { - b, err := strconv.ParseBool(generate(ra, tag)) + b, err := strconv.ParseBool(generate(f.Rand, tag)) if err != nil { return err } v.SetBool(b) - return nil - } + } else if isFakeable(t) { + value, err := callFake(f, v, reflect.Bool) + if err != nil { + return err + } - // If no tag or error converting to boolean, set with random value - v.SetBool(boolFunc(ra)) + switch i := value.(type) { + case bool: + v.SetBool(bool(i)) + default: + return errors.New("call to Fake method did not return a boolean") + } + } else { + // If no tag or error converting to boolean, set with random value + v.SetBool(boolFunc(f.Rand)) + } return nil } // rTime will set a time.Time field the best it can from either the default date tag or from the generate tag -func rTime(ra *rand.Rand, t reflect.StructField, v reflect.Value, tag string) error { +func rTime(f *Faker, t reflect.StructField, v reflect.Value, tag string) error { if tag != "" { // Generate time - timeOutput := generate(ra, tag) + timeOutput := generate(f.Rand, tag) + + // Check to see if timeOutput has monotonic clock reading + // if so, remove it. This is because time.Parse() does not + // support parsing the monotonic clock reading + if strings.Contains(timeOutput, " m=") { + timeOutput = strings.Split(timeOutput, " m=")[0] + } // Check to see if they are passing in a format to parse the time timeFormat, timeFormatOK := t.Tag.Lookup("format") @@ -407,6 +578,6 @@ func rTime(ra *rand.Rand, t reflect.StructField, v reflect.Value, tag string) er return nil } - v.Set(reflect.ValueOf(date(ra))) + v.Set(reflect.ValueOf(date(f.Rand))) return nil } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/template.go b/vendor/github.com/brianvoe/gofakeit/v6/template.go new file mode 100644 index 000000000..329d6f78e --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/template.go @@ -0,0 +1,444 @@ +package gofakeit + +import ( + "bytes" + "fmt" + "strconv" + "time" + + "math/rand" + "reflect" + "strings" + "text/template" +) + +// TemplateOptions defines values needed for template document generation +type TemplateOptions struct { + Funcs template.FuncMap `fake:"-"` + Data any `json:"data" xml:"data" fake:"-"` +} + +// Template generates an document based on the the supplied template +func Template(template string, co *TemplateOptions) (string, error) { + if co == nil { + co = &TemplateOptions{} + globalFaker.Struct(co) + } + return templateFunc(template, templateFuncMap(globalFaker.Rand, &co.Funcs), co) +} + +// Template generates an document based on the the supplied template +func (f *Faker) Template(template string, co *TemplateOptions) (string, error) { + if co == nil { + co = &TemplateOptions{} + f.Struct(co) + } + return templateFunc(template, templateFuncMap(f.Rand, &co.Funcs), co) +} + +// MarkdownOptions defines values needed for markdown document generation +type MarkdownOptions struct { +} + +// Template for Markdown +const templateMarkdown = ` +{{$repo := Gamertag}} +{{$language := RandomString (SliceString "go" "python" "javascript")}} +{{$username := Gamertag}} +{{$weightedSlice := SliceAny "github.com" "gitlab.com" "bitbucket.org"}} +{{$weightedWeights := SliceF32 5 1 1}} +{{$domain := Weighted $weightedSlice $weightedWeights}} +{{$action := RandomString (SliceString "process" "run" "execute" "perform" "handle")}} +{{$usage := RandomString (SliceString "whimsical story" "quirky message" "playful alert" "funny request" "lighthearted command")}} +{{$result := RandomString (SliceString "success" "error" "unknown" "completed" "failed" "finished" "in progress" "terminated")}} + +# {{$repo}} + +*Author: {{FirstName}} {{LastName}}* + +{{Paragraph 2 5 7 "\n\n"}} + +## Table of Contents +- [Installation](#installation) +- [Usage](#usage) +- [License](#license) + +## Installation +{{if eq $language "go"}}'''go +go get {{$domain}}/{{$username}}/{{$repo}} +'''{{else if eq $language "python"}}'''bash +pip install {{$repo}} +'''{{else if eq $language "javascript"}}'''js +npm install {{$repo}} +'''{{end}} + +## Usage +{{if eq $language "go"}}'''go +result := {{$repo}}.{{$action}}("{{ToLower $usage}}") +fmt.Println("{{ToLower $repo}} result:", "{{ToLower $result}}") +'''{{else if eq $language "python"}}'''python +result = {{ToLower $repo}}.{{$action}}("{{ToLower $usage}}") +print("{{ToLower $repo}} result:", "{{ToLower $result}}") +'''{{else if eq $language "javascript"}}'''javascript +const result = {{ToLower $repo}}.{{$action}}("{{ToLower $usage}}"); +console.log("{{ToLower $repo}} result:", "{{ToLower $result}}"); +'''{{end}} + +## License +{{RandomString (SliceString "MIT" "Apache 2.0" "GPL-3.0" "BSD-3-Clause" "ISC")}} +` + +// Markdown will return a single random Markdown template document +func Markdown(co *MarkdownOptions) (string, error) { + if co == nil { + co = &MarkdownOptions{} + globalFaker.Struct(co) + } + return templateFunc(templateMarkdown, templateFuncMap(globalFaker.Rand, nil), co) +} + +// Markdown will return a single random Markdown template document +func (f *Faker) Markdown(co *MarkdownOptions) (string, error) { + if co == nil { + co = &MarkdownOptions{} + f.Struct(co) + } + return templateFunc(templateMarkdown, templateFuncMap(f.Rand, nil), co) +} + +// EmailOptions defines values needed for email document generation +type EmailOptions struct { +} + +// Template for email text +const templateEmail = ` +Subject: {{RandomString (SliceString "Greetings" "Hello" "Hi")}} from {{FirstName}}! + +Dear {{LastName}}, + +{{RandomString (SliceString "Greetings!" "Hello there!" "Hi, how are you?")}} {{RandomString (SliceString "How's everything going?" "I hope your day is going well." "Sending positive vibes your way.")}} + +{{RandomString (SliceString "I trust this email finds you well." "I hope you're doing great." "Hoping this message reaches you in good spirits.")}} {{RandomString (SliceString "Wishing you a fantastic day!" "May your week be filled with joy." "Sending good vibes your way.")}} + +{{Paragraph 3 5 10 "\n\n"}} + +{{RandomString (SliceString "I would appreciate your thoughts on" "I'm eager to hear your feedback on" "I'm curious to know what you think about")}} it. If you have a moment, please feel free to check out the project on {{RandomString (SliceString "GitHub" "GitLab" "Bitbucket")}} + +{{RandomString (SliceString "Your insights would be invaluable." "I'm eager to hear what you think." "Feel free to share your opinions with me.")}} {{RandomString (SliceString "Looking forward to your feedback!" "Your perspective is highly valued." "Your thoughts matter to me.")}} + +{{RandomString (SliceString "Thank you for your consideration!" "I appreciate your attention to this matter." "Your support means a lot to me.")}} {{RandomString (SliceString "Wishing you a wonderful day!" "Thanks in advance for your time." "Your feedback is greatly appreciated.")}} + +{{RandomString (SliceString "Warm regards" "Best wishes" "Kind regards" "Sincerely" "With gratitude")}} +{{FirstName}} {{LastName}} +{{Email}} +{{PhoneFormatted}} +` + +// EmailText will return a single random text email template document +func EmailText(co *EmailOptions) (string, error) { + if co == nil { + co = &EmailOptions{} + globalFaker.Struct(co) + } + return templateFunc(templateEmail, templateFuncMap(globalFaker.Rand, nil), co) +} + +// EmailText will return a single random text email template document +func (f *Faker) EmailText(co *EmailOptions) (string, error) { + if co == nil { + co = &EmailOptions{} + f.Struct(co) + } + return templateFunc(templateEmail, templateFuncMap(f.Rand, nil), co) +} + +// functions that wont work with template engine +var templateExclusion = []string{ + "RandomMapKey", + "SQL", + "Template", +} + +// Build the template.FuncMap for the template engine +func templateFuncMap(r *rand.Rand, fm *template.FuncMap) *template.FuncMap { + + // create a new function map + funcMap := template.FuncMap{} + + // build the function map from a faker using their rand + f := &Faker{Rand: r} + + v := reflect.ValueOf(f) + + // loop through the methods + for i := 0; i < v.NumMethod(); i++ { + // check if the method is in the exclusion list + if stringInSlice(v.Type().Method(i).Name, templateExclusion) { + continue + } + + // Check if method has return values + // If not don't add to function map + if v.Type().Method(i).Type.NumOut() == 0 { + continue + } + + // add the method to the function map + funcMap[v.Type().Method(i).Name] = v.Method(i).Interface() + } + + // make string upper case + funcMap["ToUpper"] = strings.ToUpper + + // make string lower case + funcMap["ToLower"] = strings.ToLower + + // make string title case + funcMap["IntRange"] = func(start, end int) []int { + n := end - start + 1 + result := make([]int, n) + for i := 0; i < n; i++ { + result[i] = start + i + } + return result + } + + // enable passing any type to return a string + funcMap["ToInt"] = func(args any) int { + switch v := args.(type) { + case string: + i, err := strconv.Atoi(v) + if err != nil { + return 0 + } + + return i + case float64: + return int(v) + case float32: + return int(v) + case int: + return v + + // Anything else return 0 + default: + return 0 + } + } + + // enable passing any type to return a float64 + funcMap["ToFloat"] = func(args any) float64 { + switch v := args.(type) { + case string: + i, err := strconv.ParseFloat(v, 64) + if err != nil { + return 0 + } + + return i + case float64: + return v + case float32: + return float64(v) + case int: + return float64(v) + + // Anything else return 0 + default: + return 0 + } + } + + // ensable passing any type to return a string + funcMap["ToString"] = func(args any) string { + switch v := args.(type) { + case string: + return v + case float64: + return strconv.FormatFloat(v, 'f', -1, 64) + case float32: + return strconv.FormatFloat(float64(v), 'f', -1, 32) + case int: + return strconv.Itoa(v) + + // Anything else return empty string + default: + return "" + } + } + + // function to convert string to date time + funcMap["ToDate"] = func(dateString string) time.Time { + date, err := time.Parse("2006-01-02", dateString) + if err != nil { + return time.Now() + } + return date + } + + // enable passing slice of interface to functions + funcMap["SliceAny"] = func(args ...any) []any { + return args + } + + // enable passing slice of string to functions + funcMap["SliceString"] = func(args ...string) []string { + return args + } + + // enable passing slice of uint to functions + funcMap["SliceUInt"] = func(args ...uint) []uint { + return args + } + + // enable passing slice of int to functions + funcMap["SliceInt"] = func(args ...int) []int { + return args + } + + // enable passing slice of int to functions + funcMap["SliceF32"] = func(args ...float32) []float32 { + return args + } + + // Add passed in function map to the function map + if fm != nil { + for k, v := range *fm { + funcMap[k] = v + } + } + + return &funcMap +} + +// function to build the function map for the template engine from the global faker +func templateFunc(temp string, funcs *template.FuncMap, data any) (string, error) { + if temp == "" { + return "", fmt.Errorf("template parameter is empty") + } + + // Create a new template and parse + template_gen, err := template.New("CodeRun").Funcs(*funcs).Parse(temp) + if err != nil { + return "", err + } + + b := &bytes.Buffer{} + err = template_gen.Execute(b, data) + if err != nil { + return "", err + } + + // Return the result + return strings.ReplaceAll(b.String(), "\\n", "\n"), nil + +} + +// addTemplateLookup will add the template functions to the global lookup +func addTemplateLookup() { + AddFuncLookup("template", Info{ + Display: "Template", + Category: "template", + Description: "Generates document from template", + Example: `{{Firstname}} {{Lastname}} + +// output +Markus Moen`, + Output: "string", + ContentType: "text/plain", + Params: []Param{ + {Field: "template", Display: "Template", Type: "string", Description: "Golang template to generate the document from"}, + {Field: "data", Display: "Custom Data", Type: "string", Default: "", Optional: true, Description: "Custom data to pass to the template"}, + }, + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + tpl, err := info.GetString(m, "template") + if err != nil { + return nil, err + } + + data, err := info.GetAny(m, "data") + if err != nil { + return nil, err + } + + templateOut, err := templateFunc(tpl, templateFuncMap(r, nil), &TemplateOptions{Data: data}) + if err != nil { + return nil, err + } + + return templateOut, nil + }, + }) + + AddFuncLookup("markdown", Info{ + Display: "Random markdown document", + Category: "template", + Description: "Lightweight markup language used for formatting plain text", + Example: `# PurpleSheep5 + +*Author: Amie Feil* + +Quarterly without week it hungry thing someone. Him regularly today whomever this revolt hence. From his timing as quantity us these. Yours live these frantic not may another. How this ours his them those whose. + +Them batch its Iraqi most that few. Abroad cheese this whereas next how there. Gorgeous genetics time choir fiction therefore yourselves. Am those infrequently heap software quarterly rather. Punctuation yellow where several his orchard to. + +## Table of Contents +- [Installation](#installation) +- [Usage](#usage) +- [License](#license) + +## Installation +'''bash +pip install PurpleSheep5 +''' + +## Usage +'''python +result = purplesheep5.process("funny request") +print("purplesheep5 result:", "in progress") +''' + +## License +MIT`, + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + template_result, err := templateFunc(templateMarkdown, templateFuncMap(r, nil), &MarkdownOptions{}) + return string(template_result), err + }, + }) + + AddFuncLookup("email_text", Info{ + Display: "Random text email Document", + Category: "template", + Description: "Written content of an email message, including the sender's message to the recipient", + Example: `Subject: Greetings from Marcel! + +Dear Pagac, + +Hello there! Sending positive vibes your way. + +I hope you're doing great. May your week be filled with joy. + +Virtually woman where team late quarterly without week it hungry. Thing someone him regularly today whomever this revolt hence from. His timing as quantity us these yours live these frantic. Not may another how this ours his them those whose. Them batch its Iraqi most that few abroad cheese this. + +Whereas next how there gorgeous genetics time choir fiction therefore. Yourselves am those infrequently heap software quarterly rather punctuation yellow. Where several his orchard to frequently hence victorious boxers each. Does auspicious yourselves first soup tomorrow this that must conclude. Anyway some yearly who cough laugh himself both yet rarely. + +Me dolphin intensely block would leap plane us first then. Down them eager would hundred super throughout animal yet themselves. Been group flock shake part purchase up usually it her. None it hers boat what their there Turkmen moreover one. Lebanese to brace these shower in it everybody should whatever. + +I'm curious to know what you think about it. If you have a moment, please feel free to check out the project on Bitbucket + +I'm eager to hear what you think. Looking forward to your feedback! + +Thank you for your consideration! Thanks in advance for your time. + +Kind regards +Milford Johnston +jamelhaag@king.org +(507)096-3058`, + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + template_result, err := templateFunc(templateEmail, templateFuncMap(r, nil), &EmailOptions{}) + return string(template_result), err + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/time.go b/vendor/github.com/brianvoe/gofakeit/v6/time.go index ca8d2514e..ecd0c1cac 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/time.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/time.go @@ -14,7 +14,27 @@ func Date() time.Time { return date(globalFaker.Rand) } func (f *Faker) Date() time.Time { return date(f.Rand) } func date(r *rand.Rand) time.Time { - return time.Date(year(r), time.Month(number(r, 1, 12)), day(r), hour(r), minute(r), second(r), nanoSecond(r), time.UTC) + return time.Date(year(r), time.Month(month(r)), day(r), hour(r), minute(r), second(r), nanoSecond(r), time.UTC) +} + +// FutureDate will generate a random past time.Time struct +func PastDate() time.Time { return pastDate(globalFaker.Rand) } + +// FutureDate will generate a random past time.Time struct +func (f *Faker) PastDate() time.Time { return pastDate(f.Rand) } + +func pastDate(r *rand.Rand) time.Time { + return time.Now().Add(time.Hour * -time.Duration(number(r, 1, 12))) +} + +// FutureDate will generate a random future time.Time struct +func FutureDate() time.Time { return futureDate(globalFaker.Rand) } + +// FutureDate will generate a random future time.Time struct +func (f *Faker) FutureDate() time.Time { return futureDate(f.Rand) } + +func futureDate(r *rand.Rand) time.Time { + return time.Now().Add(time.Hour * time.Duration(number(r, 1, 12))) } // DateRange will generate a random time.Time struct between a start and end date @@ -193,7 +213,7 @@ func addDateTimeLookup() { AddFuncLookup("date", Info{ Display: "Date", Category: "time", - Description: "Random date", + Description: "Representation of a specific day, month, and year, often used for chronological reference", Example: "2006-01-02T15:04:05Z07:00", Output: "string", Params: []Param{ @@ -206,7 +226,7 @@ func addDateTimeLookup() { Description: "Date time string format output. You may also use golang time format or java time format", }, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { format, err := info.GetString(m, "format") if err != nil { return nil, err @@ -272,7 +292,7 @@ func addDateTimeLookup() { Description: "Date time string format", }, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { format, err := info.GetString(m, "format") if err != nil { return nil, err @@ -301,13 +321,35 @@ func addDateTimeLookup() { }, }) + AddFuncLookup("pasttime", Info{ + Display: "PastTime", + Category: "time", + Description: "Date that has occurred before the current moment in time", + Example: "2007-01-24 13:00:35.820738079 +0000 UTC", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return pastDate(r), nil + }, + }) + + AddFuncLookup("futuretime", Info{ + Display: "FutureTime", + Category: "time", + Description: "Date that has occurred after the current moment in time", + Example: "2107-01-24 13:00:35.820738079 +0000 UTC", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return futureDate(r), nil + }, + }) + AddFuncLookup("nanosecond", Info{ Display: "Nanosecond", Category: "time", - Description: "Random nanosecond", + Description: "Unit of time equal to One billionth (10^-9) of a second", Example: "196446360", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nanoSecond(r), nil }, }) @@ -315,10 +357,10 @@ func addDateTimeLookup() { AddFuncLookup("second", Info{ Display: "Second", Category: "time", - Description: "Random second", + Description: "Unit of time equal to 1/60th of a minute", Example: "43", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return second(r), nil }, }) @@ -326,10 +368,10 @@ func addDateTimeLookup() { AddFuncLookup("minute", Info{ Display: "Minute", Category: "time", - Description: "Random minute", + Description: "Unit of time equal to 60 seconds", Example: "34", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return minute(r), nil }, }) @@ -337,10 +379,10 @@ func addDateTimeLookup() { AddFuncLookup("hour", Info{ Display: "Hour", Category: "time", - Description: "Random hour", + Description: "Unit of time equal to 60 minutes", Example: "8", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return hour(r), nil }, }) @@ -348,10 +390,10 @@ func addDateTimeLookup() { AddFuncLookup("day", Info{ Display: "Day", Category: "time", - Description: "Random day", + Description: "24-hour period equivalent to one rotation of Earth on its axis", Example: "12", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return day(r), nil }, }) @@ -359,10 +401,10 @@ func addDateTimeLookup() { AddFuncLookup("weekday", Info{ Display: "Weekday", Category: "time", - Description: "Random week day", + Description: "Day of the week excluding the weekend", Example: "Friday", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return weekDay(r), nil }, }) @@ -370,10 +412,10 @@ func addDateTimeLookup() { AddFuncLookup("month", Info{ Display: "Month", Category: "time", - Description: "Random month", + Description: "Division of the year, typically 30 or 31 days long", Example: "1", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return month(r), nil }, }) @@ -381,10 +423,10 @@ func addDateTimeLookup() { AddFuncLookup("monthstring", Info{ Display: "Month String", Category: "time", - Description: "Random month in string output", + Description: "String Representation of a month name", Example: "September", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return monthString(r), nil }, }) @@ -392,10 +434,10 @@ func addDateTimeLookup() { AddFuncLookup("year", Info{ Display: "Year", Category: "time", - Description: "Random year", + Description: "Period of 365 days, the time Earth takes to orbit the Sun", Example: "1900", Output: "int", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return year(r), nil }, }) @@ -403,10 +445,10 @@ func addDateTimeLookup() { AddFuncLookup("timezone", Info{ Display: "Timezone", Category: "time", - Description: "Random timezone", + Description: "Region where the same standard time is used, based on longitudinal divisions of the Earth", Example: "Kaliningrad Standard Time", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZone(r), nil }, }) @@ -414,10 +456,10 @@ func addDateTimeLookup() { AddFuncLookup("timezoneabv", Info{ Display: "Timezone Abbreviation", Category: "time", - Description: "Random abbreviated timezone", + Description: "Abbreviated 3-letter word of a timezone", Example: "KST", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneAbv(r), nil }, }) @@ -425,10 +467,10 @@ func addDateTimeLookup() { AddFuncLookup("timezonefull", Info{ Display: "Timezone Full", Category: "time", - Description: "Random full timezone", + Description: "Full name of a timezone", Example: "(UTC+03:00) Kaliningrad, Minsk", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneFull(r), nil }, }) @@ -436,10 +478,10 @@ func addDateTimeLookup() { AddFuncLookup("timezoneoffset", Info{ Display: "Timezone Offset", Category: "time", - Description: "Random timezone offset", + Description: "The difference in hours from Coordinated Universal Time (UTC) for a specific region", Example: "3", Output: "float32", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneOffset(r), nil }, }) @@ -447,10 +489,10 @@ func addDateTimeLookup() { AddFuncLookup("timezoneregion", Info{ Display: "Timezone Region", Category: "time", - Description: "Random region timezone", + Description: "Geographic area sharing the same standard time", Example: "America/Alaska", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return timeZoneRegion(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/weighted.go b/vendor/github.com/brianvoe/gofakeit/v6/weighted.go index 22ead1162..c04fa6bd3 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/weighted.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/weighted.go @@ -6,17 +6,17 @@ import ( ) // Weighted will take in an array of options and weights and return a random selection based upon its indexed weight -func Weighted(options []interface{}, weights []float32) (interface{}, error) { +func Weighted(options []any, weights []float32) (any, error) { return weighted(globalFaker.Rand, options, weights) } // Weighted will take in an array of options and weights and return a random selection based upon its indexed weight -func (f *Faker) Weighted(options []interface{}, weights []float32) (interface{}, error) { +func (f *Faker) Weighted(options []any, weights []float32) (any, error) { return weighted(f.Rand, options, weights) } // Weighted will take in an array of options and weights and return a random selection based upon its indexed weight -func weighted(r *rand.Rand, options []interface{}, weights []float32) (interface{}, error) { +func weighted(r *rand.Rand, options []any, weights []float32) (any, error) { ol := len(options) wl := len(weights) @@ -85,7 +85,7 @@ func addWeightedLookup() { {Field: "options", Display: "Options", Type: "[]string", Description: "Array of any values"}, {Field: "weights", Display: "Weights", Type: "[]float", Description: "Array of weights"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { options, err := info.GetStringArray(m, "options") if err != nil { return nil, err @@ -96,7 +96,7 @@ func addWeightedLookup() { return nil, err } - optionsInterface := make([]interface{}, len(options)) + optionsInterface := make([]any, len(options)) for i, o := range options { optionsInterface[i] = o } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go b/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go index 834c2259c..c9fcbd8ec 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_adjective.go @@ -95,10 +95,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjective", Info{ Display: "Adjective", Category: "word", - Description: "Random adjective", + Description: "Word describing or modifying a noun", Example: "genuine", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjective(r), nil }, }) @@ -106,10 +106,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivedescriptive", Info{ Display: "Descriptive Adjective", Category: "word", - Description: "Random descriptive adjective", + Description: "Adjective that provides detailed characteristics about a noun", Example: "brave", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveDescriptive(r), nil }, }) @@ -117,10 +117,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivequantitative", Info{ Display: "Quantitative Adjective", Category: "word", - Description: "Random quantitative adjective", + Description: "Adjective that indicates the quantity or amount of something", Example: "a little", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveQuantitative(r), nil }, }) @@ -128,10 +128,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectiveproper", Info{ Display: "Proper Adjective", Category: "word", - Description: "Random proper adjective", + Description: "Adjective derived from a proper noun, often used to describe nationality or origin", Example: "Afghan", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveProper(r), nil }, }) @@ -139,10 +139,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivedemonstrative", Info{ Display: "Demonstrative Adjective", Category: "word", - Description: "Random demonstrative adjective", + Description: "Adjective used to point out specific things", Example: "this", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveDemonstrative(r), nil }, }) @@ -150,10 +150,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectivepossessive", Info{ Display: "Possessive Adjective", Category: "word", - Description: "Random possessive adjective", + Description: "Adjective indicating ownership or possession", Example: "my", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectivePossessive(r), nil }, }) @@ -161,10 +161,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectiveinterrogative", Info{ Display: "Interrogative Adjective", Category: "word", - Description: "Random interrogative adjective", + Description: "Adjective used to ask questions", Example: "what", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveInterrogative(r), nil }, }) @@ -172,10 +172,10 @@ func addWordAdjectiveLookup() { AddFuncLookup("adjectiveindefinite", Info{ Display: "Indefinite Adjective", Category: "word", - Description: "Random indefinite adjective", + Description: "Adjective describing a non-specific noun", Example: "few", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adjectiveIndefinite(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go b/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go index e2e196452..b148bf8d3 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_adverb.go @@ -89,10 +89,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverb", Info{ Display: "Adverb", Category: "word", - Description: "Random adverb", + Description: "Word that modifies verbs, adjectives, or other adverbs", Example: "smoothly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverb(r), nil }, }) @@ -100,10 +100,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbmanner", Info{ Display: "Adverb Manner", Category: "word", - Description: "Random manner adverb", + Description: "Adverb that describes how an action is performed", Example: "stupidly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbManner(r), nil }, }) @@ -111,10 +111,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbdegree", Info{ Display: "Adverb Degree", Category: "word", - Description: "Random degree adverb", + Description: "Adverb that indicates the degree or intensity of an action or adjective", Example: "intensely", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbDegree(r), nil }, }) @@ -122,10 +122,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbplace", Info{ Display: "Adverb Place", Category: "word", - Description: "Random place adverb", + Description: "Adverb that indicates the location or direction of an action", Example: "east", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbPlace(r), nil }, }) @@ -133,10 +133,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbtimedefinite", Info{ Display: "Adverb Time Definite", Category: "word", - Description: "Random time definite adverb", + Description: "Adverb that specifies the exact time an action occurs", Example: "now", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbTimeDefinite(r), nil }, }) @@ -144,10 +144,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbtimeindefinite", Info{ Display: "Adverb Time Indefinite", Category: "word", - Description: "Random time indefinite adverb", + Description: "Adverb that gives a general or unspecified time frame", Example: "already", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbTimeIndefinite(r), nil }, }) @@ -155,10 +155,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbfrequencydefinite", Info{ Display: "Adverb Frequency Definite", Category: "word", - Description: "Random frequency definite adverb", + Description: "Adverb that specifies how often an action occurs with a clear frequency", Example: "hourly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbFrequencyDefinite(r), nil }, }) @@ -166,10 +166,10 @@ func addWordAdverbLookup() { AddFuncLookup("adverbfrequencyindefinite", Info{ Display: "Adverb Frequency Indefinite", Category: "word", - Description: "Random frequency indefinite adverb", + Description: "Adverb that specifies how often an action occurs without specifying a particular frequency", Example: "occasionally", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return adverbFrequencyIndefinite(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_comment.go b/vendor/github.com/brianvoe/gofakeit/v6/word_comment.go new file mode 100644 index 000000000..3f5d3e419 --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_comment.go @@ -0,0 +1,73 @@ +package gofakeit + +import ( + "math/rand" + "strings" +) + +// Comment will generate a random statement or remark expressing an opinion, observation, or reaction +func Comment() string { return comment(globalFaker.Rand) } + +// Comment will generate a random statement or remark expressing an opinion, observation, or reaction +func (f *Faker) Comment() string { return comment(f.Rand) } + +func comment(r *rand.Rand) string { + structures := [][]string{ + {"interjection", "adjective", "noun", "verb", "adverb"}, + {"noun", "verb", "preposition", "determiner", "adjective", "noun"}, + {"noun", "verb", "adverb"}, + {"adjective", "noun", "verb"}, + {"noun", "verb", "preposition", "noun"}, + } + + // Randomly select a structure + structure := structures[number(r, 0, len(structures)-1)] + + // Build the sentence + var commentParts []string + for _, wordType := range structure { + switch wordType { + case "noun": + commentParts = append(commentParts, noun(r)) + case "verb": + commentParts = append(commentParts, verb(r)) + case "adjective": + commentParts = append(commentParts, adjective(r)) + case "adverb": + commentParts = append(commentParts, adverb(r)) + case "interjection": + commentParts = append(commentParts, interjection(r)) + case "preposition": + commentParts = append(commentParts, preposition(r)) + case "determiner": + commentParts = append(commentParts, nounDeterminer(r)) + default: + // Should never hit + panic("Invalid word type") + } + } + + // Combine the words into a sentence + sentence := strings.Join(commentParts, " ") + + // Capitalize the first letter + sentence = title(sentence) + + // Add a period to the end of the sentence + sentence = sentence + "." + + return sentence +} + +func addWordCommentLookup() { + AddFuncLookup("comment", Info{ + Display: "Comment", + Category: "word", + Description: "Statement or remark expressing an opinion, observation, or reaction", + Example: "wow", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return interjection(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go b/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go index ea4745f68..5be26166c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_connective.go @@ -31,14 +31,14 @@ func connectiveTime(r *rand.Rand) string { return getRandValue(r, []string{"word", "connective_time"}) } -// ConnectiveComparitive will generate a random comparative connective -func ConnectiveComparitive() string { return connectiveComparitive(globalFaker.Rand) } +// ConnectiveComparative will generate a random comparative connective +func ConnectiveComparative() string { return connectiveComparative(globalFaker.Rand) } -// ConnectiveComparitive will generate a random comparative connective -func (f *Faker) ConnectiveComparitive() string { return connectiveComparitive(f.Rand) } +// ConnectiveComparative will generate a random comparative connective +func (f *Faker) ConnectiveComparative() string { return connectiveComparative(f.Rand) } -func connectiveComparitive(r *rand.Rand) string { - return getRandValue(r, []string{"word", "connective_comparitive"}) +func connectiveComparative(r *rand.Rand) string { + return getRandValue(r, []string{"word", "connective_comparative"}) } // ConnectiveComplaint will generate a random complaint connective @@ -85,10 +85,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connective", Info{ Display: "Connective", Category: "word", - Description: "Random connective word", + Description: "Word used to connect words or sentences", Example: "such as", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connective(r), nil }, }) @@ -96,32 +96,32 @@ func addWordConnectiveLookup() { AddFuncLookup("connectivetime", Info{ Display: "Connective Time", Category: "word", - Description: "Random connective time word", + Description: "Connective word used to indicate a temporal relationship between events or actions", Example: "finally", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveTime(r), nil }, }) - AddFuncLookup("connectivecomparitive", Info{ + AddFuncLookup("connectivecomparative", Info{ Display: "Connective Comparitive", Category: "word", - Description: "Random connective comparative word", + Description: "Connective word used to indicate a comparison between two or more things", Example: "in addition", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { - return connectiveComparitive(r), nil + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return connectiveComparative(r), nil }, }) AddFuncLookup("connectivecomplaint", Info{ Display: "Connective Complaint", Category: "word", - Description: "Random connective complaint word", + Description: "Connective word used to express dissatisfaction or complaints about a situation", Example: "besides", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveComplaint(r), nil }, }) @@ -129,10 +129,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connectivelisting", Info{ Display: "Connective Listing", Category: "word", - Description: "Random connective listing word", + Description: "Connective word used to list or enumerate items or examples", Example: "firstly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveListing(r), nil }, }) @@ -140,10 +140,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connectivecasual", Info{ Display: "Connective Casual", Category: "word", - Description: "Random connective casual word", + Description: "Connective word used to indicate a cause-and-effect relationship between events or actions", Example: "an outcome of", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveCasual(r), nil }, }) @@ -151,10 +151,10 @@ func addWordConnectiveLookup() { AddFuncLookup("connectiveexamplify", Info{ Display: "Connective Examplify", Category: "word", - Description: "Random connective examplify word", + Description: "Connective word used to provide examples or illustrations of a concept or idea", Example: "then", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return connectiveExamplify(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_general.go b/vendor/github.com/brianvoe/gofakeit/v6/word_general.go index cfa2a56b1..d2a84f920 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_general.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_general.go @@ -28,10 +28,10 @@ func addWordGeneralLookup() { AddFuncLookup("word", Info{ Display: "Word", Category: "word", - Description: "Random word", + Description: "Basic unit of language representing a concept or thing, consisting of letters and having meaning", Example: "man", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return word(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go b/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go index 4079f0231..77722d76c 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_grammar.go @@ -25,10 +25,10 @@ func addWordGrammerLookup() { AddFuncLookup("sentencesimple", Info{ Display: "Simple Sentence", Category: "word", - Description: "Random simple sentence", + Description: "Group of words that expresses a complete thought", Example: "A tribe fly the lemony kitchen.", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return sentenceSimple(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_misc.go b/vendor/github.com/brianvoe/gofakeit/v6/word_misc.go new file mode 100644 index 000000000..59d47e59f --- /dev/null +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_misc.go @@ -0,0 +1,24 @@ +package gofakeit + +import "math/rand" + +// Interjection will generate a random word expressing emotion +func Interjection() string { return interjection(globalFaker.Rand) } + +// Interjection will generate a random word expressing emotion +func (f *Faker) Interjection() string { return interjection(f.Rand) } + +func interjection(r *rand.Rand) string { return getRandValue(r, []string{"word", "interjection"}) } + +func addWordMiscLookup() { + AddFuncLookup("interjection", Info{ + Display: "Interjection", + Category: "word", + Description: "Word expressing emotion", + Example: "wow", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return interjection(r), nil + }, + }) +} diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go b/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go index 3dec9396d..fbf9e806e 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_noun.go @@ -111,14 +111,22 @@ func nounProper(r *rand.Rand) string { return getRandValue(r, []string{"person", "first"}) } +// NounDeterminer will generate a random noun determiner +func NounDeterminer() string { return nounDeterminer(globalFaker.Rand) } + +// NounDeterminer will generate a random noun determiner +func (f *Faker) NounDeterminer() string { return nounDeterminer(f.Rand) } + +func nounDeterminer(r *rand.Rand) string { return getRandValue(r, []string{"word", "noun_determiner"}) } + func addWordNounLookup() { AddFuncLookup("noun", Info{ Display: "Noun", Category: "word", - Description: "Random noun", + Description: "Person, place, thing, or idea, named or referred to in a sentence", Example: "aunt", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return noun(r), nil }, }) @@ -126,10 +134,10 @@ func addWordNounLookup() { AddFuncLookup("nouncommon", Info{ Display: "Noun Common", Category: "word", - Description: "Random common noun", + Description: "General name for people, places, or things, not specific or unique", Example: "part", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCommon(r), nil }, }) @@ -137,10 +145,10 @@ func addWordNounLookup() { AddFuncLookup("nounconcrete", Info{ Display: "Noun Concrete", Category: "word", - Description: "Random concrete noun", + Description: "Names for physical entities experienced through senses like sight, touch, smell, or taste", Example: "snowman", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounConcrete(r), nil }, }) @@ -148,10 +156,10 @@ func addWordNounLookup() { AddFuncLookup("nounabstract", Info{ Display: "Noun Abstract", Category: "word", - Description: "Random abstract noun", + Description: "Ideas, qualities, or states that cannot be perceived with the five senses", Example: "confusion", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounAbstract(r), nil }, }) @@ -159,10 +167,10 @@ func addWordNounLookup() { AddFuncLookup("nouncollectivepeople", Info{ Display: "Noun Collective People", Category: "word", - Description: "Random collective noun person", + Description: "Group of people or things regarded as a unit", Example: "body", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCollectivePeople(r), nil }, }) @@ -170,10 +178,10 @@ func addWordNounLookup() { AddFuncLookup("nouncollectiveanimal", Info{ Display: "Noun Collective Animal", Category: "word", - Description: "Random collective noun animal", + Description: "Group of animals, like a 'pack' of wolves or a 'flock' of birds", Example: "party", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCollectiveAnimal(r), nil }, }) @@ -181,10 +189,10 @@ func addWordNounLookup() { AddFuncLookup("nouncollectivething", Info{ Display: "Noun Collective Thing", Category: "word", - Description: "Random collective noun thing", + Description: "Group of objects or items, such as a 'bundle' of sticks or a 'cluster' of grapes", Example: "hand", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCollectiveThing(r), nil }, }) @@ -192,10 +200,10 @@ func addWordNounLookup() { AddFuncLookup("nouncountable", Info{ Display: "Noun Countable", Category: "word", - Description: "Random countable noun", + Description: "Items that can be counted individually", Example: "neck", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounCountable(r), nil }, }) @@ -203,10 +211,10 @@ func addWordNounLookup() { AddFuncLookup("noununcountable", Info{ Display: "Noun Uncountable", Category: "word", - Description: "Random uncountable noun", + Description: "Items that can't be counted individually", Example: "seafood", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounUncountable(r), nil }, }) @@ -214,11 +222,22 @@ func addWordNounLookup() { AddFuncLookup("nounproper", Info{ Display: "Noun Proper", Category: "word", - Description: "Random proper noun", + Description: "Specific name for a particular person, place, or organization", Example: "John", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return nounProper(r), nil }, }) + + AddFuncLookup("noundeterminer", Info{ + Display: "Noun Determiner", + Category: "word", + Description: "Word that introduces a noun and identifies it as a noun", + Example: "your", + Output: "string", + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { + return nounDeterminer(r), nil + }, + }) } diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go b/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go index 34c816dd6..1432f1730 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_phrase.go @@ -30,7 +30,7 @@ func phraseNoun(r *rand.Rand) string { } // Add determiner from weighted list - prob, _ := weighted(r, []interface{}{1, 2, 3}, []float32{2, 1.5, 1}) + prob, _ := weighted(r, []any{1, 2, 3}, []float32{2, 1.5, 1}) if prob == 1 { str = getArticle(str) + " " + str } else if prob == 2 { @@ -109,10 +109,10 @@ func addWordPhraseLookup() { AddFuncLookup("phrase", Info{ Display: "Phrase", Category: "word", - Description: "Random phrase", + Description: "A small group of words standing together", Example: "time will tell", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phrase(r), nil }, }) @@ -120,10 +120,10 @@ func addWordPhraseLookup() { AddFuncLookup("phrasenoun", Info{ Display: "Noun Phrase", Category: "word", - Description: "Random noun phrase", + Description: "Phrase with a noun as its head, functions within sentence like a noun", Example: "a tribe", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phraseNoun(r), nil }, }) @@ -131,10 +131,10 @@ func addWordPhraseLookup() { AddFuncLookup("phraseverb", Info{ Display: "Verb Phrase", Category: "word", - Description: "Random verb phrase", + Description: "Phrase that Consists of a verb and its modifiers, expressing an action or state", Example: "a tribe", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phraseVerb(r), nil }, }) @@ -142,10 +142,10 @@ func addWordPhraseLookup() { AddFuncLookup("phraseadverb", Info{ Display: "Adverb Phrase", Category: "word", - Description: "Random adverb phrase", + Description: "Phrase that modifies a verb, adjective, or another adverb, providing additional information.", Example: "fully gladly", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phraseAdverb(r), nil }, }) @@ -153,10 +153,10 @@ func addWordPhraseLookup() { AddFuncLookup("phrasepreposition", Info{ Display: "Preposition Phrase", Category: "word", - Description: "Random preposition phrase", + Description: "Phrase starting with a preposition, showing relation between elements in a sentence.", Example: "out the black thing", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return phrasePreposition(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go b/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go index 7bebf004c..bf1d2f74a 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_preposition.go @@ -51,10 +51,10 @@ func addWordPrepositionLookup() { AddFuncLookup("preposition", Info{ Display: "Preposition", Category: "word", - Description: "Random preposition", + Description: "Words used to express the relationship of a noun or pronoun to other words in a sentence", Example: "other than", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return preposition(r), nil }, }) @@ -62,10 +62,10 @@ func addWordPrepositionLookup() { AddFuncLookup("prepositionsimple", Info{ Display: "Preposition Simple", Category: "word", - Description: "Random simple preposition", + Description: "Single-word preposition showing relationships between 2 parts of a sentence", Example: "out", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return prepositionSimple(r), nil }, }) @@ -73,10 +73,10 @@ func addWordPrepositionLookup() { AddFuncLookup("prepositiondouble", Info{ Display: "Preposition Double", Category: "word", - Description: "Random double preposition", + Description: "Two-word combination preposition, indicating a complex relation", Example: "before", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return prepositionDouble(r), nil }, }) @@ -84,10 +84,10 @@ func addWordPrepositionLookup() { AddFuncLookup("prepositioncompound", Info{ Display: "Preposition Compound", Category: "word", - Description: "Random compound preposition", + Description: "Preposition that can be formed by combining two or more prepositions", Example: "according to", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return prepositionCompound(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go b/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go index ca346b9ef..00c533104 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_pronoun.go @@ -106,10 +106,10 @@ func addWordPronounLookup() { AddFuncLookup("pronoun", Info{ Display: "Pronoun", Category: "word", - Description: "Generates a random pronoun", + Description: "Word used in place of a noun to avoid repetition", Example: "me", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronoun(r), nil }, }) @@ -117,10 +117,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounpersonal", Info{ Display: "Pronoun Personal", Category: "word", - Description: "Generates a random personal pronoun", + Description: "Pronoun referring to a specific persons or things", Example: "it", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounPersonal(r), nil }, }) @@ -128,10 +128,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounobject", Info{ Display: "Pronoun Object", Category: "word", - Description: "Generates a random object pronoun", + Description: "Pronoun used as the object of a verb or preposition", Example: "it", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounObject(r), nil }, }) @@ -139,10 +139,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounpossessive", Info{ Display: "Pronoun Possessive", Category: "word", - Description: "Generates a random possessive pronoun", + Description: "Pronoun indicating ownership or belonging", Example: "mine", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounPossessive(r), nil }, }) @@ -150,10 +150,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounreflective", Info{ Display: "Pronoun Reflective", Category: "word", - Description: "Generates a random reflective pronoun", + Description: "Pronoun referring back to the subject of the sentence", Example: "myself", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounReflective(r), nil }, }) @@ -161,10 +161,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounindefinite", Info{ Display: "Pronoun Indefinite", Category: "word", - Description: "Generates a random indefinite pronoun", + Description: "Pronoun that does not refer to a specific person or thing", Example: "few", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounIndefinite(r), nil }, }) @@ -172,10 +172,10 @@ func addWordPronounLookup() { AddFuncLookup("pronoundemonstrative", Info{ Display: "Pronoun Demonstrative", Category: "word", - Description: "Generates a random demonstrative pronoun", + Description: "Pronoun that points out specific people or things", Example: "this", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounDemonstrative(r), nil }, }) @@ -183,10 +183,10 @@ func addWordPronounLookup() { AddFuncLookup("pronouninterrogative", Info{ Display: "Pronoun Interrogative", Category: "word", - Description: "Generates a random interrogative pronoun", + Description: "Pronoun used to ask questions", Example: "what", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounInterrogative(r), nil }, }) @@ -194,10 +194,10 @@ func addWordPronounLookup() { AddFuncLookup("pronounrelative", Info{ Display: "Pronoun Relative", Category: "word", - Description: "Generates a random relative pronoun", + Description: "Pronoun that introduces a clause, referring back to a noun or pronoun", Example: "as", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return pronounRelative(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go b/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go index e5ae5eb21..de8d41e9e 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_sentence.go @@ -124,13 +124,13 @@ func addWordSentenceLookup() { AddFuncLookup("sentence", Info{ Display: "Sentence", Category: "word", - Description: "Random sentence", + Description: "Set of words expressing a statement, question, exclamation, or command", Example: "Interpret context record river mind.", Output: "string", Params: []Param{ {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { wordCount, err := info.GetInt(m, "wordcount") if err != nil { return nil, err @@ -146,8 +146,8 @@ func addWordSentenceLookup() { AddFuncLookup("paragraph", Info{ Display: "Paragraph", Category: "word", - Description: "Random paragraph", - Example: "Interpret context record river mind press self should compare property outcome divide. Combine approach sustain consult discover explanation direct address church husband seek army. Begin own act welfare replace press suspect stay link place manchester specialist. Arrive price satisfy sign force application hair train provide basis right pay. Close mark teacher strengthen information attempt head touch aim iron tv take. Handle wait begin look speech trust cancer visit capacity disease chancellor clean. Race aim function gain couple push faith enjoy admit ring attitude develop. Edge game prevent cast mill favour father star live search aim guess. West heart item adopt compete equipment miss output report communicate model cabinet. Seek worker variety step argue air improve give succeed relief artist suffer. Hide finish insist knowledge thatcher make research chance structure proportion husband implement. Town crown restaurant cost material compete lady climb football region discussion order. Place lee market ice like display mind stress compete weather station raise. Democracy college major recall struggle use cut intention accept period generation strike. Benefit defend recommend conclude justify result depend succeed address owner fill interpret.", + Description: "Distinct section of writing covering a single theme, composed of multiple sentences", + Example: "Interpret context record river mind press self should compare property outcome divide. Combine approach sustain consult discover explanation direct address church husband seek army. Begin own act welfare replace press suspect stay link place manchester specialist. Arrive price satisfy sign force application hair train provide basis right pay. Close mark teacher strengthen information attempt head touch aim iron tv take.", Output: "string", Params: []Param{ {Field: "paragraphcount", Display: "Paragraph Count", Type: "int", Default: "2", Description: "Number of paragraphs"}, @@ -155,7 +155,7 @@ func addWordSentenceLookup() { {Field: "wordcount", Display: "Word Count", Type: "int", Default: "5", Description: "Number of words in a sentence"}, {Field: "paragraphseparator", Display: "Paragraph Separator", Type: "string", Default: "
", Description: "String value to add between paragraphs"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { paragraphCount, err := info.GetInt(m, "paragraphcount") if err != nil { return nil, err @@ -192,21 +192,21 @@ func addWordSentenceLookup() { AddFuncLookup("question", Info{ Display: "Question", Category: "word", - Description: "Random question", + Description: "Statement formulated to inquire or seek clarification", Example: "Roof chia echo?", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return question(r), nil }, }) AddFuncLookup("quote", Info{ - Display: "Qoute", + Display: "Quote", Category: "word", - Description: "Random quote", + Description: "Direct repetition of someone else's words", Example: `"Roof chia echo." - Lura Lockman`, Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return quote(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go b/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go index ab8b209b9..6a5db2347 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/word_verb.go @@ -63,10 +63,10 @@ func addWordVerbLookup() { AddFuncLookup("verb", Info{ Display: "Verb", Category: "word", - Description: "Random verb", + Description: "Word expressing an action, event or state", Example: "release", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verb(r), nil }, }) @@ -74,10 +74,10 @@ func addWordVerbLookup() { AddFuncLookup("verbaction", Info{ Display: "Action Verb", Category: "word", - Description: "Random action verb", + Description: "Verb Indicating a physical or mental action", Example: "close", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbAction(r), nil }, }) @@ -85,10 +85,10 @@ func addWordVerbLookup() { AddFuncLookup("verbtransitive", Info{ Display: "Transitive Verb", Category: "word", - Description: "Random transitive verb", + Description: "Verb that requires a direct object to complete its meaning", Example: "follow", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbTransitive(r), nil }, }) @@ -96,10 +96,10 @@ func addWordVerbLookup() { AddFuncLookup("verbintransitive", Info{ Display: "Intransitive Verb", Category: "word", - Description: "Random intransitive verb", + Description: "Verb that does not require a direct object to complete its meaning", Example: "laugh", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbIntransitive(r), nil }, }) @@ -107,10 +107,10 @@ func addWordVerbLookup() { AddFuncLookup("verblinking", Info{ Display: "Linking Verb", Category: "word", - Description: "Random linking verb", + Description: "Verb that Connects the subject of a sentence to a subject complement", Example: "was", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbLinking(r), nil }, }) @@ -118,10 +118,10 @@ func addWordVerbLookup() { AddFuncLookup("verbhelping", Info{ Display: "Helping Verb", Category: "word", - Description: "Random helping verb", + Description: "Auxiliary verb that helps the main verb complete the sentence", Example: "be", Output: "string", - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { return verbHelping(r), nil }, }) diff --git a/vendor/github.com/brianvoe/gofakeit/v6/xml.go b/vendor/github.com/brianvoe/gofakeit/v6/xml.go index 98482cec7..b922d0def 100644 --- a/vendor/github.com/brianvoe/gofakeit/v6/xml.go +++ b/vendor/github.com/brianvoe/gofakeit/v6/xml.go @@ -11,12 +11,12 @@ import ( // XMLOptions defines values needed for json generation type XMLOptions struct { - Type string `json:"type" xml:"type"` // single or multiple + Type string `json:"type" xml:"type" fake:"{randomstring:[array,single]}"` // single or array RootElement string `json:"root_element" xml:"root_element"` RecordElement string `json:"record_element" xml:"record_element"` - RowCount int `json:"row_count" xml:"row_count"` - Fields []Field `json:"fields" xml:"fields"` + RowCount int `json:"row_count" xml:"row_count" fake:"{number:1,10}"` Indent bool `json:"indent" xml:"indent"` + Fields []Field `json:"fields" xml:"fields" fake:"{fields}"` } type xmlArray struct { @@ -27,12 +27,12 @@ type xmlArray struct { type xmlMap struct { XMLName xml.Name KeyOrder []string - Map map[string]interface{} `xml:",chardata"` + Map map[string]any `xml:",chardata"` } type xmlEntry struct { XMLName xml.Name - Value interface{} `xml:",chardata"` + Value any `xml:",chardata"` } func (m xmlMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error { @@ -97,15 +97,15 @@ func xmlMapLoop(e *xml.Encoder, m *xmlMap) error { case reflect.Map: err = e.Encode(xmlMap{ XMLName: xml.Name{Local: key}, - Map: m.Map[key].(map[string]interface{}), + Map: m.Map[key].(map[string]any), }) if err != nil { return err } case reflect.Struct: - // Convert struct to map[string]interface{} + // Convert struct to map[string]any // So we can rewrap element - var inInterface map[string]interface{} + var inInterface map[string]any inrec, _ := json.Marshal(m.Map[key]) json.Unmarshal(inrec, &inInterface) @@ -128,12 +128,22 @@ func xmlMapLoop(e *xml.Encoder, m *xmlMap) error { } // XML generates an object or an array of objects in json format -func XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(globalFaker.Rand, xo) } +// A nil XMLOptions returns a randomly structured XML. +func XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(globalFaker, xo) } // XML generates an object or an array of objects in json format -func (f *Faker) XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(f.Rand, xo) } +// A nil XMLOptions returns a randomly structured XML. +func (f *Faker) XML(xo *XMLOptions) ([]byte, error) { return xmlFunc(f, xo) } + +func xmlFunc(f *Faker, xo *XMLOptions) ([]byte, error) { + if xo == nil { + // We didn't get a XMLOptions, so create a new random one + err := f.Struct(&xo) + if err != nil { + return nil, err + } + } -func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { // Check to make sure they passed in a type if xo.Type != "single" && xo.Type != "array" { return nil, errors.New("invalid type, must be array or object") @@ -164,10 +174,10 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { v := xmlMap{ XMLName: xml.Name{Local: xo.RootElement}, KeyOrder: keyOrder, - Map: make(map[string]interface{}), + Map: make(map[string]any), } - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for _, field := range xo.Fields { // Get function info funcInfo := GetFuncLookup(field.Function) @@ -175,7 +185,7 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { return nil, errors.New("invalid function, " + field.Function + " does not exist") } - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } @@ -212,10 +222,10 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { v := xmlMap{ XMLName: xml.Name{Local: xo.RecordElement}, KeyOrder: keyOrder, - Map: make(map[string]interface{}), + Map: make(map[string]any), } - // Loop through fields and add to them to map[string]interface{} + // Loop through fields and add to them to map[string]any for _, field := range xo.Fields { if field.Function == "autoincrement" { v.Map[field.Name] = i @@ -228,7 +238,7 @@ func xmlFunc(r *rand.Rand, xo *XMLOptions) ([]byte, error) { return nil, errors.New("invalid function, " + field.Function + " does not exist") } - value, err := funcInfo.Generate(r, &field.Params, funcInfo) + value, err := funcInfo.Generate(f.Rand, &field.Params, funcInfo) if err != nil { return nil, err } @@ -261,20 +271,18 @@ func addFileXMLLookup() { Display: "XML", Category: "file", Description: "Generates an single or an array of elements in xml format", - Example: ` - - - Markus - Moen - Dc0VYXjkWABx - - - Osborne - Hilll - XPJ9OVNbs5lm - - - `, + Example: ` + + Markus + Moen + Dc0VYXjkWABx + + + Osborne + Hilll + XPJ9OVNbs5lm + +`, Output: "[]byte", ContentType: "application/xml", Params: []Param{ @@ -282,10 +290,10 @@ func addFileXMLLookup() { {Field: "rootelement", Display: "Root Element", Type: "string", Default: "xml", Description: "Root element wrapper name"}, {Field: "recordelement", Display: "Record Element", Type: "string", Default: "record", Description: "Record element for each record row"}, {Field: "rowcount", Display: "Row Count", Type: "int", Default: "100", Description: "Number of rows in JSON array"}, - {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, {Field: "indent", Display: "Indent", Type: "bool", Default: "false", Description: "Whether or not to add indents and newlines"}, + {Field: "fields", Display: "Fields", Type: "[]Field", Description: "Fields containing key name and function to run in json format"}, }, - Generate: func(r *rand.Rand, m *MapParams, info *Info) (interface{}, error) { + Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) { xo := XMLOptions{} typ, err := info.GetString(m, "type") @@ -317,6 +325,12 @@ func addFileXMLLookup() { return nil, err } + indent, err := info.GetBool(m, "indent") + if err != nil { + return nil, err + } + xo.Indent = indent + // Check to make sure fields has length if len(fieldsStr) > 0 { xo.Fields = make([]Field, len(fieldsStr)) @@ -330,13 +344,8 @@ func addFileXMLLookup() { } } - indent, err := info.GetBool(m, "indent") - if err != nil { - return nil, err - } - xo.Indent = indent - - return xmlFunc(r, &xo) + f := &Faker{Rand: r} + return xmlFunc(f, &xo) }, }) } diff --git a/vendor/github.com/codegangsta/negroni/.gitignore b/vendor/github.com/codegangsta/negroni/.gitignore new file mode 100644 index 000000000..3f2bc4741 --- /dev/null +++ b/vendor/github.com/codegangsta/negroni/.gitignore @@ -0,0 +1 @@ +/coverage.txt diff --git a/vendor/github.com/codegangsta/negroni/.travis.yml b/vendor/github.com/codegangsta/negroni/.travis.yml new file mode 100644 index 000000000..18104334d --- /dev/null +++ b/vendor/github.com/codegangsta/negroni/.travis.yml @@ -0,0 +1,27 @@ +language: go + +sudo: false +dist: trusty + +go: +- 1.x +- 1.2.x +- 1.3.x +- 1.4.x +- 1.5.x +- 1.6.x +- 1.7.x +- 1.8.x +- master + +before_install: +- find "${GOPATH%%:*}" -name '*.a' -delete +- rm -rf "${GOPATH%%:*}/src/golang.org" +- go get golang.org/x/tools/cover +- go get golang.org/x/tools/cmd/cover + +script: +- go test -race -coverprofile=coverage.txt -covermode=atomic + +after_success: +- bash <(curl -s "https://codecov.io/bash") diff --git a/vendor/github.com/codegangsta/negroni/CHANGELOG.md b/vendor/github.com/codegangsta/negroni/CHANGELOG.md new file mode 100644 index 000000000..9a6d638ec --- /dev/null +++ b/vendor/github.com/codegangsta/negroni/CHANGELOG.md @@ -0,0 +1,69 @@ +# Change Log + +**ATTN**: This project uses [semantic versioning](http://semver.org/). + +## [Unreleased] - + +## [1.0.0] - 2018-09-01 + +### Fixed +- `Logger` middleware now correctly handles paths containing a `%` instead of trying to treat it as a format specifier + +## [0.3.0] - 2017-11-11 +### Added +- `With()` helper for building a new `Negroni` struct chaining handlers from + existing `Negroni` structs +- Format log output in `Logger` middleware via a configurable `text/template` + string injectable via `.SetFormat`. Added `LoggerDefaultFormat` and + `LoggerDefaultDateFormat` to configure the default template and date format + used by the `Logger` middleware. +- Support for HTTP/2 pusher support via `http.Pusher` interface for Go 1.8+. +- `WrapFunc` to convert `http.HandlerFunc` into a `negroni.Handler` +- `Formatter` field added to `Recovery` middleware to allow configuring how + `panic`s are output. Default of `TextFormatter` (how it was output in + `0.2.0`) used. `HTMLPanicFormatter` also added to allow easy outputing of + `panic`s as HTML. + +### Fixed +- `Written()` correct returns `false` if no response header has been written +- Only implement `http.CloseNotifier` with the `negroni.ResponseWriter` if the + underlying `http.ResponseWriter` implements it (previously would always + implement it and panic if the underlying `http.ResponseWriter` did not. + +### Changed +- Set default status to `0` in the case that no handler writes status -- was + previously `200` (in 0.2.0, before that it was `0` so this reestablishes that + behavior) +- Catch `panic`s thrown by callbacks provided to the `Recovery` handler +- Recovery middleware will set `text/plain` content-type if none is set +- `ALogger` interface to allow custom logger outputs to be used with the + `Logger` middleware. Changes embeded field in `negroni.Logger` from `Logger` + to `ALogger`. +- Default `Logger` middleware output changed to be more structure and verbose + (also now configurable, see `Added`) +- Automatically bind to port specified in `$PORT` in `.Run()` if an address is + not passed in. Fall back to binding to `:8080` if no address specified + (configuable via `DefaultAddress`). +- `PanicHandlerFunc` added to `Recovery` middleware to enhance custom handling + of `panic`s by providing additional information to the handler including the + stack and the `http.Request`. `Recovery.ErrorHandlerFunc` was also added, but + deprecated in favor of the new `PanicHandlerFunc`. + +## [0.2.0] - 2016-05-10 +### Added +- Support for variadic handlers in `New()` +- Added `Negroni.Handlers()` to fetch all of the handlers for a given chain +- Allowed size in `Recovery` handler was bumped to 8k +- `Negroni.UseFunc` to push another handler onto the chain + +### Changed +- Set the status before calling `beforeFuncs` so the information is available to them +- Set default status to `200` in the case that no handler writes status -- was previously `0` +- Panic if `nil` handler is given to `negroni.Use` + +## 0.1.0 - 2013-07-22 +### Added +- Initial implementation. + +[Unreleased]: https://github.com/urfave/negroni/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/urfave/negroni/compare/v0.1.0...v0.2.0 diff --git a/vendor/github.com/codegangsta/negroni/README.md b/vendor/github.com/codegangsta/negroni/README.md index 1b3491a20..172985595 100644 --- a/vendor/github.com/codegangsta/negroni/README.md +++ b/vendor/github.com/codegangsta/negroni/README.md @@ -1,26 +1,42 @@ -# Negroni [![GoDoc](https://godoc.org/github.com/codegangsta/negroni?status.svg)](http://godoc.org/github.com/codegangsta/negroni) [![wercker status](https://app.wercker.com/status/13688a4a94b82d84a0b8d038c4965b61/s "wercker status")](https://app.wercker.com/project/bykey/13688a4a94b82d84a0b8d038c4965b61) [![codebeat](https://codebeat.co/badges/47d320b1-209e-45e8-bd99-9094bc5111e2)](https://codebeat.co/projects/github-com-codegangsta-negroni) +# Negroni +[![GoDoc](https://godoc.org/github.com/urfave/negroni?status.svg)](http://godoc.org/github.com/urfave/negroni) +[![Build Status](https://travis-ci.org/urfave/negroni.svg?branch=master)](https://travis-ci.org/urfave/negroni) +[![codebeat](https://codebeat.co/badges/47d320b1-209e-45e8-bd99-9094bc5111e2)](https://codebeat.co/projects/github-com-urfave-negroni) +[![codecov](https://codecov.io/gh/urfave/negroni/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/negroni) -Negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of `net/http` Handlers. +**Notice:** This is the library formerly known as +`github.com/codegangsta/negroni` -- Github will automatically redirect requests +to this repository, but we recommend updating your references for clarity. -If you like the idea of [Martini](https://github.com/go-martini/martini), but you think it contains too much magic, then Negroni is a great fit. +Negroni is an idiomatic approach to web middleware in Go. It is tiny, +non-intrusive, and encourages use of `net/http` Handlers. +If you like the idea of [Martini](https://github.com/go-martini/martini), but +you think it contains too much magic, then Negroni is a great fit. Language Translations: +* [Deutsch (de_DE)](translations/README_de_de.md) * [Português Brasileiro (pt_BR)](translations/README_pt_br.md) -* [繁體中文 (zh_tw)](translations/README_zh_tw.md) -* [German (de_DE)](translations/README_de_de.md) +* [简体中文 (zh_CN)](translations/README_zh_CN.md) +* [繁體中文 (zh_TW)](translations/README_zh_tw.md) +* [日本語 (ja_JP)](translations/README_ja_JP.md) +* [Français (fr_FR)](translations/README_fr_FR.md) ## Getting Started -After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`. +After installing Go and setting up your +[GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. +We'll call it `server.go`. -~~~ go + +``` go package main import ( - "github.com/codegangsta/negroni" - "net/http" "fmt" + "net/http" + + "github.com/urfave/negroni" ) func main() { @@ -29,34 +45,47 @@ func main() { fmt.Fprintf(w, "Welcome to the home page!") }) - n := negroni.Classic() + n := negroni.Classic() // Includes some default middlewares n.UseHandler(mux) - n.Run(":3000") + + http.ListenAndServe(":3000", n) } -~~~ +``` + +Then install the Negroni package (**NOTE**: >= **go 1.1** is required): -Then install the Negroni package (**go 1.1** and greater is required): -~~~ -go get github.com/codegangsta/negroni -~~~ +``` +go get github.com/urfave/negroni +``` Then run your server: -~~~ + +``` go run server.go -~~~ +``` -You will now have a Go net/http webserver running on `localhost:3000`. +You will now have a Go `net/http` webserver running on `localhost:3000`. -## Need Help? -If you have a question or feature request, [go ask the mailing list](https://groups.google.com/forum/#!forum/negroni-users). The GitHub issues for Negroni will be used exclusively for bug reports and pull requests. +### Packaging + +If you are on Debian, `negroni` is also available as [a +package](https://packages.debian.org/sid/golang-github-urfave-negroni-dev) that +you can install via `apt install golang-github-urfave-negroni-dev` (at the time +of writing, it is in the `sid` repositories). ## Is Negroni a Framework? -Negroni is **not** a framework. It is a library that is designed to work directly with net/http. + +Negroni is **not** a framework. It is a middleware-focused library that is +designed to work directly with `net/http`. ## Routing? -Negroni is BYOR (Bring your own Router). The Go community already has a number of great http routers available, Negroni tries to play well with all of them by fully supporting `net/http`. For instance, integrating with [Gorilla Mux](https://github.com/gorilla/mux) looks like so: -~~~ go +Negroni is BYOR (Bring your own Router). The Go community already has a number +of great http routers available, and Negroni tries to play well with all of them +by fully supporting `net/http`. For instance, integrating with [Gorilla Mux] +looks like so: + +``` go router := mux.NewRouter() router.HandleFunc("/", HomeHandler) @@ -66,47 +95,54 @@ n.Use(Middleware3) // router goes last n.UseHandler(router) -n.Run(":3000") -~~~ +http.ListenAndServe(":3001", n) +``` ## `negroni.Classic()` -`negroni.Classic()` provides some default middleware that is useful for most applications: -* `negroni.Recovery` - Panic Recovery Middleware. -* `negroni.Logger` - Request/Response Logger Middleware. -* `negroni.Static` - Static File serving under the "public" directory. +`negroni.Classic()` provides some default middleware that is useful for most +applications: + +* [`negroni.Recovery`](#recovery) - Panic Recovery Middleware. +* [`negroni.Logger`](#logger) - Request/Response Logger Middleware. +* [`negroni.Static`](#static) - Static File serving under the "public" + directory. This makes it really easy to get started with some useful features from Negroni. ## Handlers -Negroni provides a bidirectional middleware flow. This is done through the `negroni.Handler` interface: -~~~ go +Negroni provides a bidirectional middleware flow. This is done through the +`negroni.Handler` interface: + +``` go type Handler interface { ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) } -~~~ +``` -If a middleware hasn't already written to the ResponseWriter, it should call the next `http.HandlerFunc` in the chain to yield to the next middleware handler. This can be used for great good: +If a middleware hasn't already written to the `ResponseWriter`, it should call +the next `http.HandlerFunc` in the chain to yield to the next middleware +handler. This can be used for great good: -~~~ go +``` go func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { // do some stuff before next(rw, r) // do some stuff after } -~~~ +``` And you can map it to the handler chain with the `Use` function: -~~~ go +``` go n := negroni.New() n.Use(negroni.HandlerFunc(MyMiddleware)) -~~~ +``` You can also map plain old `http.Handler`s: -~~~ go +``` go n := negroni.New() mux := http.NewServeMux() @@ -114,22 +150,94 @@ mux := http.NewServeMux() n.UseHandler(mux) -n.Run(":3000") -~~~ +http.ListenAndServe(":3000", n) +``` + +## `With()` + +Negroni has a convenience function called `With`. `With` takes one or more +`Handler` instances and returns a new `Negroni` with the combination of the +receiver's handlers and the new handlers. + +```go +// middleware we want to reuse +common := negroni.New() +common.Use(MyMiddleware1) +common.Use(MyMiddleware2) + +// `specific` is a new negroni with the handlers from `common` combined with the +// the handlers passed in +specific := common.With( + SpecificMiddleware1, + SpecificMiddleware2 +) +``` ## `Run()` -Negroni has a convenience function called `Run`. `Run` takes an addr string identical to [http.ListenAndServe](http://golang.org/pkg/net/http#ListenAndServe). -~~~ go -n := negroni.Classic() -// ... -log.Fatal(http.ListenAndServe(":8080", n)) -~~~ +Negroni has a convenience function called `Run`. `Run` takes an addr string +identical to [`http.ListenAndServe`](https://godoc.org/net/http#ListenAndServe). + + +``` go +package main + +import ( + "github.com/urfave/negroni" +) + +func main() { + n := negroni.Classic() + n.Run(":8080") +} +``` +If no address is provided, the `PORT` environment variable is used instead. +If the `PORT` environment variable is not defined, the default address will be used. +See [Run](https://godoc.org/github.com/urfave/negroni#Negroni.Run) for a complete description. + +In general, you will want to use `net/http` methods and pass `negroni` as a +`Handler`, as this is more flexible, e.g.: + + +``` go +package main + +import ( + "fmt" + "log" + "net/http" + "time" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) + + n := negroni.Classic() // Includes some default middlewares + n.UseHandler(mux) + + s := &http.Server{ + Addr: ":8080", + Handler: n, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + log.Fatal(s.ListenAndServe()) +} +``` ## Route Specific Middleware -If you have a route group of routes that need specific middleware to be executed, you can simply create a new Negroni instance and use it as your route handler. -~~~ go +If you have a route group of routes that need specific middleware to be +executed, you can simply create a new Negroni instance and use it as your route +handler. + +``` go router := mux.NewRouter() adminRoutes := mux.NewRouter() // add admin routes here @@ -140,11 +248,11 @@ router.PathPrefix("/admin").Handler(negroni.New( Middleware2, negroni.Wrap(adminRoutes), )) -~~~ +``` -If you are using [Gorilla Mux](http://github.com/gorilla/mux) here is an example using a subrouter. +If you are using [Gorilla Mux], here is an example using a subrouter: -~~~go +``` go router := mux.NewRouter() subRouter := mux.NewRouter().PathPrefix("/subpath").Subrouter().StrictSlash(true) subRouter.HandleFunc("/", someSubpathHandler) // "/subpath/" @@ -152,44 +260,280 @@ subRouter.HandleFunc("/:id", someSubpathHandler) // "/subpath/:id" // "/subpath" is necessary to ensure the subRouter and main router linkup router.PathPrefix("/subpath").Handler(negroni.New( + Middleware1, + Middleware2, + negroni.Wrap(subRouter), +)) +``` + +`With()` can be used to eliminate redundancy for middlewares shared across +routes. + +``` go +router := mux.NewRouter() +apiRoutes := mux.NewRouter() +// add api routes here +webRoutes := mux.NewRouter() +// add web routes here + +// create common middleware to be shared across routes +common := negroni.New( Middleware1, Middleware2, - negroni.Wrap(subRouter), +) + +// create a new negroni for the api middleware +// using the common middleware as a base +router.PathPrefix("/api").Handler(common.With( + APIMiddleware1, + negroni.Wrap(apiRoutes), +)) +// create a new negroni for the web middleware +// using the common middleware as a base +router.PathPrefix("/web").Handler(common.With( + WebMiddleware1, + negroni.Wrap(webRoutes), )) -~~~ +``` -## Third Party Middleware +## Bundled Middleware + +### Static + +This middleware will serve files on the filesystem. If the files do not exist, +it proxies the request to the next middleware. If you want the requests for +non-existent files to return a `404 File Not Found` to the user you should look +at using [http.FileServer](https://golang.org/pkg/net/http/#FileServer) as +a handler. + +Example: + + +``` go +package main + +import ( + "fmt" + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) -Here is a current list of Negroni compatible middlware. Feel free to put up a PR linking your middleware if you have built one: + // Example of using a http.FileServer if you want "server-like" rather than "middleware" behavior + // mux.Handle("/public", http.FileServer(http.Dir("/home/public"))) + + n := negroni.New() + n.Use(negroni.NewStatic(http.Dir("/tmp"))) + n.UseHandler(mux) + + http.ListenAndServe(":3002", n) +} +``` + +Will serve files from the `/tmp` directory first, but proxy calls to the next +handler if the request does not match a file on the filesystem. + +### Recovery + +This middleware catches `panic`s and responds with a `500` response code. If +any other middleware has written a response code or body, this middleware will +fail to properly send a 500 to the client, as the client has already received +the HTTP response code. Additionally, an `PanicHandlerFunc` can be attached +to report 500's to an error reporting service such as Sentry or Airbrake. + +Example: + + +``` go +package main + +import ( + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + panic("oh no") + }) + + n := negroni.New() + n.Use(negroni.NewRecovery()) + n.UseHandler(mux) + + http.ListenAndServe(":3003", n) +} +``` +Will return a `500 Internal Server Error` to each request. It will also log the +stack traces as well as print the stack trace to the requester if `PrintStack` +is set to `true` (the default). + +Example with error handler: + +``` go +package main + +import ( + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + panic("oh no") + }) + + n := negroni.New() + recovery := negroni.NewRecovery() + recovery.PanicHandlerFunc = reportToSentry + n.Use(recovery) + n.UseHandler(mux) + + http.ListenAndServe(":3003", n) +} + +func reportToSentry(info *negroni.PanicInformation) { + // write code here to report error to Sentry +} +``` + +The middleware simply output the informations on STDOUT by default. +You can customize the output process by using the `SetFormatter()` function. + +You can use also the `HTMLPanicFormatter` to display a pretty HTML when a crash occurs. + + +``` go +package main + +import ( + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + panic("oh no") + }) + + n := negroni.New() + recovery := negroni.NewRecovery() + recovery.Formatter = &negroni.HTMLPanicFormatter{} + n.Use(recovery) + n.UseHandler(mux) + + http.ListenAndServe(":3003", n) +} +``` + +## Logger + +This middleware logs each incoming request and response. + +Example: + + +``` go +package main + +import ( + "fmt" + "net/http" + + "github.com/urfave/negroni" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) + + n := negroni.New() + n.Use(negroni.NewLogger()) + n.UseHandler(mux) + + http.ListenAndServe(":3004", n) +} +``` + +Will print a log similar to: + +``` +[negroni] 2017-10-04T14:56:25+02:00 | 200 | 378µs | localhost:3004 | GET / +``` + +on each request. + +You can also set your own log format by calling the `SetFormat` function. The format is a template string with fields as mentioned in the `LoggerEntry` struct. So, as an example - + +```go +l.SetFormat("[{{.Status}} {{.Duration}}] - {{.Request.UserAgent}}") +``` + +will show something like - `[200 18.263µs] - Go-User-Agent/1.1 ` + +## Third Party Middleware + +Here is a current list of Negroni compatible middlware. Feel free to put up a PR +linking your middleware if you have built one: | Middleware | Author | Description | | -----------|--------|-------------| -| [RestGate](https://github.com/pjebs/restgate) | [Prasanga Siripala](https://github.com/pjebs) | Secure authentication for REST API endpoints | -| [Graceful](https://github.com/tylerb/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown | -| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Middleware that implements a few quick security wins | -| [JWT Middleware](https://github.com/auth0/go-jwt-middleware) | [Auth0](https://github.com/auth0) | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it| +| [authz](https://github.com/casbin/negroni-authz) | [Yang Luo](https://github.com/hsluoyz) | ACL, RBAC, ABAC Authorization middlware based on [Casbin](https://github.com/casbin/casbin) | | [binding](https://github.com/mholt/binding) | [Matt Holt](https://github.com/mholt) | Data binding from HTTP requests into structs | -| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger | -| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Render JSON, XML and HTML templates | +| [cloudwatch](https://github.com/cvillecsteele/negroni-cloudwatch) | [Colin Steele](https://github.com/cvillecsteele) | AWS cloudwatch metrics middleware | +| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support | +| [csp](https://github.com/awakenetworks/csp) | [Awake Networks](https://github.com/awakenetworks) | [Content Security Policy](https://www.w3.org/TR/CSP2/) (CSP) support | +| [delay](https://github.com/jeffbmartinez/delay) | [Jeff Martinez](https://github.com/jeffbmartinez) | Add delays/latency to endpoints. Useful when testing effects of high latency | +| [New Relic Go Agent](https://github.com/yadvendar/negroni-newrelic-go-agent) | [Yadvendar Champawat](https://github.com/yadvendar) | Official [New Relic Go Agent](https://github.com/newrelic/go-agent) (currently in beta) | | [gorelic](https://github.com/jingweno/negroni-gorelic) | [Jingwen Owen Ou](https://github.com/jingweno) | New Relic agent for Go runtime | +| [Graceful](https://github.com/tylerb/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown | | [gzip](https://github.com/phyber/negroni-gzip) | [phyber](https://github.com/phyber) | GZIP response compression | +| [JWT Middleware](https://github.com/auth0/go-jwt-middleware) | [Auth0](https://github.com/auth0) | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it| +| [JWT Middleware](https://github.com/mfuentesg/go-jwtmiddleware) | [Marcelo Fuentes](https://github.com/mfuentesg) | JWT middleware for golang | +| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger | | [oauth2](https://github.com/goincremental/negroni-oauth2) | [David Bochenski](https://github.com/bochenski) | oAuth2 middleware | -| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Session Management | -| [permissions2](https://github.com/xyproto/permissions2) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, users and permissions | | [onthefly](https://github.com/xyproto/onthefly) | [Alexander Rødseth](https://github.com/xyproto) | Generate TinySVG, HTML and CSS on the fly | -| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support | -| [xrequestid](https://github.com/pilu/xrequestid) | [Andrea Franz](https://github.com/pilu) | Middleware that assigns a random X-Request-Id header to each request | -| [VanGoH](https://github.com/auroratechnologies/vangoh) | [Taylor Wrobel](https://github.com/twrobel3) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware | -| [stats](https://github.com/thoas/stats) | [Florent Messa](https://github.com/thoas) | Store information about your web application (response time, etc.) | +| [permissions2](https://github.com/xyproto/permissions2) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, users and permissions | | [prometheus](https://github.com/zbindenren/negroni-prometheus) | [Rene Zbinden](https://github.com/zbindenren) | Easily create metrics endpoint for the [prometheus](http://prometheus.io) instrumentation tool | -| [delay](https://github.com/jeffbmartinez/delay) | [Jeff Martinez](https://github.com/jeffbmartinez) | Add delays/latency to endpoints. Useful when testing effects of high latency | +| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Render JSON, XML and HTML templates | +| [RestGate](https://github.com/pjebs/restgate) | [Prasanga Siripala](https://github.com/pjebs) | Secure authentication for REST API endpoints | +| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Middleware that implements a few quick security wins | +| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Session Management | +| [stats](https://github.com/thoas/stats) | [Florent Messa](https://github.com/thoas) | Store information about your web application (response time, etc.) | +| [VanGoH](https://github.com/auroratechnologies/vangoh) | [Taylor Wrobel](https://github.com/twrobel3) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware | +| [xrequestid](https://github.com/pilu/xrequestid) | [Andrea Franz](https://github.com/pilu) | Middleware that assigns a random X-Request-Id header to each request | +| [mgo session](https://github.com/joeljames/nigroni-mgo-session) | [Joel James](https://github.com/joeljames) | Middleware that handles creating and closing mgo sessions per request | +| [digits](https://github.com/bamarni/digits) | [Bilal Amarni](https://github.com/bamarni) | Middleware that handles [Twitter Digits](https://get.digits.com/) authentication | +| [stats](https://github.com/guptachirag/stats) | [Chirag Gupta](https://github.com/guptachirag/stats) | Middleware that manages qps and latency stats for your endpoints and asynchronously flushes them to influx db | +| [Chaos](https://github.com/falzm/chaos) | [Marc Falzon](https://github.com/falzm) | Middleware for injecting chaotic behavior into application in a programmatic way | ## Examples -[Alexander Rødseth](https://github.com/xyproto) created [mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a Negroni middleware handler. + +[Alexander Rødseth](https://github.com/xyproto) created +[mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a +Negroni middleware handler. + +[Prasanga Siripala](https://github.com/pjebs) created an effective skeleton structure for web-based Go/Negroni projects: [Go-Skeleton](https://github.com/pjebs/go-skeleton) ## Live code reload? -[gin](https://github.com/codegangsta/gin) and [fresh](https://github.com/pilu/fresh) both live reload negroni apps. + +[gin](https://github.com/codegangsta/gin) and +[fresh](https://github.com/pilu/fresh) both live reload negroni apps. ## Essential Reading for Beginners of Go & Negroni @@ -198,4 +542,8 @@ Here is a current list of Negroni compatible middlware. Feel free to put up a PR ## About -Negroni is obsessively designed by none other than the [Code Gangsta](https://codegangsta.io/) +Negroni is obsessively designed by none other than the [Code +Gangsta](https://codegangsta.io/) + +[Gorilla Mux]: https://github.com/gorilla/mux +[`http.FileSystem`]: https://godoc.org/net/http#FileSystem diff --git a/vendor/github.com/codegangsta/negroni/doc.go b/vendor/github.com/codegangsta/negroni/doc.go index 24d6572c2..add1ed9f7 100644 --- a/vendor/github.com/codegangsta/negroni/doc.go +++ b/vendor/github.com/codegangsta/negroni/doc.go @@ -2,12 +2,12 @@ // // If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. // -// For a full guide visit http://github.com/codegangsta/negroni +// For a full guide visit http://github.com/urfave/negroni // // package main // // import ( -// "github.com/codegangsta/negroni" +// "github.com/urfave/negroni" // "net/http" // "fmt" // ) diff --git a/vendor/github.com/codegangsta/negroni/logger.go b/vendor/github.com/codegangsta/negroni/logger.go index e3828ef31..9c2216ba6 100644 --- a/vendor/github.com/codegangsta/negroni/logger.go +++ b/vendor/github.com/codegangsta/negroni/logger.go @@ -1,29 +1,78 @@ package negroni import ( + "bytes" + "log" "net/http" "os" + "text/template" "time" ) +// LoggerEntry is the structure passed to the template. +type LoggerEntry struct { + StartTime string + Status int + Duration time.Duration + Hostname string + Method string + Path string + Request *http.Request +} + +// LoggerDefaultFormat is the format logged used by the default Logger instance. +var LoggerDefaultFormat = "{{.StartTime}} | {{.Status}} | \t {{.Duration}} | {{.Hostname}} | {{.Method}} {{.Path}}" + +// LoggerDefaultDateFormat is the format used for date by the default Logger instance. +var LoggerDefaultDateFormat = time.RFC3339 + +// ALogger interface +type ALogger interface { + Println(v ...interface{}) + Printf(format string, v ...interface{}) +} + // Logger is a middleware handler that logs the request as it goes in and the response as it goes out. type Logger struct { - // Logger inherits from log.Logger used to log messages with the Logger middleware - *log.Logger + // ALogger implements just enough log.Logger interface to be compatible with other implementations + ALogger + dateFormat string + template *template.Template } // NewLogger returns a new Logger instance func NewLogger() *Logger { - return &Logger{log.New(os.Stdout, "[negroni] ", 0)} + logger := &Logger{ALogger: log.New(os.Stdout, "[negroni] ", 0), dateFormat: LoggerDefaultDateFormat} + logger.SetFormat(LoggerDefaultFormat) + return logger +} + +func (l *Logger) SetFormat(format string) { + l.template = template.Must(template.New("negroni_parser").Parse(format)) +} + +func (l *Logger) SetDateFormat(format string) { + l.dateFormat = format } func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { start := time.Now() - l.Printf("Started %s %s", r.Method, r.URL.Path) next(rw, r) res := rw.(ResponseWriter) - l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start)) + log := LoggerEntry{ + StartTime: start.Format(l.dateFormat), + Status: res.Status(), + Duration: time.Since(start), + Hostname: r.Host, + Method: r.Method, + Path: r.URL.Path, + Request: r, + } + + buff := &bytes.Buffer{} + l.template.Execute(buff, log) + l.Println(buff.String()) } diff --git a/vendor/github.com/codegangsta/negroni/negroni.go b/vendor/github.com/codegangsta/negroni/negroni.go index 57d15eb79..d1d77820a 100644 --- a/vendor/github.com/codegangsta/negroni/negroni.go +++ b/vendor/github.com/codegangsta/negroni/negroni.go @@ -6,6 +6,11 @@ import ( "os" ) +const ( + // DefaultAddress is used if no other is specified. + DefaultAddress = ":8080" +) + // Handler handler is an interface that objects can implement to be registered to serve as middleware // in the Negroni middleware stack. // ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc @@ -43,6 +48,16 @@ func Wrap(handler http.Handler) Handler { }) } +// WrapFunc converts a http.HandlerFunc into a negroni.Handler so it can be used as a Negroni +// middleware. The next http.HandlerFunc is automatically called after the Handler +// is executed. +func WrapFunc(handlerFunc http.HandlerFunc) Handler { + return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + handlerFunc(rw, r) + next(rw, r) + }) +} + // Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler. // Negroni middleware is evaluated in the order that they are added to the stack using // the Use and UseHandler methods. @@ -59,6 +74,14 @@ func New(handlers ...Handler) *Negroni { } } +// With returns a new Negroni instance that is a combination of the negroni +// receiver's handlers and the provided handlers. +func (n *Negroni) With(handlers ...Handler) *Negroni { + return New( + append(n.handlers, handlers...)..., + ) +} + // Classic returns a new Negroni instance with the default middleware already // in the stack. // @@ -75,6 +98,10 @@ func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { // Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. func (n *Negroni) Use(handler Handler) { + if handler == nil { + panic("handler cannot be nil") + } + n.handlers = append(n.handlers, handler) n.middleware = build(n.handlers) } @@ -89,17 +116,30 @@ func (n *Negroni) UseHandler(handler http.Handler) { n.Use(Wrap(handler)) } -// UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack. +// UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack. func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { n.UseHandler(http.HandlerFunc(handlerFunc)) } // Run is a convenience function that runs the negroni stack as an HTTP -// server. The addr string takes the same format as http.ListenAndServe. -func (n *Negroni) Run(addr string) { +// server. The addr string, if provided, takes the same format as http.ListenAndServe. +// If no address is provided but the PORT environment variable is set, the PORT value is used. +// If neither is provided, the address' value will equal the DefaultAddress constant. +func (n *Negroni) Run(addr ...string) { l := log.New(os.Stdout, "[negroni] ", 0) - l.Printf("listening on %s", addr) - l.Fatal(http.ListenAndServe(addr, n)) + finalAddr := detectAddress(addr...) + l.Printf("listening on %s", finalAddr) + l.Fatal(http.ListenAndServe(finalAddr, n)) +} + +func detectAddress(addr ...string) string { + if len(addr) > 0 { + return addr[0] + } + if port := os.Getenv("PORT"); port != "" { + return ":" + port + } + return DefaultAddress } // Returns a list of all the handlers in the current Negroni middleware chain. diff --git a/vendor/github.com/codegangsta/negroni/recovery.go b/vendor/github.com/codegangsta/negroni/recovery.go index d790cade6..c6fc24ef5 100644 --- a/vendor/github.com/codegangsta/negroni/recovery.go +++ b/vendor/github.com/codegangsta/negroni/recovery.go @@ -6,14 +6,137 @@ import ( "net/http" "os" "runtime" + "runtime/debug" + "text/template" ) +const ( + panicText = "PANIC: %s\n%s" + panicHTML = ` +PANIC: {{.RecoveredPanic}} + + +

Negroni - PANIC

+ +
+

{{.RequestDescription}}

+ Runtime error: {{.RecoveredPanic}} +
+ +{{ if .Stack }} +
+

Runtime Stack

+
{{.StackAsString}}
+
+{{ end }} + + +` + nilRequestMessage = "Request is nil" +) + +var panicHTMLTemplate = template.Must(template.New("PanicPage").Parse(panicHTML)) + +// PanicInformation contains all +// elements for printing stack informations. +type PanicInformation struct { + RecoveredPanic interface{} + Stack []byte + Request *http.Request +} + +// StackAsString returns a printable version of the stack +func (p *PanicInformation) StackAsString() string { + return string(p.Stack) +} + +// RequestDescription returns a printable description of the url +func (p *PanicInformation) RequestDescription() string { + + if p.Request == nil { + return nilRequestMessage + } + + var queryOutput string + if p.Request.URL.RawQuery != "" { + queryOutput = "?" + p.Request.URL.RawQuery + } + return fmt.Sprintf("%s %s%s", p.Request.Method, p.Request.URL.Path, queryOutput) +} + +// PanicFormatter is an interface on object can implement +// to be able to output the stack trace +type PanicFormatter interface { + // FormatPanicError output the stack for a given answer/response. + // In case the the middleware should not output the stack trace, + // the field `Stack` of the passed `PanicInformation` instance equals `[]byte{}`. + FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) +} + +// TextPanicFormatter output the stack +// as simple text on os.Stdout. If no `Content-Type` is set, +// it will output the data as `text/plain; charset=utf-8`. +// Otherwise, the origin `Content-Type` is kept. +type TextPanicFormatter struct{} + +func (t *TextPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) { + if rw.Header().Get("Content-Type") == "" { + rw.Header().Set("Content-Type", "text/plain; charset=utf-8") + } + fmt.Fprintf(rw, panicText, infos.RecoveredPanic, infos.Stack) +} + +// HTMLPanicFormatter output the stack inside +// an HTML page. This has been largely inspired by +// https://github.com/go-martini/martini/pull/156/commits. +type HTMLPanicFormatter struct{} + +func (t *HTMLPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) { + if rw.Header().Get("Content-Type") == "" { + rw.Header().Set("Content-Type", "text/html; charset=utf-8") + } + panicHTMLTemplate.Execute(rw, infos) +} + // Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. type Recovery struct { - Logger *log.Logger - PrintStack bool - StackAll bool - StackSize int + Logger ALogger + PrintStack bool + PanicHandlerFunc func(*PanicInformation) + StackAll bool + StackSize int + Formatter PanicFormatter + + // Deprecated: Use PanicHandlerFunc instead to receive panic + // error with additional information (see PanicInformation) + ErrorHandlerFunc func(interface{}) } // NewRecovery returns a new instance of Recovery @@ -23,6 +146,7 @@ func NewRecovery() *Recovery { PrintStack: true, StackAll: false, StackSize: 1024 * 8, + Formatter: &TextPanicFormatter{}, } } @@ -30,14 +154,38 @@ func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next htt defer func() { if err := recover(); err != nil { rw.WriteHeader(http.StatusInternalServerError) + stack := make([]byte, rec.StackSize) stack = stack[:runtime.Stack(stack, rec.StackAll)] - - f := "PANIC: %s\n%s" - rec.Logger.Printf(f, err, stack) + infos := &PanicInformation{RecoveredPanic: err, Request: r} if rec.PrintStack { - fmt.Fprintf(rw, f, err, stack) + infos.Stack = stack + } + rec.Logger.Printf(panicText, err, stack) + rec.Formatter.FormatPanicError(rw, r, infos) + + if rec.ErrorHandlerFunc != nil { + func() { + defer func() { + if err := recover(); err != nil { + rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack()) + rec.Logger.Printf("%s\n", debug.Stack()) + } + }() + rec.ErrorHandlerFunc(err) + }() + } + if rec.PanicHandlerFunc != nil { + func() { + defer func() { + if err := recover(); err != nil { + rec.Logger.Printf("provided PanicHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack()) + rec.Logger.Printf("%s\n", debug.Stack()) + } + }() + rec.PanicHandlerFunc(infos) + }() } } }() diff --git a/vendor/github.com/codegangsta/negroni/response_writer.go b/vendor/github.com/codegangsta/negroni/response_writer.go index 217cbd82a..cc507eb4b 100644 --- a/vendor/github.com/codegangsta/negroni/response_writer.go +++ b/vendor/github.com/codegangsta/negroni/response_writer.go @@ -13,7 +13,8 @@ import ( type ResponseWriter interface { http.ResponseWriter http.Flusher - // Status returns the status code of the response or 0 if the response has not been written. + // Status returns the status code of the response or 0 if the response has + // not been written Status() int // Written returns whether or not the ResponseWriter has been written. Written() bool @@ -28,11 +29,15 @@ type beforeFunc func(ResponseWriter) // NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { - return &responseWriter{ + nrw := &responseWriter{ ResponseWriter: rw, - status: http.StatusOK, - size: 0, - beforeFuncs: nil} + } + + if _, ok := rw.(http.CloseNotifier); ok { + return &responseWriterCloseNotifer{nrw} + } + + return nrw } type responseWriter struct { @@ -82,10 +87,6 @@ func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return hijacker.Hijack() } -func (rw *responseWriter) CloseNotify() <-chan bool { - return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() -} - func (rw *responseWriter) callBefore() { for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { rw.beforeFuncs[i](rw) @@ -95,6 +96,18 @@ func (rw *responseWriter) callBefore() { func (rw *responseWriter) Flush() { flusher, ok := rw.ResponseWriter.(http.Flusher) if ok { + if !rw.Written() { + // The status will be StatusOK if WriteHeader has not been called yet + rw.WriteHeader(http.StatusOK) + } flusher.Flush() } } + +type responseWriterCloseNotifer struct { + *responseWriter +} + +func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool { + return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() +} diff --git a/vendor/github.com/codegangsta/negroni/response_writer_pusher.go b/vendor/github.com/codegangsta/negroni/response_writer_pusher.go new file mode 100644 index 000000000..213cb35f7 --- /dev/null +++ b/vendor/github.com/codegangsta/negroni/response_writer_pusher.go @@ -0,0 +1,16 @@ +//+build go1.8 + +package negroni + +import ( + "fmt" + "net/http" +) + +func (rw *responseWriter) Push(target string, opts *http.PushOptions) error { + pusher, ok := rw.ResponseWriter.(http.Pusher) + if ok { + return pusher.Push(target, opts) + } + return fmt.Errorf("the ResponseWriter doesn't support the Pusher interface") +} diff --git a/vendor/github.com/codegangsta/negroni/static.go b/vendor/github.com/codegangsta/negroni/static.go index c5af4e688..34be967c0 100644 --- a/vendor/github.com/codegangsta/negroni/static.go +++ b/vendor/github.com/codegangsta/negroni/static.go @@ -6,7 +6,11 @@ import ( "strings" ) -// Static is a middleware handler that serves static files in the given directory/filesystem. +// Static is a middleware handler that serves static files in the given +// directory/filesystem. If the file does not exist on the filesystem, it +// passes along to the next middleware in the chain. If you desire "fileserver" +// type behavior where it returns a 404 for unfound files, you should consider +// using http.FileServer from the Go stdlib. type Static struct { // Dir is the directory to serve static files from Dir http.FileSystem diff --git a/vendor/github.com/corpix/uarand/.gitignore b/vendor/github.com/corpix/uarand/.gitignore index 4f59364bc..6fb5d8fc7 100644 --- a/vendor/github.com/corpix/uarand/.gitignore +++ b/vendor/github.com/corpix/uarand/.gitignore @@ -1,3 +1,2 @@ /build -/vendor *~ diff --git a/vendor/github.com/corpix/uarand/.go-makefile.json b/vendor/github.com/corpix/uarand/.go-makefile.json deleted file mode 100644 index b111df4e2..000000000 --- a/vendor/github.com/corpix/uarand/.go-makefile.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "build_id_generator": "0x$(shell echo $(version) | sha1sum | awk '{print $$1}')", - "host": "github.com", - "include": ["useragents.mk"], - "kind": "package", - "name": "uarand", - "tool": [], - "user": "corpix", - "version_generator": "$(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD)", - "version_variable": "cli.version" -} diff --git a/vendor/github.com/corpix/uarand/.travis.yml b/vendor/github.com/corpix/uarand/.travis.yml index 0d9e6e633..58114d498 100644 --- a/vendor/github.com/corpix/uarand/.travis.yml +++ b/vendor/github.com/corpix/uarand/.travis.yml @@ -1,9 +1,3 @@ -language: go +language: nix -go: - - 1.6 - - 1.7 - - 1.8 - - master - -script: make test +script: nix-shell --pure --command "make lint test" diff --git a/vendor/github.com/corpix/uarand/LICENSE b/vendor/github.com/corpix/uarand/LICENSE index e70c2b1f3..68a49daad 100644 --- a/vendor/github.com/corpix/uarand/LICENSE +++ b/vendor/github.com/corpix/uarand/LICENSE @@ -1,21 +1,24 @@ -The MIT License (MIT) +This is free and unencumbered software released into the public domain. -Copyright © 2017 Dmitry Moskowski +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +For more information, please refer to diff --git a/vendor/github.com/corpix/uarand/Makefile b/vendor/github.com/corpix/uarand/Makefile index d96582158..375b2acd2 100644 --- a/vendor/github.com/corpix/uarand/Makefile +++ b/vendor/github.com/corpix/uarand/Makefile @@ -1,52 +1,30 @@ .DEFAULT_GOAL = all -numcpus := $(shell cat /proc/cpuinfo | grep '^processor\s*:' | wc -l) -version := $(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD) - name := uarand package := github.com/corpix/$(name) .PHONY: all -all:: dependencies - -.PHONY: tools -tools:: - @if [ ! -e "$(GOPATH)"/bin/glide ]; then go get github.com/Masterminds/glide; fi - @if [ ! -e "$(GOPATH)"/bin/glide-cleanup ]; then go get github.com/ngdinhtoan/glide-cleanup; fi - @if [ ! -e "$(GOPATH)"/bin/glide-vc ]; then go get github.com/sgotti/glide-vc; fi - @if [ ! -e "$(GOPATH)"/bin/godef ]; then go get github.com/rogpeppe/godef; fi - @if [ ! -e "$(GOPATH)"/bin/gocode ]; then go get github.com/nsf/gocode; fi - @if [ ! -e "$(GOPATH)"/bin/gometalinter ]; then go get github.com/alecthomas/gometalinter && gometalinter --install; fi - @if [ ! -e "$(GOPATH)"/src/github.com/stretchr/testify/assert ]; then go get github.com/stretchr/testify/assert; fi - -.PHONY: dependencies -dependencies:: tools - glide install - -.PHONY: clean -clean:: tools - glide cache-clear +all:: useragents.go .PHONY: test -test:: dependencies - go test -v \ - $(shell glide novendor) - -.PHONY: bench -bench:: dependencies - go test \ - -bench=. -v \ - $(shell glide novendor) +test: + go test -v ./... .PHONY: lint -lint:: dependencies - go vet $(shell glide novendor) - gometalinter \ - --deadline=5m \ - --concurrency=$(numcpus) \ - $(shell glide novendor) +lint: +.PHONY: lint +lint: + golangci-lint --color=always \ + --exclude='uses unkeyed fields' \ + --exclude='type .* is unused' \ + --exclude='should merge variable declaration with assignment on next line' \ + --deadline=120s \ + run ./... .PHONY: check -check:: lint test +check: lint test -include useragents.mk +.PHONY: useragents.go +useragents.go: + ./scripts/fetch-user-agents | ./scripts/generate-useragents-go $(name) > $@ + go fmt $@ diff --git a/vendor/github.com/corpix/uarand/README.md b/vendor/github.com/corpix/uarand/README.md index d79b5c29b..c8d98a98a 100644 --- a/vendor/github.com/corpix/uarand/README.md +++ b/vendor/github.com/corpix/uarand/README.md @@ -35,4 +35,4 @@ Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41 ## License -MIT +[Unlicense](https://unlicense.org/) diff --git a/vendor/github.com/corpix/uarand/glide.lock b/vendor/github.com/corpix/uarand/glide.lock deleted file mode 100644 index abb3ec579..000000000 --- a/vendor/github.com/corpix/uarand/glide.lock +++ /dev/null @@ -1,16 +0,0 @@ -hash: 400dee10adae21284f2563cb7178f4b5a30e69c9ed3954a5a32a8a618d5bdfeb -updated: 2017-07-12T21:00:19.452016303Z -imports: [] -testImports: -- name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 - subpackages: - - spew -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert diff --git a/vendor/github.com/corpix/uarand/glide.yaml b/vendor/github.com/corpix/uarand/glide.yaml deleted file mode 100644 index 037ee2450..000000000 --- a/vendor/github.com/corpix/uarand/glide.yaml +++ /dev/null @@ -1,7 +0,0 @@ -package: github.com/corpix/uarand -import: [] -testImport: -- package: github.com/stretchr/testify - version: v1.1.4 - subpackages: - - assert diff --git a/vendor/github.com/corpix/uarand/shell.nix b/vendor/github.com/corpix/uarand/shell.nix new file mode 100644 index 000000000..269de81e0 --- /dev/null +++ b/vendor/github.com/corpix/uarand/shell.nix @@ -0,0 +1,14 @@ +let + nixpkgs = ; +in with import nixpkgs {}; +stdenv.mkDerivation { + name = "nix-shell"; + buildInputs = [ + coreutils bashInteractive jq curl gcc git gnumake + go golangci-lint cacert openssl python3 + ]; + shellHook = '' + unset GOPATH + export NIX_PATH=nixpkgs=${nixpkgs} + ''; +} diff --git a/vendor/github.com/corpix/uarand/uarand.go b/vendor/github.com/corpix/uarand/uarand.go index 04f9247c2..fad733784 100644 --- a/vendor/github.com/corpix/uarand/uarand.go +++ b/vendor/github.com/corpix/uarand/uarand.go @@ -2,6 +2,7 @@ package uarand import ( "math/rand" + "sync" "time" ) @@ -23,11 +24,18 @@ type Randomizer interface { // UARand describes the user agent randomizer settings. type UARand struct { Randomizer + UserAgents []string + + mutex sync.Mutex } // GetRandom returns a random user agent from UserAgents slice. func (u *UARand) GetRandom() string { - return UserAgents[u.Intn(len(UserAgents))] + u.mutex.Lock() + n := u.Intn(len(u.UserAgents)) + u.mutex.Unlock() + + return u.UserAgents[n] } // GetRandom returns a random user agent from UserAgents slice. @@ -36,6 +44,20 @@ func GetRandom() string { return Default.GetRandom() } +// New return UserAgent randomizer settings with default user-agents list func New(r Randomizer) *UARand { - return &UARand{r} + return &UARand{ + Randomizer: r, + UserAgents: UserAgents, + mutex: sync.Mutex{}, + } +} + +// NewWithCustomList return UserAgent randomizer settings with custom user-agents list +func NewWithCustomList(userAgents []string) *UARand { + return &UARand{ + Randomizer: rand.New(rand.NewSource(time.Now().UnixNano())), + UserAgents: userAgents, + mutex: sync.Mutex{}, + } } diff --git a/vendor/github.com/corpix/uarand/useragents.go b/vendor/github.com/corpix/uarand/useragents.go index aa8e44cc9..fd2fb4003 100644 --- a/vendor/github.com/corpix/uarand/useragents.go +++ b/vendor/github.com/corpix/uarand/useragents.go @@ -3,827 +3,1285 @@ package uarand var ( // UserAgents is a list of browser and bots user agents. UserAgents = []string{ - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.6 (Change: )", + "'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.39 (KHTML, like Gecko) Chrome/89.0.4389.111 Safari/537.39'", + "Adobe Application Manager 2.0", + "AdsBot-Google ( http://www.google.com/adsbot.html)", + "AndroidDownloadManager/5.1 (Linux; U; Android 5.1; Z820 Build/LMY47D)", "Avant Browser/1.2.789rel1 (http://www.avantbrowser.com)", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5", - "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27", - "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.120 Safari/535.2", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/18.6.872.0 Safari/535.2 UNTRUSTED/1.0 3gpp-gba UNTRUSTED/1.0", - "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", - "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", - "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB5", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)", - "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0a2) Gecko/20110622 Firefox/6.0a2", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", - "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0", - "Mozilla/5.0 (Windows NT 6.0; rv:14.0) Gecko/20100101 Firefox/14.0.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1", - "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0) Gecko/16.0 Firefox/16.0", - "Mozilla/5.0 (Windows NT 6.2; rv:19.0) Gecko/20121129 Firefox/19.0", - "Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Maxthon 2.0)", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b4pre) Gecko/20100815 Minefield/4.0b4pre", - "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0 )", - "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90)", - "Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a", + "Baiduspider ( http://www.baidu.com/search/spider.htm)", + "BlackBerry7100i/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/103", + "BlackBerry7520/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/5.0.3.3 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)", + "BlackBerry8300/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/107 UP.Link/6.2.3.15.0", + "BlackBerry8320/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/100", + "BlackBerry8330/4.3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/105", + "BlackBerry9000/4.6.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102", + "BlackBerry9530/4.7.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102 UP.Link/6.3.1.20.0", + "BlackBerry9700/5.0.0.351 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/123", + "Bloglines/3.1 (http://www.bloglines.com)", + "CSSCheck/1.2.2", + "Dalvik/2.1.0 (Linux; U; Android 8.0.0; SM-A520F Build/R16NW)", + "DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", + "DoCoMo/2.0 SH901iC(c100;TB;W24H12)", + "Download Demon/3.5.0.11", + "ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)", + "ELinks (0.4pre5; Linux 2.6.10-ac7 i686; 80x33)", + "ELinks/0.12~pre5-4", + "ELinks/0.9.3 (textmode; Linux 2.6.9-kanotix-8 i686; 127x41)", + "EmailWolf 1.00", + "FAST-WebCrawler/3.8 (crawler at trd dot overture dot com; http://www.alltheweb.com/help/webmaster/crawler)", + "Facebot", + "FeedFetcher-Google; ( http://www.google.com/feedfetcher.html)", + "Gaisbot/3.0 (robot@gais.cs.ccu.edu.tw; http://gais.cs.ccu.edu.tw/robot.php)", + "Googlebot-Image/1.0", + "Googlebot-News", + "Googlebot-Video/1.0", + "Googlebot/2.1 ( http://www.googlebot.com/bot.html)", + "Gregarius/0.5.2 ( http://devlog.gregarius.net/docs/ua)", + "Gulper Web Bot 0.2.4 (www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/Link/GulperBot)", + "HTC-ST7377/1.59.502.3 (67150) Opera/9.50 (Windows NT 5.1; U; en) UP.Link/6.3.1.17.0", + "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "HTMLParser/1.6", + "Java/1.6.0_13", + "Jigsaw/2.2.5 W3C_CSS_Validator_JFouffa/2.0", + "Konqueror/3.0-rc4; (Konqueror/3.0-rc4; i686 Linux;;datecode)", + "LG-GC900/V10a Obigo/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1", + "LG-LX550 AU-MIC-LX550/2.0 MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 196x84)", + "Links (2.1pre15; Linux 2.4.26 i686; 158x61)", + "Links (2.3pre1; Linux 2.6.38-8-generic x86_64; 170x48)", + "Links/0.9.1 (Linux 2.4.24; i386;)", + "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/0.8.12", + "Lynx/2.8.7dev.4 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8d", + "MOT-L7v/08.B7.5DR MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", + "MOT-V177/0.1.75 UP.Browser/6.2.3.9.c.12 (GUI) MMP/2.0 UP.Link/6.3.1.13.0", + "MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0", + "MOTORIZR-Z8/46.00.00 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 356) Opera 8.65 [it] UP.Link/6.3.0.0.0", + "MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23", + "Mediapartners-Google", + "Microsoft URL Control - 6.00.8862", + "Midori/0.1.10 (X11; Linux i686; U; en-us) WebKit/(531).(2)", + "MobileSafari/600.1.4 CFNetwork/711.1.12 Darwin/14.0.0", + "Mozilla/1.22 (compatible; MSIE 5.01; PalmOS 3.0) EudoraWeb 2.1", + "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)", "Mozilla/2.02E (Win95; U)", + "Mozilla/3.0 (compatible; NetPositive/2.1.1; BeOS)", "Mozilla/3.01Gold (Win95; I)", - "Mozilla/4.8 [en] (Windows NT 5.1; U)", - "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko Netscape/7.1 (ax)", - "Opera/7.50 (Windows XP; U)", - "Opera/7.50 (Windows ME; U) [en]", - "Opera/7.51 (Windows NT 5.1; U) [en]", + "Mozilla/4.0 (PDA; PalmOS/sony/model prmr/Revision:1.1.54 (en)) NetFront/3.0", + "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)", + "Mozilla/4.0 (compatible; Dillo 3.0)", + "Mozilla/4.0 (compatible; GoogleToolbar 4.0.1019.5266-big; Windows XP 5.1; MSIE 6.0.2900.2180)", + "Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 600x800)", + "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; MDA Pro/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1)", + "Mozilla/4.0 (compatible; MSIE 5.0; Series80/2.0 Nokia9500/4.51 Profile/MIDP-2.0 Configuration/CLDC-1.1)", + "Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)", + "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90)", + "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0 )", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) Sprint:PPC6800", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) XV6800", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile6.0)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; en) Opera 8.0", - "Opera/9.25 (Windows NT 6.0; U; en)", - "Opera/9.80 (Windows NT 5.2; U; en) Presto/2.2.15 Version/10.10", - "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10", - "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.7.62 Version/11.01", - "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00", - "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", - "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.2b) Gecko/20021001 Phoenix/0.2", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090825 SeaMonkey/1.1.18", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.17) Gecko/20110123 (like Firefox/3.x) SeaMonkey/2.0.12", - "Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", - "Mozilla/5.0 (Windows; U; ; en-NZ) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.8.0", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", + "Mozilla/4.0 (compatible; MSIE 6.0; j2me) ReqwirelessWeb/3.5", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; Avant Browser; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Beamrise/17.2.0.9 Chrome/17.0.939.0 Safari/535.8", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Maxthon 2.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0)", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)", + "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 6600;452) Opera 6.20 [en-US]", + "Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)", + "Mozilla/4.8 [en] (Windows NT 5.1; U)", + "Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)", + "Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4", + "Mozilla/5.0 (Android 4.2; rv:19.0) Gecko/20121129 Firefox/19.0", + "Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0", + "Mozilla/5.0 (Android; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", + "Mozilla/5.0 (Android; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", + "Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0", + "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.1.0.2342 Mobile Safari/537.10+", + "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.9a1) Gecko/20060702 SeaMonkey/1.5a", + "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1 (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1", + "Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.267 Mobile Safari/534.11+", + "Mozilla/5.0 (Linux U; en-US) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) Version/4.0 Kindle/3.0 (screen 600x800; rotate)", + "Mozilla/5.0 (Linux; Android 10; AC2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; BLA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; CLT-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; DL1036) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ELE-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Galaxy J2 Pro Build/QQ3A.200805.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/85.0.4183.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; HMA-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; LYA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2003J15SC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2006C3LII) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2007J20CI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2010J19SI) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.74 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; MAR-LX1B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; MAR-LX1M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; MI 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONE A2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; POCO F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; POCOPHONE F1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi Note 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SAMSUNG SM-N980F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.2 Chrome/92.0.4515.166 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-A315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-J810G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-M307F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-M315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.50 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; SM-N960F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; TECNO KE5 Build/QP1A.190711.020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.99 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; VOG-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; VOG-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; YAL-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; itel L5006C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; moto e(7) plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; moto e(7)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; moto g(7) plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; 100011886A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; AC2001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; AC2001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; BL5000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; CPH2373) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; DN2101) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; GM1910) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; GM1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; IN2025) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; IV2201) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; KB2003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; LM-V500N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; LM-V500N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; LM-V510N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36 EdgA/101.0.1210.32", + "Mozilla/5.0 (Linux; Android 11; M2003J15SC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; M2007J3SY) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; M2101K6G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; MVK-T2101) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.116 Safari/537.36 EdgA/45.09.4.5083", + "Mozilla/5.0 (Linux; Android 11; Mi 9 SE) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Mi A3 Build/RKQ1.200903.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.41 YaBrowser/22.1.0.194 (lite) Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Mi Note 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; ONEPLUS A6000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 2 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4812.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1851) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1921) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1921) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX1931) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2027) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2101) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2117) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; RMX2161) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36 OPR/68.3.3557.64528", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 8T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 9 Pro Max) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36 OPR/68.3.3557.64528", + "Mozilla/5.0 (Linux; Android 11; Redmi Note 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-A5070) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/17.0 Chrome/96.0.4664.104 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A115F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A217F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A225F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A326U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A415F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A505FN) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A505G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-A526U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-G980F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-M315F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-M317F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-M515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; SM-T500) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.73 Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; moto e20) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; moto g(40) fusion) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; motorola edge 20 fusion) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; vivo 1906) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; ASUS_I005DA) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36 EdgA/100.0.1185.50", + "Mozilla/5.0 (Linux; Android 12; I2126) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; KB2005) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; LE2121) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; M2101K6G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 4a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 6 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; RMX3081) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SAMSUNG SM-G990E) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/17.0 Chrome/96.0.4664.104 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SAMSUNG SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.2 Chrome/92.0.4515.166 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-A525F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-F926B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G780G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G780G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Mobile Safari/537.36 EdgA/101.0.1210.39", + "Mozilla/5.0 (Linux; Android 12; SM-G781U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G970F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G970U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36 EdgA/100.0.1185.50", + "Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G991U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-G998U1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N770F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Mobile Safari/537.36 EdgA/101.0.1210.39", + "Mozilla/5.0 (Linux; Android 12; SM-N975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N985F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N9860) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-N986U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; SM-P615) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; motorola edge 20 pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 12; vivo 1907) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.1.2; SHV-E250S Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.82 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.3; SPH-L710 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; LGMS323 Build/KOT49I.MS32310b) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-G900A Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.2; SM-T230NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.135 Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4.4; XT1032 Build/KXB21.14-L1.61) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.0.1; SCH-R970 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.1.1; Coolpad 3622A Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", + "Mozilla/5.0 (Linux; Android 5.1; C6740N Build/LMY47O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 5.1; Lenovo TAB 2 A8-50LC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Safari/537.36 OPR/66.2.3445.62346", + "Mozilla/5.0 (Linux; Android 6.0.1; SM-G900H Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.89 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; LG-D850 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.97 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; HUAWEI CAN-L11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; HUAWEI CAN-L11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; LG-H918 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; LGL84VL Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; LGUS997 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; Moto G (5) Plus Build/NPNS25.137-35-5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; Nexus 9 Build/NRD90R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G925R6 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; SM-N920C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.0; ZE520KL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; BBB100-1 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; CPH1725 Build/N6F26Q; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/360.0.0.10.113;]", + "Mozilla/5.0 (Linux; Android 7.1.1; CPH1729) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; CPH1729) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.98 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; Coolpad 3632A Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.1; XT1710-02 Build/NDS26.74-36) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.2; Nexus 6P Build/N2G48C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 7.1.2; Pixel Build/NHG47N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; F8331) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; HWI-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; LG-US998) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36 OPR/68.3.3557.64528", + "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SAMSUNG SM-G935F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/12.1 Chrome/79.0.3945.136 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-A520F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-A605G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-G930F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; SM-G935F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; WAS-LX1A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.1.0; TECNO KA7O Build/O11019; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.120 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.1.0; TECNO LA7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; ASUS_X00TD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; ONEPLUS A6003) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; POT-LX2J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi 4 Prime) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi Note 5 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi Note 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Redmi Note 8T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/16.2 Chrome/92.0.4515.166 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; SM-G950F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; VTR-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; Z6201V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; ZTE Blade A7 2020) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; moto g(6) plus) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522 (KHTML, like Gecko) Safari/419.3", + "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", + "Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", + "Mozilla/5.0 (Linux; U; Android 1.5; de-ch; HTC Hero Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; de-de; Galaxy Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; de-de; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 FirePHP/0.3", + "Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile_G2_Touch Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; SPH-M900 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; T-Mobile G1 Build/CRB43) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari 525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; htc_bahamas Build/CRB17) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; en-us; sdk Build/CUPCAKE) AppleWebkit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.5; fr-fr; GT-I5700 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.6; en-us; SonyEricssonX10i Build/R1AA056) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 1.6; es-es; SonyEricssonX10i Build/R1FA016) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", + "Mozilla/5.0 (Linux; U; Android 10; Infinix X688B Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 OPR/62.5.2254.61243", + "Mozilla/5.0 (Linux; U; Android 10; zh-Hans-CN; SPN-AL00 Build/HUAWEISPN-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.4.9.201 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 10; zh-Hans-CN; YAL-AL50 Build/HUAWEIYAL-AL50) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.6.6.211 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 11; ru-ru; Mi 9T Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.116 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.1.0-gn", + "Mozilla/5.0 (Linux; U; Android 11; zh-CN; M2012K11AC Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.4.8.200 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 11; zh-CN; V2121A Build/RP1A.200720.012) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.4.9.201 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; U; Android 2.0.1; de-de; Milestone Build/SHOLS_U2_01.14.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.1-update1; de-de; HTC Desire 1.19.161.5 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.1; en-us; HTC Legend Build/cupcake) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", + "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 2.3.3; en-us ; LS670 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1/UCBrowser/8.6.1.262/145/355", + "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; BNTV250 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1", + "Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7100 Build/HRI83) AppleWebkit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", + "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.0.3; de-de; Galaxy S II Build/GRJ22) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true", + "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; LG-P870/P87020d Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.1; en-us; sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.1 Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 4.2; en-us; sdk Build/MR1) AppleWebKit/535.19 (KHTML, like Gecko) Version/4.2 Safari/535.19", + "Mozilla/5.0 (Linux; U; Android 4.3; en-us; sdk Build/MR1) AppleWebKit/536.23 (KHTML, like Gecko) Version/4.3 Mobile Safari/536.23", + "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; GT-P5210 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", + "Mozilla/5.0 (Linux; U; Android 7.1.1; en-us; CPH1801 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.88 Mobile Safari/537.36 HeyTapBrowser/15.8.4.1", + "Mozilla/5.0 (Linux; U; Android 8.0.0; zh-cn; Mi Note 2 Build/OPR1.170623.032) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/MiuiBrowser/10.1.1", + "Mozilla/5.0 (Linux; arm; Android 10; HRY-LX1T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 YaBrowser/22.3.1.87.00 SA/3 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; webOS/2.2.4; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) webOSBrowser/221.56 Safari/534.6 Pre/3.0", + "Mozilla/5.0 (MSIE 9.0; Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14931", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:55.0) Gecko/20100101 Firefox/55.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre Camino/2.2a1pre", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:20.0) Gecko/20100101 Firefox/20.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:47.0) Gecko/20100101 Firefox/47.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 1083) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4853.129 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 OPR/28.0.1750.51", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.82 Safari/537.36 OPR/29.0.1795.41", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.105 Safari/537.36 Vivaldi/1.0.162.9", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2859.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.49 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.8 (KHTML, like Gecko) Version/10.1 Safari/603.1.30", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.75", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Flipboard/4.2.142", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4692.56 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4889.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.162 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.57 Whale/3.14.133.23 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4950.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4950.2 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.26", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.32", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.4972.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.27 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.49 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5056.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.61 Safari/537.36 ArchiveBox/0.6.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.42", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.136 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.865 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.866 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.75", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko)", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.54 Safari/535.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.26.17 (KHTML like Gecko) Version/6.0.2 Safari/536.26.17", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.31 (KHTML like Gecko) Chrome/26.0.1410.63 Safari/537.31", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.78.1 (KHTML like Gecko) Version/7.0.6 Safari/537.78.1", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.60", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.41 YaBrowser/21.2.0.2458 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.14) Gecko/20110218 AlexaToolbar/alxf-2.0 Firefox/3.6.14", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7;en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.302.2 Safari/532.8", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.464.0 Safari/534.3", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; de-de) AppleWebKit/534.15 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7; en-us) AppleWebKit/534.20.8 (KHTML, like Gecko) Version/5.1 Safari/534.20.8", + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0.112941", + "Mozilla/5.0 (Macintosh; U; Mac OS X Mach-O; en-US; rv:2.0a) Gecko/20040614 Firefox/3.0.0", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/85.8", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.15", + "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/312.5 (KHTML, like Gecko) Safari/312.3", + "Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", + "Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", + "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", + "Mozilla/5.0 (MeeGo; NokiaN950-00/00) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", + "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 929) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537", + "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Arora/0.11.0 Safari/533.3", + "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) QupZilla/1.3.1 Safari/533.3", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20100101 Firefox/10.0.12", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20130108 Firefox/10.0.12 SeaMonkey/2.7.2", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0 SeaMonkey/2.21", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0 SeaMonkey/2.28", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0", + "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0 SeaMonkey/2.42.9esr", + "Mozilla/5.0 (PLAYSTATION 3; 1.10)", + "Mozilla/5.0 (PLAYSTATION 3; 2.00)", + "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", + "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebkit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC6-01/011.010; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.2 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC7-00/012.003; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE6-00/021.002; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.16 Mobile Safari/533.4 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE7-00/010.016; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/014.002; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.4 3gpp-gba", + "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaX7-00/021.004; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.21 Mobile Safari/533.4 3gpp-gba", + "Mozilla/5.0 (SymbianOS 9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", + "Mozilla/5.0 (SymbianOS/9.1; U; de) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es50", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es65", + "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es70", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia5700/3.27; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia6120c/3.70; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.2.3.18.0", + "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaN95/10.0.018; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.3.0.0.0", + "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", + "Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 SonyEricssonP100/01; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 Safari/525", + "Mozilla/5.0 (Unknown; U; UNIX BSD/SYSV system; C -) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.2", + "Mozilla/5.0 (Unknown; UNIX BSD/SYSV system) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.7.0 Safari/538.1", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063", + "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.91 Safari/537.36 Vivaldi/1.92.917.39", + "Mozilla/5.0 (Windows NT 10.0; ARM; Lumia 950 Dual SIM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.59", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.136 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 UBrowser/5.6.13705.206 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 OPR/36.0.2130.46", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2869.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.90 Safari/537.36 Vivaldi/1.4.589.11", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 AOL/11.0 AOLBUILD/11.0.1305 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3191.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0", - "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240", - "Mozilla/5.0 (MSIE 9.0; Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14931", - "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063", - "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20130401 Firefox/21.0", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0", - "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0", - "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:35.0) Gecko/20100101 Firefox/35.0", - "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0", - "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0", - "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3883.400 QQBrowser/10.8.4559.400", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.0.3161 SLBChan/10", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.145 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.119 YaBrowser/22.3.0.2539 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.4.734 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.4.3000 Chrome/47.0.2526.73 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko", + "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 AtContent/96.5.9594.95", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.50", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.59", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.136 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.143 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.143 Safari/537.36 Edg/100.0.1185.57", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.147 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.151 Whale/3.14.134.62 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36 Edg/100.0.1185.39", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4950.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.26 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Edg/101.0.1210.32", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Config/99.2.4111.12", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.40 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5030.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5042.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2869.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3191.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.52", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 HBPC/12.0.0.300", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.113 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4624.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.846.563 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.119 Safari/537.36 Edg/98.0.1108.76", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.4.731 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.43", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.87 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.30", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 OPR/85.0.4341.22", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.46", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.72", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.75", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.79", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 OPR/85.0.4341.79 (Edition Campaign 76)", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.100.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko, Foregenix) Chrome/91.0.4472.77 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0", - "iTunes/9.0.2 (Windows; N)", - "Mozilla/5.0 (compatible; Konqueror/4.5; Windows) KHTML/4.5.4 (like Gecko)", - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Maxthon/3.0.8.2 Safari/533.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML like Gecko) Maxthon/4.0.0.2000 Chrome/22.0.1229.79 Safari/537.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/5.0.4.3000 Chrome/47.0.2526.73 Safari/537.36", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", - "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)", - "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)", - "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)", - "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0", - "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", - "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0", + "Mozilla/5.0 (Windows NT 10.0; rv:45.9) Gecko/20100101 Goanna/3.2 Firefox/45.9 PaleMoon/27.4.0", + "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36", + "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 YaBrowser/17.3.0.1785 Yowser/2.5 Safari/537.36", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) MxBrowser/4.5.10.7000 Chrome/30.0.1551.0 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; MATBJS; rv:11.0) like Gecko", - "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko", - "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.12 Safari/537.36 OPR/14.0.1116.4", + "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0", + "Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", + "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (Windows NT 5.2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", + "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.120 Safari/535.2", + "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Windows NT 6.0; rv:14.0) Gecko/20100101 Firefox/14.0.1", + "Mozilla/5.0 (Windows NT 6.0; rv:36.0) Gecko/20100101 Firefox/36.0 SeaMonkey/2.33.1", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/18.6.872.0 Safari/535.2 UNTRUSTED/1.0 3gpp-gba UNTRUSTED/1.0", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.29 Safari/537.36 OPR/15.0.1147.24 (Edition Next)", - "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.855 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.71 (KHTML like Gecko) WebVideo/1.0.1.10 Version/7.0 Safari/537.71", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Beamrise/17.2.0.9 Chrome/17.0.939.0 Safari/535.8", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML like Gecko) Maxthon/4.0.0.2000 Chrome/22.0.1229.79 Safari/537.1", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/89.0.4389.105 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.12 Safari/537.36 OPR/14.0.1116.4", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36 OPR/19.0.1326.56", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 OPR/20.0.1387.91", - "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36 OPR/28.0.1750.40", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.94.2 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36 OPR/31.0.1889.174", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 OPR/36.0.2130.46", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55", - "Mozilla/5.0 (Windows NT 10.0; rv:45.9) Gecko/20100101 Goanna/3.2 Firefox/45.9 PaleMoon/27.4.0", - "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5", - "Mozilla/5.0 (Windows; U; Windows NT 6.2; es-US ) AppleWebKit/540.0 (KHTML like Gecko) Version/6.0 Safari/8900.00", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.71 (KHTML like Gecko) WebVideo/1.0.1.10 Version/7.0 Safari/537.71", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20120422 Firefox/12.0 SeaMonkey/2.9", - "Mozilla/5.0 (Windows NT 6.0; rv:36.0) Gecko/20100101 Firefox/36.0 SeaMonkey/2.33.1", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 UBrowser/5.6.13705.206 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.94.2 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.90 Safari/537.36 Vivaldi/1.4.589.11", - "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.91 Safari/537.36 Vivaldi/1.92.917.39", - "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 YaBrowser/17.3.0.1785 Yowser/2.5 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Camino/2.2.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre Camino/2.2a1pre", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.302.2 Safari/532.8", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.464.0 Safari/534.3", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.54 Safari/535.2", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.36 Safari/535.7", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", - "Mozilla/5.0 (Macintosh; U; Mac OS X Mach-O; en-US; rv:2.0a) Gecko/20040614 Firefox/3.0.0", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.14) Gecko/20110218 AlexaToolbar/alxf-2.0 Firefox/3.6.14", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0", - "Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.15", - "Opera/9.0 (Macintosh; PPC Mac OS X; U; en)", - "Opera/9.20 (Macintosh; Intel Mac OS X; U; en)", - "Opera/9.64 (Macintosh; PPC Mac OS X; U; en) Presto/2.1.1", - "Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.6.30 Version/10.61", - "Opera/9.80 (Macintosh; Intel Mac OS X 10.4.11; U; en) Presto/2.7.62 Version/11.00", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/85.8", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-fr) AppleWebKit/312.5 (KHTML, like Gecko) Safari/312.3", - "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.31 (KHTML like Gecko) Chrome/26.0.1410.63 Safari/537.31", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 1083) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1664.3 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2859.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.49 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:20.0) Gecko/20100101 Firefox/20.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:40.0) Gecko/20100101 Firefox/40.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:47.0) Gecko/20100101 Firefox/47.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:55.0) Gecko/20100101 Firefox/55.0", - "iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)", - "iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0.112941", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/528.16 (KHTML, like Gecko, Safari/528.16) OmniWeb/v622.8.0", - "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 OPR/28.0.1750.51", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.82 Safari/537.36 OPR/29.0.1795.41", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; de-de) AppleWebKit/534.15 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7; en-us) AppleWebKit/534.20.8 (KHTML, like Gecko) Version/5.1 Safari/534.20.8", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.26.17 (KHTML like Gecko) Version/6.0.2 Safari/536.26.17", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.78.1 (KHTML like Gecko) Version/7.0.6 Safari/537.78.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Version/8.0.8 Safari/600.8.9", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.8 (KHTML, like Gecko) Version/10.1 Safari/603.1.30", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.5; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.105 Safari/537.36 Vivaldi/1.0.162.9", - "ELinks (0.4pre5; Linux 2.6.10-ac7 i686; 80x33)", - "ELinks/0.9.3 (textmode; Linux 2.6.9-kanotix-8 i686; 127x41)", - "ELinks/0.12~pre5-4", - "Links/0.9.1 (Linux 2.4.24; i386;)", - "Links (2.1pre15; Linux 2.4.26 i686; 158x61)", - "Links (2.3pre1; Linux 2.6.38-8-generic x86_64; 170x48)", - "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/0.8.12", - "w3m/0.5.1", - "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.4 (KHTML, like Gecko) Chrome/4.0.237.0 Safari/532.4 Debian", - "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.277.0 Safari/532.8", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.309.0 Safari/532.9", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/9.1.0.0 Safari/540.0", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.613.0 Safari/534.15", - "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.613.0 Chrome/10.0.613.0 Safari/534.15", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1", - "Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Ubuntu/11.04 Chromium/14.0.825.0 Chrome/14.0.825.0 Safari/535.1", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.120 Chrome/15.0.874.120 Safari/535.2", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", - "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Epiphany/1.2.5", - "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8", - "Mozilla/5.0 (X11; U; Linux x86_64; sv-SE; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.10 (karmic) Firefox/3.0.11", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090803 Ubuntu/9.04 (jaunty) Shiretoko/3.5.2", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5) Gecko/20091107 Firefox/3.5.5", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Linux Mint/8 (Helena) Firefox/3.5.3", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9", - "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8", - "Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre", - "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", - "Mozilla/5.0 (X11; Linux x86_64; rv:2.2a1pre) Gecko/20100101 Firefox/4.2a1pre", - "Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20100101 Firefox/6.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:7.0a1) Gecko/20110623 Firefox/7.0a1", - "Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0", - "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1", - "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Galeon/1.3.14", - "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.8.1.13) Gecko/20080313 Iceape/1.1.9 (Debian-1.1.9-5)", - "Mozilla/5.0 (X11; U; Linux i686; pt-PT; rv:1.9.2.3) Gecko/20100402 Iceweasel/3.6.3 (like Firefox/3.6.3) GTB7.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0 Iceweasel/5.0", - "Mozilla/5.0 (X11; Linux i686; rv:6.0a2) Gecko/20110615 Firefox/6.0a2 Iceweasel/6.0a2", - "Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20100101 Firefox/14.0.1 Iceweasel/14.0.1", - "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120724 Debian Iceweasel/15.02", - "Konqueror/3.0-rc4; (Konqueror/3.0-rc4; i686 Linux;;datecode)", - "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8-gentoo-r3; X11;", - "Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.30-7.dmz.1-liquorix-686; X11) KHTML/3.5.10 (like Gecko) (Debian package 4:3.5.10.dfsg.1-1 b1)", - "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; en_US) KHTML/3.5.6 (like Gecko) (Kubuntu)", - "Mozilla/5.0 (X11; Linux x86_64; en-US; rv:2.0b2pre) Gecko/20100712 Minefield/4.0b2pre", - "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Debian/1.6-7", - "MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23", - "Opera/9.64 (X11; Linux i686; U; Linux Mint; nb) Presto/2.1.1", - "Opera/9.80 (X11; Linux i686; U; en) Presto/2.2.15 Version/10.10", - "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) QupZilla/1.2.0 Safari/534.34", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.17) Gecko/20110123 SeaMonkey/2.0.12", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)", - "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.1", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b4pre) Gecko/20100815 Minefield/4.0b4pre", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0a2) Gecko/20110622 Firefox/6.0a2", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0", + "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20130401 Firefox/21.0", + "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", + "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", + "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 635) like Gecko", + "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 920) like Geckoo", + "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36 OPR/28.0.1750.40", + "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0) Gecko/16.0 Firefox/16.0", + "Mozilla/5.0 (Windows NT 6.2; rv:19.0) Gecko/20121129 Firefox/19.0", + "Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0", + "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", + "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49", + "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.3.852 Yowser/2.5 Safari/537.36", + "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0", + "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0", + "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko", + "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 630) like Gecko", + "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) like Gecko", + "Mozilla/5.0 (Windows; U; ; en-NZ) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.8.0", + "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.4) Gecko Netscape/7.1 (ax)", + "Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.2b) Gecko/20021001 Phoenix/0.2", + "Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.800) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090825 SeaMonkey/1.1.18", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10", + "Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)", + "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9", + "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", + "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.6 (Change: )", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Maxthon/3.0.8.2 Safari/533.1", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14", + "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 GTB5", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.1.17) Gecko/20110123 (like Firefox/3.x) SeaMonkey/2.0.12", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5", + "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/10.0.601.0 Safari/534.14", + "Mozilla/5.0 (Windows; U; Windows NT 6.2; es-US ) AppleWebKit/540.0 (KHTML like Gecko) Version/6.0 Safari/8900.00", + "Mozilla/5.0 (Windows; U; Windows XP) Gecko MultiZilla/1.6.1.0a", + "Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; CentOS; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0", + "Mozilla/5.0 (X11; CrOS aarch64 14388.61.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.107 Safari/537.36", + "Mozilla/5.0 (X11; CrOS aarch64 14526.89.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.56 Safari/537.4", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1478.0 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 13982.88.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.162 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14469.59.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.94 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14526.89.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14526.89.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36", + "Mozilla/5.0 (X11; CrOS x86_64 14588.98.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.59 Safari/537.36", "Mozilla/5.0 (X11; CrOS x86_64 5841.83.0) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.138 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.125 Safari/537.36", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2166.2 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36", - "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36", + "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2876.0 Safari/537.36", - "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3187.0 Safari/537.366", "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3178.0 Safari/537.36", + "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/535.22+ (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/535.22+ Epiphany/2.30.6", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/536.5 (KHTML like Gecko) Chrome/19.0.1084.56 Safari/536.5", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", + "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", + "Mozilla/5.0 (X11; FreeBSD amd64; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (X11; FreeBSD amd64; rv:54.0) Gecko/20100101 Firefox/54.0", + "Mozilla/5.0 (X11; FreeBSD i386; rv:28.0) Gecko/20100101 Firefox/28.0 SeaMonkey/2.25", + "Mozilla/5.0 (X11; Linux 3.8-6.dmz.1-liquorix-686) KHTML/4.8.4 (like Gecko) Konqueror/4.8", + "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3187.0 Safari/537.366", + "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) QupZilla/1.2.0 Safari/534.34", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Ubuntu/11.04 Chromium/14.0.825.0 Chrome/14.0.825.0 Safari/535.1", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Ubuntu/11.10 Chromium/15.0.874.120 Chrome/15.0.874.120 Safari/535.2", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/33.0.1750.152 Chrome/33.0.1750.152 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1478.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2166.2 Safari/537.36", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36 OPR/40.0.2308.62", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/51.0.2704.79 Chrome/51.0.2704.79 Safari/537.36", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/60.0.3112.78 Chrome/60.0.3112.78 Safari/537.36", - "Mozilla/4.0 (compatible; Dillo 3.0)", - "Mozilla/5.0 (X11; U; Linux i686; en-us) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) lt-GtkLauncher", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.32 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.32 Epiphany/3.8.2", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/604.1 (KHTML, like Gecko) Version/11.0 Safari/604.1 Ubuntu/17.04 (3.24.1-0ubuntu1) Epiphany/3.24.1", + "Mozilla/5.0 (X11; Linux i686) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.6 Safari/538.1", + "Mozilla/5.0 (X11; Linux i686; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", + "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0", + "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20120502 Firefox/12.0 SeaMonkey/2.9.1", + "Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20100101 Firefox/14.0.1 Iceweasel/14.0.1", "Mozilla/5.0 (X11; Linux i686; rv:16.0) Gecko/20100101 Firefox/16.0", - "Mozilla/5.0 (X11; U; Linux i686; rv:19.0) Gecko/20100101 Slackware/13 Firefox/19.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0", + "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; Linux i686; rv:2.0b6pre) Gecko/20100907 Firefox/4.0b6pre", "Mozilla/5.0 (X11; Linux i686; rv:20.0) Gecko/20100101 Firefox/20.0", "Mozilla/5.0 (X11; Linux i686; rv:25.0) Gecko/20100101 Firefox/25.0", "Mozilla/5.0 (X11; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0", "Mozilla/5.0 (X11; Linux i686; rv:32.0) Gecko/20100101 Firefox/32.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", - "Mozilla/5.0 (X11; CentOS; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0", "Mozilla/5.0 (X11; Linux i686; rv:40.0) Gecko/20100101 Firefox/40.0", "Mozilla/5.0 (X11; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0", "Mozilla/5.0 (X11; Linux i686; rv:46.0) Gecko/20100101 Firefox/46.0", "Mozilla/5.0 (X11; Linux i686; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", - "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Galeon/2.0.6 (Ubuntu 2.0.6-2)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.16) Gecko/20080716 (Gentoo) Galeon/2.0.6", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.13) Gecko/20100916 Iceape/2.0.8", - "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 Iceweasel/19.0.2", - "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1", - "Mozilla/5.0 (compatible; Konqueror/4.2; Linux) KHTML/4.2.4 (like Gecko) Slackware/13.0", - "Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.1 (like Gecko) Fedora/4.3.1-3.fc11", - "Mozilla/5.0 (compatible; Konqueror/4.4; Linux) KHTML/4.4.1 (like Gecko) Fedora/4.4.1-1.fc12", - "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", - "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", - "Mozilla/5.0 (X11; Linux 3.8-6.dmz.1-liquorix-686) KHTML/4.8.4 (like Gecko) Konqueror/4.8", - "Mozilla/5.0 (X11; Linux) KHTML/4.9.1 (like Gecko) Konqueror/4.9", + "Mozilla/5.0 (X11; Linux i686; rv:49.0) Gecko/20100101 Firefox/49.0 SeaMonkey/2.46", + "Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0", + "Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/20100101 Firefox/6.0", + "Mozilla/5.0 (X11; Linux i686; rv:6.0a2) Gecko/20110615 Firefox/6.0a2 Iceweasel/6.0a2", + "Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) konqueror/4.14.10 Safari/537.21", - "Midori/0.1.10 (X11; Linux i686; U; en-us) WebKit/(531).(2)", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a3pre) Gecko/20070330", - "Opera/9.80 (X11; Linux i686) Presto/2.12.388 Version/12.16", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.166 Safari/537.36 OPR/20.0.1396.73172", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.32 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.32 Epiphany/3.8.2", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.125 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.50", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 OPR/86.0.4363.59", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.147 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.4997.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.9999.0 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.166 Safari/537.36 OPR/20.0.1396.73172", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36 OPR/40.0.2308.62", - "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.8.0.2965AT", - "Mozilla/5.0 (X11; Linux i686) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.8.6 Safari/538.1", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.9.0 Safari/538.1", - "Mozilla/5.0 (X11; Linux i686; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 SeaMonkey/2.7.1", - "Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20120502 Firefox/12.0 SeaMonkey/2.9.1", - "Mozilla/5.0 (Windows NT 5.1; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", - "Mozilla/5.0 (X11; Linux i686; rv:49.0) Gecko/20100101 Firefox/49.0 SeaMonkey/2.46", - "Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0", - "Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.2.3) Gecko/20100406 Firefox/3.6.3 (Swiftfox)", - "Uzbl (Webkit 1.3) (Linux i686 [i686])", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 Vivaldi/1.0.344.37", - "ELinks (0.4.3; NetBSD 3.0.2PATCH sparc64; 141x19)", - "Links (2.1pre15; FreeBSD 5.3-RELEASE i386; 196x84)", - "Lynx/2.8.7dev.4 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8d", - "w3m/0.5.1", - "Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.207.0 Safari/532.0", - "Mozilla/5.0 (X11; U; OpenBSD i386; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.359.0 Safari/533.3", - "Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16", - "Mozilla/5.0 (X11; U; SunOS sun4m; en-US; rv:1.4b) Gecko/20030517 Mozilla Firebird/0.6", - "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.9.1b3) Gecko/20090429 Firefox/3.1b3", - "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.1) Gecko/20090702 Firefox/3.5", - "Mozilla/5.0 (X11; U; FreeBSD i386; de-CH; rv:1.9.2.8) Gecko/20100729 Firefox/3.6.8", - "Mozilla/5.0 (X11; FreeBSD amd64; rv:5.0) Gecko/20100101 Firefox/5.0", - "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040406 Galeon/1.3.15", - "Mozilla/5.0 (compatible; Konqueror/3.5; NetBSD 4.0_RC3; X11) KHTML/3.5.7 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/3.5; SunOS) KHTML/3.5.1 (like Gecko)", - "Mozilla/5.0 (X11; U; FreeBSD; i386; en-US; rv:1.7) Gecko", - "Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)", - "Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)", - "Mozilla/5.0 (Unknown; U; UNIX BSD/SYSV system; C -) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.2", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/536.5 (KHTML like Gecko) Chrome/19.0.1084.56 Safari/536.5", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.79 Safari/537.4", - "Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36", - "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36", - "Mozilla/5.0 (X11; NetBSD x86; en-us) AppleWebKit/666.6+ (KHTML, like Gecko) Chromium/20.0.0000.00 Chrome/20.0.0000.00 Safari/666.6+", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/535.22+ (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/535.22+ Epiphany/2.30.6", - "Mozilla/5.0 (X11; U; OpenBSD arm; en-us) AppleWebKit/531.2 (KHTML, like Gecko) Safari/531.2 Epiphany/2.30.0", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2876.0 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.3 Chrome/87.0.4280.144 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/33.0.1750.152 Chrome/33.0.1750.152 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) obsidian/0.14.6 Chrome/100.0.4896.75 Electron/18.0.4 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.56 Safari/537.4", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.9.0 Safari/538.1", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/602.1 (KHTML, like Gecko) splash Version/10.0 Safari/602.1", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/604.1 (KHTML, like Gecko) Version/11.0 Safari/604.1 Ubuntu/17.04 (3.24.1-0ubuntu1) Epiphany/3.24.1", + "Mozilla/5.0 (X11; Linux x86_64; en-US; rv:2.0b2pre) Gecko/20100712 Minefield/4.0b2pre", + "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1", + "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120724 Debian Iceweasel/15.02", + "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 Iceweasel/19.0.2", + "Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; Linux x86_64; rv:2.2a1pre) Gecko/20100101 Firefox/4.2a1pre", + "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0", + "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1", + "Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0 Iceweasel/5.0", + "Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", + "Mozilla/5.0 (X11; Linux x86_64; rv:7.0a1) Gecko/20110623 Firefox/7.0a1", + "Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0", + "Mozilla/5.0 (X11; Linux) KHTML/4.9.1 (like Gecko) Konqueror/4.9", "Mozilla/5.0 (X11; NetBSD amd64; rv:16.0) Gecko/20121102 Firefox/16.0", - "Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0", "Mozilla/5.0 (X11; NetBSD amd64; rv:30.0) Gecko/20100101 Firefox/30.0", + "Mozilla/5.0 (X11; NetBSD x86; en-us) AppleWebKit/666.6+ (KHTML, like Gecko) Chromium/20.0.0000.00 Chrome/20.0.0000.00 Safari/666.6+", + "Mozilla/5.0 (X11; NetBSD) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36", + "Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0", "Mozilla/5.0 (X11; OpenBSD amd64; rv:30.0) Gecko/20100101 Firefox/30.0", - "Mozilla/5.0 (X11; FreeBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", - "Mozilla/5.0 (X11; FreeBSD amd64; rv:54.0) Gecko/20100101 Firefox/54.0", - "Mozilla/5.0 (compatible; Konqueror/4.1; DragonFly) KHTML/4.1.4 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/4.5; NetBSD 5.0.2; X11; amd64; en_US) KHTML/4.5.4 (like Gecko)", - "Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)", - "Mozilla/5.0 (X11; U; NetBSD amd64; en-US; rv:1.9.2.15) Gecko/20110308 Namoroka/3.6.15", - "NetSurf/1.2 (NetBSD; amd64)", - "Opera/9.80 (X11; FreeBSD 8.1-RELEASE i386; Edition Next) Presto/2.12.388 Version/12.10", - "Mozilla/5.0 (Unknown; UNIX BSD/SYSV system) AppleWebKit/538.1 (KHTML, like Gecko) QupZilla/1.7.0 Safari/538.1", - "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1.12) Gecko/20080303 SeaMonkey/1.1.8", - "Mozilla/5.0 (X11; FreeBSD i386; rv:28.0) Gecko/20100101 Firefox/28.0 SeaMonkey/2.25", - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.800) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0", - "Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)", - "Mozilla/1.22 (compatible; MSIE 5.01; PalmOS 3.0) EudoraWeb 2.1", - "Mozilla/5.0 (WindowsCE 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1", + "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36", + "Mozilla/5.0 (X11; U; FreeBSD i386; de-CH; rv:1.9.2.8) Gecko/20100729 Firefox/3.6.8", + "Mozilla/5.0 (X11; U; FreeBSD i386; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.207.0 Safari/532.0", + "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040406 Galeon/1.3.15", + "Mozilla/5.0 (X11; U; FreeBSD x86_64; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16", + "Mozilla/5.0 (X11; U; FreeBSD; i386; en-US; rv:1.7) Gecko", + "Mozilla/5.0 (X11; U; Linux arm7tdmi; rv:1.8.1.11) Gecko/20071130 Minimo/0.025", "Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1", - "Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (Maemo; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", - "Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0", - "Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016", "Mozilla/5.0 (X11; U; Linux armv6l; rv 1.8.1.5pre) Gecko/20070619 Minimo/0.020", - "Mozilla/5.0 (X11; U; Linux arm7tdmi; rv:1.8.1.11) Gecko/20071130 Minimo/0.025", - "Mozilla/4.0 (PDA; PalmOS/sony/model prmr/Revision:1.1.54 (en)) NetFront/3.0", - "Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)", - "Opera/9.60 (J2ME/MIDP; Opera Mini/4.1.11320/608; U; en) Presto/2.2.0", - "Opera/9.60 (J2ME/MIDP; Opera Mini/4.2.14320/554; U; cs) Presto/2.2.0", - "Opera/9.80 (S60; SymbOS; Opera Mobi/499; U; ru) Presto/2.4.18 Version/10.00", - "Opera/10.61 (J2ME/MIDP; Opera Mini/5.1.21219/19.999; en-US; rv:1.9.3a5) WebKit/534.5 Presto/2.6.30", - "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.1010", - "Opera/9.80 (J2ME/MIDP; Opera Mini/8.0.35626/37.8918; U; en) Presto/2.12.423 Version/12.16", - "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", - "Opera/9.80 (Android; Opera Mini/9.0.1829/66.318; U; en) Presto/2.12.423 Version/12.16", - "Opera/9.80 (Linux i686; Opera Mobi/1040; U; en) Presto/2.5.24 Version/10.00", - "POLARIS/6.01 (BREW 3.1.5; U; en-us; LG; LX265; POLARIS/6.01/WAP) MMP/2.0 profile/MIDP-2.1 Configuration/CLDC-1.1", + "Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+", + "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)", + "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.4 (KHTML, like Gecko) Chrome/4.0.237.0 Safari/532.4 Debian", + "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.8 (KHTML, like Gecko) Chrome/4.0.277.0 Safari/532.8", + "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Ubuntu/10.10 Chromium/10.0.613.0 Chrome/10.0.613.0 Safari/534.15", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7 MG(Novarra-Vision/6.9)", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.16) Gecko/20080716 (Gentoo) Galeon/2.0.6", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.10 (karmic) Firefox/3.0.11", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Galeon/2.0.6 (Ubuntu 2.0.6-2)", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090803 Ubuntu/9.04 (jaunty) Shiretoko/3.5.2", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a3pre) Gecko/20070330", + "Mozilla/5.0 (X11; U; Linux i686; en-gb) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.0.5603M", + "Mozilla/5.0 (X11; U; Linux i686; en-us) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) lt-GtkLauncher", + "Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.2.3) Gecko/20100406 Firefox/3.6.3 (Swiftfox)", + "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8", + "Mozilla/5.0 (X11; U; Linux i686; pt-PT; rv:1.9.2.3) Gecko/20100402 Iceweasel/3.6.3 (like Firefox/3.6.3) GTB7.0", + "Mozilla/5.0 (X11; U; Linux i686; rv:19.0) Gecko/20100101 Slackware/13 Firefox/19.0", + "Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:1.8.1.13) Gecko/20080313 Iceape/1.1.9 (Debian-1.1.9-5)", + "Mozilla/5.0 (X11; U; Linux x86_64; en-AU) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IT", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.309.0 Safari/532.9", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.15 (KHTML, like Gecko) Chrome/10.0.613.0 Safari/534.15", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/540.0 (KHTML, like Gecko) Ubuntu/10.10 Chrome/9.1.0.0 Safari/540.0", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.3) Gecko/2008092814 (Debian-3.0.1-1)", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.13) Gecko/20100916 Iceape/2.0.8", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.17) Gecko/20110123 SeaMonkey/2.0.12", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Linux Mint/8 (Helena) Firefox/3.5.3", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5) Gecko/20091107 Firefox/3.5.5", + "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9", "Mozilla/5.0 (X11; U; Linux x86_64; en-gb) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.9174AP", "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.9174AT", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 6_1 like Mac OS X; en-HK) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IP Mobile", - "Mozilla/5.0 (X11; U; Linux x86_64; en-AU) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IT", - "Mozilla/5.0 (X11; U; Linux i686; en-gb) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.0.5603M", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25", + "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.8.0.2965AT", + "Mozilla/5.0 (X11; U; Linux x86_64; sv-SE; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12", + "Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0", + "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527 (KHTML, like Gecko, Safari/419.3) Arora/0.10.1", + "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Debian/1.6-7", + "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Epiphany/1.2.5", + "Mozilla/5.0 (X11; U; Linux; i686; en-US; rv:1.6) Gecko Galeon/1.3.14", + "Mozilla/5.0 (X11; U; NetBSD amd64; en-US; rv:1.9.2.15) Gecko/20110308 Namoroka/3.6.15", + "Mozilla/5.0 (X11; U; OpenBSD arm; en-us) AppleWebKit/531.2 (KHTML, like Gecko) Safari/531.2 Epiphany/2.30.0", + "Mozilla/5.0 (X11; U; OpenBSD i386; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.359.0 Safari/533.3", + "Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.9.1) Gecko/20090702 Firefox/3.5", + "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1.12) Gecko/20080303 SeaMonkey/1.1.8", + "Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.9.1b3) Gecko/20090429 Firefox/3.1b3", + "Mozilla/5.0 (X11; U; SunOS sun4m; en-US; rv:1.4b) Gecko/20030517 Mozilla Firebird/0.6", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0", + "Mozilla/5.0 (compatible; Exabot/3.0; http://www.exabot.com/go/robot)", + "Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)", + "Mozilla/5.0 (compatible; Konqueror/3.3; Linux 2.6.8-gentoo-r3; X11;", + "Mozilla/5.0 (compatible; Konqueror/3.5; Linux 2.6.30-7.dmz.1-liquorix-686; X11) KHTML/3.5.10 (like Gecko) (Debian package 4:3.5.10.dfsg.1-1 b1)", + "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; en_US) KHTML/3.5.6 (like Gecko) (Kubuntu)", + "Mozilla/5.0 (compatible; Konqueror/3.5; NetBSD 4.0_RC3; X11) KHTML/3.5.7 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/3.5; SunOS) KHTML/3.5.1 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.1; DragonFly) KHTML/4.1.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.1; OpenBSD) KHTML/4.1.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.2; Linux) KHTML/4.2.4 (like Gecko) Slackware/13.0", + "Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.1 (like Gecko) Fedora/4.3.1-3.fc11", + "Mozilla/5.0 (compatible; Konqueror/4.4; Linux 2.6.32-22-generic; X11; en_US) KHTML/4.4.3 (like Gecko) Kubuntu", + "Mozilla/5.0 (compatible; Konqueror/4.4; Linux) KHTML/4.4.1 (like Gecko) Fedora/4.4.1-1.fc12", + "Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.5; NetBSD 5.0.2; X11; amd64; en_US) KHTML/4.5.4 (like Gecko)", + "Mozilla/5.0 (compatible; Konqueror/4.5; Windows) KHTML/4.5.4 (like Gecko)", + "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", + "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)", + "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", + "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; XBLWP7; ZuneWP7) UCBrowser/2.9.0.263", - "Mozilla/5.0 (Linux; U; Android 2.3.3; en-us ; LS670 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1/UCBrowser/8.6.1.262/145/355", - "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/5.0 (Linux; U; Android 4.1; en-us; sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.1 Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 4.2; en-us; sdk Build/MR1) AppleWebKit/535.19 (KHTML, like Gecko) Version/4.2 Safari/535.19", - "Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/2.9174AT", - "Mozilla/5.0 (X11; U; Linux x86_64; en-AU) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IT", - "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10", - "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPad; U; CPU OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; Zune 4.7)", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Trident/5.0)", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)", + "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", + "Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)", + "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)", + "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)", + "Mozilla/5.0 (compatible; YandexNews/4.0; +http://yandex.com/bots)", + "Mozilla/5.0 (compatible; alexa site audit/1.0; +http://www.alexa.com/help/webmasters; )", + "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)", + "Mozilla/5.0 (compatible; archive.org_bot; Wayback Machine Live Record; +http://archive.org/details/archive.org_bot)", + "Mozilla/5.0 (compatible; bingbot/2.0 http://www.bing.com/bingbot.htm)", + "Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13", + "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0", + "Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/49.0.2623.109 Mobile/14A5335b Safari/601.1.46", + "Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/100.0.4896.85 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/99.0.4844.59 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPad; CPU OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Flipboard/4.2.142", + "Mozilla/5.0 (iPad; CPU OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", "Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko ) Version/5.1 Mobile/9B176 Safari/7534.48.3", "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25", + "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25 (3B92C18B-D9DE-4CB7-A02A-22FD2AF17C8F)", + "Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", "Mozilla/5.0 (iPad; CPU OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML like Gecko) Mobile/12A405 Version/7.0 Safari/9537.53", "Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4", "Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1", - "Mozilla/5.0 (iPad; CPU OS 10_0 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/49.0.2623.109 Mobile/14A5335b Safari/601.1.46", - "Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7;en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17", - "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0", - "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true", - "Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36", - "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", - "Mozilla/5.0 (Linux; U; Android 1.5; de-de; Galaxy Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; GT-P5210 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7100 Build/HRI83) AppleWebkit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 600x800)", - "Mozilla/5.0 (Linux U; en-US) AppleWebKit/528.5 (KHTML, like Gecko, Safari/528.5 ) Version/4.0 Kindle/3.0 (screen 600x800; rotate)", - "Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+", - "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true", "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10", "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", "Mozilla/5.0 (iPad; U; CPU OS 4_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5", "Mozilla/5.0 (iPad; U; CPU iPad OS 5_0_1 like Mac OS X; en-us) AppleWebKit/535.1+ (KHTML like Gecko) Version/7.2.0.0 Safari/6533.18.5", - "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25", - "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25 (3B92C18B-D9DE-4CB7-A02A-22FD2AF17C8F)", - "Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", - "Mozilla/5.0 (iPad; CPU OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML like Gecko) Mobile/12A405 Version/7.0 Safari/9537.53", - "Mozilla/5.0 (iPad; CPU OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4", - "Mozilla/5.0 (iPad; CPU OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13F69 Safari/601.1", - "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36 Puffin/4.5.0IT", - "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.200", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/531.22.7", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3", + "Mozilla/5.0 (iPhone; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.25 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/28.0 Mobile/15E148 Safari/605.1.15", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/18.0.130791545 Mobile/14A5345a Safari/600.1.4", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A346 Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G60 Safari/602.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/91.0.4472.80 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/101.0.4951.58 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_8_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 OPT/3.2.13", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X; zh-CN) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19B81 UCBrowser/13.7.2.1636 Mobile AliApp(TUnionSDK/0.1.20.4) dv(iPh14,5);pr(UCBrowser/13.7.2.1636);ov(15_1_1);ss(390x844);bt(UC);pm(0);bv(0);nm(0);im(0);nt(1);", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari Line/12.6.0", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/100.0.4896.77 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/101.0.4951.44 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/101.0.4951.58 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/96.0.4664.101 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/99.0.4844.59 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/209.1.445234187 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/99.3 Mobile/15E148 Safari/605.1.15", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Zalo iOS/448 ZaloTheme/light ZaloLanguage/en", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/605.1 NAVER(inapp; search; 1000; 11.5.7; XR)", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1", "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A403 Safari/8536.25", - "UCWEB/8.8 (iPhone; CPU OS_6; en-US)AppleWebKit/534.1 U3/3.0.0 Mobile", "Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", "Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4", "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/8.0.57838 Mobile/12H321 Safari/600.1.4", "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13C75 Safari/601.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A346 Safari/602.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/18.0.130791545 Mobile/14A5345a Safari/600.1.4", - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1_1 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7C145", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.200", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/531.22.7", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8F190", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3", + "Mozilla/5.0 (iPhone; U; CPU iPhone OS) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", + "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3", "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML like Gecko) Version/7.0 Mobile/11D167 Safari/123E71C", "Mozilla/5.0 (iPod; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/44.0.2403.67 Mobile/12H143 Safari/600.1.4", - "nook browser/1.0", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7;en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; BNTV250 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1", - "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36", - "BlackBerry7100i/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/103", - "BlackBerry8300/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/107 UP.Link/6.2.3.15.0", - "BlackBerry8320/4.2.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/100", - "BlackBerry8330/4.3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/105", - "BlackBerry9000/4.6.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102", - "BlackBerry9530/4.7.0.167 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102 UP.Link/6.3.1.20.0", - "BlackBerry9700/5.0.0.351 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/123", - "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1 (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1", - "Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.267 Mobile Safari/534.11+", - "Mozilla/5.0 (Linux; Android 7.1.1; BBB100-1 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+", - "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.1.0.2342 Mobile Safari/537.10+", - "Mozilla/5.0 (Linux; Android 5.1.1; Coolpad 3622A Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.1; Coolpad 3632A Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; sdk Build/CUPCAKE) AppleWebkit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.2; Nexus 6P Build/N2G48C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML like Gecko) Chrome/36.0.1985.135 Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", - "Mozilla/5.0 (Linux; Android 7.0; Nexus 9 Build/NRD90R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.2; Pixel Build/NHG47N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0", - "Mozilla/5.0 (Linux; webOS/2.2.4; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) webOSBrowser/221.56 Safari/534.6 Pre/3.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) Sprint:PPC6800", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) XV6800", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; htc_bahamas Build/CRB17) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.1-update1; de-de; HTC Desire 1.19.161.5 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 1.5; de-ch; HTC Hero Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.1; en-us; HTC Legend Build/cupcake) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 1.5; de-de; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 FirePHP/0.3", - "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "HTC-ST7377/1.59.502.3 (67150) Opera/9.50 (Windows NT 5.1; U; en) UP.Link/6.3.1.17.0", - "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.89 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.1; C6740N Build/LMY47O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; LG-P870/P87020d Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "LG-LX550 AU-MIC-LX550/2.0 MMP/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/5.0 (Linux; Android 6.0; LG-D850 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.97 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LG-H918 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LGL84VL Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LGUS997 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; LGMS323 Build/KOT49I.MS32310b) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Mobile Safari/537.36", - "POLARIS/6.01(BREW 3.1.5;U;en-us;LG;LX265;POLARIS/6.01/WAP;)MMP/2.0 profile/MIDP-201 Configuration /CLDC-1.1", - "LG-GC900/V10a Obigo/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1", - "Mozilla/5.0 (Linux; Android 4.4.2; LG-V410 Build/KOT49I.V41010d) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.103 Safari/537.36", - "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; MDA Pro/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1)", - "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; T-Mobile G1 Build/CRB43) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari 525.20.1", - "Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile_G2_Touch Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "MOT-L7v/08.B7.5DR MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.0.1; de-de; Milestone Build/SHOLS_U2_01.14.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; Android 7.0; Moto G (5) Plus Build/NPNS25.137-35-5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.1.1; XT1710-02 Build/NDS26.74-36) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36", - "MOT-V9mm/00.62 UP.Browser/6.2.3.4.c.1.123 (GUI) MMP/2.0", - "MOTORIZR-Z8/46.00.00 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 356) Opera 8.65 [it] UP.Link/6.3.0.0.0", - "MOT-V177/0.1.75 UP.Browser/6.2.3.9.c.12 (GUI) MMP/2.0 UP.Link/6.3.1.13.0", - "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; Android 4.4.4; XT1032 Build/KXB21.14-L1.61) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", - "portalmmm/2.0 N410i(c20;TB)", - "Nokia3230/2.0 (5.0614.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia5700/3.27; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia6120c/3.70; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Nokia6230/2.0 (04.44) Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Nokia6230i/2.0 (03.80) Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/4.1 (compatible; MSIE 5.0; Symbian OS; Nokia 6600;452) Opera 6.20 [en-US]", - "Nokia6630/1.0 (2.39.15) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Nokia7250/1.0 (3.14) Profile/MIDP-1.0 Configuration/CLDC-1.0", - "Mozilla/4.0 (compatible; MSIE 5.0; Series80/2.0 Nokia9500/4.51 Profile/MIDP-2.0 Configuration/CLDC-1.1)", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC6-01/011.010; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.2 3gpp-gba", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaC7-00/012.003; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es50", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE6-00/021.002; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.16 Mobile Safari/533.4 3gpp-gba", - "UCWEB/8.8 (SymbianOS/9.2; U; en-US; NokiaE63) AppleWebKit/534.1 UCBrowser/8.8.0.245 Mobile", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es65", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE7-00/010.016; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.7.3 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413 es70", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.2.3.18.0", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 630) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 635) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 920) like Geckoo", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) like Gecko", - "NokiaN70-1/5.0609.2.0.1 Series60/2.8 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "NokiaN73-1/3.0649.0.0.1 Series60/3.0 Profile/MIDP2.0 Configuration/CLDC-1.1", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/014.002; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.4 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", - "Mozilla/5.0 (SymbianOS/9.1; U; de) AppleWebKit/413 (KHTML, like Gecko) Safari/413", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaN95/10.0.018; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.3.0.0.0", - "Mozilla/5.0 (MeeGo; NokiaN950-00/00) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", - "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaX7-00/021.004; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.21 Mobile Safari/533.4 3gpp-gba", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1_1 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7C145", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 6_1 like Mac OS X; en-HK) AppleWebKit/534.35 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.35 Puffin/3.9174IP Mobile", "Mozilla/5.0 (webOS/1.3; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320", - "SEC-SGHE900/1.0 NetFront/3.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1378; nl; U; ssr)", - "Mozilla/5.0 (Linux; U; Android 1.5; de-de; Galaxy Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-de; Galaxy S II Build/GRJ22) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "Mozilla/5.0 (Linux; Android 4.3; SPH-L710 Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.0.1; SCH-R970 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-G900A Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; GT-P5210 Build/KOT49H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 3.0.1; en-us; GT-P7100 Build/HRI83) AppleWebkit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", + "Mozilla/5.0 Slackware/13.37 (X11; U; Linux x86_64; en-US) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41", + "NetSurf/1.2 (NetBSD; amd64)", + "Nokia3230/2.0 (5.0614.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0", + "Nokia6100/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0", + "Nokia6230/2.0 (04.44) Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia6230i/2.0 (03.80) Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia6630/1.0 (2.3.129) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia6630/1.0 (2.39.15) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Nokia7250/1.0 (3.14) Profile/MIDP-1.0 Configuration/CLDC-1.0", + "NokiaN70-1/5.0609.2.0.1 Series60/2.8 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0", + "NokiaN73-1/3.0649.0.0.1 Series60/3.0 Profile/MIDP2.0 Configuration/CLDC-1.1", + "Offline Explorer/2.5", + "Opera/10.61 (J2ME/MIDP; Opera Mini/5.1.21219/19.999; en-US; rv:1.9.3a5) WebKit/534.5 Presto/2.6.30", + "Opera/7.50 (Windows ME; U) [en]", + "Opera/7.50 (Windows XP; U)", + "Opera/7.51 (Windows NT 5.1; U) [en]", + "Opera/8.01 (J2ME/MIDP; Opera Mini/1.0.1479/HiFi; SonyEricsson P900; no; U; ssr)", + "Opera/9.0 (Macintosh; PPC Mac OS X; U; en)", + "Opera/9.20 (Macintosh; Intel Mac OS X; U; en)", + "Opera/9.25 (Windows NT 6.0; U; en)", + "Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)", + "Opera/9.5 (Microsoft Windows; PPC; Opera Mobi; U) SonyEricssonX1i/R2AA Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)", + "Opera/9.60 (J2ME/MIDP; Opera Mini/4.1.11320/608; U; en) Presto/2.2.0", + "Opera/9.60 (J2ME/MIDP; Opera Mini/4.2.14320/554; U; cs) Presto/2.2.0", + "Opera/9.64 (Macintosh; PPC Mac OS X; U; en) Presto/2.1.1", + "Opera/9.64 (X11; Linux i686; U; Linux Mint; nb) Presto/2.1.1", + "Opera/9.80 (Android 4.0.4; Linux; Opera Mobi/ADR-1205181138; U; pl) Presto/2.10.254 Version/12.00", + "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.1010", + "Opera/9.80 (Android; Opera Mini/9.0.1829/66.318; U; en) Presto/2.12.423 Version/12.16", + "Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.16823/1428; U; en) Presto/2.2.0", + "Opera/9.80 (J2ME/MIDP; Opera Mini/8.0.35626/37.8918; U; en) Presto/2.12.423 Version/12.16", + "Opera/9.80 (Linux i686; Opera Mobi/1040; U; en) Presto/2.5.24 Version/10.00", + "Opera/9.80 (Macintosh; Intel Mac OS X 10.4.11; U; en) Presto/2.7.62 Version/11.00", + "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", + "Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.6.30 Version/10.61", + "Opera/9.80 (S60; SymbOS; Opera Mobi/499; U; ru) Presto/2.4.18 Version/10.00", + "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10", + "Opera/9.80 (Windows NT 5.2; U; en) Presto/2.2.15 Version/10.10", + "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", + "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.7.62 Version/11.01", + "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00", + "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.16", + "Opera/9.80 (X11; FreeBSD 8.1-RELEASE i386; Edition Next) Presto/2.12.388 Version/12.10", + "Opera/9.80 (X11; Linux i686) Presto/2.12.388 Version/12.16", + "Opera/9.80 (X11; Linux i686; U; en) Presto/2.2.15 Version/10.10", + "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00", + "P3P Validator", + "POLARIS/6.01 (BREW 3.1.5; U; en-us; LG; LX265; POLARIS/6.01/WAP) MMP/2.0 profile/MIDP-2.1 Configuration/CLDC-1.1", + "POLARIS/6.01(BREW 3.1.5;U;en-us;LG;LX265;POLARIS/6.01/WAP;)MMP/2.0 profile/MIDP-201 Configuration /CLDC-1.1", + "Peach/1.01 (Ubuntu 8.04 LTS; U; en)", + "Python-urllib/2.5", + "Roku/DVP-4.1 (024.01E01250A)", "SAMSUNG-S8000/S8000XXIF3 SHP/VPP/R5 Jasmine/1.0 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 FirePHP/0.3", - "Mozilla/5.0 (Linux; U; Android 1.5; en-us; SPH-M900 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", "SAMSUNG-SGH-A867/A867UCHJ3 SHP/VPP/R5 NetFront/35 SMM-MMS/1.2.0 profile/MIDP-2.0 configuration/CLDC-1.1 UP.Link/6.3.0.0.0", + "SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", + "SEC-SGHE900/1.0 NetFront/3.2 Profile/MIDP-2.0 Configuration/CLDC-1.1 Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1378; nl; U; ssr)", "SEC-SGHX210/1.0 UP.Link/6.3.1.13.0", - "Mozilla/5.0 (Linux; Android 6.0.1; SM-G900H Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G925R6 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", - "Mozilla/5.0 (Linux; U; Android 1.5; fr-fr; GT-I5700 Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", "SEC-SGHX820/1.0 NetFront/3.2 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "Screaming Frog SEO Spider/8.1", + "SearchExpress", "SonyEricssonK310iv/R4DA Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.1.13.0", "SonyEricssonK550i/R1JD Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonK610i/R1CB Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonK750i/R1CA Browser/SEMC-Browser/4.2 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.16823/1428; U; en) Presto/2.2.0", "SonyEricssonK800i/R1CB Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", "SonyEricssonK810i/R1KG Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Opera/8.01 (J2ME/MIDP; Opera Mini/1.0.1479/HiFi; SonyEricsson P900; no; U; ssr)", "SonyEricssonS500i/R6BC Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 SonyEricssonP100/01; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 Safari/525", - "SonyEricssonT68/R201A", "SonyEricssonT100/R101", "SonyEricssonT610/R201 Profile/MIDP-1.0 Configuration/CLDC-1.0", "SonyEricssonT650i/R7AA Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", + "SonyEricssonT68/R201A", "SonyEricssonW580i/R6BC Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonW660i/R6AD Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonW810i/R4EA Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", "SonyEricssonW850i/R1ED Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonW950i/R100 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 323) Opera 8.60 [en-US]", "SonyEricssonW995/R1EA Profile/MIDP-2.1 Configuration/CLDC-1.1 UNTRUSTED/1.0", - "Mozilla/5.0 (Linux; U; Android 1.6; es-es; SonyEricssonX10i Build/R1FA016) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 1.6; en-us; SonyEricssonX10i Build/R1AA056) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Opera/9.5 (Microsoft Windows; PPC; Opera Mobi; U) SonyEricssonX1i/R2AA Profile/MIDP-2.0 Configuration/CLDC-1.1", "SonyEricssonZ800/R1Y Browser/SEMC-Browser/4.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", - "Opera/9.80 (Android; Opera Mini/7.5.33361/31.1543; U; en) Presto/2.8.119 Version/11.1010", - "Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0", - "Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0", - "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522 (KHTML, like Gecko) Safari/419.3", - "Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "HTC_Dream Mozilla/5.0 (Linux; U; Android 1.5; en-ca; Build/CUPCAKE) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1", - "Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-us; ADR6300 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Linux; U; Android 2.2; en-ca; GT-P1000M Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", - "Mozilla/5.0 (Android; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (Linux; U; Android 3.0.1; fr-fr; A500 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13", - "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "Mozilla/5.0 (Linux; U; Android 4.0.3; de-de; Galaxy S II Build/GRJ22) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", - "Opera/9.80 (Android 4.0.4; Linux; Opera Mobi/ADR-1205181138; U; pl) Presto/2.10.254 Version/12.00", - "Mozilla/5.0 (Android; Linux armv7l; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 Fennec/10.0.1", - "Mozilla/5.0 (Linux; Android 4.1.2; SHV-E250S Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.82 Mobile Safari/537.36", - "Mozilla/5.0 (Android 4.2; rv:19.0) Gecko/20121129 Firefox/19.0", - "Mozilla/5.0 (Linux; U; Android 4.3; en-us; sdk Build/MR1) AppleWebKit/536.23 (KHTML, like Gecko) Version/4.3 Mobile Safari/536.23", - "Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SAMSUNG-SM-T537A Build/KOT49H) AppleWebKit/537.36 (KHTML like Gecko) Chrome/35.0.1916.141 Safari/537.36", - "Mozilla/5.0 (Linux; Android 4.4.2; SM-T230NU Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.0.1; SCH-R970 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-T530NU Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Safari/537.36", - "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Safari/537.36 OPR/30.0.1856.93524", - "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0; LG-D850 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.97 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 6.0.1; SM-G900H Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; Nexus 9 Build/NRD90R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Safari/537.36", - "Mozilla/5.0 (Linux; Android 7.0; LG-H918 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36", - "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420 (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.200", - "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16", - "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10", - "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; da-dk) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8F190", - "MobileSafari/600.1.4 CFNetwork/711.1.12 Darwin/14.0.0", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3", - "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13C75 Safari/601.1", - "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5362a Safari/604.1", - "Mozilla/5.0 (X11; Linux i686 on x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (Maemo; Linux armv7l; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Fennec/2.0.1", - "Mozilla/5.0 (webOS/1.3; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; PalmSource/hspr-H102; Blazer/4.0) 16;320x320", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/014.002; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.4 3gpp-gba", - "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaX7-00/021.004; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.21 Mobile Safari/533.4 3gpp-gba", - "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE90-1/07.24.0.3; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413 UP.Link/6.2.3.18.0", - "Mozilla/5.0 (SymbianOS 9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344", - "Opera/9.80 (S60; SymbOS; Opera Mobi/499; U; ru) Presto/2.4.18 Version/10.00", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.3)", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) Sprint:PPC6800", - "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile6.0)", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6", - "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0)", - "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 530) like Gecko", - "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 630) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 635) like Gecko", - "Mozilla/5.0 (Windows NT 6.2; ARM; Trident/7.0; Touch; rv:11.0; WPDesktop; NOKIA; Lumia 920) like Geckoo", - "Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 920) like Gecko", - "Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 929) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537", - "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0", - "Mozilla/5.0 (Windows NT 10.0; ARM; Lumia 950 Dual SIM) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393", - "DoCoMo/2.0 SH901iC(c100;TB;W24H12)", - "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7 MG(Novarra-Vision/6.9)", - "Mozilla/4.0 (compatible; MSIE 6.0; j2me) ReqwirelessWeb/3.5", - "Vodafone/1.0/V802SE/SEJ001 Browser/SEMC-Browser/4.1", - "BlackBerry7520/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/5.0.3.3 UP.Link/5.1.2.12 (Google WAP Proxy/1.0)", - "Nokia6100/1.0 (04.01) Profile/MIDP-1.0 Configuration/CLDC-1.0", - "Nokia6630/1.0 (2.3.129) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1", - "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)", - "Baiduspider ( http://www.baidu.com/search/spider.htm)", - "Mozilla/5.0 (compatible; bingbot/2.0 http://www.bing.com/bingbot.htm)", - "Mozilla/5.0 (compatible; Exabot/3.0; http://www.exabot.com/go/robot)", - "FAST-WebCrawler/3.8 (crawler at trd dot overture dot com; http://www.alltheweb.com/help/webmaster/crawler)", - "AdsBot-Google ( http://www.google.com/adsbot.html)", - "Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)", - "Googlebot/2.1 ( http://www.googlebot.com/bot.html)", - "Googlebot-Image/1.0", - "Mediapartners-Google", - "DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", - "Mozilla/5.0 (iPhone; U; CPU iPhone OS) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", - "SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", - "Googlebot-News", - "Googlebot-Video/1.0", - "Mozilla/4.0 (compatible; GoogleToolbar 4.0.1019.5266-big; Windows XP 5.1; MSIE 6.0.2900.2180)", - "Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13", - "msnbot/1.0 ( http://search.msn.com/msnbot.htm)", - "msnbot/1.1 ( http://search.msn.com/msnbot.htm)", - "msnbot/0.11 ( http://search.msn.com/msnbot.htm)", - "msnbot-media/1.1 ( http://search.msn.com/msnbot.htm)", - "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)", - "Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)", - "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)", - "Mozilla/5.0 (compatible; YandexNews/4.0; +http://yandex.com/bots)", - "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)", - "Mozilla/5.0 (compatible; archive.org_bot; Wayback Machine Live Record; +http://archive.org/details/archive.org_bot)", - "Mozilla/5.0 (compatible; alexa site audit/1.0; +http://www.alexa.com/help/webmasters; )", - "EmailWolf 1.00", - "facebookexternalhit/1.1", - "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", - "Facebot", - "Gaisbot/3.0 (robot@gais.cs.ccu.edu.tw; http://gais.cs.ccu.edu.tw/robot.php)", - "grub-client-1.5.3; (grub-client-1.5.3; Crawl your own stuff with http://grub.org)", - "Gulper Web Bot 0.2.4 (www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/Link/GulperBot)", - "Screaming Frog SEO Spider/8.1", + "SuperBot/4.4.0.60 (Windows XP)", "TurnitinBot (https://turnitin.com/robot/crawlerinfo.html)", "Twitterbot/1.0", - "Xenu Link Sleuth/1.3.8", - "Mozilla/3.0 (compatible; NetPositive/2.1.1; BeOS)", - "Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.9a1) Gecko/20060702 SeaMonkey/1.5a", - "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Arora/0.11.0 Safari/533.3", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20100101 Firefox/10.0.12", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0", - "Mozilla/5.0 (OS/2; U; OS/2; en-US) AppleWebKit/533.3 (KHTML, like Gecko) QupZilla/1.3.1 Safari/533.3", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:10.0.12) Gecko/20130108 Firefox/10.0.12 SeaMonkey/2.7.2", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:24.0) Gecko/20100101 Firefox/24.0 SeaMonkey/2.21", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:31.0) Gecko/20100101 Firefox/31.0 SeaMonkey/2.28", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:38.0) Gecko/20100101 Firefox/38.0 SeaMonkey/2.35", - "Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101 Firefox/45.0 SeaMonkey/2.42.9esr", - "Adobe Application Manager 2.0", - "AndroidDownloadManager/5.1 (Linux; U; Android 5.1; Z820 Build/LMY47D)", - "Download Demon/3.5.0.11", - "Offline Explorer/2.5", - "SuperBot/4.4.0.60 (Windows XP)", - "WebCopier v4.6", + "UCWEB/8.8 (SymbianOS/9.2; U; en-US; NokiaE63) AppleWebKit/534.1 UCBrowser/8.8.0.245 Mobile", + "UCWEB/8.8 (iPhone; CPU OS_6; en-US)AppleWebKit/534.1 U3/3.0.0 Mobile", + "Uzbl (Webkit 1.3) (Linux i686 [i686])", + "Vodafone/1.0/V802SE/SEJ001 Browser/SEMC-Browser/4.1", + "W3C_Validator/1.305.2.12 libwww-perl/5.64", + "W3C_Validator/1.654", + "WDG_Validator/1.6.2", "Web Downloader/6.9", + "WebCopier v4.6", "WebZIP/3.5 (http://www.spidersoft.com)", + "Wget/1.12 (freebsd8.1)", "Wget/1.9 cvs-stable (Red Hat modified)", "Wget/1.9.1", - "Wget/1.12 (freebsd8.1)", - "Bloglines/3.1 (http://www.bloglines.com)", + "Xenu Link Sleuth/1.3.8", "everyfeed-spider/2.0 (http://www.everyfeed.com)", - "FeedFetcher-Google; ( http://www.google.com/feedfetcher.html)", - "Gregarius/0.5.2 ( http://devlog.gregarius.net/docs/ua)", - "Mozilla/5.0 (PLAYSTATION 3; 2.00)", - "Mozilla/5.0 (PLAYSTATION 3; 1.10)", - "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)", - "Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)", - "wii libnup/1.0", - "Java/1.6.0_13", - "libwww-perl/5.820", - "Peach/1.01 (Ubuntu 8.04 LTS; U; en)", - "Python-urllib/2.5", - "HTMLParser/1.6", - "Jigsaw/2.2.5 W3C_CSS_Validator_JFouffa/2.0", - "W3C_Validator/1.654", - "W3C_Validator/1.305.2.12 libwww-perl/5.64", - "P3P Validator", - "CSSCheck/1.2.2", - "WDG_Validator/1.6.2", + "facebookexternalhit/1.1", + "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", "facebookscraper/1.0( http://www.facebook.com/sharescraper_help.php)", "grub-client-1.5.3; (grub-client-1.5.3; Crawl your own stuff with http://grub.org)", "iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)", - "Microsoft URL Control - 6.00.8862", - "Roku/DVP-4.1 (024.01E01250A)", - "Mozilla/5.0 (SMART-TV; X11; Linux armv7l) AppleWebkit/537.42 (KHTML, like Gecko) Chromium/25.0.1349.2 Chrome/25.0.1349.2 Safari/537.42", - "SearchExpress", + "iTunes/9.0.2 (Windows; N)", + "iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)", + "libwww-perl/5.820", + "msnbot-media/1.1 ( http://search.msn.com/msnbot.htm)", + "msnbot/0.11 ( http://search.msn.com/msnbot.htm)", + "msnbot/1.0 ( http://search.msn.com/msnbot.htm)", + "msnbot/1.1 ( http://search.msn.com/msnbot.htm)", + "nook browser/1.0", + "portalmmm/2.0 N410i(c20;TB)", + "w3m/0.5.1", + "wii libnup/1.0", } ) diff --git a/vendor/github.com/corpix/uarand/useragents.mk b/vendor/github.com/corpix/uarand/useragents.mk deleted file mode 100644 index 2e2e457bd..000000000 --- a/vendor/github.com/corpix/uarand/useragents.mk +++ /dev/null @@ -1,10 +0,0 @@ -.PHONY: useragents.go -useragents.go: - curl -Ls -H'User-Agent: gotohellwithyour403' \ - http://techpatterns.com/downloads/firefox/useragentswitcher.xml \ - | ./scripts/extract-user-agents \ - | ./scripts/generate-useragents-go $(name) \ - > $@ - go fmt $@ - -dependencies:: useragents.go diff --git a/vendor/github.com/dghubble/sling/.travis.yml b/vendor/github.com/dghubble/sling/.travis.yml deleted file mode 100644 index 909175016..000000000 --- a/vendor/github.com/dghubble/sling/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: go -go: - - 1.9 - - "1.10.x" - - "1.11.x" - - tip -install: - - go get golang.org/x/lint/golint - - go get -v -t . -script: - - ./test diff --git a/vendor/github.com/dghubble/sling/CHANGES.md b/vendor/github.com/dghubble/sling/CHANGES.md index f867e0d7a..3ba8622b6 100644 --- a/vendor/github.com/dghubble/sling/CHANGES.md +++ b/vendor/github.com/dghubble/sling/CHANGES.md @@ -4,6 +4,24 @@ Notable changes between releases. ## Latest +## v1.4.2 + +* Update Go module dependencies + +## v1.4.1 + +* Update minimum Go version to v1.18 ([#76](https://github.com/dghubble/sling/pull/76)) + +## v1.4.0 + +* `Do` reads Body to reuse HTTP/1.x "keep-alive" TCP connections ([#59](https://github.com/dghubble/sling/pull/59)) +* `Receive` skips decoding if status is 204 (no content) ([#63](https://github.com/dghubble/sling/pull/63)) + +## v1.3.0 + +* Add Sling `ResponseDecoder` setter for receiving responses with a custom `ResponseDecoder` ([#49](https://github.com/dghubble/sling/pull/49)) +* Add Go module support (i.e. `go.mod`). Exclude `examples` (multi-module). ([#52](https://github.com/dghubble/sling/pull/52)) + ## v1.2.0 * Add `Connect`, `Options`, and `Trace` HTTP methods ([c51967](https://github.com/dghubble/sling/commit/c519674860ff275e0ceb12caf5d87b31765c4e71)) diff --git a/vendor/github.com/dghubble/sling/Makefile b/vendor/github.com/dghubble/sling/Makefile new file mode 100644 index 000000000..fb990de61 --- /dev/null +++ b/vendor/github.com/dghubble/sling/Makefile @@ -0,0 +1,15 @@ +.PHONY: all +all: test vet fmt + +.PHONY: test +test: + @go test . -cover + +.PHONY: vet +vet: + @go vet -all . + +.PHONY: fmt +fmt: + @test -z $$(go fmt ./...) + diff --git a/vendor/github.com/dghubble/sling/README.md b/vendor/github.com/dghubble/sling/README.md index ff793c60e..e790161c5 100644 --- a/vendor/github.com/dghubble/sling/README.md +++ b/vendor/github.com/dghubble/sling/README.md @@ -1,4 +1,9 @@ -# Sling [![Build Status](https://travis-ci.org/dghubble/sling.svg?branch=master)](https://travis-ci.org/dghubble/sling) [![GoDoc](https://godoc.org/github.com/dghubble/sling?status.svg)](https://godoc.org/github.com/dghubble/sling) +# Sling +[![GoDoc](https://pkg.go.dev/badge/github.com/dghubble/sling.svg)](https://pkg.go.dev/github.com/dghubble/sling) +[![Workflow](https://github.com/dghubble/sling/actions/workflows/test.yaml/badge.svg)](https://github.com/dghubble/sling/actions/workflows/test.yaml?query=branch%3Amain) +[![Sponsors](https://img.shields.io/github/sponsors/dghubble?logo=github)](https://github.com/sponsors/dghubble) +[![Mastodon](https://img.shields.io/badge/follow-news-6364ff?logo=mastodon)](https://fosstodon.org/@typhoon) + Sling is a Go HTTP client library for creating and sending API requests. @@ -272,11 +277,10 @@ func (s *IssueService) ListByRepo(owner, repo string, params *IssueListParams) ( * GoSquared [drinkin/go-gosquared](https://github.com/drinkin/go-gosquared) * Kala [ajvb/kala](https://github.com/ajvb/kala) * Parse [fergstar/go-parse](https://github.com/fergstar/go-parse) -* Rdio [apriendeau/shares](https://github.com/apriendeau/shares) * Swagger Generator [swagger-api/swagger-codegen](https://github.com/swagger-api/swagger-codegen) * Twitter [dghubble/go-twitter](https://github.com/dghubble/go-twitter) -* Hacker News [mirceamironenco/go-hackernews](https://github.com/mirceamironenco/go-hackernews) * Stacksmith [jesustinoco/go-smith](https://github.com/jesustinoco/go-smith) +* Spotify [omegastreamtv/Spotify](https://github.com/omegastreamtv/Spotify) Create a Pull Request to add a link to your own API. diff --git a/vendor/github.com/dghubble/sling/doc.go b/vendor/github.com/dghubble/sling/doc.go index dd2efb7e3..f48836c17 100644 --- a/vendor/github.com/dghubble/sling/doc.go +++ b/vendor/github.com/dghubble/sling/doc.go @@ -5,7 +5,7 @@ Slings store HTTP Request properties to simplify sending requests and decoding responses. Check the examples to learn how to compose a Sling into your API client. -Usage +# Usage Use a Sling to set path, method, header, query, or body properties and create an http.Request. @@ -18,7 +18,7 @@ http.Request. req, err := sling.New().Get("https://example.com").QueryStruct(params).Request() client.Do(req) -Path +# Path Use Path to set or extend the URL for created Requests. Extension means the path will be resolved relative to the existing URL. @@ -31,14 +31,14 @@ except they set the HTTP method too. req, err := sling.New().Post("http://upload.com/gophers") -Headers +# Headers Add or Set headers for requests created by a Sling. s := sling.New().Base(baseUrl).Set("User-Agent", "Gophergram API Client") req, err := s.New().Get("gophergram/list").Request() -QueryStruct +# QueryStruct Define url parameter structs (https://godoc.org/github.com/google/go-querystring/query). Use QueryStruct to encode a struct as query parameters on requests. @@ -59,7 +59,7 @@ Use QueryStruct to encode a struct as query parameters on requests. params := &IssueParams{Sort: "updated", State: "open"} req, err := githubBase.New().Get(path).QueryStruct(params).Request() -Json Body +# Json Body Define JSON tagged structs (https://golang.org/pkg/encoding/json/). Use BodyJSON to JSON encode a struct as the Body on requests. @@ -83,7 +83,7 @@ Use BodyJSON to JSON encode a struct as the Body on requests. Requests will include an "application/json" Content-Type header. -Form Body +# Form Body Define url tagged structs (https://godoc.org/github.com/google/go-querystring/query). Use BodyForm to form url encode a struct as the Body on requests. @@ -100,7 +100,7 @@ Use BodyForm to form url encode a struct as the Body on requests. Requests will include an "application/x-www-form-urlencoded" Content-Type header. -Plain Body +# Plain Body Use Body to set a plain io.Reader on requests created by a Sling. @@ -109,7 +109,7 @@ Use Body to set a plain io.Reader on requests created by a Sling. Set a content type header, if desired (e.g. Set("Content-Type", "text/plain")). -Extend a Sling +# Extend a Sling Each Sling generates an http.Request (say with some path and query params) each time Request() is called, based on its state. When creating @@ -137,7 +137,7 @@ is undesired. Recap: If you wish to extend a Sling, create a new child copy with New(). -Receive +# Receive Define a JSON struct to decode a type from 2XX success responses. Use ReceiveSuccess(successV interface{}) to send a new Request and decode the diff --git a/vendor/github.com/dghubble/sling/response.go b/vendor/github.com/dghubble/sling/response.go new file mode 100644 index 000000000..c918ed138 --- /dev/null +++ b/vendor/github.com/dghubble/sling/response.go @@ -0,0 +1,22 @@ +package sling + +import ( + "encoding/json" + "net/http" +) + +// ResponseDecoder decodes http responses into struct values. +type ResponseDecoder interface { + // Decode decodes the response into the value pointed to by v. + Decode(resp *http.Response, v interface{}) error +} + +// jsonDecoder decodes http response JSON into a JSON-tagged struct value. +type jsonDecoder struct { +} + +// Decode decodes the Response Body into the value pointed to by v. +// Caller must provide a non-nil v and close the resp.Body. +func (d jsonDecoder) Decode(resp *http.Response, v interface{}) error { + return json.NewDecoder(resp.Body).Decode(v) +} diff --git a/vendor/github.com/dghubble/sling/sling.go b/vendor/github.com/dghubble/sling/sling.go index c75fd678a..5492ef2e8 100644 --- a/vendor/github.com/dghubble/sling/sling.go +++ b/vendor/github.com/dghubble/sling/sling.go @@ -2,7 +2,6 @@ package sling import ( "encoding/base64" - "encoding/json" "io" "net/http" "net/url" @@ -37,24 +36,27 @@ type Sling struct { queryStructs []interface{} // body provider bodyProvider BodyProvider + // response decoder + responseDecoder ResponseDecoder } // New returns a new Sling with an http DefaultClient. func New() *Sling { return &Sling{ - httpClient: http.DefaultClient, - method: "GET", - header: make(http.Header), - queryStructs: make([]interface{}, 0), + httpClient: http.DefaultClient, + method: "GET", + header: make(http.Header), + queryStructs: make([]interface{}, 0), + responseDecoder: jsonDecoder{}, } } // New returns a copy of a Sling for creating a new Sling with properties // from a parent Sling. For example, // -// parentSling := sling.New().Client(client).Base("https://api.io/") -// fooSling := parentSling.New().Get("foo/") -// barSling := parentSling.New().Get("bar/") +// parentSling := sling.New().Client(client).Base("https://api.io/") +// fooSling := parentSling.New().Get("foo/") +// barSling := parentSling.New().Get("bar/") // // fooSling and barSling will both use the same client, but send requests to // https://api.io/foo/ and https://api.io/bar/ respectively. @@ -68,12 +70,13 @@ func (s *Sling) New() *Sling { headerCopy[k] = v } return &Sling{ - httpClient: s.httpClient, - method: s.method, - rawURL: s.rawURL, - header: headerCopy, - queryStructs: append([]interface{}{}, s.queryStructs...), - bodyProvider: s.bodyProvider, + httpClient: s.httpClient, + method: s.method, + rawURL: s.rawURL, + header: headerCopy, + queryStructs: append([]interface{}{}, s.queryStructs...), + bodyProvider: s.bodyProvider, + responseDecoder: s.responseDecoder, } } @@ -336,6 +339,15 @@ func addHeaders(req *http.Request, header http.Header) { // Sending +// ResponseDecoder sets the Sling's response decoder. +func (s *Sling) ResponseDecoder(decoder ResponseDecoder) *Sling { + if decoder == nil { + return s + } + s.responseDecoder = decoder + return s +} + // ReceiveSuccess creates a new HTTP request and returns the response. Success // responses (2XX) are JSON decoded into the value pointed to by successV. // Any error creating the request, sending it, or decoding a 2XX response @@ -347,8 +359,9 @@ func (s *Sling) ReceiveSuccess(successV interface{}) (*http.Response, error) { // Receive creates a new HTTP request and returns the response. Success // responses (2XX) are JSON decoded into the value pointed to by successV and // other responses are JSON decoded into the value pointed to by failureV. -// Any error creating the request, sending it, or decoding the response is -// returned. +// If the status code of response is 204(no content) or the Content-Lenght is 0, +// decoding is skipped. Any error creating the request, sending it, or decoding +// the response is returned. // Receive is shorthand for calling Request and Do. func (s *Sling) Receive(successV, failureV interface{}) (*http.Response, error) { req, err := s.Request() @@ -361,7 +374,9 @@ func (s *Sling) Receive(successV, failureV interface{}) (*http.Response, error) // Do sends an HTTP request and returns the response. Success responses (2XX) // are JSON decoded into the value pointed to by successV and other responses // are JSON decoded into the value pointed to by failureV. -// Any error sending the request or decoding the response is returned. +// If the status code of response is 204(no content) or the Content-Length is 0, +// decoding is skipped. Any error sending the request or decoding the response +// is returned. func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Response, error) { resp, err := s.httpClient.Do(req) if err != nil { @@ -370,14 +385,20 @@ func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Res // when err is nil, resp contains a non-nil resp.Body which must be closed defer resp.Body.Close() - // Don't try to decode on 204s - if resp.StatusCode == 204 { + // The default HTTP client's Transport may not + // reuse HTTP/1.x "keep-alive" TCP connections if the Body is + // not read to completion and closed. + // See: https://golang.org/pkg/net/http/#Response + defer io.Copy(io.Discard, resp.Body) + + // Don't try to decode on 204s or Content-Length is 0 + if resp.StatusCode == http.StatusNoContent || resp.ContentLength == 0 { return resp, nil } // Decode from json if successV != nil || failureV != nil { - err = decodeResponseJSON(resp, successV, failureV) + err = decodeResponse(resp, s.responseDecoder, successV, failureV) } return resp, err } @@ -387,22 +408,15 @@ func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Res // otherwise. If the successV or failureV argument to decode into is nil, // decoding is skipped. // Caller is responsible for closing the resp.Body. -func decodeResponseJSON(resp *http.Response, successV, failureV interface{}) error { +func decodeResponse(resp *http.Response, decoder ResponseDecoder, successV, failureV interface{}) error { if code := resp.StatusCode; 200 <= code && code <= 299 { if successV != nil { - return decodeResponseBodyJSON(resp, successV) + return decoder.Decode(resp, successV) } } else { if failureV != nil { - return decodeResponseBodyJSON(resp, failureV) + return decoder.Decode(resp, failureV) } } return nil } - -// decodeResponseBodyJSON JSON decodes a Response Body into the value pointed -// to by v. -// Caller must provide a non-nil v and close the resp.Body. -func decodeResponseBodyJSON(resp *http.Response, v interface{}) error { - return json.NewDecoder(resp.Body).Decode(v) -} diff --git a/vendor/github.com/dghubble/sling/test b/vendor/github.com/dghubble/sling/test deleted file mode 100644 index fa845c625..000000000 --- a/vendor/github.com/dghubble/sling/test +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e - -PKGS=$(go list ./... | grep -v /examples) -FORMATTABLE="$(find . -maxdepth 1 -type d)" -LINTABLE=$(go list ./...) - -go test $PKGS -cover -go vet $PKGS - -echo "Checking gofmt..." -fmtRes=$(gofmt -l $FORMATTABLE) -if [ -n "${fmtRes}" ]; then - echo -e "gofmt checking failed:\n${fmtRes}" - exit 2 -fi - -echo "Checking golint..." -lintRes=$(echo $LINTABLE | xargs -n 1 golint) -if [ -n "${lintRes}" ]; then - echo -e "golint checking failed:\n${lintRes}" - exit 2 -fi \ No newline at end of file diff --git a/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml new file mode 100644 index 000000000..f4e7dbf37 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml @@ -0,0 +1,14 @@ +freebsd_task: + name: 'FreeBSD' + freebsd_instance: + image_family: freebsd-14-1 + install_script: + - pkg update -f + - pkg install -y go + test_script: + # run tests as user "cirrus" instead of root + - pw useradd cirrus -m + - chown -R cirrus:cirrus . + - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - FSNOTIFY_DEBUG=1 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./... diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes deleted file mode 100644 index 32f1001be..000000000 --- a/vendor/github.com/fsnotify/fsnotify/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -go.sum linguist-generated diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore index 4cd0cbaf4..daea9dd6d 100644 --- a/vendor/github.com/fsnotify/fsnotify/.gitignore +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -1,6 +1,10 @@ -# Setup a Global .gitignore for OS and editor generated files: -# https://help.github.com/articles/ignoring-files -# git config --global core.excludesfile ~/.gitignore_global +# go test -c output +*.test +*.test.exe -.vagrant -*.sublime-project +# Output of go build ./cmd/fsnotify +/fsnotify +/fsnotify.exe + +/test/kqueue +/test/a.out diff --git a/vendor/github.com/fsnotify/fsnotify/AUTHORS b/vendor/github.com/fsnotify/fsnotify/AUTHORS deleted file mode 100644 index 6cbabe5ef..000000000 --- a/vendor/github.com/fsnotify/fsnotify/AUTHORS +++ /dev/null @@ -1,62 +0,0 @@ -# Names should be added to this file as -# Name or Organization -# The email address is not required for organizations. - -# You can update this list using the following command: -# -# $ (head -n10 AUTHORS && git shortlog -se | sed -E 's/^\s+[0-9]+\t//') | tee AUTHORS - -# Please keep the list sorted. - -Aaron L -Adrien Bustany -Alexey Kazakov -Amit Krishnan -Anmol Sethi -Bjørn Erik Pedersen -Brian Goff -Bruno Bigras -Caleb Spare -Case Nelson -Chris Howey -Christoffer Buchholz -Daniel Wagner-Hall -Dave Cheney -Eric Lin -Evan Phoenix -Francisco Souza -Gautam Dey -Hari haran -Ichinose Shogo -Johannes Ebke -John C Barstow -Kelvin Fo -Ken-ichirou MATSUZAWA -Matt Layher -Matthias Stone -Nathan Youngman -Nickolai Zeldovich -Oliver Bristow -Patrick -Paul Hammond -Pawel Knap -Pieter Droogendijk -Pratik Shinde -Pursuit92 -Riku Voipio -Rob Figueiredo -Rodrigo Chiossi -Slawek Ligus -Soge Zhang -Tiffany Jernigan -Tilak Sharma -Tobias Klauser -Tom Payne -Travis Cline -Tudor Golubenco -Vahe Khachikyan -Yukang -bronze1man -debrando -henrikedwards -铁哥 diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index cc01c08f5..fa854785d 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,11 +1,199 @@ # Changelog -All notable changes to this project will be documented in this file. +1.8.0 2023-10-31 +---------------- -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). +### Additions -## [Unreleased] +- all: add `FSNOTIFY_DEBUG` to print debug logs to stderr ([#619]) + +### Changes and fixes + +- windows: fix behaviour of `WatchList()` to be consistent with other platforms ([#610]) + +- kqueue: ignore events with Ident=0 ([#590]) + +- kqueue: set O_CLOEXEC to prevent passing file descriptors to children ([#617]) + +- kqueue: emit events as "/path/dir/file" instead of "path/link/file" when watching a symlink ([#625]) + +- inotify: don't send event for IN_DELETE_SELF when also watching the parent ([#620]) + +- inotify: fix panic when calling Remove() in a goroutine ([#650]) + +- fen: allow watching subdirectories of watched directories ([#621]) + +[#590]: https://github.com/fsnotify/fsnotify/pull/590 +[#610]: https://github.com/fsnotify/fsnotify/pull/610 +[#617]: https://github.com/fsnotify/fsnotify/pull/617 +[#619]: https://github.com/fsnotify/fsnotify/pull/619 +[#620]: https://github.com/fsnotify/fsnotify/pull/620 +[#621]: https://github.com/fsnotify/fsnotify/pull/621 +[#625]: https://github.com/fsnotify/fsnotify/pull/625 +[#650]: https://github.com/fsnotify/fsnotify/pull/650 + +1.7.0 - 2023-10-22 +------------------ +This version of fsnotify needs Go 1.17. + +### Additions + +- illumos: add FEN backend to support illumos and Solaris. ([#371]) + +- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful + in cases where you can't control the kernel buffer and receive a large number + of events in bursts. ([#550], [#572]) + +- all: add `AddWith()`, which is identical to `Add()` but allows passing + options. ([#521]) + +- windows: allow setting the ReadDirectoryChangesW() buffer size with + `fsnotify.WithBufferSize()`; the default of 64K is the highest value that + works on all platforms and is enough for most purposes, but in some cases a + highest buffer is needed. ([#521]) + +### Changes and fixes + +- inotify: remove watcher if a watched path is renamed ([#518]) + + After a rename the reported name wasn't updated, or even an empty string. + Inotify doesn't provide any good facilities to update it, so just remove the + watcher. This is already how it worked on kqueue and FEN. + + On Windows this does work, and remains working. + +- windows: don't listen for file attribute changes ([#520]) + + File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API, + with no way to see if they're a file write or attribute change, so would show + up as a fsnotify.Write event. This is never useful, and could result in many + spurious Write events. + +- windows: return `ErrEventOverflow` if the buffer is full ([#525]) + + Before it would merely return "short read", making it hard to detect this + error. + +- kqueue: make sure events for all files are delivered properly when removing a + watched directory ([#526]) + + Previously they would get sent with `""` (empty string) or `"."` as the path + name. + +- kqueue: don't emit spurious Create events for symbolic links ([#524]) + + The link would get resolved but kqueue would "forget" it already saw the link + itself, resulting on a Create for every Write event for the directory. + +- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516]) + +- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in + `backend_other.go`, making it easier to use on unsupported platforms such as + WASM, AIX, etc. ([#528]) + +- other: use the `backend_other.go` no-op if the `appengine` build tag is set; + Google AppEngine forbids usage of the unsafe package so the inotify backend + won't compile there. + +[#371]: https://github.com/fsnotify/fsnotify/pull/371 +[#516]: https://github.com/fsnotify/fsnotify/pull/516 +[#518]: https://github.com/fsnotify/fsnotify/pull/518 +[#520]: https://github.com/fsnotify/fsnotify/pull/520 +[#521]: https://github.com/fsnotify/fsnotify/pull/521 +[#524]: https://github.com/fsnotify/fsnotify/pull/524 +[#525]: https://github.com/fsnotify/fsnotify/pull/525 +[#526]: https://github.com/fsnotify/fsnotify/pull/526 +[#528]: https://github.com/fsnotify/fsnotify/pull/528 +[#537]: https://github.com/fsnotify/fsnotify/pull/537 +[#550]: https://github.com/fsnotify/fsnotify/pull/550 +[#572]: https://github.com/fsnotify/fsnotify/pull/572 + +1.6.0 - 2022-10-13 +------------------ +This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1, +but not documented). It also increases the minimum Linux version to 2.6.32. + +### Additions + +- all: add `Event.Has()` and `Op.Has()` ([#477]) + + This makes checking events a lot easier; for example: + + if event.Op&Write == Write && !(event.Op&Remove == Remove) { + } + + Becomes: + + if event.Has(Write) && !event.Has(Remove) { + } + +- all: add cmd/fsnotify ([#463]) + + A command-line utility for testing and some examples. + +### Changes and fixes + +- inotify: don't ignore events for files that don't exist ([#260], [#470]) + + Previously the inotify watcher would call `os.Lstat()` to check if a file + still exists before emitting events. + + This was inconsistent with other platforms and resulted in inconsistent event + reporting (e.g. when a file is quickly removed and re-created), and generally + a source of confusion. It was added in 2013 to fix a memory leak that no + longer exists. + +- all: return `ErrNonExistentWatch` when `Remove()` is called on a path that's + not watched ([#460]) + +- inotify: replace epoll() with non-blocking inotify ([#434]) + + Non-blocking inotify was not generally available at the time this library was + written in 2014, but now it is. As a result, the minimum Linux version is + bumped from 2.6.27 to 2.6.32. This hugely simplifies the code and is faster. + +- kqueue: don't check for events every 100ms ([#480]) + + The watcher would wake up every 100ms, even when there was nothing to do. Now + it waits until there is something to do. + +- macos: retry opening files on EINTR ([#475]) + +- kqueue: skip unreadable files ([#479]) + + kqueue requires a file descriptor for every file in a directory; this would + fail if a file was unreadable by the current user. Now these files are simply + skipped. + +- windows: fix renaming a watched directory if the parent is also watched ([#370]) + +- windows: increase buffer size from 4K to 64K ([#485]) + +- windows: close file handle on Remove() ([#288]) + +- kqueue: put pathname in the error if watching a file fails ([#471]) + +- inotify, windows: calling Close() more than once could race ([#465]) + +- kqueue: improve Close() performance ([#233]) + +- all: various documentation additions and clarifications. + +[#233]: https://github.com/fsnotify/fsnotify/pull/233 +[#260]: https://github.com/fsnotify/fsnotify/pull/260 +[#288]: https://github.com/fsnotify/fsnotify/pull/288 +[#370]: https://github.com/fsnotify/fsnotify/pull/370 +[#434]: https://github.com/fsnotify/fsnotify/pull/434 +[#460]: https://github.com/fsnotify/fsnotify/pull/460 +[#463]: https://github.com/fsnotify/fsnotify/pull/463 +[#465]: https://github.com/fsnotify/fsnotify/pull/465 +[#470]: https://github.com/fsnotify/fsnotify/pull/470 +[#471]: https://github.com/fsnotify/fsnotify/pull/471 +[#475]: https://github.com/fsnotify/fsnotify/pull/475 +[#477]: https://github.com/fsnotify/fsnotify/pull/477 +[#479]: https://github.com/fsnotify/fsnotify/pull/479 +[#480]: https://github.com/fsnotify/fsnotify/pull/480 +[#485]: https://github.com/fsnotify/fsnotify/pull/485 ## [1.5.4] - 2022-04-25 @@ -40,6 +228,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#385](https://github.com/fsnotify/fsnotify/pull/385) * Go 1.14+: Fix unsafe pointer conversion [#325](https://github.com/fsnotify/fsnotify/pull/325) +## [1.4.9] - 2020-03-11 + +* Move example usage to the readme #329. This may resolve #328. + +## [1.4.8] - 2020-03-10 + +* CI: test more go versions (@nathany 1d13583d846ea9d66dcabbfefbfb9d8e6fb05216) +* Tests: Queued inotify events could have been read by the test before max_queued_events was hit (@matthias-stone #265) +* Tests: t.Fatalf -> t.Errorf in go routines (@gdey #266) +* CI: Less verbosity (@nathany #267) +* Tests: Darwin: Exchangedata is deprecated on 10.13 (@nathany #267) +* Tests: Check if channels are closed in the example (@alexeykazakov #244) +* CI: Only run golint on latest version of go and fix issues (@cpuguy83 #284) +* CI: Add windows to travis matrix (@cpuguy83 #284) +* Docs: Remover appveyor badge (@nathany 11844c0959f6fff69ba325d097fce35bd85a8e93) +* Linux: create epoll and pipe fds with close-on-exec (@JohannesEbke #219) +* Linux: open files with close-on-exec (@linxiulei #273) +* Docs: Plan to support fanotify (@nathany ab058b44498e8b7566a799372a39d150d9ea0119 ) +* Project: Add go.mod (@nathany #309) +* Project: Revise editor config (@nathany #309) +* Project: Update copyright for 2019 (@nathany #309) +* CI: Drop go1.8 from CI matrix (@nathany #309) +* Docs: Updating the FAQ section for supportability with NFS & FUSE filesystems (@Pratik32 4bf2d1fec78374803a39307bfb8d340688f4f28e ) + ## [1.4.7] - 2018-01-09 * BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md index 8a642563d..e4ac2a2ff 100644 --- a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md +++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -1,60 +1,144 @@ -# Contributing +Thank you for your interest in contributing to fsnotify! We try to review and +merge PRs in a reasonable timeframe, but please be aware that: -## Issues +- To avoid "wasted" work, please discuss changes on the issue tracker first. You + can just send PRs, but they may end up being rejected for one reason or the + other. -* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues). -* Please indicate the platform you are using fsnotify on. -* A code example to reproduce the problem is appreciated. +- fsnotify is a cross-platform library, and changes must work reasonably well on + all supported platforms. -## Pull Requests +- Changes will need to be compatible; old code should still compile, and the + runtime behaviour can't change in ways that are likely to lead to problems for + users. -### Contributor License Agreement +Testing +------- +Just `go test ./...` runs all the tests; the CI runs this on all supported +platforms. Testing different platforms locally can be done with something like +[goon] or [Vagrant], but this isn't super-easy to set up at the moment. -fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). +Use the `-short` flag to make the "stress test" run faster. -Please indicate that you have signed the CLA in your pull request. +Writing new tests +----------------- +Scripts in the testdata directory allow creating test cases in a "shell-like" +syntax. The basic format is: -### How fsnotify is Developed + script -* Development is done on feature branches. -* Tests are run on BSD, Linux, macOS and Windows. -* Pull requests are reviewed and [applied to master][am] using [hub][]. - * Maintainers may modify or squash commits rather than asking contributors to. -* To issue a new release, the maintainers will: - * Update the CHANGELOG - * Tag a version, which will become available through gopkg.in. - -### How to Fork + Output: + desired output -For smooth sailing, always use the original import path. Installing with `go get` makes this easy. +For example: -1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Ensure everything works and the tests pass (see below) -4. Commit your changes (`git commit -am 'Add some feature'`) + # Create a new empty file with some data. + watch / + echo data >/file -Contribute upstream: + Output: + create /file + write /file -1. Fork fsnotify on GitHub -2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) -3. Push to the branch (`git push fork my-new-feature`) -4. Create a new Pull Request on GitHub +Just create a new file to add a new test; select which tests to run with +`-run TestScript/[path]`. -This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/). +script +------ +The script is a "shell-like" script: -### Testing + cmd arg arg -fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Windows. +Comments are supported with `#`: -Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. + # Comment + cmd arg arg # Comment -### Maintainers +All operations are done in a temp directory; a path like "/foo" is rewritten to +"/tmp/TestFoo/foo". -Help maintaining fsnotify is welcome. To be a maintainer: +Arguments can be quoted with `"` or `'`; there are no escapes and they're +functionally identical right now, but this may change in the future, so best to +assume shell-like rules. -* Submit a pull request and sign the CLA as above. -* You must be able to run the test suite on Mac, Windows, Linux and BSD. + touch "/file with spaces" -All code changes should be internal pull requests. +End-of-line escapes with `\` are not supported. -Releases are tagged using [Semantic Versioning](http://semver.org/). +### Supported commands + + watch path [ops] # Watch the path, reporting events for it. Nothing is + # watched by default. Optionally a list of ops can be + # given, as with AddWith(path, WithOps(...)). + unwatch path # Stop watching the path. + watchlist n # Assert watchlist length. + + stop # Stop running the script; for debugging. + debug [yes/no] # Enable/disable FSNOTIFY_DEBUG (tests are run in + parallel by default, so -parallel=1 is probably a good + idea). + + touch path + mkdir [-p] dir + ln -s target link # Only ln -s supported. + mkfifo path + mknod dev path + mv src dst + rm [-r] path + chmod mode path # Octal only + sleep time-in-ms + + cat path # Read path (does nothing with the data; just reads it). + echo str >>path # Append "str" to "path". + echo str >path # Truncate "path" and write "str". + + require reason # Skip the test if "reason" is true; "skip" and + skip reason # "require" behave identical; it supports both for + # readability. Possible reasons are: + # + # always Always skip this test. + # symlink Symlinks are supported (requires admin + # permissions on Windows). + # mkfifo Platform doesn't support FIFO named sockets. + # mknod Platform doesn't support device nodes. + + +output +------ +After `Output:` the desired output is given; this is indented by convention, but +that's not required. + +The format of that is: + + # Comment + event path # Comment + + system: + event path + system2: + event path + +Every event is one line, and any whitespace between the event and path are +ignored. The path can optionally be surrounded in ". Anything after a "#" is +ignored. + +Platform-specific tests can be added after GOOS; for example: + + watch / + touch /file + + Output: + # Tested if nothing else matches + create /file + + # Windows-specific test. + windows: + write /file + +You can specify multiple platforms with a comma (e.g. "windows, linux:"). +"kqueue" is a shortcut for all kqueue systems (BSD, macOS). + + +[goon]: https://github.com/arp242/goon +[Vagrant]: https://www.vagrantup.com/ +[integration_test.go]: /integration_test.go diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE index e180c8fb0..fb03ade75 100644 --- a/vendor/github.com/fsnotify/fsnotify/LICENSE +++ b/vendor/github.com/fsnotify/fsnotify/LICENSE @@ -1,28 +1,25 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012-2019 fsnotify Authors. All rights reserved. +Copyright © 2012 The Go Authors. All rights reserved. +Copyright © fsnotify Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index 0731c5ef8..e480733d1 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -1,120 +1,184 @@ -# File system notifications for Go +fsnotify is a Go library to provide cross-platform filesystem notifications on +Windows, Linux, macOS, BSD, and illumos. -[![Go Reference](https://pkg.go.dev/badge/github.com/fsnotify/fsnotify.svg)](https://pkg.go.dev/github.com/fsnotify/fsnotify) [![Go Report Card](https://goreportcard.com/badge/github.com/fsnotify/fsnotify)](https://goreportcard.com/report/github.com/fsnotify/fsnotify) [![Maintainers Wanted](https://img.shields.io/badge/maintainers-wanted-red.svg)](https://github.com/fsnotify/fsnotify/issues/413) +Go 1.17 or newer is required; the full documentation is at +https://pkg.go.dev/github.com/fsnotify/fsnotify -fsnotify utilizes [`golang.org/x/sys`](https://pkg.go.dev/golang.org/x/sys) rather than [`syscall`](https://pkg.go.dev/syscall) from the standard library. +--- -Cross platform: Windows, Linux, BSD and macOS. +Platform support: -| Adapter | OS | Status | -| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| inotify | Linux 2.6.27 or later, Android\* | Supported | -| kqueue | BSD, macOS, iOS\* | Supported | -| ReadDirectoryChangesW | Windows | Supported | -| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | -| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) | -| fanotify | Linux 2.6.37+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) | -| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | -| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | +| Backend | OS | Status | +| :-------------------- | :--------- | :------------------------------------------------------------------------ | +| inotify | Linux | Supported | +| kqueue | BSD, macOS | Supported | +| ReadDirectoryChangesW | Windows | Supported | +| FEN | illumos | Supported | +| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) | +| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment | +| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] | +| USN Journals | Windows | [Needs support in x/sys/windows][usn] | +| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) | -\* Android and iOS are untested. +Linux and illumos should include Android and Solaris, but these are currently +untested. -Please see [the documentation](https://pkg.go.dev/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information. +[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120 +[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847 +[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129 -## API stability - -fsnotify is a fork of [howeyc/fsnotify](https://github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA). - -All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). - -## Usage +Usage +----- +A basic example: ```go package main import ( - "log" + "log" - "github.com/fsnotify/fsnotify" + "github.com/fsnotify/fsnotify" ) func main() { - watcher, err := fsnotify.NewWatcher() - if err != nil { - log.Fatal(err) - } - defer watcher.Close() - - done := make(chan bool) - go func() { - for { - select { - case event, ok := <-watcher.Events: - if !ok { - return - } - log.Println("event:", event) - if event.Op&fsnotify.Write == fsnotify.Write { - log.Println("modified file:", event.Name) - } - case err, ok := <-watcher.Errors: - if !ok { - return - } - log.Println("error:", err) - } - } - }() - - err = watcher.Add("/tmp/foo") - if err != nil { - log.Fatal(err) - } - <-done + // Create new watcher. + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + // Start listening for events. + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + log.Println("event:", event) + if event.Has(fsnotify.Write) { + log.Println("modified file:", event.Name) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Println("error:", err) + } + } + }() + + // Add a path. + err = watcher.Add("/tmp") + if err != nil { + log.Fatal(err) + } + + // Block main goroutine forever. + <-make(chan struct{}) } ``` -## Contributing +Some more examples can be found in [cmd/fsnotify](cmd/fsnotify), which can be +run with: + + % go run ./cmd/fsnotify -Please refer to [CONTRIBUTING][] before opening an issue or pull request. +Further detailed documentation can be found in godoc: +https://pkg.go.dev/github.com/fsnotify/fsnotify -## FAQ +FAQ +--- +### Will a file still be watched when it's moved to another directory? +No, not unless you are watching the location it was moved to. -**When a file is moved to another directory is it still being watched?** +### Are subdirectories watched? +No, you must add watches for any directory you want to watch (a recursive +watcher is on the roadmap: [#18]). -No (it shouldn't be, unless you are watching where it was moved to). +[#18]: https://github.com/fsnotify/fsnotify/issues/18 -**When I watch a directory, are all subdirectories watched as well?** +### Do I have to watch the Error and Event channels in a goroutine? +Yes. You can read both channels in the same goroutine using `select` (you don't +need a separate goroutine for both channels; see the example). -No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap [#18][]). +### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys? +fsnotify requires support from underlying OS to work. The current NFS and SMB +protocols does not provide network level support for file notifications, and +neither do the /proc and /sys virtual filesystems. -**Do I have to watch the Error and Event channels in a separate goroutine?** +This could be fixed with a polling watcher ([#9]), but it's not yet implemented. -As of now, yes. Looking into making this single-thread friendly (see [howeyc #7][#7]) +[#9]: https://github.com/fsnotify/fsnotify/issues/9 -**Why am I receiving multiple events for the same file on OS X?** +### Why do I get many Chmod events? +Some programs may generate a lot of attribute changes; for example Spotlight on +macOS, anti-virus programs, backup applications, and some others are known to do +this. As a rule, it's typically best to ignore Chmod events. They're often not +useful, and tend to cause problems. -Spotlight indexing on OS X can result in multiple events (see [howeyc #62][#62]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#11][]). +Spotlight indexing on macOS can result in multiple events (see [#15]). A +temporary workaround is to add your folder(s) to the *Spotlight Privacy +settings* until we have a native FSEvents implementation (see [#11]). -**How many files can be watched at once?** +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#15]: https://github.com/fsnotify/fsnotify/issues/15 -There are OS-specific limits as to how many watches can be created: -* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. -* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. +### Watching a file doesn't work well +Watching individual files (rather than directories) is generally not recommended +as many programs (especially editors) update files atomically: it will write to +a temporary file which is then moved to to destination, overwriting the original +(or some variant thereof). The watcher on the original file is now lost, as that +no longer exists. -**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?** +The upshot of this is that a power failure or crash won't leave a half-written +file. -fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications. +Watch the parent directory and use `Event.Name` to filter out files you're not +interested in. There is an example of this in `cmd/fsnotify/file.go`. -[#62]: https://github.com/howeyc/fsnotify/issues/62 -[#18]: https://github.com/fsnotify/fsnotify/issues/18 -[#11]: https://github.com/fsnotify/fsnotify/issues/11 -[#7]: https://github.com/howeyc/fsnotify/issues/7 +Platform-specific notes +----------------------- +### Linux +When a file is removed a REMOVE event won't be emitted until all file +descriptors are closed; it will emit a CHMOD instead: + + fp := os.Open("file") + os.Remove("file") // CHMOD + fp.Close() // REMOVE + +This is the event that inotify sends, so not much can be changed about this. + +The `fs.inotify.max_user_watches` sysctl variable specifies the upper limit for +the number of watches per user, and `fs.inotify.max_user_instances` specifies +the maximum number of inotify instances per user. Every Watcher you create is an +"instance", and every path you add is a "watch". + +These are also exposed in `/proc` as `/proc/sys/fs/inotify/max_user_watches` and +`/proc/sys/fs/inotify/max_user_instances` + +To increase them you can use `sysctl` or write the value to proc file: + + # The default values on Linux 5.18 + sysctl fs.inotify.max_user_watches=124983 + sysctl fs.inotify.max_user_instances=128 + +To make the changes persist on reboot edit `/etc/sysctl.conf` or +`/usr/lib/sysctl.d/50-default.conf` (details differ per Linux distro; check your +distro's documentation): -[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md + fs.inotify.max_user_watches=124983 + fs.inotify.max_user_instances=128 -## Related Projects +Reaching the limit will result in a "no space left on device" or "too many open +files" error. -* [notify](https://github.com/rjeczalik/notify) -* [fsevents](https://github.com/fsnotify/fsevents) +### kqueue (macOS, all BSD systems) +kqueue requires opening a file descriptor for every file that's being watched; +so if you're watching a directory with five files then that's six file +descriptors. You will run in to your system's "max open files" limit faster on +these platforms. +The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to +control the maximum number of open files. diff --git a/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/vendor/github.com/fsnotify/fsnotify/backend_fen.go new file mode 100644 index 000000000..c349c326c --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_fen.go @@ -0,0 +1,484 @@ +//go:build solaris + +// FEN backend for illumos (supported) and Solaris (untested, but should work). +// +// See port_create(3c) etc. for docs. https://www.illumos.org/man/3C/port_create + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "sync" + "time" + + "github.com/fsnotify/fsnotify/internal" + "golang.org/x/sys/unix" +) + +type fen struct { + Events chan Event + Errors chan error + + mu sync.Mutex + port *unix.EventPort + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + dirs map[string]Op // Explicitly watched directories + watches map[string]Op // Explicitly watched non-directories +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + w := &fen{ + Events: ev, + Errors: errs, + dirs: make(map[string]Op), + watches: make(map[string]Op), + done: make(chan struct{}), + } + + var err error + w.port, err = unix.NewEventPort() + if err != nil { + return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err) + } + + go w.readEvents() + return w, nil +} + +// sendEvent attempts to send an event to the user, returning true if the event +// was put in the channel successfully and false if the watcher has been closed. +func (w *fen) sendEvent(name string, op Op) (sent bool) { + select { + case <-w.done: + return false + case w.Events <- Event{Name: name, Op: op}: + return true + } +} + +// sendError attempts to send an error to the user, returning true if the error +// was put in the channel successfully and false if the watcher has been closed. +func (w *fen) sendError(err error) (sent bool) { + if err == nil { + return true + } + select { + case <-w.done: + return false + case w.Errors <- err: + return true + } +} + +func (w *fen) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +func (w *fen) Close() error { + // Take the lock used by associateFile to prevent lingering events from + // being processed after the close + w.mu.Lock() + defer w.mu.Unlock() + if w.isClosed() { + return nil + } + close(w.done) + return w.port.Close() +} + +func (w *fen) Add(name string) error { return w.AddWith(name) } + +func (w *fen) AddWith(name string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + + // Currently we resolve symlinks that were explicitly requested to be + // watched. Otherwise we would use LStat here. + stat, err := os.Stat(name) + if err != nil { + return err + } + + // Associate all files in the directory. + if stat.IsDir() { + err := w.handleDirectory(name, stat, true, w.associateFile) + if err != nil { + return err + } + + w.mu.Lock() + w.dirs[name] = with.op + w.mu.Unlock() + return nil + } + + err = w.associateFile(name, stat, true) + if err != nil { + return err + } + + w.mu.Lock() + w.watches[name] = with.op + w.mu.Unlock() + return nil +} + +func (w *fen) Remove(name string) error { + if w.isClosed() { + return nil + } + if !w.port.PathIsWatched(name) { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + // The user has expressed an intent. Immediately remove this name from + // whichever watch list it might be in. If it's not in there the delete + // doesn't cause harm. + w.mu.Lock() + delete(w.watches, name) + delete(w.dirs, name) + w.mu.Unlock() + + stat, err := os.Stat(name) + if err != nil { + return err + } + + // Remove associations for every file in the directory. + if stat.IsDir() { + err := w.handleDirectory(name, stat, false, w.dissociateFile) + if err != nil { + return err + } + return nil + } + + err = w.port.DissociatePath(name) + if err != nil { + return err + } + + return nil +} + +// readEvents contains the main loop that runs in a goroutine watching for events. +func (w *fen) readEvents() { + // If this function returns, the watcher has been closed and we can close + // these channels + defer func() { + close(w.Errors) + close(w.Events) + }() + + pevents := make([]unix.PortEvent, 8) + for { + count, err := w.port.Get(pevents, 1, nil) + if err != nil && err != unix.ETIME { + // Interrupted system call (count should be 0) ignore and continue + if errors.Is(err, unix.EINTR) && count == 0 { + continue + } + // Get failed because we called w.Close() + if errors.Is(err, unix.EBADF) && w.isClosed() { + return + } + // There was an error not caused by calling w.Close() + if !w.sendError(err) { + return + } + } + + p := pevents[:count] + for _, pevent := range p { + if pevent.Source != unix.PORT_SOURCE_FILE { + // Event from unexpected source received; should never happen. + if !w.sendError(errors.New("Event from unexpected source received")) { + return + } + continue + } + + if debug { + internal.Debug(pevent.Path, pevent.Events) + } + + err = w.handleEvent(&pevent) + if !w.sendError(err) { + return + } + } + } +} + +func (w *fen) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error { + files, err := os.ReadDir(path) + if err != nil { + return err + } + + // Handle all children of the directory. + for _, entry := range files { + finfo, err := entry.Info() + if err != nil { + return err + } + err = handler(filepath.Join(path, finfo.Name()), finfo, false) + if err != nil { + return err + } + } + + // And finally handle the directory itself. + return handler(path, stat, follow) +} + +// handleEvent might need to emit more than one fsnotify event if the events +// bitmap matches more than one event type (e.g. the file was both modified and +// had the attributes changed between when the association was created and the +// when event was returned) +func (w *fen) handleEvent(event *unix.PortEvent) error { + var ( + events = event.Events + path = event.Path + fmode = event.Cookie.(os.FileMode) + reRegister = true + ) + + w.mu.Lock() + _, watchedDir := w.dirs[path] + _, watchedPath := w.watches[path] + w.mu.Unlock() + isWatched := watchedDir || watchedPath + + if events&unix.FILE_DELETE != 0 { + if !w.sendEvent(path, Remove) { + return nil + } + reRegister = false + } + if events&unix.FILE_RENAME_FROM != 0 { + if !w.sendEvent(path, Rename) { + return nil + } + // Don't keep watching the new file name + reRegister = false + } + if events&unix.FILE_RENAME_TO != 0 { + // We don't report a Rename event for this case, because Rename events + // are interpreted as referring to the _old_ name of the file, and in + // this case the event would refer to the new name of the file. This + // type of rename event is not supported by fsnotify. + + // inotify reports a Remove event in this case, so we simulate this + // here. + if !w.sendEvent(path, Remove) { + return nil + } + // Don't keep watching the file that was removed + reRegister = false + } + + // The file is gone, nothing left to do. + if !reRegister { + if watchedDir { + w.mu.Lock() + delete(w.dirs, path) + w.mu.Unlock() + } + if watchedPath { + w.mu.Lock() + delete(w.watches, path) + w.mu.Unlock() + } + return nil + } + + // If we didn't get a deletion the file still exists and we're going to have + // to watch it again. Let's Stat it now so that we can compare permissions + // and have what we need to continue watching the file + + stat, err := os.Lstat(path) + if err != nil { + // This is unexpected, but we should still emit an event. This happens + // most often on "rm -r" of a subdirectory inside a watched directory We + // get a modify event of something happening inside, but by the time we + // get here, the sudirectory is already gone. Clearly we were watching + // this path but now it is gone. Let's tell the user that it was + // removed. + if !w.sendEvent(path, Remove) { + return nil + } + // Suppress extra write events on removed directories; they are not + // informative and can be confusing. + return nil + } + + // resolve symlinks that were explicitly watched as we would have at Add() + // time. this helps suppress spurious Chmod events on watched symlinks + if isWatched { + stat, err = os.Stat(path) + if err != nil { + // The symlink still exists, but the target is gone. Report the + // Remove similar to above. + if !w.sendEvent(path, Remove) { + return nil + } + // Don't return the error + } + } + + if events&unix.FILE_MODIFIED != 0 { + if fmode.IsDir() && watchedDir { + if err := w.updateDirectory(path); err != nil { + return err + } + } else { + if !w.sendEvent(path, Write) { + return nil + } + } + } + if events&unix.FILE_ATTRIB != 0 && stat != nil { + // Only send Chmod if perms changed + if stat.Mode().Perm() != fmode.Perm() { + if !w.sendEvent(path, Chmod) { + return nil + } + } + } + + if stat != nil { + // If we get here, it means we've hit an event above that requires us to + // continue watching the file or directory + return w.associateFile(path, stat, isWatched) + } + return nil +} + +func (w *fen) updateDirectory(path string) error { + // The directory was modified, so we must find unwatched entities and watch + // them. If something was removed from the directory, nothing will happen, + // as everything else should still be watched. + files, err := os.ReadDir(path) + if err != nil { + return err + } + + for _, entry := range files { + path := filepath.Join(path, entry.Name()) + if w.port.PathIsWatched(path) { + continue + } + + finfo, err := entry.Info() + if err != nil { + return err + } + err = w.associateFile(path, finfo, false) + if !w.sendError(err) { + return nil + } + if !w.sendEvent(path, Create) { + return nil + } + } + return nil +} + +func (w *fen) associateFile(path string, stat os.FileInfo, follow bool) error { + if w.isClosed() { + return ErrClosed + } + // This is primarily protecting the call to AssociatePath but it is + // important and intentional that the call to PathIsWatched is also + // protected by this mutex. Without this mutex, AssociatePath has been seen + // to error out that the path is already associated. + w.mu.Lock() + defer w.mu.Unlock() + + if w.port.PathIsWatched(path) { + // Remove the old association in favor of this one If we get ENOENT, + // then while the x/sys/unix wrapper still thought that this path was + // associated, the underlying event port did not. This call will have + // cleared up that discrepancy. The most likely cause is that the event + // has fired but we haven't processed it yet. + err := w.port.DissociatePath(path) + if err != nil && !errors.Is(err, unix.ENOENT) { + return err + } + } + + var events int + if !follow { + // Watch symlinks themselves rather than their targets unless this entry + // is explicitly watched. + events |= unix.FILE_NOFOLLOW + } + if true { // TODO: implement withOps() + events |= unix.FILE_MODIFIED + } + if true { + events |= unix.FILE_ATTRIB + } + return w.port.AssociatePath(path, stat, events, stat.Mode()) +} + +func (w *fen) dissociateFile(path string, stat os.FileInfo, unused bool) error { + if !w.port.PathIsWatched(path) { + return nil + } + return w.port.DissociatePath(path) +} + +func (w *fen) WatchList() []string { + if w.isClosed() { + return nil + } + + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.watches)+len(w.dirs)) + for pathname := range w.dirs { + entries = append(entries, pathname) + } + for pathname := range w.watches { + entries = append(entries, pathname) + } + + return entries +} + +func (w *fen) xSupports(op Op) bool { + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go new file mode 100644 index 000000000..36c311694 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go @@ -0,0 +1,658 @@ +//go:build linux && !appengine + +package fsnotify + +import ( + "errors" + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "strings" + "sync" + "time" + "unsafe" + + "github.com/fsnotify/fsnotify/internal" + "golang.org/x/sys/unix" +) + +type inotify struct { + Events chan Event + Errors chan error + + // Store fd here as os.File.Read() will no longer return on close after + // calling Fd(). See: https://github.com/golang/go/issues/26439 + fd int + inotifyFile *os.File + watches *watches + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + doneMu sync.Mutex + doneResp chan struct{} // Channel to respond to Close + + // Store rename cookies in an array, with the index wrapping to 0. Almost + // all of the time what we get is a MOVED_FROM to set the cookie and the + // next event inotify sends will be MOVED_TO to read it. However, this is + // not guaranteed – as described in inotify(7) – and we may get other events + // between the two MOVED_* events (including other MOVED_* ones). + // + // A second issue is that moving a file outside the watched directory will + // trigger a MOVED_FROM to set the cookie, but we never see the MOVED_TO to + // read and delete it. So just storing it in a map would slowly leak memory. + // + // Doing it like this gives us a simple fast LRU-cache that won't allocate. + // Ten items should be more than enough for our purpose, and a loop over + // such a short array is faster than a map access anyway (not that it hugely + // matters since we're talking about hundreds of ns at the most, but still). + cookies [10]koekje + cookieIndex uint8 + cookiesMu sync.Mutex +} + +type ( + watches struct { + mu sync.RWMutex + wd map[uint32]*watch // wd → watch + path map[string]uint32 // pathname → wd + } + watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) + path string // Watch path. + recurse bool // Recursion with ./...? + } + koekje struct { + cookie uint32 + path string + } +) + +func newWatches() *watches { + return &watches{ + wd: make(map[uint32]*watch), + path: make(map[string]uint32), + } +} + +func (w *watches) len() int { + w.mu.RLock() + defer w.mu.RUnlock() + return len(w.wd) +} + +func (w *watches) add(ww *watch) { + w.mu.Lock() + defer w.mu.Unlock() + w.wd[ww.wd] = ww + w.path[ww.path] = ww.wd +} + +func (w *watches) remove(wd uint32) { + w.mu.Lock() + defer w.mu.Unlock() + watch := w.wd[wd] // Could have had Remove() called. See #616. + if watch == nil { + return + } + delete(w.path, watch.path) + delete(w.wd, wd) +} + +func (w *watches) removePath(path string) ([]uint32, error) { + w.mu.Lock() + defer w.mu.Unlock() + + path, recurse := recursivePath(path) + wd, ok := w.path[path] + if !ok { + return nil, fmt.Errorf("%w: %s", ErrNonExistentWatch, path) + } + + watch := w.wd[wd] + if recurse && !watch.recurse { + return nil, fmt.Errorf("can't use /... with non-recursive watch %q", path) + } + + delete(w.path, path) + delete(w.wd, wd) + if !watch.recurse { + return []uint32{wd}, nil + } + + wds := make([]uint32, 0, 8) + wds = append(wds, wd) + for p, rwd := range w.path { + if filepath.HasPrefix(p, path) { + delete(w.path, p) + delete(w.wd, rwd) + wds = append(wds, rwd) + } + } + return wds, nil +} + +func (w *watches) byPath(path string) *watch { + w.mu.RLock() + defer w.mu.RUnlock() + return w.wd[w.path[path]] +} + +func (w *watches) byWd(wd uint32) *watch { + w.mu.RLock() + defer w.mu.RUnlock() + return w.wd[wd] +} + +func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error { + w.mu.Lock() + defer w.mu.Unlock() + + var existing *watch + wd, ok := w.path[path] + if ok { + existing = w.wd[wd] + } + + upd, err := f(existing) + if err != nil { + return err + } + if upd != nil { + w.wd[upd.wd] = upd + w.path[upd.path] = upd.wd + + if upd.wd != wd { + delete(w.wd, wd) + } + } + + return nil +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + // Need to set nonblocking mode for SetDeadline to work, otherwise blocking + // I/O operations won't terminate on close. + fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) + if fd == -1 { + return nil, errno + } + + w := &inotify{ + Events: ev, + Errors: errs, + fd: fd, + inotifyFile: os.NewFile(uintptr(fd), ""), + watches: newWatches(), + done: make(chan struct{}), + doneResp: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +// Returns true if the event was sent, or false if watcher is closed. +func (w *inotify) sendEvent(e Event) bool { + select { + case <-w.done: + return false + case w.Events <- e: + return true + } +} + +// Returns true if the error was sent, or false if watcher is closed. +func (w *inotify) sendError(err error) bool { + if err == nil { + return true + } + select { + case <-w.done: + return false + case w.Errors <- err: + return true + } +} + +func (w *inotify) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +func (w *inotify) Close() error { + w.doneMu.Lock() + if w.isClosed() { + w.doneMu.Unlock() + return nil + } + close(w.done) + w.doneMu.Unlock() + + // Causes any blocking reads to return with an error, provided the file + // still supports deadline operations. + err := w.inotifyFile.Close() + if err != nil { + return err + } + + // Wait for goroutine to close + <-w.doneResp + + return nil +} + +func (w *inotify) Add(name string) error { return w.AddWith(name) } + +func (w *inotify) AddWith(path string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), path) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + + path, recurse := recursivePath(path) + if recurse { + return filepath.WalkDir(path, func(root string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + if root == path { + return fmt.Errorf("fsnotify: not a directory: %q", path) + } + return nil + } + + // Send a Create event when adding new directory from a recursive + // watch; this is for "mkdir -p one/two/three". Usually all those + // directories will be created before we can set up watchers on the + // subdirectories, so only "one" would be sent as a Create event and + // not "one/two" and "one/two/three" (inotifywait -r has the same + // problem). + if with.sendCreate && root != path { + w.sendEvent(Event{Name: root, Op: Create}) + } + + return w.add(root, with, true) + }) + } + + return w.add(path, with, false) +} + +func (w *inotify) add(path string, with withOpts, recurse bool) error { + var flags uint32 + if with.noFollow { + flags |= unix.IN_DONT_FOLLOW + } + if with.op.Has(Create) { + flags |= unix.IN_CREATE + } + if with.op.Has(Write) { + flags |= unix.IN_MODIFY + } + if with.op.Has(Remove) { + flags |= unix.IN_DELETE | unix.IN_DELETE_SELF + } + if with.op.Has(Rename) { + flags |= unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_MOVE_SELF + } + if with.op.Has(Chmod) { + flags |= unix.IN_ATTRIB + } + if with.op.Has(xUnportableOpen) { + flags |= unix.IN_OPEN + } + if with.op.Has(xUnportableRead) { + flags |= unix.IN_ACCESS + } + if with.op.Has(xUnportableCloseWrite) { + flags |= unix.IN_CLOSE_WRITE + } + if with.op.Has(xUnportableCloseRead) { + flags |= unix.IN_CLOSE_NOWRITE + } + return w.register(path, flags, recurse) +} + +func (w *inotify) register(path string, flags uint32, recurse bool) error { + return w.watches.updatePath(path, func(existing *watch) (*watch, error) { + if existing != nil { + flags |= existing.flags | unix.IN_MASK_ADD + } + + wd, err := unix.InotifyAddWatch(w.fd, path, flags) + if wd == -1 { + return nil, err + } + + if existing == nil { + return &watch{ + wd: uint32(wd), + path: path, + flags: flags, + recurse: recurse, + }, nil + } + + existing.wd = uint32(wd) + existing.flags = flags + return existing, nil + }) +} + +func (w *inotify) Remove(name string) error { + if w.isClosed() { + return nil + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + return w.remove(filepath.Clean(name)) +} + +func (w *inotify) remove(name string) error { + wds, err := w.watches.removePath(name) + if err != nil { + return err + } + + for _, wd := range wds { + _, err := unix.InotifyRmWatch(w.fd, wd) + if err != nil { + // TODO: Perhaps it's not helpful to return an error here in every + // case; the only two possible errors are: + // + // EBADF, which happens when w.fd is not a valid file descriptor of + // any kind. + // + // EINVAL, which is when fd is not an inotify descriptor or wd is + // not a valid watch descriptor. Watch descriptors are invalidated + // when they are removed explicitly or implicitly; explicitly by + // inotify_rm_watch, implicitly when the file they are watching is + // deleted. + return err + } + } + return nil +} + +func (w *inotify) WatchList() []string { + if w.isClosed() { + return nil + } + + entries := make([]string, 0, w.watches.len()) + w.watches.mu.RLock() + for pathname := range w.watches.path { + entries = append(entries, pathname) + } + w.watches.mu.RUnlock() + + return entries +} + +// readEvents reads from the inotify file descriptor, converts the +// received events into Event objects and sends them via the Events channel +func (w *inotify) readEvents() { + defer func() { + close(w.doneResp) + close(w.Errors) + close(w.Events) + }() + + var ( + buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events + errno error // Syscall errno + ) + for { + // See if we have been closed. + if w.isClosed() { + return + } + + n, err := w.inotifyFile.Read(buf[:]) + switch { + case errors.Unwrap(err) == os.ErrClosed: + return + case err != nil: + if !w.sendError(err) { + return + } + continue + } + + if n < unix.SizeofInotifyEvent { + var err error + if n == 0 { + err = io.EOF // If EOF is received. This should really never happen. + } else if n < 0 { + err = errno // If an error occurred while reading. + } else { + err = errors.New("notify: short read in readEvents()") // Read was too short. + } + if !w.sendError(err) { + return + } + continue + } + + // We don't know how many events we just read into the buffer + // While the offset points to at least one whole event... + var offset uint32 + for offset <= uint32(n-unix.SizeofInotifyEvent) { + var ( + // Point "raw" to the event in the buffer + raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) + mask = uint32(raw.Mask) + nameLen = uint32(raw.Len) + // Move to the next event in the buffer + next = func() { offset += unix.SizeofInotifyEvent + nameLen } + ) + + if mask&unix.IN_Q_OVERFLOW != 0 { + if !w.sendError(ErrEventOverflow) { + return + } + } + + /// If the event happened to the watched directory or the watched + /// file, the kernel doesn't append the filename to the event, but + /// we would like to always fill the the "Name" field with a valid + /// filename. We retrieve the path of the watch from the "paths" + /// map. + watch := w.watches.byWd(uint32(raw.Wd)) + /// Can be nil if Remove() was called in another goroutine for this + /// path inbetween reading the events from the kernel and reading + /// the internal state. Not much we can do about it, so just skip. + /// See #616. + if watch == nil { + next() + continue + } + + name := watch.path + if nameLen > 0 { + /// Point "bytes" at the first byte of the filename + bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] + /// The filename is padded with NULL bytes. TrimRight() gets rid of those. + name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + + if debug { + internal.Debug(name, raw.Mask, raw.Cookie) + } + + if mask&unix.IN_IGNORED != 0 { //&& event.Op != 0 + next() + continue + } + + // inotify will automatically remove the watch on deletes; just need + // to clean our state here. + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + w.watches.remove(watch.wd) + } + + // We can't really update the state when a watched path is moved; + // only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove + // the watch. + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF { + if watch.recurse { + next() // Do nothing + continue + } + + err := w.remove(watch.path) + if err != nil && !errors.Is(err, ErrNonExistentWatch) { + if !w.sendError(err) { + return + } + } + } + + /// Skip if we're watching both this path and the parent; the parent + /// will already send a delete so no need to do it twice. + if mask&unix.IN_DELETE_SELF != 0 { + if _, ok := w.watches.path[filepath.Dir(watch.path)]; ok { + next() + continue + } + } + + ev := w.newEvent(name, mask, raw.Cookie) + // Need to update watch path for recurse. + if watch.recurse { + isDir := mask&unix.IN_ISDIR == unix.IN_ISDIR + /// New directory created: set up watch on it. + if isDir && ev.Has(Create) { + err := w.register(ev.Name, watch.flags, true) + if !w.sendError(err) { + return + } + + // This was a directory rename, so we need to update all + // the children. + // + // TODO: this is of course pretty slow; we should use a + // better data structure for storing all of this, e.g. store + // children in the watch. I have some code for this in my + // kqueue refactor we can use in the future. For now I'm + // okay with this as it's not publicly available. + // Correctness first, performance second. + if ev.renamedFrom != "" { + w.watches.mu.Lock() + for k, ww := range w.watches.wd { + if k == watch.wd || ww.path == ev.Name { + continue + } + if strings.HasPrefix(ww.path, ev.renamedFrom) { + ww.path = strings.Replace(ww.path, ev.renamedFrom, ev.Name, 1) + w.watches.wd[k] = ww + } + } + w.watches.mu.Unlock() + } + } + } + + /// Send the events that are not ignored on the events channel + if !w.sendEvent(ev) { + return + } + next() + } + } +} + +func (w *inotify) isRecursive(path string) bool { + ww := w.watches.byPath(path) + if ww == nil { // path could be a file, so also check the Dir. + ww = w.watches.byPath(filepath.Dir(path)) + } + return ww != nil && ww.recurse +} + +func (w *inotify) newEvent(name string, mask, cookie uint32) Event { + e := Event{Name: name} + if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + e.Op |= Create + } + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { + e.Op |= Remove + } + if mask&unix.IN_MODIFY == unix.IN_MODIFY { + e.Op |= Write + } + if mask&unix.IN_OPEN == unix.IN_OPEN { + e.Op |= xUnportableOpen + } + if mask&unix.IN_ACCESS == unix.IN_ACCESS { + e.Op |= xUnportableRead + } + if mask&unix.IN_CLOSE_WRITE == unix.IN_CLOSE_WRITE { + e.Op |= xUnportableCloseWrite + } + if mask&unix.IN_CLOSE_NOWRITE == unix.IN_CLOSE_NOWRITE { + e.Op |= xUnportableCloseRead + } + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + e.Op |= Rename + } + if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { + e.Op |= Chmod + } + + if cookie != 0 { + if mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + w.cookiesMu.Lock() + w.cookies[w.cookieIndex] = koekje{cookie: cookie, path: e.Name} + w.cookieIndex++ + if w.cookieIndex > 9 { + w.cookieIndex = 0 + } + w.cookiesMu.Unlock() + } else if mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + w.cookiesMu.Lock() + var prev string + for _, c := range w.cookies { + if c.cookie == cookie { + prev = c.path + break + } + } + w.cookiesMu.Unlock() + e.renamedFrom = prev + } + } + return e +} + +func (w *inotify) xSupports(op Op) bool { + return true // Supports everything. +} + +func (w *inotify) state() { + w.watches.mu.Lock() + defer w.watches.mu.Unlock() + for wd, ww := range w.watches.wd { + fmt.Fprintf(os.Stderr, "%4d: recurse=%t %q\n", wd, ww.recurse, ww.path) + } +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go new file mode 100644 index 000000000..d8de5ab76 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go @@ -0,0 +1,733 @@ +//go:build freebsd || openbsd || netbsd || dragonfly || darwin + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "sync" + "time" + + "github.com/fsnotify/fsnotify/internal" + "golang.org/x/sys/unix" +) + +type kqueue struct { + Events chan Event + Errors chan error + + kq int // File descriptor (as returned by the kqueue() syscall). + closepipe [2]int // Pipe used for closing kq. + watches *watches + done chan struct{} + doneMu sync.Mutex +} + +type ( + watches struct { + mu sync.RWMutex + wd map[int]watch // wd → watch + path map[string]int // pathname → wd + byDir map[string]map[int]struct{} // dirname(path) → wd + seen map[string]struct{} // Keep track of if we know this file exists. + byUser map[string]struct{} // Watches added with Watcher.Add() + } + watch struct { + wd int + name string + linkName string // In case of links; name is the target, and this is the link. + isDir bool + dirFlags uint32 + } +) + +func newWatches() *watches { + return &watches{ + wd: make(map[int]watch), + path: make(map[string]int), + byDir: make(map[string]map[int]struct{}), + seen: make(map[string]struct{}), + byUser: make(map[string]struct{}), + } +} + +func (w *watches) listPaths(userOnly bool) []string { + w.mu.RLock() + defer w.mu.RUnlock() + + if userOnly { + l := make([]string, 0, len(w.byUser)) + for p := range w.byUser { + l = append(l, p) + } + return l + } + + l := make([]string, 0, len(w.path)) + for p := range w.path { + l = append(l, p) + } + return l +} + +func (w *watches) watchesInDir(path string) []string { + w.mu.RLock() + defer w.mu.RUnlock() + + l := make([]string, 0, 4) + for fd := range w.byDir[path] { + info := w.wd[fd] + if _, ok := w.byUser[info.name]; !ok { + l = append(l, info.name) + } + } + return l +} + +// Mark path as added by the user. +func (w *watches) addUserWatch(path string) { + w.mu.Lock() + defer w.mu.Unlock() + w.byUser[path] = struct{}{} +} + +func (w *watches) addLink(path string, fd int) { + w.mu.Lock() + defer w.mu.Unlock() + + w.path[path] = fd + w.seen[path] = struct{}{} +} + +func (w *watches) add(path, linkPath string, fd int, isDir bool) { + w.mu.Lock() + defer w.mu.Unlock() + + w.path[path] = fd + w.wd[fd] = watch{wd: fd, name: path, linkName: linkPath, isDir: isDir} + + parent := filepath.Dir(path) + byDir, ok := w.byDir[parent] + if !ok { + byDir = make(map[int]struct{}, 1) + w.byDir[parent] = byDir + } + byDir[fd] = struct{}{} +} + +func (w *watches) byWd(fd int) (watch, bool) { + w.mu.RLock() + defer w.mu.RUnlock() + info, ok := w.wd[fd] + return info, ok +} + +func (w *watches) byPath(path string) (watch, bool) { + w.mu.RLock() + defer w.mu.RUnlock() + info, ok := w.wd[w.path[path]] + return info, ok +} + +func (w *watches) updateDirFlags(path string, flags uint32) { + w.mu.Lock() + defer w.mu.Unlock() + + fd := w.path[path] + info := w.wd[fd] + info.dirFlags = flags + w.wd[fd] = info +} + +func (w *watches) remove(fd int, path string) bool { + w.mu.Lock() + defer w.mu.Unlock() + + isDir := w.wd[fd].isDir + delete(w.path, path) + delete(w.byUser, path) + + parent := filepath.Dir(path) + delete(w.byDir[parent], fd) + + if len(w.byDir[parent]) == 0 { + delete(w.byDir, parent) + } + + delete(w.wd, fd) + delete(w.seen, path) + return isDir +} + +func (w *watches) markSeen(path string, exists bool) { + w.mu.Lock() + defer w.mu.Unlock() + if exists { + w.seen[path] = struct{}{} + } else { + delete(w.seen, path) + } +} + +func (w *watches) seenBefore(path string) bool { + w.mu.RLock() + defer w.mu.RUnlock() + _, ok := w.seen[path] + return ok +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(0, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + kq, closepipe, err := newKqueue() + if err != nil { + return nil, err + } + + w := &kqueue{ + Events: ev, + Errors: errs, + kq: kq, + closepipe: closepipe, + done: make(chan struct{}), + watches: newWatches(), + } + + go w.readEvents() + return w, nil +} + +// newKqueue creates a new kernel event queue and returns a descriptor. +// +// This registers a new event on closepipe, which will trigger an event when +// it's closed. This way we can use kevent() without timeout/polling; without +// the closepipe, it would block forever and we wouldn't be able to stop it at +// all. +func newKqueue() (kq int, closepipe [2]int, err error) { + kq, err = unix.Kqueue() + if kq == -1 { + return kq, closepipe, err + } + + // Register the close pipe. + err = unix.Pipe(closepipe[:]) + if err != nil { + unix.Close(kq) + return kq, closepipe, err + } + unix.CloseOnExec(closepipe[0]) + unix.CloseOnExec(closepipe[1]) + + // Register changes to listen on the closepipe. + changes := make([]unix.Kevent_t, 1) + // SetKevent converts int to the platform-specific types. + unix.SetKevent(&changes[0], closepipe[0], unix.EVFILT_READ, + unix.EV_ADD|unix.EV_ENABLE|unix.EV_ONESHOT) + + ok, err := unix.Kevent(kq, changes, nil, nil) + if ok == -1 { + unix.Close(kq) + unix.Close(closepipe[0]) + unix.Close(closepipe[1]) + return kq, closepipe, err + } + return kq, closepipe, nil +} + +// Returns true if the event was sent, or false if watcher is closed. +func (w *kqueue) sendEvent(e Event) bool { + select { + case <-w.done: + return false + case w.Events <- e: + return true + } +} + +// Returns true if the error was sent, or false if watcher is closed. +func (w *kqueue) sendError(err error) bool { + if err == nil { + return true + } + select { + case <-w.done: + return false + case w.Errors <- err: + return true + } +} + +func (w *kqueue) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +func (w *kqueue) Close() error { + w.doneMu.Lock() + if w.isClosed() { + w.doneMu.Unlock() + return nil + } + close(w.done) + w.doneMu.Unlock() + + pathsToRemove := w.watches.listPaths(false) + for _, name := range pathsToRemove { + w.Remove(name) + } + + // Send "quit" message to the reader goroutine. + unix.Close(w.closepipe[1]) + return nil +} + +func (w *kqueue) Add(name string) error { return w.AddWith(name) } + +func (w *kqueue) AddWith(name string, opts ...addOpt) error { + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + + _, err := w.addWatch(name, noteAllEvents) + if err != nil { + return err + } + w.watches.addUserWatch(name) + return nil +} + +func (w *kqueue) Remove(name string) error { + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), name) + } + return w.remove(name, true) +} + +func (w *kqueue) remove(name string, unwatchFiles bool) error { + if w.isClosed() { + return nil + } + + name = filepath.Clean(name) + info, ok := w.watches.byPath(name) + if !ok { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) + } + + err := w.register([]int{info.wd}, unix.EV_DELETE, 0) + if err != nil { + return err + } + + unix.Close(info.wd) + + isDir := w.watches.remove(info.wd, name) + + // Find all watched paths that are in this directory that are not external. + if unwatchFiles && isDir { + pathsToRemove := w.watches.watchesInDir(name) + for _, name := range pathsToRemove { + // Since these are internal, not much sense in propagating error to + // the user, as that will just confuse them with an error about a + // path they did not explicitly watch themselves. + w.Remove(name) + } + } + return nil +} + +func (w *kqueue) WatchList() []string { + if w.isClosed() { + return nil + } + return w.watches.listPaths(true) +} + +// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) +const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME + +// addWatch adds name to the watched file set; the flags are interpreted as +// described in kevent(2). +// +// Returns the real path to the file which was added, with symlinks resolved. +func (w *kqueue) addWatch(name string, flags uint32) (string, error) { + if w.isClosed() { + return "", ErrClosed + } + + name = filepath.Clean(name) + + info, alreadyWatching := w.watches.byPath(name) + if !alreadyWatching { + fi, err := os.Lstat(name) + if err != nil { + return "", err + } + + // Don't watch sockets or named pipes. + if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) { + return "", nil + } + + // Follow symlinks. + if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + link, err := os.Readlink(name) + if err != nil { + // Return nil because Linux can add unresolvable symlinks to the + // watch list without problems, so maintain consistency with + // that. There will be no file events for broken symlinks. + // TODO: more specific check; returns os.PathError; ENOENT? + return "", nil + } + + _, alreadyWatching = w.watches.byPath(link) + if alreadyWatching { + // Add to watches so we don't get spurious Create events later + // on when we diff the directories. + w.watches.addLink(name, 0) + return link, nil + } + + info.linkName = name + name = link + fi, err = os.Lstat(name) + if err != nil { + return "", nil + } + } + + // Retry on EINTR; open() can return EINTR in practice on macOS. + // See #354, and Go issues 11180 and 39237. + for { + info.wd, err = unix.Open(name, openMode, 0) + if err == nil { + break + } + if errors.Is(err, unix.EINTR) { + continue + } + + return "", err + } + + info.isDir = fi.IsDir() + } + + err := w.register([]int{info.wd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags) + if err != nil { + unix.Close(info.wd) + return "", err + } + + if !alreadyWatching { + w.watches.add(name, info.linkName, info.wd, info.isDir) + } + + // Watch the directory if it has not been watched before, or if it was + // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + if info.isDir { + watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && + (!alreadyWatching || (info.dirFlags&unix.NOTE_WRITE) != unix.NOTE_WRITE) + w.watches.updateDirFlags(name, flags) + + if watchDir { + if err := w.watchDirectoryFiles(name); err != nil { + return "", err + } + } + } + return name, nil +} + +// readEvents reads from kqueue and converts the received kevents into +// Event values that it sends down the Events channel. +func (w *kqueue) readEvents() { + defer func() { + close(w.Events) + close(w.Errors) + _ = unix.Close(w.kq) + unix.Close(w.closepipe[0]) + }() + + eventBuffer := make([]unix.Kevent_t, 10) + for { + kevents, err := w.read(eventBuffer) + // EINTR is okay, the syscall was interrupted before timeout expired. + if err != nil && err != unix.EINTR { + if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) { + return + } + } + + for _, kevent := range kevents { + var ( + wd = int(kevent.Ident) + mask = uint32(kevent.Fflags) + ) + + // Shut down the loop when the pipe is closed, but only after all + // other events have been processed. + if wd == w.closepipe[0] { + return + } + + path, ok := w.watches.byWd(wd) + if debug { + internal.Debug(path.name, &kevent) + } + + // On macOS it seems that sometimes an event with Ident=0 is + // delivered, and no other flags/information beyond that, even + // though we never saw such a file descriptor. For example in + // TestWatchSymlink/277 (usually at the end, but sometimes sooner): + // + // fmt.Printf("READ: %2d %#v\n", kevent.Ident, kevent) + // unix.Kevent_t{Ident:0x2a, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)} + // unix.Kevent_t{Ident:0x0, Filter:-4, Flags:0x25, Fflags:0x2, Data:0, Udata:(*uint8)(nil)} + // + // The first is a normal event, the second with Ident 0. No error + // flag, no data, no ... nothing. + // + // I read a bit through bsd/kern_event.c from the xnu source, but I + // don't really see an obvious location where this is triggered – + // this doesn't seem intentional, but idk... + // + // Technically fd 0 is a valid descriptor, so only skip it if + // there's no path, and if we're on macOS. + if !ok && kevent.Ident == 0 && runtime.GOOS == "darwin" { + continue + } + + event := w.newEvent(path.name, path.linkName, mask) + + if event.Has(Rename) || event.Has(Remove) { + w.remove(event.Name, false) + w.watches.markSeen(event.Name, false) + } + + if path.isDir && event.Has(Write) && !event.Has(Remove) { + w.dirChange(event.Name) + } else if !w.sendEvent(event) { + return + } + + if event.Has(Remove) { + // Look for a file that may have overwritten this; for example, + // mv f1 f2 will delete f2, then create f2. + if path.isDir { + fileDir := filepath.Clean(event.Name) + _, found := w.watches.byPath(fileDir) + if found { + // TODO: this branch is never triggered in any test. + // Added in d6220df (2012). + // isDir check added in 8611c35 (2016): https://github.com/fsnotify/fsnotify/pull/111 + // + // I don't really get how this can be triggered either. + // And it wasn't triggered in the patch that added it, + // either. + // + // Original also had a comment: + // make sure the directory exists before we watch for + // changes. When we do a recursive watch and perform + // rm -rf, the parent directory might have gone + // missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the + // parent directory. + err := w.dirChange(fileDir) + if !w.sendError(err) { + return + } + } + } else { + path := filepath.Clean(event.Name) + if fi, err := os.Lstat(path); err == nil { + err := w.sendCreateIfNew(path, fi) + if !w.sendError(err) { + return + } + } + } + } + } + } +} + +// newEvent returns an platform-independent Event based on kqueue Fflags. +func (w *kqueue) newEvent(name, linkName string, mask uint32) Event { + e := Event{Name: name} + if linkName != "" { + // If the user watched "/path/link" then emit events as "/path/link" + // rather than "/path/target". + e.Name = linkName + } + + if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { + e.Op |= Remove + } + if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { + e.Op |= Write + } + if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { + e.Op |= Rename + } + if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { + e.Op |= Chmod + } + // No point sending a write and delete event at the same time: if it's gone, + // then it's gone. + if e.Op.Has(Write) && e.Op.Has(Remove) { + e.Op &^= Write + } + return e +} + +// watchDirectoryFiles to mimic inotify when adding a watch on a directory +func (w *kqueue) watchDirectoryFiles(dirPath string) error { + files, err := os.ReadDir(dirPath) + if err != nil { + return err + } + + for _, f := range files { + path := filepath.Join(dirPath, f.Name()) + + fi, err := f.Info() + if err != nil { + return fmt.Errorf("%q: %w", path, err) + } + + cleanPath, err := w.internalWatch(path, fi) + if err != nil { + // No permission to read the file; that's not a problem: just skip. + // But do add it to w.fileExists to prevent it from being picked up + // as a "new" file later (it still shows up in the directory + // listing). + switch { + case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM): + cleanPath = filepath.Clean(path) + default: + return fmt.Errorf("%q: %w", path, err) + } + } + + w.watches.markSeen(cleanPath, true) + } + + return nil +} + +// Search the directory for new files and send an event for them. +// +// This functionality is to have the BSD watcher match the inotify, which sends +// a create event for files created in a watched directory. +func (w *kqueue) dirChange(dir string) error { + files, err := os.ReadDir(dir) + if err != nil { + // Directory no longer exists: we can ignore this safely. kqueue will + // still give us the correct events. + if errors.Is(err, os.ErrNotExist) { + return nil + } + return fmt.Errorf("fsnotify.dirChange: %w", err) + } + + for _, f := range files { + fi, err := f.Info() + if err != nil { + return fmt.Errorf("fsnotify.dirChange: %w", err) + } + + err = w.sendCreateIfNew(filepath.Join(dir, fi.Name()), fi) + if err != nil { + // Don't need to send an error if this file isn't readable. + if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) { + return nil + } + return fmt.Errorf("fsnotify.dirChange: %w", err) + } + } + return nil +} + +// Send a create event if the file isn't already being tracked, and start +// watching this file. +func (w *kqueue) sendCreateIfNew(path string, fi os.FileInfo) error { + if !w.watches.seenBefore(path) { + if !w.sendEvent(Event{Name: path, Op: Create}) { + return nil + } + } + + // Like watchDirectoryFiles, but without doing another ReadDir. + path, err := w.internalWatch(path, fi) + if err != nil { + return err + } + w.watches.markSeen(path, true) + return nil +} + +func (w *kqueue) internalWatch(name string, fi os.FileInfo) (string, error) { + if fi.IsDir() { + // mimic Linux providing delete events for subdirectories, but preserve + // the flags used if currently watching subdirectory + info, _ := w.watches.byPath(name) + return w.addWatch(name, info.dirFlags|unix.NOTE_DELETE|unix.NOTE_RENAME) + } + + // watch file to mimic Linux inotify + return w.addWatch(name, noteAllEvents) +} + +// Register events with the queue. +func (w *kqueue) register(fds []int, flags int, fflags uint32) error { + changes := make([]unix.Kevent_t, len(fds)) + for i, fd := range fds { + // SetKevent converts int to the platform-specific types. + unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) + changes[i].Fflags = fflags + } + + // Register the events. + success, err := unix.Kevent(w.kq, changes, nil, nil) + if success == -1 { + return err + } + return nil +} + +// read retrieves pending events, or waits until an event occurs. +func (w *kqueue) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { + n, err := unix.Kevent(w.kq, nil, events, nil) + if err != nil { + return nil, err + } + return events[0:n], nil +} + +func (w *kqueue) xSupports(op Op) bool { + if runtime.GOOS == "freebsd" { + //return true // Supports everything. + } + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_other.go b/vendor/github.com/fsnotify/fsnotify/backend_other.go new file mode 100644 index 000000000..5eb5dbc66 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_other.go @@ -0,0 +1,23 @@ +//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows) + +package fsnotify + +import "errors" + +type other struct { + Events chan Event + Errors chan error +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return nil, errors.New("fsnotify not supported on the current platform") +} +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + return newBackend(ev, errs) +} +func (w *other) Close() error { return nil } +func (w *other) WatchList() []string { return nil } +func (w *other) Add(name string) error { return nil } +func (w *other) AddWith(name string, opts ...addOpt) error { return nil } +func (w *other) Remove(name string) error { return nil } +func (w *other) xSupports(op Op) bool { return false } diff --git a/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/vendor/github.com/fsnotify/fsnotify/backend_windows.go new file mode 100644 index 000000000..c54a63083 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_windows.go @@ -0,0 +1,682 @@ +//go:build windows + +// Windows backend based on ReadDirectoryChangesW() +// +// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "reflect" + "runtime" + "strings" + "sync" + "time" + "unsafe" + + "github.com/fsnotify/fsnotify/internal" + "golang.org/x/sys/windows" +) + +type readDirChangesW struct { + Events chan Event + Errors chan error + + port windows.Handle // Handle to completion port + input chan *input // Inputs to the reader are sent on this channel + quit chan chan<- error + + mu sync.Mutex // Protects access to watches, closed + watches watchMap // Map of watches (key: i-number) + closed bool // Set to true when Close() is first called +} + +func newBackend(ev chan Event, errs chan error) (backend, error) { + return newBufferedBackend(50, ev, errs) +} + +func newBufferedBackend(sz uint, ev chan Event, errs chan error) (backend, error) { + port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0) + if err != nil { + return nil, os.NewSyscallError("CreateIoCompletionPort", err) + } + w := &readDirChangesW{ + Events: ev, + Errors: errs, + port: port, + watches: make(watchMap), + input: make(chan *input, 1), + quit: make(chan chan<- error, 1), + } + go w.readEvents() + return w, nil +} + +func (w *readDirChangesW) isClosed() bool { + w.mu.Lock() + defer w.mu.Unlock() + return w.closed +} + +func (w *readDirChangesW) sendEvent(name, renamedFrom string, mask uint64) bool { + if mask == 0 { + return false + } + + event := w.newEvent(name, uint32(mask)) + event.renamedFrom = renamedFrom + select { + case ch := <-w.quit: + w.quit <- ch + case w.Events <- event: + } + return true +} + +// Returns true if the error was sent, or false if watcher is closed. +func (w *readDirChangesW) sendError(err error) bool { + if err == nil { + return true + } + select { + case w.Errors <- err: + return true + case <-w.quit: + return false + } +} + +func (w *readDirChangesW) Close() error { + if w.isClosed() { + return nil + } + + w.mu.Lock() + w.closed = true + w.mu.Unlock() + + // Send "quit" message to the reader goroutine + ch := make(chan error) + w.quit <- ch + if err := w.wakeupReader(); err != nil { + return err + } + return <-ch +} + +func (w *readDirChangesW) Add(name string) error { return w.AddWith(name) } + +func (w *readDirChangesW) AddWith(name string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s AddWith(%q)\n", + time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name)) + } + + with := getOptions(opts...) + if !w.xSupports(with.op) { + return fmt.Errorf("%w: %s", xErrUnsupported, with.op) + } + if with.bufsize < 4096 { + return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes") + } + + in := &input{ + op: opAddWatch, + path: filepath.Clean(name), + flags: sysFSALLEVENTS, + reply: make(chan error), + bufsize: with.bufsize, + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +func (w *readDirChangesW) Remove(name string) error { + if w.isClosed() { + return nil + } + if debug { + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s Remove(%q)\n", + time.Now().Format("15:04:05.000000000"), filepath.ToSlash(name)) + } + + in := &input{ + op: opRemoveWatch, + path: filepath.Clean(name), + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +func (w *readDirChangesW) WatchList() []string { + if w.isClosed() { + return nil + } + + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.watches)) + for _, entry := range w.watches { + for _, watchEntry := range entry { + for name := range watchEntry.names { + entries = append(entries, filepath.Join(watchEntry.path, name)) + } + // the directory itself is being watched + if watchEntry.mask != 0 { + entries = append(entries, watchEntry.path) + } + } + } + + return entries +} + +// These options are from the old golang.org/x/exp/winfsnotify, where you could +// add various options to the watch. This has long since been removed. +// +// The "sys" in the name is misleading as they're not part of any "system". +// +// This should all be removed at some point, and just use windows.FILE_NOTIFY_* +const ( + sysFSALLEVENTS = 0xfff + sysFSCREATE = 0x100 + sysFSDELETE = 0x200 + sysFSDELETESELF = 0x400 + sysFSMODIFY = 0x2 + sysFSMOVE = 0xc0 + sysFSMOVEDFROM = 0x40 + sysFSMOVEDTO = 0x80 + sysFSMOVESELF = 0x800 + sysFSIGNORED = 0x8000 +) + +func (w *readDirChangesW) newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { + e.Op |= Create + } + if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { + e.Op |= Remove + } + if mask&sysFSMODIFY == sysFSMODIFY { + e.Op |= Write + } + if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { + e.Op |= Rename + } + return e +} + +const ( + opAddWatch = iota + opRemoveWatch +) + +const ( + provisional uint64 = 1 << (32 + iota) +) + +type input struct { + op int + path string + flags uint32 + bufsize int + reply chan error +} + +type inode struct { + handle windows.Handle + volume uint32 + index uint64 +} + +type watch struct { + ov windows.Overlapped + ino *inode // i-number + recurse bool // Recursive watch? + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf []byte // buffer, allocated later +} + +type ( + indexMap map[uint64]*watch + watchMap map[uint32]indexMap +) + +func (w *readDirChangesW) wakeupReader() error { + err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil) + if err != nil { + return os.NewSyscallError("PostQueuedCompletionStatus", err) + } + return nil +} + +func (w *readDirChangesW) getDir(pathname string) (dir string, err error) { + attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname)) + if err != nil { + return "", os.NewSyscallError("GetFileAttributes", err) + } + if attr&windows.FILE_ATTRIBUTE_DIRECTORY != 0 { + dir = pathname + } else { + dir, _ = filepath.Split(pathname) + dir = filepath.Clean(dir) + } + return +} + +func (w *readDirChangesW) getIno(path string) (ino *inode, err error) { + h, err := windows.CreateFile(windows.StringToUTF16Ptr(path), + windows.FILE_LIST_DIRECTORY, + windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, + nil, windows.OPEN_EXISTING, + windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OVERLAPPED, 0) + if err != nil { + return nil, os.NewSyscallError("CreateFile", err) + } + + var fi windows.ByHandleFileInformation + err = windows.GetFileInformationByHandle(h, &fi) + if err != nil { + windows.CloseHandle(h) + return nil, os.NewSyscallError("GetFileInformationByHandle", err) + } + ino = &inode{ + handle: h, + volume: fi.VolumeSerialNumber, + index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), + } + return ino, nil +} + +// Must run within the I/O thread. +func (m watchMap) get(ino *inode) *watch { + if i := m[ino.volume]; i != nil { + return i[ino.index] + } + return nil +} + +// Must run within the I/O thread. +func (m watchMap) set(ino *inode, watch *watch) { + i := m[ino.volume] + if i == nil { + i = make(indexMap) + m[ino.volume] = i + } + i[ino.index] = watch +} + +// Must run within the I/O thread. +func (w *readDirChangesW) addWatch(pathname string, flags uint64, bufsize int) error { + pathname, recurse := recursivePath(pathname) + + dir, err := w.getDir(pathname) + if err != nil { + return err + } + + ino, err := w.getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watchEntry := w.watches.get(ino) + w.mu.Unlock() + if watchEntry == nil { + _, err := windows.CreateIoCompletionPort(ino.handle, w.port, 0, 0) + if err != nil { + windows.CloseHandle(ino.handle) + return os.NewSyscallError("CreateIoCompletionPort", err) + } + watchEntry = &watch{ + ino: ino, + path: dir, + names: make(map[string]uint64), + recurse: recurse, + buf: make([]byte, bufsize), + } + w.mu.Lock() + w.watches.set(ino, watchEntry) + w.mu.Unlock() + flags |= provisional + } else { + windows.CloseHandle(ino.handle) + } + if pathname == dir { + watchEntry.mask |= flags + } else { + watchEntry.names[filepath.Base(pathname)] |= flags + } + + err = w.startRead(watchEntry) + if err != nil { + return err + } + + if pathname == dir { + watchEntry.mask &= ^provisional + } else { + watchEntry.names[filepath.Base(pathname)] &= ^provisional + } + return nil +} + +// Must run within the I/O thread. +func (w *readDirChangesW) remWatch(pathname string) error { + pathname, recurse := recursivePath(pathname) + + dir, err := w.getDir(pathname) + if err != nil { + return err + } + ino, err := w.getIno(dir) + if err != nil { + return err + } + + w.mu.Lock() + watch := w.watches.get(ino) + w.mu.Unlock() + + if recurse && !watch.recurse { + return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname) + } + + err = windows.CloseHandle(ino.handle) + if err != nil { + w.sendError(os.NewSyscallError("CloseHandle", err)) + } + if watch == nil { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname) + } + if pathname == dir { + w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED) + watch.mask = 0 + } else { + name := filepath.Base(pathname) + w.sendEvent(filepath.Join(watch.path, name), "", watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + + return w.startRead(watch) +} + +// Must run within the I/O thread. +func (w *readDirChangesW) deleteWatch(watch *watch) { + for name, mask := range watch.names { + if mask&provisional == 0 { + w.sendEvent(filepath.Join(watch.path, name), "", mask&sysFSIGNORED) + } + delete(watch.names, name) + } + if watch.mask != 0 { + if watch.mask&provisional == 0 { + w.sendEvent(watch.path, "", watch.mask&sysFSIGNORED) + } + watch.mask = 0 + } +} + +// Must run within the I/O thread. +func (w *readDirChangesW) startRead(watch *watch) error { + err := windows.CancelIo(watch.ino.handle) + if err != nil { + w.sendError(os.NewSyscallError("CancelIo", err)) + w.deleteWatch(watch) + } + mask := w.toWindowsFlags(watch.mask) + for _, m := range watch.names { + mask |= w.toWindowsFlags(m) + } + if mask == 0 { + err := windows.CloseHandle(watch.ino.handle) + if err != nil { + w.sendError(os.NewSyscallError("CloseHandle", err)) + } + w.mu.Lock() + delete(w.watches[watch.ino.volume], watch.ino.index) + w.mu.Unlock() + return nil + } + + // We need to pass the array, rather than the slice. + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf)) + rdErr := windows.ReadDirectoryChanges(watch.ino.handle, + (*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len), + watch.recurse, mask, nil, &watch.ov, 0) + if rdErr != nil { + err := os.NewSyscallError("ReadDirectoryChanges", rdErr) + if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { + // Watched directory was probably removed + w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF) + err = nil + } + w.deleteWatch(watch) + w.startRead(watch) + return err + } + return nil +} + +// readEvents reads from the I/O completion port, converts the +// received events into Event objects and sends them via the Events channel. +// Entry point to the I/O thread. +func (w *readDirChangesW) readEvents() { + var ( + n uint32 + key uintptr + ov *windows.Overlapped + ) + runtime.LockOSThread() + + for { + // This error is handled after the watch == nil check below. + qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE) + + watch := (*watch)(unsafe.Pointer(ov)) + if watch == nil { + select { + case ch := <-w.quit: + w.mu.Lock() + var indexes []indexMap + for _, index := range w.watches { + indexes = append(indexes, index) + } + w.mu.Unlock() + for _, index := range indexes { + for _, watch := range index { + w.deleteWatch(watch) + w.startRead(watch) + } + } + + err := windows.CloseHandle(w.port) + if err != nil { + err = os.NewSyscallError("CloseHandle", err) + } + close(w.Events) + close(w.Errors) + ch <- err + return + case in := <-w.input: + switch in.op { + case opAddWatch: + in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize) + case opRemoveWatch: + in.reply <- w.remWatch(in.path) + } + default: + } + continue + } + + switch qErr { + case nil: + // No error + case windows.ERROR_MORE_DATA: + if watch == nil { + w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer")) + } else { + // The i/o succeeded but the buffer is full. + // In theory we should be building up a full packet. + // In practice we can get away with just carrying on. + n = uint32(unsafe.Sizeof(watch.buf)) + } + case windows.ERROR_ACCESS_DENIED: + // Watched directory was probably removed + w.sendEvent(watch.path, "", watch.mask&sysFSDELETESELF) + w.deleteWatch(watch) + w.startRead(watch) + continue + case windows.ERROR_OPERATION_ABORTED: + // CancelIo was called on this handle + continue + default: + w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr)) + continue + } + + var offset uint32 + for { + if n == 0 { + w.sendError(ErrEventOverflow) + break + } + + // Point "raw" to the event in the buffer + raw := (*windows.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) + + // Create a buf that is the size of the path name + size := int(raw.FileNameLength / 2) + var buf []uint16 + // TODO: Use unsafe.Slice in Go 1.17; https://stackoverflow.com/questions/51187973 + sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) + sh.Data = uintptr(unsafe.Pointer(&raw.FileName)) + sh.Len = size + sh.Cap = size + name := windows.UTF16ToString(buf) + fullname := filepath.Join(watch.path, name) + + if debug { + internal.Debug(fullname, raw.Action) + } + + var mask uint64 + switch raw.Action { + case windows.FILE_ACTION_REMOVED: + mask = sysFSDELETESELF + case windows.FILE_ACTION_MODIFIED: + mask = sysFSMODIFY + case windows.FILE_ACTION_RENAMED_OLD_NAME: + watch.rename = name + case windows.FILE_ACTION_RENAMED_NEW_NAME: + // Update saved path of all sub-watches. + old := filepath.Join(watch.path, watch.rename) + w.mu.Lock() + for _, watchMap := range w.watches { + for _, ww := range watchMap { + if strings.HasPrefix(ww.path, old) { + ww.path = filepath.Join(fullname, strings.TrimPrefix(ww.path, old)) + } + } + } + w.mu.Unlock() + + if watch.names[watch.rename] != 0 { + watch.names[name] |= watch.names[watch.rename] + delete(watch.names, watch.rename) + mask = sysFSMOVESELF + } + } + + if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME { + w.sendEvent(fullname, "", watch.names[name]&mask) + } + if raw.Action == windows.FILE_ACTION_REMOVED { + w.sendEvent(fullname, "", watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + + if watch.rename != "" && raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { + w.sendEvent(fullname, filepath.Join(watch.path, watch.rename), watch.mask&w.toFSnotifyFlags(raw.Action)) + } else { + w.sendEvent(fullname, "", watch.mask&w.toFSnotifyFlags(raw.Action)) + } + + if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { + w.sendEvent(filepath.Join(watch.path, watch.rename), "", watch.names[name]&mask) + } + + // Move to the next event in the buffer + if raw.NextEntryOffset == 0 { + break + } + offset += raw.NextEntryOffset + + // Error! + if offset >= n { + //lint:ignore ST1005 Windows should be capitalized + w.sendError(errors.New("Windows system assumed buffer larger than it is, events have likely been missed")) + break + } + } + + if err := w.startRead(watch); err != nil { + w.sendError(err) + } + } +} + +func (w *readDirChangesW) toWindowsFlags(mask uint64) uint32 { + var m uint32 + if mask&sysFSMODIFY != 0 { + m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE + } + if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { + m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME + } + return m +} + +func (w *readDirChangesW) toFSnotifyFlags(action uint32) uint64 { + switch action { + case windows.FILE_ACTION_ADDED: + return sysFSCREATE + case windows.FILE_ACTION_REMOVED: + return sysFSDELETE + case windows.FILE_ACTION_MODIFIED: + return sysFSMODIFY + case windows.FILE_ACTION_RENAMED_OLD_NAME: + return sysFSMOVEDFROM + case windows.FILE_ACTION_RENAMED_NEW_NAME: + return sysFSMOVEDTO + } + return 0 +} + +func (w *readDirChangesW) xSupports(op Op) bool { + if op.Has(xUnportableOpen) || op.Has(xUnportableRead) || + op.Has(xUnportableCloseWrite) || op.Has(xUnportableCloseRead) { + return false + } + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/fen.go b/vendor/github.com/fsnotify/fsnotify/fen.go deleted file mode 100644 index b3ac3d8f5..000000000 --- a/vendor/github.com/fsnotify/fsnotify/fen.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build solaris -// +build solaris - -package fsnotify - -import ( - "errors" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - return nil -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - return nil -} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 0f4ee52e8..0760efe91 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -1,69 +1,494 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !plan9 -// +build !plan9 - -// Package fsnotify provides a platform-independent interface for file system notifications. +// Package fsnotify provides a cross-platform interface for file system +// notifications. +// +// Currently supported systems: +// +// - Linux via inotify +// - BSD, macOS via kqueue +// - Windows via ReadDirectoryChangesW +// - illumos via FEN +// +// # FSNOTIFY_DEBUG +// +// Set the FSNOTIFY_DEBUG environment variable to "1" to print debug messages to +// stderr. This can be useful to track down some problems, especially in cases +// where fsnotify is used as an indirect dependency. +// +// Every event will be printed as soon as there's something useful to print, +// with as little processing from fsnotify. +// +// Example output: +// +// FSNOTIFY_DEBUG: 11:34:23.633087586 256:IN_CREATE → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:23.633202319 4:IN_ATTRIB → "/tmp/file-1" +// FSNOTIFY_DEBUG: 11:34:28.989728764 512:IN_DELETE → "/tmp/file-1" package fsnotify import ( - "bytes" "errors" "fmt" + "os" + "path/filepath" + "strings" ) -// Event represents a single file system notification. +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # Windows notes +// +// Paths can be added as "C:\\path\\to\\dir", but forward slashes +// ("C:/path/to/dir") will also work. +// +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all files, sometimes it will send no +// events, and often only for some files. +// +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. +type Watcher struct { + b backend + + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // when a file is truncated. On Windows it's never + // sent. + Events chan Event + + // Errors sends any errors. + Errors chan error +} + +// Event represents a file system notification. type Event struct { - Name string // Relative path to the file or directory. - Op Op // File operation that triggered the event. + // Path to the file or directory. + // + // Paths are relative to the input; for example with Add("dir") the Name + // will be set to "dir/file" if you create that file, but if you use + // Add("/path/to/dir") it will be "/path/to/dir/file". + Name string + + // File operation that triggered the event. + // + // This is a bitmask and some systems may send multiple operations at once. + // Use the Event.Has() method instead of comparing with ==. + Op Op + + // Create events will have this set to the old path if it's a rename. This + // only works when both the source and destination are watched. It's not + // reliable when watching individual files, only directories. + // + // For example "mv /tmp/file /tmp/rename" will emit: + // + // Event{Op: Rename, Name: "/tmp/file"} + // Event{Op: Create, Name: "/tmp/rename", RenamedFrom: "/tmp/file"} + renamedFrom string } // Op describes a set of file operations. type Op uint32 -// These are the generalized file operations that can trigger a notification. +// The operations fsnotify can trigger; see the documentation on [Watcher] for a +// full description, and check them with [Event.Has]. const ( + // A new pathname was created. Create Op = 1 << iota + + // The pathname was written to; this does *not* mean the write has finished, + // and a write can be followed by more writes. Write + + // The path was removed; any watches on it will be removed. Some "remove" + // operations may trigger a Rename if the file is actually moved (for + // example "remove to trash" is often a rename). Remove + + // The path was renamed to something else; any watches on it will be + // removed. Rename + + // File attributes were changed. + // + // It's generally not recommended to take action on this event, as it may + // get triggered very frequently by some software. For example, Spotlight + // indexing on macOS, anti-virus software, backup software, etc. Chmod + + // File descriptor was opened. + // + // Only works on Linux and FreeBSD. + xUnportableOpen + + // File was read from. + // + // Only works on Linux and FreeBSD. + xUnportableRead + + // File opened for writing was closed. + // + // Only works on Linux and FreeBSD. + // + // The advantage of using this over Write is that it's more reliable than + // waiting for Write events to stop. It's also faster (if you're not + // listening to Write events): copying a file of a few GB can easily + // generate tens of thousands of Write events in a short span of time. + xUnportableCloseWrite + + // File opened for reading was closed. + // + // Only works on Linux and FreeBSD. + xUnportableCloseRead ) -func (op Op) String() string { - // Use a buffer for efficient string concatenation - var buffer bytes.Buffer +var ( + // ErrNonExistentWatch is used when Remove() is called on a path that's not + // added. + ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch") + + // ErrClosed is used when trying to operate on a closed Watcher. + ErrClosed = errors.New("fsnotify: watcher already closed") + + // ErrEventOverflow is reported from the Errors channel when there are too + // many events: + // + // - inotify: inotify returns IN_Q_OVERFLOW – because there are too + // many queued events (the fs.inotify.max_queued_events + // sysctl can be used to increase this). + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. + ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow") + + // ErrUnsupported is returned by AddWith() when WithOps() specified an + // Unportable event that's not supported on this platform. + xErrUnsupported = errors.New("fsnotify: not supported with this backend") +) + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBackend(ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { + ev, errs := make(chan Event), make(chan error) + b, err := newBufferedBackend(sz, ev, errs) + if err != nil { + return nil, err + } + return &Watcher{b: b, Events: ev, Errors: errs}, nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. +// +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(path string) error { return w.b.Add(path) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(path string, opts ...addOpt) error { return w.b.AddWith(path, opts...) } + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) Remove(path string) error { return w.b.Remove(path) } + +// Close removes all watches and closes the Events channel. +func (w *Watcher) Close() error { return w.b.Close() } - if op&Create == Create { - buffer.WriteString("|CREATE") +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) WatchList() []string { return w.b.WatchList() } + +// Supports reports if all the listed operations are supported by this platform. +// +// Create, Write, Remove, Rename, and Chmod are always supported. It can only +// return false for an Op starting with Unportable. +func (w *Watcher) xSupports(op Op) bool { return w.b.xSupports(op) } + +func (o Op) String() string { + var b strings.Builder + if o.Has(Create) { + b.WriteString("|CREATE") + } + if o.Has(Remove) { + b.WriteString("|REMOVE") + } + if o.Has(Write) { + b.WriteString("|WRITE") } - if op&Remove == Remove { - buffer.WriteString("|REMOVE") + if o.Has(xUnportableOpen) { + b.WriteString("|OPEN") } - if op&Write == Write { - buffer.WriteString("|WRITE") + if o.Has(xUnportableRead) { + b.WriteString("|READ") } - if op&Rename == Rename { - buffer.WriteString("|RENAME") + if o.Has(xUnportableCloseWrite) { + b.WriteString("|CLOSE_WRITE") } - if op&Chmod == Chmod { - buffer.WriteString("|CHMOD") + if o.Has(xUnportableCloseRead) { + b.WriteString("|CLOSE_READ") } - if buffer.Len() == 0 { - return "" + if o.Has(Rename) { + b.WriteString("|RENAME") } - return buffer.String()[1:] // Strip leading pipe + if o.Has(Chmod) { + b.WriteString("|CHMOD") + } + if b.Len() == 0 { + return "[no events]" + } + return b.String()[1:] } -// String returns a string representation of the event in the form -// "file: REMOVE|WRITE|..." +// Has reports if this operation has the given operation. +func (o Op) Has(h Op) bool { return o&h != 0 } + +// Has reports if this event has the given operation. +func (e Event) Has(op Op) bool { return e.Op.Has(op) } + +// String returns a string representation of the event with their path. func (e Event) String() string { - return fmt.Sprintf("%q: %s", e.Name, e.Op.String()) + if e.renamedFrom != "" { + return fmt.Sprintf("%-13s %q ← %q", e.Op.String(), e.Name, e.renamedFrom) + } + return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name) } -// Common errors that can be reported by a watcher -var ( - ErrEventOverflow = errors.New("fsnotify queue overflow") +type ( + backend interface { + Add(string) error + AddWith(string, ...addOpt) error + Remove(string) error + WatchList() []string + Close() error + xSupports(Op) bool + } + addOpt func(opt *withOpts) + withOpts struct { + bufsize int + op Op + noFollow bool + sendCreate bool + } ) + +var debug = func() bool { + // Check for exactly "1" (rather than mere existence) so we can add + // options/flags in the future. I don't know if we ever want that, but it's + // nice to leave the option open. + return os.Getenv("FSNOTIFY_DEBUG") == "1" +}() + +var defaultOpts = withOpts{ + bufsize: 65536, // 64K + op: Create | Write | Remove | Rename | Chmod, +} + +func getOptions(opts ...addOpt) withOpts { + with := defaultOpts + for _, o := range opts { + if o != nil { + o(&with) + } + } + return with +} + +// WithBufferSize sets the [ReadDirectoryChangesW] buffer size. +// +// This only has effect on Windows systems, and is a no-op for other backends. +// +// The default value is 64K (65536 bytes) which is the highest value that works +// on all filesystems and should be enough for most applications, but if you +// have a large burst of events it may not be enough. You can increase it if +// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]). +// +// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw +func WithBufferSize(bytes int) addOpt { + return func(opt *withOpts) { opt.bufsize = bytes } +} + +// WithOps sets which operations to listen for. The default is [Create], +// [Write], [Remove], [Rename], and [Chmod]. +// +// Excluding operations you're not interested in can save quite a bit of CPU +// time; in some use cases there may be hundreds of thousands of useless Write +// or Chmod operations per second. +// +// This can also be used to add unportable operations not supported by all +// platforms; unportable operations all start with "Unportable": +// [UnportableOpen], [UnportableRead], [UnportableCloseWrite], and +// [UnportableCloseRead]. +// +// AddWith returns an error when using an unportable operation that's not +// supported. Use [Watcher.Support] to check for support. +func withOps(op Op) addOpt { + return func(opt *withOpts) { opt.op = op } +} + +// WithNoFollow disables following symlinks, so the symlinks themselves are +// watched. +func withNoFollow() addOpt { + return func(opt *withOpts) { opt.noFollow = true } +} + +// "Internal" option for recursive watches on inotify. +func withCreate() addOpt { + return func(opt *withOpts) { opt.sendCreate = true } +} + +var enableRecurse = false + +// Check if this path is recursive (ends with "/..." or "\..."), and return the +// path with the /... stripped. +func recursivePath(path string) (string, bool) { + path = filepath.Clean(path) + if !enableRecurse { // Only enabled in tests for now. + return path, false + } + if filepath.Base(path) == "..." { + return filepath.Dir(path), true + } + return path, false +} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go b/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go deleted file mode 100644 index 596885598..000000000 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows -// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows - -package fsnotify - -import ( - "fmt" - "runtime" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct{} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - return nil -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - return nil -} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify.go b/vendor/github.com/fsnotify/fsnotify/inotify.go deleted file mode 100644 index a6d0e0ec8..000000000 --- a/vendor/github.com/fsnotify/fsnotify/inotify.go +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux -// +build linux - -package fsnotify - -import ( - "errors" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "sync" - "unsafe" - - "golang.org/x/sys/unix" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - mu sync.Mutex // Map access - fd int - poller *fdPoller - watches map[string]*watch // Map of inotify watches (key: path) - paths map[int]string // Map of watched paths (key: watch descriptor) - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - doneResp chan struct{} // Channel to respond to Close -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - // Create inotify fd - fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC) - if fd == -1 { - return nil, errno - } - // Create epoll - poller, err := newFdPoller(fd) - if err != nil { - unix.Close(fd) - return nil, err - } - w := &Watcher{ - fd: fd, - poller: poller, - watches: make(map[string]*watch), - paths: make(map[int]string), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), - doneResp: make(chan struct{}), - } - - go w.readEvents() - return w, nil -} - -func (w *Watcher) isClosed() bool { - select { - case <-w.done: - return true - default: - return false - } -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - if w.isClosed() { - return nil - } - - // Send 'close' signal to goroutine, and set the Watcher to closed. - close(w.done) - - // Wake up goroutine - w.poller.wake() - - // Wait for goroutine to close - <-w.doneResp - - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - name = filepath.Clean(name) - if w.isClosed() { - return errors.New("inotify instance already closed") - } - - const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | - unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | - unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF - - var flags uint32 = agnosticEvents - - w.mu.Lock() - defer w.mu.Unlock() - watchEntry := w.watches[name] - if watchEntry != nil { - flags |= watchEntry.flags | unix.IN_MASK_ADD - } - wd, errno := unix.InotifyAddWatch(w.fd, name, flags) - if wd == -1 { - return errno - } - - if watchEntry == nil { - w.watches[name] = &watch{wd: uint32(wd), flags: flags} - w.paths[wd] = name - } else { - watchEntry.wd = uint32(wd) - watchEntry.flags = flags - } - - return nil -} - -// Remove stops watching the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - - // Fetch the watch. - w.mu.Lock() - defer w.mu.Unlock() - watch, ok := w.watches[name] - - // Remove it from inotify. - if !ok { - return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) - } - - // We successfully removed the watch if InotifyRmWatch doesn't return an - // error, we need to clean up our internal state to ensure it matches - // inotify's kernel state. - delete(w.paths, int(watch.wd)) - delete(w.watches, name) - - // inotify_rm_watch will return EINVAL if the file has been deleted; - // the inotify will already have been removed. - // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously - // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE - // so that EINVAL means that the wd is being rm_watch()ed or its file removed - // by another thread and we have not received IN_IGNORE event. - success, errno := unix.InotifyRmWatch(w.fd, watch.wd) - if success == -1 { - // TODO: Perhaps it's not helpful to return an error here in every case. - // the only two possible errors are: - // EBADF, which happens when w.fd is not a valid file descriptor of any kind. - // EINVAL, which is when fd is not an inotify descriptor or wd is not a valid watch descriptor. - // Watch descriptors are invalidated when they are removed explicitly or implicitly; - // explicitly by inotify_rm_watch, implicitly when the file they are watching is deleted. - return errno - } - - return nil -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { - entries = append(entries, pathname) - } - - return entries -} - -type watch struct { - wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) - flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) -} - -// readEvents reads from the inotify file descriptor, converts the -// received events into Event objects and sends them via the Events channel -func (w *Watcher) readEvents() { - var ( - buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events - n int // Number of bytes read with read() - errno error // Syscall errno - ok bool // For poller.wait - ) - - defer close(w.doneResp) - defer close(w.Errors) - defer close(w.Events) - defer unix.Close(w.fd) - defer w.poller.close() - - for { - // See if we have been closed. - if w.isClosed() { - return - } - - ok, errno = w.poller.wait() - if errno != nil { - select { - case w.Errors <- errno: - case <-w.done: - return - } - continue - } - - if !ok { - continue - } - - n, errno = unix.Read(w.fd, buf[:]) - // If a signal interrupted execution, see if we've been asked to close, and try again. - // http://man7.org/linux/man-pages/man7/signal.7.html : - // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" - if errno == unix.EINTR { - continue - } - - // unix.Read might have been woken up by Close. If so, we're done. - if w.isClosed() { - return - } - - if n < unix.SizeofInotifyEvent { - var err error - if n == 0 { - // If EOF is received. This should really never happen. - err = io.EOF - } else if n < 0 { - // If an error occurred while reading. - err = errno - } else { - // Read was too short. - err = errors.New("notify: short read in readEvents()") - } - select { - case w.Errors <- err: - case <-w.done: - return - } - continue - } - - var offset uint32 - // We don't know how many events we just read into the buffer - // While the offset points to at least one whole event... - for offset <= uint32(n-unix.SizeofInotifyEvent) { - // Point "raw" to the event in the buffer - raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) - - mask := uint32(raw.Mask) - nameLen := uint32(raw.Len) - - if mask&unix.IN_Q_OVERFLOW != 0 { - select { - case w.Errors <- ErrEventOverflow: - case <-w.done: - return - } - } - - // If the event happened to the watched directory or the watched file, the kernel - // doesn't append the filename to the event, but we would like to always fill the - // the "Name" field with a valid filename. We retrieve the path of the watch from - // the "paths" map. - w.mu.Lock() - name, ok := w.paths[int(raw.Wd)] - // IN_DELETE_SELF occurs when the file/directory being watched is removed. - // This is a sign to clean up the maps, otherwise we are no longer in sync - // with the inotify kernel state which has already deleted the watch - // automatically. - if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { - delete(w.paths, int(raw.Wd)) - delete(w.watches, name) - } - w.mu.Unlock() - - if nameLen > 0 { - // Point "bytes" at the first byte of the filename - bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] - // The filename is padded with NULL bytes. TrimRight() gets rid of those. - name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") - } - - event := newEvent(name, mask) - - // Send the events that are not ignored on the events channel - if !event.ignoreLinux(mask) { - select { - case w.Events <- event: - case <-w.done: - return - } - } - - // Move to the next event in the buffer - offset += unix.SizeofInotifyEvent + nameLen - } - } -} - -// Certain types of events can be "ignored" and not sent over the Events -// channel. Such as events marked ignore by the kernel, or MODIFY events -// against files that do not exist. -func (e *Event) ignoreLinux(mask uint32) bool { - // Ignore anything the inotify API says to ignore - if mask&unix.IN_IGNORED == unix.IN_IGNORED { - return true - } - - // If the event is not a DELETE or RENAME, the file must exist. - // Otherwise the event is ignored. - // *Note*: this was put in place because it was seen that a MODIFY - // event was sent after the DELETE. This ignores that MODIFY and - // assumes a DELETE will come or has come if the file doesn't exist. - if !(e.Op&Remove == Remove || e.Op&Rename == Rename) { - _, statErr := os.Lstat(e.Name) - return os.IsNotExist(statErr) - } - return false -} - -// newEvent returns an platform-independent Event based on an inotify mask. -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { - e.Op |= Create - } - if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { - e.Op |= Remove - } - if mask&unix.IN_MODIFY == unix.IN_MODIFY { - e.Op |= Write - } - if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { - e.Op |= Rename - } - if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { - e.Op |= Chmod - } - return e -} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go deleted file mode 100644 index b572a37c3..000000000 --- a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux -// +build linux - -package fsnotify - -import ( - "errors" - - "golang.org/x/sys/unix" -) - -type fdPoller struct { - fd int // File descriptor (as returned by the inotify_init() syscall) - epfd int // Epoll file descriptor - pipe [2]int // Pipe for waking up -} - -func emptyPoller(fd int) *fdPoller { - poller := new(fdPoller) - poller.fd = fd - poller.epfd = -1 - poller.pipe[0] = -1 - poller.pipe[1] = -1 - return poller -} - -// Create a new inotify poller. -// This creates an inotify handler, and an epoll handler. -func newFdPoller(fd int) (*fdPoller, error) { - var errno error - poller := emptyPoller(fd) - defer func() { - if errno != nil { - poller.close() - } - }() - - // Create epoll fd - poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC) - if poller.epfd == -1 { - return nil, errno - } - // Create pipe; pipe[0] is the read end, pipe[1] the write end. - errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC) - if errno != nil { - return nil, errno - } - - // Register inotify fd with epoll - event := unix.EpollEvent{ - Fd: int32(poller.fd), - Events: unix.EPOLLIN, - } - errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event) - if errno != nil { - return nil, errno - } - - // Register pipe fd with epoll - event = unix.EpollEvent{ - Fd: int32(poller.pipe[0]), - Events: unix.EPOLLIN, - } - errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event) - if errno != nil { - return nil, errno - } - - return poller, nil -} - -// Wait using epoll. -// Returns true if something is ready to be read, -// false if there is not. -func (poller *fdPoller) wait() (bool, error) { - // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. - // I don't know whether epoll_wait returns the number of events returned, - // or the total number of events ready. - // I decided to catch both by making the buffer one larger than the maximum. - events := make([]unix.EpollEvent, 7) - for { - n, errno := unix.EpollWait(poller.epfd, events, -1) - if n == -1 { - if errno == unix.EINTR { - continue - } - return false, errno - } - if n == 0 { - // If there are no events, try again. - continue - } - if n > 6 { - // This should never happen. More events were returned than should be possible. - return false, errors.New("epoll_wait returned more events than I know what to do with") - } - ready := events[:n] - epollhup := false - epollerr := false - epollin := false - for _, event := range ready { - if event.Fd == int32(poller.fd) { - if event.Events&unix.EPOLLHUP != 0 { - // This should not happen, but if it does, treat it as a wakeup. - epollhup = true - } - if event.Events&unix.EPOLLERR != 0 { - // If an error is waiting on the file descriptor, we should pretend - // something is ready to read, and let unix.Read pick up the error. - epollerr = true - } - if event.Events&unix.EPOLLIN != 0 { - // There is data to read. - epollin = true - } - } - if event.Fd == int32(poller.pipe[0]) { - if event.Events&unix.EPOLLHUP != 0 { - // Write pipe descriptor was closed, by us. This means we're closing down the - // watcher, and we should wake up. - } - if event.Events&unix.EPOLLERR != 0 { - // If an error is waiting on the pipe file descriptor. - // This is an absolute mystery, and should never ever happen. - return false, errors.New("Error on the pipe descriptor.") - } - if event.Events&unix.EPOLLIN != 0 { - // This is a regular wakeup, so we have to clear the buffer. - err := poller.clearWake() - if err != nil { - return false, err - } - } - } - } - - if epollhup || epollerr || epollin { - return true, nil - } - return false, nil - } -} - -// Close the write end of the poller. -func (poller *fdPoller) wake() error { - buf := make([]byte, 1) - n, errno := unix.Write(poller.pipe[1], buf) - if n == -1 { - if errno == unix.EAGAIN { - // Buffer is full, poller will wake. - return nil - } - return errno - } - return nil -} - -func (poller *fdPoller) clearWake() error { - // You have to be woken up a LOT in order to get to 100! - buf := make([]byte, 100) - n, errno := unix.Read(poller.pipe[0], buf) - if n == -1 { - if errno == unix.EAGAIN { - // Buffer is empty, someone else cleared our wake. - return nil - } - return errno - } - return nil -} - -// Close all poller file descriptors, but not the one passed to it. -func (poller *fdPoller) close() { - if poller.pipe[1] != -1 { - unix.Close(poller.pipe[1]) - } - if poller.pipe[0] != -1 { - unix.Close(poller.pipe[0]) - } - if poller.epfd != -1 { - unix.Close(poller.epfd) - } -} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/darwin.go b/vendor/github.com/fsnotify/fsnotify/internal/darwin.go new file mode 100644 index 000000000..b0eab1009 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/darwin.go @@ -0,0 +1,39 @@ +//go:build darwin + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +// Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ +func SetRlimit() { + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = l.Cur + + if n, err := syscall.SysctlUint32("kern.maxfiles"); err == nil && uint64(n) < maxfiles { + maxfiles = uint64(n) + } + + if n, err := syscall.SysctlUint32("kern.maxfilesperproc"); err == nil && uint64(n) < maxfiles { + maxfiles = uint64(n) + } +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go new file mode 100644 index 000000000..928319fb0 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_darwin.go @@ -0,0 +1,57 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ABSOLUTE", unix.NOTE_ABSOLUTE}, + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_BACKGROUND", unix.NOTE_BACKGROUND}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_CRITICAL", unix.NOTE_CRITICAL}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXITSTATUS", unix.NOTE_EXITSTATUS}, + {"NOTE_EXIT_CSERROR", unix.NOTE_EXIT_CSERROR}, + {"NOTE_EXIT_DECRYPTFAIL", unix.NOTE_EXIT_DECRYPTFAIL}, + {"NOTE_EXIT_DETAIL", unix.NOTE_EXIT_DETAIL}, + {"NOTE_EXIT_DETAIL_MASK", unix.NOTE_EXIT_DETAIL_MASK}, + {"NOTE_EXIT_MEMORY", unix.NOTE_EXIT_MEMORY}, + {"NOTE_EXIT_REPARENTED", unix.NOTE_EXIT_REPARENTED}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_FUNLOCK", unix.NOTE_FUNLOCK}, + {"NOTE_LEEWAY", unix.NOTE_LEEWAY}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_MACHTIME", unix.NOTE_MACHTIME}, + {"NOTE_MACH_CONTINUOUS_TIME", unix.NOTE_MACH_CONTINUOUS_TIME}, + {"NOTE_NONE", unix.NOTE_NONE}, + {"NOTE_NSECONDS", unix.NOTE_NSECONDS}, + {"NOTE_OOB", unix.NOTE_OOB}, + //{"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, -0x100000 (?!) + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_REAP", unix.NOTE_REAP}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_SECONDS", unix.NOTE_SECONDS}, + {"NOTE_SIGNAL", unix.NOTE_SIGNAL}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_USECONDS", unix.NOTE_USECONDS}, + {"NOTE_VM_ERROR", unix.NOTE_VM_ERROR}, + {"NOTE_VM_PRESSURE", unix.NOTE_VM_PRESSURE}, + {"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", unix.NOTE_VM_PRESSURE_SUDDEN_TERMINATE}, + {"NOTE_VM_PRESSURE_TERMINATE", unix.NOTE_VM_PRESSURE_TERMINATE}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go new file mode 100644 index 000000000..3186b0c34 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_dragonfly.go @@ -0,0 +1,33 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_OOB", unix.NOTE_OOB}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go new file mode 100644 index 000000000..f69fdb930 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_freebsd.go @@ -0,0 +1,42 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ABSTIME", unix.NOTE_ABSTIME}, + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_CLOSE", unix.NOTE_CLOSE}, + {"NOTE_CLOSE_WRITE", unix.NOTE_CLOSE_WRITE}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FFAND", unix.NOTE_FFAND}, + {"NOTE_FFCOPY", unix.NOTE_FFCOPY}, + {"NOTE_FFCTRLMASK", unix.NOTE_FFCTRLMASK}, + {"NOTE_FFLAGSMASK", unix.NOTE_FFLAGSMASK}, + {"NOTE_FFNOP", unix.NOTE_FFNOP}, + {"NOTE_FFOR", unix.NOTE_FFOR}, + {"NOTE_FILE_POLL", unix.NOTE_FILE_POLL}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_MSECONDS", unix.NOTE_MSECONDS}, + {"NOTE_NSECONDS", unix.NOTE_NSECONDS}, + {"NOTE_OPEN", unix.NOTE_OPEN}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_READ", unix.NOTE_READ}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_SECONDS", unix.NOTE_SECONDS}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRIGGER", unix.NOTE_TRIGGER}, + {"NOTE_USECONDS", unix.NOTE_USECONDS}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go new file mode 100644 index 000000000..607e683bd --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_kqueue.go @@ -0,0 +1,32 @@ +//go:build freebsd || openbsd || netbsd || dragonfly || darwin + +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, kevent *unix.Kevent_t) { + mask := uint32(kevent.Fflags) + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-60s → %q\n", + time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go new file mode 100644 index 000000000..35c734be4 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_linux.go @@ -0,0 +1,56 @@ +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, mask, cookie uint32) { + names := []struct { + n string + m uint32 + }{ + {"IN_ACCESS", unix.IN_ACCESS}, + {"IN_ATTRIB", unix.IN_ATTRIB}, + {"IN_CLOSE", unix.IN_CLOSE}, + {"IN_CLOSE_NOWRITE", unix.IN_CLOSE_NOWRITE}, + {"IN_CLOSE_WRITE", unix.IN_CLOSE_WRITE}, + {"IN_CREATE", unix.IN_CREATE}, + {"IN_DELETE", unix.IN_DELETE}, + {"IN_DELETE_SELF", unix.IN_DELETE_SELF}, + {"IN_IGNORED", unix.IN_IGNORED}, + {"IN_ISDIR", unix.IN_ISDIR}, + {"IN_MODIFY", unix.IN_MODIFY}, + {"IN_MOVE", unix.IN_MOVE}, + {"IN_MOVED_FROM", unix.IN_MOVED_FROM}, + {"IN_MOVED_TO", unix.IN_MOVED_TO}, + {"IN_MOVE_SELF", unix.IN_MOVE_SELF}, + {"IN_OPEN", unix.IN_OPEN}, + {"IN_Q_OVERFLOW", unix.IN_Q_OVERFLOW}, + {"IN_UNMOUNT", unix.IN_UNMOUNT}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + var c string + if cookie > 0 { + c = fmt.Sprintf("(cookie: %d) ", cookie) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-30s → %s%q\n", + time.Now().Format("15:04:05.000000000"), strings.Join(l, "|"), c, name) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go new file mode 100644 index 000000000..e5b3b6f69 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_netbsd.go @@ -0,0 +1,25 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go new file mode 100644 index 000000000..1dd455bc5 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_openbsd.go @@ -0,0 +1,28 @@ +package internal + +import "golang.org/x/sys/unix" + +var names = []struct { + n string + m uint32 +}{ + {"NOTE_ATTRIB", unix.NOTE_ATTRIB}, + // {"NOTE_CHANGE", unix.NOTE_CHANGE}, // Not on 386? + {"NOTE_CHILD", unix.NOTE_CHILD}, + {"NOTE_DELETE", unix.NOTE_DELETE}, + {"NOTE_EOF", unix.NOTE_EOF}, + {"NOTE_EXEC", unix.NOTE_EXEC}, + {"NOTE_EXIT", unix.NOTE_EXIT}, + {"NOTE_EXTEND", unix.NOTE_EXTEND}, + {"NOTE_FORK", unix.NOTE_FORK}, + {"NOTE_LINK", unix.NOTE_LINK}, + {"NOTE_LOWAT", unix.NOTE_LOWAT}, + {"NOTE_PCTRLMASK", unix.NOTE_PCTRLMASK}, + {"NOTE_PDATAMASK", unix.NOTE_PDATAMASK}, + {"NOTE_RENAME", unix.NOTE_RENAME}, + {"NOTE_REVOKE", unix.NOTE_REVOKE}, + {"NOTE_TRACK", unix.NOTE_TRACK}, + {"NOTE_TRACKERR", unix.NOTE_TRACKERR}, + {"NOTE_TRUNCATE", unix.NOTE_TRUNCATE}, + {"NOTE_WRITE", unix.NOTE_WRITE}, +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go new file mode 100644 index 000000000..f1b2e73bd --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_solaris.go @@ -0,0 +1,45 @@ +package internal + +import ( + "fmt" + "os" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +func Debug(name string, mask int32) { + names := []struct { + n string + m int32 + }{ + {"FILE_ACCESS", unix.FILE_ACCESS}, + {"FILE_MODIFIED", unix.FILE_MODIFIED}, + {"FILE_ATTRIB", unix.FILE_ATTRIB}, + {"FILE_TRUNC", unix.FILE_TRUNC}, + {"FILE_NOFOLLOW", unix.FILE_NOFOLLOW}, + {"FILE_DELETE", unix.FILE_DELETE}, + {"FILE_RENAME_TO", unix.FILE_RENAME_TO}, + {"FILE_RENAME_FROM", unix.FILE_RENAME_FROM}, + {"UNMOUNTED", unix.UNMOUNTED}, + {"MOUNTEDOVER", unix.MOUNTEDOVER}, + {"FILE_EXCEPTION", unix.FILE_EXCEPTION}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %10d:%-30s → %q\n", + time.Now().Format("15:04:05.000000000"), mask, strings.Join(l, " | "), name) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go b/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go new file mode 100644 index 000000000..52bf4ce53 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/debug_windows.go @@ -0,0 +1,40 @@ +package internal + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/sys/windows" +) + +func Debug(name string, mask uint32) { + names := []struct { + n string + m uint32 + }{ + {"FILE_ACTION_ADDED", windows.FILE_ACTION_ADDED}, + {"FILE_ACTION_REMOVED", windows.FILE_ACTION_REMOVED}, + {"FILE_ACTION_MODIFIED", windows.FILE_ACTION_MODIFIED}, + {"FILE_ACTION_RENAMED_OLD_NAME", windows.FILE_ACTION_RENAMED_OLD_NAME}, + {"FILE_ACTION_RENAMED_NEW_NAME", windows.FILE_ACTION_RENAMED_NEW_NAME}, + } + + var ( + l []string + unknown = mask + ) + for _, n := range names { + if mask&n.m == n.m { + l = append(l, n.n) + unknown ^= n.m + } + } + if unknown > 0 { + l = append(l, fmt.Sprintf("0x%x", unknown)) + } + fmt.Fprintf(os.Stderr, "FSNOTIFY_DEBUG: %s %-65s → %q\n", + time.Now().Format("15:04:05.000000000"), strings.Join(l, " | "), filepath.ToSlash(name)) +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go b/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go new file mode 100644 index 000000000..547df1df8 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/freebsd.go @@ -0,0 +1,31 @@ +//go:build freebsd + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +func SetRlimit() { + // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = uint64(l.Cur) +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, uint64(dev)) } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/internal.go b/vendor/github.com/fsnotify/fsnotify/internal/internal.go new file mode 100644 index 000000000..7daa45e19 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/internal.go @@ -0,0 +1,2 @@ +// Package internal contains some helpers. +package internal diff --git a/vendor/github.com/fsnotify/fsnotify/internal/unix.go b/vendor/github.com/fsnotify/fsnotify/internal/unix.go new file mode 100644 index 000000000..30976ce97 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/unix.go @@ -0,0 +1,31 @@ +//go:build !windows && !darwin && !freebsd + +package internal + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +var ( + SyscallEACCES = syscall.EACCES + UnixEACCES = unix.EACCES +) + +var maxfiles uint64 + +func SetRlimit() { + // Go 1.19 will do this automatically: https://go-review.googlesource.com/c/go/+/393354/ + var l syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) + if err == nil && l.Cur != l.Max { + l.Cur = l.Max + syscall.Setrlimit(syscall.RLIMIT_NOFILE, &l) + } + maxfiles = uint64(l.Cur) +} + +func Maxfiles() uint64 { return maxfiles } +func Mkfifo(path string, mode uint32) error { return unix.Mkfifo(path, mode) } +func Mknod(path string, mode uint32, dev int) error { return unix.Mknod(path, mode, dev) } diff --git a/vendor/github.com/fsnotify/fsnotify/internal/unix2.go b/vendor/github.com/fsnotify/fsnotify/internal/unix2.go new file mode 100644 index 000000000..37dfeddc2 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/unix2.go @@ -0,0 +1,7 @@ +//go:build !windows + +package internal + +func HasPrivilegesForSymlink() bool { + return true +} diff --git a/vendor/github.com/fsnotify/fsnotify/internal/windows.go b/vendor/github.com/fsnotify/fsnotify/internal/windows.go new file mode 100644 index 000000000..a72c64954 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/internal/windows.go @@ -0,0 +1,41 @@ +//go:build windows + +package internal + +import ( + "errors" + + "golang.org/x/sys/windows" +) + +// Just a dummy. +var ( + SyscallEACCES = errors.New("dummy") + UnixEACCES = errors.New("dummy") +) + +func SetRlimit() {} +func Maxfiles() uint64 { return 1<<64 - 1 } +func Mkfifo(path string, mode uint32) error { return errors.New("no FIFOs on Windows") } +func Mknod(path string, mode uint32, dev int) error { return errors.New("no device nodes on Windows") } + +func HasPrivilegesForSymlink() bool { + var sid *windows.SID + err := windows.AllocateAndInitializeSid( + &windows.SECURITY_NT_AUTHORITY, + 2, + windows.SECURITY_BUILTIN_DOMAIN_RID, + windows.DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &sid) + if err != nil { + return false + } + defer windows.FreeSid(sid) + token := windows.Token(0) + member, err := token.IsMember(sid) + if err != nil { + return false + } + return member || token.IsElevated() +} diff --git a/vendor/github.com/fsnotify/fsnotify/kqueue.go b/vendor/github.com/fsnotify/fsnotify/kqueue.go deleted file mode 100644 index 6fb8d8532..000000000 --- a/vendor/github.com/fsnotify/fsnotify/kqueue.go +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd || dragonfly || darwin -// +build freebsd openbsd netbsd dragonfly darwin - -package fsnotify - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sync" - "time" - - "golang.org/x/sys/unix" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - - kq int // File descriptor (as returned by the kqueue() syscall). - - mu sync.Mutex // Protects access to watcher data - watches map[string]int // Map of watched file descriptors (key: path). - externalWatches map[string]bool // Map of watches added by user of the library. - dirFlags map[string]uint32 // Map of watched directories to fflags used in kqueue. - paths map[int]pathInfo // Map file descriptors to path names for processing kqueue events. - fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events). - isClosed bool // Set to true when Close() is first called -} - -type pathInfo struct { - name string - isDir bool -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - kq, err := kqueue() - if err != nil { - return nil, err - } - - w := &Watcher{ - kq: kq, - watches: make(map[string]int), - dirFlags: make(map[string]uint32), - paths: make(map[int]pathInfo), - fileExists: make(map[string]bool), - externalWatches: make(map[string]bool), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), - } - - go w.readEvents() - return w, nil -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return nil - } - w.isClosed = true - - // copy paths to remove while locked - var pathsToRemove = make([]string, 0, len(w.watches)) - for name := range w.watches { - pathsToRemove = append(pathsToRemove, name) - } - w.mu.Unlock() - // unlock before calling Remove, which also locks - - for _, name := range pathsToRemove { - w.Remove(name) - } - - // send a "quit" message to the reader goroutine - close(w.done) - - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - w.mu.Lock() - w.externalWatches[name] = true - w.mu.Unlock() - _, err := w.addWatch(name, noteAllEvents) - return err -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - w.mu.Lock() - watchfd, ok := w.watches[name] - w.mu.Unlock() - if !ok { - return fmt.Errorf("can't remove non-existent kevent watch for: %s", name) - } - - const registerRemove = unix.EV_DELETE - if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil { - return err - } - - unix.Close(watchfd) - - w.mu.Lock() - isDir := w.paths[watchfd].isDir - delete(w.watches, name) - delete(w.paths, watchfd) - delete(w.dirFlags, name) - w.mu.Unlock() - - // Find all watched paths that are in this directory that are not external. - if isDir { - var pathsToRemove []string - w.mu.Lock() - for _, path := range w.paths { - wdir, _ := filepath.Split(path.name) - if filepath.Clean(wdir) == name { - if !w.externalWatches[path.name] { - pathsToRemove = append(pathsToRemove, path.name) - } - } - } - w.mu.Unlock() - for _, name := range pathsToRemove { - // Since these are internal, not much sense in propagating error - // to the user, as that will just confuse them with an error about - // a path they did not explicitly watch themselves. - w.Remove(name) - } - } - - return nil -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { - entries = append(entries, pathname) - } - - return entries -} - -// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) -const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME - -// keventWaitTime to block on each read from kevent -var keventWaitTime = durationToTimespec(100 * time.Millisecond) - -// addWatch adds name to the watched file set. -// The flags are interpreted as described in kevent(2). -// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. -func (w *Watcher) addWatch(name string, flags uint32) (string, error) { - var isDir bool - // Make ./name and name equivalent - name = filepath.Clean(name) - - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return "", errors.New("kevent instance already closed") - } - watchfd, alreadyWatching := w.watches[name] - // We already have a watch, but we can still override flags. - if alreadyWatching { - isDir = w.paths[watchfd].isDir - } - w.mu.Unlock() - - if !alreadyWatching { - fi, err := os.Lstat(name) - if err != nil { - return "", err - } - - // Don't watch sockets. - if fi.Mode()&os.ModeSocket == os.ModeSocket { - return "", nil - } - - // Don't watch named pipes. - if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { - return "", nil - } - - // Follow Symlinks - // Unfortunately, Linux can add bogus symlinks to watch list without - // issue, and Windows can't do symlinks period (AFAIK). To maintain - // consistency, we will act like everything is fine. There will simply - // be no file events for broken symlinks. - // Hence the returns of nil on errors. - if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - name, err = filepath.EvalSymlinks(name) - if err != nil { - return "", nil - } - - w.mu.Lock() - _, alreadyWatching = w.watches[name] - w.mu.Unlock() - - if alreadyWatching { - return name, nil - } - - fi, err = os.Lstat(name) - if err != nil { - return "", nil - } - } - - watchfd, err = unix.Open(name, openMode, 0700) - if watchfd == -1 { - return "", err - } - - isDir = fi.IsDir() - } - - const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE - if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { - unix.Close(watchfd) - return "", err - } - - if !alreadyWatching { - w.mu.Lock() - w.watches[name] = watchfd - w.paths[watchfd] = pathInfo{name: name, isDir: isDir} - w.mu.Unlock() - } - - if isDir { - // Watch the directory if it has not been watched before, - // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) - w.mu.Lock() - - watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && - (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) - // Store flags so this watch can be updated later - w.dirFlags[name] = flags - w.mu.Unlock() - - if watchDir { - if err := w.watchDirectoryFiles(name); err != nil { - return "", err - } - } - } - return name, nil -} - -// readEvents reads from kqueue and converts the received kevents into -// Event values that it sends down the Events channel. -func (w *Watcher) readEvents() { - eventBuffer := make([]unix.Kevent_t, 10) - -loop: - for { - // See if there is a message on the "done" channel - select { - case <-w.done: - break loop - default: - } - - // Get new events - kevents, err := read(w.kq, eventBuffer, &keventWaitTime) - // EINTR is okay, the syscall was interrupted before timeout expired. - if err != nil && err != unix.EINTR { - select { - case w.Errors <- err: - case <-w.done: - break loop - } - continue - } - - // Flush the events we received to the Events channel - for len(kevents) > 0 { - kevent := &kevents[0] - watchfd := int(kevent.Ident) - mask := uint32(kevent.Fflags) - w.mu.Lock() - path := w.paths[watchfd] - w.mu.Unlock() - event := newEvent(path.name, mask) - - if path.isDir && !(event.Op&Remove == Remove) { - // Double check to make sure the directory exists. This can happen when - // we do a rm -fr on a recursively watched folders and we receive a - // modification event first but the folder has been deleted and later - // receive the delete event - if _, err := os.Lstat(event.Name); os.IsNotExist(err) { - // mark is as delete event - event.Op |= Remove - } - } - - if event.Op&Rename == Rename || event.Op&Remove == Remove { - w.Remove(event.Name) - w.mu.Lock() - delete(w.fileExists, event.Name) - w.mu.Unlock() - } - - if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) { - w.sendDirectoryChangeEvents(event.Name) - } else { - // Send the event on the Events channel. - select { - case w.Events <- event: - case <-w.done: - break loop - } - } - - if event.Op&Remove == Remove { - // Look for a file that may have overwritten this. - // For example, mv f1 f2 will delete f2, then create f2. - if path.isDir { - fileDir := filepath.Clean(event.Name) - w.mu.Lock() - _, found := w.watches[fileDir] - w.mu.Unlock() - if found { - // make sure the directory exists before we watch for changes. When we - // do a recursive watch and perform rm -fr, the parent directory might - // have gone missing, ignore the missing directory and let the - // upcoming delete event remove the watch from the parent directory. - if _, err := os.Lstat(fileDir); err == nil { - w.sendDirectoryChangeEvents(fileDir) - } - } - } else { - filePath := filepath.Clean(event.Name) - if fileInfo, err := os.Lstat(filePath); err == nil { - w.sendFileCreatedEventIfNew(filePath, fileInfo) - } - } - } - - // Move to next event - kevents = kevents[1:] - } - } - - // cleanup - err := unix.Close(w.kq) - if err != nil { - // only way the previous loop breaks is if w.done was closed so we need to async send to w.Errors. - select { - case w.Errors <- err: - default: - } - } - close(w.Events) - close(w.Errors) -} - -// newEvent returns an platform-independent Event based on kqueue Fflags. -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { - e.Op |= Remove - } - if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { - e.Op |= Write - } - if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { - e.Op |= Rename - } - if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { - e.Op |= Chmod - } - return e -} - -func newCreateEvent(name string) Event { - return Event{Name: name, Op: Create} -} - -// watchDirectoryFiles to mimic inotify when adding a watch on a directory -func (w *Watcher) watchDirectoryFiles(dirPath string) error { - // Get all files - files, err := ioutil.ReadDir(dirPath) - if err != nil { - return err - } - - for _, fileInfo := range files { - filePath := filepath.Join(dirPath, fileInfo.Name()) - filePath, err = w.internalWatch(filePath, fileInfo) - if err != nil { - return err - } - - w.mu.Lock() - w.fileExists[filePath] = true - w.mu.Unlock() - } - - return nil -} - -// sendDirectoryEvents searches the directory for newly created files -// and sends them over the event channel. This functionality is to have -// the BSD version of fsnotify match Linux inotify which provides a -// create event for files created in a watched directory. -func (w *Watcher) sendDirectoryChangeEvents(dirPath string) { - // Get all files - files, err := ioutil.ReadDir(dirPath) - if err != nil { - select { - case w.Errors <- err: - case <-w.done: - return - } - } - - // Search for new files - for _, fileInfo := range files { - filePath := filepath.Join(dirPath, fileInfo.Name()) - err := w.sendFileCreatedEventIfNew(filePath, fileInfo) - - if err != nil { - return - } - } -} - -// sendFileCreatedEvent sends a create event if the file isn't already being tracked. -func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { - w.mu.Lock() - _, doesExist := w.fileExists[filePath] - w.mu.Unlock() - if !doesExist { - // Send create event - select { - case w.Events <- newCreateEvent(filePath): - case <-w.done: - return - } - } - - // like watchDirectoryFiles (but without doing another ReadDir) - filePath, err = w.internalWatch(filePath, fileInfo) - if err != nil { - return err - } - - w.mu.Lock() - w.fileExists[filePath] = true - w.mu.Unlock() - - return nil -} - -func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { - if fileInfo.IsDir() { - // mimic Linux providing delete events for subdirectories - // but preserve the flags used if currently watching subdirectory - w.mu.Lock() - flags := w.dirFlags[name] - w.mu.Unlock() - - flags |= unix.NOTE_DELETE | unix.NOTE_RENAME - return w.addWatch(name, flags) - } - - // watch file to mimic Linux inotify - return w.addWatch(name, noteAllEvents) -} - -// kqueue creates a new kernel event queue and returns a descriptor. -func kqueue() (kq int, err error) { - kq, err = unix.Kqueue() - if kq == -1 { - return kq, err - } - return kq, nil -} - -// register events with the queue -func register(kq int, fds []int, flags int, fflags uint32) error { - changes := make([]unix.Kevent_t, len(fds)) - - for i, fd := range fds { - // SetKevent converts int to the platform-specific types: - unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) - changes[i].Fflags = fflags - } - - // register the events - success, err := unix.Kevent(kq, changes, nil, nil) - if success == -1 { - return err - } - return nil -} - -// read retrieves pending events, or waits until an event occurs. -// A timeout of nil blocks indefinitely, while 0 polls the queue. -func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]unix.Kevent_t, error) { - n, err := unix.Kevent(kq, nil, events, timeout) - if err != nil { - return nil, err - } - return events[0:n], nil -} - -// durationToTimespec prepares a timeout value -func durationToTimespec(d time.Duration) unix.Timespec { - return unix.NsecToTimespec(d.Nanoseconds()) -} diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go deleted file mode 100644 index 36cc3845b..000000000 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd || dragonfly -// +build freebsd openbsd netbsd dragonfly - -package fsnotify - -import "golang.org/x/sys/unix" - -const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go deleted file mode 100644 index 98cd8476f..000000000 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin -// +build darwin - -package fsnotify - -import "golang.org/x/sys/unix" - -// note: this constant is not defined on BSD -const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/vendor/github.com/fsnotify/fsnotify/system_bsd.go new file mode 100644 index 000000000..f65e8fe3e --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/system_bsd.go @@ -0,0 +1,7 @@ +//go:build freebsd || openbsd || netbsd || dragonfly + +package fsnotify + +import "golang.org/x/sys/unix" + +const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/vendor/github.com/fsnotify/fsnotify/system_darwin.go new file mode 100644 index 000000000..a29fc7aab --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/system_darwin.go @@ -0,0 +1,8 @@ +//go:build darwin + +package fsnotify + +import "golang.org/x/sys/unix" + +// note: this constant is not defined on BSD +const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/windows.go b/vendor/github.com/fsnotify/fsnotify/windows.go deleted file mode 100644 index 02ce7deb0..000000000 --- a/vendor/github.com/fsnotify/fsnotify/windows.go +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -package fsnotify - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "reflect" - "runtime" - "sync" - "syscall" - "unsafe" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - isClosed bool // Set to true when Close() is first called - mu sync.Mutex // Map access - port syscall.Handle // Handle to completion port - watches watchMap // Map of watches (key: i-number) - input chan *input // Inputs to the reader are sent on this channel - quit chan chan<- error -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) - if e != nil { - return nil, os.NewSyscallError("CreateIoCompletionPort", e) - } - w := &Watcher{ - port: port, - watches: make(watchMap), - input: make(chan *input, 1), - Events: make(chan Event, 50), - Errors: make(chan error), - quit: make(chan chan<- error, 1), - } - go w.readEvents() - return w, nil -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - if w.isClosed { - return nil - } - w.isClosed = true - - // Send "quit" message to the reader goroutine - ch := make(chan error) - w.quit <- ch - if err := w.wakeupReader(); err != nil { - return err - } - return <-ch -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - if w.isClosed { - return errors.New("watcher already closed") - } - in := &input{ - op: opAddWatch, - path: filepath.Clean(name), - flags: sysFSALLEVENTS, - reply: make(chan error), - } - w.input <- in - if err := w.wakeupReader(); err != nil { - return err - } - return <-in.reply -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - in := &input{ - op: opRemoveWatch, - path: filepath.Clean(name), - reply: make(chan error), - } - w.input <- in - if err := w.wakeupReader(); err != nil { - return err - } - return <-in.reply -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for _, entry := range w.watches { - for _, watchEntry := range entry { - entries = append(entries, watchEntry.path) - } - } - - return entries -} - -const ( - // Options for AddWatch - sysFSONESHOT = 0x80000000 - sysFSONLYDIR = 0x1000000 - - // Events - sysFSACCESS = 0x1 - sysFSALLEVENTS = 0xfff - sysFSATTRIB = 0x4 - sysFSCLOSE = 0x18 - sysFSCREATE = 0x100 - sysFSDELETE = 0x200 - sysFSDELETESELF = 0x400 - sysFSMODIFY = 0x2 - sysFSMOVE = 0xc0 - sysFSMOVEDFROM = 0x40 - sysFSMOVEDTO = 0x80 - sysFSMOVESELF = 0x800 - - // Special events - sysFSIGNORED = 0x8000 - sysFSQOVERFLOW = 0x4000 -) - -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { - e.Op |= Create - } - if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { - e.Op |= Remove - } - if mask&sysFSMODIFY == sysFSMODIFY { - e.Op |= Write - } - if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { - e.Op |= Rename - } - if mask&sysFSATTRIB == sysFSATTRIB { - e.Op |= Chmod - } - return e -} - -const ( - opAddWatch = iota - opRemoveWatch -) - -const ( - provisional uint64 = 1 << (32 + iota) -) - -type input struct { - op int - path string - flags uint32 - reply chan error -} - -type inode struct { - handle syscall.Handle - volume uint32 - index uint64 -} - -type watch struct { - ov syscall.Overlapped - ino *inode // i-number - path string // Directory path - mask uint64 // Directory itself is being watched with these notify flags - names map[string]uint64 // Map of names being watched and their notify flags - rename string // Remembers the old name while renaming a file - buf [4096]byte -} - -type indexMap map[uint64]*watch -type watchMap map[uint32]indexMap - -func (w *Watcher) wakeupReader() error { - e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) - if e != nil { - return os.NewSyscallError("PostQueuedCompletionStatus", e) - } - return nil -} - -func getDir(pathname string) (dir string, err error) { - attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) - if e != nil { - return "", os.NewSyscallError("GetFileAttributes", e) - } - if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - dir = pathname - } else { - dir, _ = filepath.Split(pathname) - dir = filepath.Clean(dir) - } - return -} - -func getIno(path string) (ino *inode, err error) { - h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path), - syscall.FILE_LIST_DIRECTORY, - syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, - nil, syscall.OPEN_EXISTING, - syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) - if e != nil { - return nil, os.NewSyscallError("CreateFile", e) - } - var fi syscall.ByHandleFileInformation - if e = syscall.GetFileInformationByHandle(h, &fi); e != nil { - syscall.CloseHandle(h) - return nil, os.NewSyscallError("GetFileInformationByHandle", e) - } - ino = &inode{ - handle: h, - volume: fi.VolumeSerialNumber, - index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), - } - return ino, nil -} - -// Must run within the I/O thread. -func (m watchMap) get(ino *inode) *watch { - if i := m[ino.volume]; i != nil { - return i[ino.index] - } - return nil -} - -// Must run within the I/O thread. -func (m watchMap) set(ino *inode, watch *watch) { - i := m[ino.volume] - if i == nil { - i = make(indexMap) - m[ino.volume] = i - } - i[ino.index] = watch -} - -// Must run within the I/O thread. -func (w *Watcher) addWatch(pathname string, flags uint64) error { - dir, err := getDir(pathname) - if err != nil { - return err - } - if flags&sysFSONLYDIR != 0 && pathname != dir { - return nil - } - ino, err := getIno(dir) - if err != nil { - return err - } - w.mu.Lock() - watchEntry := w.watches.get(ino) - w.mu.Unlock() - if watchEntry == nil { - if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { - syscall.CloseHandle(ino.handle) - return os.NewSyscallError("CreateIoCompletionPort", e) - } - watchEntry = &watch{ - ino: ino, - path: dir, - names: make(map[string]uint64), - } - w.mu.Lock() - w.watches.set(ino, watchEntry) - w.mu.Unlock() - flags |= provisional - } else { - syscall.CloseHandle(ino.handle) - } - if pathname == dir { - watchEntry.mask |= flags - } else { - watchEntry.names[filepath.Base(pathname)] |= flags - } - if err = w.startRead(watchEntry); err != nil { - return err - } - if pathname == dir { - watchEntry.mask &= ^provisional - } else { - watchEntry.names[filepath.Base(pathname)] &= ^provisional - } - return nil -} - -// Must run within the I/O thread. -func (w *Watcher) remWatch(pathname string) error { - dir, err := getDir(pathname) - if err != nil { - return err - } - ino, err := getIno(dir) - if err != nil { - return err - } - w.mu.Lock() - watch := w.watches.get(ino) - w.mu.Unlock() - if watch == nil { - return fmt.Errorf("can't remove non-existent watch for: %s", pathname) - } - if pathname == dir { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) - watch.mask = 0 - } else { - name := filepath.Base(pathname) - w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) - delete(watch.names, name) - } - return w.startRead(watch) -} - -// Must run within the I/O thread. -func (w *Watcher) deleteWatch(watch *watch) { - for name, mask := range watch.names { - if mask&provisional == 0 { - w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) - } - delete(watch.names, name) - } - if watch.mask != 0 { - if watch.mask&provisional == 0 { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) - } - watch.mask = 0 - } -} - -// Must run within the I/O thread. -func (w *Watcher) startRead(watch *watch) error { - if e := syscall.CancelIo(watch.ino.handle); e != nil { - w.Errors <- os.NewSyscallError("CancelIo", e) - w.deleteWatch(watch) - } - mask := toWindowsFlags(watch.mask) - for _, m := range watch.names { - mask |= toWindowsFlags(m) - } - if mask == 0 { - if e := syscall.CloseHandle(watch.ino.handle); e != nil { - w.Errors <- os.NewSyscallError("CloseHandle", e) - } - w.mu.Lock() - delete(w.watches[watch.ino.volume], watch.ino.index) - w.mu.Unlock() - return nil - } - e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], - uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) - if e != nil { - err := os.NewSyscallError("ReadDirectoryChanges", e) - if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { - // Watched directory was probably removed - if w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) { - if watch.mask&sysFSONESHOT != 0 { - watch.mask = 0 - } - } - err = nil - } - w.deleteWatch(watch) - w.startRead(watch) - return err - } - return nil -} - -// readEvents reads from the I/O completion port, converts the -// received events into Event objects and sends them via the Events channel. -// Entry point to the I/O thread. -func (w *Watcher) readEvents() { - var ( - n, key uint32 - ov *syscall.Overlapped - ) - runtime.LockOSThread() - - for { - e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE) - watch := (*watch)(unsafe.Pointer(ov)) - - if watch == nil { - select { - case ch := <-w.quit: - w.mu.Lock() - var indexes []indexMap - for _, index := range w.watches { - indexes = append(indexes, index) - } - w.mu.Unlock() - for _, index := range indexes { - for _, watch := range index { - w.deleteWatch(watch) - w.startRead(watch) - } - } - var err error - if e := syscall.CloseHandle(w.port); e != nil { - err = os.NewSyscallError("CloseHandle", e) - } - close(w.Events) - close(w.Errors) - ch <- err - return - case in := <-w.input: - switch in.op { - case opAddWatch: - in.reply <- w.addWatch(in.path, uint64(in.flags)) - case opRemoveWatch: - in.reply <- w.remWatch(in.path) - } - default: - } - continue - } - - switch e { - case syscall.ERROR_MORE_DATA: - if watch == nil { - w.Errors <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer") - } else { - // The i/o succeeded but the buffer is full. - // In theory we should be building up a full packet. - // In practice we can get away with just carrying on. - n = uint32(unsafe.Sizeof(watch.buf)) - } - case syscall.ERROR_ACCESS_DENIED: - // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) - w.deleteWatch(watch) - w.startRead(watch) - continue - case syscall.ERROR_OPERATION_ABORTED: - // CancelIo was called on this handle - continue - default: - w.Errors <- os.NewSyscallError("GetQueuedCompletionPort", e) - continue - case nil: - } - - var offset uint32 - for { - if n == 0 { - w.Events <- newEvent("", sysFSQOVERFLOW) - w.Errors <- errors.New("short read in readEvents()") - break - } - - // Point "raw" to the event in the buffer - raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) - // TODO: Consider using unsafe.Slice that is available from go1.17 - // https://stackoverflow.com/questions/51187973/how-to-create-an-array-or-a-slice-from-an-array-unsafe-pointer-in-golang - // instead of using a fixed syscall.MAX_PATH buf, we create a buf that is the size of the path name - size := int(raw.FileNameLength / 2) - var buf []uint16 - sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) - sh.Data = uintptr(unsafe.Pointer(&raw.FileName)) - sh.Len = size - sh.Cap = size - name := syscall.UTF16ToString(buf) - fullname := filepath.Join(watch.path, name) - - var mask uint64 - switch raw.Action { - case syscall.FILE_ACTION_REMOVED: - mask = sysFSDELETESELF - case syscall.FILE_ACTION_MODIFIED: - mask = sysFSMODIFY - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - watch.rename = name - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - if watch.names[watch.rename] != 0 { - watch.names[name] |= watch.names[watch.rename] - delete(watch.names, watch.rename) - mask = sysFSMOVESELF - } - } - - sendNameEvent := func() { - if w.sendEvent(fullname, watch.names[name]&mask) { - if watch.names[name]&sysFSONESHOT != 0 { - delete(watch.names, name) - } - } - } - if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME { - sendNameEvent() - } - if raw.Action == syscall.FILE_ACTION_REMOVED { - w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) - delete(watch.names, name) - } - if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) { - if watch.mask&sysFSONESHOT != 0 { - watch.mask = 0 - } - } - if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME { - fullname = filepath.Join(watch.path, watch.rename) - sendNameEvent() - } - - // Move to the next event in the buffer - if raw.NextEntryOffset == 0 { - break - } - offset += raw.NextEntryOffset - - // Error! - if offset >= n { - w.Errors <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.") - break - } - } - - if err := w.startRead(watch); err != nil { - w.Errors <- err - } - } -} - -func (w *Watcher) sendEvent(name string, mask uint64) bool { - if mask == 0 { - return false - } - event := newEvent(name, uint32(mask)) - select { - case ch := <-w.quit: - w.quit <- ch - case w.Events <- event: - } - return true -} - -func toWindowsFlags(mask uint64) uint32 { - var m uint32 - if mask&sysFSACCESS != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS - } - if mask&sysFSMODIFY != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE - } - if mask&sysFSATTRIB != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES - } - if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME - } - return m -} - -func toFSnotifyFlags(action uint32) uint64 { - switch action { - case syscall.FILE_ACTION_ADDED: - return sysFSCREATE - case syscall.FILE_ACTION_REMOVED: - return sysFSDELETE - case syscall.FILE_ACTION_MODIFIED: - return sysFSMODIFY - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - return sysFSMOVEDFROM - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - return sysFSMOVEDTO - } - return 0 -} diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go index 19437b34f..91198f819 100644 --- a/vendor/github.com/google/go-querystring/query/encode.go +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -51,8 +51,8 @@ type Encoder interface { // - the field is empty and its tag specifies the "omitempty" option // // The empty values are false, 0, any nil pointer or interface value, any array -// slice, map, or string of length zero, and any time.Time that returns true -// for IsZero(). +// slice, map, or string of length zero, and any type (such as time.Time) that +// returns true for IsZero(). // // The URL parameter name defaults to the struct field name but can be // specified in the struct field's tag value. The "url" key in the struct @@ -82,7 +82,14 @@ type Encoder interface { // // time.Time values default to encoding as RFC3339 timestamps. Including the // "unix" option signals that the field should be encoded as a Unix time (see -// time.Unix()) +// time.Unix()). The "unixmilli" and "unixnano" options will encode the number +// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see +// time.UnixNano()). Including the "layout" struct tag (separate from the +// "url" tag) will use the value of the "layout" tag as a layout passed to +// time.Format. For example: +// +// // Encode a time.Time as YYYY-MM-DD +// Field time.Time `layout:"2006-01-02"` // // Slice and Array values default to encoding as multiple URL values of the // same name. Including the "comma" option signals that the field should be @@ -92,7 +99,13 @@ type Encoder interface { // Including the "brackets" option signals that the multiple URL values should // have "[]" appended to the value name. "numbered" will append a number to // the end of each incidence of the value name, example: -// name0=value0&name1=value1, etc. +// name0=value0&name1=value1, etc. Including the "del" struct tag (separate +// from the "url" tag) will use the value of the "del" tag as the delimiter. +// For example: +// +// // Encode a slice of bools as ints ("1" for true, "0" for false), +// // separated by exclamation points "!". +// Field []bool `url:",int" del:"!"` // // Anonymous struct fields are usually encoded as if their inner exported // fields were fields in the outer struct, subject to the standard Go @@ -151,11 +164,15 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { continue } name, opts := parseTag(tag) + if name == "" { - if sf.Anonymous && sv.Kind() == reflect.Struct { - // save embedded struct for later processing - embedded = append(embedded, sv) - continue + if sf.Anonymous { + v := reflect.Indirect(sv) + if v.IsValid() && v.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, v) + continue + } } name = sf.Name @@ -170,7 +187,9 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } if sv.Type().Implements(encoderType) { - if !reflect.Indirect(sv).IsValid() { + // if sv is a nil pointer and the custom encoder is defined on a non-pointer + // method receiver, set sv to the zero value of the underlying type + if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) { sv = reflect.New(sv.Type().Elem()) } @@ -181,28 +200,38 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { continue } + // recursively dereference pointers. break on nil pointers + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { - var del byte + var del string if opts.Contains("comma") { - del = ',' + del = "," } else if opts.Contains("space") { - del = ' ' + del = " " } else if opts.Contains("semicolon") { - del = ';' + del = ";" } else if opts.Contains("brackets") { name = name + "[]" + } else { + del = sf.Tag.Get("del") } - if del != 0 { + if del != "" { s := new(bytes.Buffer) first := true for i := 0; i < sv.Len(); i++ { if first { first = false } else { - s.WriteByte(del) + s.WriteString(del) } - s.WriteString(valueString(sv.Index(i), opts)) + s.WriteString(valueString(sv.Index(i), opts, sf)) } values.Add(name, s.String()) } else { @@ -211,30 +240,25 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { if opts.Contains("numbered") { k = fmt.Sprintf("%s%d", name, i) } - values.Add(k, valueString(sv.Index(i), opts)) + values.Add(k, valueString(sv.Index(i), opts, sf)) } } continue } if sv.Type() == timeType { - values.Add(name, valueString(sv, opts)) + values.Add(name, valueString(sv, opts, sf)) continue } - for sv.Kind() == reflect.Ptr { - if sv.IsNil() { - break - } - sv = sv.Elem() - } - if sv.Kind() == reflect.Struct { - reflectValue(values, sv, name) + if err := reflectValue(values, sv, name); err != nil { + return err + } continue } - values.Add(name, valueString(sv, opts)) + values.Add(name, valueString(sv, opts, sf)) } for _, f := range embedded { @@ -247,7 +271,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } // valueString returns the string representation of a value. -func valueString(v reflect.Value, opts tagOptions) string { +func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string { for v.Kind() == reflect.Ptr { if v.IsNil() { return "" @@ -267,6 +291,15 @@ func valueString(v reflect.Value, opts tagOptions) string { if opts.Contains("unix") { return strconv.FormatInt(t.Unix(), 10) } + if opts.Contains("unixmilli") { + return strconv.FormatInt((t.UnixNano() / 1e6), 10) + } + if opts.Contains("unixnano") { + return strconv.FormatInt(t.UnixNano(), 10) + } + if layout := sf.Tag.Get("layout"); layout != "" { + return t.Format(layout) + } return t.Format(time.RFC3339) } @@ -291,8 +324,12 @@ func isEmptyValue(v reflect.Value) bool { return v.IsNil() } - if v.Type() == timeType { - return v.Interface().(time.Time).IsZero() + type zeroable interface { + IsZero() bool + } + + if z, ok := v.Interface().(zeroable); ok { + return z.IsZero() } return false diff --git a/vendor/github.com/google/uuid/CHANGELOG.md b/vendor/github.com/google/uuid/CHANGELOG.md new file mode 100644 index 000000000..7ec5ac7ea --- /dev/null +++ b/vendor/github.com/google/uuid/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog + +## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16) + + +### Features + +* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3)) + + +### Bug Fixes + +* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06)) +* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6)) + +## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12) + + +### Features + +* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29)) + +## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26) + + +### Features + +* UUIDs slice type with Strings() convenience method ([#133](https://github.com/google/uuid/issues/133)) ([cd5fbbd](https://github.com/google/uuid/commit/cd5fbbdd02f3e3467ac18940e07e062be1f864b4)) + +### Fixes + +* Clarify that Parse's job is to parse but not necessarily validate strings. (Documents current behavior) + +## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18) + + +### Bug Fixes + +* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0)) + +## Changelog diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md new file mode 100644 index 000000000..a502fdc51 --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# How to contribute + +We definitely welcome patches and contribution to this project! + +### Tips + +Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org). + +Always try to include a test case! If it is not possible or not necessary, +please explain why in the pull request description. + +### Releasing + +Commits that would precipitate a SemVer change, as described in the Conventional +Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action) +to create a release candidate pull request. Once submitted, `release-please` +will create a release. + +For tips on how to work with `release-please`, see its documentation. + +### Legal requirements + +In order to protect both you and ourselves, you will need to sign the +[Contributor License Agreement](https://cla.developers.google.com/clas). + +You may have already signed it for other Google projects. diff --git a/vendor/github.com/google/uuid/CONTRIBUTORS b/vendor/github.com/google/uuid/CONTRIBUTORS new file mode 100644 index 000000000..b4bb97f6b --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTORS @@ -0,0 +1,9 @@ +Paul Borman +bmatsuo +shawnps +theory +jboverfelt +dsymonds +cd1 +wallclockbuilder +dansouza diff --git a/vendor/github.com/gorilla/context/LICENSE b/vendor/github.com/google/uuid/LICENSE similarity index 83% rename from vendor/github.com/gorilla/context/LICENSE rename to vendor/github.com/google/uuid/LICENSE index 0e5fb8728..5dc68268d 100644 --- a/vendor/github.com/gorilla/context/LICENSE +++ b/vendor/github.com/google/uuid/LICENSE @@ -1,16 +1,16 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. +Copyright (c) 2009,2014 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md new file mode 100644 index 000000000..3e9a61889 --- /dev/null +++ b/vendor/github.com/google/uuid/README.md @@ -0,0 +1,21 @@ +# uuid +The uuid package generates and inspects UUIDs based on +[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) +and DCE 1.1: Authentication and Security Services. + +This package is based on the github.com/pborman/uuid package (previously named +code.google.com/p/go-uuid). It differs from these earlier packages in that +a UUID is a 16 byte array rather than a byte slice. One loss due to this +change is the ability to represent an invalid UUID (vs a NIL UUID). + +###### Install +```sh +go get github.com/google/uuid +``` + +###### Documentation +[![Go Reference](https://pkg.go.dev/badge/github.com/google/uuid.svg)](https://pkg.go.dev/github.com/google/uuid) + +Full `go doc` style documentation for the package can be viewed online without +installing this package by using the GoDoc site here: +http://pkg.go.dev/github.com/google/uuid diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go new file mode 100644 index 000000000..fa820b9d3 --- /dev/null +++ b/vendor/github.com/google/uuid/dce.go @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "fmt" + "os" +) + +// A Domain represents a Version 2 domain +type Domain byte + +// Domain constants for DCE Security (Version 2) UUIDs. +const ( + Person = Domain(0) + Group = Domain(1) + Org = Domain(2) +) + +// NewDCESecurity returns a DCE Security (Version 2) UUID. +// +// The domain should be one of Person, Group or Org. +// On a POSIX system the id should be the users UID for the Person +// domain and the users GID for the Group. The meaning of id for +// the domain Org or on non-POSIX systems is site defined. +// +// For a given domain/id pair the same token may be returned for up to +// 7 minutes and 10 seconds. +func NewDCESecurity(domain Domain, id uint32) (UUID, error) { + uuid, err := NewUUID() + if err == nil { + uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 + uuid[9] = byte(domain) + binary.BigEndian.PutUint32(uuid[0:], id) + } + return uuid, err +} + +// NewDCEPerson returns a DCE Security (Version 2) UUID in the person +// domain with the id returned by os.Getuid. +// +// NewDCESecurity(Person, uint32(os.Getuid())) +func NewDCEPerson() (UUID, error) { + return NewDCESecurity(Person, uint32(os.Getuid())) +} + +// NewDCEGroup returns a DCE Security (Version 2) UUID in the group +// domain with the id returned by os.Getgid. +// +// NewDCESecurity(Group, uint32(os.Getgid())) +func NewDCEGroup() (UUID, error) { + return NewDCESecurity(Group, uint32(os.Getgid())) +} + +// Domain returns the domain for a Version 2 UUID. Domains are only defined +// for Version 2 UUIDs. +func (uuid UUID) Domain() Domain { + return Domain(uuid[9]) +} + +// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2 +// UUIDs. +func (uuid UUID) ID() uint32 { + return binary.BigEndian.Uint32(uuid[0:4]) +} + +func (d Domain) String() string { + switch d { + case Person: + return "Person" + case Group: + return "Group" + case Org: + return "Org" + } + return fmt.Sprintf("Domain%d", int(d)) +} diff --git a/vendor/github.com/google/uuid/doc.go b/vendor/github.com/google/uuid/doc.go new file mode 100644 index 000000000..5b8a4b9af --- /dev/null +++ b/vendor/github.com/google/uuid/doc.go @@ -0,0 +1,12 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package uuid generates and inspects UUIDs. +// +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to +// maps or compared directly. +package uuid diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go new file mode 100644 index 000000000..dc60082d3 --- /dev/null +++ b/vendor/github.com/google/uuid/hash.go @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "crypto/md5" + "crypto/sha1" + "hash" +) + +// Well known namespace IDs and UUIDs +var ( + NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) + Nil UUID // empty UUID, all zeros + + // The Max UUID is special form of UUID that is specified to have all 128 bits set to 1. + Max = UUID{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + } +) + +// NewHash returns a new UUID derived from the hash of space concatenated with +// data generated by h. The hash should be at least 16 byte in length. The +// first 16 bytes of the hash are used to form the UUID. The version of the +// UUID will be the lower 4 bits of version. NewHash is used to implement +// NewMD5 and NewSHA1. +func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { + h.Reset() + h.Write(space[:]) //nolint:errcheck + h.Write(data) //nolint:errcheck + s := h.Sum(nil) + var uuid UUID + copy(uuid[:], s) + uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) + uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant + return uuid +} + +// NewMD5 returns a new MD5 (Version 3) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(md5.New(), space, data, 3) +func NewMD5(space UUID, data []byte) UUID { + return NewHash(md5.New(), space, data, 3) +} + +// NewSHA1 returns a new SHA1 (Version 5) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(sha1.New(), space, data, 5) +func NewSHA1(space UUID, data []byte) UUID { + return NewHash(sha1.New(), space, data, 5) +} diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go new file mode 100644 index 000000000..14bd34072 --- /dev/null +++ b/vendor/github.com/google/uuid/marshal.go @@ -0,0 +1,38 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "fmt" + +// MarshalText implements encoding.TextMarshaler. +func (uuid UUID) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], uuid) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (uuid *UUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + return err + } + *uuid = id + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (uuid UUID) MarshalBinary() ([]byte, error) { + return uuid[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (uuid *UUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(uuid[:], data) + return nil +} diff --git a/vendor/github.com/google/uuid/node.go b/vendor/github.com/google/uuid/node.go new file mode 100644 index 000000000..d651a2b06 --- /dev/null +++ b/vendor/github.com/google/uuid/node.go @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "sync" +) + +var ( + nodeMu sync.Mutex + ifname string // name of interface being used + nodeID [6]byte // hardware for version 1 UUIDs + zeroID [6]byte // nodeID with only 0's +) + +// NodeInterface returns the name of the interface from which the NodeID was +// derived. The interface "user" is returned if the NodeID was set by +// SetNodeID. +func NodeInterface() string { + defer nodeMu.Unlock() + nodeMu.Lock() + return ifname +} + +// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. +// If name is "" then the first usable interface found will be used or a random +// Node ID will be generated. If a named interface cannot be found then false +// is returned. +// +// SetNodeInterface never fails when name is "". +func SetNodeInterface(name string) bool { + defer nodeMu.Unlock() + nodeMu.Lock() + return setNodeInterface(name) +} + +func setNodeInterface(name string) bool { + iname, addr := getHardwareInterface(name) // null implementation for js + if iname != "" && addr != nil { + ifname = iname + copy(nodeID[:], addr) + return true + } + + // We found no interfaces with a valid hardware address. If name + // does not specify a specific interface generate a random Node ID + // (section 4.1.6) + if name == "" { + ifname = "random" + randomBits(nodeID[:]) + return true + } + return false +} + +// NodeID returns a slice of a copy of the current Node ID, setting the Node ID +// if not already set. +func NodeID() []byte { + defer nodeMu.Unlock() + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + nid := nodeID + return nid[:] +} + +// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes +// of id are used. If id is less than 6 bytes then false is returned and the +// Node ID is not set. +func SetNodeID(id []byte) bool { + if len(id) < 6 { + return false + } + defer nodeMu.Unlock() + nodeMu.Lock() + copy(nodeID[:], id) + ifname = "user" + return true +} + +// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is +// not valid. The NodeID is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) NodeID() []byte { + var node [6]byte + copy(node[:], uuid[10:]) + return node[:] +} diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go new file mode 100644 index 000000000..b2a0bc871 --- /dev/null +++ b/vendor/github.com/google/uuid/node_js.go @@ -0,0 +1,12 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build js + +package uuid + +// getHardwareInterface returns nil values for the JS version of the code. +// This removes the "net" dependency, because it is not used in the browser. +// Using the "net" library inflates the size of the transpiled JS code by 673k bytes. +func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go new file mode 100644 index 000000000..0cbbcddbd --- /dev/null +++ b/vendor/github.com/google/uuid/node_net.go @@ -0,0 +1,33 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !js + +package uuid + +import "net" + +var interfaces []net.Interface // cached list of interfaces + +// getHardwareInterface returns the name and hardware address of interface name. +// If name is "" then the name and hardware address of one of the system's +// interfaces is returned. If no interfaces are found (name does not exist or +// there are no interfaces) then "", nil is returned. +// +// Only addresses of at least 6 bytes are returned. +func getHardwareInterface(name string) (string, []byte) { + if interfaces == nil { + var err error + interfaces, err = net.Interfaces() + if err != nil { + return "", nil + } + } + for _, ifs := range interfaces { + if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { + return ifs.Name, ifs.HardwareAddr + } + } + return "", nil +} diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go new file mode 100644 index 000000000..d7fcbf286 --- /dev/null +++ b/vendor/github.com/google/uuid/null.go @@ -0,0 +1,118 @@ +// Copyright 2021 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "database/sql/driver" + "encoding/json" + "fmt" +) + +var jsonNull = []byte("null") + +// NullUUID represents a UUID that may be null. +// NullUUID implements the SQL driver.Scanner interface so +// it can be used as a scan destination: +// +// var u uuid.NullUUID +// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) +// ... +// if u.Valid { +// // use u.UUID +// } else { +// // NULL value +// } +// +type NullUUID struct { + UUID UUID + Valid bool // Valid is true if UUID is not NULL +} + +// Scan implements the SQL driver.Scanner interface. +func (nu *NullUUID) Scan(value interface{}) error { + if value == nil { + nu.UUID, nu.Valid = Nil, false + return nil + } + + err := nu.UUID.Scan(value) + if err != nil { + nu.Valid = false + return err + } + + nu.Valid = true + return nil +} + +// Value implements the driver Valuer interface. +func (nu NullUUID) Value() (driver.Value, error) { + if !nu.Valid { + return nil, nil + } + // Delegate to UUID Value function + return nu.UUID.Value() +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (nu NullUUID) MarshalBinary() ([]byte, error) { + if nu.Valid { + return nu.UUID[:], nil + } + + return []byte(nil), nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (nu *NullUUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(nu.UUID[:], data) + nu.Valid = true + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (nu NullUUID) MarshalText() ([]byte, error) { + if nu.Valid { + return nu.UUID.MarshalText() + } + + return jsonNull, nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (nu *NullUUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + nu.Valid = false + return err + } + nu.UUID = id + nu.Valid = true + return nil +} + +// MarshalJSON implements json.Marshaler. +func (nu NullUUID) MarshalJSON() ([]byte, error) { + if nu.Valid { + return json.Marshal(nu.UUID) + } + + return jsonNull, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (nu *NullUUID) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, jsonNull) { + *nu = NullUUID{} + return nil // valid null UUID + } + err := json.Unmarshal(data, &nu.UUID) + nu.Valid = err == nil + return err +} diff --git a/vendor/github.com/google/uuid/sql.go b/vendor/github.com/google/uuid/sql.go new file mode 100644 index 000000000..2e02ec06c --- /dev/null +++ b/vendor/github.com/google/uuid/sql.go @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements sql.Scanner so UUIDs can be read from databases transparently. +// Currently, database types that map to string and []byte are supported. Please +// consult database-specific driver documentation for matching types. +func (uuid *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case nil: + return nil + + case string: + // if an empty UUID comes from a table, we return a null UUID + if src == "" { + return nil + } + + // see Parse for required string format + u, err := Parse(src) + if err != nil { + return fmt.Errorf("Scan: %v", err) + } + + *uuid = u + + case []byte: + // if an empty UUID comes from a table, we return a null UUID + if len(src) == 0 { + return nil + } + + // assumes a simple slice of bytes if 16 bytes + // otherwise attempts to parse + if len(src) != 16 { + return uuid.Scan(string(src)) + } + copy((*uuid)[:], src) + + default: + return fmt.Errorf("Scan: unable to scan type %T into UUID", src) + } + + return nil +} + +// Value implements sql.Valuer so that UUIDs can be written to databases +// transparently. Currently, UUIDs map to strings. Please consult +// database-specific driver documentation for matching types. +func (uuid UUID) Value() (driver.Value, error) { + return uuid.String(), nil +} diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go new file mode 100644 index 000000000..c35112927 --- /dev/null +++ b/vendor/github.com/google/uuid/time.go @@ -0,0 +1,134 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "sync" + "time" +) + +// A Time represents a time as the number of 100's of nanoseconds since 15 Oct +// 1582. +type Time int64 + +const ( + lillian = 2299160 // Julian day of 15 Oct 1582 + unix = 2440587 // Julian day of 1 Jan 1970 + epoch = unix - lillian // Days between epochs + g1582 = epoch * 86400 // seconds between epochs + g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs +) + +var ( + timeMu sync.Mutex + lasttime uint64 // last time we returned + clockSeq uint16 // clock sequence for this run + + timeNow = time.Now // for testing +) + +// UnixTime converts t the number of seconds and nanoseconds using the Unix +// epoch of 1 Jan 1970. +func (t Time) UnixTime() (sec, nsec int64) { + sec = int64(t - g1582ns100) + nsec = (sec % 10000000) * 100 + sec /= 10000000 + return sec, nsec +} + +// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and +// clock sequence as well as adjusting the clock sequence as needed. An error +// is returned if the current time cannot be determined. +func GetTime() (Time, uint16, error) { + defer timeMu.Unlock() + timeMu.Lock() + return getTime() +} + +func getTime() (Time, uint16, error) { + t := timeNow() + + // If we don't have a clock sequence already, set one. + if clockSeq == 0 { + setClockSequence(-1) + } + now := uint64(t.UnixNano()/100) + g1582ns100 + + // If time has gone backwards with this clock sequence then we + // increment the clock sequence + if now <= lasttime { + clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000 + } + lasttime = now + return Time(now), clockSeq, nil +} + +// ClockSequence returns the current clock sequence, generating one if not +// already set. The clock sequence is only used for Version 1 UUIDs. +// +// The uuid package does not use global static storage for the clock sequence or +// the last time a UUID was generated. Unless SetClockSequence is used, a new +// random clock sequence is generated the first time a clock sequence is +// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) +func ClockSequence() int { + defer timeMu.Unlock() + timeMu.Lock() + return clockSequence() +} + +func clockSequence() int { + if clockSeq == 0 { + setClockSequence(-1) + } + return int(clockSeq & 0x3fff) +} + +// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to +// -1 causes a new sequence to be generated. +func SetClockSequence(seq int) { + defer timeMu.Unlock() + timeMu.Lock() + setClockSequence(seq) +} + +func setClockSequence(seq int) { + if seq == -1 { + var b [2]byte + randomBits(b[:]) // clock sequence + seq = int(b[0])<<8 | int(b[1]) + } + oldSeq := clockSeq + clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant + if oldSeq != clockSeq { + lasttime = 0 + } +} + +// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in +// uuid. The time is only defined for version 1, 2, 6 and 7 UUIDs. +func (uuid UUID) Time() Time { + var t Time + switch uuid.Version() { + case 6: + time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110 + t = Time(time) + case 7: + time := binary.BigEndian.Uint64(uuid[:8]) + t = Time((time>>16)*10000 + g1582ns100) + default: // forward compatible + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + t = Time(time) + } + return t +} + +// ClockSequence returns the clock sequence encoded in uuid. +// The clock sequence is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) ClockSequence() int { + return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff +} diff --git a/vendor/github.com/google/uuid/util.go b/vendor/github.com/google/uuid/util.go new file mode 100644 index 000000000..5ea6c7378 --- /dev/null +++ b/vendor/github.com/google/uuid/util.go @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// randomBits completely fills slice b with random data. +func randomBits(b []byte) { + if _, err := io.ReadFull(rander, b); err != nil { + panic(err.Error()) // rand should never fail + } +} + +// xvalues returns the value of a byte as a hexadecimal digit or 255. +var xvalues = [256]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +} + +// xtob converts hex characters x1 and x2 into a byte. +func xtob(x1, x2 byte) (byte, bool) { + b1 := xvalues[x1] + b2 := xvalues[x2] + return (b1 << 4) | b2, b1 != 255 && b2 != 255 +} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go new file mode 100644 index 000000000..5232b4867 --- /dev/null +++ b/vendor/github.com/google/uuid/uuid.go @@ -0,0 +1,365 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io" + "strings" + "sync" +) + +// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC +// 4122. +type UUID [16]byte + +// A Version represents a UUID's version. +type Version byte + +// A Variant represents a UUID's variant. +type Variant byte + +// Constants returned by Variant. +const ( + Invalid = Variant(iota) // Invalid UUID + RFC4122 // The variant specified in RFC4122 + Reserved // Reserved, NCS backward compatibility. + Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future // Reserved for future definition. +) + +const randPoolSize = 16 * 16 + +var ( + rander = rand.Reader // random function + poolEnabled = false + poolMu sync.Mutex + poolPos = randPoolSize // protected with poolMu + pool [randPoolSize]byte // protected with poolMu +) + +type invalidLengthError struct{ len int } + +func (err invalidLengthError) Error() string { + return fmt.Sprintf("invalid UUID length: %d", err.len) +} + +// IsInvalidLengthError is matcher function for custom error invalidLengthError +func IsInvalidLengthError(err error) bool { + _, ok := err.(invalidLengthError) + return ok +} + +// Parse decodes s into a UUID or returns an error if it cannot be parsed. Both +// the standard UUID forms defined in RFC 4122 +// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition, +// Parse accepts non-standard strings such as the raw hex encoding +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings, +// e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are +// examined in the latter case. Parse should not be used to validate strings as +// it parses non-standard encodings as indicated above. +func Parse(s string) (UUID, error) { + var uuid UUID + switch len(s) { + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36: + + // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: + if !strings.EqualFold(s[:9], "urn:uuid:") { + return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + + // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + case 36 + 2: + s = s[1:] + + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + case 32: + var ok bool + for i := range uuid { + uuid[i], ok = xtob(s[i*2], s[i*2+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, invalidLengthError{len(s)} + } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34, + } { + v, ok := xtob(s[x], s[x+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + uuid[i] = v + } + return uuid, nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + var uuid UUID + switch len(b) { + case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) { + return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) + } + b = b[9:] + case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + b = b[1:] + case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + var ok bool + for i := 0; i < 32; i += 2 { + uuid[i/2], ok = xtob(b[i], b[i+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, invalidLengthError{len(b)} + } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34, + } { + v, ok := xtob(b[x], b[x+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + uuid[i] = v + } + return uuid, nil +} + +// MustParse is like Parse but panics if the string cannot be parsed. +// It simplifies safe initialization of global variables holding compiled UUIDs. +func MustParse(s string) UUID { + uuid, err := Parse(s) + if err != nil { + panic(`uuid: Parse(` + s + `): ` + err.Error()) + } + return uuid +} + +// FromBytes creates a new UUID from a byte slice. Returns an error if the slice +// does not have a length of 16. The bytes are copied from the slice. +func FromBytes(b []byte) (uuid UUID, err error) { + err = uuid.UnmarshalBinary(b) + return uuid, err +} + +// Must returns uuid if err is nil and panics otherwise. +func Must(uuid UUID, err error) UUID { + if err != nil { + panic(err) + } + return uuid +} + +// Validate returns an error if s is not a properly formatted UUID in one of the following formats: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} +// It returns an error if the format is invalid, otherwise nil. +func Validate(s string) error { + switch len(s) { + // Standard UUID format + case 36: + + // UUID with "urn:uuid:" prefix + case 36 + 9: + if !strings.EqualFold(s[:9], "urn:uuid:") { + return fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + + // UUID enclosed in braces + case 36 + 2: + if s[0] != '{' || s[len(s)-1] != '}' { + return fmt.Errorf("invalid bracketed UUID format") + } + s = s[1 : len(s)-1] + + // UUID without hyphens + case 32: + for i := 0; i < len(s); i += 2 { + _, ok := xtob(s[i], s[i+1]) + if !ok { + return errors.New("invalid UUID format") + } + } + + default: + return invalidLengthError{len(s)} + } + + // Check for standard UUID format + if len(s) == 36 { + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return errors.New("invalid UUID format") + } + for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { + if _, ok := xtob(s[x], s[x+1]); !ok { + return errors.New("invalid UUID format") + } + } + } + + return nil +} + +// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// , or "" if uuid is invalid. +func (uuid UUID) String() string { + var buf [36]byte + encodeHex(buf[:], uuid) + return string(buf[:]) +} + +// URN returns the RFC 2141 URN form of uuid, +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. +func (uuid UUID) URN() string { + var buf [36 + 9]byte + copy(buf[:], "urn:uuid:") + encodeHex(buf[9:], uuid) + return string(buf[:]) +} + +func encodeHex(dst []byte, uuid UUID) { + hex.Encode(dst, uuid[:4]) + dst[8] = '-' + hex.Encode(dst[9:13], uuid[4:6]) + dst[13] = '-' + hex.Encode(dst[14:18], uuid[6:8]) + dst[18] = '-' + hex.Encode(dst[19:23], uuid[8:10]) + dst[23] = '-' + hex.Encode(dst[24:], uuid[10:]) +} + +// Variant returns the variant encoded in uuid. +func (uuid UUID) Variant() Variant { + switch { + case (uuid[8] & 0xc0) == 0x80: + return RFC4122 + case (uuid[8] & 0xe0) == 0xc0: + return Microsoft + case (uuid[8] & 0xe0) == 0xe0: + return Future + default: + return Reserved + } +} + +// Version returns the version of uuid. +func (uuid UUID) Version() Version { + return Version(uuid[6] >> 4) +} + +func (v Version) String() string { + if v > 15 { + return fmt.Sprintf("BAD_VERSION_%d", v) + } + return fmt.Sprintf("VERSION_%d", v) +} + +func (v Variant) String() string { + switch v { + case RFC4122: + return "RFC4122" + case Reserved: + return "Reserved" + case Microsoft: + return "Microsoft" + case Future: + return "Future" + case Invalid: + return "Invalid" + } + return fmt.Sprintf("BadVariant%d", int(v)) +} + +// SetRand sets the random number generator to r, which implements io.Reader. +// If r.Read returns an error when the package requests random data then +// a panic will be issued. +// +// Calling SetRand with nil sets the random number generator to the default +// generator. +func SetRand(r io.Reader) { + if r == nil { + rander = rand.Reader + return + } + rander = r +} + +// EnableRandPool enables internal randomness pool used for Random +// (Version 4) UUID generation. The pool contains random bytes read from +// the random number generator on demand in batches. Enabling the pool +// may improve the UUID generation throughput significantly. +// +// Since the pool is stored on the Go heap, this feature may be a bad fit +// for security sensitive applications. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func EnableRandPool() { + poolEnabled = true +} + +// DisableRandPool disables the randomness pool if it was previously +// enabled with EnableRandPool. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func DisableRandPool() { + poolEnabled = false + defer poolMu.Unlock() + poolMu.Lock() + poolPos = randPoolSize +} + +// UUIDs is a slice of UUID types. +type UUIDs []UUID + +// Strings returns a string slice containing the string form of each UUID in uuids. +func (uuids UUIDs) Strings() []string { + var uuidStrs = make([]string, len(uuids)) + for i, uuid := range uuids { + uuidStrs[i] = uuid.String() + } + return uuidStrs +} diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go new file mode 100644 index 000000000..463109629 --- /dev/null +++ b/vendor/github.com/google/uuid/version1.go @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" +) + +// NewUUID returns a Version 1 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewUUID returns nil. If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewUUID returns nil and an error. +// +// In most cases, New should be used. +func NewUUID() (UUID, error) { + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + timeLow := uint32(now & 0xffffffff) + timeMid := uint16((now >> 32) & 0xffff) + timeHi := uint16((now >> 48) & 0x0fff) + timeHi |= 0x1000 // Version 1 + + binary.BigEndian.PutUint32(uuid[0:], timeLow) + binary.BigEndian.PutUint16(uuid[4:], timeMid) + binary.BigEndian.PutUint16(uuid[6:], timeHi) + binary.BigEndian.PutUint16(uuid[8:], seq) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() + + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go new file mode 100644 index 000000000..7697802e4 --- /dev/null +++ b/vendor/github.com/google/uuid/version4.go @@ -0,0 +1,76 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "io" + +// New creates a new random UUID or panics. New is equivalent to +// the expression +// +// uuid.Must(uuid.NewRandom()) +func New() UUID { + return Must(NewRandom()) +} + +// NewString creates a new random UUID and returns it as a string or panics. +// NewString is equivalent to the expression +// +// uuid.New().String() +func NewString() string { + return Must(NewRandom()).String() +} + +// NewRandom returns a Random (Version 4) UUID. +// +// The strength of the UUIDs is based on the strength of the crypto/rand +// package. +// +// Uses the randomness pool if it was enabled with EnableRandPool. +// +// A note about uniqueness derived from the UUID Wikipedia entry: +// +// Randomly generated UUIDs have 122 random bits. One's annual risk of being +// hit by a meteorite is estimated to be one chance in 17 billion, that +// means the probability is about 0.00000000006 (6 × 10−11), +// equivalent to the odds of creating a few tens of trillions of UUIDs in a +// year and having one duplicate. +func NewRandom() (UUID, error) { + if !poolEnabled { + return NewRandomFromReader(rander) + } + return newRandomFromPool() +} + +// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. +func NewRandomFromReader(r io.Reader) (UUID, error) { + var uuid UUID + _, err := io.ReadFull(r, uuid[:]) + if err != nil { + return Nil, err + } + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} + +func newRandomFromPool() (UUID, error) { + var uuid UUID + poolMu.Lock() + if poolPos == randPoolSize { + _, err := io.ReadFull(rander, pool[:]) + if err != nil { + poolMu.Unlock() + return Nil, err + } + poolPos = 0 + } + copy(uuid[:], pool[poolPos:(poolPos+16)]) + poolPos += 16 + poolMu.Unlock() + + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version6.go b/vendor/github.com/google/uuid/version6.go new file mode 100644 index 000000000..339a959a7 --- /dev/null +++ b/vendor/github.com/google/uuid/version6.go @@ -0,0 +1,56 @@ +// Copyright 2023 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "encoding/binary" + +// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality. +// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs. +// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead. +// +// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6 +// +// NewV6 returns a Version 6 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewV6 returns Nil and an error. +func NewV6() (UUID, error) { + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_high | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_mid | time_low_and_version | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |clk_seq_hi_res | clk_seq_low | node (0-1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | node (2-5) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + binary.BigEndian.PutUint64(uuid[0:], uint64(now)) + binary.BigEndian.PutUint16(uuid[8:], seq) + + uuid[6] = 0x60 | (uuid[6] & 0x0F) + uuid[8] = 0x80 | (uuid[8] & 0x3F) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() + + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version7.go b/vendor/github.com/google/uuid/version7.go new file mode 100644 index 000000000..3167b643d --- /dev/null +++ b/vendor/github.com/google/uuid/version7.go @@ -0,0 +1,104 @@ +// Copyright 2023 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// UUID version 7 features a time-ordered value field derived from the widely +// implemented and well known Unix Epoch timestamp source, +// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded. +// As well as improved entropy characteristics over versions 1 or 6. +// +// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7 +// +// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible. +// +// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch). +// Uses the randomness pool if it was enabled with EnableRandPool. +// On error, NewV7 returns Nil and an error +func NewV7() (UUID, error) { + uuid, err := NewRandom() + if err != nil { + return uuid, err + } + makeV7(uuid[:]) + return uuid, nil +} + +// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch). +// it use NewRandomFromReader fill random bits. +// On error, NewV7FromReader returns Nil and an error. +func NewV7FromReader(r io.Reader) (UUID, error) { + uuid, err := NewRandomFromReader(r) + if err != nil { + return uuid, err + } + + makeV7(uuid[:]) + return uuid, nil +} + +// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6]) +// uuid[8] already has the right version number (Variant is 10) +// see function NewV7 and NewV7FromReader +func makeV7(uuid []byte) { + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unix_ts_ms | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unix_ts_ms | ver | rand_a (12 bit seq) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |var| rand_b | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | rand_b | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + _ = uuid[15] // bounds check + + t, s := getV7Time() + + uuid[0] = byte(t >> 40) + uuid[1] = byte(t >> 32) + uuid[2] = byte(t >> 24) + uuid[3] = byte(t >> 16) + uuid[4] = byte(t >> 8) + uuid[5] = byte(t) + + uuid[6] = 0x70 | (0x0F & byte(s>>8)) + uuid[7] = byte(s) +} + +// lastV7time is the last time we returned stored as: +// +// 52 bits of time in milliseconds since epoch +// 12 bits of (fractional nanoseconds) >> 8 +var lastV7time int64 + +const nanoPerMilli = 1000000 + +// getV7Time returns the time in milliseconds and nanoseconds / 256. +// The returned (milli << 12 + seq) is guarenteed to be greater than +// (milli << 12 + seq) returned by any previous call to getV7Time. +func getV7Time() (milli, seq int64) { + timeMu.Lock() + defer timeMu.Unlock() + + nano := timeNow().UnixNano() + milli = nano / nanoPerMilli + // Sequence number is between 0 and 3906 (nanoPerMilli>>8) + seq = (nano - milli*nanoPerMilli) >> 8 + now := milli<<12 + seq + if now <= lastV7time { + now = lastV7time + 1 + milli = now >> 12 + seq = now & 0xfff + } + lastV7time = now + return milli, seq +} diff --git a/vendor/github.com/gorilla/context/.travis.yml b/vendor/github.com/gorilla/context/.travis.yml deleted file mode 100644 index 24882fc7b..000000000 --- a/vendor/github.com/gorilla/context/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.3 - - go: 1.4 - - go: 1.5 - - go: 1.6 - - go: tip - allow_failures: - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go vet $(go list ./... | grep -v /vendor/) - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/context/README.md b/vendor/github.com/gorilla/context/README.md deleted file mode 100644 index c60a31b05..000000000 --- a/vendor/github.com/gorilla/context/README.md +++ /dev/null @@ -1,7 +0,0 @@ -context -======= -[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) - -gorilla/context is a general purpose registry for global request variables. - -Read the full documentation here: http://www.gorillatoolkit.org/pkg/context diff --git a/vendor/github.com/gorilla/context/context.go b/vendor/github.com/gorilla/context/context.go deleted file mode 100644 index 81cb128b1..000000000 --- a/vendor/github.com/gorilla/context/context.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context - -import ( - "net/http" - "sync" - "time" -) - -var ( - mutex sync.RWMutex - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) -) - -// Set stores a value for a given key in a given request. -func Set(r *http.Request, key, val interface{}) { - mutex.Lock() - if data[r] == nil { - data[r] = make(map[interface{}]interface{}) - datat[r] = time.Now().Unix() - } - data[r][key] = val - mutex.Unlock() -} - -// Get returns a value stored for a given key in a given request. -func Get(r *http.Request, key interface{}) interface{} { - mutex.RLock() - if ctx := data[r]; ctx != nil { - value := ctx[key] - mutex.RUnlock() - return value - } - mutex.RUnlock() - return nil -} - -// GetOk returns stored value and presence state like multi-value return of map access. -func GetOk(r *http.Request, key interface{}) (interface{}, bool) { - mutex.RLock() - if _, ok := data[r]; ok { - value, ok := data[r][key] - mutex.RUnlock() - return value, ok - } - mutex.RUnlock() - return nil, false -} - -// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. -func GetAll(r *http.Request) map[interface{}]interface{} { - mutex.RLock() - if context, ok := data[r]; ok { - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result - } - mutex.RUnlock() - return nil -} - -// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if -// the request was registered. -func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { - mutex.RLock() - context, ok := data[r] - result := make(map[interface{}]interface{}, len(context)) - for k, v := range context { - result[k] = v - } - mutex.RUnlock() - return result, ok -} - -// Delete removes a value stored for a given key in a given request. -func Delete(r *http.Request, key interface{}) { - mutex.Lock() - if data[r] != nil { - delete(data[r], key) - } - mutex.Unlock() -} - -// Clear removes all values stored for a given request. -// -// This is usually called by a handler wrapper to clean up request -// variables at the end of a request lifetime. See ClearHandler(). -func Clear(r *http.Request) { - mutex.Lock() - clear(r) - mutex.Unlock() -} - -// clear is Clear without the lock. -func clear(r *http.Request) { - delete(data, r) - delete(datat, r) -} - -// Purge removes request data stored for longer than maxAge, in seconds. -// It returns the amount of requests removed. -// -// If maxAge <= 0, all request data is removed. -// -// This is only used for sanity check: in case context cleaning was not -// properly set some request data can be kept forever, consuming an increasing -// amount of memory. In case this is detected, Purge() must be called -// periodically until the problem is fixed. -func Purge(maxAge int) int { - mutex.Lock() - count := 0 - if maxAge <= 0 { - count = len(data) - data = make(map[*http.Request]map[interface{}]interface{}) - datat = make(map[*http.Request]int64) - } else { - min := time.Now().Unix() - int64(maxAge) - for r := range data { - if datat[r] < min { - clear(r) - count++ - } - } - } - mutex.Unlock() - return count -} - -// ClearHandler wraps an http.Handler and clears request values at the end -// of a request lifetime. -func ClearHandler(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer Clear(r) - h.ServeHTTP(w, r) - }) -} diff --git a/vendor/github.com/gorilla/context/doc.go b/vendor/github.com/gorilla/context/doc.go deleted file mode 100644 index 73c740031..000000000 --- a/vendor/github.com/gorilla/context/doc.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012 The Gorilla Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package context stores values shared during a request lifetime. - -For example, a router can set variables extracted from the URL and later -application handlers can access those values, or it can be used to store -sessions values to be saved at the end of a request. There are several -others common uses. - -The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: - - http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 - -Here's the basic usage: first define the keys that you will need. The key -type is interface{} so a key can be of any type that supports equality. -Here we define a key using a custom int type to avoid name collisions: - - package foo - - import ( - "github.com/gorilla/context" - ) - - type key int - - const MyKey key = 0 - -Then set a variable. Variables are bound to an http.Request object, so you -need a request instance to set a value: - - context.Set(r, MyKey, "bar") - -The application can later access the variable using the same key you provided: - - func MyHandler(w http.ResponseWriter, r *http.Request) { - // val is "bar". - val := context.Get(r, foo.MyKey) - - // returns ("bar", true) - val, ok := context.GetOk(r, foo.MyKey) - // ... - } - -And that's all about the basic usage. We discuss some other ideas below. - -Any type can be stored in the context. To enforce a given type, make the key -private and wrap Get() and Set() to accept and return values of a specific -type: - - type key int - - const mykey key = 0 - - // GetMyKey returns a value for this package from the request values. - func GetMyKey(r *http.Request) SomeType { - if rv := context.Get(r, mykey); rv != nil { - return rv.(SomeType) - } - return nil - } - - // SetMyKey sets a value for this package in the request values. - func SetMyKey(r *http.Request, val SomeType) { - context.Set(r, mykey, val) - } - -Variables must be cleared at the end of a request, to remove all values -that were stored. This can be done in an http.Handler, after a request was -served. Just call Clear() passing the request: - - context.Clear(r) - -...or use ClearHandler(), which conveniently wraps an http.Handler to clear -variables at the end of a request lifetime. - -The Routers from the packages gorilla/mux and gorilla/pat call Clear() -so if you are using either of them you don't need to clear the context manually. -*/ -package context diff --git a/vendor/github.com/gorilla/mux/.editorconfig b/vendor/github.com/gorilla/mux/.editorconfig new file mode 100644 index 000000000..c6b74c3e0 --- /dev/null +++ b/vendor/github.com/gorilla/mux/.editorconfig @@ -0,0 +1,20 @@ +; https://editorconfig.org/ + +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[{Makefile,go.mod,go.sum,*.go,.gitmodules}] +indent_style = tab +indent_size = 4 + +[*.md] +indent_size = 4 +trim_trailing_whitespace = false + +eclint_indent_style = unset \ No newline at end of file diff --git a/vendor/github.com/gorilla/mux/.gitignore b/vendor/github.com/gorilla/mux/.gitignore new file mode 100644 index 000000000..84039fec6 --- /dev/null +++ b/vendor/github.com/gorilla/mux/.gitignore @@ -0,0 +1 @@ +coverage.coverprofile diff --git a/vendor/github.com/gorilla/mux/.travis.yml b/vendor/github.com/gorilla/mux/.travis.yml deleted file mode 100644 index f4084bd81..000000000 --- a/vendor/github.com/gorilla/mux/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.2 - - go: 1.3 - - go: 1.4 - - go: 1.5 - - go: 1.6 - - go: tip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go tool vet . - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/mux/LICENSE b/vendor/github.com/gorilla/mux/LICENSE index 0e5fb8728..bb9d80bc9 100644 --- a/vendor/github.com/gorilla/mux/LICENSE +++ b/vendor/github.com/gorilla/mux/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012 Rodrigo Moraes. All rights reserved. +Copyright (c) 2023 The Gorilla Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/github.com/gorilla/mux/Makefile b/vendor/github.com/gorilla/mux/Makefile new file mode 100644 index 000000000..98f5ab75f --- /dev/null +++ b/vendor/github.com/gorilla/mux/Makefile @@ -0,0 +1,34 @@ +GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '') +GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +GO_SEC=$(shell which gosec 2> /dev/null || echo '') +GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest + +GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '') +GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest + +.PHONY: golangci-lint +golangci-lint: + $(if $(GO_LINT), ,go install $(GO_LINT_URI)) + @echo "##### Running golangci-lint" + golangci-lint run -v + +.PHONY: gosec +gosec: + $(if $(GO_SEC), ,go install $(GO_SEC_URI)) + @echo "##### Running gosec" + gosec ./... + +.PHONY: govulncheck +govulncheck: + $(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI)) + @echo "##### Running govulncheck" + govulncheck ./... + +.PHONY: verify +verify: golangci-lint gosec govulncheck + +.PHONY: test +test: + @echo "##### Running tests" + go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./... \ No newline at end of file diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md index 9516c5191..382513d57 100644 --- a/vendor/github.com/gorilla/mux/README.md +++ b/vendor/github.com/gorilla/mux/README.md @@ -1,29 +1,60 @@ -mux -=== -[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) -[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux) +# gorilla/mux -http://www.gorillatoolkit.org/pkg/mux +![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux) +[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) -Package `gorilla/mux` implements a request router and dispatcher. + +![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5) + +Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to +their respective handler. The name mux stands for "HTTP request multiplexer". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: +* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. * Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers. -* URL hosts and paths can have variables with an optional regular expression. +* URL hosts, paths and query values can have variables with an optional regular expression. * Registered URLs can be built, or "reversed", which helps maintaining references to resources. * Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching. -* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`. + +--- + +* [Install](#install) +* [Examples](#examples) +* [Matching Routes](#matching-routes) +* [Static Files](#static-files) +* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.) +* [Registered URLs](#registered-urls) +* [Walking Routes](#walking-routes) +* [Graceful Shutdown](#graceful-shutdown) +* [Middleware](#middleware) +* [Handling CORS Requests](#handling-cors-requests) +* [Testing Handlers](#testing-handlers) +* [Full Example](#full-example) + +--- + +## Install + +With a [correctly configured](https://golang.org/doc/install#testing) Go toolchain: + +```sh +go get -u github.com/gorilla/mux +``` + +## Examples Let's start registering a couple of URL paths and handlers: ```go func main() { - r := mux.NewRouter() - r.HandleFunc("/", HomeHandler) - r.HandleFunc("/products", ProductsHandler) - r.HandleFunc("/articles", ArticlesHandler) - http.Handle("/", r) + r := mux.NewRouter() + r.HandleFunc("/", HomeHandler) + r.HandleFunc("/products", ProductsHandler) + r.HandleFunc("/articles", ArticlesHandler) + http.Handle("/", r) } ``` @@ -41,12 +72,17 @@ r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`: ```go -vars := mux.Vars(request) -category := vars["category"] +func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Category: %v\n", vars["category"]) +} ``` And this is all you need to know about the basic usage. More advanced options are explained below. +### Matching Routes + Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables: ```go @@ -54,7 +90,7 @@ r := mux.NewRouter() // Only matches if domain is "www.example.com". r.Host("www.example.com") // Matches a dynamic subdomain. -r.Host("{subdomain:[a-z]+}.domain.com") +r.Host("{subdomain:[a-z]+}.example.com") ``` There are several other matchers that can be added. To match path prefixes: @@ -91,7 +127,7 @@ r.Queries("key", "value") ```go r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { - return r.ProtoMajor == 0 + return r.ProtoMajor == 0 }) ``` @@ -104,6 +140,14 @@ r.HandleFunc("/products", ProductsHandler). Schemes("http") ``` +Routes are tested in the order they were added to the router. If two routes match, the first one wins: + +```go +r := mux.NewRouter() +r.HandleFunc("/specific", specificHandler) +r.PathPrefix("/").Handler(catchAllHandler) +``` + Setting the same matching conditions again and again can be boring, so we have a way to group several routes that share the same requirements. We call it "subrouting". For example, let's say we have several URLs that should only match when the host is `www.example.com`. Create a route for that host and get a "subrouter" from it: @@ -118,7 +162,7 @@ Then register routes in the subrouter: ```go s.HandleFunc("/products/", ProductsHandler) s.HandleFunc("/products/{key}", ProductHandler) -s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +s.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) ``` The three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route. @@ -138,6 +182,118 @@ s.HandleFunc("/{key}/", ProductHandler) s.HandleFunc("/{key}/details", ProductDetailsHandler) ``` + +### Static Files + +Note that the path provided to `PathPrefix()` represents a "wildcard": calling +`PathPrefix("/static/").Handler(...)` means that the handler will be passed any +request that matches "/static/\*". This makes it easy to serve static files with mux: + +```go +func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Serving Single Page Applications + +Most of the time it makes sense to serve your SPA on a separate web server from your API, +but sometimes it's desirable to serve them both from one place. It's possible to write a simple +handler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage +mux's powerful routing for your API endpoints. + +```go +package main + +import ( + "encoding/json" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gorilla/mux" +) + +// spaHandler implements the http.Handler interface, so we can use it +// to respond to HTTP requests. The path to the static directory and +// path to the index file within that static directory are used to +// serve the SPA in the given static directory. +type spaHandler struct { + staticPath string + indexPath string +} + +// ServeHTTP inspects the URL path to locate a file within the static dir +// on the SPA handler. If a file is found, it will be served. If not, the +// file located at the index path on the SPA handler will be served. This +// is suitable behavior for serving an SPA (single page application). +func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Join internally call path.Clean to prevent directory traversal + path := filepath.Join(h.staticPath, r.URL.Path) + + // check whether a file exists or is a directory at the given path + fi, err := os.Stat(path) + if os.IsNotExist(err) || fi.IsDir() { + // file does not exist or path is a directory, serve index.html + http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath)) + return + } + + if err != nil { + // if we got an error (that wasn't that the file doesn't exist) stating the + // file, return a 500 internal server error and stop + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // otherwise, use http.FileServer to serve the static file + http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r) +} + +func main() { + router := mux.NewRouter() + + router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + // an example API handler + json.NewEncoder(w).Encode(map[string]bool{"ok": true}) + }) + + spa := spaHandler{staticPath: "build", indexPath: "index.html"} + router.PathPrefix("/").Handler(spa) + + srv := &http.Server{ + Handler: router, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + +### Registered URLs + Now let's see how to build registered URLs. Routes can be named. All routes that define a name can have their URLs built, or "reversed". We define a name calling `Name()` on a route. For example: @@ -160,19 +316,21 @@ url, err := r.Get("article").URL("category", "technology", "id", "42") "/articles/technology/42" ``` -This also works for host variables: +This also works for host and query value variables: ```go r := mux.NewRouter() -r.Host("{subdomain}.domain.com"). +r.Host("{subdomain}.example.com"). Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). HandlerFunc(ArticleHandler). Name("article") -// url.String() will be "http://news.domain.com/articles/technology/42" +// url.String() will be "http://news.example.com/articles/technology/42?filter=gorilla" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", - "id", "42") + "id", "42", + "filter", "gorilla") ``` All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match. @@ -188,7 +346,7 @@ r.HeadersRegexp("Content-Type", "application/(text|json)") There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do: ```go -// "http://news.domain.com/" +// "http://news.example.com/" host, err := r.Get("article").URLHost("subdomain", "news") // "/articles/technology/42" @@ -199,41 +357,453 @@ And if you use subrouters, host and path defined separately can be built as well ```go r := mux.NewRouter() -s := r.Host("{subdomain}.domain.com").Subrouter() +s := r.Host("{subdomain}.example.com").Subrouter() s.Path("/articles/{category}/{id:[0-9]+}"). HandlerFunc(ArticleHandler). Name("article") -// "http://news.domain.com/articles/technology/42" +// "http://news.example.com/articles/technology/42" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", "id", "42") ``` -## Full Example +To find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available: +```go +r := mux.NewRouter() +r.Host("{domain}"). + Path("/{group}/{item_id}"). + Queries("some_data1", "{some_data1}"). + Queries("some_data2", "{some_data2}"). + Name("article") -Here's a complete, runnable example of a small `mux` based server: +// Will print [domain group item_id some_data1 some_data2] +fmt.Println(r.Get("article").GetVarNames()) + +``` +### Walking Routes + +The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example, +the following prints all of the registered routes: ```go package main import ( + "fmt" "net/http" + "strings" "github.com/gorilla/mux" ) -func YourHandler(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Gorilla!\n")) +func handler(w http.ResponseWriter, r *http.Request) { + return } func main() { r := mux.NewRouter() - // Routes consist of a path and a handler function. - r.HandleFunc("/", YourHandler) + r.HandleFunc("/", handler) + r.HandleFunc("/products", handler).Methods("POST") + r.HandleFunc("/articles", handler).Methods("GET") + r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") + r.HandleFunc("/authors", handler).Queries("surname", "{surname}") + err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { + pathTemplate, err := route.GetPathTemplate() + if err == nil { + fmt.Println("ROUTE:", pathTemplate) + } + pathRegexp, err := route.GetPathRegexp() + if err == nil { + fmt.Println("Path regexp:", pathRegexp) + } + queriesTemplates, err := route.GetQueriesTemplates() + if err == nil { + fmt.Println("Queries templates:", strings.Join(queriesTemplates, ",")) + } + queriesRegexps, err := route.GetQueriesRegexp() + if err == nil { + fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ",")) + } + methods, err := route.GetMethods() + if err == nil { + fmt.Println("Methods:", strings.Join(methods, ",")) + } + fmt.Println() + return nil + }) + + if err != nil { + fmt.Println(err) + } + + http.Handle("/", r) +} +``` + +### Graceful Shutdown + +Go 1.8 introduced the ability to [gracefully shutdown](https://golang.org/doc/go1.8#http_shutdown) a `*http.Server`. Here's how to do that alongside `mux`: + +```go +package main + +import ( + "context" + "flag" + "log" + "net/http" + "os" + "os/signal" + "time" + + "github.com/gorilla/mux" +) + +func main() { + var wait time.Duration + flag.DurationVar(&wait, "graceful-timeout", time.Second * 15, "the duration for which the server gracefully wait for existing connections to finish - e.g. 15s or 1m") + flag.Parse() + + r := mux.NewRouter() + // Add your routes as needed + + srv := &http.Server{ + Addr: "0.0.0.0:8080", + // Good practice to set timeouts to avoid Slowloris attacks. + WriteTimeout: time.Second * 15, + ReadTimeout: time.Second * 15, + IdleTimeout: time.Second * 60, + Handler: r, // Pass our instance of gorilla/mux in. + } + + // Run our server in a goroutine so that it doesn't block. + go func() { + if err := srv.ListenAndServe(); err != nil { + log.Println(err) + } + }() + + c := make(chan os.Signal, 1) + // We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C) + // SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught. + signal.Notify(c, os.Interrupt) + + // Block until we receive our signal. + <-c + + // Create a deadline to wait for. + ctx, cancel := context.WithTimeout(context.Background(), wait) + defer cancel() + // Doesn't block if no connections, but will otherwise wait + // until the timeout deadline. + srv.Shutdown(ctx) + // Optionally, you could run srv.Shutdown in a goroutine and block on + // <-ctx.Done() if your application should wait for other services + // to finalize based on context cancellation. + log.Println("shutting down") + os.Exit(0) +} +``` + +### Middleware + +Mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed in the order they are added if a match is found, including its subrouters. +Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or `ResponseWriter` hijacking. + +Mux middlewares are defined using the de facto standard type: + +```go +type MiddlewareFunc func(http.Handler) http.Handler +``` + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc. This takes advantage of closures being able access variables from the context where they are created, while retaining the signature enforced by the receivers. + +A very basic middleware which logs the URI of the request being handled could be written as: + +```go +func loggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) +} +``` + +Middlewares can be added to a router using `Router.Use()`: + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) +r.Use(loggingMiddleware) +``` + +A more complex authentication middleware, which maps session token to users, could be written as: + +```go +// Define our struct +type authenticationMiddleware struct { + tokenUsers map[string]string +} + +// Initialize it somewhere +func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" +} + +// Middleware function, which will be called for each request +func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + // Pass down the request to the next middleware (or final handler) + next.ServeHTTP(w, r) + } else { + // Write an error and stop the handler chain + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) +} +``` + +```go +r := mux.NewRouter() +r.HandleFunc("/", handler) + +amw := authenticationMiddleware{tokenUsers: make(map[string]string)} +amw.Populate() + +r.Use(amw.Middleware) +``` + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it. + +### Handling CORS Requests + +[CORSMethodMiddleware](https://godoc.org/github.com/gorilla/mux#CORSMethodMiddleware) intends to make it easier to strictly set the `Access-Control-Allow-Methods` response header. + +* You will still need to use your own CORS handler to set the other CORS headers such as `Access-Control-Allow-Origin` +* The middleware will set the `Access-Control-Allow-Methods` header to all the method matchers (e.g. `r.Methods(http.MethodGet, http.MethodPut, http.MethodOptions)` -> `Access-Control-Allow-Methods: GET,PUT,OPTIONS`) on a route +* If you do not specify any methods, then: +> _Important_: there must be an `OPTIONS` method matcher for the middleware to set the headers. + +Here is an example of using `CORSMethodMiddleware` along with a custom `OPTIONS` handler to set all the required CORS headers: + +```go +package main + +import ( + "net/http" + "github.com/gorilla/mux" +) + +func main() { + r := mux.NewRouter() + + // IMPORTANT: you must specify an OPTIONS method matcher for the middleware to set CORS headers + r.HandleFunc("/foo", fooHandler).Methods(http.MethodGet, http.MethodPut, http.MethodPatch, http.MethodOptions) + r.Use(mux.CORSMethodMiddleware(r)) + + http.ListenAndServe(":8080", r) +} + +func fooHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + if r.Method == http.MethodOptions { + return + } + + w.Write([]byte("foo")) +} +``` + +And an request to `/foo` using something like: + +```bash +curl localhost:8080/foo -v +``` + +Would look like: + +```bash +* Trying ::1... +* TCP_NODELAY set +* Connected to localhost (::1) port 8080 (#0) +> GET /foo HTTP/1.1 +> Host: localhost:8080 +> User-Agent: curl/7.59.0 +> Accept: */* +> +< HTTP/1.1 200 OK +< Access-Control-Allow-Methods: GET,PUT,PATCH,OPTIONS +< Access-Control-Allow-Origin: * +< Date: Fri, 28 Jun 2019 20:13:30 GMT +< Content-Length: 3 +< Content-Type: text/plain; charset=utf-8 +< +* Connection #0 to host localhost left intact +foo +``` + +### Testing Handlers + +Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_. + +First, our simple HTTP handler: + +```go +// endpoints.go +package main + +func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { + // A very simple health check. + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + // In the future we could report back on the status of our DB, or our cache + // (e.g. Redis) by performing a simple PING, and include them in the response. + io.WriteString(w, `{"alive": true}`) +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/health", HealthCheckHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test code: + +```go +// endpoints_test.go +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestHealthCheckHandler(t *testing.T) { + // Create a request to pass to our handler. We don't have any query parameters for now, so we'll + // pass 'nil' as the third parameter. + req, err := http.NewRequest("GET", "/health", nil) + if err != nil { + t.Fatal(err) + } + + // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. + rr := httptest.NewRecorder() + handler := http.HandlerFunc(HealthCheckHandler) + + // Our handlers satisfy http.Handler, so we can call their ServeHTTP method + // directly and pass in our Request and ResponseRecorder. + handler.ServeHTTP(rr, req) + + // Check the status code is what we expect. + if status := rr.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + status, http.StatusOK) + } + + // Check the response body is what we expect. + expected := `{"alive": true}` + if rr.Body.String() != expected { + t.Errorf("handler returned unexpected body: got %v want %v", + rr.Body.String(), expected) + } +} +``` + +In the case that our routes have [variables](#examples), we can pass those in the request. We could write +[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple +possible route variables as needed. + +```go +// endpoints.go +func main() { + r := mux.NewRouter() + // A route with a route variable: + r.HandleFunc("/metrics/{type}", MetricsHandler) + + log.Fatal(http.ListenAndServe("localhost:8080", r)) +} +``` + +Our test file, with a table-driven test of `routeVariables`: + +```go +// endpoints_test.go +func TestMetricsHandler(t *testing.T) { + tt := []struct{ + routeVariable string + shouldPass bool + }{ + {"goroutines", true}, + {"heap", true}, + {"counters", true}, + {"queries", true}, + {"adhadaeqm3k", false}, + } + + for _, tc := range tt { + path := fmt.Sprintf("/metrics/%s", tc.routeVariable) + req, err := http.NewRequest("GET", path, nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + + // To add the vars to the context, + // we need to create a router through which we can pass the request. + router := mux.NewRouter() + router.HandleFunc("/metrics/{type}", MetricsHandler) + router.ServeHTTP(rr, req) + + // In this case, our MetricsHandler returns a non-200 response + // for a route variable it doesn't know about. + if rr.Code == http.StatusOK && !tc.shouldPass { + t.Errorf("handler should have failed on routeVariable %s: got %v want %v", + tc.routeVariable, rr.Code, http.StatusOK) + } + } +} +``` + +## Full Example + +Here's a complete, runnable example of a small `mux` based server: + +```go +package main + +import ( + "net/http" + "log" + "github.com/gorilla/mux" +) + +func YourHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Gorilla!\n")) +} + +func main() { + r := mux.NewRouter() + // Routes consist of a path and a handler function. + r.HandleFunc("/", YourHandler) - // Bind to a port and pass our router in - http.ListenAndServe(":8000", r) + // Bind to a port and pass our router in + log.Fatal(http.ListenAndServe(":8000", r)) } ``` diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go index 835f5342e..80601351f 100644 --- a/vendor/github.com/gorilla/mux/doc.go +++ b/vendor/github.com/gorilla/mux/doc.go @@ -10,18 +10,18 @@ http.ServeMux, mux.Router matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are: - * Requests can be matched based on URL host, path, path prefix, schemes, - header and query values, HTTP methods or using custom matchers. - * URL hosts and paths can have variables with an optional regular - expression. - * Registered URLs can be built, or "reversed", which helps maintaining - references to resources. - * Routes can be used as subrouters: nested routes are only tested if the - parent route matches. This is useful to define groups of routes that - share common conditions like a host, a path prefix or other repeated - attributes. As a bonus, this optimizes request matching. - * It implements the http.Handler interface so it is compatible with the - standard http.ServeMux. + - Requests can be matched based on URL host, path, path prefix, schemes, + header and query values, HTTP methods or using custom matchers. + - URL hosts, paths and query values can have variables with an optional + regular expression. + - Registered URLs can be built, or "reversed", which helps maintaining + references to resources. + - Routes can be used as subrouters: nested routes are only tested if the + parent route matches. This is useful to define groups of routes that + share common conditions like a host, a path prefix or other repeated + attributes. As a bonus, this optimizes request matching. + - It implements the http.Handler interface so it is compatible with the + standard http.ServeMux. Let's start registering a couple of URL paths and handlers: @@ -47,12 +47,21 @@ variable will be anything until the next slash. For example: r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) +Groups can be used inside patterns, as long as they are non-capturing (?:re). For example: + + r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler) + The names are used to create a map of route variables which can be retrieved calling mux.Vars(): vars := mux.Vars(request) category := vars["category"] +Note that if any capturing groups are present, mux will panic() during parsing. To prevent +this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to +"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably +when capturing groups were present. + And this is all you need to know about the basic usage. More advanced options are explained below. @@ -136,6 +145,31 @@ the inner routes use it as base for their paths: // "/products/{key}/details" s.HandleFunc("/{key}/details", ProductDetailsHandler) +Note that the path provided to PathPrefix() represents a "wildcard": calling +PathPrefix("/static/").Handler(...) means that the handler will be passed any +request that matches "/static/*". This makes it easy to serve static files with mux: + + func main() { + var dir string + + flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir") + flag.Parse() + r := mux.NewRouter() + + // This will serve files under http://localhost:8000/static/ + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir)))) + + srv := &http.Server{ + Handler: r, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) + } + Now let's see how to build registered URLs. Routes can be named. All routes that define a name can have their URLs built, @@ -154,18 +188,20 @@ key/value pairs for the route variables. For the previous route, we would do: "/articles/technology/42" -This also works for host variables: +This also works for host and query value variables: r := mux.NewRouter() r.Host("{subdomain}.domain.com"). Path("/articles/{category}/{id:[0-9]+}"). + Queries("filter", "{filter}"). HandlerFunc(ArticleHandler). Name("article") - // url.String() will be "http://news.domain.com/articles/technology/42" + // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" url, err := r.Get("article").URL("subdomain", "news", "category", "technology", - "id", "42") + "id", "42", + "filter", "gorilla") All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a @@ -202,5 +238,68 @@ as well: url, err := r.Get("article").URL("subdomain", "news", "category", "technology", "id", "42") + +Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking. + + type MiddlewareFunc func(http.Handler) http.Handler + +Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created). + +A very basic middleware which logs the URI of the request being handled could be written as: + + func simpleMw(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println(r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) + } + +Middlewares can be added to a router using `Router.Use()`: + + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.Use(simpleMw) + +A more complex authentication middleware, which maps session token to users, could be written as: + + // Define our struct + type authenticationMiddleware struct { + tokenUsers map[string]string + } + + // Initialize it somewhere + func (amw *authenticationMiddleware) Populate() { + amw.tokenUsers["00000000"] = "user0" + amw.tokenUsers["aaaaaaaa"] = "userA" + amw.tokenUsers["05f717e5"] = "randomUser" + amw.tokenUsers["deadbeef"] = "user0" + } + + // Middleware function, which will be called for each request + func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("X-Session-Token") + + if user, found := amw.tokenUsers[token]; found { + // We found the token in our map + log.Printf("Authenticated user %s\n", user) + next.ServeHTTP(w, r) + } else { + http.Error(w, "Forbidden", http.StatusForbidden) + } + }) + } + + r := mux.NewRouter() + r.HandleFunc("/", handler) + + amw := authenticationMiddleware{tokenUsers: make(map[string]string)} + amw.Populate() + + r.Use(amw.Middleware) + +Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. */ package mux diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go new file mode 100644 index 000000000..cb51c565e --- /dev/null +++ b/vendor/github.com/gorilla/mux/middleware.go @@ -0,0 +1,74 @@ +package mux + +import ( + "net/http" + "strings" +) + +// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler. +// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed +// to it, and then calls the handler passed as parameter to the MiddlewareFunc. +type MiddlewareFunc func(http.Handler) http.Handler + +// middleware interface is anything which implements a MiddlewareFunc named Middleware. +type middleware interface { + Middleware(handler http.Handler) http.Handler +} + +// Middleware allows MiddlewareFunc to implement the middleware interface. +func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler { + return mw(handler) +} + +// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. +func (r *Router) Use(mwf ...MiddlewareFunc) { + for _, fn := range mwf { + r.middlewares = append(r.middlewares, fn) + } +} + +// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. +func (r *Router) useInterface(mw middleware) { + r.middlewares = append(r.middlewares, mw) +} + +// CORSMethodMiddleware automatically sets the Access-Control-Allow-Methods response header +// on requests for routes that have an OPTIONS method matcher to all the method matchers on +// the route. Routes that do not explicitly handle OPTIONS requests will not be processed +// by the middleware. See examples for usage. +func CORSMethodMiddleware(r *Router) MiddlewareFunc { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + allMethods, err := getAllMethodsForRoute(r, req) + if err == nil { + for _, v := range allMethods { + if v == http.MethodOptions { + w.Header().Set("Access-Control-Allow-Methods", strings.Join(allMethods, ",")) + } + } + } + + next.ServeHTTP(w, req) + }) + } +} + +// getAllMethodsForRoute returns all the methods from method matchers matching a given +// request. +func getAllMethodsForRoute(r *Router, req *http.Request) ([]string, error) { + var allMethods []string + + for _, route := range r.routes { + var match RouteMatch + if route.Match(req, &match) || match.MatchErr == ErrMethodMismatch { + methods, err := route.GetMethods() + if err != nil { + return nil, err + } + + allMethods = append(allMethods, methods...) + } + } + + return allMethods, nil +} diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go index 94f5ddd9c..1e089906f 100644 --- a/vendor/github.com/gorilla/mux/mux.go +++ b/vendor/github.com/gorilla/mux/mux.go @@ -5,18 +5,25 @@ package mux import ( + "context" "errors" "fmt" "net/http" "path" "regexp" +) - "github.com/gorilla/context" +var ( + // ErrMethodMismatch is returned when the method in the request does not match + // the method defined against the route. + ErrMethodMismatch = errors.New("method is not allowed") + // ErrNotFound is returned when no route match is found. + ErrNotFound = errors.New("no matching route was found") ) // NewRouter returns a new router instance. func NewRouter() *Router { - return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} + return &Router{namedRoutes: make(map[string]*Route)} } // Router registers routes to be matched and dispatches a handler. @@ -24,49 +31,140 @@ func NewRouter() *Router { // It implements the http.Handler interface, so it can be registered to serve // requests: // -// var router = mux.NewRouter() +// var router = mux.NewRouter() // -// func main() { -// http.Handle("/", router) -// } +// func main() { +// http.Handle("/", router) +// } // // Or, for Google App Engine, register it in a init() function: // -// func init() { -// http.Handle("/", router) -// } +// func init() { +// http.Handle("/", router) +// } // // This will send all incoming requests to the router. type Router struct { // Configurable Handler to be used when no route matches. + // This can be used to render your own 404 Not Found errors. NotFoundHandler http.Handler - // Parent route, if this is a subrouter. - parent parentRoute + + // Configurable Handler to be used when the request method does not match the route. + // This can be used to render your own 405 Method Not Allowed errors. + MethodNotAllowedHandler http.Handler + // Routes to be matched, in order. routes []*Route + // Routes by name for URL building. namedRoutes map[string]*Route - // See Router.StrictSlash(). This defines the flag for new routes. + + // If true, do not clear the request context after handling the request. + // + // Deprecated: No effect, since the context is stored on the request itself. + KeepContext bool + + // Slice of middlewares to be called after a match is found + middlewares []middleware + + // configuration shared with `Route` + routeConf +} + +// common route configuration shared between `Router` and `Route` +type routeConf struct { + // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to" + useEncodedPath bool + + // If true, when the path pattern is "/path/", accessing "/path" will + // redirect to the former and vice versa. strictSlash bool - // See Router.SkipClean(). This defines the flag for new routes. + + // If true, when the path pattern is "/path//to", accessing "/path//to" + // will not redirect skipClean bool - // If true, do not clear the request context after handling the request - KeepContext bool + + // Manager for the variables from host and path. + regexp routeRegexpGroup + + // List of matchers. + matchers []matcher + + // The scheme used when building URLs. + buildScheme string + + buildVarsFunc BuildVarsFunc } -// Match matches registered routes against the request. +// returns an effective deep copy of `routeConf` +func copyRouteConf(r routeConf) routeConf { + c := r + + if r.regexp.path != nil { + c.regexp.path = copyRouteRegexp(r.regexp.path) + } + + if r.regexp.host != nil { + c.regexp.host = copyRouteRegexp(r.regexp.host) + } + + c.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries)) + for _, q := range r.regexp.queries { + c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q)) + } + + c.matchers = make([]matcher, len(r.matchers)) + copy(c.matchers, r.matchers) + + return c +} + +func copyRouteRegexp(r *routeRegexp) *routeRegexp { + c := *r + return &c +} + +// Match attempts to match the given request against the router's registered routes. +// +// If the request matches a route of this router or one of its subrouters the Route, +// Handler, and Vars fields of the the match argument are filled and this function +// returns true. +// +// If the request does not match any of this router's or its subrouters' routes +// then this function returns false. If available, a reason for the match failure +// will be filled in the match argument's MatchErr field. If the match failure type +// (eg: not found) has a registered handler, the handler is assigned to the Handler +// field of the match argument. func (r *Router) Match(req *http.Request, match *RouteMatch) bool { for _, route := range r.routes { if route.Match(req, match) { + // Build middleware chain if no error was found + if match.MatchErr == nil { + for i := len(r.middlewares) - 1; i >= 0; i-- { + match.Handler = r.middlewares[i].Middleware(match.Handler) + } + } return true } } + if match.MatchErr == ErrMethodMismatch { + if r.MethodNotAllowedHandler != nil { + match.Handler = r.MethodNotAllowedHandler + return true + } + + return false + } + // Closest match for a router (includes sub-routers) if r.NotFoundHandler != nil { match.Handler = r.NotFoundHandler + match.MatchErr = ErrNotFound return true } + + match.MatchErr = ErrNotFound return false } @@ -76,8 +174,12 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool { // mux.Vars(request). func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if !r.skipClean { + path := req.URL.Path + if r.useEncodedPath { + path = req.URL.EscapedPath() + } // Clean path to canonical form and redirect. - if p := cleanPath(req.URL.Path); p != req.URL.Path { + if p := cleanPath(path); p != path { // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query. // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: @@ -95,39 +197,47 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { var handler http.Handler if r.Match(req, &match) { handler = match.Handler - setVars(req, match.Vars) - setCurrentRoute(req, match.Route) + req = requestWithVars(req, match.Vars) + req = requestWithRoute(req, match.Route) + } + + if handler == nil && match.MatchErr == ErrMethodMismatch { + handler = methodNotAllowedHandler() } + if handler == nil { handler = http.NotFoundHandler() } - if !r.KeepContext { - defer context.Clear(req) - } + handler.ServeHTTP(w, req) } // Get returns a route registered with the given name. func (r *Router) Get(name string) *Route { - return r.getNamedRoutes()[name] + return r.namedRoutes[name] } // GetRoute returns a route registered with the given name. This method // was renamed to Get() and remains here for backwards compatibility. func (r *Router) GetRoute(name string) *Route { - return r.getNamedRoutes()[name] + return r.namedRoutes[name] } // StrictSlash defines the trailing slash behavior for new routes. The initial // value is false. // -// When true, if the route path is "/path/", accessing "/path" will redirect +// When true, if the route path is "/path/", accessing "/path" will perform a redirect // to the former and vice versa. In other words, your application will always // see the path as specified in the route. // // When false, if the route path is "/path", accessing "/path/" will not match // this route and vice versa. // +// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for +// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed +// request will be made as a GET by most clients. Use middleware or client settings +// to modify this behaviour as needed. +// // Special case: when a route sets a path prefix using the PathPrefix() method, // strict slash is ignored for that route because the redirect behavior can't // be determined from a prefix alone. However, any subrouters created from that @@ -150,35 +260,15 @@ func (r *Router) SkipClean(value bool) *Router { return r } -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// getNamedRoutes returns the map where named routes are registered. -func (r *Router) getNamedRoutes() map[string]*Route { - if r.namedRoutes == nil { - if r.parent != nil { - r.namedRoutes = r.parent.getNamedRoutes() - } else { - r.namedRoutes = make(map[string]*Route) - } - } - return r.namedRoutes -} - -// getRegexpGroup returns regexp definitions from the parent route, if any. -func (r *Router) getRegexpGroup() *routeRegexpGroup { - if r.parent != nil { - return r.parent.getRegexpGroup() - } - return nil -} - -func (r *Router) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } - return m +// UseEncodedPath tells the router to match the encoded original path +// to the routes. +// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to". +// +// If not called, the router will match the unencoded path to the routes. +// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to" +func (r *Router) UseEncodedPath() *Router { + r.useEncodedPath = true + return r } // ---------------------------------------------------------------------------- @@ -187,11 +277,18 @@ func (r *Router) buildVars(m map[string]string) map[string]string { // NewRoute registers an empty route. func (r *Router) NewRoute() *Route { - route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean} + // initialize a route with a copy of the parent router's configuration + route := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes} r.routes = append(r.routes, route) return route } +// Name registers a new route with a name. +// See Route.Name(). +func (r *Router) Name(name string) *Route { + return r.NewRoute().Name(name) +} + // Handle registers a new route with a matcher for the URL path. // See Route.Path() and Route.Handler(). func (r *Router) Handle(path string, handler http.Handler) *Route { @@ -277,20 +374,21 @@ type WalkFunc func(route *Route, router *Router, ancestors []*Route) error func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error { for _, t := range r.routes { - if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" { - continue - } - err := walkFn(t, r, ancestors) if err == SkipRouter { continue } + if err != nil { + return err + } for _, sr := range t.matchers { if h, ok := sr.(*Router); ok { + ancestors = append(ancestors, t) err := h.walk(walkFn, ancestors) if err != nil { return err } + ancestors = ancestors[:len(ancestors)-1] } } if h, ok := t.handler.(*Router); ok { @@ -314,6 +412,11 @@ type RouteMatch struct { Route *Route Handler http.Handler Vars map[string]string + + // MatchErr is set to appropriate matching error + // It is set to ErrMethodMismatch if there is a mismatch in + // the request method and route method + MatchErr error } type contextKey int @@ -325,7 +428,7 @@ const ( // Vars returns the route variables for the current request, if any. func Vars(r *http.Request) map[string]string { - if rv := context.Get(r, varsKey); rv != nil { + if rv := r.Context().Value(varsKey); rv != nil { return rv.(map[string]string) } return nil @@ -334,25 +437,22 @@ func Vars(r *http.Request) map[string]string { // CurrentRoute returns the matched route for the current request, if any. // This only works when called inside the handler of the matched route // because the matched route is stored in the request context which is cleared -// after the handler returns, unless the KeepContext option is set on the -// Router. +// after the handler returns. func CurrentRoute(r *http.Request) *Route { - if rv := context.Get(r, routeKey); rv != nil { + if rv := r.Context().Value(routeKey); rv != nil { return rv.(*Route) } return nil } -func setVars(r *http.Request, val interface{}) { - if val != nil { - context.Set(r, varsKey, val) - } +func requestWithVars(r *http.Request, vars map[string]string) *http.Request { + ctx := context.WithValue(r.Context(), varsKey, vars) + return r.WithContext(ctx) } -func setCurrentRoute(r *http.Request, val interface{}) { - if val != nil { - context.Set(r, routeKey, val) - } +func requestWithRoute(r *http.Request, route *Route) *http.Request { + ctx := context.WithValue(r.Context(), routeKey, route) + return r.WithContext(ctx) } // ---------------------------------------------------------------------------- @@ -415,7 +515,7 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) { return m, nil } -// mapFromPairsToRegex converts variadic string paramers to a +// mapFromPairsToRegex converts variadic string parameters to a // string to regex map. func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) { length, err := checkPairs(pairs...) @@ -497,3 +597,12 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s } return true } + +// methodNotAllowed replies to the request with an HTTP status code 405. +func methodNotAllowed(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusMethodNotAllowed) +} + +// methodNotAllowedHandler returns a simple request handler +// that replies to each request with a status code 405. +func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) } diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index 08710bc98..5d05cfa0e 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -14,6 +14,20 @@ import ( "strings" ) +type routeRegexpOptions struct { + strictSlash bool + useEncodedPath bool +} + +type regexpType int + +const ( + regexpTypePath regexpType = iota + regexpTypeHost + regexpTypePrefix + regexpTypeQuery +) + // newRouteRegexp parses a route template and returns a routeRegexp, // used to match a host, a path or a query string. // @@ -24,7 +38,7 @@ import ( // Previously we accepted only Python-like identifiers for variable // names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that // name and pattern can't be empty, and names can't contain a colon. -func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { +func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) { // Check if it is well-formed. idxs, errBraces := braceIndices(tpl) if errBraces != nil { @@ -34,19 +48,18 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash template := tpl // Now let's parse it. defaultPattern := "[^/]+" - if matchQuery { - defaultPattern = "[^?&]*" - } else if matchHost { + if typ == regexpTypeQuery { + defaultPattern = ".*" + } else if typ == regexpTypeHost { defaultPattern = "[^.]+" - matchPrefix = false } // Only match strict slash if not matching - if matchPrefix || matchHost || matchQuery { - strictSlash = false + if typ != regexpTypePath { + options.strictSlash = false } // Set a flag for strictSlash. endSlash := false - if strictSlash && strings.HasSuffix(tpl, "/") { + if options.strictSlash && strings.HasSuffix(tpl, "/") { tpl = tpl[:len(tpl)-1] endSlash = true } @@ -88,18 +101,25 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash // Add the remaining. raw := tpl[end:] pattern.WriteString(regexp.QuoteMeta(raw)) - if strictSlash { + if options.strictSlash { pattern.WriteString("[/]?") } - if matchQuery { + if typ == regexpTypeQuery { // Add the default pattern if the query value is empty if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { pattern.WriteString(defaultPattern) } } - if !matchPrefix { + if typ != regexpTypePrefix { pattern.WriteByte('$') } + + var wildcardHostPort bool + if typ == regexpTypeHost { + if !strings.Contains(pattern.String(), ":") { + wildcardHostPort = true + } + } reverse.WriteString(raw) if endSlash { reverse.WriteByte('/') @@ -109,16 +129,23 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash if errCompile != nil { return nil, errCompile } + + // Check for capturing groups which used to work in older versions + if reg.NumSubexp() != len(idxs)/2 { + panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + + "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") + } + // Done! return &routeRegexp{ - template: template, - matchHost: matchHost, - matchQuery: matchQuery, - strictSlash: strictSlash, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, + template: template, + regexpType: typ, + options: options, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, + wildcardHostPort: wildcardHostPort, }, nil } @@ -127,12 +154,10 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash type routeRegexp struct { // The unmodified template. template string - // True for host match, false for path or query string match. - matchHost bool - // True for query string match, false for path and host match. - matchQuery bool - // The strictSlash value defined on the route, but disabled if PathPrefix was used. - strictSlash bool + // The type of match + regexpType regexpType + // Options for matching + options routeRegexpOptions // Expanded regexp. regexp *regexp.Regexp // Reverse template. @@ -141,19 +166,31 @@ type routeRegexp struct { varsN []string // Variable regexps (validators). varsR []*regexp.Regexp + // Wildcard host-port (no strict port match in hostname) + wildcardHostPort bool } // Match matches the regexp against the URL host or path. func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if !r.matchHost { - if r.matchQuery { - return r.matchQueryString(req) + if r.regexpType == regexpTypeHost { + host := getHost(req) + if r.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } } - - return r.regexp.MatchString(req.URL.Path) + return r.regexp.MatchString(host) } - return r.regexp.MatchString(getHost(req)) + if r.regexpType == regexpTypeQuery { + return r.matchQueryString(req) + } + path := req.URL.Path + if r.options.useEncodedPath { + path = req.URL.EscapedPath() + } + return r.regexp.MatchString(path) } // url builds a URL part using the given values. @@ -164,6 +201,9 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { if !ok { return "", fmt.Errorf("mux: missing route variable %q", v) } + if r.regexpType == regexpTypeQuery { + value = url.QueryEscape(value) + } urlValues[k] = value } rv := fmt.Sprintf(r.reverse, urlValues...) @@ -186,18 +226,55 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { // For a URL with foo=bar&baz=ding, we return only the relevant key // value pair for the routeRegexp. func (r *routeRegexp) getURLQuery(req *http.Request) string { - if !r.matchQuery { + if r.regexpType != regexpTypeQuery { return "" } templateKey := strings.SplitN(r.template, "=", 2)[0] - for key, vals := range req.URL.Query() { - if key == templateKey && len(vals) > 0 { - return key + "=" + vals[0] - } + val, ok := findFirstQueryKey(req.URL.RawQuery, templateKey) + if ok { + return templateKey + "=" + val } return "" } +// findFirstQueryKey returns the same result as (*url.URL).Query()[key][0]. +// If key was not found, empty string and false is returned. +func findFirstQueryKey(rawQuery, key string) (value string, ok bool) { + query := []byte(rawQuery) + for len(query) > 0 { + foundKey := query + if i := bytes.IndexAny(foundKey, "&;"); i >= 0 { + foundKey, query = foundKey[:i], foundKey[i+1:] + } else { + query = query[:0] + } + if len(foundKey) == 0 { + continue + } + var value []byte + if i := bytes.IndexByte(foundKey, '='); i >= 0 { + foundKey, value = foundKey[:i], foundKey[i+1:] + } + if len(foundKey) < len(key) { + // Cannot possibly be key. + continue + } + keyString, err := url.QueryUnescape(string(foundKey)) + if err != nil { + continue + } + if keyString != key { + continue + } + valueString, err := url.QueryUnescape(string(value)) + if err != nil { + continue + } + return valueString, true + } + return "", false +} + func (r *routeRegexp) matchQueryString(req *http.Request) bool { return r.regexp.MatchString(r.getURLQuery(req)) } @@ -244,23 +321,33 @@ type routeRegexpGroup struct { } // setMatch extracts the variables from the URL once a route matches. -func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { +func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { // Store host variables. if v.host != nil { host := getHost(req) + if v.host.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } + } matches := v.host.regexp.FindStringSubmatchIndex(host) if len(matches) > 0 { extractVars(host, matches, v.host.varsN, m.Vars) } } + path := req.URL.Path + if r.useEncodedPath { + path = req.URL.EscapedPath() + } // Store path variables. if v.path != nil { - matches := v.path.regexp.FindStringSubmatchIndex(req.URL.Path) + matches := v.path.regexp.FindStringSubmatchIndex(path) if len(matches) > 0 { - extractVars(req.URL.Path, matches, v.path.varsN, m.Vars) + extractVars(path, matches, v.path.varsN, m.Vars) // Check if we should redirect. - if v.path.strictSlash { - p1 := strings.HasSuffix(req.URL.Path, "/") + if v.path.options.strictSlash { + p1 := strings.HasSuffix(path, "/") p2 := strings.HasSuffix(v.path.template, "/") if p1 != p2 { u, _ := url.Parse(req.URL.String()) @@ -269,7 +356,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } else { u.Path += "/" } - m.Handler = http.RedirectHandler(u.String(), 301) + m.Handler = http.RedirectHandler(u.String(), http.StatusMovedPermanently) } } } @@ -285,28 +372,17 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } // getHost tries its best to return the request host. +// According to section 14.23 of RFC 2616 the Host header +// can include the port number if the default value of 80 is not used. func getHost(r *http.Request) string { if r.URL.IsAbs() { return r.URL.Host } - host := r.Host - // Slice off any port information. - if i := strings.Index(host, ":"); i != -1 { - host = host[:i] - } - return host - + return r.Host } func extractVars(input string, matches []int, names []string, output map[string]string) { - matchesCount := 0 - prevEnd := -1 - for i := 2; i < len(matches) && matchesCount < len(names); i += 2 { - if prevEnd < matches[i+1] { - value := input[matches[i]:matches[i+1]] - output[names[matchesCount]] = value - prevEnd = matches[i+1] - matchesCount++ - } + for i, name := range names { + output[name] = input[matches[2*i+2]:matches[2*i+3]] } } diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go index 6c53f9f1d..e8f11df22 100644 --- a/vendor/github.com/gorilla/mux/route.go +++ b/vendor/github.com/gorilla/mux/route.go @@ -15,20 +15,8 @@ import ( // Route stores information to match a request and build URLs. type Route struct { - // Parent where the route was registered (a Router). - parent parentRoute // Request handler for the route. handler http.Handler - // List of matchers. - matchers []matcher - // Manager for the variables from host and path. - regexp *routeRegexpGroup - // If true, when the path pattern is "/path/", accessing "/path" will - // redirect to the former and vice versa. - strictSlash bool - // If true, when the path pattern is "/path//to", accessing "/path//to" - // will not redirect - skipClean bool // If true, this route never matches: it is only used to build URLs. buildOnly bool // The name used to build URLs. @@ -36,9 +24,15 @@ type Route struct { // Error resulted from building a route. err error - buildVarsFunc BuildVarsFunc + // "global" reference to all named routes + namedRoutes map[string]*Route + + // config possibly passed in from `Router` + routeConf } +// SkipClean reports whether path cleaning is enabled for this route via +// Router.SkipClean. func (r *Route) SkipClean() bool { return r.skipClean } @@ -48,12 +42,55 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if r.buildOnly || r.err != nil { return false } + + var matchErr error + // Match everything. for _, m := range r.matchers { if matched := m.Match(req, match); !matched { + if _, ok := m.(methodMatcher); ok { + matchErr = ErrMethodMismatch + continue + } + + // Ignore ErrNotFound errors. These errors arise from match call + // to Subrouters. + // + // This prevents subsequent matching subrouters from failing to + // run middleware. If not ignored, the middleware would see a + // non-nil MatchErr and be skipped, even when there was a + // matching route. + if match.MatchErr == ErrNotFound { + match.MatchErr = nil + } + + matchErr = nil // nolint:ineffassign return false + } else { + // Multiple routes may share the same path but use different HTTP methods. For instance: + // Route 1: POST "/users/{id}". + // Route 2: GET "/users/{id}", parameters: "id": "[0-9]+". + // + // The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2", + // The router should return a "Not Found" error as no route fully matches this request. + if match.MatchErr == ErrMethodMismatch { + match.MatchErr = nil + } } } + + if matchErr != nil { + match.MatchErr = matchErr + return false + } + + if match.MatchErr == ErrMethodMismatch && r.handler != nil { + // We found a route which matches request method, clear MatchErr + match.MatchErr = nil + // Then override the mis-matched handler + match.Handler = r.handler + } + // Yay, we have a match. Let's collect some info about it. if match.Route == nil { match.Route = r @@ -64,10 +101,9 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { if match.Vars == nil { match.Vars = make(map[string]string) } + // Set variables. - if r.regexp != nil { - r.regexp.setMatch(req, match, r) - } + r.regexp.setMatch(req, match, r) return true } @@ -109,7 +145,7 @@ func (r *Route) GetHandler() http.Handler { // Name ----------------------------------------------------------------------- // Name sets the name for the route, used to build URLs. -// If the name was registered already it will be overwritten. +// It is an error to call Name more than once on a route. func (r *Route) Name(name string) *Route { if r.name != "" { r.err = fmt.Errorf("mux: route already has name %q, can't set %q", @@ -117,7 +153,7 @@ func (r *Route) Name(name string) *Route { } if r.err == nil { r.name = name - r.getNamedRoutes()[name] = r + r.namedRoutes[name] = r } return r } @@ -145,20 +181,22 @@ func (r *Route) addMatcher(m matcher) *Route { } // addRegexpMatcher adds a host or path matcher and builder to a route. -func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { +func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { if r.err != nil { return r.err } - r.regexp = r.getRegexpGroup() - if !matchHost && !matchQuery { - if len(tpl) == 0 || tpl[0] != '/' { + if typ == regexpTypePath || typ == regexpTypePrefix { + if len(tpl) > 0 && tpl[0] != '/' { return fmt.Errorf("mux: path must start with a slash, got %q", tpl) } if r.regexp.path != nil { tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl } } - rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash) + rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ + strictSlash: r.strictSlash, + useEncodedPath: r.useEncodedPath, + }) if err != nil { return err } @@ -167,7 +205,7 @@ func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery return err } } - if matchHost { + if typ == regexpTypeHost { if r.regexp.path != nil { if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { return err @@ -180,7 +218,7 @@ func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery return err } } - if matchQuery { + if typ == regexpTypeQuery { r.regexp.queries = append(r.regexp.queries, rr) } else { r.regexp.path = rr @@ -202,9 +240,9 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { // Headers adds a matcher for request header values. // It accepts a sequence of key/value pairs to be matched. For example: // -// r := mux.NewRouter() -// r.Headers("Content-Type", "application/json", -// "X-Requested-With", "XMLHttpRequest") +// r := mux.NewRouter().NewRoute() +// r.Headers("Content-Type", "application/json", +// "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both request header values match. // If the value is an empty string, it will match any value if the key is set. @@ -227,12 +265,13 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool { // HeadersRegexp accepts a sequence of key/value pairs, where the value has regex // support. For example: // -// r := mux.NewRouter() -// r.HeadersRegexp("Content-Type", "application/(text|json)", -// "X-Requested-With", "XMLHttpRequest") +// r := mux.NewRouter().NewRoute() +// r.HeadersRegexp("Content-Type", "application/(text|json)", +// "X-Requested-With", "XMLHttpRequest") // // The above route will only match if both the request header matches both regular expressions. -// It the value is an empty string, it will match any value if the key is set. +// If the value is an empty string, it will match any value if the key is set. +// Use the start and end of string anchors (^ and $) to match an exact value. func (r *Route) HeadersRegexp(pairs ...string) *Route { if r.err == nil { var headers map[string]*regexp.Regexp @@ -254,15 +293,15 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route { // // For example: // -// r := mux.NewRouter() -// r.Host("www.example.com") -// r.Host("{subdomain}.domain.com") -// r.Host("{subdomain:[a-z]+}.domain.com") +// r := mux.NewRouter().NewRoute() +// r.Host("www.example.com") +// r.Host("{subdomain}.domain.com") +// r.Host("{subdomain:[a-z]+}.domain.com") // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Host(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, true, false, false) + r.err = r.addRegexpMatcher(tpl, regexpTypeHost) return r } @@ -313,16 +352,16 @@ func (r *Route) Methods(methods ...string) *Route { // // For example: // -// r := mux.NewRouter() -// r.Path("/products/").Handler(ProductsHandler) -// r.Path("/products/{key}").Handler(ProductsHandler) -// r.Path("/articles/{category}/{id:[0-9]+}"). -// Handler(ArticleHandler) +// r := mux.NewRouter().NewRoute() +// r.Path("/products/").Handler(ProductsHandler) +// r.Path("/products/{key}").Handler(ProductsHandler) +// r.Path("/articles/{category}/{id:[0-9]+}"). +// Handler(ArticleHandler) // // Variable names must be unique in a given route. They can be retrieved // calling mux.Vars(request). func (r *Route) Path(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, false, false) + r.err = r.addRegexpMatcher(tpl, regexpTypePath) return r } @@ -338,7 +377,7 @@ func (r *Route) Path(tpl string) *Route { // Also note that the setting of Router.StrictSlash() has no effect on routes // with a PathPrefix matcher. func (r *Route) PathPrefix(tpl string) *Route { - r.err = r.addRegexpMatcher(tpl, false, true, false) + r.err = r.addRegexpMatcher(tpl, regexpTypePrefix) return r } @@ -348,13 +387,13 @@ func (r *Route) PathPrefix(tpl string) *Route { // It accepts a sequence of key/value pairs. Values may define variables. // For example: // -// r := mux.NewRouter() -// r.Queries("foo", "bar", "id", "{id:[0-9]+}") +// r := mux.NewRouter().NewRoute() +// r.Queries("foo", "bar", "id", "{id:[0-9]+}") // // The above route will only match if the URL contains the defined queries // values, e.g.: ?foo=bar&id=42. // -// It the value is an empty string, it will match any value if the key is set. +// If the value is an empty string, it will match any value if the key is set. // // Variables can define an optional regexp pattern to be matched: // @@ -369,7 +408,7 @@ func (r *Route) Queries(pairs ...string) *Route { return nil } for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, false, true); r.err != nil { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil { return r } } @@ -383,15 +422,37 @@ func (r *Route) Queries(pairs ...string) *Route { type schemeMatcher []string func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.URL.Scheme) + scheme := r.URL.Scheme + // https://golang.org/pkg/net/http/#Request + // "For [most] server requests, fields other than Path and RawQuery will be + // empty." + // Since we're an http muxer, the scheme is either going to be http or https + // though, so we can just set it based on the tls termination state. + if scheme == "" { + if r.TLS == nil { + scheme = "http" + } else { + scheme = "https" + } + } + return matchInArray(m, scheme) } // Schemes adds a matcher for URL schemes. // It accepts a sequence of schemes to be matched, e.g.: "http", "https". +// If the request's URL has a scheme set, it will be matched against. +// Generally, the URL scheme will only be set if a previous handler set it, +// such as the ProxyHeaders handler from gorilla/handlers. +// If unset, the scheme will be determined based on the request's TLS +// termination state. +// The first argument to Schemes will be used when constructing a route URL. func (r *Route) Schemes(schemes ...string) *Route { for k, v := range schemes { schemes[k] = strings.ToLower(v) } + if len(schemes) > 0 { + r.buildScheme = schemes[0] + } return r.addMatcher(schemeMatcher(schemes)) } @@ -404,7 +465,15 @@ type BuildVarsFunc func(map[string]string) map[string]string // BuildVarsFunc adds a custom function to be used to modify build variables // before a route's URL is built. func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { - r.buildVarsFunc = f + if r.buildVarsFunc != nil { + // compose the old and new functions + old := r.buildVarsFunc + r.buildVarsFunc = func(m map[string]string) map[string]string { + return f(old(m)) + } + } else { + r.buildVarsFunc = f + } return r } @@ -414,16 +483,17 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { // // It will test the inner routes only if the parent route matched. For example: // -// r := mux.NewRouter() -// s := r.Host("www.example.com").Subrouter() -// s.HandleFunc("/products/", ProductsHandler) -// s.HandleFunc("/products/{key}", ProductHandler) -// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +// r := mux.NewRouter().NewRoute() +// s := r.Host("www.example.com").Subrouter() +// s.HandleFunc("/products/", ProductsHandler) +// s.HandleFunc("/products/{key}", ProductHandler) +// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) // // Here, the routes registered in the subrouter won't be tested if the host // doesn't match. func (r *Route) Subrouter() *Router { - router := &Router{parent: r, strictSlash: r.strictSlash} + // initialize a subrouter with a copy of the parent route's configuration + router := &Router{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes} r.addMatcher(router) return router } @@ -437,29 +507,36 @@ func (r *Route) Subrouter() *Router { // It accepts a sequence of key/value pairs for the route variables. For // example, given this route: // -// r := mux.NewRouter() -// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Name("article") // // ...a URL for it can be built using: // -// url, err := r.Get("article").URL("category", "technology", "id", "42") +// url, err := r.Get("article").URL("category", "technology", "id", "42") // // ...which will return an url.URL with the following path: // -// "/articles/technology/42" +// "/articles/technology/42" // // This also works for host variables: // -// r := mux.NewRouter() -// r.Host("{subdomain}.domain.com"). -// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). -// Name("article") +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Host("{subdomain}.domain.com"). +// Name("article") +// +// // url.String() will be "http://news.domain.com/articles/technology/42" +// url, err := r.Get("article").URL("subdomain", "news", +// "category", "technology", +// "id", "42") // -// // url.String() will be "http://news.domain.com/articles/technology/42" -// url, err := r.Get("article").URL("subdomain", "news", -// "category", "technology", -// "id", "42") +// The scheme of the resulting url will be the first argument that was passed to Schemes: +// +// // url.String() will be "https://example.com" +// r := mux.NewRouter().NewRoute() +// url, err := r.Host("example.com") +// .Schemes("https", "http").URL() // // All variables defined in the route are required, and their values must // conform to the corresponding patterns. @@ -467,30 +544,38 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) { if r.err != nil { return nil, r.err } - if r.regexp == nil { - return nil, errors.New("mux: route doesn't have a host or path") - } values, err := r.prepareVars(pairs...) if err != nil { return nil, err } var scheme, host, path string + queries := make([]string, 0, len(r.regexp.queries)) if r.regexp.host != nil { - // Set a default scheme. - scheme = "http" if host, err = r.regexp.host.url(values); err != nil { return nil, err } + scheme = "http" + if r.buildScheme != "" { + scheme = r.buildScheme + } } if r.regexp.path != nil { if path, err = r.regexp.path.url(values); err != nil { return nil, err } } + for _, q := range r.regexp.queries { + var query string + if query, err = q.url(values); err != nil { + return nil, err + } + queries = append(queries, query) + } return &url.URL{ - Scheme: scheme, - Host: host, - Path: path, + Scheme: scheme, + Host: host, + Path: path, + RawQuery: strings.Join(queries, "&"), }, nil } @@ -501,7 +586,7 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) { if r.err != nil { return nil, r.err } - if r.regexp == nil || r.regexp.host == nil { + if r.regexp.host == nil { return nil, errors.New("mux: route doesn't have a host") } values, err := r.prepareVars(pairs...) @@ -512,10 +597,14 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) { if err != nil { return nil, err } - return &url.URL{ + u := &url.URL{ Scheme: "http", Host: host, - }, nil + } + if r.buildScheme != "" { + u.Scheme = r.buildScheme + } + return u, nil } // URLPath builds the path part of the URL for a route. See Route.URL(). @@ -525,7 +614,7 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) { if r.err != nil { return nil, r.err } - if r.regexp == nil || r.regexp.path == nil { + if r.regexp.path == nil { return nil, errors.New("mux: route doesn't have a path") } values, err := r.prepareVars(pairs...) @@ -550,12 +639,80 @@ func (r *Route) GetPathTemplate() (string, error) { if r.err != nil { return "", r.err } - if r.regexp == nil || r.regexp.path == nil { + if r.regexp.path == nil { return "", errors.New("mux: route doesn't have a path") } return r.regexp.path.template, nil } +// GetPathRegexp returns the expanded regular expression used to match route path. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define a path. +func (r *Route) GetPathRegexp() (string, error) { + if r.err != nil { + return "", r.err + } + if r.regexp.path == nil { + return "", errors.New("mux: route does not have a path") + } + return r.regexp.path.regexp.String(), nil +} + +// GetQueriesRegexp returns the expanded regular expressions used to match the +// route queries. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not have queries. +func (r *Route) GetQueriesRegexp() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + queries := make([]string, 0, len(r.regexp.queries)) + for _, query := range r.regexp.queries { + queries = append(queries, query.regexp.String()) + } + return queries, nil +} + +// GetQueriesTemplates returns the templates used to build the +// query matching. +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if the route does not define queries. +func (r *Route) GetQueriesTemplates() ([]string, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp.queries == nil { + return nil, errors.New("mux: route doesn't have queries") + } + queries := make([]string, 0, len(r.regexp.queries)) + for _, query := range r.regexp.queries { + queries = append(queries, query.template) + } + return queries, nil +} + +// GetMethods returns the methods the route matches against +// This is useful for building simple REST API documentation and for instrumentation +// against third-party services. +// An error will be returned if route does not have methods. +func (r *Route) GetMethods() ([]string, error) { + if r.err != nil { + return nil, r.err + } + for _, m := range r.matchers { + if methods, ok := m.(methodMatcher); ok { + return []string(methods), nil + } + } + return nil, errors.New("mux: route doesn't have methods") +} + // GetHostTemplate returns the template used to build the // route match. // This is useful for building simple REST API documentation and for instrumentation @@ -565,12 +722,31 @@ func (r *Route) GetHostTemplate() (string, error) { if r.err != nil { return "", r.err } - if r.regexp == nil || r.regexp.host == nil { + if r.regexp.host == nil { return "", errors.New("mux: route doesn't have a host") } return r.regexp.host.template, nil } +// GetVarNames returns the names of all variables added by regexp matchers +// These can be used to know which route variables should be passed into r.URL() +func (r *Route) GetVarNames() ([]string, error) { + if r.err != nil { + return nil, r.err + } + var varNames []string + if r.regexp.host != nil { + varNames = append(varNames, r.regexp.host.varsN...) + } + if r.regexp.path != nil { + varNames = append(varNames, r.regexp.path.varsN...) + } + for _, regx := range r.regexp.queries { + varNames = append(varNames, regx.varsN...) + } + return varNames, nil +} + // prepareVars converts the route variable pairs into a map. If the route has a // BuildVarsFunc, it is invoked. func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { @@ -582,53 +758,8 @@ func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { } func (r *Route) buildVars(m map[string]string) map[string]string { - if r.parent != nil { - m = r.parent.buildVars(m) - } if r.buildVarsFunc != nil { m = r.buildVarsFunc(m) } return m } - -// ---------------------------------------------------------------------------- -// parentRoute -// ---------------------------------------------------------------------------- - -// parentRoute allows routes to know about parent host and path definitions. -type parentRoute interface { - getNamedRoutes() map[string]*Route - getRegexpGroup() *routeRegexpGroup - buildVars(map[string]string) map[string]string -} - -// getNamedRoutes returns the map where named routes are registered. -func (r *Route) getNamedRoutes() map[string]*Route { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - return r.parent.getNamedRoutes() -} - -// getRegexpGroup returns regexp definitions from this route. -func (r *Route) getRegexpGroup() *routeRegexpGroup { - if r.regexp == nil { - if r.parent == nil { - // During tests router is not always set. - r.parent = NewRouter() - } - regexp := r.parent.getRegexpGroup() - if regexp == nil { - r.regexp = new(routeRegexpGroup) - } else { - // Copy. - r.regexp = &routeRegexpGroup{ - host: regexp.host, - path: regexp.path, - queries: regexp.queries, - } - } - } - return r.regexp -} diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go new file mode 100644 index 000000000..5f5c496de --- /dev/null +++ b/vendor/github.com/gorilla/mux/test_helpers.go @@ -0,0 +1,19 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import "net/http" + +// SetURLVars sets the URL variables for the given request, to be accessed via +// mux.Vars for testing route behaviour. Arguments are not modified, a shallow +// copy is returned. +// +// This API should only be used for testing purposes; it provides a way to +// inject variables into the request context. Alternatively, URL variables +// can be set by making a route that captures the required variables, +// starting a server and sending the request to that server. +func SetURLVars(r *http.Request, val map[string]string) *http.Request { + return requestWithVars(r, val) +} diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md index 19aa2e75c..d33ed7fdd 100644 --- a/vendor/github.com/gorilla/websocket/README.md +++ b/vendor/github.com/gorilla/websocket/README.md @@ -6,6 +6,7 @@ Gorilla WebSocket is a [Go](http://golang.org/) implementation of the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. + ### Documentation * [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc) @@ -30,35 +31,3 @@ The Gorilla WebSocket package passes the server tests in the [Autobahn Test Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). -### Gorilla WebSocket compared with other packages - - - - - - - - - - - - - - - - - - -
github.com/gorillagolang.org/x/net
RFC 6455 Features
Passes Autobahn Test SuiteYesNo
Receive fragmented messageYesNo, see note 1
Send close messageYesNo
Send pings and receive pongsYesNo
Get the type of a received data messageYesYes, see note 2
Other Features
Compression ExtensionsExperimentalNo
Read message using io.ReaderYesNo, see note 3
Write message using io.WriteCloserYesNo, see note 3
- -Notes: - -1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html). -2. The application can get the type of a received data message by implementing - a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal) - function. -3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries. - Read returns when the input buffer is full or a frame boundary is - encountered. Each call to Write sends a single frame message. The Gorilla - io.Reader and io.WriteCloser operate on a single WebSocket message. - diff --git a/vendor/github.com/gorilla/websocket/client.go b/vendor/github.com/gorilla/websocket/client.go index 962c06a39..04fdafee1 100644 --- a/vendor/github.com/gorilla/websocket/client.go +++ b/vendor/github.com/gorilla/websocket/client.go @@ -9,6 +9,7 @@ import ( "context" "crypto/tls" "errors" + "fmt" "io" "io/ioutil" "net" @@ -48,15 +49,23 @@ func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufS } // A Dialer contains options for connecting to WebSocket server. +// +// It is safe to call Dialer's methods concurrently. type Dialer struct { // NetDial specifies the dial function for creating TCP connections. If // NetDial is nil, net.Dial is used. NetDial func(network, addr string) (net.Conn, error) // NetDialContext specifies the dial function for creating TCP connections. If - // NetDialContext is nil, net.DialContext is used. + // NetDialContext is nil, NetDial is used. NetDialContext func(ctx context.Context, network, addr string) (net.Conn, error) + // NetDialTLSContext specifies the dial function for creating TLS/TCP connections. If + // NetDialTLSContext is nil, NetDialContext is used. + // If NetDialTLSContext is set, Dial assumes the TLS handshake is done there and + // TLSClientConfig is ignored. + NetDialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error) + // Proxy specifies a function to return a proxy for a given // Request. If the function returns a non-nil error, the // request is aborted with the provided error. @@ -65,6 +74,8 @@ type Dialer struct { // TLSClientConfig specifies the TLS configuration to use with tls.Client. // If nil, the default configuration is used. + // If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake + // is done there and TLSClientConfig is ignored. TLSClientConfig *tls.Config // HandshakeTimeout specifies the duration for the handshake to complete. @@ -176,7 +187,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } req := &http.Request{ - Method: "GET", + Method: http.MethodGet, URL: u, Proto: "HTTP/1.1", ProtoMajor: 1, @@ -237,13 +248,32 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h // Get network dial function. var netDial func(network, add string) (net.Conn, error) - if d.NetDialContext != nil { - netDial = func(network, addr string) (net.Conn, error) { - return d.NetDialContext(ctx, network, addr) + switch u.Scheme { + case "http": + if d.NetDialContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialContext(ctx, network, addr) + } + } else if d.NetDial != nil { + netDial = d.NetDial } - } else if d.NetDial != nil { - netDial = d.NetDial - } else { + case "https": + if d.NetDialTLSContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialTLSContext(ctx, network, addr) + } + } else if d.NetDialContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialContext(ctx, network, addr) + } + } else if d.NetDial != nil { + netDial = d.NetDial + } + default: + return nil, nil, errMalformedURL + } + + if netDial == nil { netDialer := &net.Dialer{} netDial = func(network, addr string) (net.Conn, error) { return netDialer.DialContext(ctx, network, addr) @@ -289,14 +319,14 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } netConn, err := netDial("tcp", hostPort) + if err != nil { + return nil, nil, err + } if trace != nil && trace.GotConn != nil { trace.GotConn(httptrace.GotConnInfo{ Conn: netConn, }) } - if err != nil { - return nil, nil, err - } defer func() { if netConn != nil { @@ -304,7 +334,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } }() - if u.Scheme == "https" { + if u.Scheme == "https" && d.NetDialTLSContext == nil { + // If NetDialTLSContext is set, assume that the TLS handshake has already been done + cfg := cloneTLSConfig(d.TLSClientConfig) if cfg.ServerName == "" { cfg.ServerName = hostNoPort @@ -312,11 +344,12 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h tlsConn := tls.Client(netConn, cfg) netConn = tlsConn - var err error - if trace != nil { - err = doHandshakeWithTrace(trace, tlsConn, cfg) - } else { - err = doHandshake(tlsConn, cfg) + if trace != nil && trace.TLSHandshakeStart != nil { + trace.TLSHandshakeStart() + } + err := doHandshake(ctx, tlsConn, cfg) + if trace != nil && trace.TLSHandshakeDone != nil { + trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) } if err != nil { @@ -338,6 +371,17 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h resp, err := http.ReadResponse(conn.br, req) if err != nil { + if d.TLSClientConfig != nil { + for _, proto := range d.TLSClientConfig.NextProtos { + if proto != "http/1.1" { + return nil, nil, fmt.Errorf( + "websocket: protocol %q was given but is not supported;"+ + "sharing tls.Config with net/http Transport can cause this error: %w", + proto, err, + ) + } + } + } return nil, nil, err } @@ -348,8 +392,8 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h } if resp.StatusCode != 101 || - !strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") || - !strings.EqualFold(resp.Header.Get("Connection"), "upgrade") || + !tokenListContainsValue(resp.Header, "Upgrade", "websocket") || + !tokenListContainsValue(resp.Header, "Connection", "upgrade") || resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) { // Before closing the network connection on return from this // function, slurp up some of the response to aid application @@ -382,14 +426,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h return conn, resp, nil } -func doHandshake(tlsConn *tls.Conn, cfg *tls.Config) error { - if err := tlsConn.Handshake(); err != nil { - return err - } - if !cfg.InsecureSkipVerify { - if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { - return err - } +func cloneTLSConfig(cfg *tls.Config) *tls.Config { + if cfg == nil { + return &tls.Config{} } - return nil + return cfg.Clone() } diff --git a/vendor/github.com/gorilla/websocket/client_clone.go b/vendor/github.com/gorilla/websocket/client_clone.go deleted file mode 100644 index 4f0d94372..000000000 --- a/vendor/github.com/gorilla/websocket/client_clone.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.8 - -package websocket - -import "crypto/tls" - -func cloneTLSConfig(cfg *tls.Config) *tls.Config { - if cfg == nil { - return &tls.Config{} - } - return cfg.Clone() -} diff --git a/vendor/github.com/gorilla/websocket/client_clone_legacy.go b/vendor/github.com/gorilla/websocket/client_clone_legacy.go deleted file mode 100644 index babb007fb..000000000 --- a/vendor/github.com/gorilla/websocket/client_clone_legacy.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.8 - -package websocket - -import "crypto/tls" - -// cloneTLSConfig clones all public fields except the fields -// SessionTicketsDisabled and SessionTicketKey. This avoids copying the -// sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a -// config in active use. -func cloneTLSConfig(cfg *tls.Config) *tls.Config { - if cfg == nil { - return &tls.Config{} - } - return &tls.Config{ - Rand: cfg.Rand, - Time: cfg.Time, - Certificates: cfg.Certificates, - NameToCertificate: cfg.NameToCertificate, - GetCertificate: cfg.GetCertificate, - RootCAs: cfg.RootCAs, - NextProtos: cfg.NextProtos, - ServerName: cfg.ServerName, - ClientAuth: cfg.ClientAuth, - ClientCAs: cfg.ClientCAs, - InsecureSkipVerify: cfg.InsecureSkipVerify, - CipherSuites: cfg.CipherSuites, - PreferServerCipherSuites: cfg.PreferServerCipherSuites, - ClientSessionCache: cfg.ClientSessionCache, - MinVersion: cfg.MinVersion, - MaxVersion: cfg.MaxVersion, - CurvePreferences: cfg.CurvePreferences, - } -} diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go index ca46d2f79..5161ef81f 100644 --- a/vendor/github.com/gorilla/websocket/conn.go +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -13,6 +13,7 @@ import ( "math/rand" "net" "strconv" + "strings" "sync" "time" "unicode/utf8" @@ -401,6 +402,12 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error return nil } +func (c *Conn) writeBufs(bufs ...[]byte) error { + b := net.Buffers(bufs) + _, err := b.WriteTo(c.conn) + return err +} + // WriteControl writes a control message with the given deadline. The allowed // message types are CloseMessage, PingMessage and PongMessage. func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) error { @@ -794,47 +801,69 @@ func (c *Conn) advanceFrame() (int, error) { } // 2. Read and parse first two bytes of frame header. + // To aid debugging, collect and report all errors in the first two bytes + // of the header. + + var errors []string p, err := c.read(2) if err != nil { return noFrame, err } - final := p[0]&finalBit != 0 frameType := int(p[0] & 0xf) + final := p[0]&finalBit != 0 + rsv1 := p[0]&rsv1Bit != 0 + rsv2 := p[0]&rsv2Bit != 0 + rsv3 := p[0]&rsv3Bit != 0 mask := p[1]&maskBit != 0 c.setReadRemaining(int64(p[1] & 0x7f)) c.readDecompress = false - if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 { - c.readDecompress = true - p[0] &^= rsv1Bit + if rsv1 { + if c.newDecompressionReader != nil { + c.readDecompress = true + } else { + errors = append(errors, "RSV1 set") + } + } + + if rsv2 { + errors = append(errors, "RSV2 set") } - if rsv := p[0] & (rsv1Bit | rsv2Bit | rsv3Bit); rsv != 0 { - return noFrame, c.handleProtocolError("unexpected reserved bits 0x" + strconv.FormatInt(int64(rsv), 16)) + if rsv3 { + errors = append(errors, "RSV3 set") } switch frameType { case CloseMessage, PingMessage, PongMessage: if c.readRemaining > maxControlFramePayloadSize { - return noFrame, c.handleProtocolError("control frame length > 125") + errors = append(errors, "len > 125 for control") } if !final { - return noFrame, c.handleProtocolError("control frame not final") + errors = append(errors, "FIN not set on control") } case TextMessage, BinaryMessage: if !c.readFinal { - return noFrame, c.handleProtocolError("message start before final message frame") + errors = append(errors, "data before FIN") } c.readFinal = final case continuationFrame: if c.readFinal { - return noFrame, c.handleProtocolError("continuation after final message frame") + errors = append(errors, "continuation after FIN") } c.readFinal = final default: - return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType)) + errors = append(errors, "bad opcode "+strconv.Itoa(frameType)) + } + + if mask != c.isServer { + errors = append(errors, "bad MASK") + } + + if len(errors) > 0 { + return noFrame, c.handleProtocolError(strings.Join(errors, ", ")) } // 3. Read and parse frame length as per @@ -872,10 +901,6 @@ func (c *Conn) advanceFrame() (int, error) { // 4. Handle frame masking. - if mask != c.isServer { - return noFrame, c.handleProtocolError("incorrect mask flag") - } - if mask { c.readMaskPos = 0 p, err := c.read(len(c.readMaskKey)) @@ -935,7 +960,7 @@ func (c *Conn) advanceFrame() (int, error) { if len(payload) >= 2 { closeCode = int(binary.BigEndian.Uint16(payload)) if !isValidReceivedCloseCode(closeCode) { - return noFrame, c.handleProtocolError("invalid close code") + return noFrame, c.handleProtocolError("bad close code " + strconv.Itoa(closeCode)) } closeText = string(payload[2:]) if !utf8.ValidString(closeText) { @@ -952,7 +977,11 @@ func (c *Conn) advanceFrame() (int, error) { } func (c *Conn) handleProtocolError(message string) error { - c.WriteControl(CloseMessage, FormatCloseMessage(CloseProtocolError, message), time.Now().Add(writeWait)) + data := FormatCloseMessage(CloseProtocolError, message) + if len(data) > maxControlFramePayloadSize { + data = data[:maxControlFramePayloadSize] + } + c.WriteControl(CloseMessage, data, time.Now().Add(writeWait)) return errors.New("websocket: " + message) } @@ -1160,8 +1189,16 @@ func (c *Conn) SetPongHandler(h func(appData string) error) { c.handlePong = h } +// NetConn returns the underlying connection that is wrapped by c. +// Note that writing to or reading from this connection directly will corrupt the +// WebSocket connection. +func (c *Conn) NetConn() net.Conn { + return c.conn +} + // UnderlyingConn returns the internal net.Conn. This can be used to further // modifications to connection specific flags. +// Deprecated: Use the NetConn method. func (c *Conn) UnderlyingConn() net.Conn { return c.conn } diff --git a/vendor/github.com/gorilla/websocket/conn_write.go b/vendor/github.com/gorilla/websocket/conn_write.go deleted file mode 100644 index a509a21f8..000000000 --- a/vendor/github.com/gorilla/websocket/conn_write.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.8 - -package websocket - -import "net" - -func (c *Conn) writeBufs(bufs ...[]byte) error { - b := net.Buffers(bufs) - _, err := b.WriteTo(c.conn) - return err -} diff --git a/vendor/github.com/gorilla/websocket/conn_write_legacy.go b/vendor/github.com/gorilla/websocket/conn_write_legacy.go deleted file mode 100644 index 37edaff5a..000000000 --- a/vendor/github.com/gorilla/websocket/conn_write_legacy.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.8 - -package websocket - -func (c *Conn) writeBufs(bufs ...[]byte) error { - for _, buf := range bufs { - if len(buf) > 0 { - if _, err := c.conn.Write(buf); err != nil { - return err - } - } - } - return nil -} diff --git a/vendor/github.com/gorilla/websocket/mask.go b/vendor/github.com/gorilla/websocket/mask.go index 577fce9ef..d0742bf2a 100644 --- a/vendor/github.com/gorilla/websocket/mask.go +++ b/vendor/github.com/gorilla/websocket/mask.go @@ -2,6 +2,7 @@ // this source code is governed by a BSD-style license that can be found in the // LICENSE file. +//go:build !appengine // +build !appengine package websocket diff --git a/vendor/github.com/gorilla/websocket/mask_safe.go b/vendor/github.com/gorilla/websocket/mask_safe.go index 2aac060e5..36250ca7c 100644 --- a/vendor/github.com/gorilla/websocket/mask_safe.go +++ b/vendor/github.com/gorilla/websocket/mask_safe.go @@ -2,6 +2,7 @@ // this source code is governed by a BSD-style license that can be found in the // LICENSE file. +//go:build appengine // +build appengine package websocket diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go index e87a8c9f0..e0f466b72 100644 --- a/vendor/github.com/gorilla/websocket/proxy.go +++ b/vendor/github.com/gorilla/websocket/proxy.go @@ -48,7 +48,7 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) } connectReq := &http.Request{ - Method: "CONNECT", + Method: http.MethodConnect, URL: &url.URL{Opaque: addr}, Host: addr, Header: connectHeader, diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go index 887d55891..bb3359743 100644 --- a/vendor/github.com/gorilla/websocket/server.go +++ b/vendor/github.com/gorilla/websocket/server.go @@ -23,6 +23,8 @@ func (e HandshakeError) Error() string { return e.message } // Upgrader specifies parameters for upgrading an HTTP connection to a // WebSocket connection. +// +// It is safe to call Upgrader's methods concurrently. type Upgrader struct { // HandshakeTimeout specifies the duration for the handshake to complete. HandshakeTimeout time.Duration @@ -115,8 +117,8 @@ func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header // Upgrade upgrades the HTTP server connection to the WebSocket protocol. // // The responseHeader is included in the response to the client's upgrade -// request. Use the responseHeader to specify cookies (Set-Cookie) and the -// application negotiated subprotocol (Sec-WebSocket-Protocol). +// request. Use the responseHeader to specify cookies (Set-Cookie). To specify +// subprotocols supported by the server, set Upgrader.Subprotocols directly. // // If the upgrade fails, then Upgrade replies to the client with an HTTP error // response. @@ -131,7 +133,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header") } - if r.Method != "GET" { + if r.Method != http.MethodGet { return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET") } @@ -152,8 +154,8 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade } challengeKey := r.Header.Get("Sec-Websocket-Key") - if challengeKey == "" { - return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank") + if !isValidChallengeKey(challengeKey) { + return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header must be Base64 encoded value of 16-byte in length") } subprotocol := u.selectSubprotocol(r, responseHeader) diff --git a/vendor/github.com/gorilla/websocket/tls_handshake.go b/vendor/github.com/gorilla/websocket/tls_handshake.go new file mode 100644 index 000000000..a62b68ccb --- /dev/null +++ b/vendor/github.com/gorilla/websocket/tls_handshake.go @@ -0,0 +1,21 @@ +//go:build go1.17 +// +build go1.17 + +package websocket + +import ( + "context" + "crypto/tls" +) + +func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error { + if err := tlsConn.HandshakeContext(ctx); err != nil { + return err + } + if !cfg.InsecureSkipVerify { + if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/gorilla/websocket/tls_handshake_116.go b/vendor/github.com/gorilla/websocket/tls_handshake_116.go new file mode 100644 index 000000000..e1b2b44f6 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/tls_handshake_116.go @@ -0,0 +1,21 @@ +//go:build !go1.17 +// +build !go1.17 + +package websocket + +import ( + "context" + "crypto/tls" +) + +func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error { + if err := tlsConn.Handshake(); err != nil { + return err + } + if !cfg.InsecureSkipVerify { + if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/gorilla/websocket/trace.go b/vendor/github.com/gorilla/websocket/trace.go deleted file mode 100644 index 834f122a0..000000000 --- a/vendor/github.com/gorilla/websocket/trace.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build go1.8 - -package websocket - -import ( - "crypto/tls" - "net/http/httptrace" -) - -func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { - if trace.TLSHandshakeStart != nil { - trace.TLSHandshakeStart() - } - err := doHandshake(tlsConn, cfg) - if trace.TLSHandshakeDone != nil { - trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) - } - return err -} diff --git a/vendor/github.com/gorilla/websocket/trace_17.go b/vendor/github.com/gorilla/websocket/trace_17.go deleted file mode 100644 index 77d05a0b5..000000000 --- a/vendor/github.com/gorilla/websocket/trace_17.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build !go1.8 - -package websocket - -import ( - "crypto/tls" - "net/http/httptrace" -) - -func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { - return doHandshake(tlsConn, cfg) -} diff --git a/vendor/github.com/gorilla/websocket/util.go b/vendor/github.com/gorilla/websocket/util.go index 7bf2f66c6..31a5dee64 100644 --- a/vendor/github.com/gorilla/websocket/util.go +++ b/vendor/github.com/gorilla/websocket/util.go @@ -281,3 +281,18 @@ headers: } return result } + +// isValidChallengeKey checks if the argument meets RFC6455 specification. +func isValidChallengeKey(s string) bool { + // From RFC6455: + // + // A |Sec-WebSocket-Key| header field with a base64-encoded (see + // Section 4 of [RFC4648]) value that, when decoded, is 16 bytes in + // length. + + if s == "" { + return false + } + decoded, err := base64.StdEncoding.DecodeString(s) + return err == nil && len(decoded) == 16 +} diff --git a/vendor/github.com/hashicorp/golang-lru/.golangci.yml b/vendor/github.com/hashicorp/golang-lru/.golangci.yml new file mode 100644 index 000000000..49202fc41 --- /dev/null +++ b/vendor/github.com/hashicorp/golang-lru/.golangci.yml @@ -0,0 +1,30 @@ +linters: + enable: + - megacheck + - revive + - govet + - unconvert + - megacheck + - gas + - gocyclo + - dupl + - misspell + - unparam + - unused + - typecheck + - ineffassign + - stylecheck + - exportloopref + - gocritic + - nakedret + - gosimple + - prealloc + fast: false + disable-all: true + +issues: + exclude-rules: + - path: _test\.go + linters: + - dupl + exclude-use-default: false diff --git a/vendor/github.com/hashicorp/golang-lru/2q.go b/vendor/github.com/hashicorp/golang-lru/2q.go index e474cd075..15fcad030 100644 --- a/vendor/github.com/hashicorp/golang-lru/2q.go +++ b/vendor/github.com/hashicorp/golang-lru/2q.go @@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) { // New2QParams creates a new TwoQueueCache using the provided // parameter values. -func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) { +func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) { if size <= 0 { return nil, fmt.Errorf("invalid size") } @@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) { // Add to the recently seen list c.ensureSpace(false) c.recent.Add(key, value) - return } // ensureSpace is used to ensure we have space in the cache diff --git a/vendor/github.com/hashicorp/golang-lru/LICENSE b/vendor/github.com/hashicorp/golang-lru/LICENSE index be2cc4dfb..0e5d580e0 100644 --- a/vendor/github.com/hashicorp/golang-lru/LICENSE +++ b/vendor/github.com/hashicorp/golang-lru/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2014 HashiCorp, Inc. + Mozilla Public License, version 2.0 1. Definitions diff --git a/vendor/github.com/hashicorp/golang-lru/README.md b/vendor/github.com/hashicorp/golang-lru/README.md index 33e58cfaf..03bcfb5b7 100644 --- a/vendor/github.com/hashicorp/golang-lru/README.md +++ b/vendor/github.com/hashicorp/golang-lru/README.md @@ -1,25 +1,7 @@ golang-lru ========== -This provides the `lru` package which implements a fixed-size -thread safe LRU cache. It is based on the cache in Groupcache. - -Documentation -============= - -Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru) - -Example -======= - -Using the LRU is very simple: - -```go -l, _ := New(128) -for i := 0; i < 256; i++ { - l.Add(i, nil) -} -if l.Len() != 128 { - panic(fmt.Sprintf("bad len: %v", l.Len())) -} -``` +Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will +not be updated anymore. The v2 version supports generics and is faster; old code +can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for +backwards compatibility. diff --git a/vendor/github.com/hashicorp/golang-lru/arc.go b/vendor/github.com/hashicorp/golang-lru/arc.go index 555225a21..e396f8428 100644 --- a/vendor/github.com/hashicorp/golang-lru/arc.go +++ b/vendor/github.com/hashicorp/golang-lru/arc.go @@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) { // Add to the recently seen list c.t1.Add(key, value) - return } // replace is used to adaptively evict from either T1 or T2 diff --git a/vendor/github.com/hashicorp/golang-lru/lru.go b/vendor/github.com/hashicorp/golang-lru/lru.go index 1cbe04b7d..895d8e3ea 100644 --- a/vendor/github.com/hashicorp/golang-lru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/lru.go @@ -6,10 +6,17 @@ import ( "github.com/hashicorp/golang-lru/simplelru" ) +const ( + // DefaultEvictedBufferSize defines the default buffer size to store evicted key/val + DefaultEvictedBufferSize = 16 +) + // Cache is a thread-safe fixed size LRU cache. type Cache struct { - lru simplelru.LRUCache - lock sync.RWMutex + lru *simplelru.LRU + evictedKeys, evictedVals []interface{} + onEvictedCB func(k, v interface{}) + lock sync.RWMutex } // New creates an LRU of the given size. @@ -19,30 +26,63 @@ func New(size int) (*Cache, error) { // NewWithEvict constructs a fixed size cache with the given eviction // callback. -func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) { - lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted)) - if err != nil { - return nil, err +func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) { + // create a cache with default settings + c = &Cache{ + onEvictedCB: onEvicted, } - c := &Cache{ - lru: lru, + if onEvicted != nil { + c.initEvictBuffers() + onEvicted = c.onEvicted } - return c, nil + c.lru, err = simplelru.NewLRU(size, onEvicted) + return +} + +func (c *Cache) initEvictBuffers() { + c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize) + c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize) +} + +// onEvicted save evicted key/val and sent in externally registered callback +// outside of critical section +func (c *Cache) onEvicted(k, v interface{}) { + c.evictedKeys = append(c.evictedKeys, k) + c.evictedVals = append(c.evictedVals, v) } // Purge is used to completely clear the cache. func (c *Cache) Purge() { + var ks, vs []interface{} c.lock.Lock() c.lru.Purge() + if c.onEvictedCB != nil && len(c.evictedKeys) > 0 { + ks, vs = c.evictedKeys, c.evictedVals + c.initEvictBuffers() + } c.lock.Unlock() + // invoke callback outside of critical section + if c.onEvictedCB != nil { + for i := 0; i < len(ks); i++ { + c.onEvictedCB(ks[i], vs[i]) + } + } } -// Add adds a value to the cache. Returns true if an eviction occurred. +// Add adds a value to the cache. Returns true if an eviction occurred. func (c *Cache) Add(key, value interface{}) (evicted bool) { + var k, v interface{} c.lock.Lock() evicted = c.lru.Add(key, value) + if c.onEvictedCB != nil && evicted { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } c.lock.Unlock() - return evicted + if c.onEvictedCB != nil && evicted { + c.onEvictedCB(k, v) + } + return } // Get looks up a key's value from the cache. @@ -71,32 +111,107 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) { return value, ok } -// ContainsOrAdd checks if a key is in the cache without updating the -// recent-ness or deleting it for being stale, and if not, adds the value. +// ContainsOrAdd checks if a key is in the cache without updating the +// recent-ness or deleting it for being stale, and if not, adds the value. // Returns whether found and whether an eviction occurred. func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) { + var k, v interface{} c.lock.Lock() - defer c.lock.Unlock() - if c.lru.Contains(key) { + c.lock.Unlock() return true, false } evicted = c.lru.Add(key, value) + if c.onEvictedCB != nil && evicted { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } + c.lock.Unlock() + if c.onEvictedCB != nil && evicted { + c.onEvictedCB(k, v) + } return false, evicted } +// PeekOrAdd checks if a key is in the cache without updating the +// recent-ness or deleting it for being stale, and if not, adds the value. +// Returns whether found and whether an eviction occurred. +func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) { + var k, v interface{} + c.lock.Lock() + previous, ok = c.lru.Peek(key) + if ok { + c.lock.Unlock() + return previous, true, false + } + evicted = c.lru.Add(key, value) + if c.onEvictedCB != nil && evicted { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } + c.lock.Unlock() + if c.onEvictedCB != nil && evicted { + c.onEvictedCB(k, v) + } + return nil, false, evicted +} + // Remove removes the provided key from the cache. -func (c *Cache) Remove(key interface{}) { +func (c *Cache) Remove(key interface{}) (present bool) { + var k, v interface{} c.lock.Lock() - c.lru.Remove(key) + present = c.lru.Remove(key) + if c.onEvictedCB != nil && present { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } c.lock.Unlock() + if c.onEvictedCB != nil && present { + c.onEvictedCB(k, v) + } + return +} + +// Resize changes the cache size. +func (c *Cache) Resize(size int) (evicted int) { + var ks, vs []interface{} + c.lock.Lock() + evicted = c.lru.Resize(size) + if c.onEvictedCB != nil && evicted > 0 { + ks, vs = c.evictedKeys, c.evictedVals + c.initEvictBuffers() + } + c.lock.Unlock() + if c.onEvictedCB != nil && evicted > 0 { + for i := 0; i < len(ks); i++ { + c.onEvictedCB(ks[i], vs[i]) + } + } + return evicted } // RemoveOldest removes the oldest item from the cache. -func (c *Cache) RemoveOldest() { +func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) { + var k, v interface{} c.lock.Lock() - c.lru.RemoveOldest() + key, value, ok = c.lru.RemoveOldest() + if c.onEvictedCB != nil && ok { + k, v = c.evictedKeys[0], c.evictedVals[0] + c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0] + } c.lock.Unlock() + if c.onEvictedCB != nil && ok { + c.onEvictedCB(k, v) + } + return +} + +// GetOldest returns the oldest entry +func (c *Cache) GetOldest() (key, value interface{}, ok bool) { + c.lock.RLock() + key, value, ok = c.lru.GetOldest() + c.lock.RUnlock() + return } // Keys returns a slice of the keys in the cache, from oldest to newest. diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go index 5673773b2..9233583c9 100644 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go @@ -25,7 +25,7 @@ type entry struct { // NewLRU constructs an LRU of the given size func NewLRU(size int, onEvict EvictCallback) (*LRU, error) { if size <= 0 { - return nil, errors.New("Must provide a positive size") + return nil, errors.New("must provide a positive size") } c := &LRU{ size: size, @@ -73,6 +73,9 @@ func (c *LRU) Add(key, value interface{}) (evicted bool) { func (c *LRU) Get(key interface{}) (value interface{}, ok bool) { if ent, ok := c.items[key]; ok { c.evictList.MoveToFront(ent) + if ent.Value.(*entry) == nil { + return nil, false + } return ent.Value.(*entry).value, true } return @@ -106,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) { } // RemoveOldest removes the oldest item from the cache. -func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) { +func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) { ent := c.evictList.Back() if ent != nil { c.removeElement(ent) @@ -117,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) { } // GetOldest returns the oldest entry -func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) { +func (c *LRU) GetOldest() (key, value interface{}, ok bool) { ent := c.evictList.Back() if ent != nil { kv := ent.Value.(*entry) @@ -142,6 +145,19 @@ func (c *LRU) Len() int { return c.evictList.Len() } +// Resize changes the cache size. +func (c *LRU) Resize(size int) (evicted int) { + diff := c.Len() - size + if diff < 0 { + diff = 0 + } + for i := 0; i < diff; i++ { + c.removeOldest() + } + c.size = size + return diff +} + // removeOldest removes the oldest item from the cache. func (c *LRU) removeOldest() { ent := c.evictList.Back() diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go index 74c707744..cb7f8caf0 100644 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go @@ -1,3 +1,4 @@ +// Package simplelru provides simple LRU implementation based on build-in container/list. package simplelru // LRUCache is the interface for simple LRU cache. @@ -10,7 +11,7 @@ type LRUCache interface { // updates the "recently used"-ness of the key. #value, isFound Get(key interface{}) (value interface{}, ok bool) - // Check if a key exsists in cache without updating the recent-ness. + // Checks if a key exists in cache without updating the recent-ness. Contains(key interface{}) (ok bool) // Returns key's value without updating the "recently used"-ness of the key. @@ -31,6 +32,9 @@ type LRUCache interface { // Returns the number of items in the cache. Len() int - // Clear all cache entries + // Clears all cache entries. Purge() + + // Resizes cache, returning number evicted + Resize(int) int } diff --git a/vendor/github.com/hashicorp/golang-lru/testing.go b/vendor/github.com/hashicorp/golang-lru/testing.go new file mode 100644 index 000000000..492760782 --- /dev/null +++ b/vendor/github.com/hashicorp/golang-lru/testing.go @@ -0,0 +1,16 @@ +package lru + +import ( + "crypto/rand" + "math" + "math/big" + "testing" +) + +func getRand(tb testing.TB) int64 { + out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) + if err != nil { + tb.Fatal(err) + } + return out.Int64() +} diff --git a/vendor/github.com/hashicorp/hcl/.travis.yml b/vendor/github.com/hashicorp/hcl/.travis.yml index 83dc540ef..cb63a3216 100644 --- a/vendor/github.com/hashicorp/hcl/.travis.yml +++ b/vendor/github.com/hashicorp/hcl/.travis.yml @@ -1,3 +1,13 @@ sudo: false + language: go -go: 1.5 + +go: + - 1.x + - tip + +branches: + only: + - master + +script: make test diff --git a/vendor/github.com/hashicorp/hcl/Makefile b/vendor/github.com/hashicorp/hcl/Makefile index ad404a811..84fd743f5 100644 --- a/vendor/github.com/hashicorp/hcl/Makefile +++ b/vendor/github.com/hashicorp/hcl/Makefile @@ -6,6 +6,7 @@ fmt: generate go fmt ./... test: generate + go get -t ./... go test $(TEST) $(TESTARGS) generate: diff --git a/vendor/github.com/hashicorp/hcl/README.md b/vendor/github.com/hashicorp/hcl/README.md index 3d5b8bd92..c8223326d 100644 --- a/vendor/github.com/hashicorp/hcl/README.md +++ b/vendor/github.com/hashicorp/hcl/README.md @@ -81,9 +81,20 @@ FOO * Boolean values: `true`, `false` * Arrays can be made by wrapping it in `[]`. Example: - `["foo", "bar", 42]`. Arrays can contain primitives - and other arrays, but cannot contain objects. Objects must - use the block syntax shown below. + `["foo", "bar", 42]`. Arrays can contain primitives, + other arrays, and objects. As an alternative, lists + of objects can be created with repeated blocks, using + this structure: + + ```hcl + service { + key = "value" + } + + service { + key = "value" + } + ``` Objects and nested objects are created using the structure shown below: @@ -92,6 +103,16 @@ variable "ami" { description = "the AMI to use" } ``` +This would be equivalent to the following json: +``` json +{ + "variable": { + "ami": { + "description": "the AMI to use" + } + } +} +``` ## Thanks diff --git a/vendor/github.com/hashicorp/hcl/appveyor.yml b/vendor/github.com/hashicorp/hcl/appveyor.yml index e70f03b96..4db0b7112 100644 --- a/vendor/github.com/hashicorp/hcl/appveyor.yml +++ b/vendor/github.com/hashicorp/hcl/appveyor.yml @@ -4,7 +4,7 @@ clone_folder: c:\gopath\src\github.com\hashicorp\hcl environment: GOPATH: c:\gopath init: - - git config --global core.autocrlf true + - git config --global core.autocrlf false install: - cmd: >- echo %Path% @@ -12,5 +12,8 @@ install: go version go env + + go get -t ./... + build_script: - cmd: go test -v ./... diff --git a/vendor/github.com/hashicorp/hcl/decoder.go b/vendor/github.com/hashicorp/hcl/decoder.go index 02888d2ab..bed9ebbe1 100644 --- a/vendor/github.com/hashicorp/hcl/decoder.go +++ b/vendor/github.com/hashicorp/hcl/decoder.go @@ -89,9 +89,9 @@ func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error switch k.Kind() { case reflect.Bool: return d.decodeBool(name, node, result) - case reflect.Float64: + case reflect.Float32, reflect.Float64: return d.decodeFloat(name, node, result) - case reflect.Int: + case reflect.Int, reflect.Int32, reflect.Int64: return d.decodeInt(name, node, result) case reflect.Interface: // When we see an interface, we make our own thing @@ -137,13 +137,13 @@ func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) e func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error { switch n := node.(type) { case *ast.LiteralType: - if n.Token.Type == token.FLOAT { + if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER { v, err := strconv.ParseFloat(n.Token.Text, 64) if err != nil { return err } - result.Set(reflect.ValueOf(v)) + result.Set(reflect.ValueOf(v).Convert(result.Type())) return nil } } @@ -164,7 +164,11 @@ func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) er return err } - result.Set(reflect.ValueOf(int(v))) + if result.Kind() == reflect.Interface { + result.Set(reflect.ValueOf(int(v))) + } else { + result.SetInt(v) + } return nil case token.STRING: v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0) @@ -172,7 +176,11 @@ func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) er return err } - result.Set(reflect.ValueOf(int(v))) + if result.Kind() == reflect.Interface { + result.Set(reflect.ValueOf(int(v))) + } else { + result.SetInt(v) + } return nil } } @@ -409,7 +417,6 @@ func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) if result.Kind() == reflect.Interface { result = result.Elem() } - // Create the slice if it isn't nil resultType := result.Type() resultElemType := resultType.Elem() @@ -443,6 +450,12 @@ func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) // Decode val := reflect.Indirect(reflect.New(resultElemType)) + + // if item is an object that was decoded from ambiguous JSON and + // flattened, make sure it's expanded if it needs to decode into a + // defined structure. + item := expandObject(item, val) + if err := d.decode(fieldName, item, val); err != nil { return err } @@ -455,6 +468,57 @@ func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) return nil } +// expandObject detects if an ambiguous JSON object was flattened to a List which +// should be decoded into a struct, and expands the ast to properly deocode. +func expandObject(node ast.Node, result reflect.Value) ast.Node { + item, ok := node.(*ast.ObjectItem) + if !ok { + return node + } + + elemType := result.Type() + + // our target type must be a struct + switch elemType.Kind() { + case reflect.Ptr: + switch elemType.Elem().Kind() { + case reflect.Struct: + //OK + default: + return node + } + case reflect.Struct: + //OK + default: + return node + } + + // A list value will have a key and field name. If it had more fields, + // it wouldn't have been flattened. + if len(item.Keys) != 2 { + return node + } + + keyToken := item.Keys[0].Token + item.Keys = item.Keys[1:] + + // we need to un-flatten the ast enough to decode + newNode := &ast.ObjectItem{ + Keys: []*ast.ObjectKey{ + &ast.ObjectKey{ + Token: keyToken, + }, + }, + Val: &ast.ObjectType{ + List: &ast.ObjectList{ + Items: []*ast.ObjectItem{item}, + }, + }, + } + + return newNode +} + func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error { switch n := node.(type) { case *ast.LiteralType: @@ -489,7 +553,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // the yacc parser would always ensure top-level elements were arrays. The new // parser does not make the same guarantees, thus we need to convert any // top-level literal elements into a list. - if _, ok := node.(*ast.LiteralType); ok { + if _, ok := node.(*ast.LiteralType); ok && item != nil { node = &ast.ObjectList{Items: []*ast.ObjectItem{item}} } @@ -509,7 +573,11 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // Compile the list of all the fields that we're going to be decoding // from all the structs. - fields := make(map[*reflect.StructField]reflect.Value) + type field struct { + field reflect.StructField + val reflect.Value + } + fields := []field{} for len(structs) > 0 { structVal := structs[0] structs = structs[1:] @@ -517,6 +585,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) structType := structVal.Type() for i := 0; i < structType.NumField(); i++ { fieldType := structType.Field(i) + tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") + + // Ignore fields with tag name "-" + if tagParts[0] == "-" { + continue + } if fieldType.Anonymous { fieldKind := fieldType.Type.Kind() @@ -531,7 +605,6 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // We have an embedded field. We "squash" the fields down // if specified in the tag. squash := false - tagParts := strings.Split(fieldType.Tag.Get(tagName), ",") for _, tag := range tagParts[1:] { if tag == "squash" { squash = true @@ -547,7 +620,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) } // Normal struct field, store it away - fields[&fieldType] = structVal.Field(i) + fields = append(fields, field{fieldType, structVal.Field(i)}) } } @@ -555,26 +628,27 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) decodedFields := make([]string, 0, len(fields)) decodedFieldsVal := make([]reflect.Value, 0) unusedKeysVal := make([]reflect.Value, 0) - for fieldType, field := range fields { - if !field.IsValid() { + for _, f := range fields { + field, fieldValue := f.field, f.val + if !fieldValue.IsValid() { // This should never happen panic("field is not valid") } // If we can't set the field, then it is unexported or something, // and we just continue onwards. - if !field.CanSet() { + if !fieldValue.CanSet() { continue } - fieldName := fieldType.Name + fieldName := field.Name - tagValue := fieldType.Tag.Get(tagName) + tagValue := field.Tag.Get(tagName) tagParts := strings.SplitN(tagValue, ",", 2) if len(tagParts) >= 2 { switch tagParts[1] { case "decodedFields": - decodedFieldsVal = append(decodedFieldsVal, field) + decodedFieldsVal = append(decodedFieldsVal, fieldValue) continue case "key": if item == nil { @@ -585,10 +659,10 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) } } - field.SetString(item.Keys[0].Token.Value().(string)) + fieldValue.SetString(item.Keys[0].Token.Value().(string)) continue case "unusedKeys": - unusedKeysVal = append(unusedKeysVal, field) + unusedKeysVal = append(unusedKeysVal, fieldValue) continue } } @@ -601,6 +675,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // match (only object with the field), then we decode it exactly. // If it is a prefix match, then we decode the matches. filter := list.Filter(fieldName) + prefixMatches := filter.Children() matches := filter.Elem() if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 { @@ -614,7 +689,7 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) // because we actually want the value. fieldName = fmt.Sprintf("%s.%s", name, fieldName) if len(prefixMatches.Items) > 0 { - if err := d.decode(fieldName, prefixMatches, field); err != nil { + if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil { return err } } @@ -624,12 +699,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) decodeNode = &ast.ObjectList{Items: ot.List.Items} } - if err := d.decode(fieldName, decodeNode, field); err != nil { + if err := d.decode(fieldName, decodeNode, fieldValue); err != nil { return err } } - decodedFields = append(decodedFields, fieldType.Name) + decodedFields = append(decodedFields, field.Name) } if len(decodedFieldsVal) > 0 { diff --git a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go index f8bb71a04..6e5ef654b 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go +++ b/vendor/github.com/hashicorp/hcl/hcl/ast/ast.go @@ -133,6 +133,12 @@ type ObjectItem struct { } func (o *ObjectItem) Pos() token.Pos { + // I'm not entirely sure what causes this, but removing this causes + // a test failure. We should investigate at some point. + if len(o.Keys) == 0 { + return token.Pos{} + } + return o.Keys[0].Pos() } @@ -150,7 +156,8 @@ func (o *ObjectKey) Pos() token.Pos { type LiteralType struct { Token token.Token - // associated line comment, only when used in a list + // comment types, only used when in a list + LeadComment *CommentGroup LineComment *CommentGroup } @@ -208,4 +215,5 @@ func (c *CommentGroup) Pos() token.Pos { // GoStringer //------------------------------------------------------------------- -func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } +func (o *ObjectKey) GoString() string { return fmt.Sprintf("*%#v", *o) } +func (o *ObjectList) GoString() string { return fmt.Sprintf("*%#v", *o) } diff --git a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go index cc129b6c7..64c83bcfb 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go +++ b/vendor/github.com/hashicorp/hcl/hcl/parser/parser.go @@ -3,6 +3,7 @@ package parser import ( + "bytes" "errors" "fmt" "strings" @@ -36,6 +37,11 @@ func newParser(src []byte) *Parser { // Parse returns the fully parsed source and returns the abstract syntax tree. func Parse(src []byte) (*ast.File, error) { + // normalize all line endings + // since the scanner and output only work with "\n" line endings, we may + // end up with dangling "\r" characters in the parsed data. + src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) + p := newParser(src) return p.Parse() } @@ -50,7 +56,7 @@ func (p *Parser) Parse() (*ast.File, error) { scerr = &PosError{Pos: pos, Err: errors.New(msg)} } - f.Node, err = p.objectList() + f.Node, err = p.objectList(false) if scerr != nil { return nil, scerr } @@ -62,11 +68,23 @@ func (p *Parser) Parse() (*ast.File, error) { return f, nil } -func (p *Parser) objectList() (*ast.ObjectList, error) { +// objectList parses a list of items within an object (generally k/v pairs). +// The parameter" obj" tells this whether to we are within an object (braces: +// '{', '}') or just at the top level. If we're within an object, we end +// at an RBRACE. +func (p *Parser) objectList(obj bool) (*ast.ObjectList, error) { defer un(trace(p, "ParseObjectList")) node := &ast.ObjectList{} for { + if obj { + tok := p.scan() + p.unscan() + if tok.Type == token.RBRACE { + break + } + } + n, err := p.objectItem() if err == errEofToken { break // we are finished @@ -79,6 +97,13 @@ func (p *Parser) objectList() (*ast.ObjectList, error) { } node.Add(n) + + // object lists can be optionally comma-delimited e.g. when a list of maps + // is being expressed, so a comma is allowed here - it's simply consumed + tok := p.scan() + if tok.Type != token.COMMA { + p.unscan() + } } return node, nil } @@ -172,9 +197,18 @@ func (p *Parser) objectItem() (*ast.ObjectItem, error) { keyStr = append(keyStr, k.Token.Text) } - return nil, fmt.Errorf( - "key '%s' expected start of object ('{') or assignment ('=')", - strings.Join(keyStr, " ")) + return nil, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf( + "key '%s' expected start of object ('{') or assignment ('=')", + strings.Join(keyStr, " ")), + } + } + + // key=#comment + // val + if p.lineComment != nil { + o.LineComment, p.lineComment = p.lineComment, nil } // do a look-ahead for line comment @@ -220,13 +254,27 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { return keys, nil case token.LBRACE: + var err error + + // If we have no keys, then it is a syntax error. i.e. {{}} is not + // allowed. + if len(keys) == 0 { + err = &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type), + } + } + // object - return keys, nil + return keys, err case token.IDENT, token.STRING: keyCount++ keys = append(keys, &ast.ObjectKey{Token: p.tok}) case token.ILLEGAL: - fmt.Println("illegal") + return keys, &PosError{ + Pos: p.tok.Pos, + Err: fmt.Errorf("illegal character"), + } default: return keys, &PosError{ Pos: p.tok.Pos, @@ -270,7 +318,7 @@ func (p *Parser) objectType() (*ast.ObjectType, error) { Lbrace: p.tok.Pos, } - l, err := p.objectList() + l, err := p.objectList(true) // if we hit RBRACE, we are good to go (means we parsed all Items), if it's // not a RBRACE, it's an syntax error and we just return it. @@ -278,9 +326,12 @@ func (p *Parser) objectType() (*ast.ObjectType, error) { return nil, err } - // If there is no error, we should be at a RBRACE to end the object - if p.tok.Type != token.RBRACE { - return nil, fmt.Errorf("object expected closing RBRACE got: %s", p.tok.Type) + // No error, scan and expect the ending to be a brace + if tok := p.scan(); tok.Type != token.RBRACE { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type), + } } o.List = l @@ -300,27 +351,38 @@ func (p *Parser) listType() (*ast.ListType, error) { needComma := false for { tok := p.scan() - switch tok.Type { - case token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: - if needComma { + if needComma { + switch tok.Type { + case token.COMMA, token.RBRACK: + default: return nil, &PosError{ Pos: tok.Pos, - Err: fmt.Errorf("unexpected token: %s. Expecting %s", tok.Type, token.COMMA), + Err: fmt.Errorf( + "error parsing list, expected comma or list end, got: %s", + tok.Type), } } - + } + switch tok.Type { + case token.BOOL, token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC: node, err := p.literalType() if err != nil { return nil, err } + // If there is a lead comment, apply it + if p.leadComment != nil { + node.LeadComment = p.leadComment + p.leadComment = nil + } + l.Add(node) needComma = true case token.COMMA: // get next list item or we are at the end // do a look-ahead for line comment p.scan() - if p.lineComment != nil { + if p.lineComment != nil && len(l.List) > 0 { lit, ok := l.List[len(l.List)-1].(*ast.LiteralType) if ok { lit.LineComment = p.lineComment @@ -332,12 +394,28 @@ func (p *Parser) listType() (*ast.ListType, error) { needComma = false continue - case token.BOOL: - // TODO(arslan) should we support? not supported by HCL yet + case token.LBRACE: + // Looks like a nested object, so parse it out + node, err := p.objectType() + if err != nil { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error while trying to parse object within list: %s", err), + } + } + l.Add(node) + needComma = true case token.LBRACK: - // TODO(arslan) should we support nested lists? Even though it's - // written in README of HCL, it's not a part of the grammar - // (not defined in parse.y) + node, err := p.listType() + if err != nil { + return nil, &PosError{ + Pos: tok.Pos, + Err: fmt.Errorf( + "error while trying to parse list within list: %s", err), + } + } + l.Add(node) case token.RBRACK: // finished l.Rbrack = p.tok.Pos diff --git a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go index a3f34a7b5..624a18fe3 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go +++ b/vendor/github.com/hashicorp/hcl/hcl/scanner/scanner.go @@ -74,14 +74,6 @@ func (s *Scanner) next() rune { return eof } - if ch == utf8.RuneError && size == 1 { - s.srcPos.Column++ - s.srcPos.Offset += size - s.lastCharLen = size - s.err("illegal UTF-8 encoding") - return ch - } - // remember last position s.prevPos = s.srcPos @@ -89,12 +81,27 @@ func (s *Scanner) next() rune { s.lastCharLen = size s.srcPos.Offset += size + if ch == utf8.RuneError && size == 1 { + s.err("illegal UTF-8 encoding") + return ch + } + if ch == '\n' { s.srcPos.Line++ s.lastLineLen = s.srcPos.Column s.srcPos.Column = 0 } + if ch == '\x00' { + s.err("unexpected null character (0x00)") + return eof + } + + if ch == '\uE123' { + s.err("unicode code point U+E123 reserved for internal use") + return utf8.RuneError + } + // debug // fmt.Printf("ch: %q, offset:column: %d:%d\n", ch, s.srcPos.Offset, s.srcPos.Column) return ch @@ -224,6 +231,11 @@ func (s *Scanner) Scan() token.Token { func (s *Scanner) scanComment(ch rune) { // single line comments if ch == '#' || (ch == '/' && s.peek() != '*') { + if ch == '/' && s.peek() != '/' { + s.err("expected '/' for comment") + return + } + ch = s.next() for ch != '\n' && ch >= 0 && ch != eof { ch = s.next() @@ -340,7 +352,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type { return token.NUMBER } -// scanMantissa scans the mantissa begining from the rune. It returns the next +// scanMantissa scans the mantissa beginning from the rune. It returns the next // non decimal rune. It's used to determine wheter it's a fraction or exponent. func (s *Scanner) scanMantissa(ch rune) rune { scanned := false @@ -421,16 +433,16 @@ func (s *Scanner) scanHeredoc() { // Read the identifier identBytes := s.src[offs : s.srcPos.Offset-s.lastCharLen] - if len(identBytes) == 0 { + if len(identBytes) == 0 || (len(identBytes) == 1 && identBytes[0] == '-') { s.err("zero-length heredoc anchor") return } var identRegexp *regexp.Regexp if identBytes[0] == '-' { - identRegexp = regexp.MustCompile(fmt.Sprintf(`[[:space:]]*%s\z`, identBytes[1:])) + identRegexp = regexp.MustCompile(fmt.Sprintf(`^[[:space:]]*%s\r*\z`, identBytes[1:])) } else { - identRegexp = regexp.MustCompile(fmt.Sprintf(`[[:space:]]*%s\z`, identBytes)) + identRegexp = regexp.MustCompile(fmt.Sprintf(`^[[:space:]]*%s\r*\z`, identBytes)) } // Read the actual string value @@ -469,7 +481,7 @@ func (s *Scanner) scanString() { // read character after quote ch := s.next() - if ch == '\n' || ch < 0 || ch == eof { + if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { s.err("literal not terminated") return } @@ -525,16 +537,27 @@ func (s *Scanner) scanEscape() rune { // scanDigits scans a rune with the given base for n times. For example an // octal notation \184 would yield in scanDigits(ch, 8, 3) func (s *Scanner) scanDigits(ch rune, base, n int) rune { + start := n for n > 0 && digitVal(ch) < base { ch = s.next() + if ch == eof { + // If we see an EOF, we halt any more scanning of digits + // immediately. + break + } + n-- } if n > 0 { s.err("illegal char escape") } - // we scanned all digits, put the last non digit char back - s.unread() + if n != start && ch != eof { + // we scanned all digits, put the last non digit char back, + // only if we read anything at all + s.unread() + } + return ch } diff --git a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go index e87ac6356..5f981eaa2 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go +++ b/vendor/github.com/hashicorp/hcl/hcl/strconv/quote.go @@ -27,7 +27,7 @@ func Unquote(s string) (t string, err error) { if quote != '"' { return "", ErrSyntax } - if contains(s, '\n') { + if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { return "", ErrSyntax } @@ -49,7 +49,7 @@ func Unquote(s string) (t string, err error) { for len(s) > 0 { // If we're starting a '${}' then let it through un-unquoted. // Specifically: we don't unquote any characters within the `${}` - // section, except for escaped quotes, which we handle specifically. + // section. if s[0] == '$' && len(s) > 1 && s[1] == '{' { buf = append(buf, '$', '{') s = s[2:] @@ -64,14 +64,6 @@ func Unquote(s string) (t string, err error) { s = s[size:] - // We special case escaped double quotes in interpolations, converting - // them to straight double quotes. - if r == '\\' { - if q, _ := utf8.DecodeRuneInString(s); q == '"' { - continue - } - } - n := utf8.EncodeRune(runeTmp[:], r) buf = append(buf, runeTmp[:n]...) @@ -95,6 +87,10 @@ func Unquote(s string) (t string, err error) { } } + if s[0] == '\n' { + return "", ErrSyntax + } + c, multibyte, ss, err := unquoteChar(s, quote) if err != nil { return "", err diff --git a/vendor/github.com/hashicorp/hcl/hcl/token/token.go b/vendor/github.com/hashicorp/hcl/hcl/token/token.go index 6e9949804..e37c0664e 100644 --- a/vendor/github.com/hashicorp/hcl/hcl/token/token.go +++ b/vendor/github.com/hashicorp/hcl/hcl/token/token.go @@ -152,6 +152,11 @@ func (t Token) Value() interface{} { f = strconv.Unquote } + // This case occurs if json null is used + if t.Text == "" { + return "" + } + v, err := f(t.Text) if err != nil { panic(fmt.Sprintf("unquote %s err: %s", t.Text, err)) diff --git a/vendor/github.com/hashicorp/hcl/json/parser/flatten.go b/vendor/github.com/hashicorp/hcl/json/parser/flatten.go index 6eb14a253..f652d6fe7 100644 --- a/vendor/github.com/hashicorp/hcl/json/parser/flatten.go +++ b/vendor/github.com/hashicorp/hcl/json/parser/flatten.go @@ -48,6 +48,12 @@ func flattenListType( item *ast.ObjectItem, items []*ast.ObjectItem, frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) { + // If the list is empty, keep the original list + if len(ot.List) == 0 { + items = append(items, item) + return items, frontier + } + // All the elements of this object must also be objects! for _, subitem := range ot.List { if _, ok := subitem.(*ast.ObjectType); !ok { diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/vendor/github.com/hashicorp/hcl/json/parser/parser.go index 65d56c9b8..125a5f072 100644 --- a/vendor/github.com/hashicorp/hcl/json/parser/parser.go +++ b/vendor/github.com/hashicorp/hcl/json/parser/parser.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/hashicorp/hcl/hcl/ast" + hcltoken "github.com/hashicorp/hcl/hcl/token" "github.com/hashicorp/hcl/json/scanner" "github.com/hashicorp/hcl/json/token" ) @@ -85,6 +86,7 @@ func (p *Parser) objectList() (*ast.ObjectList, error) { break } } + return node, nil } @@ -103,6 +105,14 @@ func (p *Parser) objectItem() (*ast.ObjectItem, error) { switch p.tok.Type { case token.COLON: + pos := p.tok.Pos + o.Assign = hcltoken.Pos{ + Filename: pos.Filename, + Offset: pos.Offset, + Line: pos.Line, + Column: pos.Column, + } + o.Val, err = p.objectValue() if err != nil { return nil, err @@ -128,10 +138,16 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) { Token: p.tok.HCLToken(), }) case token.COLON: + // If we have a zero keycount it means that we never got + // an object key, i.e. `{ :`. This is a syntax error. + if keyCount == 0 { + return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) + } + // Done return keys, nil case token.ILLEGAL: - fmt.Println("illegal") + return nil, errors.New("illegal") default: return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type) } diff --git a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go index 477f71ff3..fe3f0f095 100644 --- a/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go +++ b/vendor/github.com/hashicorp/hcl/json/scanner/scanner.go @@ -246,7 +246,7 @@ func (s *Scanner) scanNumber(ch rune) token.Type { return token.NUMBER } -// scanMantissa scans the mantissa begining from the rune. It returns the next +// scanMantissa scans the mantissa beginning from the rune. It returns the next // non decimal rune. It's used to determine wheter it's a fraction or exponent. func (s *Scanner) scanMantissa(ch rune) rune { scanned := false @@ -296,7 +296,7 @@ func (s *Scanner) scanString() { return } - if ch == '"' && braces == 0 { + if ch == '"' { break } diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/icrowley/fake/.editorconfig similarity index 54% rename from vendor/github.com/fsnotify/fsnotify/.editorconfig rename to vendor/github.com/icrowley/fake/.editorconfig index fad895851..480374920 100644 --- a/vendor/github.com/fsnotify/fsnotify/.editorconfig +++ b/vendor/github.com/icrowley/fake/.editorconfig @@ -1,12 +1,16 @@ root = true -[*.go] -indent_style = tab -indent_size = 4 -insert_final_newline = true - -[*.{yml,yaml}] +[*] +charset = utf-8 +end_of_line = lf indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true + +[{*.go,go.mod,go.sum}] +indent_style = tab + +[makefile] +indent_style = tab +indent_size = 2 diff --git a/vendor/github.com/icrowley/fake/.go-makefile.json b/vendor/github.com/icrowley/fake/.go-makefile.json deleted file mode 100644 index 7f688de04..000000000 --- a/vendor/github.com/icrowley/fake/.go-makefile.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "build_id_generator": "0x$(shell echo $(version) | sha1sum | awk '{print $$1}')", - "host": "github.com", - "include": [], - "kind": "package", - "name": "fake", - "tool": [], - "user": "icrowley", - "version_generator": "$(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD)", - "version_variable": "cli.version" -} diff --git a/vendor/github.com/icrowley/fake/.travis.yml b/vendor/github.com/icrowley/fake/.travis.yml deleted file mode 100644 index b809e455f..000000000 --- a/vendor/github.com/icrowley/fake/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -sudo: false -language: go - -go: - - 1.6 - - 1.7 - - 1.8 - - master - - tip - -script: make test diff --git a/vendor/github.com/icrowley/fake/Makefile b/vendor/github.com/icrowley/fake/Makefile index ab4233b3a..2d3016908 100644 --- a/vendor/github.com/icrowley/fake/Makefile +++ b/vendor/github.com/icrowley/fake/Makefile @@ -1,34 +1,14 @@ .DEFAULT_GOAL = all -numcpus := $(shell cat /proc/cpuinfo | grep '^processor\s*:' | wc -l) -version := $(shell git rev-list --count HEAD).$(shell git rev-parse --short HEAD) - name := fake package := github.com/icrowley/$(name) .PHONY: all -all:: dependencies - -.PHONY: tools -tools:: - @if [ ! -e "$(GOPATH)"/bin/glide ]; then go get github.com/Masterminds/glide; fi - @if [ ! -e "$(GOPATH)"/bin/godef ]; then go get github.com/rogpeppe/godef; fi - @if [ ! -e "$(GOPATH)"/bin/gocode ]; then go get github.com/nsf/gocode; fi - @if [ ! -e "$(GOPATH)"/bin/gometalinter ]; then go get github.com/alecthomas/gometalinter && gometalinter --install; fi - @if [ ! -e "$(GOPATH)"/src/github.com/stretchr/testify/assert ]; then go get github.com/stretchr/testify/assert; fi - -.PHONY: dependencies -dependencies:: tools - glide install - -.PHONY: clean -clean:: tools - glide cache-clear +all: .PHONY: test -test:: dependencies - go test -v \ - $(shell glide novendor) +test: + go test -v ./... .PHONY: bench bench:: dependencies @@ -37,12 +17,8 @@ bench:: dependencies $(shell glide novendor) .PHONY: lint -lint:: dependencies - go vet $(shell glide novendor) - gometalinter \ - --deadline=5m \ - --concurrency=$(numcpus) \ - $(shell glide novendor) +lint: + golangci-lint --color=always --timeout=120s run ./... .PHONY: check -check:: lint test +check: lint test diff --git a/vendor/github.com/icrowley/fake/credit_cards.go b/vendor/github.com/icrowley/fake/credit_cards.go index 47d6ca726..8d6d277b2 100644 --- a/vendor/github.com/icrowley/fake/credit_cards.go +++ b/vendor/github.com/icrowley/fake/credit_cards.go @@ -1,9 +1,10 @@ package fake import ( - "strings" - + "fmt" + "sort" "strconv" + "strings" ) type creditCard struct { @@ -12,11 +13,27 @@ type creditCard struct { prefixes []int } -var creditCards = map[string]creditCard{ - "visa": {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}}, - "mastercard": {"MasterCard", 16, []int{51, 52, 53, 54, 55}}, - "amex": {"American Express", 15, []int{34, 37}}, - "discover": {"Discover", 16, []int{6011}}, +func (c creditCard) RandomPrefix() int { + return c.prefixes[r.Intn(len(c.prefixes))] +} + +var ( + creditCards = map[string]creditCard{ + "visa": {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}}, + "mastercard": {"MasterCard", 16, []int{51, 52, 53, 54, 55}}, + "amex": {"American Express", 15, []int{34, 37}}, + "discover": {"Discover", 16, []int{6011}}, + } + creditCardsKeys = make([]string, len(creditCards)) +) + +func init() { + n := 0 + for key := range creditCards { + creditCardsKeys[n] = key + n++ + } + sort.Strings(creditCardsKeys) } // CreditCardType returns one of the following credit values: @@ -36,34 +53,40 @@ func CreditCardNum(vendor string) string { if vendor != "" { vendor = strings.ToLower(vendor) } else { - var vendors []string - for v := range creditCards { - vendors = append(vendors, v) - } - vendor = vendors[r.Intn(len(vendors))] + vendor = creditCardsKeys[r.Intn(len(creditCardsKeys))] + } + card, ok := creditCards[vendor] + if !ok { + panic(fmt.Sprintf("unsupported vendor %q", vendor)) } - card := creditCards[vendor] - prefix := strconv.Itoa(card.prefixes[r.Intn(len(card.prefixes))]) + + prefix := strconv.Itoa(card.RandomPrefix()) num := []rune(prefix) - for i := 0; i < card.length-len(prefix); i++ { - num = append(num, genCCDigit(num)) + for i := 0; i < card.length-len(prefix)-1; i++ { + num = append(num, rune(strconv.Itoa(r.Intn(10))[0])) } + num = append(num, creditCardNumChecksum(num)) + return string(num) } -func genCCDigit(num []rune) rune { +func creditCardNumChecksum(num []rune) rune { + // See: https://en.wikipedia.org/wiki/Luhn_algorithm sum := 0 + pos := 0 for i := len(num) - 1; i >= 0; i-- { - n := int(num[i]) - if i%2 != 0 { - sum += n - } else { - if n*2 > 9 { - sum += n*2 - 9 - } else { - sum += n * 2 + n := int(num[i] - '0') + if pos%2 == 0 { + n *= 2 + if n > 9 { + n -= 9 } } + sum += n + pos++ } - return rune(((sum/10+1)*10 - sum) % 10) + + // https://en.wikipedia.org/wiki/Talk:Luhn_algorithm#Formula_error + checksum := 10 - (sum%10)%10 + return rune(strconv.Itoa(checksum)[0]) } diff --git a/vendor/github.com/icrowley/fake/data.go b/vendor/github.com/icrowley/fake/data.go index 7249a9d38..f100510a5 100644 --- a/vendor/github.com/icrowley/fake/data.go +++ b/vendor/github.com/icrowley/fake/data.go @@ -3,6 +3,7 @@ package fake import ( "bytes" "compress/gzip" + "encoding/base64" "io/ioutil" "net/http" "os" @@ -11,35 +12,41 @@ import ( "time" ) -type localFS struct{} +type _escLocalFS struct{} -var local localFS +var _escLocal _escLocalFS -type staticFS struct{} +type _escStaticFS struct{} -var static staticFS +var _escStatic _escStaticFS -type file struct { +type _escDirectory struct { + fs http.FileSystem + name string +} + +type _escFile struct { compressed string size int64 + modtime int64 local string isDir bool - data []byte once sync.Once + data []byte name string } -func (fs localFS) Open(name string) (http.File, error) { - f, present := data[name] +func (_escLocalFS) Open(name string) (http.File, error) { + f, present := _escData[path.Clean(name)] if !present { return nil, os.ErrNotExist } return os.Open(f.local) } -func (fs staticFS) Open(name string) (http.File, error) { - f, present := data[path.Clean(name)] +func (_escStaticFS) prepare(name string) (*_escFile, error) { + f, present := _escData[path.Clean(name)] if !present { return nil, os.ErrNotExist } @@ -50,7 +57,8 @@ func (fs staticFS) Open(name string) (http.File, error) { return } var gr *gzip.Reader - gr, err = gzip.NewReader(bytes.NewBufferString(f.compressed)) + b64 := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(f.compressed)) + gr, err = gzip.NewReader(b64) if err != nil { return } @@ -59,54 +67,65 @@ func (fs staticFS) Open(name string) (http.File, error) { if err != nil { return nil, err } + return f, nil +} + +func (fs _escStaticFS) Open(name string) (http.File, error) { + f, err := fs.prepare(name) + if err != nil { + return nil, err + } return f.File() } -func (f *file) File() (http.File, error) { - return &httpFile{ - Reader: bytes.NewReader(f.data), - file: f, - }, nil +func (dir _escDirectory) Open(name string) (http.File, error) { + return dir.fs.Open(dir.name + name) } -type httpFile struct { - *bytes.Reader - *file +func (f *_escFile) File() (http.File, error) { + type httpFile struct { + *bytes.Reader + *_escFile + } + return &httpFile{ + Reader: bytes.NewReader(f.data), + _escFile: f, + }, nil } -func (f *file) Close() error { +func (f *_escFile) Close() error { return nil } -func (f *file) Readdir(count int) ([]os.FileInfo, error) { +func (f *_escFile) Readdir(count int) ([]os.FileInfo, error) { return nil, nil } -func (f *file) Stat() (os.FileInfo, error) { +func (f *_escFile) Stat() (os.FileInfo, error) { return f, nil } -func (f *file) Name() string { +func (f *_escFile) Name() string { return f.name } -func (f *file) Size() int64 { +func (f *_escFile) Size() int64 { return f.size } -func (f *file) Mode() os.FileMode { +func (f *_escFile) Mode() os.FileMode { return 0 } -func (f *file) ModTime() time.Time { - return time.Time{} +func (f *_escFile) ModTime() time.Time { + return time.Unix(f.modtime, 0) } -func (f *file) IsDir() bool { +func (f *_escFile) IsDir() bool { return f.isDir } -func (f *file) Sys() interface{} { +func (f *_escFile) Sys() interface{} { return f } @@ -114,119 +133,414 @@ func (f *file) Sys() interface{} { // the filesystem's contents are instead used. func FS(useLocal bool) http.FileSystem { if useLocal { - return local + return _escLocal } - return static + return _escStatic +} + +// Dir returns a http.Filesystem for the embedded assets on a given prefix dir. +// If useLocal is true, the filesystem's contents are instead used. +func Dir(useLocal bool, name string) http.FileSystem { + if useLocal { + return _escDirectory{fs: _escLocal, name: name} + } + return _escDirectory{fs: _escStatic, name: name} +} + +// FSByte returns the named file from the embedded assets. If useLocal is +// true, the filesystem's contents are instead used. +func FSByte(useLocal bool, name string) ([]byte, error) { + if useLocal { + f, err := _escLocal.Open(name) + if err != nil { + return nil, err + } + return ioutil.ReadAll(f) + } + f, err := _escStatic.prepare(name) + if err != nil { + return nil, err + } + return f.data, nil +} + +// FSMustByte is the same as FSByte, but panics if name is not present. +func FSMustByte(useLocal bool, name string) []byte { + b, err := FSByte(useLocal, name) + if err != nil { + panic(err) + } + return b +} + +// FSString is the string version of FSByte. +func FSString(useLocal bool, name string) (string, error) { + b, err := FSByte(useLocal, name) + return string(b), err +} + +// FSMustString is the string version of FSMustByte. +func FSMustString(useLocal bool, name string) string { + return string(FSMustByte(useLocal, name)) } -var data = map[string]*file{ +var _escData = map[string]*_escFile{ "/data/en/adjectives": { - local: "data/en/adjectives", - size: 119, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x14\x8b\xc1\n\xc20\x10D\xef\xf3W\x85H\xf5d\xb0\xe2=\xa6cYH\xbb\xb2n\xf0\xf7\xbb\xb9\xcc\xf0\x98y\x93\x18f6L\xdd\x15Y\xff4<\xcb\x16\xb8ʻ\x11ׄ9/1\x98\x97\xc1I~\x15\x97\xc6\xea&\x15\x99\xf6Q\xdb\xcbQ\x89EV\xe2\x15\xa1\xb8\x1d\xdf\xee\xb8w\x1f\x95\xc4\xe2\x8d\aw\xf5\xe1o\xe2\xa5\xe1\f\x00\x00\xff\xff\xd8\x18m\xadw\x00\x00\x00", + local: "data/en/adjectives", + size: 119, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/xSLwQrCMBBE7/NXhUj1ZLDiPaZjWUi7sm7w97u5zPCYeZMYZjZM3RVZ/zQ8yxa4yrsR +14Q5LzGYl8FJfhWXxuomFZn2UdvLUYlFVuIVobgd3+64dx+VxOKNB3f14W/ipeEMAAD//9gYba13AAAA +`, }, "/data/en/characters": { - local: "data/en/characters", - size: 72, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x04\xc0\xc3\x01\xc4\x00\x00\x00\xb0\u007f\xa69c\x9c\xdav\xa7o\x02\xa1H,\x91\xca\xe4\n\xa5J\xad\xd1\xea\xf4\x06\xa3\xc9l\xb1\xda\xec\x0e\xa7\x9b\xbb\x87\xa7\x97\xb7\x8f\xaf\x9f\xbf+\x00\x00\xff\xffq\xa7L\x96H\x00\x00\x00", + local: "data/en/characters", + size: 72, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wTAwwHEAAAAsH+mOWOc2nanbwKhSCyRyuQKpUqt0er0BqPJbLHa7A6nm7uHp5e3j6+f +vysAAP//cadMlkgAAAA= +`, }, "/data/en/cities": { - local: "data/en/cities", - size: 4837, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\\X[\x9a\xe3(\xd2}\xd7*\xb4\x81\xfe\xf7\x90wgwf\xa5\u007f\u06dd\xf9\xd5cX\xc2\x16m\x04\x1a@v\xb9v5k\x98\x8d\xcd9\x01rWϋ\xe3\x04B\b\xe2r\"\xf0]o\x9c\xf8\x1c\x9a\xbbc\x98\xa3\xb4+\xeb\\j\ue70c\xa6\x17Ƚ\xf8+\xc4 \xe3>R\xb7)\xb4\x9f\xd6\xfc\x85\x17\\\xc6\v\x98;J\x1fb\xfb`3&\x8e&\xdaN|\xfb\x80ׂo\xee\xbc\fƎ\x90\xbd\x89I\a\x8e\xc6%<\x1e'\xe0lC74w\xd3\xe4L\xfb)\xce\x19\xac\x10;魨\xcc\x141\\C\xfb\x12\x05+@\xcb&\xe9ó\xc5ZY\x12&\x9b\x88\xbd\xe4\xc1\xc4\xcc\xf5\xf3E\xb2\x89\xcdݼ\x9f#Գ8\x8e\x9e\x8d\x17\xd7\xdc\xfd\x9c\x934\xf7r\xc2^\x0eָ\x1e\xd8\xf5\x17\xeb۵\xc4\x13\x14\xef\xad?BƔå\xb972\x8f\xc1g\x00\xe7\xf4\xa7}\x91\xd8\x1b\x9fT9\xb8p\xc1\x97\x00\x97Ig\x83\xcd\x18 o;\xec\xf2\xdeē\xe1\x99\xee\xcd\xd9Dw\xad\xb6\xbd\xb7\xc7\x16K\xc7\xf6\r\x1b\xa1v\xe4X\x1a\xc2\xd4ܻ\xd9\xd4awő\x9a\xfb(=\x0er%\xb8\xe8R\xd1\b\u007f|\xbe\x84\x80\xfdG\x9b\xe0!L\x9c\xb1#\x1a\x00\xc0K=\xcf\x1c\xf1L\xa5ù\xe0\xd1\xe6A\x9c\xec%\xc1k@\xe6\x87\xed\x02\x81=\x84\xe8\xad\x14\x17R\x1f\r\xecD0I\x8e\xb6@\x98\xe4H4J\xc41\xf8\x1e=\\v\xfb \x93\xcd\xc1\xf1qt\xd8PO0\x1a\xf7\xdb\xfe\xfa\x1b\x8e\xf1\xdb\xd6\xe8\xa3\xc9z\xf8F\xd7\xd3`x\x10<죸\xfae\x18/\xf17b1\x80A\xb77X_\u007f\xab\xfd\x1e\x86p\xe9\x06@\xac3\xccN\x10\x8e\t\x91\x82%\xe2\x9cڕ\xb1\xc7!c\x96\x93h\xd41@WZ\xe6\xc1\xc1\xe8N\xb7\xeb\x02\x1c\xd2\xc3\x02\n-f\a\xe9\x06\xa3K\x06Qc\x01\xb8\x83\xfc\xa0\x18U\xd1%\x82c\x04q\xb7m8\xb4\x0faD\xbcwX%\x8cSy\xee\xbb\x10q\xfa\x10!\x85\x03QC\n2x\xa9\xa2\x0f\x04ٴ\xef\f^\x8eb\xff\xed\xbb\xda\x8d\xb3\x8d͓\xa4\xac\x13[0Gh\x9e\xe0u\xf9\v\xcb\x10\xe0\x90\xb1\f\x15\xef\x13\xbe\xc3y\x86`k\x8e\xb3\xef9v\x02\x11\xc0u\xcd\x13\xcc~-Gz\xf2\x9d\xf5\x16L\xd0<\x81\f\x98\xec\x90خ\xe5\v\x19F|\x9a\xa39A\xfc0\xe4\x85g\xb1\x91nU\xa9\x14\xf0\xccH\x8d\xa9\xac\xf6l\xa2\u05f8x\x86:\x86H\x10\xcd^\xe6\xe3\xd0<\a\x97\xc2\b\xe13L\v\t;!-\x8f\xc7\x02\u007f\x0f\x1e\xd1K8\xebӔ\x17/=\x87\x19\xaf\x80e*\xc5=\a\xa42\xb6R\xe3\x132\xc1\xf2\xcf3\x1e*\x87\xbd\x88\xcbMa\x9azޢH\xf3b\x1d\xe8\xb0yq\xa6\xecR\x01\x02\xady\t\xced\n\xff\x13\xe3\xa9Q\xbelw0\xa6 <\xa1\xa5\xb4|\xfd%\x1a\xe3\xcb\xd1_\xa2\xed\xcb\x10\xf3\x81\xa4\x046~\x99\x05k#\xb0\x80\x12b\xcb4+q\ax\x03\xc9~/Wh\xfe\xc0\x18_\xc9E\xac\x05\xd5/\x9c\x88\x81< \xde\xf9\xc2\xf5\"\x9cb@\xaf\t\xfcu\x04\x1cM\xc6o\xecf\xee\x0f`\fI\xea'W&M\xca\v+\xdb\xf3\xd0%\xcfWHd\xc4$\x96\xa1\xbaG\xea\xd0\v\xab\xe0\xc8E\xb0\x1fP.^[\xe1\x01\xf9d\x05;#d3wZ\x16\xfe{@\x19q5#\xff\x9a\xd7Q\xbf\xe6n\xa0\xce~E\xd4\xe0<_\x86_\xa7\x12n\x99\x0e\r\xc6\x00\x0f\xbf\xfa\xa33J\xbd\xaf\xf0w\xf3\xcaBD\x81\"\xa2\x1eyMp\x04\xbe\xf1\xbbt'n\xe9\x0f\x1c\x14<\xf0\avQ\x82\x81\xa8\x98\xe4\r\x84+\xff\xf97\xac\xdd>#Q@\xb4\xfd\xd1pt%,\xb5\v\xb81\xda[\xe5\bJ\x8b\xba\xa0\b\xf94\x16\x00\xde\xcf\xfa\xfa\xff\xcfXL\xc7>\r\xbd\xf1&\a\xb9\x9a\xac\x0f\x91H\x8bѫRl]\x95o\xf6\x88:\xb2h_8&\x1f\x9dL\xfb\xe4\x12X&\x9a\xa2!\xc8Mʊ'Ļ\x02\xb5ɛ\xf8N\xd49o0w\x9af\x825\x94\x01\xed\xc1`2\v\x10f\xe0\xcd%É\x118\x86`Rj|\xb7)YX\xbd4n\uf847\xfb(=\xbc\x80\xb4#\xd3\xc2\xe5FA\xe7@\x8d\x8a\f\x98\x17\x9dF(\xcaް\xea+\x8c\xfcH\x05u7p\xe3T\x00\x18\x91+\xf2\xc5ۆB\xd1/]\xc27cz\xba\xe8\x9b93u\xea\u0605\x1f\x87`\xb2ALJ\xcej\xf9o\xac\xc5\xfc\xbd\x88Ôp\x863\x1bĖ\x06#\xa4\x1a\x98\x12\x1b\xfd\xe8\x8c\xf8d\xd1i~\xfc%\xb6\xf9\xc0\x96\"X\xe0\x03l\x8a\xd4,\x02U\xffL\xac\xa1\xf7Q\xfc\xf3A;\xd2u\x1f?<\x89o-\x9d=خFyդa\xb2\xb6\xa5\xc2\x16\xbc\x94X*\xba\x9f\xbfˣVTf0|\xd5>\xc1D\xe8|1\x88\xbc\xb7\xc9(\x18i2\"g\x91pktuZ#\x00B\xbb\t{\xa7\xf3\x91\xf6\xdaj\xad\x8d\xd6\xea5\x8c\xeaf0\xc6\x1aQ\xd8n\x98]Ħ\xd7J\xb4F\x8es\x136\x8d\xa1Zoms.t\xb5v\xc2^\x04\xe1\xa2(\x96\x03\xaf\xd1T%\xc4vq\xee\xa2\xf1\x83\xee\x8a\rf\xac\xc0\x16\xa4\xbd\x8b\xba\xb70\x06\x15l1@X(\n\xaa\xdcV\x03f\x1bY\xe5\x12?\xebpA\xbcl@.C\x80\xf9c\x0f'\xdeԹc{r\xbc\r\x90\x1bᬪ\xfdj\xc6el\x8b\x1d\n;\xa0#\xbc\x8b \xdb\x1847n>\x1c\x88z\xb6k\x90\xf4k\"@/\xb1\x18\x03\x1a\x13\xb3\xc4\xdcF\xe3\x10Ғ\x15 \xba\x81m\x12\x00h\xbcS\x82\xdc\xd8\x00w\xc3.\x04\xa5K\xdd\xd8\t\xc6Q\xc3ko\xaeH#n\x13\xba\x13\xfb\xa5M\x18<[0ͫ\r\xab\x1d\xf8\xac0\xd4?\xb4[PlB\x82\x1d\xd1s\x13\x14;\x02\xa5f+\x1d\x82\xc4\xf0n\xb7eO+\x1c\xf2\xa0\xb8\xc4\x1b\x8bb\xdcP\x18\xafl U\x8dsE\xec\xe3C\x99\x8f\xb6y\xd4\xd2B\xe5њc\xa8h\xac\v\xb2g\x12\xf6g\xaa G:\x8b\x0eL\xb5\x17\x140t\x1a\x8aQ\x11m\xd9\vp\x90\u007f\xa1JU\x9c\xcaڿ\xcf܂\xccY\ru\x1b\xe1\xdd\x02\xa5W\xea\xceސ\xa1}\xacx\xb6\xa9\xfd\xd8\xdb4\x15\x1d.\xed\uab95^\x97\xd1l\nZ\xcb\xde\x15\xb4AM\xac\xfb\xda0|\x88\xaa_\xb7L\xf2ؔ \xc1\xfd\xb5\"t\xbf{$]\xd5x\xbb\xf8\x15\xdb|\xd3\xe2\xfc\xb3\xc2gsK\xf0[\xc8\xd9e\x1e\xf8\x93\x94P\x94\xb5\xe0\x1eS1|W\xa0\xa1Y\xa2\xe8\xb5k+\xb8w86\xc6\xdb. #\x97\xcc\xc0\xc5j\xe9^\x005\x8e\xb6hW\xc1\xeeS\xc0\xf1\f\x9b\x030\xec\x81%\xb90m\xb9\xb0m-[C^@\"\x95#\xd9U3xkG{[\x1c)xk\x17\xa0\x98\x1eA\x06y\x86\x85 }\xe0\xe2\x10\xb4\x04S\xbd\xbd5\xedEE\xd9\\\xa0\xb6\r;\x19\xc22p\xa3\xab\xa2\xfeO\xe8\xe4\xffC\xd7\xe3\xf4q.t\xb2\xcdH\x8f\x02f4f\xd5U\xf0\xff\xec\x17\xec\xfd\xf5L\x0e\xdd\xc2T\xf5\xbe\xb3\x9d\xb3v\xe1hyO\xcd\x0efhvf\xc0i\x10R\x8ap\x80\x1d\xa2\xbb\xa3\xf5\x01\xf87\x84.\xb6\x1b\x02\x17\xe9\xcb\xd5h\x87\xf2ξq\x87҅-\x9af\x87\xae\x1a\x93\xe0ZK\x93\xec\xe2ܝ\xe0\xad\xdd\xcc;'\x85\xd1k\xe6\x0e\xf7n\xec\x1a\x92}t\xb3\xbb \x8d\xae\xb8\x0e\x1a\xed\xdaR\xf3\xe7\xc9\xca\xd0\xfc\xe9Y\x99\xf5\xb3\u007fNZM>\xa5\x93\xb2\u007fu\x04*\xf6'ޜaf6t\xd8ȧ\xedr\xa8\x94\xf9ɋp!\v0\fbD\x9a\xc24_\xe2\xfc\x9c\xab\xa8&\xf8\x12\x9a\xf7\x8b\xff\x90h\x0f\x0f\x84\xe2P\x16\xfa\x02\x9f\xe1\aw\xb4z\xfbT\xfc\v\x89P\xe7\xb9Z\xfd\xe4\xd1\xe8\xc0h\xbd\xf6{\x8aC\xa9\x86_\x83\x91\\\x11\xca\a\xab\xd3\x17^\xc152\x15\x90\x8b\f\x17J\xd0l\xe0\x04\xb6\x13\xd0\xc1\xafj\xbc\x02\xb8\x06\xbbP\x06\xf6\xf7\x80\f\xac-\xdfw־\xb2\xef\xefz\xbd\xfb\x8eki1\xe2w\x14\x04;q\xa4\xeb\x96\n\xf2\xdf\x00\x00\x00\xff\xffPpU\a\xe5\x12\x00\x00", + local: "data/en/cities", + size: 4837, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1xYW5rjKNJ91yq0gf73kHdnd2alf9ud+dVjWMIWbQQaQHa5djVrmI3NOQFyV8+L4wRC +COJyIvBdb5z4HJq7Y5ijtCvrXGrunIymF8i9+CvEIOM+UrcptJ/W/IUXXMYLmDtKH2L7YDMmjibaTnz7 +gNeCb+68DMaOkL2JSQeOxiU8HifgbEM3NHfT5Ez7Kc4ZrBA76a2ozBQxXEP7EgUrQMsm6cOzxVpZEiab +iL3kwcTM9fNFsonN3byfI9SzOI6ejRfX3P2ckzT3csJeDta4Htj1F+vbtcQTFO+tP0LGlMOluTcyj8Fn +AOf0p32R2BufVDm4cMGXAJdJZ4PNGCBvO+zy3sST4ZnuzdlEd622vbfHFkvH9g0boXbkWBrC1Ny72dRh +d8WRmvsoPQ5yJbjoUtEIf3y+hID9R5vgIUycsSMaAMBLPc8c8Uylw7ng0eZBnOwlwWtA5oftAoE9hOit +FBdSHw3sRDBJjrZAmORINErEMfgePVx2+yCTzcHxcXTYUE8wGvfb/vobjvHb1uijyXr4RtfTYHgQPOyj +uPplGC/xN2IxgEG3N1hff6v9HoZw6QZArDPMThCOCZGCJeKc2pWxxyFjlpNo1DFAV1rmwcHoTrfrAhzS +wwIKLWYH6QajSwZRYwG4g/ygGFXRJYJjBHG3bTi0D2FEvHdYJYxTee67EHH6ECGFA1FDCjJ4qaIPBNm0 +7wxejmL/7bvaPGTJFgLxDQ326ODqap65l4ECcRaXoQlhrwa6TpicmkdBnOmzR2EcBJic8Ax7GQAe9tE4 +fDqq3Jhr+yEnHRSs82gSVmxXIbfbKWLreGIFduzbe75i/bwXiB847WOAp/A8JMSbC0QXjxh9nAWng9jD +khA+jbONzZOkrBNbMEdonuB1+QvLEOCQsQwV7xO+w3mGYGuOs+85dgIRwHXNE8x+LUd68p31FkzQPIEM +mOyQ2K7lCxlGfJqjOUH8MOSFZ7GRblWpFPDMSI2prPZsote4eIY6hkgQzV7m49A8B5fCCOEzTAsJOyEt +j8cCfw8e0Us469OUFy89hxmvgGUqxT0HpDK2UuMTMsHyzzMeKoe9iMtNYZp63qJI82Id6LB5cabsUgEC +rXkJzmQK/xPjqVG+bHcwpiA8oaW0fP0lGuPL0V+i7csQ84GkBDZ+mQVrI7CAEmLLNCtxB3gDyX4vV2j+ +wBhfyUWsBdUvnIiBPCDe+cL1IpxiQK8J/HUEHE3Gb+xm7g9gDEnqJ1cmTcoLK9vz0CXPV0hkxCSWobpH +6tALq+DIRbAfUC5eW+EB+WQFOyNkM3daFv57QBlxNSP/mtdRv+ZuoM5+RdTgPF+GX6cSbpkODcYAD7/6 +ozNKva/wd/PKQkSBIqIeeU1wBL7xu3QnbukPHBQ88Ad2UYKBqJjkDYQr//k3rN0+I1FAtP3RcHQlLLUL +uDHaW+UISou6oAj5NBYA3s/6+v/PWEzHPg298SYHuZqsD5FIi9GrUmxdlW/2iDqyaF84Jh+dTPvkElgm +mqIhyE3KiifEuwK1yZv4TtQ5bzB3mmaCPESUtje5FAu9MeprXBPrqha86TxlnxBjb/ZsSEsK4limnGk5 +2vYt9BY/o7ScL4Q2q5hCB+GPyxEDnuAEICg2NFpVivIPtNiAOtsTUzDagTrrRcr8q2gVeLt6PW2l73cU +jP0MMY4hD1oQEzQ/SAZR1K1Az6bjZPRHYSrAq2CO/SS4VhJ6R/ro+t0zCxYy4J1pjiNCgj41lAHtwWAy +CxBm4M0lw4kROIZgUmp8tylZWL00bu+hh/soPbyAtCPTwuVGQedAjYoMmBedRijK3rDqK4z8SAV1N3Dj +VAAYkSvyxduGQjxKSWviGJRI3kmL7XYQVu/3G0dac2neZ1QBEto3mfiDPtEvXcI3Y3q66Js5M3Xq2IUf +h2CyQUxKzmr5b6zF/L2Iw5RwhjMbxJYGI6QamBIb/eiM+GTRaX78Jbb5wJYiWOADbIrULAJV/0ysofdR +/PNBO9J1Hz88iW8tnT3YrkZ51aRhsralwha8lFgqup+/y6NWVGYwfNU+wUTofDGIvLfJKBhpMiJnkXBr +dHVaIwBCuwl7p/OR9tpqrY3W6jWM6mYwxhpR2G6YXcSm10q0Ro5zEzaNoVpvbXMudLV2wl4E4aIolgOv +0VQlxHZx7qLxg+6KDWaswBakvYu6tzAGFWwxQFgoCqrcVgNmG1nlEj/rcEG8bEAuQ4D5Yw8n3tS5Y3ty +vA2QG+Gsqv1qxmVsix0KO6AjvIsg2xg0N24+HIh6tmuQ9GsiQC+xGAMaE7PE3EbjENKSFSC6gW0SAGi8 +U4Lc2AB3wy4EpUvd2AnGUcNrb65II24TuhP7pU0YPFswzasNqx34rDDUP7RbUGxCgh3RcxMUOwKlZisd +gsTwbrdlTysc8qC4xBuLYtxQGK9sIFWNc0Xs40OZj7Z51NJC5dGaY6horAuyZxL2Z6ogRzqLDky1FxQw +dBqKURFt2QtwkH+hSlWcytq/z9yCzFkNdRvh3QKlV+rO3pChfax4tqn92Ns0FR0u7equlV6X0WwKWsve +FbRBTaz72jB8iKpft0zy2JQgwf21InS/eyRd1Xi7+BXbfNPi/LPCZ3NL8FvI2WUe+JOUUJS14B5TMXxX +oKFZoui1ayu4dzg2xtsuICOXzMDFauleADWOtmhXwe5TwPEMmwMw7IEluTBtubBtLVtDXkAilSPZVTN4 +a0d7WxwpeGsXoJgeQQZ5hoUgfeDiELQEU729Ne1FRdlcoLYNOxnCMnCjq6L+T+jk/0PX4/RxLnSyzUiP +AmY0ZtVV8P/sF+z99UwO3cJU9b6znbN24Wh5T80OZmh2ZsBpEFKKcIAdoruj9QH4N4QuthsCF+nL1WiH +8s6+cYfShS2aZoeuGpPgWkuT7OLcneCt3cw7J4XRa+YO927sGpJ9dLO7II2uuA4a7dpS8+fJytD86VmZ +9bN/TlpNPqWTsn91BCr2J96cYWY2dNjIp+1yqJT5yYtwIQswDGJEmsI0X+L8nKuoJvgSmveL/5BoDw+E +4lAW+gKf4Qd3tHr7VPwLiVDnuVr95NHowGi99nuKQ6mGX4ORXBHKB6vTF17BNTIVkIsMF0rQbOAEthPQ +wa9qvAK4BrtQBvb3gAysLd931r6y7+96vfuOa2kx4ncUBDtxpOuWCvLfAAAA//9QcFUH5RIAAA== +`, }, "/data/en/colors": { - local: "data/en/colors", - size: 128, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\f\xcaA\xaa\xc2P\f\x05\xd0\xf9\xdd\xd5\xff\x82ED,R\x04\x87\xa1\xefRC\xd3ĦF\xb7oGgrnl\xf8\xb7\"\xba$\x1d\x0f\x9a\xc5\x17\xd7\x14\x9f\x88\xbe\xf2e\xc4]\xc3\xf8\xc6ɛN\x81\x81b\xe8\xd5g\x1ck\x1bUЅ5zF\xc3Eꃿ\xb5d\x91T'\x86ʵB7\u243al\xe1\xfb\xc8\xd8\xe9k$\xceO\x99\xf5\x17\x00\x00\xff\xff\xfe\x16\b\xa6\x80\x00\x00\x00", + local: "data/en/colors", + size: 128, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wzKQarCUAwF0Pnd1f+CRUQsUgSHoe9SQ9PEpka3b0dncm5s+LciuiQdD5rFF9cUn4i+ +8mXEXcP4xsmbToGBYujVZxxrG1XQhTV6RsNF6oO/tWSRVCeGyrVCN+KQumzh+8jY6Wskzk+Z9RcAAP// +/hYIpoAAAAA= +`, }, "/data/en/companies": { - local: "data/en/companies", - size: 3157, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffTV\xdbR\xe3<\x13\xbc\xd7[q\b\xd4G\b\xb0@\xb1\u007fr'\xc7J\xa2\x8dm\xb9|\b\xb1\x9f\xfe\xef\xee\x91\xd9ڋ-6\xb6<\x9a\xe9\xe9\xee\x99\xf5w\xac\xe2pr+?%\xf7\x95R\xfeQ\xa4\xab{\x8cG\xfd݄p\t\xc9mS]\x8cn\x15\xbb\xe0^\xa7Ԕ\xa1s\xf7S\xe3\xe7yr\xf7\xa1\x8e|\xf9;\x9e\xe3<\xbb\xff\x9a&\xed\xdc[\xbc\xa6f\xba\xba\x8fƷ\x83?\xf6n\xeb\xeb\xe8\xdd\xcd\xc5\u05f5\xbb\v\xcd\x10\xf5\xb3\xf0\x83w\x0f!\x94u\xbc\xba\a_\xe2\xa6\xcfS\x1a\x8f\xa7\xa1\xe8by\f\xcb/\xbe\xbe9\xc6\xcb\xe8\x9e<\xc3ގEQ\x05>\xbd\x8f\x17\xdf\x06\xf7\x1c\x18\x13\xcf\xe7\xb9\b\xbe\xe1\xe1\xba\xf08}\xed[\xfc\xfc8O\xf8\xf6\xa1\x8am?\xa4\xaev\xb7]\xfa\xeeCQ\xf9\u00adpM;V}pw\xe9\x18Y\xf2\xb3\xff\x93\xdc{\xf0Ւ\xc3wD\xd2\xc0\xaa\x19\x97|,\n\xe3\xa5\x16u\xdc\xfb\xa2?\xa5\xa1w/\xad\a\x82\xa8\xf2\x12\x82\xbb\xad\xd2\xf1\u007f\x1f\b\ap\x91\x80\xd2)\x8a\xd0\xf5\xed)t?\xa5)\x89\x8fslP\xcc\x1b\x82\xa0\t\xfd \x14\xff\xf8Z/\b6@G\x95\x19\xe2[\xcf\xea\xf5\xe1\xfbi\x9ac\"\xba\x05n$\x18MJe\x15\xf2\x99>\f\xee\x13)\xee\xbf=nܦ2%\xf4\xebҦ\xd8\f\xaa\\A\xf0\xa4?\xf1\xc0g7\xf2\x04\x81\xe0_\x16\xd0\xfa\x92\xccP\x12\x9b\xa9\x19\x02\xda4\xcc\xee\xd1\x17\xc3\xd8\x04<*\x00\xb9[\xfb\x89,Y\xfbyt_\x91\xa7T\n+\x00\x81p~\x97\x12\x0f\xe8i1\x1eY\x0f\xf0 \xc8\xfb\xb1@\xfb\xe2%\x1cb\u007fB\x04\xa4\xf1D\xc4n\xbbHt\xd8L\xbe\x15\xb0@1\x97\x87\x94\xe3a\"\xf0\xbcc\xed\xed\x8azN\r?\xaf\x98\xbc\xb5\x18w}\x9c\xc6á\ne\x870L\x87\xa4}\xc0\xffs{QJߦ\xc1\xbd\xe3\xfbZ/\xf6'?\xa8x0\x97a\xf3\x9d\xeb\x05\xdb;p\xb9$\xe8e\xa8\x04\xaaal\xa4\xb0\x1e\x0fS\xcbD\x86.\x928\xe4\xf5\u007f\xecӗ\xee\x00+U\x17\x9a\x9b\xf9\xb8\x89\xd0\x01%\xb7\xafF\xb1\x81\xea\xc8\x19\xf4@\x14\xe5Qn\x17P(\f\xdfT\xe1\x06TM\xee\xd7(\x9a\xaf\"\xc9\xffJ\x86\x8du\vαc\xe0S曮\xf8\x87\xb9\x9b\xe9;u\xe7\x9e0\x12\xa1\xe7\u061c3\x1a@\xf4\x00=\x12'Q\n\xb9 \xecV\xdd[I\xef?=$\u007f\x94\xaf\x1c\xc1\xe4\xc5\xe7\xd4>\x93\xdb1\xdfO\u007f\x14Q\xd8\x1d\x8ak\x15\t\x1a\x10h\xfc\x10SCq\rC\xe8,\x9dߩ+\xdbPF\xf3\x84|\x02\x19\xed\xdcf$ʾ\xf2MX>Y\xd4ٙ\x871\xe1Zw\xb7?G$\xa5W2\x8d\xcc\x0e$\x85\x8f\xcd\x05\x90\x04\xa1m\xa2\x85\x86rc\xc9\xc7\x03\xd1\xddҗd\x01\xd4\a07\x87\xd8\xfa\xb3\x84\x81\xa2\xa8\v\x02\xf0m\xc7\xf7\xa13\xbd\xe4\xa4e\x01ɽ\x92\x89π\r\xe0\xe0\xb6\xecE\xb1\xd5% \xdc5\x1b\r5\xb4\x19\xf1K\xd4\a\x9b\x8c\xac/$\xa0\xb8\xa5$n\x00\x11ɕ\xb47\xa2\xa1\x91u\xceHS\x8a\xa3\x85\xbc@[\xcc\xfd䙨\x8fL\xfb\xa4\x96\xde\xe3\xe1`6aSN\f\x90\xc1\x10!\xf3'\xfa+\x1e\xb1\x19\xc0\x9b\xa2\xea\xc6\xd6:*L\x91&\xf4\xf9\xa2\x1bОC\x85s\xe4\x1bc\xab3\x1c\x82\xcaT\x84\x90\xd0\xe0Z\xe6S,\x8f3B\xde\xe39\xfd\xd8\xfa\xad \\\xa9\x06\x98\x8b>\xb9\xcf\xc5\xdc\xe18zn\x15\xbfU\xdc0\x10Ĩ\x1bI\x12f)\xd0wr\x05bn\x02:k\x1ba\xc5y\xb5\x90\xe1C\x97\xa4\xfb&\xda\b\xe2l\xd9L\x80)\x8f}\x99<\x00\x94/\xf0\x02b\xc7]b\b恙j\x1c\xcbc\xf6&\xac\n7Q\x06\xbb\xf3\x8c\xa7s\xb9\xa9\xb6o1\x88\x99\x80\xfd\x1e\xfe\x8a=\x17;ϸ\xdcB\x9bv:3\xcd?\x1a}\xd2\u007f6\x93\x0fˉ\x9a\x97\x1c\x81\x89\xc8\xfa\xb3\x12,\x0e\xf6\xcf\xceD룾1q\xd8\xd2e ?i\xb9\\\xc6&\xf3\x16WLUֲmb\xda0h3ASƍ\x82mu\x0f/\xe6B\xa9\x8c\xb4\r\xbd\x12\xe9ܸl\x85\\@\xcaŔ\xc8\xf0\xac\xe5\xec\xfa\x0fKBˈ\"\x1f?\xad0\xab\xe3g\x9f\x19\x96\xb5';\tF\xe5\x97\f\xe4-\x95\x92\x8e/d\x19Xl\xafZ\xac\xa2Qd`\xd6<\aAp\xb8\xa8w\xf4\x9f\xec\xc1\xcbVɛ\x1f\xf5\xe4\xcbx\xb5\x12FZo4\xb3\x93\r2\nD\xeb\x13ljm\x9c^\xb4\aČ\u007f\xa3\xdd^\x9a\x12\x99\xd8Mn5\xb6\xf1\xd8\xfc\x04r\xe6\xa4+nD\xff\x0f\x00\x00\xff\xff\x16.\x1a\x04\xa5\xad\xb7\x99$\xb1\x99\x89\x14ꈓ\xcaJ\x9b\xa8\xc0młB\x95\x1a\xc8B\xcb\x10;\xe5z\xce\xf7\x87Ta\x1djv\x83xW<\x0e\xd3\xf3i\x88\x81\xac\x1ePN\xe9\x99CE\xf2\x13&.\xa8\xa3\x9e\x06\xa5\x81D\xf7\xae\xb5\xd4\xf0\xd0\x19}\x88\x1a\x0f\x1d[\n)\xd3VR\xafT\xce\f\xe2\xf4\x03\x0e\xbd\x9a\xb3蒺\xbc\xf0V\x8exb\xe1\a\x98\x94\r~\xe0p\xe6\xd6\x1f\xd5ԅ\x8fÉ2\x93\x8e\x1c/&.\x02\x9dłH\x94\xa1+\xde$\xb4r\xb1\u007f\xb8\x8a\x1f]#\x88ڷ\x9a\xb1\xee8@\xec\xc3\bur,ō\xda8\x90%\x18\x98lK\xea\xe8\"\x85=\x9e-\xeeh\xf0\xbaI\xb8\xc1,\xa9\xafE17\xbe\x17\xa7W]\x98\x0f\x0e\xdf\xd6\t\x98\b\xe6\xb6\x1d\x0f\xd1\xdcZ`\xd8\x1e'ɯDȇ L\xf7I\x1c\x93\xb9E\x82\x82\xd2!z\xc5\xe7m\xec\xc4\x1f\xc0ܑݫ\xdd\x17\xf3\x8bO\x1b܂\xf0\r\x9f\xa1\v\x9e\xaf~\xdd\xc9O\xc1\xe2r\xcc\xee\x02\xb9\x9aA\xd8\xc1~<\xa2@\x9aw[oGǃ\\\x05%\\\xe98\xbc\x03Ex0\xf7T!\xdd\xf7\x94#\u007f\xcf\x1e0S\x1a\x90\xeb\xd1\xdcwz\u07fdT\xc84*\xcf\xdc\af<\xa7dz\x1f\\\xc6\xc9=B\xc0֧\x03+\xdb\xeb\x12\xb9\a\xf2\xc0\xe1Łq\xd7\x14\x81\x89\xfc\xb5\x10\x003a7\xea\v\x0f\x048\x9b\a\xa6\xd0\xe4\xfa\xd8\xd47ޑ\xbdF\xc3\xd1\x01\xaa'\x0ej\xef\x93\x0f\rv+:Ӿ˽k\xc5n$\xb3\x92 \x15\x00dV\x1e\x99\xfcR<\xfb\x10\xbb\xcb&\x87ج\xd2\t\x0e\x99\xd5\x18\xda\xf1\x9c?]\x13\U0003c9a8}`\xcd\xe8}\x88\xf9\x9a\a\x1f;o\xd6R\xe5\x1e\b:\xea\n$F\xb4\xab\xc8h%k\x89]ʝr\x9d~3\x8a4\x85\xd6l\xa8F\xe8\xb0r\x93A\xb4A\x06Z\x1aj$\b\xa0\xa1\x93d2\x0eYe\x1b9\"\xcd`\xb28\xaa,\f\x1dY{\r.\x04h\x9a\xf2+1\xd8\x04d\xd0t\xab\xb2\x92T?\xfa\x18\xa1\xe4\xdfR{\xb3\x91:\xcc1\xdex\xdb\xf8\xa3RG\xaa\xd1\xea\xb4Y\xee\xe0\x02\xb7!\xcb\xe2\x00\xbcQ\x04\x1b|\x9d\x8f\x9d\x15n\xf9=\xa4\x1f\x95f\x9e\xa9\x17\x05\xe03\x1eM\xe6\x99\x0fd\xb1*Z'\x13?\xf0\x85v~kY\x85\xa7bIv\x8e\x82\xee\xbe3\xe5L?#\x9b\x810\x1e\xc0\xe1\x95g\xc1\x94\x99V=\xe8\xc3\x0fo/\x8d\xc2\xe4\xfciUl\xb4?\xa23^\xc2\x02ʼnF\xf3\r\x95`\xb6\xb4\x9f\xe6\xd7\x16\x0f$]yИ}\xec\xba_І\xebt\x10n\xa0w\x80\x14\xc8\x01\x13J\r\x9b\xc1\xbf\x9d\xac\x1a͖\xe1\xe6\x16MR\x0e\ah\x06\xb3\x95X\x93\x84\xeb\x84B\xf1N$\xc4\xd4\"\x18[\x94Q\xf4\xdaμ\xf9/i-\xbepr\x18i\xe6\xc5\xf79_/h\xf5J0KP\x90%&W\xd4\xc1\b\xdf,\xf7\xe3,x\xc0\xc6]\xb4+\x89q\xc8\xf5\xf6\xccG\x19f\xe9:\xd5r91!c\xdel\x05\x9e\xf2T\x9f\x9a<\xeb/\x9a7A\x13\x02U\x15\xde+\xa6\xae\x90\xfd\x9a\xe6yISx\x9d\a닝\xef\xa7{\xb6\x10Ղ\xa6QRB\xf5\x16_\x03)\nJ\xc5\x0e\x9c.1\x93\xf3v\xacᅦ\xbcT\x1b\xa8X3\x00\x88\r:\xc0\x01\x85gJ\v\x14\xee\xf5(\x98<\xf8K\x1d&\xfe}\\\x95\x88\x92\xcdr\x14\xe8<\xb4\xe6\xcd\xdc\xf4\xae\xd6OR\x98ܜ\x04]\xf3z\xc3A\u007f\x06\xca Ś\xdc\x1e\x1f'm\x0f%\x8a\x04\xb9\x86\tG\xc2?\xcdܿ\x9e\xb2\xbf#\u007fx\xff\xa4\xe3\\SZ\x9e\xb8a|x\x92x\x9e m\xcaQq\xb9#A\xee@~\xca\f\xb6\x1d\xb9s\xce\xed\xae\xa3\xe9\xe3\x9d`4\xfe\x85\u0381r\xdc\xf9\xd6cٳ\"r\x87\xd2\xc39\x18#\rMF\xec|Ez\x020Q`\xec0\xf8\xd1֔\xe8\xbf\xd1\xf4\x006\x13\x02\x96h\x80~\xb8\x9a\xbbKp'\x99\xd76\x83\xe9u\xaf?Bl^\x9dDnr\x96\x8a\xdb^P\xd3H\xc9,\\!\x19\x8d\xef/\xdb2\xaaR\xbb\xed\xfck\xf7\x87\xe2\x8f\xff\x99אr]\xbc\x96\xc0\x96\xf3\xa1\xf8\x96\xa2\x1dq\xe5\xfb\x89\xb2|1\xaf\xe7\x8a\xe7ؼ\x91ÌI\xa01\x8f\xe3\xa5\xc4q\xba\xbc\xf8\xf4\x80\xc9W\x94̟\xcd\x1b\x90t\x06Tɼ\tG$\xca\xfc\x8d\xce'\x93\xcfw)\xa6\x0f\xf5\xfe\xb7F5\xe8/h\x8725\xff0\xc2d\xfeI\xad\x87^\xfb\xf6\xf7iF~\x97\xbe\xa2\xea\xc4\xff\x06\x00\x00\xff\xff\xf40\xec\xfc\xd6\n\x00\x00", + local: "data/en/countries", + size: 2774, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1xWTZbbOA7e8xTaTfJe+hCx6992xVNyVb/ODpIQCTFFOhRpR97PyeZi/YGSXfWyIUCA +IvHzAdDXH21HToZIzvz/f5ZcY77aChICbTko7UFqckVJvcfWNT4Epa23mSSxmYkU6oiTykqbqMBtxYJC +lRrIQssQO+V6zveHVGEdanaDeFc8DtPzaYiBrB5QTumZQ0XyEyYuqKOeBqWBRPeutdTw0Bl9iBoPHVsK +KdNWUq9Uzgzi9AMOvZqz6JK6vPBWjnhi4QeYlA1+4HDm1h/V1IWPw4kyk44cLyYuAp3FgkiUoSveJLRy +sX+4ih9dI4jat5qx7jhA7MMIdXIsxY3aOJAlGJhsS+roIoU9ni3uaPC6SbjBLKmvPG5ShoP3DoyjRvcH +Lt44NAx27OndgiUijRAWX39MiXvhQ6qs1GbZUYNFLOsKv5ZdQO4R0YtrS1/7ofi0YgTNtZ/fxdb3lRrh +ex8Q5KVH+r9cby78j4vohntfBwIQ/tD6/buBHoArXhQrSx+5aP7zePQSYFXw+BJShcZyPGgel2euu3cf +btj1FPbm5qdUPkUxN74Xp1ddmA8O39YJmAjmth0P0dxaYNgeJ8mvRMiHIEz3SRyTuUWCgtIhesXnbezE +H8Dckd2r3Rfzi08b3ILwDZ+hC56vft3JT8HicszuArmaQdjBfjyiQJp3W29Hx4NcBSVc6Ti8A0V4MPdU +Id33lCN/zx4wUxqQ69Hcd3rfvVTINCrP3AdmPKdkeh9cxsk9QsDWpwMr2+sSuQfywOHFgXHXFIGJ/LUQ +ADNhN+oLDwQ4mwem0OT62NQ33pG9RsM8eNekQJlpixUW85AcED2ax5qzKbkUdPWT048IjS6/sMwnBsuA +SbFRxRCIrXmMZEfzhHrX5D7RAaonDmrvkw8Ndis6077LvWvFbiSzkiAVAGRWHpn8Ujz7ELvLJofYrNIJ +DpnVGNrxnD9dE/C8pqh9YM3ofYj5mgcfO2/WUuUeCDrqCiRGtKvIaCVriV3KnXKdfjOKNIXWbKhG6LBy +k0G0QQZaGmokCKChk2QyDlllGzkizWCyOKosDB1Zew0uBGia8isx2ARk0HSrspJUP/oYoeTfUnuzkTrM +Md542/ijUkeq0eq0We7gArchy+IAvFEEG3ydj50Vbvk9pB+VZp6pFwXgMx5N5pkPZLEqWicTP/CFdn5r +WYWnYkl2joLuvjPlTD8jm4EwHsDhlWfBlJlWPejDD28vjcLk/GlVbLQ/ojNewgLFiUbzDZVgtrSf5tcW +DyRdedCYfey6X9CG63QQbqB3gBTIARNKDZvBv52sGs2W4eYWTVIOB2gGs5VYk4TrhELxTiTE1CIYW5RR +9NrOvPkvaS2+cHIYaebF9zlfL2j1SjBLUJAlJlfUwQjfLPfjLHjAxl20K4lxyPX2zEcZZuk61XI5MSFj +3mwFnvJUn5o86y+aN0ETAlUV3iumrpD9muZ5SVN4nQfri53vp3u2ENWCplFSQvUWXwMpCkrFDpwuMZPz +dqzhhaa8VBuoWDMAiA06wAGFZ0oLFO71KJg8+EsdJv59XJWIks1yFOg8tObN3PSu1k9SmNycBF3zesNB +fwbKIMWa3B4fJ20PJYoEuYYJR8I/zdy/nrK/I394/6TjXFNanrhhfHiSeJ4gbcpRcbkjQe5AfsoMth25 +c87trqPp451gNP6FzoFy3PnWY9mzInKH0sM5GCMNTUbsfEV6AjBRYOww+NHWlOi/0fQANhMClmiAfria +u0twJ5nXNoPpda8/QmxenURucpaK215Q00jJLFwhGY3vL9syqlK77fxr94fij/+Z15ByXbyWwJbzofiW +oh1x5fuJsnwxr+eK59i8kcOMSaAxj+OlxHG6vPj0gMlXlMyfzRuQdAZUybwJRyTK/I3OJ5PPdymmD/X+ +t0Y16C9ohzI1/zDCZP5JrYde+/b3aUZ+l76i6sT/BgAA///0MOz81goAAA== +`, }, "/data/en/currencies": { - local: "data/en/currencies", - size: 1800, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xfftUKv\xeb6\f\x9ds\x15\x1c\xc6\xcb\xf0\xf7%\xb1\x9d\xb8\x96۞\x97\x19,\xa1\x12k\x8at!2~\xca\xea{)\x8bJzN:\xb1\t\x10\x04..>\x9a\xffU7\xe4L\x17\xc8\xe9|Vs{\xc6?\xe9\x1d_\x18B\xcd\x02ae\x1c\t\xeeZH%\xe9\x87ߝ\t\\\xe9\"P\xe0n\xa6W\xde\xda\xe1^jv\x01\xb6\xfa\xc0\x9d\x87\x1c\xbb d\x93\x83l\x914\x90\x8b\xb21\xd6\x1aWwjA\r\xb5\xd4M&\x90\x85\x8c\xcb1\x17\xe4jK\x15w\x8d>х ˙*\xffŞmmb\xab7B\xaeL\xa2\xb4\xb1\xfa\x8c\xb8\x10\xfa0V\x1f\x99\x90\xdc\"ښd\xc8\xee\x9dԒ\x1c}\xb1\\n\xe6z\xb1\\\xcf_\xb3\xabA\xb1\x9e/'\x19\x98yL\rg\xa4\xf93\x82\xba#\xbbָ\xb3Q\xc7\xfdB?|s1SKo}{6\x99\x97\xe5\xe60\xf9\xf4\xa0_\x1f\x13\xab\xc9\xc81T\xe2)\xc0v\x1b\x1d0\xf6W\x89\x9d>\xf8\xe8*\\}p\xd9\xc0\xef5\x9e\xad)\xf5\xd6Kt\xbdZ!\x0e\xc9Eo\x05\xef\x05b\f]ٰ~\xf8\x01.\xc8\xf53\xbd\xc7u\xa7V\x1ep\x10\xc9}z\xb8\xe3Y\xc5\x00\xb7\x0f/\x1c\x1a\x16K\x884\xd3?\xa2\xb1\x15\x83\x965u\x81\xc5\xe9%\x88;\x9f\x19\xaf3a뺿\x86\fm\xdd\x05\x9f\xfa\x06 \xf0\xaf\xd6Q\xe0xc\xfe6\x93\xf9Ƹ\xe4{\x00s!R\x03\x03\x9c\x89\x18\xb1\xea\t\xfd\x1d\xf3\x0fo+\xfd\x1aa\x88\xb30\xe3\xc1J\xa8lZb\xf5\x98\x1c\xc3\xe1\xff\x00\u007f\xf4\xae\x06E\xf8\xc9\b\x1e\xa3C\xf9{\xbd\xf1b\\PO%\x0f\xef\x13oQ\xd4\xd3~\xa3\x8b+\x97\x86l\x8aqCw\xa20u\x03CW!\xb3c\xbc2P@He\xba+\f5\xd0H\xa2\x14φ\xe3?\xb9s\x9f\xe4\xee~$\xe8\xa9\x13b\xab_\xf8\xa6\x8b\x06Õ\xac\x03\xd9^\uf330z\xc6\f\xa4&\xc8P\x9f\xe9\n\xa7?٩g/\x15M\xe3\xb0e\xd7c|\xa6\xe9A\v0\x06\xb2\xf0143\xfd\xa7wj\x1bodB\xb6\xdf1\xc6ٻ\fb\x17\u007fq{\xf6Q\xea\xcc\xfb\x9e,\xf5C6\xf0W\x9b0hВ@ep\x8cb\x82A\x03\x8e\xc9\xef\xf9\x97)\xfd\xd86{/\xbe\x84\xb42\x82\x11\xeeԗ2|V!\xe5\xfb\xc640\x91\x93{\xf1r\xa3>\xf7\xebk;\xd1w\xa0\xcb}\x1d\x8d\xe1\x0e\x84\aU\x9a\xee\xb1\x05\x0e,Q\xbfD~\xc7\x02(\xbcM\x1aPa\xaeW\x83\x92\x8c\xb0\x0e\x16\xe3㾼\xf1\xd6`{\xbcY\x1fz\b\x12b\x8d\n\xaf\xbb2b\x8d\xa8\xdf(\x90 |\x9f\xe2\x1f};,\xbf\x04z\xc7f\x92\x87s\xec\xeeE?\xa7\xb0\x05\xc5\xca\xe8\xb9\xd0y\xa0nx]\x18\xfbΒ\xc3\x16\xe0\x93\xae(ϔva\xfd;\x12\xa4<\xb7I\xe6\xe4\xfe\xe4\xef\xf7\xa9\x88\xd8\xc4Î=\x82\xb0Qs\xafq\xaamqM\x9b\x11ir \xd8\u007f\u05ec\x9d~@#\xcfT!F\xef\xc8]\xa6\xbe-bj\xa3\xb1\x0f\x8a\x1bW\xec\x86\nx\x81d\xc2ǽr\xb9-Ndn0ODd\xf8\xa7\x86\xcc`\x82\r\x1d\xd4\t#d*\xaatҜ\xfc\x99j\xffi\x19\xf1%\xf9\xfcl\x9c\xa2\\x\xe8sR\xe3\x97#\x11\xa7\xd7-4\xf8\x80L\r4^n\x91L\xe5ی\xf5?\x1f\x9b)\xc6\x1f\xec\xf8#b\xc2\xf4\x02\xf5}'\xe1ouz\x13YB\xba3\x1c\x1c\xb5x\xefj\xf5F\xc36\xdeްIH\xfd\x1b\x00\x00\xff\xff\xbc\xbdΙ\b\a\x00\x00", + local: "data/en/currencies", + size: 1800, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/3RVS3brNgydcxUcxsvw9yWxnbiW256XGSyhEmuKdCEyfsrqeymLSnpOOrEJEAQuLj6a +/1U35EwXyOl8VnN7xj/pHV8YQs0CYWUcCe5aSCXph9+dCVzpIlDgbqZX3trhXmp2Abb6wJ2HHLsgZJOD +bJE0kIuyMdYaV3dqQQ211E0mkIWMyzEX5GpLFXeNPtGFIMuZKv/Fnm1tYqs3Qq5MorSx+oy4EPowVh+Z +kNwi2ppkyO6d1JIcfbFcbuZ6sVzPX7OrQbGeLycZmHlMDWek+TOCuiO71rizUcf9Qj98czFTS299ezaZ +l+XmMPn0oF8fE6vJyDFU4inAdhsdMPZXiZ0++OgqXH1w2cDvNZ6tKfXWS3S9WiEOyUVvBe8FYgxd2bB+ ++AEuyPUzvcd1p1YecBDJfXq441nFALcPLxwaFkuINNM/orEVg5Y1dYHF6SWIO58ZrzNh67q/hgxt3QWf ++gYg8K/WUeB4Y/42k/nGuOR7AHMhUgMDnIkYseoJ/R3zD28r/RphiLMw48FKqGxaYvWYHMPh/wB/9K4G +RfjJCB6jQ/l7vfFiXFBPJQ/vE29R1NN+o4srl4ZsinFDd6IwdQNDVyGzY7wyUEBIZborDDXQSKIUz4bj +P7lzn+TufiToqRNiq1/4posGw5WsA9le74ywesYMpCbIUJ/pCqc/2alnLxVN47Bl12N8pulBCzAGsvAx +NDP9p3dqG29kQrbfMcbZuwxiF39xe/ZR6sz7niz1QzbwV5swaNCSQGVwjGKCQQOOye/5lyn92DZ7L76E +tDKCEe7UlzJ8ViHl+8Y0MJGTe/Fyoz7362s70Xegy30djeEOhAdVmu6xBQ4sUb9EfscCKLxNGlBhrleD +koywDhbj47688dZge7xZH3oIEmKNCq+7MmKNqN8okCB8n+IffTssvwR6x2aSh3Ps7kU/p7AFxcroudB5 +oG54XRj7zpLDFuCTrijPlHZh/TsSpDy3Sebk/uTv96mI2MTDjj2CsFFzr3GqbXFNmxFpciDYf9esnX5A +I89UIUbvyF2mvi1iaqOxD4obV+yGCniBZMLHvXK5LU5kbjBPRGT4p4bMYIINHdQJI2QqqnTSnPyZav9p +GfEl+fxsnKJceOhzUuOXIxGn1y00+IBMDTRebpFM5duM9T8fmynGH+z4I2LC9AL1fSfhb3V6E1lCujMc +HLV472r1RsM23t6wSUj9GwAA//+8vc6ZCAcAAA== +`, }, "/data/en/currency_codes": { - local: "data/en/currency_codes", - size: 519, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff$\x91Kz\x80 \f\x84\xf7s+0\xa0\xc8C\x1a\xb0E\xef\u007f\x90\x0e\xb8\x98/Bb\x92\xf9q\xb7\xe2n\x82\xddVlF`n\xc1Y\x1f\x84\xa2(\xaf`;<^\xa3\x98u\xc6\x17\x98\x94 \xbc\x9f\xff\x18m\xab\xde\xf4\x06˳=(鰖\xd1y\xd8̨\tv/\xab\xf7\xb8<\x86\xf1\xd8\x12g\x95\xe7\xd3U1*\xeftá\x11\xdb\xc3\xdc\x1b!\x91r\x19\xc2|I;\xc6&p{\x85sq\xed\xe2O\x81\x0f\x19^\xfd\xaa\x1b\xe6Ʈ\xb2j\x8f(8n\x8f\xd0\"\x86\xe8\xf2\x12fT\xeaG\x10\\EH\r\xa1'\x9c\xf9\xf3{^\x82\xe8\x1a\xa2\xfe!\xfe\t\x12y$\xf6ȏ\"\xb3.sf\x1e\x05\xd9|3&\x9brE\\YQ\xa3҃\xa0\xba\x82zL?\x1d5\xf1\xbb;\xfc\x90\x9d^\x85J\xd0ۢ\xf1<̎\xb6\v\x1a=\xb6\xd0\x17\xdf9\u05f5\xba\xf6M\xecׄ5\xf4:\xf9w\xee\xd3\x0f\x8b\xde\x19\v\xa5\x0f\x8c\xfb\xdel\xbeï\xb3\x94\xc7/so\xfe\xf8L\u038b7\xd9.v\xf3Ntq\x9a\xf3W\xe4\x9eso\xe6\xfe\x03\x00\x00\xff\xff\xf7O\x92\xa7\a\x02\x00\x00", + local: "data/en/currency_codes", + size: 519, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/ySRS3qAIAyE93MrMKDIQxqwRe9/kA64mC9CYpL5cbfiboLdVmxGYG7BWR+EoiivYDs8 +XqOYdcYXmJQgvJ//GG2r3vQGy7M9KOmwltF52MyoCXYvq/e4PIbx2BJnlefTVTEq73TDoRHbw9wbIZFy +GcJ8STvGJnB7hXNx7eJPgQ8ZXv2qG+bGrrJqjyg4bo/QIobo8hJmVOpHEFxFSA2hJ5z583tegugaov4h +/gkSeST2yI8isy5zZh4F2XwzJptyRVxZUaPSg6C6gnpMPx018bs7/JCdXoVK0Nui8TzMjrYLGj220Bff +Ode1uvZN7NeENfQ6+Xfu0w+L3hkLpQ+M+95svsOvs5THL3Nv/vhMzos32S528050cZrzV+Sec2/m/gMA +AP//90+SpwcCAAA= +`, }, "/data/en/domain_zones": { - local: "data/en/domain_zones", - size: 753, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\f\xcbA\xb6\xa5 \f\x00\xd1y\xed2 F\x84 \x8f\x80\xb6\xae\xbe\xff\xf4\x9e*\x89Ȇ$dG\x14\xc9HE\fiȅ\xfc\x90\x8182\x91\x85<\xc8?\xe4#\b!\x106B\"\xec\x04%\x1c\x84L8\t\x95`\x84F\xb8\b\x83\xe0\x84I\xb8\t\x0f\xe1%|D!F\xe2F܉J<\x88\x99X\x88\x95h\xc4F\xbc\x88\x83\xb8\x887\xf1\x1f\xf1%~l\x89\xedd+l\xc6v\xb1}\xa4HJ$%\x1d\xa4Ar\xd2$-\xf6\xcc~\xb2\x17vc\xbf\xd8\a*h@74\xa1;\xaa\xe8\x81f\xb4\xa2\x866\xb4\xa3?\xf4\xaftt\xa2\v}З\xa3p\x18G\xe3\x18\x1c\x93c\x917r\"W\xb2\x91\x1b\xf9\"\xffȃ\xec\xe4ə8\x8d\xf3\xe2\xec\x94DQ\xcaA\xc9\x14\xa34\xca\x1f\x0e\xcaCy)\x1fU\xa8\x81\x1a\xa9\x99Z\xa8\x83\xea\xd4I]ԛ\xfab\x82El\xc3\x12\xa6\u0601\x15\xacb\x865\xec\xc2:\xf6\xc3\x06\xe6\xd8\xc4\x16vc\x0f\xf6\x0f\xfb\xdb?\x9a\xd0\"-\xd1v\x9a\xd22\xad\xd2.Z\xa7\rڢ}\\F\x17z\xa2\xeft\xa5\x1f\xf4B\xaf\xf4?o\xf4Aw\xfa\xa4?\xf4\x97\x9f0\x12\xe3b8c1\x1e\\\xf0\x80G|\xc3\x13\xae\xf8\x81g\xfc\xc4\v^q\xc3\x1b~\xe1\x03\x9f\xf8\xc2o\xfc\xc5?fdn̝\xa9̃y2\v\xb32\x8d٘\x17\xb33\as2o\xe6\xc3\xfcX\xc2RVa\x19\xcbY/\xeb\xe3\x16\xeeȝ\xb8\x95;s7\xeeų\xf38o❼\x8bO\xf8\x8c\xef\xe1\u007f\x00\x00\x00\xff\xff\x88\xcdet\xf1\x02\x00\x00", + local: "data/en/domain_zones", + size: 753, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wzLQbalIAwA0XntMiBGhCCPgLauvv/0niqJyIYkZEcUyUhFDGnIhfyQgTgykYU8yD/k +IwghEDZCIuwEJRyETDgJlWCERrgIg+CESbgJD+ElfEQhRuJG3IlKPIiZWIiVaMRGvIiDuIg38R/xJX5s +ie1kK2zGdrF9pEhKJCUdpEFy0iQt9sx+shd2Y7/YBypoQDc0oTuq6IFmtKKGNrSjP/SvdHSiC33Ql6Nw +GEfjGByTY5E3ciJXspEb+SL/yIPs5MmZOI3z4uyURFHKQckUozTKHw7KQ3kpH1WogRqpmVqog+rUSV3U +m/pigkVswxKm2IEVrGKGNezCOvbDBubYxBZ2Yw/2D/vbP5rQIi3RdprSMq3SLlqnDdqifVxGF3qi73Sl +H/RCr/Q/b/RBd/qkP/SXnzAS42I4YzEeXPCAR3zDE674gWf8xAteccMbfuEDn/jCb/zFP2ZkbsydqcyD +eTILszKN2ZgXszMHczJv5sP8WMJSVmEZy1kv6+MW7siduJU7czfuxbPzOG/inbyLT/iM7+F/AAAA//+I +zWV08QIAAA== +`, }, "/data/en/female_first_names": { - local: "data/en/female_first_names", - size: 686, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xb7Y\xe8\xa2\x18\xa1ST\xd4\xfd\x16\x81y\x97}\x9c\x9ebR<\x0e\xac\xa4\xaf1{\xaco\x9f\xe24\xbd\xb0s\x89\xb5\x88X\xe2b\xb2\xec\x82\x0f\x92>\xa3{*\xc1\xed\xf7ۢ\x88\xf0\x91\xcb.\xc6Y\xae\b\xb1\xd1M\xe7\x1c\x9dri\xffU\x1f\xae\x1b=\xc3A\xdd\xc9\xe7\xbfl\x93\x02\xff\xe4\x15q}Cr\x871\x1a\xa0\x89\x1e\xecg\xd9\xfd\xba\xb4\x13n(\xc7\"\xc3\xe7\x907\x87\xfa\xb1ܴ\x03\xe7\xdf\x1b\x8e\x80\xf2\xc7\x1eb\x87s\xeb\xe1\x1dg\xd8&\xfc$\x19\x86\x9f.\xe7\x1eZĽ\xe8\x96m\xc5\x17o8\x84\a\xb6\xef\x02hP\xb4a\xf6m\x057LN\x9a\xfe\x06\x00\x00\xff\xff\xff\u0091\b\xae\x02\x00\x00", + local: "data/en/female_first_names", + size: 686, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zxSXa+bMAx9978q7d3uKLeqSrU9G/AaSyHZnHCl7NfvGKa9mdjH58N8sDW6czWdlWnQ +tDB1bBMb01vUPzxJDdRLSvpTjDCOsXErnLx+sUmlS7ZcQwO6MN04zY2uaCTqpNZG7xJRj5wW7LzklJjO +bDnSY8PqMaDGMp2DxCg08IaxEfyBrrpOYrHRRabsD72UojPaQS1Ko3NLNUDQKb0kMn1I1AINHcjh47Q2 +dED3kElmwL6rvTRh/so1RIGqO687kK0GdhpzGDt6rPIrcFI51LZE52BaqibZYxDqOcH9GbvE/PWLwbsU +56Q+t1noohihU1TU/RaBeZd9nJ5iUjwOrKSvMXusb5/iNL2wc4m1iFjiYrLsgg+SPqN7KsHt99uiiPCR +yy7GWa4IsdFN5xydcmn/VR+uGz3DQd3J579skwL/5BVxfUNyhzEaoIke7GfZ/bq0E24oxyLD55A3h/qx +3LQD598bjoDyxx5ih3Pr4R1n2Cb8JBmGny7nHlrEveiWbcUXbziEB7bvAmhQtGH2bQU3TE6a/gYAAP// +/8KRCK4CAAA= +`, }, "/data/en/female_last_names": { - local: "data/en/female_last_names", - size: 1764, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffDU\xddr\xe2:\x13\xbc\xd7[\x05\xb2@%\x90P\x86\xfa\xa8\xefr\xb0'X\x85-qF\x12\x8ey\xfa\xd3-\xb297\x9b\xb5\xfe\xa6\xa7\xbb\xa79\x8c>\xf7\xee-\xf6!\xc5\xe0N~\x18\xbc\x8c\t\vA\x93[X\x9c\x82{\x95\xbbOn\x87-5\x9e\xe0\xc1]\x8c\xa6\xee(\xf3\x10ͽ\x84N\x8d\xab\xc7>\x8e\x82\xcb\xd2^\xebk\xbd\xcf\xea6b\xc6\xfbb\xd9?\x8fܸ\xb9\x16k\xbd\xfc,\xeb\xc35\xf1\xec+\x86\xe5 v\xc5gg\xfeR\xb0\xb1\xd5\t\u05f7\xaa\xee$\xc3\x15\x1062\f\xee\x05h\x82\xfb\u007f,\xe1\xe26jA\x80\xe1\xe1\xde=>O\xb8\xd8g\xb7\x8d7\xacl\x00\xdb\x1dژ\xb3[\x9b\xe2\xcaK\xc7\xfe\x16\u0097\xd61d\xc5Bv\a\tx\xf4\x01\xe6*\x1dM\xbc\x803רv8\x1a\xaf\\\xbfHp\v>\xb8+v\xebg\x80\xf4\x83ή\xf1w5\xe1\xa9\x1b\xaa4\xbe\xedY\x80p\xe3\xb7\xdbD\x96\x035\xf8爧\xa1\xda^\xf3S\x8e\xb5\tn\xcb\xe8\xd9ś\x8c\xd8;I\xe6\x0e\x84\x8d\xd7\xe4\xdeQl&2\xea\xe7\xf6\xe6[\x05\x80\x10\x14l\x9db\xec\x80\xc0\xe8\x83&\xa6\x04\x96\xffʌ\xd6t\x04\xd67\rW\xb6\b\x9alv\xfb8\x11\xfb6B\x82\xbd\xe4\x1f\f\x9br\xe9\xf1\xc2\n>\xa9\xe5S\x0f\x892!\x94L?\x1d\xfc8F\xbc\xb1\x8a)\xff\xa7\b\xad7KȐY\xbf+<ה\x94\xf8\xfe\xda\xfc\xd7\x17\x8c\xf4\xea\x05\xeaʌ\xb3\xbb\x99\xf0W\x11\x14l\xd0퐟\xbd\xf72\xbaC\x81\nЅ\xde\x19\x04\xed\xb1\xad*\x0e\xfe\xab)\xc3\xe8\xd6a\xfbs\xd2@5\xe6\x10\a\xec\xaf|\xea\xa9(.\xa7\x1f\x03\xf3M\u007f\xae\xdeo\xbb\x18d\x80nV\x1e4p\xea\xe9\xc8O\x18\xf9\x81\x06F\x8a\\\x8cܯ\xe08\x12u\x02p4\xaf\xe73\xfb\xad\xf6\x87-\xee,y,-\xbd\xb3\x8f\xd5y\x9b\x12\xea\x1f\x8f\x01\xc2\xf32}զ4\x80\xdfE\x9c;T{N\x9fU\x92ީU7S}SR\xf2\x8dM\b\x1ek+d\x11\x96M\xc0d\x1dK\xf62\xc1/\x03}\xd0P\xea\x1fcW\x95\xc0\xf5\x02\x04]1\xed\xc1c\x1a !\x0eZ\x1d\xfb\xe4>`\xba\x88\xbf`\x15\a\xdfC\x1d\xb0\x95ڥ\xf06\xec\xa1h\b\x91\x01\xae\xa6j\x89\xd7\x12\x02}Q?6\xa5\xda\xf5p\xd3\xd0Rcx\x95\x83\x04\nn=9\xd8ˌ\xab{\xafV\xfdG3\xed`\xa0^\xa7\xe4^\x8c\x8a\xa0\xc3Kx\xa6\x0f\x15i\x84=\xe7\xfa\xf8\xe7\xdf\xc95\f\x1c\xeb\xb6 \xfc\x10\xe6\xae&\x05\x06o\t(\xf0\x1cݰ0\xe98Q[A=\xa4\x96\xb1BS<\x8dd\x1c\xae\x15&\xaa\xa9C\xf7bc\xcaF//\xb9Ue9\xa9܉\x9f9\xa2xd26T]\xc2|Y\xf6\xd8~Pa\xc0.\x89i\xf7\x1c\xc5:gJ;H\xb8\"\x14x\x95\xa0W \x1af[\x97\x8c\xd6k\xd2\xcc\xc4\xde\xf6\xa3\xefrm\xc9\xfdO\xd2?\f\xc1\xa5\xe0\xbda\x88\xc8TU\xce\r\x8a\xddh\xadρ\xe9\x00G\x84|\x81\xf5l\xfe\r\x88\xdf0G\xa5\x9a\xefu\xea\x80\x00\x03\x03s\x98[\xc0\xe4\xf1\x06;\xb7qf\x8eh\x8dջ\xd8oJ\xd1\x19\xc84Xk\xf5\x1b\xb1P\xef!\xe4\xebN\"}\xc6\x14\xd3f\xb9zZ\x02\xfb\xfc\xb8\x94\x19w֊HS\xfe\x1a\xc43\r\xe9;\xe4\xf3\xe8V\xa5\xfe\x90lg\xe4\xa1{U\xe1\\\r4\"\x9f6FO\xc3F\"\xa7\x06'\xb6Rs\x04\xdc=\xf2\xdbE\xefB\xffa\x03֮>[\xa5\xb5\xe8\x1f\x9e\xe1\xb2\xf6\x82okP\x8fhi5ba\x87^ȇ\xcb\b\x92\xaa\xf8\n\xbf\xfa[8\x1d\xad\x80\x10\xb82WZ\x81\t\x99\xa1\xadt\xb0\xbe\x88]\x99\x04\x92\x06f\xb8\xaa,\x8b\xa4Dk\xbb\xdd*\xfd\x1f\xefټ-\xb5\xe5߹ʒ\xe9\x14Z\xda']m\x1c\xe1\x8by\xda8\xc7\t\xd8`\xbd\x04~+m\x12\xff2\\\x04gM\x01A\u007f3\xfd\xe5aջV\xe4\x10\xe7\x16J\xb3i4\xfa\x1b\x00\x00\xff\xffa\x8c\xf8f\x9a\x02\x00\x00", + local: "data/en/female_patronymics", + size: 666, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zSSzY4qOwyE934r/gbUw1whQHfWhvZ0ckjbyJ2A8vanktHZIJF2VeorZ+BZFhosKJ3t +Jp7pK94DS6LvmFLkmbb8iiOd26mPtMFv6opFnoGuwWZecOpxyfYM4pjXCPmJS6Iv9gdtTTmNtBfzSehT +VCUHumR5idJufDfbtUduCfrkSnMwrRh9RaWBF1M45RzkTXv2Stc4Ww61h6AjO44G+flxqfThrA+63C1n +2nm8t3sQS2E6OvRnrrMp0rhM5t0iFIa8mWyRLS70zSkD5MQZBg86Sft3YDdk21qZEogPohBsUAatPIfi +dK6dYMLsYEJD4ZYd+lXqvQ6Ay6EdliWD69qv3Is35E+JrROey7/mBVETGj7y20XvQv9hA9auPlultegf +nuGy9oJva1CPaGk1YmGHXsiHywiSqvgKv/pbOB2tgBC4MldagQmZoa10sL6IXZkEkgZmuKosi6REa7vd +Kv0f79m8LbXl37nKkukUWtonXW0c4Yt52jjHCdhgvQR+K20S/zJcBGdNAUF/M/3lYdW7VuQQ5xZKs2k0 ++hsAAP//YYz4ZpoCAAA= +`, }, "/data/en/genders": { - local: "data/en/genders", - size: 11, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xf2M\xccI\xe5rK\xcd\x05R\x80\x00\x00\x00\xff\xff\x92'H2\v\x00\x00\x00", + local: "data/en/genders", + size: 11, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA//JNzEnlckvNBVKAAAAA//+SJ0gyCwAAAA== +`, }, "/data/en/industries": { - local: "data/en/industries", - size: 4922, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xfftX\xcdV\xe3<\x12\xdd\xfb)\xbcb՜\xef\x19 \x01\x9a9\t\xe4\xc4\x19X+v\xc5\xd1`[\x1eY\x0e\x9dy\xfa\xb9%Y?\x0e\xeeM7\xae\x92JUW\xf5s\x95G1\xc82\xdf\nCZ\x8af\xc8\x1ej-˱1\xa3\x16M\xbe:S+K+n\xc6Vvc\x9b\x05Q~\x8f]\xffQ:_\xcb\v\xe9A\x9e$U\xd9J\xf5=\xe9\xecE5U\xf6\xdaU\xd4\x13\xfe\xe9L\xfe.\x9b\xfc.\u007f\x11\x03K\xc7\xc1\xf0Y\xf9\x96\f۹˷\xb2#ͧ8\x83\xaf\x9d\xa1Zã*\xd9\xf7\xa6\xba\x96\xd77\xec\xad[\xcf\xffˮ\xce¢|\xad%\x16t5>\x9f\xfe\xf4\x8d\x82\x11\xa9\xbad\xc1\xd3\u007fGٷ\xec\xd1]^\x90\xbeȒ\x86D\xbd\x93=a\xffL\xb6\xa7\x93=\x86\xfd\x14\xfa\x8b\f\x1fY\xc8\x06AgEO%\"1\xd7\x04\xa9\xc2\x10\xf1\xdeW\x8d\x93\x8bkg\xce\xd8R\x0e\x80\xa6\xab\x1b\xd5\x12\a\xb6\xf05\x8c\xf8\xc8_\x94\xaa\x00v\xdf7Rt\xec\xdb\xc3h\x14\xce\xedƓ(q'\x00\xda\xe3\xeeT;\xa1͐=\x12\xbc\x115\xb1\xf2Q\xd37\x96\xcdd\x85:\x19\x06\xa7\xfb\x9a\xcb?\x19HI|\ak9\x18\x80gw\x8e\x03c\x90\xa0\x95\xadd-4\x19\xebkC\xc2\xe2\xb1Ӫ\x1aKc\xbd?Q\xc9H\xf3\ued50\xfa\x1a\x95O\rT\x80\x02\xd7\x16\xcd=\v\xdd\xc6%\xcf\bz1\x9b~\x03\xa0\xfcyԝ\x1c\xce8\x91\xdd|\x96\u007f\x18\x86\x01\xbaq\xa0o8\xc5҇\x12X\r\x8aCɶ$L\xb4\xfd~:\xe1\x8e\xf3bdH\xa1݉\xf2K\xd4\xee:\xe1\xb7\x11\xd2:\xbd\x13H[\x88\xdc\xffa\xf7\x0e:\xd5!Ӣ䬌Br\xf6\xe74 Φp\x82V\xec\f\x92\x97\xcd\xf1i\xf8\xd3\xdd\xeb\x9eJM6%aҊ~\xe5\xef\xc8\x0f=\xd7|\x10\x8c70\xb5\x1f\x8fG\xe7V#\x06\x9bDE\xaf4'\xe0d\xf0@\u007fpi\x04\xf0\x902\xc0\x02\x15\xdb(\xc3X-\xa8\x00\xb3\xf9&\xa1o\xf0:\xa8\xa3(K\x15B\xf4.\x1d\xd4u\xb0%\xd0\xf2\"=\x96_\xfciu\xd1\xc3g\xd9!OQ\x02\x19L\xca\xcaA\xf1\x9bP\x12g\x94\xf1\x80&\x82,\xce\x1e\x00\x87\xe1,\x06\x16.\x9d\x1a\x05\x80\ue7fa\n\xd7\xdb\xf1\xe5\xaf\xe9\xb8$f\x84\xcduA\xf1\xac4ɺ\xcbV\x9a*ib-'\xe9\x03\a.4\x18>\x90s̮ϷHRT+d\b\xe3QpAx՞j\x87\xbf\x13\a\xf7QQꋓ$ڛD\b\a\xae\xbcM\xf7\xf67\xbd\xb7\x9bm\xe4\x89\x12T\x16\\\xd9\xe2vk\xde\x15Mq>!'\xd1b\x90\xb0b\x18m\xb7\x89F\x826Aw\xff\xf4z`H\x93J\x9aD\xeefJ\xa4C\xfe,J\xd9H\xc3\x19\xe0\x95\xcaP\xf3ϖ\xff\xf5\xa2ج\xbd\xc4Փ\xff\xda\xd3`/=Y\xb0G\x93\x96\xf8\xc2I\xf9\xd3`\xd0\xdep\xb7\x17j\x94\xab\xfc\x002\xea]V\xf7\x0f\xa6\x11\xd8^N\xf1ϵ߀\xe0\xa7\xe2\r\x18\x9dI,\xa9Pn\bw\xc1X\xa1ƿ\xed\xb1\xaa\xe4\xa4B\\\xa6V\xb3Q\xa2\xc37\xba\x8d\x05\xff M\x93^_\xc42{\x94\x00\xad\x9a\x88!\x18z\xc9\xc37\xdb`\x0e\xdd\x1f\b\xedxu\x93\x15[\x14\x16\x06Z\x1e\x87\x11O\xd5\xd0½\x1a\x80\x18=\xda\"K\xbb\xa0Wođ\xa7\xb0\x9a\xa6\f\x12\x06\x1d\xa8<\a\xfdN#J\xe9g\xc74O\xe5\xff\x10\xdf\xe4o\xa8\xec\x848LS\x924\xc2\x10%\xfd\xb3\xa6\x13u\x03-ΐ\x9f\xab\xa8,\x17\x8cK\xc1>l\n \xa7.\xae-\xf9\x9a\x9a\x19\xc9^\x98t\xe9\x10\xc4\rq\x9c\x89_\xdb^\xab\v\xa5`,\x16Xt\xe2_ \xd4M4\xbeQUmk\xc5\xf6\x1a$\x9d{1\xc4썐\x84\aC\"\x9a\x1a\xdf\xd2A[u\x91\x94\xd4\xef\xaf\xfc\x80\xa9ŷ\x9bmGN\xc0\xbb\xfc\x03զ\xbc'\x81\x9e\x06\xeb\xbb\xf1\xd8L1\xe3%\xa0\xd4\u05cd荾\xd1\f{KyS9,IU\xb9\a\xcc\x1eI\xc6\xf9\x9b\x8c\xc9\x10\xe4\x1e\x0e\v~\xddl0Mgq\xf9\xce>\x93(m\xdb\xec\x8a\xd7*+1\x82\xc7'ZVA娥\x9d\xac\bظ\xf7C\xdc\\\xa0:{\xfb\xd2\nO\xac'[94$\"G6|\xad\ar\x9c\xa4˜0{\xe0\n#\xc0c\xec#\xe0}4\x83\x1au9\v\xe6\xc0\xd3\xdc^S\x14)v\xf5\xb7:\x1eC\"XR\xcc>\x86\x1b\f\xdc9\xb2\x01;>\xa7\xaa\xe1gط%\f\xa1\xe0'\xc9l\x16\xa9\xb6\x1d;\xbf'y\x83M\xa5\x0e\xa2¯\x8b\xd0\x1d\xbc\x98\xef\xb0?\xbb\x87\xf4\x1a-ú\xc9d\x12\xfc\xeb\a7\x9e\x1f\xb2H\x9f\x83a\u007fR\xaaL*;aB\xe8\xe9'\xa5\xdb\x1b\xa3\xa9\xf0.v\xf0E}D.\xd5Ë\x0e/\x88t!\x92\xe6\x82ZЉzڰ\xa8Z\xc0\x99\xa9\x8f}\xf6Z\x92\x0f\xfa\x83䲕\xd6\x18٢J\x05\xbf~\xdcK/^T\xf6F\xe6[\xe9/\xff\x82LQ\xf48\x87\xb2\f\xcd\x194]vL\xdaVR\x97xѠ4\x85\xae\xc2[\xd1\xe6\x9e\x03ٕ\x83#v\x05\xa6\x1e&\xeb\xc9\x16~LɄq\xc5*Z\n\xb0\xe0\x9f$T\xc7\xc6Ш\xf8\x97\x01Tu\xbeA\xe6\xfdP%?\xb9L.\xfeܞ\x90\xb3\x1b]\xcaJ\"\xfb\x99\xad\x015\xa3Vi\xfe\xa1\x84\xc7n\x8c\xe6n\x8a<\"| \xe4\x96jC\x1c\x80OBh\xaf\x1c;hmZ\xa9\xb8ӦJ\xd8\xf1\v\x84w\xf2\x06+\xf2\x06\xb3\x01\v\xcaq\x82\xd9\x1f\xff\xbd\xfe\x9fl\x1c\xcd\xe5Y\xaa\x9e=Y+miq\x9e\x9b{\xf5\xd4NR\xa1\xc1\x84\xaf콶\xd6K\xd7I\x01\x98\x94\xe2\xa3\xee\xd9A\x1a\xe1\xa5c\xcf`e\xaf\xd8\xc4\x15\xef\xa3\xf5n\x1d\xab\x8d\xee\r\x9f&\x82\xd6Ͼ$\xa7\x8c@+9\xabG\xae\xd4\x06\xc7\xf0\x0e\xac\xd5\v\xa6\x85\xe4\x0eJ\xcc;=aVZ\xb1f\x06\xb4\x8e\x18\x16\x92\xfeKjK\xa4X'\x11W\x11\xf4m\x0f\xeeϒ\x90\x98f4[\xa9\xf0ˬA\b&\x8b5\xdd`\xd4\xf3\x84\xfc&\xcf\xea0\xc0$\x05\x1f\xd9Q\xf5\xe8\x8d\xd9\x1e\x06\t]\xaa?\xa3\xf2&K\xa7\x119\xa4\xb0\x9chu\xd0\xd3\xe4\x95twv\xf1\xce\x00\x17\xc3\xce:\x83\xb2\xa1\xbc\xf5v\x04\xbd\x03\xb3\xa6\xb8)\xe0\x805\xb3\xdc\xfe\xea\x99;\xbe\x11\x12\x01\x1f\xdcb\x8bsO\xb5\t\xc1Ϥ\xa2\x91\x9d\xef\xbd\x042U\xfb\x8a\xf0\xfc\xe9\xf4\xcc\x1a?\xcf\xda8v\x051\xa8\x85\xdd*\x12\x05\xe9SҀ\xa0\x0f\xeb\x8e5|\x04[\x1d[I\xf7\x1fG\xc4͖\xbe\xf4'\x84\x1e\xd5M\x1a\xad\xa6\x90LA\xc7\xd6@wW\xeb8\xb0\x06\x84\x01GR\xfe\x86\x95*\x8a\xc1\x12o\x92DR \x91\xc4oZ\xb7l\xe9#\x1eNߛT\t\xb9\x181H\x87IV'@%\"\x92\xb4z\x02\x8drߦ\x1e\xb1D\xff\xc9\xf0y\x90\"J\x01\xedg\xe0\xa3\x1b\xb0\x03\xd4\xda\xc5\xe5\f\xe3L\xf6OvA\xb6\x96\x9ed\xa8 \xf4\xecq\x90p\xba\xad\xf6F\x80ݏ\xe4ޜ\x92\xfc\xae:m\xd2DD\x85d\x1b\xeaFQ\x8d>4\xe3o\xd4\x1e\xf6(/\x95\x1fГ9]U\xfd\x90\x1f\x86\x1bJ煛O\xd8n\x90\x02K7\xbc`\xfe<\xaa<^\xbeR\x15\x06\xda3\xb4\xd2[s\xec\"\x15\x86\xff\xeea\x92۟\u07ba\xe5o9\x1b\xf5\xc0\x91:A\x9f\xac\x87\xbb]\xca\b\xb7܋\xaaq\xf9\xb4^\xb8\x9cn\xdeFyՅ\x14\x8a\xf3fJ\x11\xff\x89\n[i\xfbǣ\xc2q\t\x1c\xb4rFoD\x9fL\xebmo(tܶ\xf9_\xc9\xff\x1b\x90\x16\xc1@\xcb\x02\x89(\x10$\x18\xb5\xb7#\xa7\xc4\xc3R\xcdP\x88lx\axoVd\b\\\x86\xb9\x88\n\xe7\xed#T5\xb0\xe8j\xbf\x8c\"\xbc\xae\x8a\x04\xc4\xd5\x10O\x8f\xd3\x1a\r\x0fTD\xfc!%\xbdD\xbfkT':\xe9\xce\xfd\xe2\x06\x88\\\xebǐH¶\x9bg\x85\xaf`\xdd\xde6\x032\xc1j\xee\x868\xf1U\xe3xױ\xfd[\x1b\xd0F\xe0\nu\xd1k\xf7\x065Π~\xbcY+\x94Ŕ\x14ƌ\xa5M\xff\xb8\xb2\xaf\xfc\xabd\xf8JO\bF\xe4u\xf6n\x16\xad\xfc[\xb3\xfc\xe6\xd1i\x9d]:$I\a\x19\xd1\\\x10\xbaS%Aa\x95\xbf\xc3Ǻ\xe1B\x1a\x01ټ\x00\xbf\x03\x00\x00\xff\xff\xb11\x04X\xc6\b\x00\x00", + local: "data/en/jobs", + size: 2246, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2RVXXLjNgx+1yk40wP0DKnjtbezidXI0zwzFCRxI5Ea/njj6fTuC4ikSMkvHvMDIAIf +PoBPQmivHDtobVqpuNOmStjxC4R38gYr8gazAQvKcYLZH/+9/p9sHM3lWaqePVkrbWlxnpt79dROUqHB +hK/svbbWS9dJAZiU4qPu2UEa4aVjz2Blr9jEFe+j9W4dq43uDZ8mgtbPviSnjEArOatHrtQGx/AOrNUL +poXkDkrMOz1hVlqxZga0jhgWkv5LakukWCcRVxH0bQ/uz5KQmGY0W6nwy6xBCCaLNd1g1POE/CbP6jDA +JAUf2VH16I3ZHgYJXao/o/ImS6cROaSwnGh10NPklXR3dvHOABfDzjqDsqG89XYEvQOzprgp4IA1s9z+ +6pk7vhESAR/cYotzT7UJwc+kopGd770EMlX7ivD86fTMGj/P2jh2BTGohd0qEgXpU9KAoA/rjjV8BFsd +W0n3H0fEzZa+9CeEHtVNGq2mkExBx9ZAd1frOLAGhAFHUv6GlSqKwRJvkkRSIJHEb1q3bOkjHk7fm1QJ +uRgxSIdJVidAJSKStHoCjXLfph6xRP/J8HmQIkoB7WfgoxuwA9TaxeUM40z2T3ZBtpaeZKgg9OxxkHC6 +rfZGgN2P5N6ckvyuOm3SRESFZBvqRlGNPjTjb9Qe9igvlR/QkzldVf2QH4YbSueFm0/YbpACSze8YP48 +qjxevlIVBjx6hiJevRiBG1brXwitnq/eWAi/OOpc0ABrYvMihJ+X2kgAA9I3UwPDPtoztNJbc+wiFYb/ +7mGS25/euuVvORv1wJE6QZ+sh7tdygi33Iuqcfm0Xricbt5GedWFFIrzZkoR/4kKW2n7x6PCcQkctHJG +b0SfTOttbyh03Lb5X8n/G5AWwUDLAokoECQYtbcjp8TDUs1QiGx4B3hvVmQIXIa5iArn7SNUNbDoar+M +IryuigTE1RBPj9MaDQ9URPwhJb1Ev2tUJzrpzv3iBohc68eQSMK2m2eFr2Dd3jYDMsFq7oY48VXjeNex +/Vsb0EbgCnXRa/cGNc6gfrxZK5TFlBTGjKVN/7iyr/yrZPhKTwhG5HX2bhat/Fuz/ObRaZ1dOiRJBxnR +XBC6UyVBYZW/w8e64UIaAdm8AL8DAAD//7ExBFjGCAAA +`, }, "/data/en/jobs_suffixes": { @@ -236,258 +550,603 @@ var data = map[string]*file{ }, "/data/en/languages": { - local: "data/en/languages", - size: 821, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff,RQv\x1a;\f\xfd\xd7*f+@\x12\xc8\x03\xf2h\u171e\xe6O0\xaa-\xb0e\x8el\x87\xc2_\x17\xd4U\xb4\v\xab\xec\xc9nj\xaeeIֽ\xd2\xec\x87\xf2\x05Q2\xcc\xc2\x11\x85Q`\x16=*\x9f`\xa6x\xec&\xd2\xe4\xcf\x19#e\x82\xd9=\xa2\"\xcc\x1e\xa4\fs\n\xa85\xb7\x809\x89\xc3`.\xce\x01#\xc2<\xe5\x9e8\xaf\xc1YŎ\xb4WX`\xc1`\xe7\x85g\xe9gMXZ\xc0\xe2A'\x0fO\xd6Hn\xc6\xea?y\xfe o\xb6\x96v\xf3H\xe2.\x1e\xe1Y\\h1Ϲ\xa4\xfe\xc8\v\x9f'\x13\xf8ʒ\fH/\xf2\xa2$\x96\xf8\x8dr\x19^\x94{\xa3KtX\x1f\xb0\xa4\xa4\xae\x9fIc3Jt\x81e5r\xf2緁\xb3\xa1°Bn\xcd\r\v\xa5\x14\bVtT\xba\xc1\x8ae\xb4;V\x1e\xb6\xa9TXU\xf9d\xf9z2M\xec\xf2\x04\xaf2&#\u061d\xf6\xb6\x1f\x96H\xa1\xf9\x8d~s\xfe\x87W\xec\x02\xacQ\x04G4\x9b}\xb4\x92\x06\x1ex\xf1\xb0\xf6\x91\x14\xd6Iɢ\xd7U\xc7Fi}Ww\u007f\xc0\x06\x93}\xe5\xa3\x15\xdap\xf1u\x1aߦ\xfe\xa4xLըY\xec\x16O4N\nmMr\x87\xf9\xde\xc1\xe7\u07fe\xd8PiMl\xff\xfeJ\xf6\xf4\xb6\xb16ŷ)\x8c\xe9\xa3%\x9a\xe6\xa9\xf7k\xa8\x90\x90S\x16x\x1b\xe9H&\xc7\x1b]\xdb\xd0\xdf\xe86\xbcS\x9b\xea8\xec\xd9ɰAq\x15\x9d\x05$-\x9eT\x86}*>\xb5㍺\xec\xff+\xdf\x11vxe\xdb+)\xc9`\xf6͐v\xc9v\xa9\x8fxg\xf9\xd5\xd5\xd6\xe1\xae\xcaٖ\x12\xbeT[\x93\x8a\xf05ʼn\xf4ހ51\xbd\xb0\xbfN\xfb\xb3\xbf\xa1\xe7潵)\xeeo\xd4\xd5;\xe0\x99/\xf6\x8f\x1c\xe0@\xc1*\x9b)5\xc2\xc1#\xc3!]\x86\x9dm\x89\xc0!\x1bm4sCA\xf8\xcec\xcf~\xaf\xa1¿\x00\x00\x00\xff\xffq\xe9\xea75\x03\x00\x00", + local: "data/en/languages", + size: 821, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/yxSUXYaOwz91ypmK0ASyAPyaOGcnuZPMKotsGWObIfCXxfUVbQLq+zJx4yuZUnWvdLs +h/IFUTLMwhGFUWAWPSqfYKZ47CbS5M8ZI2WC2T2iIswepAxzCqg1t4A5icNgLs4BI8I85Z44r8FZxY60 +V1hgwWDnhWfpZ01YWsDiQScPT9ZIbsbqP3n+IG+2lnbzSOIuHuFZXGgxz7mk/sgLnycT+MqSDEgv8qIk +lviNchlelHujS3RYH7CkpK6fSWMzSnSBZTVy8ue3gbOhwrBCbs0NC6UUCFZ0VLrBimW0O1YetqlUWFX5 +ZPl6Mk3s8gSvMiYj2J32th+WSKH5jX5z/odX7AKsUQRHNJt9tJIGHnjxsPaRFNZJyaLXVcdGaX1Xd3/A +BpN95aMV2nDxdRrfpv6keEzVqFnsFk80TgptTXKH+d7B59++2FBpTWz//kr29LaxNsW3KYzpoyWa5qn3 +a6iQkFMWeBvpSCbHG13b0N/oNrxTm+o47NnJsEFxFZ0FJC2eVIZ9Kj6144267P8r3xF2eGXbKynJYPbN +kHbJdqmPeGf51dXW4a7K2ZYSvlRbk4rwNcWJ9N6ANTG9sL9O+7O/oefmvbUp7m/U1TvgmS/2jxzgQMEq +myk1wsEjwyFdhp1ticAhG200c0NB+M5jz36vocK/AAAA//9x6eo3NQMAAA== +`, }, "/data/en/male_first_names": { - local: "data/en/male_first_names", - size: 665, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff4\x92͎*;\f\x84\xf7~+\xfe\x06\xd4\xc3\\!@wֆ\xf6trH\xdbȝ\x80\xf2\xf6\xa7\x92\xd1\xd9 \x91vU\xea+g\xe0Y\x16\x1a,(\x9d\xed&\x9e\xe9+\xde\x03K\xa2\xef\x98R䙶\xfc\x8a#\x9d۩\x8f\xb4\xc1o\xea\x8aE\x9e\x81\xae\xc1f^p\xeaq\xc9\xf6\f\xe2\x98\xd7\b\xf9\x89K\xa2/\xf6\amM9\x8d\xb4\x17\xf3I\xe8ST%\a\xbady\x89\xd2n|7۵Gn\t\xfa\xe4Js0\xad\x18}E\xa5\x81\x17S8\xe5\x1c\xe4M{\xf6J\xd78[\x0e\xb5\x87\xa0#;\x8e\x06\xf9\xf9q\xa9\xf4\xe1\xac\x0f\xba\xdc-g\xday\xbc\xb7{\x10Ka::\xf4g\xae\xb3)ҸL\xe6\xdd\"\x14\x86\xbc\x99l\x91-.\xf4\xcd)\x03\xe4\xc4\x19\x06\x0f:I\xfbw`7d\xdbZ\x99\x12\x88\x0f\xa2\x10lP\x06\xad<\x87\xe2t\xae\x9d`\xc2\xec`BC\xe1\x96\x1d\xfaU\xea\xbd\x0e\x80ˡ\x1d\x96%\x83\xebگ܋7\xe4O\x89\xad\x13\x9e˿\xe6\x05Q\x13\x1a>\xf2\xdbE\xefB\xffa\x03֮>[\xa5\xb5\xe8\x1f\x9e\xe1\xb2\xf6\x82okP\x8fhi5ba\x87^ȇ\xcb\b\x92\xaa\xf8\n\xbf\xfa[8\x1d\xad\x80\x10\xb82WZ\x81\t\x99\xa1\xadt\xb0\xbe\x88]\x99\x04\x92\x06f\xb8\xaa,\x8b\xa4Dk\xbb\xdd*\xfd\x1f\xefټ-\xb5\xe5߹ʒ\xe9\x14Z\xda']m\x1c\xe1\x8by\xda8\xc7\t\xd8`\xbd\x04~+m\x12\xff2\\\x04gM\x01A\u007f3\xfd\xe5aջV\xe4\x10\xe7\x16J\xb3i\xb4\xbf\x01\x00\x00\xff\xff\xf6\xdb\xdd\xf1\x99\x02\x00\x00", + local: "data/en/male_first_names", + size: 665, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zSSzY4qOwyE934r/gbUw1whQHfWhvZ0ckjbyJ2A8vanktHZIJF2VeorZ+BZFhosKJ3t +Jp7pK94DS6LvmFLkmbb8iiOd26mPtMFv6opFnoGuwWZecOpxyfYM4pjXCPmJS6Iv9gdtTTmNtBfzSehT +VCUHumR5idJufDfbtUduCfrkSnMwrRh9RaWBF1M45RzkTXv2Stc4Ww61h6AjO44G+flxqfThrA+63C1n +2nm8t3sQS2E6OvRnrrMp0rhM5t0iFIa8mWyRLS70zSkD5MQZBg86Sft3YDdk21qZEogPohBsUAatPIfi +dK6dYMLsYEJD4ZYd+lXqvQ6Ay6EdliWD69qv3Is35E+JrROey7/mBVETGj7y20XvQv9hA9auPlultegf +nuGy9oJva1CPaGk1YmGHXsiHywiSqvgKv/pbOB2tgBC4MldagQmZoa10sL6IXZkEkgZmuKosi6REa7vd +Kv0f79m8LbXl37nKkukUWtonXW0c4Yt52jjHCdhgvQR+K20S/zJcBGdNAUF/M/3lYdW7VuQQ5xZKs2m0 +vwEAAP//9tvd8ZkCAAA= +`, }, "/data/en/male_last_names": { - local: "data/en/male_last_names", - size: 1764, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffDU\xddr\xe2:\x13\xbc\xd7[\x05\xb2@%\x90P\x86\xfa\xa8\xefr\xb0'X\x85-qF\x12\x8ey\xfa\xd3-\xb297\x9b\xb5\xfe\xa6\xa7\xbb\xa79\x8c>\xf7\xee-\xf6!\xc5\xe0N~\x18\xbc\x8c\t\vA\x93[X\x9c\x82{\x95\xbbOn\x87-5\x9e\xe0\xc1]\x8c\xa6\xee(\xf3\x10ͽ\x84N\x8d\xab\xc7>\x8e\x82\xcb\xd2^\xebk\xbd\xcf\xea6b\xc6\xfbb\xd9?\x8fܸ\xb9\x16k\xbd\xfc,\xeb\xc35\xf1\xec+\x86\xe5 v\xc5gg\xfeR\xb0\xb1\xd5\t\u05f7\xaa\xee$\xc3\x15\x1062\f\xee\x05h\x82\xfb\u007f,\xe1\xe26jA\x80\xe1\xe1\xde=>O\xb8\xd8g\xb7\x8d7\xacl\x00\xdb\x1dژ\xb3[\x9b\xe2\xcaK\xc7\xfe\x16\u0097\xd61d\xc5Bv\a\tx\xf4\x01\xe6*\x1dM\xbc\x803רv8\x1a\xaf\\\xbfHp\v>\xb8+v\xebg\x80\xf4\x83ή\xf1w5\xe1\xa9\x1b\xaa4\xbe\xedY\x80p\xe3\xb7\xdbD\x96\x035\xf8爧\xa1\xda^\xf3S\x8e\xb5\tn\xcb\xe8\xd9ś\x8c\xd8;I\xe6\x0e\x84\x8d\xd7\xe4\xdeQl&2\xea\xe7\xf6\xe6[\x05\x80\x10\x14l\x9db\xec\x80\xc0\xe8\x83&\xa6\x04\x96\xffʌ\xd6t\x04\xd67\rW\xb6\b\x9alv\xfb8\x11\xfb6B\x82\xbd\xe4\x1f\f\x9br\xe9\xf1\xc2\n>\xa9\xe5S\x0f\x892!\x94L?\x1d\xfc8F\xbc\xb1\x8a)\xff\xa7\b\xad7KȐY\xbf+<ה\x94\xf8\xfe\xda\xfc\xd7\x17\x8c\xf4\xea\x05\xeaʌ\xb3\xbb\x99\xf0W\x11\x14l\xd0퐟\xbd\xf72\xbaC\x81\nЅ\xde\x19\x04\xed\xb1\xad*\x0e\xfe\xab)\xc3\xe8\xd6a\xfbs\xd2@5\xe6\x10\a\xec\xaf|\xea\xa9(.\xa7\x1f\x03\xf3M\u007f\xae\xdeo\xbb\x18d\x80nV\x1e4p\xea\xe9\xc8O\x18\xf9\x81\x06F\x8a\\\x8cܯ\xe08\x12u\x02p4\xaf\xe73\xfb\xad\xf6\x87-\xee,y,-\xbd\xb3\x8f\xd5y\x9b\x12\xea\x1f\x8f\x01\xc2\xf32}զ4\x80\xdfE\x9c;T{N\x9fU\x92ީU7S}SR\xf2\x8dM\b\x1ek+d\x11\x96M\xc0d\x1dK\xf62\xc1/\x03}\xd0P\xea\x1fcW\x95\xc0\xf5\x02\x04]1\xed\xc1c\x1a !\x0eZ\x1d\xfb\xe4>`\xba\x88\xbf`\x15\a\xdfC\x1d\xb0\x95ڥ\xf06\xec\xa1h\b\x91\x01\xae\xa6j\x89\xd7\x12\x02}Q?6\xa5\xda\xf5p\xd3\xd0Rcx\x95\x83\x04\nn=9\xd8ˌ\xab{\xafV\xfdG3\xed`\xa0^\xa7\xe4^\x8c\x8a\xa0\xc3Kx\xa6\x0f\x15i\x84=\xe7\xfa\xf8\xe7\xdf\xc95\f\x1c\xeb\xb6 \xfc\x10\xe6\xae&\x05\x06o\t(\xf0\x1cݰ0\xe98Q[A=\xa4\x96\xb1BS<\x8dd\x1c\xae\x15&\xaa\xa9C\xf7bc\xcaF//\xb9Ue9\xa9܉\x9f9\xa2xd26T]\xc2|Y\xf6\xd8~Pa\xc0.\x89i\xf7\x1c\xc5:gJ;H\xb8\"\x14x\x95\xa0W \x1af[\x97\x8c\xd6k\xd2\xcc\xc4\xde\xf6\xa3\xefrm\xc9\xfdO\xd2?\f\xc1\xa5\xe0\xbda\x88\xc8TU\xce\r\x8a\xddh\xadρ\xe9\x00G\x84|\x81\xf5l\xfe\r\x88\xdf0G\xa5\x9a\xefu\xea\x80\x00\x03\x03s\x98[\xc0\xe4\xf1\x06;\xb7qf\x8eh\x8dջ\xd8oJ\xd1\x19\xc84Xk\xf5\x1b\xb1P\xef!\xe4\xebN\"}\xc6\x14\xd3f\xb9zZ\x02\xfb\xfc\xb8\x94\x19w֊HS\xfe\x1a\xc43\r\xe9;\xe4\xf3\xe8V\xa5\xfe\x90lg\xe4\xa1{U\xe1\\\r4\"\x9f6FO\xc3F\"\xa7\x06'\xb6Rs\x04\xdc=\xf2\xdbE\xefB\xffa\x03֮>[\xa5\xb5\xe8\x1f\x9e\xe1\xb2\xf6\x82okP\x8fhi5ba\x87^ȇ\xcb\b\x92\xaa\xf8\n\xbf\xfa[8\x1d\xad\x80\x10\xb82WZ\x81\t\x99\xa1\xadt\xb0\xbe\x88]\x99\x04\x92\x06f\xb8\xaa,\x8b\xa4Dk\xbb\xdd*\xfd\x1f\xefټ-\xb5\xe5߹ʒ\xe9\x14Z\xda']m\x1c\xe1\x8by\xda8\xc7\t\xd8`\xbd\x04~+m\x12\xff2\\\x04gM\x01A\u007f3\xfd\xe5aջV\xe4\x10\xe7\x16J\xb3i4\xfa\x1b\x00\x00\xff\xffa\x8c\xf8f\x9a\x02\x00\x00", + local: "data/en/male_patronymics", + size: 666, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/zSSzY4qOwyE934r/gbUw1whQHfWhvZ0ckjbyJ2A8vanktHZIJF2VeorZ+BZFhosKJ3t +Jp7pK94DS6LvmFLkmbb8iiOd26mPtMFv6opFnoGuwWZecOpxyfYM4pjXCPmJS6Iv9gdtTTmNtBfzSehT +VCUHumR5idJufDfbtUduCfrkSnMwrRh9RaWBF1M45RzkTXv2Stc4Ww61h6AjO44G+flxqfThrA+63C1n +2nm8t3sQS2E6OvRnrrMp0rhM5t0iFIa8mWyRLS70zSkD5MQZBg86Sft3YDdk21qZEogPohBsUAatPIfi +dK6dYMLsYEJD4ZYd+lXqvQ6Ay6EdliWD69qv3Is35E+JrROey7/mBVETGj7y20XvQv9hA9auPlultegf +nuGy9oJva1CPaGk1YmGHXsiHywiSqvgKv/pbOB2tgBC4MldagQmZoa10sL6IXZkEkgZmuKosi6REa7vd +Kv0f79m8LbXl37nKkukUWtonXW0c4Yt52jjHCdhgvQR+K20S/zJcBGdNAUF/M/3lYdW7VuQQ5xZKs2k0 ++hsAAP//YYz4ZpoCAAA= +`, }, "/data/en/months": { - local: "data/en/months", - size: 86, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xf2J\xcc+M,\xaa\xe4rKM*\x023|\x13\x8b\x923\xb8\x1c\v\x8a2s\x80\xecJ.\xafҼT \x91S\xc9\xe5X\x9a^Z\\\xc2\x15\x9cZP\x92\x9a\x9b\x94Z\xc4\xe5\x9f\\\x92\x0f\xa2\xfd\xf2\xcb \x02.\xa9\xc9\x10\x06 \x00\x00\xff\xff\xa4\x95F\xf2V\x00\x00\x00", + local: "data/en/months", + size: 86, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA//JKzCtNLKrkcktNKgIzfBOLkjO4HAuKMnOA7Eour9K8VCCRU8nlWJpeWlzCFZxaUJKa +m5RaxOWfXJIPov3yyyACLqnJEAYgAAD//6SVRvJWAAAA +`, }, "/data/en/months_short": { - local: "data/en/months_short", - size: 48, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xf2J\xcc\xe3rKM\xe2\xf2M,\xe2r,(\x02ҕ\\^\xa5y@\x9c\xc3\xe5X\x9a\xce\x15\x9cZ\xc0\xe5\x9f\\\xc2\xe5\x97_\xc6咚\xcc\x05\b\x00\x00\xff\xff\xc5\xed\xe490\x00\x00\x00", + local: "data/en/months_short", + size: 48, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA//JKzONyS03i8k0s4nIsKALSlVxepXlAnMPlWJrOFZxawOWfXMLll1/G5ZKazAUIAAD/ +/8Xt5DkwAAAA +`, }, "/data/en/nouns": { - local: "data/en/nouns", - size: 128, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff,\x8d\xc1\n\xc2@\f\x05\xef\xf9\xabZ\xf0\"^\xb4x_ڧ\x04w\x93%I\x15\xffެx\xca@\x867G\xae\x01\xa3Y[7\xb8\xab\xd1\xf5\xe3\x81F7\xc6;\x1fg\xdd%h.\x0e\x9a\xb6҇;\xb5^\xf9\xceI\a\xe3\xed\x81\xe6@\x96\xab\xbf\x02[\xa3b\xec\xef\x93\x0e\xde\xf2\x1b\x00\x00\xff\xff\x9e\xdfr&\xd7\x01\x00\x00", + local: "data/en/states", + size: 471, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0yQb2/CQAjG3/Mp+lUWzWbn1GV/NHuJLeuRXsEcV7X79OOqyZY05cdBHnh4iHjEAcGj +9R4S/6iU2KMYGiww8rcmYYSFRk3YqoMINZmbMcOSIl4wETx6kVuEJ9LUeffKn5mhbjEo1DGyKBvU0jK6 +fq0XhPVtxJokj00/wYuObHN5gyzk/zRFlNbBDJswGuVssOEmcIfi4HuYZu9ns/KdTjyzjslBJRexLR3T +bG5LZ2xLuFQrHE4W2Pcu2TMlo2nGDV250Rm/NPWw1ZRDtcCk7gDv6RL7MnUXWGHXR3foF9wl6lTglURs +imcsJ3sL2lJV2+ziXcf/Urf0LvVBxYoROV39Jp8ZA+wpDe4B9uwXLXIH9J2lyz7mQJarvwJbo2Ls75MO +3vIbAAD//57fcibXAQAA +`, }, "/data/en/street_suffixes": { - local: "data/en/street_suffixes", - size: 132, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x1c\xc9\xc1\n\xc2@\f\x84\xe1\xfb\xbcU\xa9\a\x11\x0fE\v\x9e\xc3:H0d!\x9b\xad\xacOo\xeb\xe5\x1b\x86\u007f2\xe3\xc0\xb4\xd1;1ӓ\x81Y\xa3\xd8\xfej\x8f\xc4\x1c\xb55\xf5\x17N\xa1\x1bqV3\\\xba\x97\xd4긊\x13\x8b\xc4\xfb\xcfGƾ\xada1)<\xfc\n\x96\xaa\x9e\xb8Uy\xe2\x9eA&VF\x1c}\rQ\xc3C\xc6/\x00\x00\xff\xff\xb0\xa40\r\x84\x00\x00\x00", + local: "data/en/street_suffixes", + size: 132, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/xzJwQrCQAyE4fu8VakHEQ9FC57DOkgwZCGbraxPb+vlG4Z/MuPAtNE7MdOTgVmj2P5q +j8QctTX1F06hG3FWM1y6l9TquIoTi8T7z0fGvq1hMSk8/AqWqp64VXninkEmVkYcfQ1Rw0PGLwAA//+w +pDANhAAAAA== +`, }, "/data/en/streets": { - local: "data/en/streets", - size: 4162, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffDW\xc9b\xea:\x12\xdd\xfb+\xfc\v=\xf7\xf6\x86$p_\xe0\x86\x86\xbcd-\xec\xc2ֳ,\xd1\x1ap\xc8\xd7\xf79%\xd2oA\xd5\x11\x1ak.\xff%\xe5毾o\xfe\x16\xfb\xe6\xefyl\xfe\x81\xdf?\xf1\xfb\x17~\xff\xc6\xef\xc7I\xe2\xd0\xfc\xe8&\x89\xcd\x0f7\x84ـ\xcd\x01\xe4b\xbd4?f\x89\xb63\xfe\xff\xa0\xfd\x91\xb0i\x0e\xdc\xea{\x89)`Ώ\xc6e0of\x13'\x02{Ŕ\x897\xe0\xbd|2N\u007f\xe2vi~\xa2x!a\xf5j\xf3\x9f\xccT^\x03\x0e\xb9\xe1gXL\xf3\x9b\xd1l\f\xee9\xb85\xbf\x89\xb7\x10\x80\x9c\xff\x84ѷ\x1fP\x91\"]X\x90\x90^\f\xfd\x02\xeay1\x8c\xa4\x17\u9fd4\xa1\x06p\x163\x90\x91.\x02\xa8\xef|\x81\x03\xf4\x82c_`\x8c\x17L\xa6J\xb5V\x01%\x8a\xfdb/\x8e\xbayA\xaa\xe6U/1\\\xce\xcdִ\xcf\xd0\a\x82C\x80'\xa9\xceA\xa4.A\xa0W|\x03$Ox6\u07b65Lq[S\"i\xdaxcE|\x8b\xc5|6op\xee\x96\x01\x95\x9a\xdf=\x1b\xea\xdf/\xa3\x99\x9b߳\x19\x9bwv\xfc\xbe\xa9\x19\xa2}\xe2\xd3\xde\xc5\xc2|\xefx\x03\x89\xb6\x89\xe0\x1e\xfb\xdem\x97\x99\xc1\x01z\x1d\xf2\xa3F\xbey[[54\x17\xb4\xc8\a\xfa,z\xe3\x87QS}\xb0\xab\f\xe4i\xbc\x17\xca\x0fZ,\x19\xf0O\x8d\xbe\x0fs\xab\xea\xfb\xb8\x17\xa3\x0f\x91\v\xbf\xc0\xf4s\x16#\xa7\x14\x8d\x19\tJH\xe5\xf7\x0e\x9aX\x05'\xd0s\xfe\x17\x00\x00\xff\xffT\xdd\xfd\xb3B\x10\x00\x00", + local: "data/en/streets", + size: 4162, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0RXyWLqOhLd+yv8Cz339oYkcF/ghoa8ZC3swtazLNEacMjX9zkl0m9B1REaay7/JeXm +r75v/hb75u95bP6B3z/x+xd+/8bvx0ni0PzoJonNDzeE2YDNAeRivTQ/Zom2M/7/oP2RsGkO3Op7iSlg +zo/GZTBvZhMnAnvFlIk34DxKAvuyfuAd0VzMGHBytF/B47Y4GZ8MlsTZpmw7TsWwhNADZJt4ea7Dksvs +262Yc/NgejEFzPc4GDyebqRecibP4iq3zuGJDyaN5wAdAFgHysW3ZHtpHkSFfxDrziUlAOeGGK6YsbEb +9eYHZ7rpZKMi6uXBFWkfcHa7p8Qc/sEzwVOWuXkIp2W0GQuD9zw9LDMEeQg3HBHFV4EeojWxXUXsIe4m +aPN+IDTgK1XxCh5F6k37Di0Z4NHx3OKyHlw8hGg3Vpf5XDdFbm4/9KpCpUK6krPEsxXX37EvuVkZZ40f +FNwuKYDPp2j7QYA87biCgiVWAI0bRyA6tKEz5BeIhSetTOpgnGZ1H45YgVesYoByV6PEMAlmR+tDmMih +6ZXDYXPwuSLfw2Qrx3+wxQVdceulXRvnzDDy2NDj8oA1kB48RNMHgjKfCjbBkX03CgE8t7N8cKBe8CrF +wVXxAuTiCbEX6ICAQoaYuoDXhJyDV1vRSh02t69mSjrK7ZauAMEWR03QWBC2z82jgXFApwBLPRpEEmhc +lF1tD7oQ3mDISI47mkc5RUOaQDpowWSrf7t2x1Xgx+DIzQIVETiIjJgDRMBxW5QJ9JNqf7TtNkTJAehq +kx5lP0mDVFvQRR4RgXCExxD1CZDW4mToOxtEyWOUBcp4jFA9ZsuEueLVIR8XO4y5eTID1A/q5O7GT+ZO +HGUkUO09DQOsinBsntwAcZ6cDcSTAZk1Dp9gKPwV8YKn1I0gDMsnJBKGNPkQBe94+rzgptQ8GxurMYiq +RxNdrSwAzt1BnLtAFs0ATwdYGEvPXJ8gtQCmqXmGB4lH8nmmJ8xkFKey9tE4+caH4gkTtfx899rn4hiN +YNTjmqvXuNEmHWVZkBvWEqnrNYKnWSOf2O94XTuqhluCg6JrfgOupF2FEpNU/E6R1lCoQ95r1tF08o0E +/kvukQfBUprMfCG6jWaZAKg7pe1BPX8d7QwCY8dmXVwSpPSNQSLeqFE30CATxsZ4XQJOaSrj3/EEryG/ +6GyZQK6Ig425Cee/xHWqw40YHi3nM5INTxYIbMCQ8MnhSX965Mb6/CXNJiCQQOVCJ9iE85lxvgl80/39 +GMxavABu9/SyCbOov22QW3TjFZ61Kb0+vXwyTn/idml+onghYfVq85/MVF4DDrnhZ1hM85vRbAzuObg1 +v4m3EICc/4TRtx9QkSJdWJCQXgz9Aup5MYykF+m/lKEGcBYzkJEuAqjvfIED9IJjX2CMF0ymSrVWASWK +/WIvjrp5QarmVS8xXM7N1rTP0AeCQ4Anqc5BpC5BoFd8AyRPeDbetjVMcVtTIjxmyzDdSuyRssgDZiw8 +Zcv4HkNJKHOG/zlWCHDfU+mjIl2XM4L/2UmJzRb2QhnDZDjnNEAGvHYb6E7bwKTeawkBHjQ4tyGg5oOh +R7jiBghS+ruGtmWaeH7hJjCNt+2Nvrcz3WWsrcfODMzbMOgOdRkESRGaIw+4aQdNRMhPYHNYLJoXQLoB +WDmbLkMLkUdenFRa6yVybsdFqF2YRxBeOR3/W1TfQDfV8g7OHklr/gFQne86Vk+s67oAL+8moKFYpO2d +IGl/u/B98M7g/xPr68SdlLLMgcG7uQQ5DUIi50QWtB0LJSoMeEAaslyBjsUgIQFEvVYVvkO+hBTdONue +c2wgdrCTpWV29nx2PNZqDgNbEMwo0TubUUHh4rvQTbCK9j+7UOXGdaj6YJkBQi5sBwDKLHxA0BcHbUG+ +udY7YFRKMMQCbwk1ae6gnmZ3i/Cm5peZZTID/v2FKn5rfomjsX/J1fQGbGlXrDBYGE7w4V9IRGOl1QwK +9Z2KLkxUimpLo1AdUNHCli16DpCn2+oKv8LVkFCJKDL8fdsGsJ7zOtrQvDpGFnyC4DiiRjSvXpjXX30a +6Iyv8CESNCvN66dG9t6w50zgA2re3vgJ5f6rYevXVkdQrHVxbxaN/r0Ydfk9skm6uSs82mBwQfqtLrun +a0ZcskdpQWmL5zOgvyeGvROT4OzNHmEIEjPuVg6j7yMKp5X2QKPdB6qgPXtV9uT/KZaWOJg5CZnvSa+I +0IP0LXq00hMtfOlBkBuYTwgQfOrsLNUV6cGKWBYPVhjgBzt4HqwfDhT7AKeTs6hPHrRNaQ9Cfz3w2+OA +nov2PYTPU4GHHwpqOAlUDZbotocCF6GdDjdsO5puTErzH8IhJo7IGRkNd3GABekOGjsiLPRSAGfngWsR +OHgkUzEgOkeyEr/AQnU4APQooDWLHQVdCJR2HA1D7cgognDgcByeAqCnjeEyBbI0shM5usB/tWXFWwOe +VGn1t+PFaNd1ROFKfOEFtQc0at2oXJV7RFAOpFE955hR9ZPqCxCpE5vY+SCrRX6cYFBwbuDf0RSG1DEX +NmvHwmbtiO7GXvmywpfdk1cd1PsALVf7U2RTD9Dz+wX8rh+0jfVr61jgrzbw0MiEcSxJD0YFiPWF+lFS +b1i0B2mOt87MDKw3fKZoRQSYDZe8sbTC3BXdGB9v8okm5m3UEIODvY0IB0j5Nob5ogvCiUeEWVv8t+Cx +Bq/FEXB8l+iUQD5p2nhjRXyLxXw2b3DulgGVmt89G+rfL6OZm9+zGZt3dvy+qRmifeLT3sXCfO94A4m2 +ieAe+95tl5nBAXod8qNGvnlbWzU0F7TIB/oseuOHUVN9sKsM5Gm8F8oPWiwZ8E+Nvg9zq+r7uBejD5EL +v8D0cxYjpxSNGQlKSOX3DppYBSfQc/4XAAD//1Td/bNCEAAA +`, }, "/data/en/top_level_domains": { - local: "data/en/top_level_domains", - size: 37, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffJʬ\xe2J\xce\xcf\xe5\xca\xccK\xcb\xe7\xcaK\xccM\xe5\xcaK-\xe1\xca/J\xe7J\xcf/\xe3JM)\xe5\xca\xcd\xcc\x01\x04\x00\x00\xff\xff\x04\x1a\xcc\xeb%\x00\x00\x00", + local: "data/en/top_level_domains", + size: 37, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0rKrOJKzs/lysxLy+fKS8xN5cpLLeHKL0rnSs8v40pNKeXKzcwBBAAA//8EGszrJQAA +AA== +`, }, "/data/en/weekdays": { - local: "data/en/weekdays", - size: 57, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\n.\xcdKI\xac\xe4\xf2\xcd\aS!\xa5\xa9\xc5 :<5%\x0f\xc2\n\xc9(-\x023܊2ATpbIi\x11\x88\x01\b\x00\x00\xff\xff\u007f&+w9\x00\x00\x00", + local: "data/en/weekdays", + size: 57, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wouzUtJrOTyzQdTIaWpxSA6PDUlD8IKySgtAjPcijJBVHBiSWkRiAEIAAD//38mK3c5 +AAAA +`, }, "/data/en/weekdays_short": { - local: "data/en/weekdays_short", - size: 28, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\n.\xcd\xe3\xf2\xcd\xcf\xe3\n)M\xe5\nOM\xe1\n\xc9(\xe5r+\xca\xe4\nN,\xe1\x02\x04\x00\x00\xff\xffܹ\x9c\x9e\x1c\x00\x00\x00", + local: "data/en/weekdays_short", + size: 28, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wouzePyzc/jCilN5QpPTeEKySjlcivK5ApOLOECBAAA///cuZyeHAAAAA== +`, }, "/data/en/words": { - local: "data/en/words", - size: 1685, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffLU\xdbr\xeb0\b|\xe7/\xb1D\x1bft;B\xca\xf4\xf3ς\x9c\x8c_:\xb1\xcdewY(\x17e\xa3ԛɿ\xcdkO\xe2\xbdh\xc8\xfc\x91)-\xab\x91\xe9\xa2w/{,^R\x89S\xda\xc6m鮔{\xe9S\xea\xbf-\xc4HQ\xae$\xecO:\x8c\t\xf5\xf0\xfe\"-\xa5\x93\xb6\xb7\xb4\x85hz#\x10\xa5PY\x96ǘ\x12\xcf\xf4\xd2%iu\xba\x84\x17\xd2\xde\xea\u007f\xb3\xa6\xc5d\xbb-\x92\xbfQ4\xf1Չ\r\xad\xda\x17j\xcf\xc0\xe7?~\xf6/~\x99d\x14U\xfePB.\x02+\xff6\xbd\xe1\xa2o7\x8f\xa1\t\x14\xbdɓ\x9d\xa7(5\xb1\xa4\u07b5\x89\xb3\xb9i:+\x90\x8e\xea\xf1*\xa4\xe1\n\x1a\xd1,-\tPY\x87\"\x1fD\xcb\x13P\xeb\x8dچX\xae\x92n\xa3\n脦\xa3O\x86>I\xb3\xb7\x04\x93\x02\x9a\x10\nuO瀏,\xcc*\xb2]X`\u007f\xe2F\x964EH\xa6\xaa\xf8\xc1\xe8\xde4b!t\xeb\xb6&\xa0˟\xcc\x14\xe2\x836\x92JAD\xea\x13\b\b\xdc\xcf\xc7\x11\xb6Aq\xe8\rV\xbb'4\xc5,\x81$pjF;\xd8\x01\xf5k0}z,Pah(\r\x95H\x80M7\x88N\x19S^\xf0\x9d{$f\xa4\xcdk|\xa1ܢ\x8a\x99Ph\xd1\xf4\xa5\x05R\x16\xb1\xa5\x1c\xa2A[\x18\t-;\f\x84\xb9\x9bi\xc5\xc4\xf3NZ\xf7\x99\xfcU\x18\xde^\n\x14c\xb2\x98\x1c?\x17\xde\xf9\xb6\xf6\xea\v\xd5}\xea\x9f\xde\xeew)\xd0g\xc1\xb0\xcb}\x01\xe5&>)Jz\xfd\x8f\xbb\x8e\xab\xbf\x98\xf0\xe6/\xc9\x00m\x85r\x98pO\x89%a\b\x94\xf6Ь\xc1\xcb\xdd1f\u007fk\x06\x960\xcdYC\x1b\x9a4\xb6eC\x15\xea\x15|H\xcd3\x00\t\xb5\xe7\f#Vu\xd1\xe5,\vDK\xbb\f\x0e\xae\xfd\xe7\xc7K\x00\xbc\xc9\xf4\xaf\x00\x06\r\xf1\x861k(\x8cA\xd9=G\xf7\xc8\xed:\xfc\xc4F\xb1?\xbfx\x1e\xdfgqI\xe2\x13'4\xb4Ȕ\xd8Nq\"\x10\x1c\x94[\x82\xc1\xc8\x1d[\xf4\x92\xd9o\x93C0d\x1a\xe4\\\xbe\r\xd7'\xbd\xe8\xaf_\x1a\xea\xc3\xd3Ҏ{r\xe6\xaa5\xea\xba\xc0\x84\n(\xe5\xce9+d\xc7 \xb0;dP_\xb2\x0e\xf3\xf3\x9fV\xa1Q8\xe1\x908L\x9c1\xa4\xba\a\x10v\xe4\xfb\x1a\x99\r\v\x8d\xde\x1c\xd5\xcedz\xd90\xa2\x14\f;#\xe9\xa0\xd7k\u007f,\x8b\xb6x\xc8\x1cb\xf9\xe9yZ\xdb\xfd\x8c\x8bw\x04\xfb\x9e\x0e9rb\x92\xc1勠\xf9\x0e\xd2`\xdcθ\x1d\xcb\xcfc\x8f\v\xe5\xb5\xe3\xd6\x06\xf0\x18\xa2ÓK\xd7Y\x9e{\x14M\x12\xd6!\xb6\xda!\x1a\x03:\x89\xaf\xbf\xc45\x91ǡ0'\xb6\xb3\xc2\xfdؕp\xa3\xac\xc7\xf6\xb8\v\xa7ā\xf7\x00\x14\xf5YH\xcc\xfft{i\x82 \xed\\:4\x1b\n\xbfJlFr?\xeeuC\x03\xdc\xf3\xff\xe3\xd3<\xd0U\xd6X\x92\xd0\xe5H\xea\xe7\xfc\xbc<\xa2C\x83\xff\x01\x00\x00\xff\xff]\xcec\x0f\x95\x06\x00\x00", + local: "data/en/words", + size: 1685, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0xV23LrMAh85y+xRBtmdDtCyvTzz4KcjF86sc1ld1koF2Wj1JvJv81rT+K9aMj8kSkt +q5HponcveyxeUolT2sZt6a6Ue+lT6r8txEhRriTsTzqMCfXw/iItpZO2t7SFaHojEKVQWZbHmBLP9NIl +aXW6hBfS3up/s6bFZLstkr9RNPHViQ2t2hdqz8DnP372L36ZZBRV/lBCLgIr/za94aJvN4+hCRS9yZOd +pyg1saTetYmzuWk6K5CO6vEqpOEKGtEsLQlQWYciH0TLE1DrjdqGWK6SbqMK6ISmo0+GPkmztwSTApoQ +CnVP54CPLMwqsl1YYH/iRpY0RUimqvjB6N40YiF067YmoMufzBTigzaSSkFE6hMIPEpqP1V8fPVZPgjc +z8cRtkFx6A1Wuyc0xSyBJHBqRjvYAfVrMH16LFBhaCgNlUiATTeIThlTXvCdeyRmpM1rfKHcooqZUGjR +9KUFUhaxpRyiQVsYCS07DIS5m2nFxPNOWveZ/FUY3l4KFGOymBw/F975tvbqC9V96p/e7ncp0GfBsMt9 +AeUmPilKev2Pu46rv5jw5i/JAG2FcphwT4klYQiU9tCswcvdMWZ/awaWMM1ZQxuaNLZlQxXqFXxIzTMA +CbXnDCNWddHlLAtES7sMDq7958dLALzJ9K8ABg3xhjFrKIxB2T1H98jtOvzERrE/v3ge32dxSeITJzS0 +yJTYTnEiEByUW4LByB1b9JLZb5NDMGQa5Fy+DdcnveivXxrqw9PSjnty5qo16rrAhAoo5c45K2THILA7 +ZFBfsg7z859WoVE44ZA4TJwxpLoHEHbk+xqZDQuN3hzVzsez2TCiFAw7I+mg12t/LIu2eMgcYvnpeVrb +/YyLdwT7ng45cmKSweWLoPkO0mDczrgdy89jjwvltePWBvAYosOTS9dZnnsUTRLWIbbaIRoDOomvv8Q1 +kcehMCe2s8L92JVwo6zH9rgLp8SB9wAU9VlIzP90e2mCIO1cOjQbCr9KbEZyP+51QwPc8//j0zzQVdZY +ktDlSOrn/Lw8okOD/wEAAP//Xc5jD5UGAAA= +`, }, "/data/en/zips_format": { - local: "data/en/zips_format", - size: 8, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffR\x86\x00.@\x00\x00\x00\xff\xff\x87\xdd'=\b\x00\x00\x00", + local: "data/en/zips_format", + size: 8, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1KGAC5AAAAA//+H3Sc9CAAAAA== +`, }, "/data/ru/characters": { - local: "data/ru/characters", - size: 119, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x04\xc0U\x15\xc3\x00\x00\xc5\xd0\xff\xa8\x19\x83\xbb1Ù\x931\xb7\xb5\xf0\xe2\xa87gr!Wr#w\xf2\xc0\x13y\x92\x17y\x93\x0f\xf9\x92\x1f\xf9\x93\x82\x94\xa4\xc2\x11\x8eq\x82S\x9c\xe1\x1c\x17\xb8\xc4\x15\xaeq\x83[\xdc\xe1\x1e\x0fx\xa4A\x93\x16m:t\xe9\xd1g\xc0\x90:\x00\x00\xff\xff\xb7\x8c\"\x8ew\x00\x00\x00", + local: "data/ru/characters", + size: 119, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/wTAVRXDAADF0P+oGYO7McOZkzG3tfDiqDdnciFXciN38sATeZIXeZMP+ZIf+ZOClKTC +EY5xglOc4RwXuMQVrnGDW9zhHg94pEGTFm06dOnRZ8CQOgAA//+3jCKOdwAAAA== +`, }, "/data/ru/cities": { - local: "data/ru/cities", - size: 2271, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xfflVir\xf2F\x10\xfd\xcf)\xb8\x00wD\xe0\xd8N\xe1\n\xf1Vv\xe4\x05\x03\x95\xf2\xaf\xc4b\x11\x8c\x85\x90\xaf0s\xa3\xbc\xf7zF\x88\xd4\xf7\x8bަ\x97\u05cb\xf0\u007f\xfa\xad?\xf82\f{ A\xf8*d\xbe\xf0G\xbf\rC\xdf\xf85\xc5G\b~|\x01\x12\xb2=\x98\xda\x17!\x13\x1b~\x93\xf1\x06\x0f\x0f\xe1\x06O\xab$vx\xd2\f\xfc;d\"\xfd\xdaW\xe6#\v#\xf8)\xeci\xb8\xe9\xf9[\xbc\xde!\x87K\xbe&s\x80\xc3F\xf1\xb7\x14\x18\xb96\xef\xb7\xf0>\xc5;1wpq@\x05\x85\xff&×\x0ea\x9c\xff\xee\xfb7\xc5\xec8\xfa\x9f~\xa9D\xfe\xf0\x1bi`T\x86)\xc9\x03\xbcma\xb2\xc6KX\xe0m\xd5\x15\xd7\xde\x11\xac;ȕ\xa6߰\x18\xf3O\x11\x04LH\xac\"\x1fY\x1d\xd80\xf1+\x89\x18\x10%\xec\xc3\r\x81\xec\xf9{\x15\xe1\u0095H\xe4t\x850GӔ\xea\t\xba\x01\x80\x1c\x13\xb9O\xf5\x10\xaf\x96\x05\x96,V\xa2\a\xa58J\xed{\bcĕ\xbbGC\x03q˄\xe6\xa3\xffND\xc5\xd8\x02\x82\xd1Wal\xa9>\xaar\xb0x\\\x18\xab0O0g\xe1\xf1\xfd\x13\xc3\xe3\x9d\xeb\"\xfe\f!ǃ\xb95dw\xa7\xc8Ϙ$\xe1a\xec_ \xaf\x95\xc3\x10CØ=\x9f\xe3\xf1>\rIn()\xc4\xf1\x04\xba\xc4)9c\x00-m\xc4j\xfajC\"G\xf0Z\x05\xc6|r\xea\x90\xc0\xc4H4\n)\xd4\xe6\xc8\t\x87\x83\x1a\xbaN\x82\x96\xccL\xce*-\xfd\xdcr#\xc1ImM\x1b\xe4\xd2Y\x8d<\x8eHm\r\xc9m\xc4dnq\xb5\x18\x19\xb5a\xda\xd7ڰ\x9e㹎\xdd/8\x84\x1dQ\x98&$s\x9b\xbap\x8dn\x02\xa20\xa2h\x9c\xb4/\x86)\xc7\xdd:\x01ےb.i\\\xc1\x17\x98\xdb@\xb9pIt^\x85\xbdb0cMD\x9c\xb6W\xd8\xedNc\xf0*}ž\x83\xd1\f\xd5\xea\xa0i%@\xad$/9/I>A\xb2.\xfc\xee\x9d1\xd7ZR\xc0\xf9\x86\x9f\x9dz\xfe\xab\x8d>\xd3.\x10gÞ\xf5\xa2\xa1mF\xa6\x11\x88\xe9%\x05E+\xb6\xd4\xc4\xef\x18\x03# \xb9\xa5\x87w\xad~\xa1D\xd4ʙJ\x8e]\xef\xb3#}<\xab\x88\xddL\x83\xbfgųxH\x12Dh\xfc\x80\x9b\xa2\xa5Ʉ\x8c\xe3\xa92\xbb\x9asM\xd2֎\x85]D\x81*\xdc\xcbG;c3\xf3B\x82\x13МƊ\x82*\r\xdd,vU\xe4\xf8\x04e\x87\x89\x89\x94\xfdx\x10&\xd4Nق(\x90\u05cf\xf6\x00\xae\xfb\xe7\xc7\xf3L7 \x18\x03\x9c\x1d\x0e\xdd\x18*l\xa3\xc0\xf8\xd0\xc5s\xa9\xc9\x1fZ̸\xcd\xf3\xf8\x15\x19\xd2p\xae#Q\x85Ѡ\x83F{\x80\xe6\xf1\xd0D7\x89\xfdA\x98C\xcbZ*d\xd7\xf2`w\xb8-e\xcei\xe7\xaa\xc8\xce\xd6JY\x18\xee\x8e\xea>a\xd4\xc7o\x9b4?i\x11(\xa8\xb5\xbb\xe5)\x8f&\x02R\xa4\xe9\x99\xc7\xed\xe6\x97Ή\xe5)\a!D\xb6:N\x88j\x83ʂر\x8d\tꄌ1+\x8b\xba`uH\"#L\v\xd564\xa3F&\xed\x04,\"\x83&\xb2\x8d&\xa8[\x1d\"\xed\xecCFf\x94\xbe<\vb\x18\t]\x8bRA\xf1Q\xacU(\"-\x91j\xfc8--\x82\xddss\xbd\f\x17|\xfe\xb7\x92\x1f\x85\xc9@\xa7\xe2\xd8]\xb9OxZi>3\x1531\x11\xcfZg8>mq\xe2\x1f\x05]\x96\u007f\x14Wk\xd8\xf3\xff\xa6\xcf\xd6@\xc3\x1e\xeb\xb6Y\xfc\x02+\xa3\xaf\xb3\xf3D\xac\xff\v\x00\x00\xff\xffL\x92o\xa5\xdf\b\x00\x00", + local: "data/ru/cities", + size: 2271, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2xWaXLyRhD9zym4AHdE4NhO4QrxVnbkBQOV8q/EYhGMhZCvMHOjvPd6RojU94veppfX +i/B/+q0/+DIMeyBB+CpkvvBHvw1D3/g1xUcIfnwBErI9mNoXIRMbfpPxBg8P4QZPqyR2eNIM/DtkIv3a +V+YjCyP4KexpuOn5W7zeIYdLviZzgMNG8bcUGLk277fwPsU7MXdwcUAFhf8mw5cOYZz/7vs3xew4+p9+ +qUT+8BtpYFSGKckDvG1hssZLWOBt1RXX3hGsO8iVpt+wGPNPEQRMSKwiH1kd2DDxK4kYECXsww2B7Pl7 +FeHClUjkdIUwR9OU6gm6AYAcE7lP9RCvlgWWLFaiB6U4Su17CGPElbtHQwNxy4Tmo/9ORMXYAoLRV2Fs +qT6qcrB4XBirME8wZ+Hx/RPD453rIv4MIceDuTVkd6fIz5gk4WHsXyCvlcMQQ8OYPZ/j8T4NSW4oKcTx +BLrEKTljAC1txGr6akMiR/BaBcZ8cuqQwMRINAop1ObICYeDGrpOgpbMTM4qLf3cciPBSW1NG+TSWY08 +jkhtDcltxGRucbUYGbVh2tfasJ7juY7dLziEHVGYJiRzm7pwjW4CojCiaJy0L4Ypx906AduSYi5pXMEX +mNtAuXBJdF6FvWIwY01EnLZX2O1OY/AqfcW+g9EM1eqgaSVArSQvOS9JPkGyLvzunTHXWlLA+YafnXr+ +q40+0y4QZ8Oe9aKhbUamEYjpJQVFK7bUxO8YAyMguaWHd61+oUTUyplKjl3vsyN9PKuI3UyDv2fFs3hI +EkRo/ICboqXJhIzjqTK7mnNN0taOhV1EgSrcy0c7YzPzQoIT0JzGioIqDd0sdlXk+ARlh4mJlP14ECbU +TtmCKJDXj/YArvvnx/NMNyAYA5wdDt0YKmyjwPjQxXOpyR9azLjN8/gVGdJwriNRhdGgg0Z7gObx0EQ3 +if1BmEPLWipk1/Jgd7gtZc5p56rIztZKWRjujuo+YdTHb5s0P2kRKKi1u+UpjyYCUqTpmcft5pfOieUp +ByFEtjpOiGqDyoLYsY0J6oSMMSuLumB1SCIjTAvVNjSjRibtBCwigyayjSaoWx0i7exDRmaUvjwLYhgJ +XYtSQfFRrFUoIi2Ravw4LS2C3XNzvQwXfP63kh+FyUCn4thduU94Wmk+MxUzMRHPWmc4Pm1x4h8FXZZ/ +FFdr2PP/ps/WQMMe67ZZ/AIro6+z80Ss/wsAAP//TJJvpd8IAAA= +`, }, "/data/ru/colors": { - local: "data/ru/colors", - size: 216, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffD\x8e\xbd\x0e\xc20\f\x84\xf7\x8e\xdcF\x0e\x1e\xfa\xa1\xdd\xe6\xfbQc\xa4-6\xea\xbb0MU\x8a>\xba\x16\xb4\xc5Rl\xa1\xe2eJ\xf8\xc0\xf8\x03s\xee\x8d\xcb\xc9\xe2\xfc(\xcd{\x03\xec\xd1|K\xa5\x1e\xbd\x8c\xa4;\x89\xb3\xf1\u007f\xcc\xe2\x94,{\x02\xc1\xccxT\x8d|\xa2OE\x00E\xfb\xd7@t\u007f,\x95\xd5>ז\xe4\xa7&Q\x18\x81\xa9\x99\x03\xbe\xf2H\x96>*G\x06\xb1\x9c\n\xdbVC\x0f(\xdba\xddbO*\xcb \x1a,\xb7\nl[s+1\xb49\xc7f\xb0%Ă\xb9\xb4\xc1\xaa\x9bўk\f\x99\xf2N\xb2\xf8n)O\xc9^\xb1\xcaZ\x9c}c\xc2rk\x11\x94E\xb6t\xe5\xff\x14'\xa2\x92D\x0e5\xc3b\x8e\xf1\xca2ѣ\xd2\x03B\xe7\x98\xd7\xf4\x99K\xad\x93\x932Γw%\xc0ka%\xeb\x15ԕ\x8a2\xe6a\xb9\xd2\xecԿgȆ`\r\u007f\x00\xd7\x15\xea\xa8\xf1}J<٨\xb0P\x19Y\xa9(\\#z|\xc3\bx\v|7\xab\xbf\x9bO\xbeK\xaf\xcaܗ3\x80\xe0E\xdeF\v\xe5\xabw\xf5\x8f\xdd\xefNP\xd6\xe5\x95\xe8P\x1d\xbf\xb2\xbe\xf5\x86\xa5W:N\xea\vE}\xb2\x86\xd2\xe6͚\xb2\xfe'\"\xf5\xd5\xca\xd1x\xc377\x82<\x1b\xf97\x1aȒ\xcb\xcf\xfc\x13\xfb\xa1\x94ۛ\xdc\x1f\xb8\x97\x9f\xfe\x1b\x00\x00\xff\xff\xf3G\xd8e\xc2\v\x00\x00", + local: "data/ru/countries", + size: 3010, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2xWWXYbtxL95164Rw6Wn86RX2QNObZJMSIlJdaP4maTMMGhm1tAbyEryb23Ct2t43wB +dQHUPCB9TmUzbibNKBXpmGJzPehBTu5SALHGjX3app9YK8JHQVW+dcRJbEbcVmmTagCFEdtUNyNKENlM +UkybZioS6CYFB6sMnQg53+YDbpgYKGWyb7AQPDVXRlAgxEFSaC4FucIUPTbgAlCABXofcJ1KTcF0bJIM +jGnn2+YTmLYnFfXjlnZtxN/Par0qWxL8qo6YgCylIWy7kZt3uO6uvqEKOINeJKY4P5gjhukFQsapdlzX +tika6X645UJPQsyUpFlwgE5rKTjpAnQrIzZZbyMDzJ82/7dQ3VJ3PKmb/4HrFVW6hRMCoIrOHqQ7LGsw +r2xL/tG2+2wiiRMuSchdh5ZUEjJPyjOHolS4fkcM4TaEGtenxIPSobXijtLTVp4qGNk7RbVSqAsnm49+ +WW7bGXHfMblnpsJDU9P/HjxPEk/XFb8AcMaYK5/+zpxIZzplkL70bf0C/KScW8OYMEhf007hjkwlkoof +r9q2Vtx3GUI20oSs41e9PeRNZZujLmQ2UOsX4NxnMemK+pt8H8hoZlEcMgckNBi2U5G0RTZz62qr+QwE +y0UjW7/PFN6C5T/rindGXxkWVekx22tApL8sCLO0SEsuKCfwb906UyxYqij1JRMWHKc4PXbRomV1Oigl +wAzpG7qIkfE9Wf/n45nnPOpt2ccmw7T9Z/QNcSlVX7RBLwvblCxZ5sAcHlCLmUu4t4G5ZNUsJhK0M+TK +m6tbyMXzrnHMVU0l+XN7oWKpmkutalrz5jfYOJa1axXAZpAewKiUJ9k39j2gX/sPFib1LXPMyMADuFkm +tveYUSUjkol9jpkB+QSdYUv1GRcHKFIE5CMe7ENONpd6i56bHwTZ4h5/AL7LxcSkf1BX3ZoqJrtWsjnL +uh0xdgrZ14BOZLYQo5gTaMFOwpzlNqg+jtxGDh76od3m+1FjpC026rswTVWKProWtMVSbKHiZUr4wPgD +c+6Ny8ni/CjNewPs0XxLpR69jKQ7ibPxf8zilCx7AsHMeFSNfKJPRQBF+9dAdH8sldU+15bkpyZRGIGp +mQO+8kiWPipHBrGcCttWQw8o22HdYk8qyyAaLLcKbFtzKzG0OcdmsCXEgrm0waqb0Z5rDJnyTrL4bilP +yV6xylqcfWPCcmsRlEW2dOX/FCeikkQONcNijvHKMtGj0gNC55jX9JlLrZOTMs6TdyXAa2El6xXUlYoy +5mG50uzUv2fIhmANfwDXFeqo8X1KPNmosFAZWakoXCN6fMMIPHn2I0BPLi9KBb5Sa2JMp0bo26Stvha9 +j5WgPCmf/Y+lHHmG2DULtK/es/XX/Et71hRoc/NFfSTkDgyYH4jAg2jG2vao4XlWcK8MqqDsdTfDXmzc +ZcX+9NKyxg7gL4u7/VfhYUalaD54C3w3q7+bT75Lr8rclzOA4EXeRgvlq3f1j93vTlDW5ZXoUB2/sr71 +hqVXOk7qC0V9sobS5s2asv4nIvXVytF4wzc3gjwb+TcayJLLz/wT+6GU25vcH7iXn/4bAAD///NH2GXC +CwAA +`, }, "/data/ru/currencies": { - local: "data/ru/currencies", - size: 4636, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x8cX]\x8e\xdcD\x10~\xefS\xf8\x02\xb9\x06\x8a\xe0\x05!x\x80\xd3\xcc\xcf\xeef\xa5\xec2\vBB\n,\xcaF\b\xf1\x12\xe1\xf1\xd8;=\xb6ǾB\xfbF\xd4\xf7U{\xdc\xedm/(\x0f\x99\xb8\xbb\xab\xab\xbe\xfa\xea\xab\xea\xb8\xd2\xd9a5\\\xbbܵ\x99\xfb\xc3=\xb8\xcf\xc6\xe5Õ;ȗ\xf3\xb0v\xb5\xb3\xee\x94M\x9f\x9c\x95u\u05f8}\xbc\u07b8\xca\xd58\xb9r\xed\xb0\vWJ\xf9$\xc6\r\xf7o\xe4[3\xdcM\xab\x87a\x8b\x0f\xe2F\xe5\xce\xdc#\xd7t\x97=\xf9\xb0\xcb䯂\vG\x97\xeb\r\al\xa6-\xbd\xa7sU\xe6zW\xc9?:\xd8(\x86\xf5\xb0\xe1\xb5\rn\t|\x81i\xf9#F\xb0\xef(GV\x8c\xe4$K\xcfqD-\xeḟ\x8d\xd1X\xe5V9\bG\x87ۋo\xe2D\x8e\x9f\xd8\x03\xd3\a\x98\x8eQ)x~\xb8\x96\x9b*\xb9'D\x06\x01\xa8/\xfba+\xe7\xb6\xf2\xcf2\xf2x\xb8b\x18g`\xbb\xf7;\xaaň\xd4\a+pEQ\x87\x9fa\xab\xa3-\xc6\x1fg\x83.\nh\x1a1\xd2\xdd.\xdf$\b\xaf51S\xa6zdSѨ\xe4G\a\x8f%\x17\x93}Y\xdf\xe3J\x83\x13\b^葾\x01Y\xf5\\\x10[\xc7\x14\"í\xdc\x0f4n\"\xd4\xc3\x1d\xef\x10\xe1\x05\x8d\x98'\xb2\x9b\xe9\v\xd0\xfe\x91\xe1\xdc\xe9\xed\x8d8ۊ\xbbK\xa7;\xb0\x8c|\xb4\x1a\xcd\x14\t\x8f#\x00\xd9ǐ\x93L\x15\xefB.\xc9\xd6\x15\x83\xce\xcd\x14B\xe6~\x11bZ\x12d\x83\xda+A\xc9\xd4\x19\xb2\xfd\x99՜`\xd8pOo\xbb0[\xc1\xd9J\x90\xb6tl\x13\xe2\xb8E\x99\xe1\xec\x95|\xe9$\xbd\x13\xa7\x86\xf7Ȓ\xd0\x1bFL\x98\xbb\xcc\xfd){PO\u058c62ގjk\xe8\x12\xf2Zd\xee\t\x80x/\xa5\xa4\xc1M,\x11@:\xc7\x02\xe2\xd9\x02n\x1eȠ\xe3\x05N_d́\x99I\x96\xfc\xa0i\xfd\x1e&\xd2C\x93\xf3\xe4Zw\x14އt\xe9a=G\x00T\x85H\xc0jbv\xa3\x9f\r\x03;\x8f\xe4]\xa0\xb6\xee)Q\xf2p`JH\xc3\vz\xe4\x10$\xb8&\b\xc5<\xe1[MYA\xc4\x0e\x005\xf0\x99G,!\xcf2\xf7sb\x0f\tq\xc3|\x9e\xd5k\xd9\xfd^uB)\x97\xbd\xfd\xee\vC+V\xdd1\xa4l\x87NY{\xc2vZE\xa1\x95\x15\xef\x17,q\xff\xe3\u007fe\xd2}\x88-e\xd9Wo\xbf1\xac\x8c\x82\xd5\xd8\xf9J\xab\x82\x8c\xc8R7R\x8c?2\xf7\x91\x8aիzS\xee,l\xf3$\x12\aR\xaa\x14o\x92ɫ\xd9l\xd0\x04)\x99a\x1a7#E\xff_@\v\x9e\xcc\xccK\x9c?|K\x8c]\x9f\xb9\xdf\xe4S\xe7묃\xb5G\x11Տ\xc6\xf7\xc4ț\x8b\xe4\xdd\x02\xe97\x9eW\xf5\"c\x1b\xf6\x10\x94@ G\x163CC\xc1\x98u\xe2F\xe7\x89D\x8f\x0e\xc0j\xa9g\xc8L\xfd\x82\x95㨆] q\xa9\xd3N8o\x9c\x8c\x8a\x94vp\xe8[x\x8f\xb6+/\x98\xa5R\x19\x92\x9d\xc4\xf5w\x0e7\x95\x97\x01\x06\xdcJi\xcbx\xa7\xd3ф\xdb;\r\xac\x9d\x9av(\x01\x1b1{\xd0>\xa9Ρi\u0600\t\x84u\x8bj\xe0\x1d\xe3\x8eW\x80\x1fC,\xa2\x1d:*\xc2\x1b\xec\xa8(%as\x8e[\xf8h\xe3\x14\xe8ۥ\xc8\x10\xc6AS\x89\xa8\x8e\x97\x1eR\x87#b\xc5)\xb4V!\x8az\xe0#\x0fX\x1e\xb1\x86b@\x1d\x8e\xfd=S\x99\xa0\xf6\xdcQ339\xa7\xe2h\xb0:\xea@\xc1yc7\xb6Gܷף\xda(*\xf7\x9c\xec\xee\x90\xf0>h\\I\x11g\x90U\xa4\xa4/ղ\x9b'\xfe\xa2½\x9f\xe7\xdap\xee\xd4\x1a\x86\xfc䆸\xaf\x82\xc0|3\x1a\xfb\a\xc5\x0fM\x82\xc3F\xc3q\xa4_\x18\xf1{\x12\xd3Fj2\x0f\xaa\x9f\xb1P\xa2#\x82\xb8\x8c\x16\x14i*\xc0)~\x90\xe4\xbe\xf3[*\x97\x0ey\x89\x90\x03\xdfqo+?\xcf\xf3Z\x84\xd6⍑\xec-k\xf9kK\x80\x8bȼTX\xa3*}b\xfb\\ț\x84\xbf\x9du\xae@\xc0ȇtG\\{~\xe7(\xf8x^\x9cr-\xd6\xef\x981\xc1\xe2\r\xa3\xe9\xe6\xe1q80ڵ^<\xb6f\r\x0f\xce\xfa\xc2Z|V\xc0\xb1\xa0B\xe2\x80\xf4\xb1\xc1'\ve\xab\x8c$\xd7\xf3\xf6\xa0}א\x17\xf6%\x99\xf7\xd4)\xaejk\xadg\xcdW\x95.\xca톎\xd7\x14\x94\xe4\xfb\x90\xfav&\x1dSY\xd6\xf3\x954\xb6˘\xa7\x03^,\x18\x9f<:\x96)-\xd1vE\x82?i\x8dCSc\xa7\xa8[ڽ\xee\x16\xd0܌\xaf\xe6\xd7G\x11q\xbe\xf6\x83[\xa08\xaaׅ\x12f\xeb\xdf\xfe\xe5\xab#M\x14Γ\xfb\xdb=\x18\xff\xac\r\xab,~\x02a\x9a\xdf{\xa5\x1e\xf3\x80Z\x1a\xe7ۊ\xbc\xb9\x8f+yz\xd0\xe2*PD\x9e(+\x8c\x12r\x8c\xacݤh\xc6`\x83\x97\xd5\ay\xa8\xb4\xa7\xdaen\x163\x0e\xd4S\x83\xcfT\xb2\xc3\xe7g\xf4\xf8\xa0.\x86\x8enA\x15\x8d\xb6h\xa4\x16\xbf\x94\xf1G>K\x04\xd2)#Mqw\x8e\xee\x15\xaa\xeb\xb8;\x97\xc4\x16\xd0\xfe\x13\xcaCv(\xfe\x86p\x81_\x153W\xd8k\xe8\xc4xt\xaa\x83˰\x9c\xec\xec\a\x04z O\x81=vKż\xc0ℶ\xa6\xe4;\x1a\xfb\xb9\xf2\xd8x-\xfcdrf\b=\xfbÕc.h\xe3\xe7\xd6\xdd\xd2\x19-kw\u007f\xd9\x16]\xf0?D\xfe\x04\x87{\x04@\xc9y\xc3^\x8f\xb6wJ\xc9+\xceHh\xe7\xd8a\xa4\xd0S\xa7>\xb2\xb4\xf8M\xca5\xa6F\xd9I\xbb\xbc\xa0\x04z*\xde\x1d>2,S\xc6R`\x81\f\xe4\xe4,\xb4\x19\x04g\xf5\x115\nE \x01\x1ar\xb08+ȍ\x18-\xa4\xaf\x04I~Y\xb0\x13$\xad2ËF\x03\xbb\xc0\xec9\x06~`\xd1[\x8d^\xa5\xe1d\x1a\xa2ڌ\xf7\xc2\xde\x05\xf7uT\xb9\x06\xa8\xa7d\x1e\xf6\x80\x88\xd9\x19w\x82\x8fQOx\x06\xd5\x062\x1bp\xe4\x1c\xe5}-]\x1e\x94\xab\x95\xbb\x153\xa7\xdd\xc1\x9e\xb0\x85\xf67\x82c\x91\xee\x8f\x00n#Wor\xe9\xc6p\x17\x93\x003\x9c\xd1]\xbb\xe8Κo+\xc0+!\xda\x00d\xed\x10\xc4ܥ\xa5\x82\v\x19J(\xfe\x8a\xac\xd6\xd8X\xda\x16\xea\xc9ߢ`!\f\x8fz\xaf\x99\xceV\xfd\x96\x8b\x97\xcc\v\xf3.\x96\xa9\\\x86\xb9\xb8\xe5%\x9d\xbf\x18\x01\xb0\x9a\x1e\v\xd1\xef\xe2\xea6\xff>8\x85\\\x9a8\xa0\x94LڡV\xa2v\xc2}\xe7\xed\xe7\xb9͒\x98\x80Y\xea\xbb6\xb3\x8f\xd8\x06\xd7f\xb8\xe2ѻO\x81\xec\x83n\x18J\xb3\x16\x90\xa9U;\x152L\x1ax%\x94\xdd\xca#\x968\x1cb\xe3\xc85\a[\u007f\x0e\x04bc|\xa4\xfb\x02D\x0fJ\xceV<\xe2G\f\xa1w\xb4\x87\x00\x90:<\xe03\xeb\xe7\xa37\x96wڒ\x1f7\xb5\x80\b\x84\x82{\xb9DO\x9c\\\v\xf5\x99\xda.\xc7m4\x14\xfct_\xac#\xd6(\x18\xac\xabĒ,1+\x1a\u07bc+\x8f\r\x11\r\x9a\x03z\xa4\xeao\x00\x00\x00\xff\xff\xc0T\xbbH\xbe\x06\x00\x00", + local: "data/ru/female_last_names", + size: 1726, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2xUW27bQAz876kdJQ0KJED8SmO4blynBpp+VZIlWNHzCtwbdch9kHb7YXjFJbnDmdml +DZWU00Aj/3+iJeXuhhrq3CPVPrSn2mVuFjMO1FODz1Syw+dn9PigLoaObkEVjbZopBa/lPFHPksE0ikj +TXF3ju4Vquu4O5fEFtD+E8pDdij+hnCBXxUzV9hr6MR4dKqDy7Cc7OwHBHogT4E9dkvFvMDihLam5Dsa ++7ny2Hgt/GRyZgg9+8OVYy5o4+fW3dIZLWt3f9kWXfA/RP4Eh3sEQMl5w16PtndKySvOSGjn2GGk0FOn +PrK0+E3KNaZG2Um7vKAEeireHT4yLFPGUmCBDOTkLLQZBGf1ETUKRSABGnKwOCvIjRgtpK8ESX5ZsBMk +rTLDi0YDu8DsOQZ+YNFbjV6l4WQaotqM98LeBfd1VLkGqKdkHvaAiNkZd4KPUU94BtUGMhtw5BzlfS1d +HpSrlbsVM6fdwZ6whfY3gmOR7o8AbiNXb3LpxnAXkwAznNFdu+jOmm8rwCsh2gBk7RDE3KWlggsZSij+ +iqzW2FjaFurJ36JgIQyPeq+Zzlb9louXzAvzLpapXIa5uOUlnb8YAbCaHgvR7+LqNv8+OIVcmjiglEza +oVaidsJ95+3nuc2SmIBZ6rs2s4/YBtdmuOLRu0+B7INuGEqzFpCpVTsVMkwaeCWU3cojljgcYuPINQdb +fw4EYmN8pPsCRA9KzlY84kcMoXe0hwCQOjzgM+vnozeWd9qSHze1gAiEgnu5RE+cXAv1mdoux200FPx0 +X6wj1igYrKvEkiwxKxrevCuPDRENmgN6pOpvAAAA///AVLtIvgYAAA== +`, }, "/data/ru/female_patronymics": { - local: "data/ru/female_patronymics", - size: 237, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffT\x8eA\x0e\xc3 \f\x04\xef}5X\xed\x8dC\x9f\xe2V UP\x92/\xac\u007f\x94\x15\t\x91\x11\x17<\f\xeb\xc5\x1b\r\x05\xd5\"\x14\x1d\xd9\x026|y\xd3\a\x9fNPx&\xb2`/\xfc\xb0{k\x06x\x0f݄Nw\x1e\x8dʱYB^\xbe\x13|P\x98,\xde\x0e\xb4\x95\xfb\x93\xdf\xfe\x1c-\xd5\xe2\x82\a\x92+{\xe9*\x1c\xffw\xea\x11\x00\x00\xff\xff\xfc;\xa2\x9c\xed\x00\x00\x00", + local: "data/ru/female_patronymics", + size: 237, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1SOQQ7DIAwE7301WO2NQ5/iViBVUJIvrH+UFQmRERc8DOvFGw0F1SIUHdkCNnx50wef +TlB4JrJgL/ywe2sGeA/dhE53Ho3KsVlCXr4TfFCYLN4OtJX7k9/+HC3V4oIHkit76Soc/3fqEQAA///8 +O6Kc7QAAAA== +`, }, "/data/ru/genders": { - local: "data/ru/genders", - size: 30, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\xba0\xe7b\xf3\x85m\x17\x1b/캰\xef\xc2N\xae\v\xd3.l\xbd\xb0\x17\xcc\xdd\x01\xe4\x02\x02\x00\x00\xff\xffdgd\x9f\x1e\x00\x00\x00", + local: "data/ru/genders", + size: 30, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/7ow52LzhW0XGy/surDvwk6uC9MubL2wF8zdAeQCAgAA//9kZ2SfHgAAAA== +`, }, "/data/ru/languages": { - local: "data/ru/languages", - size: 419, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\\\x90Mn\x830\x10\x85\xf7\x9cڀ`\x85ԟ\x15\xa2TT\xb4]\xe36\xa0\x98\x80\xc9\x15\xde\xdc(o\x90\x90MVx\xbe\x99y|6\x1a8\xc9`1K\x8a\x1b\x1c\xe6\x045\x8fw\"\x1f\xd0+<.X\xb4\b\xf0\x97\x1f\x8f\x11\x8e}1\\\xf8\v\xbd\x0e\x9b\x18\xc9$\xe7\x9a\xc5\"Uh\xbda\xdaӞ\xf0\x97䒆r\xa0\xc2\x16+\f\xf8?;}\xc0J\xc1\xdf{\xd8\x04\x9f\f]1Iyt\x1b\x15 \x8c|\u007fvI/%\xad\xae\x01\xf7\x9cZTT\xf2\x04-C9E\xf3B\xef\xd5S\xcaı=\x13V\x1eO\xea\xefRq&S\x13\xac\x01\u007fsu\xd4\xd0z\u007fa]y\x89/\xd0*\f\xf7\x01\x1ba\xb1!\xe1\xc0\x16\xac\x14\x95C\xca\x16\xa5W\x1d\xf8[\xd4F#H\b\xc7?\xaf\x92\xcc$+\r\xfa\x8fl\xde4\xd7\xc5K\b\x1a4]\xa9\x0f\x99b\xb6\x84\xa3\x17\xf8\x1aGo\xb2\xeb\xce\x13\xce|\xe8\xae\xe83)\x93\nx\xb9\xed\x05\xab\xed\xed.\xe1\x85!\x9b\r\xbeZ\xe3\xb7\xe8\xe1+\xc9\xe2IV\x91b\xb7\x14\x18+\xe1M\x91\"I'\x9b'\xe1\x9cw?\xe2\x94\xf0A~&\xac\x82Y{%|\xf2\xdd\x1ak\x9c\xfc`S\x1c\xf3\xc4V\x19?\xe1|\x11\xceq\xae\xefk\x98\xdf\x00\x00\x00\xff\xfft5E\xb6\xae\x01\x00\x00", + local: "data/ru/male_first_names", + size: 430, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0xQy0rEQBC8z1ebBW8L6rqCiK8FzxI2GZjNZOIvVP+RVd076CWpx/SjGveoyFhswIiG +2W7SPynjItow2g4b5dIFPgz3ARthsSHhwBasFJVDyhalVx34W9RGI0gIxz+vkswkKw36j2zeNNfFSwga +NF2pD5litoSjF/gaR2+y684TznzorugzKZMKeLntBavt7S7hhSGbDb5a47fo4SvJ4klWkWK3FBgr4U2R +IkknmyfhnHc/4pTwQX4mrIJZeyV88t0aa5z8YFMc88RWGT/hfBHOca7va5jfAAAA//90NUW2rgEAAA== +`, }, "/data/ru/male_last_names": { - local: "data/ru/male_last_names", - size: 1531, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffdT\xdbn\x1aK\x10|\xf7W\xe3\xc5\a\x1dɖ\xc2\xcd1\"\xd8\x04\a)\xceS\x96\x85\x15xaw\u007f\xa1\xe7\x8fR]==\x03\xc9\x03Zf\xa6/\xd5U5#\v\xa9\xa4\x94V:\xa9\xeed*e\xb8\x97\x93\x9cÓԺ\xb1\x96:\x14a`\xa7\x1b\xb9\xc8\t\x8b\x18\xbc\xc2\xe2?\xe4~\xca\xd96\xb6a\"\a\xe9rx'\r~\xf1\xf47\x17\x15\x96\xb1r'\xbd\x9d\x8cQ\xf1\x80\xac\xdaN\xc6\fi\x00䟍2F2\xed\x1b6w\xf8\x1d,j\x86\xfd\x93쵿\xa3߄\x02\u007f\xfa<\xdf\x06\xcb\vP\xc6\xe5\x1a'\x95\xe3\x9b\xe0\xb3G\xb1\x14\xfc\x8ar\x86\xbf\xb4rs\xce_\xb0\x0f7\x9e\xad\x9ds\xa7\xa1\x8d-\x96a(G\x14\xaa\xc3\xe8\xba\x18\xb2\xf1m\x8d\x1b\xf6\rO\x80\x83\xf3w\xec_P\xec\xc1\x87~C݈l\x8c]E\x05m|\xb2\xad\x8a\x84_\xef\x1cb2$\xec=\xfb\x05\xc1\xd0Ʊ\xad\xf0\xb7\xc0\xa8\xf1t\xaa t\\\x9c\x97*Y\x82\x8c\xfa\x17C\x88\x14RNX<\xc7\xe7\xe8\x90\x16\xb4\b\x03g\xec\\^\x87\xaeع\xf1\xc9U\xf5\x93/W\x91\xb1#\x97w\xf2\x1d\xdfK&\xfd\x8du\xfaT\aii\x8a\x175\x1b\b\xadM\xae\x1a\x18\xbeD\xedUH\xearN\x96\xc2\xc0\x9dW}\x06\x83\t\x9d\xfa\xa6\xd3s's\xce\xecG'b\x16\x86\xf4^P\x14\xa4\x86\x91\xbd\x8c\x83쾭\x99B=2\xd5\xd7\xc4e$\xdd\b\x1dy\x93-_\xb3\xce\xf9x\x05\xeac\x1e\xf3G\xf8?\xab:Gh\x9b\x1dA#\xa9T\xaa\x8d=2\xb7\xfeh\xad?J\x02\xa6Q\xf1'\x00\x00\xff\xff\f\xe6\xecL\xfb\x05\x00\x00", + local: "data/ru/male_last_names", + size: 1531, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2RU224aSxB891fjxQcdyZbCzTEi2AQHKc5TloUVeGF3f6Hnj1JdPT0DyQNaZqYv1VU1 +IwuppJRWOqnuZCpluJeTnMOT1LqxljoUYWCnG7nICYsYvMLiP+R+ytk2tmEiB+lyeCcNfvH0NxcVlrFy +J72djFHxgKzaTsYMaQDkn40yRjLtGzZ3+B0saob9k+y1v6PfhAJ/+jzfBssLUMblGieV45vgs0exFPyK +coa/tHJzzl+wDzeerZ1zp6GNLZZhKEcUqsPouhiy8W2NG/YNT4CD83fsX1DswYd+Q92IbIxdRQVtfLKt +ioRf7xxiMiTsPfsFwdDGsa3wt8Co8XSqIHRcnJcqWYKM+hdDiBRSTlg8x+fokBa0CANn7Fxeh67YufHJ +VfWTL1eRsSOXd/Id30sm/Y11+lQHaWmKFzUbCK1NrhoYvkTtVUjqck6WwsCdV30Ggwmd+qbTcydzzuxH +J2IWhvRePGlz1SUEvGffSTQ4oTVGxDvvQxcvSeR0gLrnWws8ZM8sCfFA/hIcFQJbmK3Kw2qKNmfaV0Q0 +yXUstnMj/aIcOzLX+UVToho3SkkjpCv+QcUPocAEWuqaqp/aE8hS9oRqXN2n0983fkdn2yAM7j2zdiJW +ZPSsQI21IgoDSJU/JYP8cizg6/aGIfOMt11HFQDdIyagvXEr7Ag5jjQjHUO+HJGd1ssZg7rVWG0QruJ+ +RksDwaOPvqTKNgg3PlAUpIaRvYyD7L6tmUI9MtXXxGUk3QgdeZMtX7PO+XgF6mMe80f4P6s6R2ibHUEj +qVSqjT0yt/5orT9KAqZR8ScAAP//DObsTPsFAAA= +`, }, "/data/ru/male_patronymics": { - local: "data/ru/male_patronymics", - size: 1165, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffl\x93\xcfN\xf30\x10\xc4\xef\xdfS\xb7\xfd@\xbdT\x02J+UP\xfe\x14q\x05J\x12K!N\xd2WX\xbf\x11\xb3Cpv\x1b\xd4C\xad\x9f\xc7\xeb\xf1\xecF\xae%J\x90&\xcd\xe5(\x9dTi&\xbd\x14R\xa7\xe5?\xb3\x15\xf0˰\x93cZ@\x15\xd3\xcac=\xec\x95\xd4u\xa6\"\x14\r.\xaa\xdc\xd14\x83.H;\xean\xb0,\xa5\xa2%\vq\xbc\x86\x9d\x8c\xd6P\xa8G\xbd\xa8\xb6\xdaa\x03\x95\xcdE\x808\\{\xe3k\x80F}ڗ\x03\x02\x1dϕQ\xadC\xdf\x028\xf5\xb0\x81\xea\xba*\xccV\xbaJK\xf8\x98lܪk\x8d\x92\x05\x83\xc5\xea\xa4tP\x9f\r\xd4\xfb\xe7l\x18\x0f\x9e3Vݰ\xaa\x8bhC\xb7\v\x96\xc8G\xb7X\x94\xccmea\xe9Sئ\v>6\x83\x1d\x16\xae%\xbb\xe1H\x18\x81F6,{M\x1b5\xb2\xfc\x8e\xb9\xa9\xe3h!F$͙\xf7\xa4\x8f\xf7\x9a\a_Y\x19\x88+L\x94{\x1cl\xd8\xd8\xd6A\xd4*\xec<\xee\xf1w\t헽\xfdAۯÌ\x8d\xac|\xe4P\x95\xa3\xea\x89͋\x16\x04fj@\x1c>\v\xe3\xfe\x19\xcbON\xe1\xc2\xc3\xd6\xc7x\xe0\xf4\x873\xc410\xfe\x0f?\x11\xfd5f\a~@'_\xf5\x05\x86f\x1cy\x83\x18\x12zb\xea\xbebY\xf9\xce+\x8a\xfc0\xe6\x16ք'\xfc2|÷\xfc\x9f\x17\x99\x06\xbd\xfbA\xfd`\xc2\x05C\xfdEz\xdb\xe4\x1d\xdf\x01\x00\x00\xff\xff[hP\x9b\x8d\x04\x00\x00", + local: "data/ru/male_patronymics", + size: 1165, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/2yTz07zMBDE799Tt/1AvVQCSitVUP4UcQVKEkshTtJXWL8Rs0NwdhvUQ62fx+vx7Eau +JUqQJs3lKJ1UaSa9FFKn5T+zFfDLsJNjWkAV08pjPeyV1HWmIhQNLqrc0TSDLkg76m6wLKWiJQtxvIad +jNZQqEe9qLbaYQOVzUWAOFx742uARn3alwMCHc+VUa1D3wI49bCB6roqzFa6Skv4mGzcqmuNkgWDxeqk +dFCfDdT752wYD54zVt2wqotoQ7cLlshHt1iUzG1lYelT2KYLPjaDHRauJbvhSBiBRjYse00bNbL8jrmp +42ghRiTNmfekj/eaB19ZGYgrTJR7HGzY2NZB1CrsPO7xdwntl739Qduvw4yNrHzkUJWj6onNixYEZmpA +HD4L4/4Zy09O4cLD1sd44PSHM8QxMP4PPxH9NWYHfkAnX/UFhmYceYMYEnpi6r5iWfnOK4r8MOYW1oQn +/DJ8w7f8nxeZBr37Qf1gwgVD/UV62+Qd3wEAAP//W2hQm40EAAA= +`, }, "/data/ru/months": { - local: "data/ru/months", - size: 148, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffL\x8c1\x0e\x02!\x14\x05{N\xbd\xae\xadQ\n\v\v51\xb1\x171\x14b\xd0+̻\x91\xffC\xa2\xdb1\xc3\xfbÍF&i\xd2&p\xa5\x905\x91x9\x1e\xbb\x9f\x03\x91\x8f\xd9\xf2\xb3<\x03\ami\xce\xfe\xe8\x1f\xd1B\x0f\xad\xb5\xf2\x93\x8b͛f\xed\xb8\x8f\xf6\x99\xba\xc4\x13\xef?\xecm\\-;\xf0\x1b\x00\x00\xff\xff\xe9\xeb\xb4ٔ\x00\x00\x00", + local: "data/ru/months", + size: 148, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/0yMMQ4CIRQFe069rq1RCgsLNTGxFzEUYtArzLuR/0Oi2zHD+8ONRiZp0iZwpZA1kXg5 +HrufA5GP2fKzPAMHbWnO/ugf0UIPrbXyk4vNm2btuI/2mbrEE+8/7G1cLTvwGwAA///p67TZlAAAAA== +`, }, "/data/ru/phones_format": { - local: "data/ru/phones_format", - size: 26, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffR\xd6UV\x86a \xe2B\xb0\x00\x01\x00\x00\xff\xff\xb5\xe6\x87^\x1a\x00\x00\x00", + local: "data/ru/phones_format", + size: 26, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1LWVVaGYSDiQrAAAQAA//+15odeGgAAAA== +`, }, "/data/ru/states": { - local: "data/ru/states", - size: 2756, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\x8cVKR\x1bA\f\xdds\n/\x93\x05w4C\bTA\xc5@H\x852`bS\x14\xab\x04c{`\xf0|\xb8\x82\xfa\n9I\xde{\xdd6\xa4\x98\x91Y@yZ\xaf\xf5yRK\xb2c[\x84C\x9b[\x1e\x06[\xf8(CfS{\u07b2\x13\x9b\x86\x03[Z\x13\xfa8j\u008e\x045\x04a\x17G\x03|\x16\xbcr\x86S\xde^\xcbϭ\xb690\a8L\x98!$\x0f\xd0\u05f7\x85\x15\x107\xdbTo%\xd4\xf3p\x8d)\xad\x82/\xcb\xf5\x01dӰ\x0fAn3^\xba\x83\xca>\xe4\xb0\xf6\x16\x93\xe3b\xfal\xac\xb2b\xcb.\xa3^{\xee\xd9o+\xf9\xdd\xc8x\x03=B\x8e\x01سi\xef\x93\xdd\xdb\x12\xce\xca\xd1\xcf<\xa7)Z\xa9\x81\x18\xf4l\x04S)\x8e\xde\xdf\xfeY\x8f\x141Ψf\x02PF[\xaf\xe1O\x10\xc1L\x9a'a\x97\xbf\xa0\xf5\x06\xa6+і\b\xb9\x05\x96\xb1\xa70\x18\u05fe\xd5\xfa\x19/\x81\xbd\x18\x91(x\x9b\x19\xdcY\xc6Ȗ\x941U?#\xbd\xf6L\x9d\xc0\x1d\xb5`HoE.C\xd6&\x95\x99\x1d\xa6\x06\xae*\x1e\x0f\x83\xec\xb7!\xaeE\\\xd5&Q6*\x15\xd3{\xe9X\x91\xcd\xf0\xd9\xd8\v\xfe\xda#\xb8]\x17\x11\xb2\xd8\"\x1fAZ\xd2C\x92L\xc2\"\xe3;\"\x1a\x99l^\xe5\xe1\br\xc8\xf6\x94\xc99\v(\x99lG\xf2G?V\f\xb2ԅ;Q!\xceUj\xa0\xb1\x1b\xc7\xe7\xe3\xe89U\x85-DX\xe1DpJ\xaah\x0fύ\x1ct[\x8c\xc8FX\x17%\xcfk\xc4\xf1؉:gy\xaaPf\xdd\x18\xbeR\xbe\xaaND|\xed\xec\x05\x85څ\xef\xbf\xd0x\x18\xdd^\r\xe1s\xa5\xf2\xf3\xfc\x1a\x92\xcf\r\x88&e\xbbI\x85܊be\x81M\xaf\x1a\x86n\xf5]\xc0ߏ\xc5~\x01\xd4\v\"\xfb\xda!\xbfT\xffe\xbdxް\x01R\xe6\xc5~\xa9\xa8*W\xcf\x15\xbcy\x84\uf6eb\xfcJ\xcd\xf6\xa38zW@\xe0\xd5\xfb\xc8\xc9\xc8Hc\xa0\xb6\x87\x98\x19\x17W\xba,\\K\xcf\x13\xffwc6r\xf9+ML\x17\x83.\xf0\xe4\xb2=f\xd3^\xb7\xe3\x0e\x84:\x93o)M\xbb\xf8\xe2\x1cT\x9c|\x8b\r\f\x8d\xd9\xc8q\xe014\x91\xe7\x0f\xae\x9eI\xb4\xe7Ƚ7\xc8\xe9\xeau\xedI\xf8Ǝ\xe0\xf8x\xa3\xfb\x83\r\xbd\xecN\xd3a\xc0\xdattݳ\xca!-5ȺP\xdfW\xaf\x01\xfbA\xf8\x02\xc5\v\x11\xae\x99-7\xf0\\z\xa8\x89ZkO\xbe\xda2V\x8f\x17\x8d7\xd6D\x8d\xee\x9amk\xdefҐ\xca~\xb5\xbfLS\xed\xa5a\xcaa8\xd3A\xad\x05\xa9nu\xee\x87&p\x9e6\f!\x8em\xf4\xee.֛\x9cw1w\x91\x819]\xba\x92\xab\xb1Ei&\xebޭJ;\v\x87\xdb\xeaQ\xb5^\xf8\x9b\xf5\x05\xa0\xb8Q\xfd\x89=0\xee>\\8\xb3\xff@ WM\xa9\xe4\x06\xd8j\xea_\x00\x00\x00\xff\xff\x9du\x89T\xc4\n\x00\x00", + local: "data/ru/states", + size: 2756, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/4xWS1IbQQzdcwovkwV3NEMIVEHFQEiFMmBiUxSrBGN7YPB8uIL6CjlJ3nvdNqSYkVlA +eVqv9XlSS7JjW4RDm1seBlv4KENmU3veshObhgNbWhP6OGrCjgQ1BGEXRwN8FrxyhlPeXsvPrbY5MAc4 +TJghJA/Q17eFFRA321RvJdTzcI0prYIvy/UBZNOwD0FuM166g8o+5LD2FpPjYvpsrLJiyy6jXnvu2W8r ++d3IeAM9Qo4B2LNp75Pd2xLOytHPPKcpWqmBGPRsBFMpjt7f/lmPFDHOqGYCUEZbr+FPEMFMmidhl7+g +9QamK9GWCLkFlrGnMBjXvtX6GS+BvRiRKHibGdxZxsiWlDFVPyO99kydwB21YEhvRS5D1iaVmR2mBq4q +Hg+D7LchrkVc1SZRNioV03vpWJHN8NnYC/7aI7hdFxGy2CIfQVrSQ5JMwiLjOyIamWxe5eEIcsj2lMk5 +CyiZbEfyRz9WDLLUhTtRIc5VaqCxG8fn4+g5VYUtRFjhRHBKqmgPz40cdFuMyEZYFyXPa8Tx2Ik6Z3mq +UGbdGL5SvqpORHzt7AWF2oXvv9B4GN1eDeFzpfLz/BqSzw2IJmW7SYXcimJlgU2vGoZu9V3A34/FfgHU +CyL72iG/VP9lvXjesAFS5sV+qagqV88VvHmE75ur/ErN9qM4eldA4NX7yMnISGOgtoeYGRdXuixcS88T +/3djNnL5K01MF4Mu8OSyPWbTXrfjDoQ6k28pTbv44hxUnHyLDQyN2chx4DE0kecPrp5JtOfIvTfI6ep1 +7Un4xo7g+Hij+4MNvexO02HA2nR03bPKIS01yLpQ31evAftB+ALFCxGumS038Fx6qIlaa0++2jJWjxeN +N9ZEje6abWveZtKQyn61v0xT7aVhymE400GtBalude6HJnCeNgwhjm307i7Wm5x3MXeRgTldupKrsUVp +JuverUo7C4fb6lG1Xvib9QWguFH9iT0w7j5cOLP/QCBXTankBthq6l8AAAD//511iVTECgAA +`, }, "/data/ru/streets": { - local: "data/ru/streets", - size: 694, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\\\x92\xcbn\xf2@\f\x85\xf7\x1a\x94\xad\xb3\xa5k\xad\xad۹\xc9\xca;8Ee\x1b\xfd\xe3\xfb\x9cR\x0f\xac\x97\x84\x1b\x9c\xe4=Ǫe&w\x1c\x9b66\xc6^/\xabF8\xd1s\xb4^\x1b\xeb\xc71\x98\xf0\xe4=\xf5\xaa:\xe4\xef\xf7\"st\xe3\xa9xu\x1ce\xae\x979\xe7\xdeU\xfa\x01\x1a@\x84\xf8d\xe2\xc6'\x8cf=Q\x96x\u007f\x02\x00\x00\xff\xff#>\x03\x17\xb6\x02\x00\x00", + local: "data/ru/streets", + size: 694, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1ySy27yQAyF9zx1Avr1VwIJ9aJWCqUpm7YrFC4DCSnhFY7fqMfOTD3qIkG2D/bn4+AD +AVeZSoEGvSxwRSPLCV4xoOdzZPmUkl+4aNpVG4Z7BP69ZMlSK4Zlqq+tHqUNm/2Ga4Y7Sou8/wt/mJD/ +TtEqmHVlrtW8ygLZQhLVhhpS55XMcPBBb7gQb4mdFLJwzIqKb4Z8jyt56ZFoByOJ82rj3Ju2QefKjU3V +YvJDpkzdcnt6BtlGlW1kdBNsffWawwaTFt7/PhqUrbOla62t27nJyjs4RWUb/eP7nFIPrJeEG5zkPceq +ZSZ3HJs2NsZeL6tGONFztF4b68cxmPDkPfWqOuTv9yJzdOOpeHUcZa6XOefeVfoBGkCE+GTixieMZj1R +lnh/AgAA//8jPgMXtgIAAA== +`, }, "/data/ru/weekdays": { - local: "data/ru/weekdays", - size: 117, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xff4\x8d;\n\x031\fD{\x9d\xdaI U \xe0\v\x18Wi\xb3\x1f\xc1\xe2\xc5>\xc3Ӎv\\,\xc6\xd2<\xcd\bQ\x18t\x9c]\xff\x8c\x8f\xf4A3r<\x19\x91n\xac\x923\xf37~\xb8\xbcU5\xb1\x19%\xbeB\xc5\xe2=\xdd\x1a/\x16\xbd\xa1\xa10K\x98{a#H\xa2\x91\v\x10\x00\x00\xff\xff\xber!\xd8#\x00\x00\x00", + local: "data/ru/weekdays_short", + size: 35, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/7ow/8JerguTLjZxXVh4sYHrwnIQaz6Ye2EjSKKRCxAAAP//vnIh2CMAAAA= +`, }, "/data/ru/zips_format": { - local: "data/ru/zips_format", - size: 8, - compressed: "\x1f\x8b\b\x00\x00\tn\x88\x00\xffR\x86\x00.@\x00\x00\x00\xff\xff\x87\xdd'=\b\x00\x00\x00", + local: "data/ru/zips_format", + size: 8, + modtime: 1464022103, + compressed: ` +H4sIAAAJbogA/1KGAC5AAAAA//+H3Sc9CAAAAA== +`, }, "/": { isDir: true, + local: "/", }, "/data": { isDir: true, + local: "/data", }, "/data/en": { isDir: true, + local: "/data/en", }, "/data/ru": { isDir: true, + local: "/data/ru", }, } diff --git a/vendor/github.com/icrowley/fake/fake.go b/vendor/github.com/icrowley/fake/fake.go index df3cb77c0..b9ada47a6 100644 --- a/vendor/github.com/icrowley/fake/fake.go +++ b/vendor/github.com/icrowley/fake/fake.go @@ -93,7 +93,7 @@ func (s *rndSrc) Seed(n int64) { // GetLangs returns a slice of available languages func GetLangs() []string { var langs []string - for k, v := range data { + for k, v := range _escData { if v.isDir && k != "/" && k != "/data" { langs = append(langs, strings.Replace(k, "/data/", "", 1)) } diff --git a/vendor/github.com/icrowley/fake/glide.lock b/vendor/github.com/icrowley/fake/glide.lock deleted file mode 100644 index 515144a38..000000000 --- a/vendor/github.com/icrowley/fake/glide.lock +++ /dev/null @@ -1,6 +0,0 @@ -hash: 9238b15272824ad573d8ef645fb468cb646b72598c63eae8977c3410ebfebe4a -updated: 2017-07-23T15:10:00.972860398Z -imports: -- name: github.com/corpix/uarand - version: 031be390f409fb4bac8fb299e3bcd101479f89f8 -testImports: [] diff --git a/vendor/github.com/icrowley/fake/glide.yaml b/vendor/github.com/icrowley/fake/glide.yaml deleted file mode 100644 index 93f9bfae3..000000000 --- a/vendor/github.com/icrowley/fake/glide.yaml +++ /dev/null @@ -1,3 +0,0 @@ -package: github.com/icrowley/fake -import: -- package: github.com/corpix/uarand diff --git a/vendor/github.com/icrowley/fake/nix-cage.json b/vendor/github.com/icrowley/fake/nix-cage.json new file mode 100644 index 000000000..f6abd3af9 --- /dev/null +++ b/vendor/github.com/icrowley/fake/nix-cage.json @@ -0,0 +1,23 @@ +{ + "mounts": { + "rw": [ + ".", "~/.emacs.d", + ["./.cache", "~/.cache", "d"], + ["./.config", "~/.config", "d"], + ["./.local", "~/.local", "d"], + ["$SSH_AUTH_SOCK", "$SSH_AUTH_SOCK"], + "/run" + ], + "ro": [ + "~/.ssh", + "~/.gitconfig", + "/" + ], + "dev": ["/dev"], + "tmpfs": [ + "/tmp", + "/home", + "~" + ] + } +} diff --git a/vendor/github.com/icrowley/fake/shell.nix b/vendor/github.com/icrowley/fake/shell.nix new file mode 100644 index 000000000..1aba19b56 --- /dev/null +++ b/vendor/github.com/icrowley/fake/shell.nix @@ -0,0 +1,38 @@ +let + inherit (pkgs) + writeScript + stdenv + ; + + nixpkgs = ; + config = {}; + pkgs = import nixpkgs { inherit config; }; + + shellWrapper = writeScript "shell-wrapper" '' + #! ${stdenv.shell} + set -e + + exec -a shell ${pkgs.fish}/bin/fish --login --interactive "$@" + ''; +in stdenv.mkDerivation rec { + name = "nix-shell"; + buildInputs = with pkgs; [ + glibcLocales bashInteractive man + nix cacert curl utillinux coreutils + git jq yq-go tmux findutils gnumake + + go gopls golangci-lint + ]; + shellHook = '' + export root=$(pwd) + + export LANG="en_US.UTF-8" + export NIX_PATH="nixpkgs=${nixpkgs}" + + if [ ! -z "$PS1" ] + then + export SHELL="${shellWrapper}" + exec "$SHELL" + fi + ''; +} diff --git a/vendor/github.com/inconshreveable/mousetrap/LICENSE b/vendor/github.com/inconshreveable/mousetrap/LICENSE index 5f0d1fb6a..5f920e973 100644 --- a/vendor/github.com/inconshreveable/mousetrap/LICENSE +++ b/vendor/github.com/inconshreveable/mousetrap/LICENSE @@ -1,13 +1,201 @@ -Copyright 2014 Alan Shreve + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Alan Shreve (@inconshreveable) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_others.go b/vendor/github.com/inconshreveable/mousetrap/trap_others.go index 9d2d8a4ba..06a91f086 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_others.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_others.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package mousetrap diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go index 336142a5e..0c5688021 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go @@ -1,81 +1,32 @@ -// +build windows -// +build !go1.4 - package mousetrap import ( - "fmt" - "os" "syscall" "unsafe" ) -const ( - // defined by the Win32 API - th32cs_snapprocess uintptr = 0x2 -) - -var ( - kernel = syscall.MustLoadDLL("kernel32.dll") - CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot") - Process32First = kernel.MustFindProc("Process32FirstW") - Process32Next = kernel.MustFindProc("Process32NextW") -) - -// ProcessEntry32 structure defined by the Win32 API -type processEntry32 struct { - dwSize uint32 - cntUsage uint32 - th32ProcessID uint32 - th32DefaultHeapID int - th32ModuleID uint32 - cntThreads uint32 - th32ParentProcessID uint32 - pcPriClassBase int32 - dwFlags uint32 - szExeFile [syscall.MAX_PATH]uint16 -} - -func getProcessEntry(pid int) (pe *processEntry32, err error) { - snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) - if snapshot == uintptr(syscall.InvalidHandle) { - err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1) - return +func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { + snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err } - defer syscall.CloseHandle(syscall.Handle(snapshot)) - - var processEntry processEntry32 - processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) - ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32First: %v", e1) - return + defer syscall.CloseHandle(snapshot) + var procEntry syscall.ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = syscall.Process32First(snapshot, &procEntry); err != nil { + return nil, err } - for { - if processEntry.th32ProcessID == uint32(pid) { - pe = &processEntry - return + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil } - - ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32Next: %v", e1) - return + err = syscall.Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err } } } -func getppid() (pid int, err error) { - pe, err := getProcessEntry(os.Getpid()) - if err != nil { - return - } - - pid = int(pe.th32ParentProcessID) - return -} - // StartedByExplorer returns true if the program was invoked by the user double-clicking // on the executable from explorer.exe // @@ -83,16 +34,9 @@ func getppid() (pid int, err error) { // It does not guarantee that the program was run from a terminal. It only can tell you // whether it was launched from explorer.exe func StartedByExplorer() bool { - ppid, err := getppid() + pe, err := getProcessEntry(syscall.Getppid()) if err != nil { return false } - - pe, err := getProcessEntry(ppid) - if err != nil { - return false - } - - name := syscall.UTF16ToString(pe.szExeFile[:]) - return name == "explorer.exe" + return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) } diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go deleted file mode 100644 index 9a28e57c3..000000000 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build windows -// +build go1.4 - -package mousetrap - -import ( - "os" - "syscall" - "unsafe" -) - -func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { - snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) - if err != nil { - return nil, err - } - defer syscall.CloseHandle(snapshot) - var procEntry syscall.ProcessEntry32 - procEntry.Size = uint32(unsafe.Sizeof(procEntry)) - if err = syscall.Process32First(snapshot, &procEntry); err != nil { - return nil, err - } - for { - if procEntry.ProcessID == uint32(pid) { - return &procEntry, nil - } - err = syscall.Process32Next(snapshot, &procEntry) - if err != nil { - return nil, err - } - } -} - -// StartedByExplorer returns true if the program was invoked by the user double-clicking -// on the executable from explorer.exe -// -// It is conservative and returns false if any of the internal calls fail. -// It does not guarantee that the program was run from a terminal. It only can tell you -// whether it was launched from explorer.exe -func StartedByExplorer() bool { - pe, err := getProcessEntry(os.Getppid()) - if err != nil { - return false - } - return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) -} diff --git a/vendor/github.com/kardianos/osext/README.md b/vendor/github.com/kardianos/osext/README.md index 61350baba..15cbc3d95 100644 --- a/vendor/github.com/kardianos/osext/README.md +++ b/vendor/github.com/kardianos/osext/README.md @@ -1,7 +1,12 @@ ### Extensions to the "os" package. +[![GoDoc](https://godoc.org/github.com/kardianos/osext?status.svg)](https://godoc.org/github.com/kardianos/osext) + ## Find the current Executable and ExecutableFolder. +As of go1.8 the Executable function may be found in `os`. The Executable function +in the std lib `os` package is used if available. + There is sometimes utility in finding the current executable file that is running. This can be used for upgrading the current executable or finding resources located relative to the executable file. Both diff --git a/vendor/github.com/kardianos/osext/osext_go18.go b/vendor/github.com/kardianos/osext/osext_go18.go new file mode 100644 index 000000000..009d8a926 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_go18.go @@ -0,0 +1,9 @@ +//+build go1.8,!openbsd + +package osext + +import "os" + +func executable() (string, error) { + return os.Executable() +} diff --git a/vendor/github.com/kardianos/osext/osext_plan9.go b/vendor/github.com/kardianos/osext/osext_plan9.go index 655750c54..95e237137 100644 --- a/vendor/github.com/kardianos/osext/osext_plan9.go +++ b/vendor/github.com/kardianos/osext/osext_plan9.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//+build !go1.8 + package osext import ( diff --git a/vendor/github.com/kardianos/osext/osext_procfs.go b/vendor/github.com/kardianos/osext/osext_procfs.go index d59847ee5..e1f16f885 100644 --- a/vendor/github.com/kardianos/osext/osext_procfs.go +++ b/vendor/github.com/kardianos/osext/osext_procfs.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux netbsd solaris dragonfly +// +build !go1.8,android !go1.8,linux !go1.8,netbsd !go1.8,solaris !go1.8,dragonfly package osext @@ -16,7 +16,7 @@ import ( func executable() (string, error) { switch runtime.GOOS { - case "linux": + case "linux", "android": const deletedTag = " (deleted)" execpath, err := os.Readlink("/proc/self/exe") if err != nil { diff --git a/vendor/github.com/kardianos/osext/osext_sysctl.go b/vendor/github.com/kardianos/osext/osext_sysctl.go index 66da0bcf9..33cee2522 100644 --- a/vendor/github.com/kardianos/osext/osext_sysctl.go +++ b/vendor/github.com/kardianos/osext/osext_sysctl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin freebsd openbsd +// +build !go1.8,darwin !go1.8,freebsd openbsd package osext diff --git a/vendor/github.com/kardianos/osext/osext_windows.go b/vendor/github.com/kardianos/osext/osext_windows.go index 72d282cf8..074b3b385 100644 --- a/vendor/github.com/kardianos/osext/osext_windows.go +++ b/vendor/github.com/kardianos/osext/osext_windows.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//+build !go1.8 + package osext import ( diff --git a/vendor/github.com/magiconair/properties/.gitignore b/vendor/github.com/magiconair/properties/.gitignore index 7054822dc..e7081ff52 100644 --- a/vendor/github.com/magiconair/properties/.gitignore +++ b/vendor/github.com/magiconair/properties/.gitignore @@ -2,3 +2,5 @@ *.sublime-workspace *.un~ *.swp +.idea/ +*.iml diff --git a/vendor/github.com/magiconair/properties/.travis.yml b/vendor/github.com/magiconair/properties/.travis.yml deleted file mode 100644 index 5ef5d72f3..000000000 --- a/vendor/github.com/magiconair/properties/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: go -go: - - 1.4.3 - - 1.5.3 - - 1.6 - - tip diff --git a/vendor/github.com/magiconair/properties/CHANGELOG.md b/vendor/github.com/magiconair/properties/CHANGELOG.md deleted file mode 100644 index bf49a1376..000000000 --- a/vendor/github.com/magiconair/properties/CHANGELOG.md +++ /dev/null @@ -1,81 +0,0 @@ -## Changelog - -### [1.7.0](https://github.com/magiconair/properties/tags/v1.7.0) - 20 Mar 2016 - - * [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#Properties.LoadURL) method to load properties from a URL. - * [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#Properties.LoadString) method to load properties from an UTF8 string. - * [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe) - -### [1.6.0](https://github.com/magiconair/properties/tags/v1.6.0) - 11 Dec 2015 - - * Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags. - -### [1.5.6](https://github.com/magiconair/properties/tags/v1.5.6) - 18 Oct 2015 - - * Vendored in gopkg.in/check.v1 - -### [1.5.5](https://github.com/magiconair/properties/tags/v1.5.5) - 31 Jul 2015 - - * [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs) - -### [1.5.4](https://github.com/magiconair/properties/tags/v1.5.4) - 23 Jun 2015 - - * [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references. - -### [1.5.3](https://github.com/magiconair/properties/tags/v1.5.3) - 02 Jun 2015 - - * [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) - -### [1.5.2](https://github.com/magiconair/properties/tags/v1.5.2) - 10 Apr 2015 - - * [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty - * Add clickable links to README - -### [1.5.1](https://github.com/magiconair/properties/tags/v1.5.1) - 08 Dec 2014 - - * Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with - [time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration). - -### [1.5.0](https://github.com/magiconair/properties/tags/v1.5.0) - 18 Nov 2014 - - * Added support for single and multi-line comments (reading, writing and updating) - * The order of keys is now preserved - * Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry - * Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method - * Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1) - -### [1.4.2](https://github.com/magiconair/properties/tags/v1.4.2) - 15 Nov 2014 - - * [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one - -### [1.4.1](https://github.com/magiconair/properties/tags/v1.4.1) - 13 Nov 2014 - - * [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string - -### [1.4.0](https://github.com/magiconair/properties/tags/v1.4.0) - 23 Sep 2014 - - * Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys - * Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties - -### [1.3.0](https://github.com/magiconair/properties/tags/v1.3.0) - 18 Mar 2014 - -* Added support for time.Duration -* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tags/vior configurable (log.Fatal, panic) - custom) -* Changed default of MustXXX() failure from panic to log.Fatal - -### [1.2.0](https://github.com/magiconair/properties/tags/v1.2.0) - 05 Mar 2014 - -* Added MustGet... functions -* Added support for int and uint with range checks on 32 bit platforms - -### [1.1.0](https://github.com/magiconair/properties/tags/v1.1.0) - 20 Jan 2014 - -* Renamed from goproperties to properties -* Added support for expansion of environment vars in - filenames and value expressions -* Fixed bug where value expressions were not at the - start of the string - -### [1.0.0](https://github.com/magiconair/properties/tags/v1.0.0) - 7 Jan 2014 - -* Initial release diff --git a/vendor/github.com/magiconair/properties/LICENSE b/vendor/github.com/magiconair/properties/LICENSE.md similarity index 84% rename from vendor/github.com/magiconair/properties/LICENSE rename to vendor/github.com/magiconair/properties/LICENSE.md index 7eab43b6b..79c87e3e6 100644 --- a/vendor/github.com/magiconair/properties/LICENSE +++ b/vendor/github.com/magiconair/properties/LICENSE.md @@ -1,15 +1,14 @@ -goproperties - properties file decoder for Go - -Copyright (c) 2013-2014 - Frank Schroeder +Copyright (c) 2013-2020, Frank Schroeder All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, + + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. diff --git a/vendor/github.com/magiconair/properties/README.md b/vendor/github.com/magiconair/properties/README.md index 1ae0035a0..4872685f4 100644 --- a/vendor/github.com/magiconair/properties/README.md +++ b/vendor/github.com/magiconair/properties/README.md @@ -1,7 +1,8 @@ -Overview [![Build Status](https://travis-ci.org/magiconair/properties.svg?branch=master)](https://travis-ci.org/magiconair/properties) -======== +[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases) +[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE) +[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) -#### Current version: 1.7.0 +# Overview properties is a Go library for reading and writing properties files. @@ -25,8 +26,9 @@ changed from `panic` to `log.Fatal` but this is configurable and custom error handling functions can be provided. See the package documentation for details. -Getting Started ---------------- +Read the full documentation on [![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties) + +## Getting Started ```go import ( @@ -35,13 +37,38 @@ import ( ) func main() { + // init from a file p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8) - // via getters + // or multiple files + p = properties.MustLoadFiles([]string{ + "${HOME}/config.properties", + "${HOME}/config-${USER}.properties", + }, properties.UTF8, true) + + // or from a map + p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"}) + + // or from a string + p = properties.MustLoadString("key=value\nabc=def") + + // or from a URL + p = properties.MustLoadURL("http://host/path") + + // or from multiple URLs + p = properties.MustLoadURL([]string{ + "http://host/config", + "http://host/config-${USER}", + }, true) + + // or from flags + p.MustFlag(flag.CommandLine) + + // get values through getters host := p.MustGetString("host") port := p.GetInt("port", 8080) - // or via decode + // or through Decode type Config struct { Host string `properties:"host"` Port int `properties:"port,default=9000"` @@ -52,30 +79,20 @@ func main() { if err := p.Decode(&cfg); err != nil { log.Fatal(err) } - - // or via flags - p.MustFlag(flag.CommandLine) - - // or via url - p = properties.MustLoadURL("http://host/path") } ``` -Read the full documentation on [GoDoc](https://godoc.org/github.com/magiconair/properties) [![GoDoc](https://godoc.org/github.com/magiconair/properties?status.png)](https://godoc.org/github.com/magiconair/properties) - -Installation and Upgrade ------------------------- +## Installation and Upgrade ``` $ go get -u github.com/magiconair/properties ``` -License -------- +## License 2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details. -ToDo ----- +## ToDo + * Dump contents with passwords and secrets obscured diff --git a/vendor/github.com/magiconair/properties/decode.go b/vendor/github.com/magiconair/properties/decode.go index b989e6397..f5e252f8d 100644 --- a/vendor/github.com/magiconair/properties/decode.go +++ b/vendor/github.com/magiconair/properties/decode.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -48,49 +48,49 @@ import ( // // Examples: // -// // Field is ignored. -// Field int `properties:"-"` +// // Field is ignored. +// Field int `properties:"-"` // -// // Field is assigned value of 'Field'. -// Field int +// // Field is assigned value of 'Field'. +// Field int // -// // Field is assigned value of 'myName'. -// Field int `properties:"myName"` +// // Field is assigned value of 'myName'. +// Field int `properties:"myName"` // -// // Field is assigned value of key 'myName' and has a default -// // value 15 if the key does not exist. -// Field int `properties:"myName,default=15"` +// // Field is assigned value of key 'myName' and has a default +// // value 15 if the key does not exist. +// Field int `properties:"myName,default=15"` // -// // Field is assigned value of key 'Field' and has a default -// // value 15 if the key does not exist. -// Field int `properties:",default=15"` +// // Field is assigned value of key 'Field' and has a default +// // value 15 if the key does not exist. +// Field int `properties:",default=15"` // -// // Field is assigned value of key 'date' and the date -// // is in format 2006-01-02 -// Field time.Time `properties:"date,layout=2006-01-02"` +// // Field is assigned value of key 'date' and the date +// // is in format 2006-01-02 +// Field time.Time `properties:"date,layout=2006-01-02"` // -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas. -// Field []string +// // Field is assigned the non-empty and whitespace trimmed +// // values of key 'Field' split by commas. +// Field []string // -// // Field is assigned the non-empty and whitespace trimmed -// // values of key 'Field' split by commas and has a default -// // value ["a", "b", "c"] if the key does not exist. -// Field []string `properties:",default=a;b;c"` +// // Field is assigned the non-empty and whitespace trimmed +// // values of key 'Field' split by commas and has a default +// // value ["a", "b", "c"] if the key does not exist. +// Field []string `properties:",default=a;b;c"` // -// // Field is decoded recursively with "Field." as key prefix. -// Field SomeStruct +// // Field is decoded recursively with "Field." as key prefix. +// Field SomeStruct // -// // Field is decoded recursively with "myName." as key prefix. -// Field SomeStruct `properties:"myName"` +// // Field is decoded recursively with "myName." as key prefix. +// Field SomeStruct `properties:"myName"` // -// // Field is decoded recursively with "Field." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string +// // Field is decoded recursively with "Field." as key prefix +// // and the next dotted element of the key as map key. +// Field map[string]string // -// // Field is decoded recursively with "myName." as key prefix -// // and the next dotted element of the key as map key. -// Field map[string]string `properties:"myName"` +// // Field is decoded recursively with "myName." as key prefix +// // and the next dotted element of the key as map key. +// Field map[string]string `properties:"myName"` func (p *Properties) Decode(x interface{}) error { t, v := reflect.TypeOf(x), reflect.ValueOf(x) if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct { @@ -158,16 +158,16 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle // keydef returns the property key and the default value based on the // name of the struct field and the options in the tag. keydef := func(f reflect.StructField) (string, *string, map[string]string) { - key, opts := parseTag(f.Tag.Get("properties")) + _key, _opts := parseTag(f.Tag.Get("properties")) - var def *string - if d, ok := opts["default"]; ok { - def = &d + var _def *string + if d, ok := _opts["default"]; ok { + _def = &d } - if key != "" { - return key, def, opts + if _key != "" { + return _key, _def, _opts } - return f.Name, def, opts + return f.Name, _def, _opts } switch { @@ -189,12 +189,12 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle for i := 0; i < v.NumField(); i++ { fv := v.Field(i) fk, def, opts := keydef(t.Field(i)) - if !fv.CanSet() { - return fmt.Errorf("cannot set ", t.Field(i).Name) - } if fk == "-" { continue } + if !fv.CanSet() { + return fmt.Errorf("cannot set %s", t.Field(i).Name) + } if key != "" { fk = key + "." + fk } @@ -223,7 +223,7 @@ func dec(p *Properties, key string, def *string, opts map[string]string, v refle case isMap(t): valT := t.Elem() m := reflect.MakeMap(t) - for postfix, _ := range p.FilterStripPrefix(key + ".").m { + for postfix := range p.FilterStripPrefix(key + ".").m { pp := strings.SplitN(postfix, ".", 2) mk, mv := pp[0], reflect.New(valT) if err := dec(p, key+"."+mk, nil, nil, mv); err != nil { @@ -274,7 +274,6 @@ func isArray(t reflect.Type) bool { return t.Kind() == reflect.Array || t.Kin func isBool(t reflect.Type) bool { return t.Kind() == reflect.Bool } func isDuration(t reflect.Type) bool { return t == reflect.TypeOf(time.Second) } func isMap(t reflect.Type) bool { return t.Kind() == reflect.Map } -func isNumeric(t reflect.Type) bool { return isInt(t) || isUint(t) || isFloat(t) } func isPtr(t reflect.Type) bool { return t.Kind() == reflect.Ptr } func isString(t reflect.Type) bool { return t.Kind() == reflect.String } func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } diff --git a/vendor/github.com/magiconair/properties/doc.go b/vendor/github.com/magiconair/properties/doc.go index ed1ff510a..7c7979315 100644 --- a/vendor/github.com/magiconair/properties/doc.go +++ b/vendor/github.com/magiconair/properties/doc.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -13,7 +13,7 @@ // // To load a single properties file use MustLoadFile(): // -// p := properties.MustLoadFile(filename, properties.UTF8) +// p := properties.MustLoadFile(filename, properties.UTF8) // // To load multiple properties files use MustLoadFiles() // which loads the files in the given order and merges the @@ -23,25 +23,25 @@ // Filenames can contain environment variables which are expanded // before loading. // -// f1 := "/etc/myapp/myapp.conf" -// f2 := "/home/${USER}/myapp.conf" -// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) +// f1 := "/etc/myapp/myapp.conf" +// f2 := "/home/${USER}/myapp.conf" +// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) // // All of the different key/value delimiters ' ', ':' and '=' are // supported as well as the comment characters '!' and '#' and // multi-line values. // -// ! this is a comment -// # and so is this +// ! this is a comment +// # and so is this // -// # the following expressions are equal -// key value -// key=value -// key:value -// key = value -// key : value -// key = val\ -// ue +// # the following expressions are equal +// key value +// key=value +// key:value +// key = value +// key : value +// key = val\ +// ue // // Properties stores all comments preceding a key and provides // GetComments() and SetComments() methods to retrieve and @@ -55,62 +55,62 @@ // and malformed expressions are not allowed and cause an // error. Expansion of environment variables is supported. // -// # standard property -// key = value +// # standard property +// key = value // -// # property expansion: key2 = value -// key2 = ${key} +// # property expansion: key2 = value +// key2 = ${key} // -// # recursive expansion: key3 = value -// key3 = ${key2} +// # recursive expansion: key3 = value +// key3 = ${key2} // -// # circular reference (error) -// key = ${key} +// # circular reference (error) +// key = ${key} // -// # malformed expression (error) -// key = ${ke +// # malformed expression (error) +// key = ${ke // -// # refers to the users' home dir -// home = ${HOME} +// # refers to the users' home dir +// home = ${HOME} // -// # local key takes precendence over env var: u = foo -// USER = foo -// u = ${USER} +// # local key takes precedence over env var: u = foo +// USER = foo +// u = ${USER} // // The default property expansion format is ${key} but can be // changed by setting different pre- and postfix values on the // Properties object. // -// p := properties.NewProperties() -// p.Prefix = "#[" -// p.Postfix = "]#" +// p := properties.NewProperties() +// p.Prefix = "#[" +// p.Postfix = "]#" // // Properties provides convenience functions for getting typed // values with default values if the key does not exist or the // type conversion failed. // -// # Returns true if the value is either "1", "on", "yes" or "true" -// # Returns false for every other value and the default value if -// # the key does not exist. -// v = p.GetBool("key", false) +// # Returns true if the value is either "1", "on", "yes" or "true" +// # Returns false for every other value and the default value if +// # the key does not exist. +// v = p.GetBool("key", false) // -// # Returns the value if the key exists and the format conversion -// # was successful. Otherwise, the default value is returned. -// v = p.GetInt64("key", 999) -// v = p.GetUint64("key", 999) -// v = p.GetFloat64("key", 123.0) -// v = p.GetString("key", "def") -// v = p.GetDuration("key", 999) +// # Returns the value if the key exists and the format conversion +// # was successful. Otherwise, the default value is returned. +// v = p.GetInt64("key", 999) +// v = p.GetUint64("key", 999) +// v = p.GetFloat64("key", 123.0) +// v = p.GetString("key", "def") +// v = p.GetDuration("key", 999) // -// As an alterantive properties may be applied with the standard +// As an alternative properties may be applied with the standard // library's flag implementation at any time. // -// # Standard configuration -// v = flag.Int("key", 999, "help message") -// flag.Parse() +// # Standard configuration +// v = flag.Int("key", 999, "help message") +// flag.Parse() // -// # Merge p into the flag set -// p.MustFlag(flag.CommandLine) +// # Merge p into the flag set +// p.MustFlag(flag.CommandLine) // // Properties provides several MustXXX() convenience functions // which will terminate the app if an error occurs. The behavior @@ -119,30 +119,30 @@ // of logging the error set a different ErrorHandler before // you use the Properties package. // -// properties.ErrorHandler = properties.PanicHandler +// properties.ErrorHandler = properties.PanicHandler // -// # Will panic instead of logging an error -// p := properties.MustLoadFile("config.properties") +// # Will panic instead of logging an error +// p := properties.MustLoadFile("config.properties") // // You can also provide your own ErrorHandler function. The only requirement // is that the error handler function must exit after handling the error. // -// properties.ErrorHandler = func(err error) { -// fmt.Println(err) -// os.Exit(1) -// } +// properties.ErrorHandler = func(err error) { +// fmt.Println(err) +// os.Exit(1) +// } // -// # Will write to stdout and then exit -// p := properties.MustLoadFile("config.properties") +// # Will write to stdout and then exit +// p := properties.MustLoadFile("config.properties") // // Properties can also be loaded into a struct via the `Decode` // method, e.g. // -// type S struct { -// A string `properties:"a,default=foo"` -// D time.Duration `properties:"timeout,default=5s"` -// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` -// } +// type S struct { +// A string `properties:"a,default=foo"` +// D time.Duration `properties:"timeout,default=5s"` +// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` +// } // // See `Decode()` method for the full documentation. // @@ -152,5 +152,4 @@ // http://en.wikipedia.org/wiki/.properties // // http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 -// package properties diff --git a/vendor/github.com/magiconair/properties/integrate.go b/vendor/github.com/magiconair/properties/integrate.go index 37baaad95..35d0ae97b 100644 --- a/vendor/github.com/magiconair/properties/integrate.go +++ b/vendor/github.com/magiconair/properties/integrate.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -10,8 +10,9 @@ import "flag" // the respective key for flag.Flag.Name. // // It's use is recommended with command line arguments as in: -// flag.Parse() -// p.MustFlag(flag.CommandLine) +// +// flag.Parse() +// p.MustFlag(flag.CommandLine) func (p *Properties) MustFlag(dst *flag.FlagSet) { m := make(map[string]*flag.Flag) dst.VisitAll(func(f *flag.Flag) { diff --git a/vendor/github.com/magiconair/properties/lex.go b/vendor/github.com/magiconair/properties/lex.go index 014e63f0e..3d15a1f6e 100644 --- a/vendor/github.com/magiconair/properties/lex.go +++ b/vendor/github.com/magiconair/properties/lex.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -72,7 +72,7 @@ type lexer struct { // next returns the next rune in the input. func (l *lexer) next() rune { - if int(l.pos) >= len(l.input) { + if l.pos >= len(l.input) { l.width = 0 return eof } @@ -96,8 +96,8 @@ func (l *lexer) backup() { // emit passes an item back to the client. func (l *lexer) emit(t itemType) { - item := item{t, l.start, string(l.runes)} - l.items <- item + i := item{t, l.start, string(l.runes)} + l.items <- i l.start = l.pos l.runes = l.runes[:0] } @@ -114,7 +114,7 @@ func (l *lexer) appendRune(r rune) { // accept consumes the next rune if it's from the valid set. func (l *lexer) accept(valid string) bool { - if strings.IndexRune(valid, l.next()) >= 0 { + if strings.ContainsRune(valid, l.next()) { return true } l.backup() @@ -123,23 +123,11 @@ func (l *lexer) accept(valid string) bool { // acceptRun consumes a run of runes from the valid set. func (l *lexer) acceptRun(valid string) { - for strings.IndexRune(valid, l.next()) >= 0 { + for strings.ContainsRune(valid, l.next()) { } l.backup() } -// acceptRunUntil consumes a run of runes up to a terminator. -func (l *lexer) acceptRunUntil(term rune) { - for term != l.next() { - } - l.backup() -} - -// hasText returns true if the current parsed text is not empty. -func (l *lexer) isNotEmpty() bool { - return l.pos > l.start -} - // lineNumber reports which line we're on, based on the position of // the previous item returned by nextItem. Doing it this way // means we don't have to worry about peek double counting. @@ -156,9 +144,9 @@ func (l *lexer) errorf(format string, args ...interface{}) stateFn { // nextItem returns the next item from the input. func (l *lexer) nextItem() item { - item := <-l.items - l.lastPos = item.pos - return item + i := <-l.items + l.lastPos = i.pos + return i } // lex creates a new scanner for the input string. @@ -196,9 +184,8 @@ func lexBeforeKey(l *lexer) stateFn { return lexComment case isWhitespace(r): - l.acceptRun(whitespace) l.ignore() - return lexKey + return lexBeforeKey default: l.backup() @@ -279,8 +266,7 @@ func lexValue(l *lexer) stateFn { for { switch r := l.next(); { case isEscape(r): - r := l.peek() - if isEOL(r) { + if isEOL(l.peek()) { l.next() l.acceptRun(whitespace) } else { diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go index 3915c7397..6567e0c71 100644 --- a/vendor/github.com/magiconair/properties/load.go +++ b/vendor/github.com/magiconair/properties/load.go @@ -1,13 +1,12 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package properties import ( - "bytes" "fmt" - "io/ioutil" + "io" "net/http" "os" "strings" @@ -17,53 +16,221 @@ import ( type Encoding uint const ( + // utf8Default is a private placeholder for the zero value of Encoding to + // ensure that it has the correct meaning. UTF8 is the default encoding but + // was assigned a non-zero value which cannot be changed without breaking + // existing code. Clients should continue to use the public constants. + utf8Default Encoding = iota + // UTF8 interprets the input data as UTF-8. - UTF8 Encoding = 1 << iota + UTF8 // ISO_8859_1 interprets the input data as ISO-8859-1. ISO_8859_1 ) +type Loader struct { + // Encoding determines how the data from files and byte buffers + // is interpreted. For URLs the Content-Type header is used + // to determine the encoding of the data. + Encoding Encoding + + // DisableExpansion configures the property expansion of the + // returned property object. When set to true, the property values + // will not be expanded and the Property object will not be checked + // for invalid expansion expressions. + DisableExpansion bool + + // IgnoreMissing configures whether missing files or URLs which return + // 404 are reported as errors. When set to true, missing files and 404 + // status codes are not reported as errors. + IgnoreMissing bool +} + +// Load reads a buffer into a Properties struct. +func (l *Loader) LoadBytes(buf []byte) (*Properties, error) { + return l.loadBytes(buf, l.Encoding) +} + +// LoadReader reads an io.Reader into a Properties struct. +func (l *Loader) LoadReader(r io.Reader) (*Properties, error) { + if buf, err := io.ReadAll(r); err != nil { + return nil, err + } else { + return l.loadBytes(buf, l.Encoding) + } +} + +// LoadAll reads the content of multiple URLs or files in the given order into +// a Properties struct. If IgnoreMissing is true then a 404 status code or +// missing file will not be reported as error. Encoding sets the encoding for +// files. For the URLs see LoadURL for the Content-Type header and the +// encoding. +func (l *Loader) LoadAll(names []string) (*Properties, error) { + all := NewProperties() + for _, name := range names { + n, err := expandName(name) + if err != nil { + return nil, err + } + + var p *Properties + switch { + case strings.HasPrefix(n, "http://"): + p, err = l.LoadURL(n) + case strings.HasPrefix(n, "https://"): + p, err = l.LoadURL(n) + default: + p, err = l.LoadFile(n) + } + if err != nil { + return nil, err + } + all.Merge(p) + } + + all.DisableExpansion = l.DisableExpansion + if all.DisableExpansion { + return all, nil + } + return all, all.check() +} + +// LoadFile reads a file into a Properties struct. +// If IgnoreMissing is true then a missing file will not be +// reported as error. +func (l *Loader) LoadFile(filename string) (*Properties, error) { + data, err := os.ReadFile(filename) + if err != nil { + if l.IgnoreMissing && os.IsNotExist(err) { + LogPrintf("properties: %s not found. skipping", filename) + return NewProperties(), nil + } + return nil, err + } + return l.loadBytes(data, l.Encoding) +} + +// LoadURL reads the content of the URL into a Properties struct. +// +// The encoding is determined via the Content-Type header which +// should be set to 'text/plain'. If the 'charset' parameter is +// missing, 'iso-8859-1' or 'latin1' the encoding is set to +// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the +// encoding is set to UTF-8. A missing content type header is +// interpreted as 'text/plain; charset=utf-8'. +func (l *Loader) LoadURL(url string) (*Properties, error) { + resp, err := http.Get(url) + if err != nil { + return nil, fmt.Errorf("properties: error fetching %q. %s", url, err) + } + defer resp.Body.Close() + + if resp.StatusCode == 404 && l.IgnoreMissing { + LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode) + return NewProperties(), nil + } + + if resp.StatusCode != 200 { + return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("properties: %s error reading response. %s", url, err) + } + + ct := resp.Header.Get("Content-Type") + ct = strings.Join(strings.Fields(ct), "") + var enc Encoding + switch strings.ToLower(ct) { + case "text/plain", "text/plain;charset=iso-8859-1", "text/plain;charset=latin1": + enc = ISO_8859_1 + case "", "text/plain;charset=utf-8": + enc = UTF8 + default: + return nil, fmt.Errorf("properties: invalid content type %s", ct) + } + + return l.loadBytes(body, enc) +} + +func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) { + p, err := parse(convert(buf, enc)) + if err != nil { + return nil, err + } + p.DisableExpansion = l.DisableExpansion + if p.DisableExpansion { + return p, nil + } + return p, p.check() +} + // Load reads a buffer into a Properties struct. func Load(buf []byte, enc Encoding) (*Properties, error) { - return loadBuf(buf, enc) + l := &Loader{Encoding: enc} + return l.LoadBytes(buf) } // LoadString reads an UTF8 string into a properties struct. func LoadString(s string) (*Properties, error) { - return loadBuf([]byte(s), UTF8) + l := &Loader{Encoding: UTF8} + return l.LoadBytes([]byte(s)) +} + +// LoadMap creates a new Properties struct from a string map. +func LoadMap(m map[string]string) *Properties { + p := NewProperties() + for k, v := range m { + p.Set(k, v) + } + return p } // LoadFile reads a file into a Properties struct. func LoadFile(filename string, enc Encoding) (*Properties, error) { - return loadFiles([]string{filename}, enc, false) + l := &Loader{Encoding: enc} + return l.LoadAll([]string{filename}) +} + +// LoadReader reads an io.Reader into a Properties struct. +func LoadReader(r io.Reader, enc Encoding) (*Properties, error) { + l := &Loader{Encoding: enc} + return l.LoadReader(r) } // LoadFiles reads multiple files in the given order into // a Properties struct. If 'ignoreMissing' is true then // non-existent files will not be reported as error. func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - return loadFiles(filenames, enc, ignoreMissing) + l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} + return l.LoadAll(filenames) } // LoadURL reads the content of the URL into a Properties struct. -// -// The encoding is determined via the Content-Type header which -// should be set to 'text/plain'. If the 'charset' parameter is -// missing, 'iso-8859-1' or 'latin1' the encoding is set to -// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the -// encoding is set to UTF-8. A missing content type header is -// interpreted as 'text/plain; charset=utf-8'. +// See Loader#LoadURL for details. func LoadURL(url string) (*Properties, error) { - return loadURLs([]string{url}, false) + l := &Loader{Encoding: UTF8} + return l.LoadAll([]string{url}) } // LoadURLs reads the content of multiple URLs in the given order into a -// Properties struct. If 'ignoreMissing' is true then a 404 status code will -// not be reported as error. See LoadURL for the Content-Type header +// Properties struct. If IgnoreMissing is true then a 404 status code will +// not be reported as error. See Loader#LoadURL for the Content-Type header // and the encoding. func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - return loadURLs(urls, ignoreMissing) + l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing} + return l.LoadAll(urls) +} + +// LoadAll reads the content of multiple URLs or files in the given order into a +// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will +// not be reported as error. Encoding sets the encoding for files. For the URLs please see +// LoadURL for the Content-Type header and the encoding. +func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) { + l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing} + return l.LoadAll(names) } // MustLoadString reads an UTF8 string into a Properties struct and @@ -72,6 +239,12 @@ func MustLoadString(s string) *Properties { return must(LoadString(s)) } +// MustLoadSReader reads an io.Reader into a Properties struct and +// panics on error. +func MustLoadReader(r io.Reader, enc Encoding) *Properties { + return must(LoadReader(r, enc)) +} + // MustLoadFile reads a file into a Properties struct and // panics on error. func MustLoadFile(filename string, enc Encoding) *Properties { @@ -91,81 +264,19 @@ func MustLoadURL(url string) *Properties { return must(LoadURL(url)) } -// MustLoadFiles reads the content of multiple URLs in the given order into a +// MustLoadURLs reads the content of multiple URLs in the given order into a // Properties struct and panics on error. If 'ignoreMissing' is true then a 404 // status code will not be reported as error. func MustLoadURLs(urls []string, ignoreMissing bool) *Properties { return must(LoadURLs(urls, ignoreMissing)) } -func loadBuf(buf []byte, enc Encoding) (*Properties, error) { - p, err := parse(convert(buf, enc)) - if err != nil { - return nil, err - } - return p, p.check() -} - -func loadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) { - var buf bytes.Buffer - for _, filename := range filenames { - f, err := expandFilename(filename) - if err != nil { - return nil, err - } - - data, err := ioutil.ReadFile(f) - if err != nil { - if ignoreMissing && os.IsNotExist(err) { - LogPrintf("properties: %s not found. skipping", filename) - continue - } - return nil, err - } - - // concatenate the buffers and add a new line in case - // the previous file didn't end with a new line - buf.Write(data) - buf.WriteRune('\n') - } - return loadBuf(buf.Bytes(), enc) -} - -func loadURLs(urls []string, ignoreMissing bool) (*Properties, error) { - var buf bytes.Buffer - for _, u := range urls { - resp, err := http.Get(u) - if err != nil { - return nil, fmt.Errorf("properties: error fetching %q. %s", u, err) - } - if resp.StatusCode == 404 && ignoreMissing { - LogPrintf("properties: %s returned %d. skipping", u, resp.StatusCode) - continue - } - if resp.StatusCode != 200 { - return nil, fmt.Errorf("properties: %s returned %d", u, resp.StatusCode) - } - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - return nil, fmt.Errorf("properties: %s error reading response. %s", u, err) - } - - ct := resp.Header.Get("Content-Type") - var enc Encoding - switch strings.ToLower(ct) { - case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1": - enc = ISO_8859_1 - case "", "text/plain; charset=utf-8": - enc = UTF8 - default: - return nil, fmt.Errorf("properties: invalid content type %s", ct) - } - - buf.WriteString(convert(body, enc)) - buf.WriteRune('\n') - } - return loadBuf(buf.Bytes(), UTF8) +// MustLoadAll reads the content of multiple URLs or files in the given order into a +// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will +// not be reported as error. Encoding sets the encoding for files. For the URLs please see +// LoadURL for the Content-Type header and the encoding. It panics on error. +func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties { + return must(LoadAll(names, enc, ignoreMissing)) } func must(p *Properties, err error) *Properties { @@ -175,12 +286,12 @@ func must(p *Properties, err error) *Properties { return p } -// expandFilename expands ${ENV_VAR} expressions in a filename. +// expandName expands ${ENV_VAR} expressions in a name. // If the environment variable does not exist then it will be replaced // with an empty string. Malformed expressions like "${ENV_VAR" will // be reported as error. -func expandFilename(filename string) (string, error) { - return expand(filename, make(map[string]bool), "${", "}", make(map[string]string)) +func expandName(name string) (string, error) { + return expand(name, []string{}, "${", "}", make(map[string]string)) } // Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string. @@ -188,7 +299,7 @@ func expandFilename(filename string) (string, error) { // first 256 unicode code points cover ISO-8859-1. func convert(buf []byte, enc Encoding) string { switch enc { - case UTF8: + case utf8Default, UTF8: return string(buf) case ISO_8859_1: runes := make([]rune, len(buf)) diff --git a/vendor/github.com/magiconair/properties/parser.go b/vendor/github.com/magiconair/properties/parser.go index ff0e1e157..fccfd39f6 100644 --- a/vendor/github.com/magiconair/properties/parser.go +++ b/vendor/github.com/magiconair/properties/parser.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -59,14 +59,6 @@ func (p *parser) errorf(format string, args ...interface{}) { panic(fmt.Errorf(format, args...)) } -func (p *parser) expect(expected itemType) (token item) { - token = p.lex.nextItem() - if token.typ != expected { - p.unexpected(token) - } - return token -} - func (p *parser) expectOneOf(expected ...itemType) (token item) { token = p.lex.nextItem() for _, v := range expected { @@ -91,5 +83,4 @@ func (p *parser) recover(errp *error) { } *errp = e.(error) } - return } diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go index 884ef4e07..fb2f7b404 100644 --- a/vendor/github.com/magiconair/properties/properties.go +++ b/vendor/github.com/magiconair/properties/properties.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -8,17 +8,21 @@ package properties // BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used. import ( + "bytes" "fmt" "io" "log" "os" "regexp" + "sort" "strconv" "strings" "time" "unicode/utf8" ) +const maxExpansionDepth = 64 + // ErrorHandlerFunc defines the type of function which handles failures // of the MustXXX() functions. An error handler function must exit // the application after handling the error. @@ -28,8 +32,10 @@ type ErrorHandlerFunc func(error) // functions. The default is LogFatalHandler. var ErrorHandler ErrorHandlerFunc = LogFatalHandler +// LogHandlerFunc defines the function prototype for logging errors. type LogHandlerFunc func(fmt string, args ...interface{}) +// LogPrintf defines a log handler which uses log.Printf. var LogPrintf LogHandlerFunc = log.Printf // LogFatalHandler handles the error by logging a fatal error and exiting. @@ -65,6 +71,9 @@ type Properties struct { // Stores the keys in order of appearance. k []string + + // WriteSeparator specifies the separator of key and value while writing the properties. + WriteSeparator string } // NewProperties creates a new Properties struct with the default @@ -79,6 +88,17 @@ func NewProperties() *Properties { } } +// Load reads a buffer into the given Properties struct. +func (p *Properties) Load(buf []byte, enc Encoding) error { + l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion} + newProperties, err := l.LoadBytes(buf) + if err != nil { + return err + } + p.Merge(newProperties) + return nil +} + // Get returns the expanded value for the given key if exists. // Otherwise, ok is false. func (p *Properties) Get(key string) (value string, ok bool) { @@ -90,13 +110,13 @@ func (p *Properties) Get(key string) (value string, ok bool) { return "", false } - expanded, err := p.expand(v) + expanded, err := p.expand(key, v) // we guarantee that the expanded value is free of // circular references and malformed expressions // so we panic if we still get an error here. if err != nil { - ErrorHandler(fmt.Errorf("%s in %q", err, key+" = "+v)) + ErrorHandler(err) } return expanded, true @@ -444,6 +464,8 @@ func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties { pp := NewProperties() for _, k := range p.k { if re.MatchString(k) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) pp.Set(k, p.m[k]) } } @@ -456,6 +478,8 @@ func (p *Properties) FilterPrefix(prefix string) *Properties { pp := NewProperties() for _, k := range p.k { if strings.HasPrefix(k, prefix) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are just copying a subset of keys this cannot happen (fingers crossed) pp.Set(k, p.m[k]) } } @@ -469,6 +493,9 @@ func (p *Properties) FilterStripPrefix(prefix string) *Properties { n := len(prefix) for _, k := range p.k { if len(k) > len(prefix) && strings.HasPrefix(k, prefix) { + // TODO(fs): we are ignoring the error which flags a circular reference. + // TODO(fs): since we are modifying keys I am not entirely sure whether we can create a circular reference + // TODO(fs): this function should probably return an error but the signature is fixed pp.Set(k[n:], p.m[k]) } } @@ -483,9 +510,7 @@ func (p *Properties) Len() int { // Keys returns all keys in the same order as in the input. func (p *Properties) Keys() []string { keys := make([]string, len(p.k)) - for i, k := range p.k { - keys[i] = k - } + copy(keys, p.k) return keys } @@ -504,6 +529,9 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { if p.DisableExpansion { prev, ok = p.Get(key) p.m[key] = value + if !ok { + p.k = append(p.k, key) + } return prev, ok, nil } @@ -515,7 +543,7 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { p.m[key] = value // now check for a circular reference - _, err = p.expand(value) + _, err = p.expand(key, value) if err != nil { // revert to the previous state @@ -535,6 +563,13 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) { return prev, ok, nil } +// SetValue sets property key to the default string value +// as defined by fmt.Sprintf("%v"). +func (p *Properties) SetValue(key string, value interface{}) error { + _, _, err := p.Set(key, fmt.Sprintf("%v", value)) + return err +} + // MustSet sets the property key to the corresponding value. // If a value for key existed before then ok is true and prev // contains the previous value. An empty key is silently ignored. @@ -556,6 +591,12 @@ func (p *Properties) String() string { return s } +// Sort sorts the properties keys in alphabetical order. +// This is helpfully before writing the properties. +func (p *Properties) Sort() { + sort.Strings(p.k) +} + // Write writes all unexpanded 'key = value' pairs to the given writer. // Write returns the number of bytes written and any write error encountered. func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) { @@ -596,7 +637,7 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i } for _, c := range comments { - x, err = fmt.Fprintf(w, "%s%s\n", prefix, encode(c, "", enc)) + x, err = fmt.Fprintf(w, "%s%s\n", prefix, c) if err != nil { return } @@ -605,8 +646,11 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i } } } - - x, err = fmt.Fprintf(w, "%s = %s\n", encode(key, " :", enc), encode(value, "", enc)) + sep := " = " + if p.WriteSeparator != "" { + sep = p.WriteSeparator + } + x, err = fmt.Fprintf(w, "%s%s%s\n", encode(key, " :", enc), sep, encode(value, "", enc)) if err != nil { return } @@ -615,6 +659,30 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i return } +// Map returns a copy of the properties as a map. +func (p *Properties) Map() map[string]string { + m := make(map[string]string) + for k, v := range p.m { + m[k] = v + } + return m +} + +// FilterFunc returns a copy of the properties which includes the values which passed all filters. +func (p *Properties) FilterFunc(filters ...func(k, v string) bool) *Properties { + pp := NewProperties() +outer: + for k, v := range p.m { + for _, f := range filters { + if !f(k, v) { + continue outer + } + pp.Set(k, v) + } + } + return pp +} + // ---------------------------------------------------------------------------- // Delete removes the key and its comments. @@ -624,67 +692,95 @@ func (p *Properties) Delete(key string) { newKeys := []string{} for _, k := range p.k { if k != key { - newKeys = append(newKeys, key) + newKeys = append(newKeys, k) } } p.k = newKeys } +// Merge merges properties, comments and keys from other *Properties into p +func (p *Properties) Merge(other *Properties) { + for _, k := range other.k { + if _, ok := p.m[k]; !ok { + p.k = append(p.k, k) + } + } + for k, v := range other.m { + p.m[k] = v + } + for k, v := range other.c { + p.c[k] = v + } +} + // ---------------------------------------------------------------------------- // check expands all values and returns an error if a circular reference or // a malformed expression was found. func (p *Properties) check() error { - for _, value := range p.m { - if _, err := p.expand(value); err != nil { + for key, value := range p.m { + if _, err := p.expand(key, value); err != nil { return err } } return nil } -func (p *Properties) expand(input string) (string, error) { +func (p *Properties) expand(key, input string) (string, error) { // no pre/postfix -> nothing to expand if p.Prefix == "" && p.Postfix == "" { return input, nil } - return expand(input, make(map[string]bool), p.Prefix, p.Postfix, p.m) + return expand(input, []string{key}, p.Prefix, p.Postfix, p.m) } // expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values. // The function keeps track of the keys that were already expanded and stops if it // detects a circular reference or a malformed expression of the form '(prefix)key'. -func expand(s string, keys map[string]bool, prefix, postfix string, values map[string]string) (string, error) { - start := strings.Index(s, prefix) - if start == -1 { - return s, nil +func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) { + if len(keys) > maxExpansionDepth { + return "", fmt.Errorf("expansion too deep") } - keyStart := start + len(prefix) - keyLen := strings.Index(s[keyStart:], postfix) - if keyLen == -1 { - return "", fmt.Errorf("malformed expression") - } - - end := keyStart + keyLen + len(postfix) - 1 - key := s[keyStart : keyStart+keyLen] + for { + start := strings.Index(s, prefix) + if start == -1 { + return s, nil + } - // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) + keyStart := start + len(prefix) + keyLen := strings.Index(s[keyStart:], postfix) + if keyLen == -1 { + return "", fmt.Errorf("malformed expression") + } - if _, ok := keys[key]; ok { - return "", fmt.Errorf("circular reference") - } + end := keyStart + keyLen + len(postfix) - 1 + key := s[keyStart : keyStart+keyLen] - val, ok := values[key] - if !ok { - val = os.Getenv(key) - } + // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key) - // remember that we've seen the key - keys[key] = true + for _, k := range keys { + if key == k { + var b bytes.Buffer + b.WriteString("circular reference in:\n") + for _, k1 := range keys { + fmt.Fprintf(&b, "%s=%s\n", k1, values[k1]) + } + return "", fmt.Errorf(b.String()) + } + } - return expand(s[:start]+val+s[end+1:], keys, prefix, postfix, values) + val, ok := values[key] + if !ok { + val = os.Getenv(key) + } + new_val, err := expand(val, append(keys, key), prefix, postfix, values) + if err != nil { + return "", err + } + s = s[:start] + new_val + s[end+1:] + } } // encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters. @@ -737,6 +833,8 @@ func escape(r rune, special string) string { return "\\r" case '\t': return "\\t" + case '\\': + return "\\\\" default: if strings.ContainsRune(special, r) { return "\\" + string(r) diff --git a/vendor/github.com/magiconair/properties/rangecheck.go b/vendor/github.com/magiconair/properties/rangecheck.go index d9ce2806b..dbd60b36e 100644 --- a/vendor/github.com/magiconair/properties/rangecheck.go +++ b/vendor/github.com/magiconair/properties/rangecheck.go @@ -1,4 +1,4 @@ -// Copyright 2016 Frank Schroeder. All rights reserved. +// Copyright 2013-2022 Frank Schroeder. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/mattn/go-runewidth/.travis.yml b/vendor/github.com/mattn/go-runewidth/.travis.yml deleted file mode 100644 index 5c9c2a30f..000000000 --- a/vendor/github.com/mattn/go-runewidth/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -go: - - tip -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL diff --git a/vendor/github.com/mattn/go-runewidth/LICENSE b/vendor/github.com/mattn/go-runewidth/LICENSE new file mode 100644 index 000000000..91b5cef30 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/mattn/go-runewidth/README.md b/vendor/github.com/mattn/go-runewidth/README.md new file mode 100644 index 000000000..5e2cfd98c --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/README.md @@ -0,0 +1,27 @@ +go-runewidth +============ + +[![Build Status](https://github.com/mattn/go-runewidth/workflows/test/badge.svg?branch=master)](https://github.com/mattn/go-runewidth/actions?query=workflow%3Atest) +[![Codecov](https://codecov.io/gh/mattn/go-runewidth/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-runewidth) +[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) +[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) + +Provides functions to get fixed width of the character or string. + +Usage +----- + +```go +runewidth.StringWidth("つのだ☆HIRO") == 12 +``` + + +Author +------ + +Yasuhiro Matsumoto + +License +------- + +under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/mattn/go-runewidth/README.mkd b/vendor/github.com/mattn/go-runewidth/README.mkd deleted file mode 100644 index ffb0edd2c..000000000 --- a/vendor/github.com/mattn/go-runewidth/README.mkd +++ /dev/null @@ -1,26 +0,0 @@ -go-runewidth -============ - -[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) -[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) -[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) - -Provides functions to get fixed width of the character or string. - -Usage ------ - -```go -runewidth.StringWidth("つのだ☆HIRO") == 12 -``` - - -Author ------- - -Yasuhiro Matsumoto - -License -------- - -under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go index 3fbf33d59..7dfbb3be9 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -1,380 +1,262 @@ package runewidth -var EastAsianWidth = IsEastAsian() -var DefaultCondition = &Condition{EastAsianWidth} +import ( + "os" + "strings" + + "github.com/rivo/uniseg" +) + +//go:generate go run script/generate.go + +var ( + // EastAsianWidth will be set true if the current locale is CJK + EastAsianWidth bool + + // StrictEmojiNeutral should be set false if handle broken fonts + StrictEmojiNeutral bool = true + + // DefaultCondition is a condition in current locale + DefaultCondition = &Condition{ + EastAsianWidth: false, + StrictEmojiNeutral: true, + } +) + +func init() { + handleEnv() +} + +func handleEnv() { + env := os.Getenv("RUNEWIDTH_EASTASIAN") + if env == "" { + EastAsianWidth = IsEastAsian() + } else { + EastAsianWidth = env == "1" + } + // update DefaultCondition + if DefaultCondition.EastAsianWidth != EastAsianWidth { + DefaultCondition.EastAsianWidth = EastAsianWidth + if len(DefaultCondition.combinedLut) > 0 { + DefaultCondition.combinedLut = DefaultCondition.combinedLut[:0] + CreateLUT() + } + } +} type interval struct { first rune last rune } -var combining = []interval{ - {0x0300, 0x036F}, {0x0483, 0x0486}, {0x0488, 0x0489}, - {0x0591, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, - {0x05C4, 0x05C5}, {0x05C7, 0x05C7}, {0x0600, 0x0603}, - {0x0610, 0x0615}, {0x064B, 0x065E}, {0x0670, 0x0670}, - {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, - {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A}, - {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, {0x0901, 0x0902}, - {0x093C, 0x093C}, {0x0941, 0x0948}, {0x094D, 0x094D}, - {0x0951, 0x0954}, {0x0962, 0x0963}, {0x0981, 0x0981}, - {0x09BC, 0x09BC}, {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, - {0x09E2, 0x09E3}, {0x0A01, 0x0A02}, {0x0A3C, 0x0A3C}, - {0x0A41, 0x0A42}, {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, - {0x0A70, 0x0A71}, {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, - {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, - {0x0AE2, 0x0AE3}, {0x0B01, 0x0B01}, {0x0B3C, 0x0B3C}, - {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43}, {0x0B4D, 0x0B4D}, - {0x0B56, 0x0B56}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0}, - {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48}, - {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0CBC, 0x0CBC}, - {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, - {0x0CE2, 0x0CE3}, {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, - {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, - {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, - {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, - {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, - {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, - {0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, - {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, - {0x1032, 0x1032}, {0x1036, 0x1037}, {0x1039, 0x1039}, - {0x1058, 0x1059}, {0x1160, 0x11FF}, {0x135F, 0x135F}, - {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, - {0x1772, 0x1773}, {0x17B4, 0x17B5}, {0x17B7, 0x17BD}, - {0x17C6, 0x17C6}, {0x17C9, 0x17D3}, {0x17DD, 0x17DD}, - {0x180B, 0x180D}, {0x18A9, 0x18A9}, {0x1920, 0x1922}, - {0x1927, 0x1928}, {0x1932, 0x1932}, {0x1939, 0x193B}, - {0x1A17, 0x1A18}, {0x1B00, 0x1B03}, {0x1B34, 0x1B34}, - {0x1B36, 0x1B3A}, {0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, - {0x1B6B, 0x1B73}, {0x1DC0, 0x1DCA}, {0x1DFE, 0x1DFF}, - {0x200B, 0x200F}, {0x202A, 0x202E}, {0x2060, 0x2063}, - {0x206A, 0x206F}, {0x20D0, 0x20EF}, {0x302A, 0x302F}, - {0x3099, 0x309A}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, - {0xA825, 0xA826}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, - {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, - {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, - {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x1D167, 0x1D169}, - {0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, {0xE0001, 0xE0001}, {0xE0020, 0xE007F}, - {0xE0100, 0xE01EF}, +type table []interval + +func inTables(r rune, ts ...table) bool { + for _, t := range ts { + if inTable(r, t) { + return true + } + } + return false } -type ctype int +func inTable(r rune, t table) bool { + if r < t[0].first { + return false + } -const ( - narrow ctype = iota - ambiguous - wide - halfwidth - fullwidth - neutral -) + bot := 0 + top := len(t) - 1 + for top >= bot { + mid := (bot + top) >> 1 -type intervalType struct { - first rune - last rune - ctype ctype + switch { + case t[mid].last < r: + bot = mid + 1 + case t[mid].first > r: + top = mid - 1 + default: + return true + } + } + + return false +} + +var private = table{ + {0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD}, } -var ctypes = []intervalType{ - {0x0020, 0x007E, narrow}, - {0x00A1, 0x00A1, ambiguous}, - {0x00A2, 0x00A3, narrow}, - {0x00A4, 0x00A4, ambiguous}, - {0x00A5, 0x00A6, narrow}, - {0x00A7, 0x00A8, ambiguous}, - {0x00AA, 0x00AA, ambiguous}, - {0x00AC, 0x00AC, narrow}, - {0x00AD, 0x00AE, ambiguous}, - {0x00AF, 0x00AF, narrow}, - {0x00B0, 0x00B4, ambiguous}, - {0x00B6, 0x00BA, ambiguous}, - {0x00BC, 0x00BF, ambiguous}, - {0x00C6, 0x00C6, ambiguous}, - {0x00D0, 0x00D0, ambiguous}, - {0x00D7, 0x00D8, ambiguous}, - {0x00DE, 0x00E1, ambiguous}, - {0x00E6, 0x00E6, ambiguous}, - {0x00E8, 0x00EA, ambiguous}, - {0x00EC, 0x00ED, ambiguous}, - {0x00F0, 0x00F0, ambiguous}, - {0x00F2, 0x00F3, ambiguous}, - {0x00F7, 0x00FA, ambiguous}, - {0x00FC, 0x00FC, ambiguous}, - {0x00FE, 0x00FE, ambiguous}, - {0x0101, 0x0101, ambiguous}, - {0x0111, 0x0111, ambiguous}, - {0x0113, 0x0113, ambiguous}, - {0x011B, 0x011B, ambiguous}, - {0x0126, 0x0127, ambiguous}, - {0x012B, 0x012B, ambiguous}, - {0x0131, 0x0133, ambiguous}, - {0x0138, 0x0138, ambiguous}, - {0x013F, 0x0142, ambiguous}, - {0x0144, 0x0144, ambiguous}, - {0x0148, 0x014B, ambiguous}, - {0x014D, 0x014D, ambiguous}, - {0x0152, 0x0153, ambiguous}, - {0x0166, 0x0167, ambiguous}, - {0x016B, 0x016B, ambiguous}, - {0x01CE, 0x01CE, ambiguous}, - {0x01D0, 0x01D0, ambiguous}, - {0x01D2, 0x01D2, ambiguous}, - {0x01D4, 0x01D4, ambiguous}, - {0x01D6, 0x01D6, ambiguous}, - {0x01D8, 0x01D8, ambiguous}, - {0x01DA, 0x01DA, ambiguous}, - {0x01DC, 0x01DC, ambiguous}, - {0x0251, 0x0251, ambiguous}, - {0x0261, 0x0261, ambiguous}, - {0x02C4, 0x02C4, ambiguous}, - {0x02C7, 0x02C7, ambiguous}, - {0x02C9, 0x02CB, ambiguous}, - {0x02CD, 0x02CD, ambiguous}, - {0x02D0, 0x02D0, ambiguous}, - {0x02D8, 0x02DB, ambiguous}, - {0x02DD, 0x02DD, ambiguous}, - {0x02DF, 0x02DF, ambiguous}, - {0x0300, 0x036F, ambiguous}, - {0x0391, 0x03A2, ambiguous}, - {0x03A3, 0x03A9, ambiguous}, - {0x03B1, 0x03C1, ambiguous}, - {0x03C3, 0x03C9, ambiguous}, - {0x0401, 0x0401, ambiguous}, - {0x0410, 0x044F, ambiguous}, - {0x0451, 0x0451, ambiguous}, - {0x1100, 0x115F, wide}, - {0x2010, 0x2010, ambiguous}, - {0x2013, 0x2016, ambiguous}, - {0x2018, 0x2019, ambiguous}, - {0x201C, 0x201D, ambiguous}, - {0x2020, 0x2022, ambiguous}, - {0x2024, 0x2027, ambiguous}, - {0x2030, 0x2030, ambiguous}, - {0x2032, 0x2033, ambiguous}, - {0x2035, 0x2035, ambiguous}, - {0x203B, 0x203B, ambiguous}, - {0x203E, 0x203E, ambiguous}, - {0x2074, 0x2074, ambiguous}, - {0x207F, 0x207F, ambiguous}, - {0x2081, 0x2084, ambiguous}, - {0x20A9, 0x20A9, halfwidth}, - {0x20AC, 0x20AC, ambiguous}, - {0x2103, 0x2103, ambiguous}, - {0x2105, 0x2105, ambiguous}, - {0x2109, 0x2109, ambiguous}, - {0x2113, 0x2113, ambiguous}, - {0x2116, 0x2116, ambiguous}, - {0x2121, 0x2122, ambiguous}, - {0x2126, 0x2126, ambiguous}, - {0x212B, 0x212B, ambiguous}, - {0x2153, 0x2154, ambiguous}, - {0x215B, 0x215E, ambiguous}, - {0x2160, 0x216B, ambiguous}, - {0x2170, 0x2179, ambiguous}, - {0x2189, 0x218A, ambiguous}, - {0x2190, 0x2199, ambiguous}, - {0x21B8, 0x21B9, ambiguous}, - {0x21D2, 0x21D2, ambiguous}, - {0x21D4, 0x21D4, ambiguous}, - {0x21E7, 0x21E7, ambiguous}, - {0x2200, 0x2200, ambiguous}, - {0x2202, 0x2203, ambiguous}, - {0x2207, 0x2208, ambiguous}, - {0x220B, 0x220B, ambiguous}, - {0x220F, 0x220F, ambiguous}, - {0x2211, 0x2211, ambiguous}, - {0x2215, 0x2215, ambiguous}, - {0x221A, 0x221A, ambiguous}, - {0x221D, 0x2220, ambiguous}, - {0x2223, 0x2223, ambiguous}, - {0x2225, 0x2225, ambiguous}, - {0x2227, 0x222C, ambiguous}, - {0x222E, 0x222E, ambiguous}, - {0x2234, 0x2237, ambiguous}, - {0x223C, 0x223D, ambiguous}, - {0x2248, 0x2248, ambiguous}, - {0x224C, 0x224C, ambiguous}, - {0x2252, 0x2252, ambiguous}, - {0x2260, 0x2261, ambiguous}, - {0x2264, 0x2267, ambiguous}, - {0x226A, 0x226B, ambiguous}, - {0x226E, 0x226F, ambiguous}, - {0x2282, 0x2283, ambiguous}, - {0x2286, 0x2287, ambiguous}, - {0x2295, 0x2295, ambiguous}, - {0x2299, 0x2299, ambiguous}, - {0x22A5, 0x22A5, ambiguous}, - {0x22BF, 0x22BF, ambiguous}, - {0x2312, 0x2312, ambiguous}, - {0x2329, 0x232A, wide}, - {0x2460, 0x24E9, ambiguous}, - {0x24EB, 0x254B, ambiguous}, - {0x2550, 0x2573, ambiguous}, - {0x2580, 0x258F, ambiguous}, - {0x2592, 0x2595, ambiguous}, - {0x25A0, 0x25A1, ambiguous}, - {0x25A3, 0x25A9, ambiguous}, - {0x25B2, 0x25B3, ambiguous}, - {0x25B6, 0x25B7, ambiguous}, - {0x25BC, 0x25BD, ambiguous}, - {0x25C0, 0x25C1, ambiguous}, - {0x25C6, 0x25C8, ambiguous}, - {0x25CB, 0x25CB, ambiguous}, - {0x25CE, 0x25D1, ambiguous}, - {0x25E2, 0x25E5, ambiguous}, - {0x25EF, 0x25EF, ambiguous}, - {0x2605, 0x2606, ambiguous}, - {0x2609, 0x2609, ambiguous}, - {0x260E, 0x260F, ambiguous}, - {0x2614, 0x2615, ambiguous}, - {0x261C, 0x261C, ambiguous}, - {0x261E, 0x261E, ambiguous}, - {0x2640, 0x2640, ambiguous}, - {0x2642, 0x2642, ambiguous}, - {0x2660, 0x2661, ambiguous}, - {0x2663, 0x2665, ambiguous}, - {0x2667, 0x266A, ambiguous}, - {0x266C, 0x266D, ambiguous}, - {0x266F, 0x266F, ambiguous}, - {0x269E, 0x269F, ambiguous}, - {0x26BE, 0x26BF, ambiguous}, - {0x26C4, 0x26CD, ambiguous}, - {0x26CF, 0x26E1, ambiguous}, - {0x26E3, 0x26E3, ambiguous}, - {0x26E8, 0x26FF, ambiguous}, - {0x273D, 0x273D, ambiguous}, - {0x2757, 0x2757, ambiguous}, - {0x2776, 0x277F, ambiguous}, - {0x27E6, 0x27ED, narrow}, - {0x2985, 0x2986, narrow}, - {0x2B55, 0x2B59, ambiguous}, - {0x2E80, 0x2E9A, wide}, - {0x2E9B, 0x2EF4, wide}, - {0x2F00, 0x2FD6, wide}, - {0x2FF0, 0x2FFC, wide}, - {0x3000, 0x3000, fullwidth}, - {0x3001, 0x303E, wide}, - {0x3041, 0x3097, wide}, - {0x3099, 0x3100, wide}, - {0x3105, 0x312E, wide}, - {0x3131, 0x318F, wide}, - {0x3190, 0x31BB, wide}, - {0x31C0, 0x31E4, wide}, - {0x31F0, 0x321F, wide}, - {0x3220, 0x3247, wide}, - {0x3248, 0x324F, ambiguous}, - {0x3250, 0x32FF, wide}, - {0x3300, 0x4DBF, wide}, - {0x4E00, 0xA48D, wide}, - {0xA490, 0xA4C7, wide}, - {0xA960, 0xA97D, wide}, - {0xAC00, 0xD7A4, wide}, - {0xE000, 0xF8FF, ambiguous}, - {0xF900, 0xFAFF, wide}, - {0xFE00, 0xFE0F, ambiguous}, - {0xFE10, 0xFE1A, wide}, - {0xFE30, 0xFE53, wide}, - {0xFE54, 0xFE67, wide}, - {0xFE68, 0xFE6C, wide}, - {0xFF01, 0xFF60, fullwidth}, - {0xFF61, 0xFFBF, halfwidth}, - {0xFFC2, 0xFFC8, halfwidth}, - {0xFFCA, 0xFFD0, halfwidth}, - {0xFFD2, 0xFFD8, halfwidth}, - {0xFFDA, 0xFFDD, halfwidth}, - {0xFFE0, 0xFFE7, fullwidth}, - {0xFFE8, 0xFFEF, halfwidth}, - {0xFFFD, 0xFFFE, ambiguous}, - {0x1B000, 0x1B002, wide}, - {0x1F100, 0x1F10A, ambiguous}, - {0x1F110, 0x1F12D, ambiguous}, - {0x1F130, 0x1F169, ambiguous}, - {0x1F170, 0x1F19B, ambiguous}, - {0x1F200, 0x1F203, wide}, - {0x1F210, 0x1F23B, wide}, - {0x1F240, 0x1F249, wide}, - {0x1F250, 0x1F252, wide}, - {0x20000, 0x2FFFE, wide}, - {0x30000, 0x3FFFE, wide}, - {0xE0100, 0xE01F0, ambiguous}, - {0xF0000, 0xFFFFD, ambiguous}, - {0x100000, 0x10FFFE, ambiguous}, +var nonprint = table{ + {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, + {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, + {0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, } +// Condition have flag EastAsianWidth whether the current locale is CJK or not. type Condition struct { - EastAsianWidth bool + combinedLut []byte + EastAsianWidth bool + StrictEmojiNeutral bool } +// NewCondition return new instance of Condition which is current locale. func NewCondition() *Condition { - return &Condition{EastAsianWidth} + return &Condition{ + EastAsianWidth: EastAsianWidth, + StrictEmojiNeutral: StrictEmojiNeutral, + } } // RuneWidth returns the number of cells in r. // See http://www.unicode.org/reports/tr11/ func (c *Condition) RuneWidth(r rune) int { - if r == 0 { + if r < 0 || r > 0x10FFFF { return 0 } - if r < 32 || (r >= 0x7f && r < 0xa0) { - return 1 + if len(c.combinedLut) > 0 { + return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3 } - for _, iv := range combining { - if iv.first <= r && r <= iv.last { + // optimized version, verified by TestRuneWidthChecksums() + if !c.EastAsianWidth { + switch { + case r < 0x20: + return 0 + case (r >= 0x7F && r <= 0x9F) || r == 0xAD: // nonprint + return 0 + case r < 0x300: + return 1 + case inTable(r, narrow): + return 1 + case inTables(r, nonprint, combining): return 0 + case inTable(r, doublewidth): + return 2 + default: + return 1 + } + } else { + switch { + case inTables(r, nonprint, combining): + return 0 + case inTable(r, narrow): + return 1 + case inTables(r, ambiguous, doublewidth): + return 2 + case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow): + return 2 + default: + return 1 } } +} - if c.EastAsianWidth && IsAmbiguousWidth(r) { - return 2 +// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation. +// This should not be called concurrently with other operations on c. +// If options in c is changed, CreateLUT should be called again. +func (c *Condition) CreateLUT() { + const max = 0x110000 + lut := c.combinedLut + if len(c.combinedLut) != 0 { + // Remove so we don't use it. + c.combinedLut = nil + } else { + lut = make([]byte, max/2) } - - if r >= 0x1100 && - (r <= 0x115f || r == 0x2329 || r == 0x232a || - (r >= 0x2e80 && r <= 0xa4cf && r != 0x303f) || - (r >= 0xac00 && r <= 0xd7a3) || - (r >= 0xf900 && r <= 0xfaff) || - (r >= 0xfe30 && r <= 0xfe6f) || - (r >= 0xff00 && r <= 0xff60) || - (r >= 0xffe0 && r <= 0xffe6) || - (r >= 0x20000 && r <= 0x2fffd) || - (r >= 0x30000 && r <= 0x3fffd)) { - return 2 + for i := range lut { + i32 := int32(i * 2) + x0 := c.RuneWidth(i32) + x1 := c.RuneWidth(i32 + 1) + lut[i] = uint8(x0) | uint8(x1)<<4 } - return 1 + c.combinedLut = lut } +// StringWidth return width as you can see func (c *Condition) StringWidth(s string) (width int) { - for _, r := range []rune(s) { - width += c.RuneWidth(r) + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // Our best guess at this point is to use the width of the first non-zero-width rune. + } + } + width += chWidth } - return width + return } +// Truncate return string truncated with w cells func (c *Condition) Truncate(s string, w int, tail string) string { if c.StringWidth(s) <= w { return s } - r := []rune(s) - tw := c.StringWidth(tail) - w -= tw - width := 0 - i := 0 - for ; i < len(r); i++ { - cw := c.RuneWidth(r[i]) - if width+cw > w { + w -= c.StringWidth(tail) + var width int + pos := len(s) + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // See StringWidth() for details. + } + } + if width+chWidth > w { + pos, _ = g.Positions() break } - width += cw + width += chWidth + } + return s[:pos] + tail +} + +// TruncateLeft cuts w cells from the beginning of the `s`. +func (c *Condition) TruncateLeft(s string, w int, prefix string) string { + if c.StringWidth(s) <= w { + return prefix + } + + var width int + pos := len(s) + + g := uniseg.NewGraphemes(s) + for g.Next() { + var chWidth int + for _, r := range g.Runes() { + chWidth = c.RuneWidth(r) + if chWidth > 0 { + break // See StringWidth() for details. + } + } + + if width+chWidth > w { + if width < w { + _, pos = g.Positions() + prefix += strings.Repeat(" ", width+chWidth-w) + } else { + pos, _ = g.Positions() + } + + break + } + + width += chWidth } - return string(r[0:i]) + tail + + return prefix + s[pos:] } +// Wrap return string wrapped with w cells func (c *Condition) Wrap(s string, w int) string { width := 0 out := "" - for _, r := range []rune(s) { - cw := RuneWidth(r) + for _, r := range s { + cw := c.RuneWidth(r) if r == '\n' { out += string(r) width = 0 @@ -392,6 +274,7 @@ func (c *Condition) Wrap(s string, w int) string { return out } +// FillLeft return string filled in left by spaces in w cells func (c *Condition) FillLeft(s string, w int) string { width := c.StringWidth(s) count := w - width @@ -405,6 +288,7 @@ func (c *Condition) FillLeft(s string, w int) string { return s } +// FillRight return string filled in left by spaces in w cells func (c *Condition) FillRight(s string, w int) string { width := c.StringWidth(s) count := w - width @@ -424,41 +308,51 @@ func RuneWidth(r rune) int { return DefaultCondition.RuneWidth(r) } -func ct(r rune) ctype { - for _, iv := range ctypes { - if iv.first <= r && r <= iv.last { - return iv.ctype - } - } - return neutral -} - // IsAmbiguousWidth returns whether is ambiguous width or not. func IsAmbiguousWidth(r rune) bool { - return ct(r) == ambiguous + return inTables(r, private, ambiguous) } -// IsAmbiguousWidth returns whether is ambiguous width or not. +// IsNeutralWidth returns whether is neutral width or not. func IsNeutralWidth(r rune) bool { - return ct(r) == neutral + return inTable(r, neutral) } +// StringWidth return width as you can see func StringWidth(s string) (width int) { return DefaultCondition.StringWidth(s) } +// Truncate return string truncated with w cells func Truncate(s string, w int, tail string) string { return DefaultCondition.Truncate(s, w, tail) } +// TruncateLeft cuts w cells from the beginning of the `s`. +func TruncateLeft(s string, w int, prefix string) string { + return DefaultCondition.TruncateLeft(s, w, prefix) +} + +// Wrap return string wrapped with w cells func Wrap(s string, w int) string { return DefaultCondition.Wrap(s, w) } +// FillLeft return string filled in left by spaces in w cells func FillLeft(s string, w int) string { return DefaultCondition.FillLeft(s, w) } +// FillRight return string filled in left by spaces in w cells func FillRight(s string, w int) string { return DefaultCondition.FillRight(s, w) } + +// CreateLUT will create an in-memory lookup table of 557055 bytes for faster operation. +// This should not be called concurrently with other operations. +func CreateLUT() { + if len(DefaultCondition.combinedLut) > 0 { + return + } + DefaultCondition.CreateLUT() +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go b/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go new file mode 100644 index 000000000..84b6528df --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_appengine.go @@ -0,0 +1,9 @@ +//go:build appengine +// +build appengine + +package runewidth + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + return false +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go index 0ce32c5e7..c2abbc2db 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_js.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -1,4 +1,5 @@ -// +build js +//go:build js && !appengine +// +build js,!appengine package runewidth diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go index a4495909d..5a31d738e 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -1,4 +1,5 @@ -// +build !windows,!js +//go:build !windows && !js && !appengine +// +build !windows,!js,!appengine package runewidth @@ -10,20 +11,25 @@ import ( var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) -func IsEastAsian() bool { - locale := os.Getenv("LC_CTYPE") - if locale == "" { - locale = os.Getenv("LANG") - } - - // ignore C locale - if locale == "POSIX" || locale == "C" { - return false - } - if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { - return false - } +var mblenTable = map[string]int{ + "utf-8": 6, + "utf8": 6, + "jis": 8, + "eucjp": 3, + "euckr": 2, + "euccn": 2, + "sjis": 2, + "cp932": 2, + "cp51932": 2, + "cp936": 2, + "cp949": 2, + "cp950": 2, + "big5": 2, + "gbk": 2, + "gb2312": 2, +} +func isEastAsian(locale string) bool { charset := strings.ToLower(locale) r := reLoc.FindStringSubmatch(locale) if len(r) == 2 { @@ -40,26 +46,11 @@ func IsEastAsian() bool { break } } - - mbc_max := 1 - switch charset { - case "utf-8", "utf8": - mbc_max = 6 - case "jis": - mbc_max = 8 - case "eucjp": - mbc_max = 3 - case "euckr", "euccn": - mbc_max = 2 - case "sjis", "cp932", "cp51932", "cp936", "cp949", "cp950": - mbc_max = 2 - case "big5": - mbc_max = 2 - case "gbk", "gb2312": - mbc_max = 2 + max := 1 + if m, ok := mblenTable[charset]; ok { + max = m } - - if mbc_max > 1 && (charset[0] != 'u' || + if max > 1 && (charset[0] != 'u' || strings.HasPrefix(locale, "ja") || strings.HasPrefix(locale, "ko") || strings.HasPrefix(locale, "zh")) { @@ -67,3 +58,24 @@ func IsEastAsian() bool { } return false } + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + locale := os.Getenv("LC_ALL") + if locale == "" { + locale = os.Getenv("LC_CTYPE") + } + if locale == "" { + locale = os.Getenv("LANG") + } + + // ignore C locale + if locale == "POSIX" || locale == "C" { + return false + } + if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { + return false + } + + return isEastAsian(locale) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_table.go b/vendor/github.com/mattn/go-runewidth/runewidth_table.go new file mode 100644 index 000000000..ad025ad52 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_table.go @@ -0,0 +1,450 @@ +// Code generated by script/generate.go. DO NOT EDIT. + +package runewidth + +var combining = table{ + {0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3}, + {0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0CF3, 0x0CF3}, + {0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x1A7F, 0x1A7F}, + {0x1AB0, 0x1ACE}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF}, + {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF}, + {0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D}, + {0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1}, + {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x10376, 0x1037A}, + {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x10F82, 0x10F85}, + {0x11300, 0x11301}, {0x1133B, 0x1133C}, {0x11366, 0x1136C}, + {0x11370, 0x11374}, {0x16AF0, 0x16AF4}, {0x1CF00, 0x1CF2D}, + {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172}, + {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD}, + {0x1D242, 0x1D244}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, + {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, + {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6}, +} + +var doublewidth = table{ + {0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A}, + {0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3}, + {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653}, + {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1}, + {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, + {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, + {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, + {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B}, + {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E}, + {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797}, + {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, + {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x303E}, + {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312F}, + {0x3131, 0x318E}, {0x3190, 0x31E3}, {0x31EF, 0x321E}, + {0x3220, 0x3247}, {0x3250, 0x4DBF}, {0x4E00, 0xA48C}, + {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, + {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, + {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE4}, {0x16FF0, 0x16FF1}, + {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 0x18D08}, + {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1AFFD, 0x1AFFE}, + {0x1B000, 0x1B122}, {0x1B132, 0x1B132}, {0x1B150, 0x1B152}, + {0x1B155, 0x1B155}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, + {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, + {0x1F240, 0x1F248}, {0x1F250, 0x1F251}, {0x1F260, 0x1F265}, + {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, {0x1F337, 0x1F37C}, + {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, {0x1F3CF, 0x1F3D3}, + {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, {0x1F3F8, 0x1F43E}, + {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, {0x1F4FF, 0x1F53D}, + {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, {0x1F57A, 0x1F57A}, + {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, {0x1F5FB, 0x1F64F}, + {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, {0x1F6D0, 0x1F6D2}, + {0x1F6D5, 0x1F6D7}, {0x1F6DC, 0x1F6DF}, {0x1F6EB, 0x1F6EC}, + {0x1F6F4, 0x1F6FC}, {0x1F7E0, 0x1F7EB}, {0x1F7F0, 0x1F7F0}, + {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1F9FF}, + {0x1FA70, 0x1FA7C}, {0x1FA80, 0x1FA88}, {0x1FA90, 0x1FABD}, + {0x1FABF, 0x1FAC5}, {0x1FACE, 0x1FADB}, {0x1FAE0, 0x1FAE8}, + {0x1FAF0, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, +} + +var ambiguous = table{ + {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, + {0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, + {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, + {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, + {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, + {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, + {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, + {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, + {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, + {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, + {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, + {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, + {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, + {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, + {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, + {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, + {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F}, + {0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, + {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, + {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, + {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, + {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, + {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E}, + {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, + {0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105}, + {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, + {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, + {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, + {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, + {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4}, + {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, + {0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F}, + {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, + {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, + {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, + {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, + {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, + {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, + {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, + {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312}, + {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, + {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1}, + {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, + {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, + {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5}, + {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, + {0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E}, + {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, + {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, + {0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF}, + {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1}, + {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1}, + {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC}, + {0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F}, + {0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF}, + {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, + {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, +} +var narrow = table{ + {0x0020, 0x007E}, {0x00A2, 0x00A3}, {0x00A5, 0x00A6}, + {0x00AC, 0x00AC}, {0x00AF, 0x00AF}, {0x27E6, 0x27ED}, + {0x2985, 0x2986}, +} + +var neutral = table{ + {0x0000, 0x001F}, {0x007F, 0x00A0}, {0x00A9, 0x00A9}, + {0x00AB, 0x00AB}, {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, + {0x00C0, 0x00C5}, {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, + {0x00D9, 0x00DD}, {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, + {0x00EB, 0x00EB}, {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, + {0x00F4, 0x00F6}, {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, + {0x00FF, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, + {0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A}, + {0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E}, + {0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C}, + {0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A}, + {0x016C, 0x01CD}, {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, + {0x01D3, 0x01D3}, {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, + {0x01D9, 0x01D9}, {0x01DB, 0x01DB}, {0x01DD, 0x0250}, + {0x0252, 0x0260}, {0x0262, 0x02C3}, {0x02C5, 0x02C6}, + {0x02C8, 0x02C8}, {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, + {0x02D1, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, + {0x02E0, 0x02FF}, {0x0370, 0x0377}, {0x037A, 0x037F}, + {0x0384, 0x038A}, {0x038C, 0x038C}, {0x038E, 0x0390}, + {0x03AA, 0x03B0}, {0x03C2, 0x03C2}, {0x03CA, 0x0400}, + {0x0402, 0x040F}, {0x0450, 0x0450}, {0x0452, 0x052F}, + {0x0531, 0x0556}, {0x0559, 0x058A}, {0x058D, 0x058F}, + {0x0591, 0x05C7}, {0x05D0, 0x05EA}, {0x05EF, 0x05F4}, + {0x0600, 0x070D}, {0x070F, 0x074A}, {0x074D, 0x07B1}, + {0x07C0, 0x07FA}, {0x07FD, 0x082D}, {0x0830, 0x083E}, + {0x0840, 0x085B}, {0x085E, 0x085E}, {0x0860, 0x086A}, + {0x0870, 0x088E}, {0x0890, 0x0891}, {0x0898, 0x0983}, + {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, + {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, + {0x09BC, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CE}, + {0x09D7, 0x09D7}, {0x09DC, 0x09DD}, {0x09DF, 0x09E3}, + {0x09E6, 0x09FE}, {0x0A01, 0x0A03}, {0x0A05, 0x0A0A}, + {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, + {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, + {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, {0x0A47, 0x0A48}, + {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, {0x0A59, 0x0A5C}, + {0x0A5E, 0x0A5E}, {0x0A66, 0x0A76}, {0x0A81, 0x0A83}, + {0x0A85, 0x0A8D}, {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, + {0x0AAA, 0x0AB0}, {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, + {0x0ABC, 0x0AC5}, {0x0AC7, 0x0AC9}, {0x0ACB, 0x0ACD}, + {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE3}, {0x0AE6, 0x0AF1}, + {0x0AF9, 0x0AFF}, {0x0B01, 0x0B03}, {0x0B05, 0x0B0C}, + {0x0B0F, 0x0B10}, {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, + {0x0B32, 0x0B33}, {0x0B35, 0x0B39}, {0x0B3C, 0x0B44}, + {0x0B47, 0x0B48}, {0x0B4B, 0x0B4D}, {0x0B55, 0x0B57}, + {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B63}, {0x0B66, 0x0B77}, + {0x0B82, 0x0B83}, {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, + {0x0B92, 0x0B95}, {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, + {0x0B9E, 0x0B9F}, {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, + {0x0BAE, 0x0BB9}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, + {0x0BCA, 0x0BCD}, {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, + {0x0BE6, 0x0BFA}, {0x0C00, 0x0C0C}, {0x0C0E, 0x0C10}, + {0x0C12, 0x0C28}, {0x0C2A, 0x0C39}, {0x0C3C, 0x0C44}, + {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, + {0x0C58, 0x0C5A}, {0x0C5D, 0x0C5D}, {0x0C60, 0x0C63}, + {0x0C66, 0x0C6F}, {0x0C77, 0x0C8C}, {0x0C8E, 0x0C90}, + {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, + {0x0CBC, 0x0CC4}, {0x0CC6, 0x0CC8}, {0x0CCA, 0x0CCD}, + {0x0CD5, 0x0CD6}, {0x0CDD, 0x0CDE}, {0x0CE0, 0x0CE3}, + {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF3}, {0x0D00, 0x0D0C}, + {0x0D0E, 0x0D10}, {0x0D12, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4F}, {0x0D54, 0x0D63}, {0x0D66, 0x0D7F}, + {0x0D81, 0x0D83}, {0x0D85, 0x0D96}, {0x0D9A, 0x0DB1}, + {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, {0x0DC0, 0x0DC6}, + {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, {0x0DD6, 0x0DD6}, + {0x0DD8, 0x0DDF}, {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF4}, + {0x0E01, 0x0E3A}, {0x0E3F, 0x0E5B}, {0x0E81, 0x0E82}, + {0x0E84, 0x0E84}, {0x0E86, 0x0E8A}, {0x0E8C, 0x0EA3}, + {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EBD}, {0x0EC0, 0x0EC4}, + {0x0EC6, 0x0EC6}, {0x0EC8, 0x0ECE}, {0x0ED0, 0x0ED9}, + {0x0EDC, 0x0EDF}, {0x0F00, 0x0F47}, {0x0F49, 0x0F6C}, + {0x0F71, 0x0F97}, {0x0F99, 0x0FBC}, {0x0FBE, 0x0FCC}, + {0x0FCE, 0x0FDA}, {0x1000, 0x10C5}, {0x10C7, 0x10C7}, + {0x10CD, 0x10CD}, {0x10D0, 0x10FF}, {0x1160, 0x1248}, + {0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258}, + {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D}, + {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, + {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, + {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A}, + {0x135D, 0x137C}, {0x1380, 0x1399}, {0x13A0, 0x13F5}, + {0x13F8, 0x13FD}, {0x1400, 0x169C}, {0x16A0, 0x16F8}, + {0x1700, 0x1715}, {0x171F, 0x1736}, {0x1740, 0x1753}, + {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1772, 0x1773}, + {0x1780, 0x17DD}, {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, + {0x1800, 0x1819}, {0x1820, 0x1878}, {0x1880, 0x18AA}, + {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1920, 0x192B}, + {0x1930, 0x193B}, {0x1940, 0x1940}, {0x1944, 0x196D}, + {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, + {0x19D0, 0x19DA}, {0x19DE, 0x1A1B}, {0x1A1E, 0x1A5E}, + {0x1A60, 0x1A7C}, {0x1A7F, 0x1A89}, {0x1A90, 0x1A99}, + {0x1AA0, 0x1AAD}, {0x1AB0, 0x1ACE}, {0x1B00, 0x1B4C}, + {0x1B50, 0x1B7E}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, + {0x1C3B, 0x1C49}, {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, + {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA}, {0x1D00, 0x1F15}, + {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, + {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, + {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, + {0x1FB6, 0x1FC4}, {0x1FC6, 0x1FD3}, {0x1FD6, 0x1FDB}, + {0x1FDD, 0x1FEF}, {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFE}, + {0x2000, 0x200F}, {0x2011, 0x2012}, {0x2017, 0x2017}, + {0x201A, 0x201B}, {0x201E, 0x201F}, {0x2023, 0x2023}, + {0x2028, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, + {0x2036, 0x203A}, {0x203C, 0x203D}, {0x203F, 0x2064}, + {0x2066, 0x2071}, {0x2075, 0x207E}, {0x2080, 0x2080}, + {0x2085, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, + {0x20AA, 0x20AB}, {0x20AD, 0x20C0}, {0x20D0, 0x20F0}, + {0x2100, 0x2102}, {0x2104, 0x2104}, {0x2106, 0x2108}, + {0x210A, 0x2112}, {0x2114, 0x2115}, {0x2117, 0x2120}, + {0x2123, 0x2125}, {0x2127, 0x212A}, {0x212C, 0x2152}, + {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F}, + {0x217A, 0x2188}, {0x218A, 0x218B}, {0x219A, 0x21B7}, + {0x21BA, 0x21D1}, {0x21D3, 0x21D3}, {0x21D5, 0x21E6}, + {0x21E8, 0x21FF}, {0x2201, 0x2201}, {0x2204, 0x2206}, + {0x2209, 0x220A}, {0x220C, 0x220E}, {0x2210, 0x2210}, + {0x2212, 0x2214}, {0x2216, 0x2219}, {0x221B, 0x221C}, + {0x2221, 0x2222}, {0x2224, 0x2224}, {0x2226, 0x2226}, + {0x222D, 0x222D}, {0x222F, 0x2233}, {0x2238, 0x223B}, + {0x223E, 0x2247}, {0x2249, 0x224B}, {0x224D, 0x2251}, + {0x2253, 0x225F}, {0x2262, 0x2263}, {0x2268, 0x2269}, + {0x226C, 0x226D}, {0x2270, 0x2281}, {0x2284, 0x2285}, + {0x2288, 0x2294}, {0x2296, 0x2298}, {0x229A, 0x22A4}, + {0x22A6, 0x22BE}, {0x22C0, 0x2311}, {0x2313, 0x2319}, + {0x231C, 0x2328}, {0x232B, 0x23E8}, {0x23ED, 0x23EF}, + {0x23F1, 0x23F2}, {0x23F4, 0x2426}, {0x2440, 0x244A}, + {0x24EA, 0x24EA}, {0x254C, 0x254F}, {0x2574, 0x257F}, + {0x2590, 0x2591}, {0x2596, 0x259F}, {0x25A2, 0x25A2}, + {0x25AA, 0x25B1}, {0x25B4, 0x25B5}, {0x25B8, 0x25BB}, + {0x25BE, 0x25BF}, {0x25C2, 0x25C5}, {0x25C9, 0x25CA}, + {0x25CC, 0x25CD}, {0x25D2, 0x25E1}, {0x25E6, 0x25EE}, + {0x25F0, 0x25FC}, {0x25FF, 0x2604}, {0x2607, 0x2608}, + {0x260A, 0x260D}, {0x2610, 0x2613}, {0x2616, 0x261B}, + {0x261D, 0x261D}, {0x261F, 0x263F}, {0x2641, 0x2641}, + {0x2643, 0x2647}, {0x2654, 0x265F}, {0x2662, 0x2662}, + {0x2666, 0x2666}, {0x266B, 0x266B}, {0x266E, 0x266E}, + {0x2670, 0x267E}, {0x2680, 0x2692}, {0x2694, 0x269D}, + {0x26A0, 0x26A0}, {0x26A2, 0x26A9}, {0x26AC, 0x26BC}, + {0x26C0, 0x26C3}, {0x26E2, 0x26E2}, {0x26E4, 0x26E7}, + {0x2700, 0x2704}, {0x2706, 0x2709}, {0x270C, 0x2727}, + {0x2729, 0x273C}, {0x273E, 0x274B}, {0x274D, 0x274D}, + {0x274F, 0x2752}, {0x2756, 0x2756}, {0x2758, 0x2775}, + {0x2780, 0x2794}, {0x2798, 0x27AF}, {0x27B1, 0x27BE}, + {0x27C0, 0x27E5}, {0x27EE, 0x2984}, {0x2987, 0x2B1A}, + {0x2B1D, 0x2B4F}, {0x2B51, 0x2B54}, {0x2B5A, 0x2B73}, + {0x2B76, 0x2B95}, {0x2B97, 0x2CF3}, {0x2CF9, 0x2D25}, + {0x2D27, 0x2D27}, {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, + {0x2D6F, 0x2D70}, {0x2D7F, 0x2D96}, {0x2DA0, 0x2DA6}, + {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, {0x2DB8, 0x2DBE}, + {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, {0x2DD0, 0x2DD6}, + {0x2DD8, 0x2DDE}, {0x2DE0, 0x2E5D}, {0x303F, 0x303F}, + {0x4DC0, 0x4DFF}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7}, + {0xA700, 0xA7CA}, {0xA7D0, 0xA7D1}, {0xA7D3, 0xA7D3}, + {0xA7D5, 0xA7D9}, {0xA7F2, 0xA82C}, {0xA830, 0xA839}, + {0xA840, 0xA877}, {0xA880, 0xA8C5}, {0xA8CE, 0xA8D9}, + {0xA8E0, 0xA953}, {0xA95F, 0xA95F}, {0xA980, 0xA9CD}, + {0xA9CF, 0xA9D9}, {0xA9DE, 0xA9FE}, {0xAA00, 0xAA36}, + {0xAA40, 0xAA4D}, {0xAA50, 0xAA59}, {0xAA5C, 0xAAC2}, + {0xAADB, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, + {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, + {0xAB30, 0xAB6B}, {0xAB70, 0xABED}, {0xABF0, 0xABF9}, + {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDFFF}, + {0xFB00, 0xFB06}, {0xFB13, 0xFB17}, {0xFB1D, 0xFB36}, + {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, + {0xFB43, 0xFB44}, {0xFB46, 0xFBC2}, {0xFBD3, 0xFD8F}, + {0xFD92, 0xFDC7}, {0xFDCF, 0xFDCF}, {0xFDF0, 0xFDFF}, + {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFC}, {0x10000, 0x1000B}, + {0x1000D, 0x10026}, {0x10028, 0x1003A}, {0x1003C, 0x1003D}, + {0x1003F, 0x1004D}, {0x10050, 0x1005D}, {0x10080, 0x100FA}, + {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018E}, + {0x10190, 0x1019C}, {0x101A0, 0x101A0}, {0x101D0, 0x101FD}, + {0x10280, 0x1029C}, {0x102A0, 0x102D0}, {0x102E0, 0x102FB}, + {0x10300, 0x10323}, {0x1032D, 0x1034A}, {0x10350, 0x1037A}, + {0x10380, 0x1039D}, {0x1039F, 0x103C3}, {0x103C8, 0x103D5}, + {0x10400, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, + {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, + {0x1056F, 0x1057A}, {0x1057C, 0x1058A}, {0x1058C, 0x10592}, + {0x10594, 0x10595}, {0x10597, 0x105A1}, {0x105A3, 0x105B1}, + {0x105B3, 0x105B9}, {0x105BB, 0x105BC}, {0x10600, 0x10736}, + {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785}, + {0x10787, 0x107B0}, {0x107B2, 0x107BA}, {0x10800, 0x10805}, + {0x10808, 0x10808}, {0x1080A, 0x10835}, {0x10837, 0x10838}, + {0x1083C, 0x1083C}, {0x1083F, 0x10855}, {0x10857, 0x1089E}, + {0x108A7, 0x108AF}, {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, + {0x108FB, 0x1091B}, {0x1091F, 0x10939}, {0x1093F, 0x1093F}, + {0x10980, 0x109B7}, {0x109BC, 0x109CF}, {0x109D2, 0x10A03}, + {0x10A05, 0x10A06}, {0x10A0C, 0x10A13}, {0x10A15, 0x10A17}, + {0x10A19, 0x10A35}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A48}, + {0x10A50, 0x10A58}, {0x10A60, 0x10A9F}, {0x10AC0, 0x10AE6}, + {0x10AEB, 0x10AF6}, {0x10B00, 0x10B35}, {0x10B39, 0x10B55}, + {0x10B58, 0x10B72}, {0x10B78, 0x10B91}, {0x10B99, 0x10B9C}, + {0x10BA9, 0x10BAF}, {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, + {0x10CC0, 0x10CF2}, {0x10CFA, 0x10D27}, {0x10D30, 0x10D39}, + {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD}, + {0x10EB0, 0x10EB1}, {0x10EFD, 0x10F27}, {0x10F30, 0x10F59}, + {0x10F70, 0x10F89}, {0x10FB0, 0x10FCB}, {0x10FE0, 0x10FF6}, + {0x11000, 0x1104D}, {0x11052, 0x11075}, {0x1107F, 0x110C2}, + {0x110CD, 0x110CD}, {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, + {0x11100, 0x11134}, {0x11136, 0x11147}, {0x11150, 0x11176}, + {0x11180, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, + {0x11213, 0x11241}, {0x11280, 0x11286}, {0x11288, 0x11288}, + {0x1128A, 0x1128D}, {0x1128F, 0x1129D}, {0x1129F, 0x112A9}, + {0x112B0, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11303}, + {0x11305, 0x1130C}, {0x1130F, 0x11310}, {0x11313, 0x11328}, + {0x1132A, 0x11330}, {0x11332, 0x11333}, {0x11335, 0x11339}, + {0x1133B, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D}, + {0x11350, 0x11350}, {0x11357, 0x11357}, {0x1135D, 0x11363}, + {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x1145B}, + {0x1145D, 0x11461}, {0x11480, 0x114C7}, {0x114D0, 0x114D9}, + {0x11580, 0x115B5}, {0x115B8, 0x115DD}, {0x11600, 0x11644}, + {0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B9}, + {0x116C0, 0x116C9}, {0x11700, 0x1171A}, {0x1171D, 0x1172B}, + {0x11730, 0x11746}, {0x11800, 0x1183B}, {0x118A0, 0x118F2}, + {0x118FF, 0x11906}, {0x11909, 0x11909}, {0x1190C, 0x11913}, + {0x11915, 0x11916}, {0x11918, 0x11935}, {0x11937, 0x11938}, + {0x1193B, 0x11946}, {0x11950, 0x11959}, {0x119A0, 0x119A7}, + {0x119AA, 0x119D7}, {0x119DA, 0x119E4}, {0x11A00, 0x11A47}, + {0x11A50, 0x11AA2}, {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09}, + {0x11C00, 0x11C08}, {0x11C0A, 0x11C36}, {0x11C38, 0x11C45}, + {0x11C50, 0x11C6C}, {0x11C70, 0x11C8F}, {0x11C92, 0x11CA7}, + {0x11CA9, 0x11CB6}, {0x11D00, 0x11D06}, {0x11D08, 0x11D09}, + {0x11D0B, 0x11D36}, {0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D}, + {0x11D3F, 0x11D47}, {0x11D50, 0x11D59}, {0x11D60, 0x11D65}, + {0x11D67, 0x11D68}, {0x11D6A, 0x11D8E}, {0x11D90, 0x11D91}, + {0x11D93, 0x11D98}, {0x11DA0, 0x11DA9}, {0x11EE0, 0x11EF8}, + {0x11F00, 0x11F10}, {0x11F12, 0x11F3A}, {0x11F3E, 0x11F59}, + {0x11FB0, 0x11FB0}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399}, + {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, + {0x12F90, 0x12FF2}, {0x13000, 0x13455}, {0x14400, 0x14646}, + {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, + {0x16A6E, 0x16ABE}, {0x16AC0, 0x16AC9}, {0x16AD0, 0x16AED}, + {0x16AF0, 0x16AF5}, {0x16B00, 0x16B45}, {0x16B50, 0x16B59}, + {0x16B5B, 0x16B61}, {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, + {0x16E40, 0x16E9A}, {0x16F00, 0x16F4A}, {0x16F4F, 0x16F87}, + {0x16F8F, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, + {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BCA3}, + {0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1CF50, 0x1CFC3}, + {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D1EA}, + {0x1D200, 0x1D245}, {0x1D2C0, 0x1D2D3}, {0x1D2E0, 0x1D2F3}, + {0x1D300, 0x1D356}, {0x1D360, 0x1D378}, {0x1D400, 0x1D454}, + {0x1D456, 0x1D49C}, {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, + {0x1D4A5, 0x1D4A6}, {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, + {0x1D4BB, 0x1D4BB}, {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, + {0x1D507, 0x1D50A}, {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, + {0x1D51E, 0x1D539}, {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, + {0x1D546, 0x1D546}, {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, + {0x1D6A8, 0x1D7CB}, {0x1D7CE, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, + {0x1DAA1, 0x1DAAF}, {0x1DF00, 0x1DF1E}, {0x1DF25, 0x1DF2A}, + {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E030, 0x1E06D}, + {0x1E08F, 0x1E08F}, {0x1E100, 0x1E12C}, {0x1E130, 0x1E13D}, + {0x1E140, 0x1E149}, {0x1E14E, 0x1E14F}, {0x1E290, 0x1E2AE}, + {0x1E2C0, 0x1E2F9}, {0x1E2FF, 0x1E2FF}, {0x1E4D0, 0x1E4F9}, + {0x1E7E0, 0x1E7E6}, {0x1E7E8, 0x1E7EB}, {0x1E7ED, 0x1E7EE}, + {0x1E7F0, 0x1E7FE}, {0x1E800, 0x1E8C4}, {0x1E8C7, 0x1E8D6}, + {0x1E900, 0x1E94B}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, + {0x1EC71, 0x1ECB4}, {0x1ED01, 0x1ED3D}, {0x1EE00, 0x1EE03}, + {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, {0x1EE24, 0x1EE24}, + {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, {0x1EE34, 0x1EE37}, + {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, {0x1EE42, 0x1EE42}, + {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, {0x1EE4B, 0x1EE4B}, + {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, {0x1EE54, 0x1EE54}, + {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, {0x1EE5B, 0x1EE5B}, + {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, {0x1EE61, 0x1EE62}, + {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, {0x1EE6C, 0x1EE72}, + {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, {0x1EE7E, 0x1EE7E}, + {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, {0x1EEA1, 0x1EEA3}, + {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, {0x1EEF0, 0x1EEF1}, + {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, {0x1F030, 0x1F093}, + {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CE}, + {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10F}, {0x1F12E, 0x1F12F}, + {0x1F16A, 0x1F16F}, {0x1F1AD, 0x1F1AD}, {0x1F1E6, 0x1F1FF}, + {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, + {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, + {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, + {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, + {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, + {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, + {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6D3, 0x1F6D4}, + {0x1F6E0, 0x1F6EA}, {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F776}, + {0x1F77B, 0x1F7D9}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, + {0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, + {0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F90B}, {0x1F93B, 0x1F93B}, + {0x1F946, 0x1F946}, {0x1FA00, 0x1FA53}, {0x1FA60, 0x1FA6D}, + {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA}, {0x1FBF0, 0x1FBF9}, + {0xE0001, 0xE0001}, {0xE0020, 0xE007F}, +} + +var emoji = table{ + {0x203C, 0x203C}, {0x2049, 0x2049}, {0x2122, 0x2122}, + {0x2139, 0x2139}, {0x2194, 0x2199}, {0x21A9, 0x21AA}, + {0x231A, 0x231B}, {0x2328, 0x2328}, {0x2388, 0x2388}, + {0x23CF, 0x23CF}, {0x23E9, 0x23F3}, {0x23F8, 0x23FA}, + {0x24C2, 0x24C2}, {0x25AA, 0x25AB}, {0x25B6, 0x25B6}, + {0x25C0, 0x25C0}, {0x25FB, 0x25FE}, {0x2600, 0x2605}, + {0x2607, 0x2612}, {0x2614, 0x2685}, {0x2690, 0x2705}, + {0x2708, 0x2712}, {0x2714, 0x2714}, {0x2716, 0x2716}, + {0x271D, 0x271D}, {0x2721, 0x2721}, {0x2728, 0x2728}, + {0x2733, 0x2734}, {0x2744, 0x2744}, {0x2747, 0x2747}, + {0x274C, 0x274C}, {0x274E, 0x274E}, {0x2753, 0x2755}, + {0x2757, 0x2757}, {0x2763, 0x2767}, {0x2795, 0x2797}, + {0x27A1, 0x27A1}, {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, + {0x2934, 0x2935}, {0x2B05, 0x2B07}, {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x3030, 0x3030}, + {0x303D, 0x303D}, {0x3297, 0x3297}, {0x3299, 0x3299}, + {0x1F000, 0x1F0FF}, {0x1F10D, 0x1F10F}, {0x1F12F, 0x1F12F}, + {0x1F16C, 0x1F171}, {0x1F17E, 0x1F17F}, {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, {0x1F1AD, 0x1F1E5}, {0x1F201, 0x1F20F}, + {0x1F21A, 0x1F21A}, {0x1F22F, 0x1F22F}, {0x1F232, 0x1F23A}, + {0x1F23C, 0x1F23F}, {0x1F249, 0x1F3FA}, {0x1F400, 0x1F53D}, + {0x1F546, 0x1F64F}, {0x1F680, 0x1F6FF}, {0x1F774, 0x1F77F}, + {0x1F7D5, 0x1F7FF}, {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, + {0x1F85A, 0x1F85F}, {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F8FF}, + {0x1F90C, 0x1F93A}, {0x1F93C, 0x1F945}, {0x1F947, 0x1FAFF}, + {0x1FC00, 0x1FFFD}, +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go index bdd84454b..5f987a310 100644 --- a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -1,3 +1,6 @@ +//go:build windows && !appengine +// +build windows,!appengine + package runewidth import ( @@ -9,6 +12,7 @@ var ( procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") ) +// IsEastAsian return true if the current locale is CJK func IsEastAsian() bool { r1, _, _ := procGetConsoleOutputCP.Call() if r1 == 0 { diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go index 47e1f9ef8..25378537e 100644 --- a/vendor/github.com/mitchellh/go-homedir/homedir.go +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -76,34 +76,62 @@ func Expand(path string) (string, error) { return filepath.Join(dir, path[1:]), nil } +// Reset clears the cache, forcing the next call to Dir to re-detect +// the home directory. This generally never has to be called, but can be +// useful in tests if you're modifying the home directory via the HOME +// env var or something. +func Reset() { + cacheLock.Lock() + defer cacheLock.Unlock() + homedirCache = "" +} + func dirUnix() (string, error) { + homeEnv := "HOME" + if runtime.GOOS == "plan9" { + // On plan9, env vars are lowercase. + homeEnv = "home" + } + // First prefer the HOME environmental variable - if home := os.Getenv("HOME"); home != "" { + if home := os.Getenv(homeEnv); home != "" { return home, nil } - // If that fails, try getent var stdout bytes.Buffer - cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) - cmd.Stdout = &stdout - if err := cmd.Run(); err != nil { - // If the error is ErrNotFound, we ignore it. Otherwise, return it. - if err != exec.ErrNotFound { - return "", err + + // If that fails, try OS specific commands + if runtime.GOOS == "darwin" { + cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + result := strings.TrimSpace(stdout.String()) + if result != "" { + return result, nil + } } } else { - if passwd := strings.TrimSpace(stdout.String()); passwd != "" { - // username:password:uid:gid:gecos:home:shell - passwdParts := strings.SplitN(passwd, ":", 7) - if len(passwdParts) > 5 { - return passwdParts[5], nil + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } } } } // If all else fails, try the shell stdout.Reset() - cmd = exec.Command("sh", "-c", "cd && pwd") + cmd := exec.Command("sh", "-c", "cd && pwd") cmd.Stdout = &stdout if err := cmd.Run(); err != nil { return "", err @@ -123,14 +151,16 @@ func dirWindows() (string, error) { return home, nil } + // Prefer standard environment variable USERPROFILE + if home := os.Getenv("USERPROFILE"); home != "" { + return home, nil + } + drive := os.Getenv("HOMEDRIVE") path := os.Getenv("HOMEPATH") home := drive + path if drive == "" || path == "" { - home = os.Getenv("USERPROFILE") - } - if home == "" { - return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") + return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank") } return home, nil diff --git a/vendor/github.com/nxadm/tail/.cirrus.yml b/vendor/github.com/nxadm/tail/.cirrus.yml new file mode 100644 index 000000000..97e1b978e --- /dev/null +++ b/vendor/github.com/nxadm/tail/.cirrus.yml @@ -0,0 +1,8 @@ +task: + name: FreeBSD + freebsd_instance: + image_family: freebsd-12-2 + install_script: pkg install -y go + script: | + go build + go test -v -race -timeout 2m ./... diff --git a/vendor/github.com/nxadm/tail/.gitignore b/vendor/github.com/nxadm/tail/.gitignore index 35d9351d3..063e5a65a 100644 --- a/vendor/github.com/nxadm/tail/.gitignore +++ b/vendor/github.com/nxadm/tail/.gitignore @@ -1,3 +1,2 @@ .idea/ -.test/ -examples/_* \ No newline at end of file +examples/_* diff --git a/vendor/github.com/nxadm/tail/CHANGES.md b/vendor/github.com/nxadm/tail/CHANGES.md index 224e54b44..e6c74d773 100644 --- a/vendor/github.com/nxadm/tail/CHANGES.md +++ b/vendor/github.com/nxadm/tail/CHANGES.md @@ -1,7 +1,15 @@ +# Version v1.4.11 +* Bump fsnotify to v1.6.0. Should fix some issues. + +# Version v1.4.9 +* Bump fsnotify to v1.5.1 fixes issue #28, hpcloud/tail#90. +* PR #27: "Add timeout to tests"by @kokes++. Also timeout on FreeBSD. +* PR #29: "Use temp directory for tests, instead of relative" by @ches++. + # Version v1.4.7-v1.4.8 * Documentation updates. * Small linter cleanups. -* Added example in test. +* Added example in test. # Version v1.4.6 diff --git a/vendor/github.com/nxadm/tail/CONTRIBUTING.md b/vendor/github.com/nxadm/tail/CONTRIBUTING.md new file mode 100644 index 000000000..23c99ddde --- /dev/null +++ b/vendor/github.com/nxadm/tail/CONTRIBUTING.md @@ -0,0 +1,5 @@ +# Contributing +Comments (at Discussions), Issues and PRs are always welcome. In the case of issues, +code examples make it easier to reproduce the problem. In the case of PRs add tests +if applicable so we make sure nothing breaks for people using the library on different +OSes. diff --git a/vendor/github.com/nxadm/tail/README.md b/vendor/github.com/nxadm/tail/README.md index f47939c74..fca8901c0 100644 --- a/vendor/github.com/nxadm/tail/README.md +++ b/vendor/github.com/nxadm/tail/README.md @@ -1,12 +1,13 @@ -![ci](https://github.com/nxadm/tail/workflows/ci/badge.svg)[![Go Reference](https://pkg.go.dev/badge/github.com/nxadm/tail.svg)](https://pkg.go.dev/github.com/nxadm/tail) - +[![Go Reference](https://pkg.go.dev/badge/github.com/nxadm/tail.svg)](https://pkg.go.dev/github.com/nxadm/tail#section-documentation) +![ci](https://github.com/nxadm/tail/workflows/ci/badge.svg) +[![FreeBSD](https://api.cirrus-ci.com/github/nxadm/tail.svg)](https://cirrus-ci.com/github/nxadm/tail) # tail functionality in Go nxadm/tail provides a Go library that emulates the features of the BSD `tail` program. The library comes with full support for truncation/move detection as it is designed to work with log rotation tools. The library works on all -operating systems supported by Go, including POSIX systems like Linux and -*BSD, and MS Windows. Go 1.9 is the oldest compiler release supported. +operating systems supported by Go, including POSIX systems like Linux, *BSD, +MacOS, and MS Windows. Go 1.12 is the oldest compiler release supported. A simple example: @@ -24,7 +25,7 @@ for line := range t.Lines { } ``` -See [API documentation](https://pkg.go.dev/github.com/nxadm/tail). +See [API documentation](https://pkg.go.dev/github.com/nxadm/tail#section-documentation). ## Installing @@ -41,4 +42,4 @@ nxadm/tail continues the development by keeping up to date with the Go toolchain and fixing bugs. ## Examples -Examples, e.g. used to debug an issue, are kept in the [examples directory](/examples). \ No newline at end of file +Examples, e.g. used to debug an issue, are kept in the [examples directory](/examples). diff --git a/vendor/github.com/nxadm/tail/tail.go b/vendor/github.com/nxadm/tail/tail.go index 37ea4411e..c962599be 100644 --- a/vendor/github.com/nxadm/tail/tail.go +++ b/vendor/github.com/nxadm/tail/tail.go @@ -77,8 +77,9 @@ type Config struct { Pipe bool // The file is a named pipe (mkfifo) // Generic IO - Follow bool // Continue looking for new lines (tail -f) - MaxLineSize int // If non-zero, split longer lines into multiple lines + Follow bool // Continue looking for new lines (tail -f) + MaxLineSize int // If non-zero, split longer lines into multiple lines + CompleteLines bool // Only return complete lines (that end with "\n" or EOF when Follow is false) // Optionally, use a ratelimiter (e.g. created by the ratelimiter/NewLeakyBucket function) RateLimiter *ratelimiter.LeakyBucket @@ -97,6 +98,8 @@ type Tail struct { reader *bufio.Reader lineNum int + lineBuf *strings.Builder + watcher watch.FileWatcher changes *watch.FileChanges @@ -128,6 +131,10 @@ func TailFile(filename string, config Config) (*Tail, error) { Config: config, } + if config.CompleteLines { + t.lineBuf = new(strings.Builder) + } + // when Logger was not specified in config, use default logger if t.Logger == nil { t.Logger = DefaultLogger @@ -202,6 +209,9 @@ func (tail *Tail) closeFile() { } func (tail *Tail) reopen() error { + if tail.lineBuf != nil { + tail.lineBuf.Reset() + } tail.closeFile() tail.lineNum = 0 for { @@ -229,16 +239,32 @@ func (tail *Tail) readLine() (string, error) { tail.lk.Lock() line, err := tail.reader.ReadString('\n') tail.lk.Unlock() - if err != nil { + + newlineEnding := strings.HasSuffix(line, "\n") + line = strings.TrimRight(line, "\n") + + // if we don't have to handle incomplete lines, we can return the line as-is + if !tail.Config.CompleteLines { // Note ReadString "returns the data read before the error" in // case of an error, including EOF, so we return it as is. The // caller is expected to process it if err is EOF. return line, err } - line = strings.TrimRight(line, "\n") + if _, err := tail.lineBuf.WriteString(line); err != nil { + return line, err + } - return line, err + if newlineEnding { + line = tail.lineBuf.String() + tail.lineBuf.Reset() + return line, nil + } else { + if tail.Config.Follow { + line = "" + } + return line, io.EOF + } } func (tail *Tail) tailFileSync() { diff --git a/vendor/github.com/olekukonko/tablewriter/.gitignore b/vendor/github.com/olekukonko/tablewriter/.gitignore new file mode 100644 index 000000000..b66cec635 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/.gitignore @@ -0,0 +1,15 @@ +# Created by .ignore support plugin (hsz.mobi) +### Go template +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + diff --git a/vendor/github.com/olekukonko/tablewriter/.travis.yml b/vendor/github.com/olekukonko/tablewriter/.travis.yml index 354b7f8b2..366d48a35 100644 --- a/vendor/github.com/olekukonko/tablewriter/.travis.yml +++ b/vendor/github.com/olekukonko/tablewriter/.travis.yml @@ -1,8 +1,22 @@ language: go - +arch: + - ppc64le + - amd64 go: - - 1.1 - - 1.2 - 1.3 - 1.4 + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 + - "1.10" - tip +jobs: + exclude : + - arch : ppc64le + go : + - 1.3 + - arch : ppc64le + go : + - 1.4 diff --git a/vendor/github.com/olekukonko/tablewriter/LICENCE.md b/vendor/github.com/olekukonko/tablewriter/LICENSE.md similarity index 98% rename from vendor/github.com/olekukonko/tablewriter/LICENCE.md rename to vendor/github.com/olekukonko/tablewriter/LICENSE.md index 1fd848425..a0769b5c1 100644 --- a/vendor/github.com/olekukonko/tablewriter/LICENCE.md +++ b/vendor/github.com/olekukonko/tablewriter/LICENSE.md @@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md index 805330adc..f06530d75 100644 --- a/vendor/github.com/olekukonko/tablewriter/README.md +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -1,11 +1,13 @@ ASCII Table Writer ========= -[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) [![Total views](https://sourcegraph.com/api/repos/github.com/olekukonko/tablewriter/counters/views.png)](https://sourcegraph.com/github.com/olekukonko/tablewriter) +[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) +[![Total views](https://img.shields.io/sourcegraph/rrc/github.com/olekukonko/tablewriter.svg)](https://sourcegraph.com/github.com/olekukonko/tablewriter) +[![Godoc](https://godoc.org/github.com/olekukonko/tablewriter?status.svg)](https://godoc.org/github.com/olekukonko/tablewriter) Generate ASCII table on the fly ... Installation is simple as - go get github.com/olekukonko/tablewriter + go get github.com/olekukonko/tablewriter #### Features @@ -22,7 +24,8 @@ Generate ASCII table on the fly ... Installation is simple as - Enable or disable table border - Set custom footer support - Optional identical cells merging - +- Set custom caption +- Optional reflowing of paragraphs in multi-line cells. #### Example 1 - Basic ```go @@ -75,21 +78,21 @@ table.Render() ``` DATE | DESCRIPTION | CV2 | AMOUNT -+----------+--------------------------+-------+---------+ +-----------+--------------------------+-------+---------- 1/1/2014 | Domain name | 2233 | $10.98 1/1/2014 | January Hosting | 2233 | $54.95 1/4/2014 | February Hosting | 2233 | $51.00 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 -+----------+--------------------------+-------+---------+ +-----------+--------------------------+-------+---------- TOTAL | $146 93 - +-------+---------+ + --------+---------- ``` #### Example 3 - CSV ```go -table, _ := tablewriter.NewCSV(os.Stdout, "test_info.csv", true) +table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test_info.csv", true) table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment table.Render() ``` @@ -107,12 +110,12 @@ table.Render() #### Example 4 - Custom Separator ```go -table, _ := tablewriter.NewCSV(os.Stdout, "test.csv", true) +table, _ := tablewriter.NewCSV(os.Stdout, "testdata/test.csv", true) table.SetRowLine(true) // Enable row line // Change table lines table.SetCenterSeparator("*") -table.SetColumnSeparator("‡") +table.SetColumnSeparator("╪") table.SetRowSeparator("-") table.SetAlignment(tablewriter.ALIGN_LEFT) @@ -132,7 +135,7 @@ table.Render() *------------*-----------*---------* ``` -##### Example 5 - Markdown Format +#### Example 5 - Markdown Format ```go data := [][]string{ []string{"1/1/2014", "Domain name", "2233", "$10.98"}, @@ -194,11 +197,235 @@ table.Render() +----------+--------------------------+-------+---------+ ``` +#### Example 7 - Identical cells merging (specify the column index to merge) +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "1234", "$10.98"}, + []string{"1/1/2014", "January Hosting", "1234", "$10.98"}, + []string{"1/4/2014", "February Hosting", "3456", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) +table.SetAutoMergeCellsByColumnIndex([]int{2, 3}) +table.SetRowLine(true) +table.AppendBulk(data) +table.Render() +``` + +##### Output 7 +``` ++----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 1234 | $10.98 | ++----------+--------------------------+ + + +| 1/1/2014 | January Hosting | | | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Hosting | 3456 | $51.00 | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $146.93 | ++----------+--------------------------+-------+---------+ +``` + + +#### Table with color +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.SetBorder(false) // Set Border to false + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, + tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, + tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, + tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.FgHiRedColor}) + +table.AppendBulk(data) +table.Render() +``` + +#### Table with color Output +![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) + +#### Example - 8 Table Cells with Color + +Individual Cell Colors from `func Rich` take precedence over Column Colors + +```go +data := [][]string{ + []string{"Test1Merge", "HelloCol2 - 1", "HelloCol3 - 1", "HelloCol4 - 1"}, + []string{"Test1Merge", "HelloCol2 - 2", "HelloCol3 - 2", "HelloCol4 - 2"}, + []string{"Test1Merge", "HelloCol2 - 3", "HelloCol3 - 3", "HelloCol4 - 3"}, + []string{"Test2Merge", "HelloCol2 - 4", "HelloCol3 - 4", "HelloCol4 - 4"}, + []string{"Test2Merge", "HelloCol2 - 5", "HelloCol3 - 5", "HelloCol4 - 5"}, + []string{"Test2Merge", "HelloCol2 - 6", "HelloCol3 - 6", "HelloCol4 - 6"}, + []string{"Test2Merge", "HelloCol2 - 7", "HelloCol3 - 7", "HelloCol4 - 7"}, + []string{"Test3Merge", "HelloCol2 - 8", "HelloCol3 - 8", "HelloCol4 - 8"}, + []string{"Test3Merge", "HelloCol2 - 9", "HelloCol3 - 9", "HelloCol4 - 9"}, + []string{"Test3Merge", "HelloCol2 - 10", "HelloCol3 -10", "HelloCol4 - 10"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Col1", "Col2", "Col3", "Col4"}) +table.SetFooter([]string{"", "", "Footer3", "Footer4"}) +table.SetBorder(false) + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, + tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, + tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, + tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.FgHiRedColor}) + +colorData1 := []string{"TestCOLOR1Merge", "HelloCol2 - COLOR1", "HelloCol3 - COLOR1", "HelloCol4 - COLOR1"} +colorData2 := []string{"TestCOLOR2Merge", "HelloCol2 - COLOR2", "HelloCol3 - COLOR2", "HelloCol4 - COLOR2"} + +for i, row := range data { + if i == 4 { + table.Rich(colorData1, []tablewriter.Colors{tablewriter.Colors{}, tablewriter.Colors{tablewriter.Normal, tablewriter.FgCyanColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgWhiteColor}, tablewriter.Colors{}}) + table.Rich(colorData2, []tablewriter.Colors{tablewriter.Colors{tablewriter.Normal, tablewriter.FgMagentaColor}, tablewriter.Colors{}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgRedColor}, tablewriter.Colors{tablewriter.FgHiGreenColor, tablewriter.Italic, tablewriter.BgHiCyanColor}}) + } + table.Append(row) +} + +table.SetAutoMergeCells(true) +table.Render() + +``` + +##### Table cells with color Output +![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png) + +#### Example 9 - Set table caption +```go +data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) +table.SetCaption(true, "Movie ratings.") + +for _, v := range data { + table.Append(v) +} +table.Render() // Send output +``` + +Note: Caption text will wrap with total width of rendered table. + +##### Output 9 +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +Movie ratings. +``` + +#### Example 10 - Set NoWhiteSpace and TablePadding option +```go +data := [][]string{ + {"node1.example.com", "Ready", "compute", "1.11"}, + {"node2.example.com", "Ready", "compute", "1.11"}, + {"node3.example.com", "Ready", "compute", "1.11"}, + {"node4.example.com", "NotReady", "compute", "1.11"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Status", "Role", "Version"}) +table.SetAutoWrapText(false) +table.SetAutoFormatHeaders(true) +table.SetHeaderAlignment(ALIGN_LEFT) +table.SetAlignment(ALIGN_LEFT) +table.SetCenterSeparator("") +table.SetColumnSeparator("") +table.SetRowSeparator("") +table.SetHeaderLine(false) +table.SetBorder(false) +table.SetTablePadding("\t") // pad with tabs +table.SetNoWhiteSpace(true) +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 10 +``` +NAME STATUS ROLE VERSION +node1.example.com Ready compute 1.11 +node2.example.com Ready compute 1.11 +node3.example.com Ready compute 1.11 +node4.example.com NotReady compute 1.11 +``` + +#### Render table into a string + +Instead of rendering the table to `io.Stdout` you can also render it into a string. Go 1.10 introduced the `strings.Builder` type which implements the `io.Writer` interface and can therefore be used for this task. Example: + +```go +package main + +import ( + "strings" + "fmt" + + "github.com/olekukonko/tablewriter" +) + +func main() { + tableString := &strings.Builder{} + table := tablewriter.NewWriter(tableString) + + /* + * Code to fill the table + */ + + table.Render() + + fmt.Println(tableString.String()) +} +``` + #### TODO - ~~Import Directly from CSV~~ - `done` - ~~Support for `SetFooter`~~ - `done` - ~~Support for `SetBorder`~~ - `done` - ~~Support table with uneven rows~~ - `done` -- Support custom alignment +- ~~Support custom alignment~~ - General Improvement & Optimisation - `NewHTML` Parse table from HTML diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go index 3314bfba5..f913149c6 100644 --- a/vendor/github.com/olekukonko/tablewriter/table.go +++ b/vendor/github.com/olekukonko/tablewriter/table.go @@ -36,8 +36,8 @@ const ( ) var ( - decimal = regexp.MustCompile(`^-*\d*\.?\d*$`) - percent = regexp.MustCompile(`^-*\d*\.?\d*$%$`) + decimal = regexp.MustCompile(`^-?(?:\d{1,3}(?:,\d{3})*|\d+)(?:\.\d+)?$`) + percent = regexp.MustCompile(`^-?\d+\.?\d*$%$`) ) type Border struct { @@ -48,64 +48,81 @@ type Border struct { } type Table struct { - out io.Writer - rows [][]string - lines [][][]string - cs map[int]int - rs map[int]int - headers []string - footers []string - autoFmt bool - autoWrap bool - mW int - pCenter string - pRow string - pColumn string - tColumn int - tRow int - hAlign int - fAlign int - align int - newLine string - rowLine bool - autoMergeCells bool - hdrLine bool - borders Border - colSize int + out io.Writer + rows [][]string + lines [][][]string + cs map[int]int + rs map[int]int + headers [][]string + footers [][]string + caption bool + captionText string + autoFmt bool + autoWrap bool + reflowText bool + mW int + pCenter string + pRow string + pColumn string + tColumn int + tRow int + hAlign int + fAlign int + align int + newLine string + rowLine bool + autoMergeCells bool + columnsToAutoMergeCells map[int]bool + noWhiteSpace bool + tablePadding string + hdrLine bool + borders Border + colSize int + headerParams []string + columnsParams []string + footerParams []string + columnsAlign []int } // Start New Table // Take io.Writer Directly func NewWriter(writer io.Writer) *Table { t := &Table{ - out: writer, - rows: [][]string{}, - lines: [][][]string{}, - cs: make(map[int]int), - rs: make(map[int]int), - headers: []string{}, - footers: []string{}, - autoFmt: true, - autoWrap: true, - mW: MAX_ROW_WIDTH, - pCenter: CENTER, - pRow: ROW, - pColumn: COLUMN, - tColumn: -1, - tRow: -1, - hAlign: ALIGN_DEFAULT, - fAlign: ALIGN_DEFAULT, - align: ALIGN_DEFAULT, - newLine: NEWLINE, - rowLine: false, - hdrLine: true, - borders: Border{Left: true, Right: true, Bottom: true, Top: true}, - colSize: -1} + out: writer, + rows: [][]string{}, + lines: [][][]string{}, + cs: make(map[int]int), + rs: make(map[int]int), + headers: [][]string{}, + footers: [][]string{}, + caption: false, + captionText: "Table caption.", + autoFmt: true, + autoWrap: true, + reflowText: true, + mW: MAX_ROW_WIDTH, + pCenter: CENTER, + pRow: ROW, + pColumn: COLUMN, + tColumn: -1, + tRow: -1, + hAlign: ALIGN_DEFAULT, + fAlign: ALIGN_DEFAULT, + align: ALIGN_DEFAULT, + newLine: NEWLINE, + rowLine: false, + hdrLine: true, + borders: Border{Left: true, Right: true, Bottom: true, Top: true}, + colSize: -1, + headerParams: []string{}, + columnsParams: []string{}, + footerParams: []string{}, + columnsAlign: []int{}} return t } // Render table output -func (t Table) Render() { +func (t *Table) Render() { if t.borders.Top { t.printLine(true) } @@ -115,20 +132,27 @@ func (t Table) Render() { } else { t.printRows() } - if !t.rowLine && t.borders.Bottom { t.printLine(true) } t.printFooter() + if t.caption { + t.printCaption() + } } +const ( + headerRowIdx = -1 + footerRowIdx = -2 +) + // Set table header func (t *Table) SetHeader(keys []string) { t.colSize = len(keys) for i, v := range keys { - t.parseDimension(v, i, -1) - t.headers = append(t.headers, v) + lines := t.parseDimension(v, i, headerRowIdx) + t.headers = append(t.headers, lines) } } @@ -136,8 +160,16 @@ func (t *Table) SetHeader(keys []string) { func (t *Table) SetFooter(keys []string) { //t.colSize = len(keys) for i, v := range keys { - t.parseDimension(v, i, -1) - t.footers = append(t.footers, v) + lines := t.parseDimension(v, i, footerRowIdx) + t.footers = append(t.footers, lines) + } +} + +// Set table Caption +func (t *Table) SetCaption(caption bool, captionText ...string) { + t.caption = caption + if len(captionText) == 1 { + t.captionText = captionText[0] } } @@ -151,11 +183,21 @@ func (t *Table) SetAutoWrapText(auto bool) { t.autoWrap = auto } +// Turn automatic reflowing of multiline text when rewrapping. Default is on (true). +func (t *Table) SetReflowDuringAutoWrap(auto bool) { + t.reflowText = auto +} + // Set the Default column width func (t *Table) SetColWidth(width int) { t.mW = width } +// Set the minimal width for a column +func (t *Table) SetColMinWidth(column int, width int) { + t.cs[column] = width +} + // Set the Column Separator func (t *Table) SetColumnSeparator(sep string) { t.pColumn = sep @@ -186,6 +228,32 @@ func (t *Table) SetAlignment(align int) { t.align = align } +// Set No White Space +func (t *Table) SetNoWhiteSpace(allow bool) { + t.noWhiteSpace = allow +} + +// Set Table Padding +func (t *Table) SetTablePadding(padding string) { + t.tablePadding = padding +} + +func (t *Table) SetColumnAlignment(keys []int) { + for _, v := range keys { + switch v { + case ALIGN_CENTER: + break + case ALIGN_LEFT: + break + case ALIGN_RIGHT: + break + default: + v = ALIGN_DEFAULT + } + t.columnsAlign = append(t.columnsAlign, v) + } +} + // Set New Line func (t *Table) SetNewLine(nl string) { t.newLine = nl @@ -209,6 +277,21 @@ func (t *Table) SetAutoMergeCells(auto bool) { t.autoMergeCells = auto } +// Set Auto Merge Cells By Column Index +// This would enable / disable the merge of cells with identical values for specific columns +// If cols is empty, it is the same as `SetAutoMergeCells(true)`. +func (t *Table) SetAutoMergeCellsByColumnIndex(cols []int) { + t.autoMergeCells = true + + if len(cols) > 0 { + m := make(map[int]bool) + for _, col := range cols { + m[col] = true + } + t.columnsToAutoMergeCells = m + } +} + // Set Table Border // This would enable / disable line around the table func (t *Table) SetBorder(border bool) { @@ -241,6 +324,33 @@ func (t *Table) Append(row []string) { t.lines = append(t.lines, line) } +// Append row to table with color attributes +func (t *Table) Rich(row []string, colors []Colors) { + rowSize := len(t.headers) + if rowSize > t.colSize { + t.colSize = rowSize + } + + n := len(t.lines) + line := [][]string{} + for i, v := range row { + + // Detect string width + // Detect String height + // Break strings into words + out := t.parseDimension(v, i, n) + + if len(colors) > i { + color := colors[i] + out[0] = format(out[0], color) + } + + // Append broken words + line = append(line, out) + } + t.lines = append(t.lines, line) +} + // Allow Support for Bulk Append // Eliminates repeated for loops func (t *Table) AppendBulk(rows [][]string) { @@ -249,16 +359,44 @@ func (t *Table) AppendBulk(rows [][]string) { } } +// NumLines to get the number of lines +func (t *Table) NumLines() int { + return len(t.lines) +} + +// Clear rows +func (t *Table) ClearRows() { + t.lines = [][][]string{} +} + +// Clear footer +func (t *Table) ClearFooter() { + t.footers = [][]string{} +} + +// Center based on position and border. +func (t *Table) center(i int) string { + if i == -1 && !t.borders.Left { + return t.pRow + } + + if i == len(t.cs)-1 && !t.borders.Right { + return t.pRow + } + + return t.pCenter +} + // Print line based on row width -func (t Table) printLine(nl bool) { - fmt.Fprint(t.out, t.pCenter) +func (t *Table) printLine(nl bool) { + fmt.Fprint(t.out, t.center(-1)) for i := 0; i < len(t.cs); i++ { v := t.cs[i] fmt.Fprintf(t.out, "%s%s%s%s", t.pRow, strings.Repeat(string(t.pRow), v), t.pRow, - t.pCenter) + t.center(i)) } if nl { fmt.Fprint(t.out, t.newLine) @@ -266,7 +404,7 @@ func (t Table) printLine(nl bool) { } // Print line based on row width with our without cell separator -func (t Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { +func (t *Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { fmt.Fprint(t.out, t.pCenter) for i := 0; i < len(t.cs); i++ { v := t.cs[i] @@ -303,43 +441,82 @@ func pad(align int) func(string, string, int) string { } // Print heading information -func (t Table) printHeading() { +func (t *Table) printHeading() { // Check if headers is available if len(t.headers) < 1 { return } - // Check if border is set - // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) - // Identify last column end := len(t.cs) - 1 // Get pad function padFunc := pad(t.hAlign) - // Print Heading column - for i := 0; i <= end; i++ { - v := t.cs[i] - h := t.headers[i] - if t.autoFmt { - h = Title(h) + // Checking for ANSI escape sequences for header + is_esc_seq := false + if len(t.headerParams) > 0 { + is_esc_seq = true + } + + // Maximum height. + max := t.rs[headerRowIdx] + + // Print Heading + for x := 0; x < max; x++ { + // Check if border is set + // Replace with space if not set + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + } + + for y := 0; y <= end; y++ { + v := t.cs[y] + h := "" + + if y < len(t.headers) && x < len(t.headers[y]) { + h = t.headers[y][x] + } + if t.autoFmt { + h = Title(h) + } + pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn) + if t.noWhiteSpace { + pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding) + } + if is_esc_seq { + if !t.noWhiteSpace { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } else { + fmt.Fprintf(t.out, "%s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } + } else { + if !t.noWhiteSpace { + fmt.Fprintf(t.out, " %s %s", + padFunc(h, SPACE, v), + pad) + } else { + // the spaces between breaks the kube formatting + fmt.Fprintf(t.out, "%s%s", + padFunc(h, SPACE, v), + pad) + } + } } - pad := ConditionString((i == end && !t.borders.Left), SPACE, t.pColumn) - fmt.Fprintf(t.out, " %s %s", - padFunc(h, SPACE, v), - pad) + // Next line + fmt.Fprint(t.out, t.newLine) } - // Next line - fmt.Fprint(t.out, t.newLine) if t.hdrLine { t.printLine(true) } } // Print heading information -func (t Table) printFooter() { +func (t *Table) printFooter() { // Check if headers is available if len(t.footers) < 1 { return @@ -349,9 +526,6 @@ func (t Table) printFooter() { if !t.borders.Bottom { t.printLine(true) } - // Check if border is set - // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) // Identify last column end := len(t.cs) - 1 @@ -359,25 +533,56 @@ func (t Table) printFooter() { // Get pad function padFunc := pad(t.fAlign) - // Print Heading column - for i := 0; i <= end; i++ { - v := t.cs[i] - f := t.footers[i] - if t.autoFmt { - f = Title(f) - } - pad := ConditionString((i == end && !t.borders.Top), SPACE, t.pColumn) + // Checking for ANSI escape sequences for header + is_esc_seq := false + if len(t.footerParams) > 0 { + is_esc_seq = true + } - if len(t.footers[i]) == 0 { - pad = SPACE + // Maximum height. + max := t.rs[footerRowIdx] + + // Print Footer + erasePad := make([]bool, len(t.footers)) + for x := 0; x < max; x++ { + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) + + for y := 0; y <= end; y++ { + v := t.cs[y] + f := "" + if y < len(t.footers) && x < len(t.footers[y]) { + f = t.footers[y][x] + } + if t.autoFmt { + f = Title(f) + } + pad := ConditionString((y == end && !t.borders.Top), SPACE, t.pColumn) + + if erasePad[y] || (x == 0 && len(f) == 0) { + pad = SPACE + erasePad[y] = true + } + + if is_esc_seq { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(f, SPACE, v), + t.footerParams[y]), pad) + } else { + fmt.Fprintf(t.out, " %s %s", + padFunc(f, SPACE, v), + pad) + } + + //fmt.Fprintf(t.out, " %s %s", + // padFunc(f, SPACE, v), + // pad) } - fmt.Fprintf(t.out, " %s %s", - padFunc(f, SPACE, v), - pad) + // Next line + fmt.Fprint(t.out, t.newLine) + //t.printLine(true) } - // Next line - fmt.Fprint(t.out, t.newLine) - //t.printLine(true) hasPrinted := false @@ -385,7 +590,7 @@ func (t Table) printFooter() { v := t.cs[i] pad := t.pRow center := t.pCenter - length := len(t.footers[i]) + length := len(t.footers[i][0]) if length > 0 { hasPrinted = true @@ -398,6 +603,9 @@ func (t Table) printFooter() { // Print first junction if i == 0 { + if length > 0 && !t.borders.Left { + center = t.pRow + } fmt.Fprint(t.out, center) } @@ -405,16 +613,27 @@ func (t Table) printFooter() { if length == 0 { pad = SPACE } - // Ignore left space of it has printed before + // Ignore left space as it has printed before if hasPrinted || t.borders.Left { pad = t.pRow center = t.pCenter } + // Change Center end position + if center != SPACE { + if i == end && !t.borders.Right { + center = t.pRow + } + } + // Change Center start position if center == SPACE { - if i < end && len(t.footers[i+1]) != 0 { - center = t.pCenter + if i < end && len(t.footers[i+1][0]) != 0 { + if !t.borders.Left { + center = t.pRow + } else { + center = t.pCenter + } } } @@ -428,22 +647,53 @@ func (t Table) printFooter() { } fmt.Fprint(t.out, t.newLine) +} +// Print caption text +func (t Table) printCaption() { + width := t.getTableWidth() + paragraph, _ := WrapString(t.captionText, width) + for linecount := 0; linecount < len(paragraph); linecount++ { + fmt.Fprintln(t.out, paragraph[linecount]) + } +} + +// Calculate the total number of characters in a row +func (t Table) getTableWidth() int { + var chars int + for _, v := range t.cs { + chars += v + } + + // Add chars, spaces, seperators to calculate the total width of the table. + // ncols := t.colSize + // spaces := ncols * 2 + // seps := ncols + 1 + + return (chars + (3 * t.colSize) + 2) } func (t Table) printRows() { for i, lines := range t.lines { t.printRow(lines, i) } +} +func (t *Table) fillAlignment(num int) { + if len(t.columnsAlign) < num { + t.columnsAlign = make([]int, num) + for i := range t.columnsAlign { + t.columnsAlign[i] = t.align + } + } } // Print Row Information // Adjust column alignment based on type -func (t Table) printRow(columns [][]string, colKey int) { +func (t *Table) printRow(columns [][]string, rowIdx int) { // Get Maximum Height - max := t.rs[colKey] + max := t.rs[rowIdx] total := len(columns) // TODO Fix uneven col size @@ -455,9 +705,15 @@ func (t Table) printRow(columns [][]string, colKey int) { //} // Pad Each Height - // pads := []int{} pads := []int{} + // Checking for ANSI escape sequences for columns + is_esc_seq := false + if len(t.columnsParams) > 0 { + is_esc_seq = true + } + t.fillAlignment(total) + for i, line := range columns { length := len(line) pad := max - length @@ -471,14 +727,21 @@ func (t Table) printRow(columns [][]string, colKey int) { for y := 0; y < total; y++ { // Check if border is set - fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + fmt.Fprintf(t.out, SPACE) + } - fmt.Fprintf(t.out, SPACE) str := columns[y][x] + // Embedding escape sequence with column value + if is_esc_seq { + str = format(str, t.columnsParams[y]) + } + // This would print alignment // Default alignment would use multiple configuration - switch t.align { + switch t.columnsAlign[y] { case ALIGN_CENTER: // fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) case ALIGN_RIGHT: @@ -500,11 +763,17 @@ func (t Table) printRow(columns [][]string, colKey int) { } } - fmt.Fprintf(t.out, SPACE) + if !t.noWhiteSpace { + fmt.Fprintf(t.out, SPACE) + } else { + fmt.Fprintf(t.out, t.tablePadding) + } } // Check if border is set // Replace with space if not set - fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + if !t.noWhiteSpace { + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + } fmt.Fprint(t.out, t.newLine) } @@ -514,7 +783,7 @@ func (t Table) printRow(columns [][]string, colKey int) { } // Print the rows of the table and merge the cells that are identical -func (t Table) printRowsMergeCells() { +func (t *Table) printRowsMergeCells() { var previousLine []string var displayCellBorder []bool var tmpWriter bytes.Buffer @@ -537,14 +806,19 @@ func (t Table) printRowsMergeCells() { // Print Row Information to a writer and merge identical cells. // Adjust column alignment based on type -func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey int, previousLine []string) ([]string, []bool) { +func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx int, previousLine []string) ([]string, []bool) { // Get Maximum Height - max := t.rs[colKey] + max := t.rs[rowIdx] total := len(columns) // Pad Each Height pads := []int{} + // Checking for ANSI escape sequences for columns + is_esc_seq := false + if len(t.columnsParams) > 0 { + is_esc_seq = true + } for i, line := range columns { length := len(line) pad := max - length @@ -555,6 +829,7 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i } var displayCellBorder []bool + t.fillAlignment(total) for x := 0; x < max; x++ { for y := 0; y < total; y++ { @@ -565,10 +840,25 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i str := columns[y][x] + // Embedding escape sequence with column value + if is_esc_seq { + str = format(str, t.columnsParams[y]) + } + if t.autoMergeCells { + var mergeCell bool + if t.columnsToAutoMergeCells != nil { + // Check to see if the column index is in columnsToAutoMergeCells. + if t.columnsToAutoMergeCells[y] { + mergeCell = true + } + } else { + // columnsToAutoMergeCells was not set. + mergeCell = true + } //Store the full line to merge mutli-lines cells - fullLine := strings.Join(columns[y], " ") - if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { + fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ") + if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" && mergeCell { // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. displayCellBorder = append(displayCellBorder, false) str = "" @@ -580,7 +870,7 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i // This would print alignment // Default alignment would use multiple configuration - switch t.align { + switch t.columnsAlign[y] { case ALIGN_CENTER: // fmt.Fprintf(writer, "%s", Pad(str, SPACE, t.cs[y])) case ALIGN_RIGHT: @@ -605,7 +895,7 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i //The new previous line is the current one previousLine = make([]string, total) for y := 0; y < total; y++ { - previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells + previousLine[y] = strings.TrimRight(strings.Join(columns[y], " "), " ") //Store the full line for multi-lines cells } //Returns the newly added line and wether or not a border should be displayed above. return previousLine, displayCellBorder @@ -613,44 +903,59 @@ func (t Table) printRowMergeCells(writer io.Writer, columns [][]string, colKey i func (t *Table) parseDimension(str string, colKey, rowKey int) []string { var ( - raw []string - max int + raw []string + maxWidth int ) - w := DisplayWidth(str) - // Calculate Width - // Check if with is grater than maximum width - if w > t.mW { - w = t.mW - } - // Check if width exists - v, ok := t.cs[colKey] - if !ok || v < w || v == 0 { - t.cs[colKey] = w + raw = getLines(str) + maxWidth = 0 + for _, line := range raw { + if w := DisplayWidth(line); w > maxWidth { + maxWidth = w + } } - if rowKey == -1 { - return raw - } - // Calculate Height + // If wrapping, ensure that all paragraphs in the cell fit in the + // specified width. if t.autoWrap { - raw, _ = WrapString(str, t.cs[colKey]) - } else { - raw = getLines(str) - } + // If there's a maximum allowed width for wrapping, use that. + if maxWidth > t.mW { + maxWidth = t.mW + } - for _, line := range raw { - if w := DisplayWidth(line); w > max { - max = w + // In the process of doing so, we need to recompute maxWidth. This + // is because perhaps a word in the cell is longer than the + // allowed maximum width in t.mW. + newMaxWidth := maxWidth + newRaw := make([]string, 0, len(raw)) + + if t.reflowText { + // Make a single paragraph of everything. + raw = []string{strings.Join(raw, " ")} } + for i, para := range raw { + paraLines, _ := WrapString(para, maxWidth) + for _, line := range paraLines { + if w := DisplayWidth(line); w > newMaxWidth { + newMaxWidth = w + } + } + if i > 0 { + newRaw = append(newRaw, " ") + } + newRaw = append(newRaw, paraLines...) + } + raw = newRaw + maxWidth = newMaxWidth } - // Make sure the with is the same length as maximum word - // Important for cases where the width is smaller than maxu word - if max > t.cs[colKey] { - t.cs[colKey] = max + // Store the new known maximum width. + v, ok := t.cs[colKey] + if !ok || v < maxWidth || v == 0 { + t.cs[colKey] = maxWidth } + // Remember the number of lines for the row printer. h := len(raw) v, ok = t.rs[rowKey] diff --git a/vendor/github.com/olekukonko/tablewriter/table_with_color.go b/vendor/github.com/olekukonko/tablewriter/table_with_color.go new file mode 100644 index 000000000..ae7a364ae --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/table_with_color.go @@ -0,0 +1,136 @@ +package tablewriter + +import ( + "fmt" + "strconv" + "strings" +) + +const ESC = "\033" +const SEP = ";" + +const ( + BgBlackColor int = iota + 40 + BgRedColor + BgGreenColor + BgYellowColor + BgBlueColor + BgMagentaColor + BgCyanColor + BgWhiteColor +) + +const ( + FgBlackColor int = iota + 30 + FgRedColor + FgGreenColor + FgYellowColor + FgBlueColor + FgMagentaColor + FgCyanColor + FgWhiteColor +) + +const ( + BgHiBlackColor int = iota + 100 + BgHiRedColor + BgHiGreenColor + BgHiYellowColor + BgHiBlueColor + BgHiMagentaColor + BgHiCyanColor + BgHiWhiteColor +) + +const ( + FgHiBlackColor int = iota + 90 + FgHiRedColor + FgHiGreenColor + FgHiYellowColor + FgHiBlueColor + FgHiMagentaColor + FgHiCyanColor + FgHiWhiteColor +) + +const ( + Normal = 0 + Bold = 1 + UnderlineSingle = 4 + Italic +) + +type Colors []int + +func startFormat(seq string) string { + return fmt.Sprintf("%s[%sm", ESC, seq) +} + +func stopFormat() string { + return fmt.Sprintf("%s[%dm", ESC, Normal) +} + +// Making the SGR (Select Graphic Rendition) sequence. +func makeSequence(codes []int) string { + codesInString := []string{} + for _, code := range codes { + codesInString = append(codesInString, strconv.Itoa(code)) + } + return strings.Join(codesInString, SEP) +} + +// Adding ANSI escape sequences before and after string +func format(s string, codes interface{}) string { + var seq string + + switch v := codes.(type) { + + case string: + seq = v + case []int: + seq = makeSequence(v) + case Colors: + seq = makeSequence(v) + default: + return s + } + + if len(seq) == 0 { + return s + } + return startFormat(seq) + s + stopFormat() +} + +// Adding header colors (ANSI codes) +func (t *Table) SetHeaderColor(colors ...Colors) { + if t.colSize != len(colors) { + panic("Number of header colors must be equal to number of headers.") + } + for i := 0; i < len(colors); i++ { + t.headerParams = append(t.headerParams, makeSequence(colors[i])) + } +} + +// Adding column colors (ANSI codes) +func (t *Table) SetColumnColor(colors ...Colors) { + if t.colSize != len(colors) { + panic("Number of column colors must be equal to number of headers.") + } + for i := 0; i < len(colors); i++ { + t.columnsParams = append(t.columnsParams, makeSequence(colors[i])) + } +} + +// Adding column colors (ANSI codes) +func (t *Table) SetFooterColor(colors ...Colors) { + if len(t.footers) != len(colors) { + panic("Number of footer colors must be equal to number of footer.") + } + for i := 0; i < len(colors); i++ { + t.footerParams = append(t.footerParams, makeSequence(colors[i])) + } +} + +func Color(colors ...int) []int { + return colors +} diff --git a/vendor/github.com/olekukonko/tablewriter/test.csv b/vendor/github.com/olekukonko/tablewriter/test.csv deleted file mode 100644 index 1609327e9..000000000 --- a/vendor/github.com/olekukonko/tablewriter/test.csv +++ /dev/null @@ -1,4 +0,0 @@ -first_name,last_name,ssn -John,Barry,123456 -Kathy,Smith,687987 -Bob,McCornick,3979870 \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/test_info.csv b/vendor/github.com/olekukonko/tablewriter/test_info.csv deleted file mode 100644 index e4c40e983..000000000 --- a/vendor/github.com/olekukonko/tablewriter/test_info.csv +++ /dev/null @@ -1,4 +0,0 @@ -Field,Type,Null,Key,Default,Extra -user_id,smallint(5),NO,PRI,NULL,auto_increment -username,varchar(10),NO,,NULL, -password,varchar(100),NO,,NULL, \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/util.go b/vendor/github.com/olekukonko/tablewriter/util.go index 2deefbc52..380e7ab35 100644 --- a/vendor/github.com/olekukonko/tablewriter/util.go +++ b/vendor/github.com/olekukonko/tablewriter/util.go @@ -30,17 +30,38 @@ func ConditionString(cond bool, valid, inValid string) string { return inValid } +func isNumOrSpace(r rune) bool { + return ('0' <= r && r <= '9') || r == ' ' +} + // Format Table Header // Replace _ , . and spaces func Title(name string) string { - name = strings.Replace(name, "_", " ", -1) - name = strings.Replace(name, ".", " ", -1) + origLen := len(name) + rs := []rune(name) + for i, r := range rs { + switch r { + case '_': + rs[i] = ' ' + case '.': + // ignore floating number 0.0 + if (i != 0 && !isNumOrSpace(rs[i-1])) || (i != len(rs)-1 && !isNumOrSpace(rs[i+1])) { + rs[i] = ' ' + } + } + } + name = string(rs) name = strings.TrimSpace(name) + if len(name) == 0 && origLen > 0 { + // Keep at least one character. This is important to preserve + // empty lines in multi-line headers/footers. + name = " " + } return strings.ToUpper(name) } // Pad String -// Attempts to play string in the center +// Attempts to place string in the center func Pad(s, pad string, width int) string { gap := width - DisplayWidth(s) if gap > 0 { @@ -52,7 +73,7 @@ func Pad(s, pad string, width int) string { } // Pad String Right position -// This would pace string at the left side fo the screen +// This would place string at the left side of the screen func PadRight(s, pad string, width int) string { gap := width - DisplayWidth(s) if gap > 0 { @@ -62,7 +83,7 @@ func PadRight(s, pad string, width int) string { } // Pad String Left position -// This would pace string at the right side fo the screen +// This would place string at the right side of the screen func PadLeft(s, pad string, width int) string { gap := width - DisplayWidth(s) if gap > 0 { diff --git a/vendor/github.com/olekukonko/tablewriter/wrap.go b/vendor/github.com/olekukonko/tablewriter/wrap.go index 5290fb65a..a092ee1f7 100644 --- a/vendor/github.com/olekukonko/tablewriter/wrap.go +++ b/vendor/github.com/olekukonko/tablewriter/wrap.go @@ -10,7 +10,8 @@ package tablewriter import ( "math" "strings" - "unicode/utf8" + + "github.com/mattn/go-runewidth" ) var ( @@ -27,7 +28,7 @@ func WrapString(s string, lim int) ([]string, int) { var lines []string max := 0 for _, v := range words { - max = len(v) + max = runewidth.StringWidth(v) if max > lim { lim = max } @@ -55,9 +56,9 @@ func WrapWords(words []string, spc, lim, pen int) [][]string { length := make([][]int, n) for i := 0; i < n; i++ { length[i] = make([]int, n) - length[i][i] = utf8.RuneCountInString(words[i]) + length[i][i] = runewidth.StringWidth(words[i]) for j := i + 1; j < n; j++ { - length[i][j] = length[i][j-1] + spc + utf8.RuneCountInString(words[j]) + length[i][j] = length[i][j-1] + spc + runewidth.StringWidth(words[j]) } } nbrk := make([]int, n) @@ -94,10 +95,5 @@ func WrapWords(words []string, spc, lim, pen int) [][]string { // getLines decomposes a multiline string into a slice of strings. func getLines(s string) []string { - var lines []string - - for _, line := range strings.Split(s, nl) { - lines = append(lines, line) - } - return lines + return strings.Split(s, nl) } diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md index 494abdbfb..a26bc530f 100644 --- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.16.5 + +Ginkgo 2.0 now has a Release Candidate. 1.16.5 advertises the existence of the RC. +1.16.5 deprecates GinkgoParallelNode in favor of GinkgoParallelProcess + +You can silence the RC advertisement by setting an `ACK_GINKG_RC=true` environment variable or creating a file in your home directory called `.ack-ginkgo-rc` + ## 1.16.4 ### Fixes diff --git a/vendor/github.com/onsi/ginkgo/README.md b/vendor/github.com/onsi/ginkgo/README.md index 05321e6ea..a25ca5e03 100644 --- a/vendor/github.com/onsi/ginkgo/README.md +++ b/vendor/github.com/onsi/ginkgo/README.md @@ -1,23 +1,18 @@ ![Ginkgo: A Go BDD Testing Framework](https://onsi.github.io/ginkgo/images/ginkgo.png) -[![Build Status](https://travis-ci.org/onsi/ginkgo.svg?branch=master)](https://travis-ci.org/onsi/ginkgo) [![test](https://github.com/onsi/ginkgo/workflows/test/badge.svg?branch=master)](https://github.com/onsi/ginkgo/actions?query=workflow%3Atest+branch%3Amaster) Jump to the [docs](https://onsi.github.io/ginkgo/) | [中文文档](https://ke-chain.github.io/ginkgodoc) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)! If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW). -# Ginkgo 2.0 is coming soon! +# Ginkgo 2.0 Release Candidate is available! -An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [v2](https://github.com/onsi/ginkgo/tree/v2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion and links to the original [proposal doc](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#). +An effort is underway to develop and deliver Ginkgo 2.0. The work is happening in the [ver2](https://github.com/onsi/ginkgo/tree/ver2) branch and a changelog and migration guide is being maintained on that branch [here](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md). Issue [#711](https://github.com/onsi/ginkgo/issues/711) is the central place for discussion. -As described in the [changelog](https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711). +As described in the [changelog](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md) and [proposal](https://docs.google.com/document/d/1h28ZknXRsTLPNNiOjdHIO-F2toCzq4xoZDXbfYaBdoQ/edit#), Ginkgo 2.0 will clean up the Ginkgo codebase, deprecate and remove some v1 functionality, and add several new much-requested features. To help users get ready for the migration, Ginkgo v1 has started emitting deprecation warnings for features that will no longer be supported with links to documentation for how to migrate away from these features. If you have concerns or comments please chime in on [#711](https://github.com/onsi/ginkgo/issues/711). -The current timeline for completion of 2.0 looks like: - -- Early April 2021: first public release of 2.0, deprecation warnings land in v1. -- May 2021: first beta/rc of 2.0 with most new functionality in place. -- June/July 2021: 2.0 ships and fully replaces the 1.x codebase on master. +Please start exploring and using the V2 release! To get started follow the [Using the Release Candidate](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta) directions in the migration guide. ## TLDR Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests. diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go index 5f3f43969..3130c7789 100644 --- a/vendor/github.com/onsi/ginkgo/config/config.go +++ b/vendor/github.com/onsi/ginkgo/config/config.go @@ -20,7 +20,7 @@ import ( "fmt" ) -const VERSION = "1.16.4" +const VERSION = "1.16.5" type GinkgoConfigType struct { RandomSeed int64 diff --git a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go index 4a6e1e1ee..ccd7685e3 100644 --- a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go +++ b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go @@ -73,9 +73,15 @@ func GinkgoRandomSeed() int64 { return config.GinkgoConfig.RandomSeed } -//GinkgoParallelNode returns the parallel node number for the current ginkgo process -//The node number is 1-indexed +//GinkgoParallelNode is deprecated, use GinkgoParallelProcess instead func GinkgoParallelNode() int { + deprecationTracker.TrackDeprecation(types.Deprecations.ParallelNode(), codelocation.New(1)) + return GinkgoParallelProcess() +} + +//GinkgoParallelProcess returns the parallel process number for the current ginkgo process +//The process number is 1-indexed +func GinkgoParallelProcess() int { return config.GinkgoConfig.ParallelNode } @@ -109,6 +115,7 @@ func GinkgoT(optionalOffset ...int) GinkgoTInterface { //in the testing package's T. type GinkgoTInterface interface { Cleanup(func()) + Setenv(key, value string) Error(args ...interface{}) Errorf(format string, args ...interface{}) Fail() diff --git a/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go b/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go index d7bbb7a96..4dcfaf4cd 100644 --- a/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go +++ b/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go @@ -34,6 +34,11 @@ func (t *ginkgoTestingTProxy) Cleanup(func()) { // No-op } +func (t *ginkgoTestingTProxy) Setenv(kev, value string) { + fmt.Println("Setenv is a noop for Ginkgo at the moment but will be implemented in V2") + // No-op until Cleanup is implemented +} + func (t *ginkgoTestingTProxy) Error(args ...interface{}) { t.fail(fmt.Sprintln(args...), t.offset) } diff --git a/vendor/github.com/onsi/ginkgo/types/deprecation_support.go b/vendor/github.com/onsi/ginkgo/types/deprecation_support.go index 305c134b7..d5a6658f3 100644 --- a/vendor/github.com/onsi/ginkgo/types/deprecation_support.go +++ b/vendor/github.com/onsi/ginkgo/types/deprecation_support.go @@ -52,6 +52,14 @@ func (d deprecations) Measure() Deprecation { } } +func (d deprecations) ParallelNode() Deprecation { + return Deprecation{ + Message: "GinkgoParallelNode is deprecated and will be removed in Ginkgo V2. Please use GinkgoParallelProcess instead.", + DocLink: "renamed-ginkgoparallelnode", + Version: "1.16.5", + } +} + func (d deprecations) Convert() Deprecation { return Deprecation{ Message: "The convert command is deprecated in Ginkgo V2", @@ -99,16 +107,18 @@ func (d *DeprecationTracker) DidTrackDeprecations() bool { } func (d *DeprecationTracker) DeprecationsReport() string { - out := formatter.F("{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n") + out := formatter.F("\n{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n") out += formatter.F("{{light-yellow}}============================================={{/}}\n") - out += formatter.F("Ginkgo 2.0 is under active development and will introduce (a small number of) breaking changes.\n") - out += formatter.F("To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md{{/}}\n") - out += formatter.F("To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n") + out += formatter.F("{{bold}}{{green}}Ginkgo 2.0{{/}} is under active development and will introduce several new features, improvements, and a small handful of breaking changes.\n") + out += formatter.F("A release candidate for 2.0 is now available and 2.0 should GA in Fall 2021. {{bold}}Please give the RC a try and send us feedback!{{/}}\n") + out += formatter.F(" - To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md{{/}}\n") + out += formatter.F(" - For instructions on using the Release Candidate visit {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta{{/}}\n") + out += formatter.F(" - To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n") for deprecation, locations := range d.deprecations { out += formatter.Fi(1, "{{yellow}}"+deprecation.Message+"{{/}}\n") if deprecation.DocLink != "" { - out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink) + out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink) } for _, location := range locations { out += formatter.Fi(2, "{{gray}}%s{{/}}\n", location) diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md index b797577ff..79c3f6199 100644 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.36.1 + +### Fixes +- Fix https://github.com/onsi/gomega/issues/803 [1c6c112] +- resolves onsi/gomega#696: make HaveField great on pointer receivers given only a non-addressable value [4feb9d7] + ## 1.36.0 ### Features diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go index eb74f6f6a..c6ac499f7 100644 --- a/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -22,7 +22,7 @@ import ( "github.com/onsi/gomega/types" ) -const GOMEGA_VERSION = "1.36.0" +const GOMEGA_VERSION = "1.36.1" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. If you're using Ginkgo then you probably forgot to put your assertion in an It(). diff --git a/vendor/github.com/onsi/gomega/matchers/have_field.go b/vendor/github.com/onsi/gomega/matchers/have_field.go index 8dd3f871a..293457e85 100644 --- a/vendor/github.com/onsi/gomega/matchers/have_field.go +++ b/vendor/github.com/onsi/gomega/matchers/have_field.go @@ -40,7 +40,12 @@ func extractField(actual interface{}, field string, matchername string) (any, er extractedValue = actualValue.Addr().MethodByName(strings.TrimSuffix(fields[0], "()")) } if extractedValue == (reflect.Value{}) { - return nil, missingFieldError(fmt.Sprintf("%s could not find method named '%s' in struct of type %T.", matchername, fields[0], actual)) + ptr := reflect.New(actualValue.Type()) + ptr.Elem().Set(actualValue) + extractedValue = ptr.MethodByName(strings.TrimSuffix(fields[0], "()")) + if extractedValue == (reflect.Value{}) { + return nil, missingFieldError(fmt.Sprintf("%s could not find method named '%s' in struct of type %T.", matchername, fields[0], actual)) + } } t := extractedValue.Type() if t.NumIn() != 0 || t.NumOut() != 1 { diff --git a/vendor/github.com/pborman/uuid/.travis.yml b/vendor/github.com/pborman/uuid/.travis.yml index a6a98db8a..3deb4a124 100644 --- a/vendor/github.com/pborman/uuid/.travis.yml +++ b/vendor/github.com/pborman/uuid/.travis.yml @@ -1,9 +1,9 @@ language: go go: - - 1.4.3 - - 1.5.3 - - release + - "1.9" + - "1.10" + - "1.11" - tip script: diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md index f023d47ca..810ad40dc 100644 --- a/vendor/github.com/pborman/uuid/README.md +++ b/vendor/github.com/pborman/uuid/README.md @@ -1,7 +1,9 @@ This project was automatically exported from code.google.com/p/go-uuid # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) -The uuid package generates and inspects UUIDs based on [RFC 412](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. +The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. + +This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package). ###### Install `go get github.com/pborman/uuid` diff --git a/vendor/github.com/pborman/uuid/doc.go b/vendor/github.com/pborman/uuid/doc.go index d8bd013e6..727d76167 100644 --- a/vendor/github.com/pborman/uuid/doc.go +++ b/vendor/github.com/pborman/uuid/doc.go @@ -4,5 +4,10 @@ // The uuid package generates and inspects UUIDs. // -// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// This package is a partial wrapper around the github.com/google/uuid package. +// This package represents a UUID as []byte while github.com/google/uuid +// represents a UUID as [16]byte. package uuid diff --git a/vendor/github.com/pborman/uuid/json.go b/vendor/github.com/pborman/uuid/json.go deleted file mode 100644 index 9dda1dfba..000000000 --- a/vendor/github.com/pborman/uuid/json.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import "errors" - -func (u UUID) MarshalJSON() ([]byte, error) { - if len(u) != 16 { - return []byte(`""`), nil - } - var js [38]byte - js[0] = '"' - encodeHex(js[1:], u) - js[37] = '"' - return js[:], nil -} - -func (u *UUID) UnmarshalJSON(data []byte) error { - if string(data) == `""` { - return nil - } - if data[0] != '"' { - return errors.New("invalid UUID format") - } - data = data[1 : len(data)-1] - uu := Parse(string(data)) - if uu == nil { - return errors.New("invalid UUID format") - } - *u = uu - return nil -} diff --git a/vendor/github.com/pborman/uuid/marshal.go b/vendor/github.com/pborman/uuid/marshal.go new file mode 100644 index 000000000..35b89352a --- /dev/null +++ b/vendor/github.com/pborman/uuid/marshal.go @@ -0,0 +1,85 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "errors" + "fmt" + + guuid "github.com/google/uuid" +) + +// MarshalText implements encoding.TextMarshaler. +func (u UUID) MarshalText() ([]byte, error) { + if len(u) != 16 { + return nil, nil + } + var js [36]byte + encodeHex(js[:], u) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (u *UUID) UnmarshalText(data []byte) error { + if len(data) == 0 { + return nil + } + id := Parse(string(data)) + if id == nil { + return errors.New("invalid UUID") + } + *u = id + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (u UUID) MarshalBinary() ([]byte, error) { + return u[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (u *UUID) UnmarshalBinary(data []byte) error { + if len(data) == 0 { + return nil + } + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + var id [16]byte + copy(id[:], data) + *u = id[:] + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (u Array) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], u[:]) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (u *Array) UnmarshalText(data []byte) error { + id, err := guuid.ParseBytes(data) + if err != nil { + return err + } + *u = Array(id) + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (u Array) MarshalBinary() ([]byte, error) { + return u[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (u *Array) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(u[:], data) + return nil +} diff --git a/vendor/github.com/pborman/uuid/node.go b/vendor/github.com/pborman/uuid/node.go index 42d60da8f..e524e0101 100644 --- a/vendor/github.com/pborman/uuid/node.go +++ b/vendor/github.com/pborman/uuid/node.go @@ -5,24 +5,14 @@ package uuid import ( - "net" - "sync" -) - -var ( - nodeMu sync.Mutex - interfaces []net.Interface // cached list of interfaces - ifname string // name of interface being used - nodeID []byte // hardware for version 1 UUIDs + guuid "github.com/google/uuid" ) // NodeInterface returns the name of the interface from which the NodeID was // derived. The interface "user" is returned if the NodeID was set by // SetNodeID. func NodeInterface() string { - defer nodeMu.Unlock() - nodeMu.Lock() - return ifname + return guuid.NodeInterface() } // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. @@ -32,77 +22,20 @@ func NodeInterface() string { // // SetNodeInterface never fails when name is "". func SetNodeInterface(name string) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - return setNodeInterface(name) -} - -func setNodeInterface(name string) bool { - if interfaces == nil { - var err error - interfaces, err = net.Interfaces() - if err != nil && name != "" { - return false - } - } - - for _, ifs := range interfaces { - if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { - if setNodeID(ifs.HardwareAddr) { - ifname = ifs.Name - return true - } - } - } - - // We found no interfaces with a valid hardware address. If name - // does not specify a specific interface generate a random Node ID - // (section 4.1.6) - if name == "" { - if nodeID == nil { - nodeID = make([]byte, 6) - } - randomBits(nodeID) - return true - } - return false + return guuid.SetNodeInterface(name) } // NodeID returns a slice of a copy of the current Node ID, setting the Node ID // if not already set. func NodeID() []byte { - defer nodeMu.Unlock() - nodeMu.Lock() - if nodeID == nil { - setNodeInterface("") - } - nid := make([]byte, 6) - copy(nid, nodeID) - return nid + return guuid.NodeID() } // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes // of id are used. If id is less than 6 bytes then false is returned and the // Node ID is not set. func SetNodeID(id []byte) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - if setNodeID(id) { - ifname = "user" - return true - } - return false -} - -func setNodeID(id []byte) bool { - if len(id) < 6 { - return false - } - if nodeID == nil { - nodeID = make([]byte, 6) - } - copy(nodeID, id) - return true + return guuid.SetNodeID(id) } // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is diff --git a/vendor/github.com/pborman/uuid/sql.go b/vendor/github.com/pborman/uuid/sql.go index d015bfd13..929c3847e 100644 --- a/vendor/github.com/pborman/uuid/sql.go +++ b/vendor/github.com/pborman/uuid/sql.go @@ -40,7 +40,9 @@ func (uuid *UUID) Scan(src interface{}) error { // assumes a simple slice of bytes if 16 bytes // otherwise attempts to parse if len(b) == 16 { - *uuid = UUID(b) + parsed := make([]byte, 16) + copy(parsed, b) + *uuid = UUID(parsed) } else { u := Parse(string(b)) diff --git a/vendor/github.com/pborman/uuid/time.go b/vendor/github.com/pborman/uuid/time.go index eedf24219..7286824d8 100644 --- a/vendor/github.com/pborman/uuid/time.go +++ b/vendor/github.com/pborman/uuid/time.go @@ -6,65 +6,18 @@ package uuid import ( "encoding/binary" - "sync" - "time" + + guuid "github.com/google/uuid" ) // A Time represents a time as the number of 100's of nanoseconds since 15 Oct // 1582. -type Time int64 - -const ( - lillian = 2299160 // Julian day of 15 Oct 1582 - unix = 2440587 // Julian day of 1 Jan 1970 - epoch = unix - lillian // Days between epochs - g1582 = epoch * 86400 // seconds between epochs - g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs -) - -var ( - timeMu sync.Mutex - lasttime uint64 // last time we returned - clock_seq uint16 // clock sequence for this run - - timeNow = time.Now // for testing -) - -// UnixTime converts t the number of seconds and nanoseconds using the Unix -// epoch of 1 Jan 1970. -func (t Time) UnixTime() (sec, nsec int64) { - sec = int64(t - g1582ns100) - nsec = (sec % 10000000) * 100 - sec /= 10000000 - return sec, nsec -} +type Time = guuid.Time // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and // clock sequence as well as adjusting the clock sequence as needed. An error // is returned if the current time cannot be determined. -func GetTime() (Time, uint16, error) { - defer timeMu.Unlock() - timeMu.Lock() - return getTime() -} - -func getTime() (Time, uint16, error) { - t := timeNow() - - // If we don't have a clock sequence already, set one. - if clock_seq == 0 { - setClockSequence(-1) - } - now := uint64(t.UnixNano()/100) + g1582ns100 - - // If time has gone backwards with this clock sequence then we - // increment the clock sequence - if now <= lasttime { - clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000 - } - lasttime = now - return Time(now), clock_seq, nil -} +func GetTime() (Time, uint16, error) { return guuid.GetTime() } // ClockSequence returns the current clock sequence, generating one if not // already set. The clock sequence is only used for Version 1 UUIDs. @@ -74,39 +27,11 @@ func getTime() (Time, uint16, error) { // clock sequence is generated the first time a clock sequence is requested by // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated // for -func ClockSequence() int { - defer timeMu.Unlock() - timeMu.Lock() - return clockSequence() -} - -func clockSequence() int { - if clock_seq == 0 { - setClockSequence(-1) - } - return int(clock_seq & 0x3fff) -} +func ClockSequence() int { return guuid.ClockSequence() } -// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to +// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to // -1 causes a new sequence to be generated. -func SetClockSequence(seq int) { - defer timeMu.Unlock() - timeMu.Lock() - setClockSequence(seq) -} - -func setClockSequence(seq int) { - if seq == -1 { - var b [2]byte - randomBits(b[:]) // clock sequence - seq = int(b[0])<<8 | int(b[1]) - } - old_seq := clock_seq - clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant - if old_seq != clock_seq { - lasttime = 0 - } -} +func SetClockSequence(seq int) { guuid.SetClockSequence(seq) } // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in // uuid. It returns false if uuid is not valid. The time is only well defined diff --git a/vendor/github.com/pborman/uuid/util.go b/vendor/github.com/pborman/uuid/util.go index fc8e052c7..255b5e248 100644 --- a/vendor/github.com/pborman/uuid/util.go +++ b/vendor/github.com/pborman/uuid/util.go @@ -4,17 +4,6 @@ package uuid -import ( - "io" -) - -// randomBits completely fills slice b with random data. -func randomBits(b []byte) { - if _, err := io.ReadFull(rander, b); err != nil { - panic(err.Error()) // rand should never fail - } -} - // xvalues returns the value of a byte as a hexadecimal digit or 255. var xvalues = [256]byte{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, diff --git a/vendor/github.com/pborman/uuid/uuid.go b/vendor/github.com/pborman/uuid/uuid.go index 82c9e7ee7..337000420 100644 --- a/vendor/github.com/pborman/uuid/uuid.go +++ b/vendor/github.com/pborman/uuid/uuid.go @@ -8,9 +8,9 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "fmt" "io" - "strings" + + guuid "github.com/google/uuid" ) // Array is a pass-by-value UUID that can be used as an effecient key in a map. @@ -24,7 +24,7 @@ func (uuid Array) UUID() UUID { // String returns the string representation of uuid, // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. func (uuid Array) String() string { - return uuid.UUID().String() + return guuid.UUID(uuid).String() } // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -32,18 +32,18 @@ func (uuid Array) String() string { type UUID []byte // A Version represents a UUIDs version. -type Version byte +type Version = guuid.Version // A Variant represents a UUIDs variant. -type Variant byte +type Variant = guuid.Variant // Constants returned by Variant. const ( - Invalid = Variant(iota) // Invalid UUID - RFC4122 // The variant specified in RFC4122 - Reserved // Reserved, NCS backward compatibility. - Microsoft // Reserved, Microsoft Corporation backward compatibility. - Future // Reserved for future definition. + Invalid = guuid.Invalid // Invalid UUID + RFC4122 = guuid.RFC4122 // The variant specified in RFC4122 + Reserved = guuid.Reserved // Reserved, NCS backward compatibility. + Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future = guuid.Future // Reserved for future definition. ) var rander = rand.Reader // random function @@ -54,35 +54,23 @@ func New() string { return NewRandom().String() } -// Parse decodes s into a UUID or returns nil. Both the UUID form of -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. +// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for +// the formats parsed. func Parse(s string) UUID { - if len(s) == 36+9 { - if strings.ToLower(s[:9]) != "urn:uuid:" { - return nil - } - s = s[9:] - } else if len(s) != 36 { - return nil - } - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return nil + gu, err := guuid.Parse(s) + if err == nil { + return gu[:] } - var uuid [16]byte - for i, x := range [16]int{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34} { - if v, ok := xtob(s[x:]); !ok { - return nil - } else { - uuid[i] = v - } + return nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + gu, err := guuid.ParseBytes(b) + if err == nil { + return gu[:], nil } - return uuid[:] + return nil, err } // Equal returns true if uuid1 and uuid2 are equal. @@ -163,39 +151,12 @@ func (uuid UUID) Version() (Version, bool) { return Version(uuid[6] >> 4), true } -func (v Version) String() string { - if v > 15 { - return fmt.Sprintf("BAD_VERSION_%d", v) - } - return fmt.Sprintf("VERSION_%d", v) -} - -func (v Variant) String() string { - switch v { - case RFC4122: - return "RFC4122" - case Reserved: - return "Reserved" - case Microsoft: - return "Microsoft" - case Future: - return "Future" - case Invalid: - return "Invalid" - } - return fmt.Sprintf("BadVariant%d", int(v)) -} - -// SetRand sets the random number generator to r, which implents io.Reader. +// SetRand sets the random number generator to r, which implements io.Reader. // If r.Read returns an error when the package requests random data then // a panic will be issued. // // Calling SetRand with nil sets the random number generator to the default // generator. func SetRand(r io.Reader) { - if r == nil { - rander = rand.Reader - return - } - rander = r + guuid.SetRand(r) } diff --git a/vendor/github.com/pborman/uuid/version1.go b/vendor/github.com/pborman/uuid/version1.go index 0127eacfa..7af948da7 100644 --- a/vendor/github.com/pborman/uuid/version1.go +++ b/vendor/github.com/pborman/uuid/version1.go @@ -5,7 +5,7 @@ package uuid import ( - "encoding/binary" + guuid "github.com/google/uuid" ) // NewUUID returns a Version 1 UUID based on the current NodeID and clock @@ -15,27 +15,9 @@ import ( // SetClockSequence then it will be set automatically. If GetTime fails to // return the current NewUUID returns nil. func NewUUID() UUID { - if nodeID == nil { - SetNodeInterface("") + gu, err := guuid.NewUUID() + if err == nil { + return UUID(gu[:]) } - - now, seq, err := GetTime() - if err != nil { - return nil - } - - uuid := make([]byte, 16) - - time_low := uint32(now & 0xffffffff) - time_mid := uint16((now >> 32) & 0xffff) - time_hi := uint16((now >> 48) & 0x0fff) - time_hi |= 0x1000 // Version 1 - - binary.BigEndian.PutUint32(uuid[0:], time_low) - binary.BigEndian.PutUint16(uuid[4:], time_mid) - binary.BigEndian.PutUint16(uuid[6:], time_hi) - binary.BigEndian.PutUint16(uuid[8:], seq) - copy(uuid[10:], nodeID) - - return uuid + return nil } diff --git a/vendor/github.com/pborman/uuid/version4.go b/vendor/github.com/pborman/uuid/version4.go index b3d4a368d..767dd0c3a 100644 --- a/vendor/github.com/pborman/uuid/version4.go +++ b/vendor/github.com/pborman/uuid/version4.go @@ -4,12 +4,14 @@ package uuid -// Random returns a Random (Version 4) UUID or panics. +import guuid "github.com/google/uuid" + +// NewRandom returns a Random (Version 4) UUID or panics. // // The strength of the UUIDs is based on the strength of the crypto/rand // package. // -// A note about uniqueness derived from from the UUID Wikipedia entry: +// A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being // hit by a meteorite is estimated to be one chance in 17 billion, that @@ -17,9 +19,8 @@ package uuid // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() UUID { - uuid := make([]byte, 16) - randomBits([]byte(uuid)) - uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid + if gu, err := guuid.NewRandom(); err == nil { + return UUID(gu[:]) + } + return nil } diff --git a/vendor/github.com/phayes/freeport/.gitignore b/vendor/github.com/phayes/freeport/.gitignore new file mode 100644 index 000000000..1521c8b76 --- /dev/null +++ b/vendor/github.com/phayes/freeport/.gitignore @@ -0,0 +1 @@ +dist diff --git a/vendor/github.com/phayes/freeport/.goreleaser.yml b/vendor/github.com/phayes/freeport/.goreleaser.yml new file mode 100644 index 000000000..9e16500a2 --- /dev/null +++ b/vendor/github.com/phayes/freeport/.goreleaser.yml @@ -0,0 +1,135 @@ +project_name: freeport + +release: + github: + owner: phayes + name: freeport + +builds: + - binary: freeport + goos: + - linux + - darwin + goarch: + - amd64 + - "386" + - arm64 + goarm: + - "6" + main: ./cmd/freeport + ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} + +archive: + format: tar.gz + name_template: '{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ + .Arm }}{{ end }}' + files: + - licence* + - LICENCE* + - license* + - LICENSE* + - readme* + - README* + - changelog* + - CHANGELOG* + +snapshot: + name_template: SNAPSHOT-{{ .Commit }} + +checksum: + name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' + +# Create RPM and .DEB files +fpm: + vendor: Patrick Hayes + + # Your app's homepage. + #homepage: https://example.com/ + + # Your app's maintainer + maintainer: Patrick Hayes + + # Your app's description. + description: Get a free open TCP port that is ready to use. + + # Your app's license. + # Default is empty. + license: BSD + + # Formats to be generated. + formats: + - deb + - rpm + + # Packages your package depends on. + #dependencies: + # - git + # - zsh + + # Packages that conflict with your package. + #conflicts: + # - svn + # - bash + + # Files or directories to add to your package (beyond the binary). + # Keys are source paths to get the files from. + # Values are the destination locations of the files in the package. + #files: + # "scripts/etc/init.d/": "/etc/init.d" + +# Homebrew repos +brew: + # Reporitory to push the tap to. + github: + owner: phayes + name: homebrew-repo + + # Git author used to commit to the repository. + # Defaults are shown. + commit_author: + name: goreleaserbot + email: goreleaser@carlosbecker.com + + # Folder inside the repository to put the formula. + # Default is the root folder. + # folder: . + + # Caveats for the user of your binary. + # Default is empty. + # caveats: "How to use this binary" + + # Your app's homepage. + # Default is empty. + # homepage: "https://example.com/" + + # Your app's description. + # Default is empty. + description: "Get a free open TCP port that is ready to use." + + # Packages your package depends on. + #dependencies: + # - git + # - zsh + + # Packages that conflict with your package. + #conflicts: + # - svn + # - bash + + # Specify for packages that run as a service. + # Default is empty. + #plist: | + # + # ... + + # So you can `brew test` your formula. + # Default is empty. + #test: | + # system "#{bin}/program --version" + # ... + + # Custom install script for brew. + # Default is 'bin.install "program"'. + #install: | + # bin.install "program" + # ... diff --git a/vendor/github.com/phayes/freeport/README.md b/vendor/github.com/phayes/freeport/README.md index 36171cf31..1665ccf4d 100644 --- a/vendor/github.com/phayes/freeport/README.md +++ b/vendor/github.com/phayes/freeport/README.md @@ -1,8 +1,9 @@ FreePort ======== -Get a free open TCP port that is ready to use +Get a free open TCP port that is ready to use. +## Command Line Example: ```bash # Ask the kernel to give us an open port. export port=$(freeport) @@ -14,14 +15,44 @@ httpd -X -c "Listen $port" & curl localhost:$port ``` -#### Binary Downloads - - Mac: https://phayes.github.io/bin/current/freeport/mac/freeport.gz - - Linux: https://phayes.github.io/bin/current/freeport/linux/freeport.gz +## Golang example: +```go +package main + +import "github.com/phayes/freeport" + +func main() { + port, err := freeport.GetFreePort() + if err != nil { + log.Fatal(err) + } + // port is ready to listen on +} + +``` + +## Installation + +#### Mac OSX +```bash +brew install phayes/repo/freeport +``` + + +#### CentOS and other RPM based systems +```bash +wget https://github.com/phayes/freeport/releases/download/1.0.2/freeport_1.0.2_linux_386.rpm +rpm -Uvh freeport_1.0.2_linux_386.rpm +``` + +#### Ubuntu and other DEB based systems +```bash +wget wget https://github.com/phayes/freeport/releases/download/1.0.2/freeport_1.0.2_linux_amd64.deb +dpkg -i freeport_1.0.2_linux_amd64.deb +``` #### Building From Source ```bash sudo apt-get install golang # Download go. Alternativly build from source: https://golang.org/doc/install/source -mkdir ~/.gopath && export GOPATH=~/.gopath # Replace with desired GOPATH -export PATH=$PATH:$GOPATH/bin # For convenience, add go's bin dir to your PATH -go get github.com/phayes/freeport/cmd/freeport +go get github.com/phayes/freeport ``` diff --git a/vendor/github.com/phayes/freeport/freeport.go b/vendor/github.com/phayes/freeport/freeport.go index 8ff03c221..fcfb6bab0 100644 --- a/vendor/github.com/phayes/freeport/freeport.go +++ b/vendor/github.com/phayes/freeport/freeport.go @@ -4,17 +4,46 @@ import ( "net" ) -// Ask the kernel for a free open port that is ready to use -func GetPort() int { +// GetFreePort asks the kernel for a free open port that is ready to use. +func GetFreePort() (int, error) { addr, err := net.ResolveTCPAddr("tcp", "localhost:0") if err != nil { - panic(err) + return 0, err } l, err := net.ListenTCP("tcp", addr) if err != nil { - panic(err) + return 0, err } defer l.Close() - return l.Addr().(*net.TCPAddr).Port + return l.Addr().(*net.TCPAddr).Port, nil +} + +// GetPort is deprecated, use GetFreePort instead +// Ask the kernel for a free open port that is ready to use +func GetPort() int { + port, err := GetFreePort() + if err != nil { + panic(err) + } + return port +} + +// GetFreePort asks the kernel for free open ports that are ready to use. +func GetFreePorts(count int) ([]int, error) { + var ports []int + for i := 0; i < count; i++ { + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + return nil, err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil, err + } + defer l.Close() + ports = append(ports, l.Addr().(*net.TCPAddr).Port) + } + return ports, nil } diff --git a/vendor/github.com/rakyll/statik/fs/fs.go b/vendor/github.com/rakyll/statik/fs/fs.go index e328d5a24..5a5b46f2f 100644 --- a/vendor/github.com/rakyll/statik/fs/fs.go +++ b/vendor/github.com/rakyll/statik/fs/fs.go @@ -12,135 +12,227 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package contains an HTTP file system that works with zip contents. +// Package fs contains an HTTP file system that works with zip contents. package fs import ( "archive/zip" "bytes" "errors" + "fmt" "io" "io/ioutil" "net/http" "os" + "path" + "path/filepath" + "sort" "strings" - "sync" + "time" ) -var zipData string +var zipData = map[string]string{} + +// file holds unzipped read-only file contents and file metadata. +type file struct { + os.FileInfo + data []byte + fs *statikFS +} type statikFS struct { - files map[string]*zip.File + files map[string]file + dirs map[string][]string +} + +const defaultNamespace = "default" + +// IsDefaultNamespace returns true if the assetNamespace is +// the default one +func IsDefaultNamespace(assetNamespace string) bool { + return assetNamespace == defaultNamespace } -// Registers zip contents data, later used to initialize +// Register registers zip contents data, later used to initialize // the statik file system. func Register(data string) { - zipData = data + RegisterWithNamespace(defaultNamespace, data) } -// Creates a new file system with the registered zip contents data. +// RegisterWithNamespace registers zip contents data and set asset namespace, +// later used to initialize the statik file system. +func RegisterWithNamespace(assetNamespace string, data string) { + zipData[assetNamespace] = data +} + +// New creates a new file system with the default registered zip contents data. +// It unzips all files and stores them in an in-memory map. func New() (http.FileSystem, error) { - if zipData == "" { - return nil, errors.New("statik/fs: No zip data registered.") + return NewWithNamespace(defaultNamespace) +} + +// NewWithNamespace creates a new file system with the registered zip contents data. +// It unzips all files and stores them in an in-memory map. +func NewWithNamespace(assetNamespace string) (http.FileSystem, error) { + asset, ok := zipData[assetNamespace] + if !ok { + return nil, errors.New("statik/fs: no zip data registered") } - zipReader, err := zip.NewReader(strings.NewReader(zipData), int64(len(zipData))) + zipReader, err := zip.NewReader(strings.NewReader(asset), int64(len(asset))) if err != nil { return nil, err } - files := make(map[string]*zip.File) - for _, file := range zipReader.File { - files["/"+file.Name] = file + files := make(map[string]file, len(zipReader.File)) + dirs := make(map[string][]string) + fs := &statikFS{files: files, dirs: dirs} + for _, zipFile := range zipReader.File { + fi := zipFile.FileInfo() + f := file{FileInfo: fi, fs: fs} + f.data, err = unzip(zipFile) + if err != nil { + return nil, fmt.Errorf("statik/fs: error unzipping file %q: %s", zipFile.Name, err) + } + files["/"+zipFile.Name] = f + } + for fn := range files { + // go up directories recursively in order to care deep directory + for dn := path.Dir(fn); dn != fn; { + if _, ok := files[dn]; !ok { + files[dn] = file{FileInfo: dirInfo{dn}, fs: fs} + } else { + break + } + fn, dn = dn, path.Dir(dn) + } + } + for fn := range files { + dn := path.Dir(fn) + if fn != dn { + fs.dirs[dn] = append(fs.dirs[dn], path.Base(fn)) + } + } + for _, s := range fs.dirs { + sort.Strings(s) } - return &statikFS{files: files}, nil + return fs, nil } -// Opens a file, unzip the contents and initializes -// readers. Returns os.ErrNotExists if file is not -// found in the archive. -func (fs *statikFS) Open(name string) (http.File, error) { - name = strings.Replace(name, "//", "/", -1) - f, ok := fs.files[name] - - // The file doesn't match, but maybe it's a directory, - // thus we should look for index.html - if !ok { - indexName := strings.Replace(name+"/index.html", "//", "/", -1) - f, ok = fs.files[indexName] +var _ = os.FileInfo(dirInfo{}) - if !ok { - return nil, os.ErrNotExist - } +type dirInfo struct { + name string +} - return newFile(f, true) +func (di dirInfo) Name() string { return path.Base(di.name) } +func (di dirInfo) Size() int64 { return 0 } +func (di dirInfo) Mode() os.FileMode { return 0755 | os.ModeDir } +func (di dirInfo) ModTime() time.Time { return time.Time{} } +func (di dirInfo) IsDir() bool { return true } +func (di dirInfo) Sys() interface{} { return nil } + +// Open returns a file matching the given file name, or os.ErrNotExists if +// no file matching the given file name is found in the archive. +// If a directory is requested, Open returns the file named "index.html" +// in the requested directory, if that file exists. +func (fs *statikFS) Open(name string) (http.File, error) { + name = filepath.ToSlash(filepath.Clean(name)) + if f, ok := fs.files[name]; ok { + return newHTTPFile(f), nil } - return newFile(f, false) + return nil, os.ErrNotExist } -var nopCloser = ioutil.NopCloser(nil) - -func newFile(zf *zip.File, isDir bool) (*file, error) { - rc, err := zf.Open() - if err != nil { - return nil, err +func newHTTPFile(file file) *httpFile { + if file.IsDir() { + return &httpFile{file: file, isDir: true} } - defer rc.Close() - all, err := ioutil.ReadAll(rc) - if err != nil { - return nil, err - } - return &file{ - FileInfo: zf.FileInfo(), - data: all, - readerAt: bytes.NewReader(all), - Closer: nopCloser, - isDir: isDir, - }, nil + return &httpFile{file: file, reader: bytes.NewReader(file.data)} } -// Represents an HTTP file, acts as a bridge between -// zip.File and http.File. -type file struct { - os.FileInfo - io.Closer - - data []byte // non-nil if regular file - reader *io.SectionReader - readerAt io.ReaderAt // over data - isDir bool +// httpFile represents an HTTP file and acts as a bridge +// between file and http.File. +type httpFile struct { + file - once sync.Once + reader *bytes.Reader + isDir bool + dirIdx int } -func (f *file) newReader() { - f.reader = io.NewSectionReader(f.readerAt, 0, f.FileInfo.Size()) -} - -// Reads bytes into p, returns the number of read bytes. -func (f *file) Read(p []byte) (n int, err error) { - f.once.Do(f.newReader) +// Read reads bytes into p, returns the number of read bytes. +func (f *httpFile) Read(p []byte) (n int, err error) { + if f.reader == nil && f.isDir { + return 0, io.EOF + } return f.reader.Read(p) } -// Seeks to the offset. -func (f *file) Seek(offset int64, whence int) (ret int64, err error) { - f.once.Do(f.newReader) +// Seek seeks to the offset. +func (f *httpFile) Seek(offset int64, whence int) (ret int64, err error) { return f.reader.Seek(offset, whence) } -// Stats the file. -func (f *file) Stat() (os.FileInfo, error) { +// Stat stats the file. +func (f *httpFile) Stat() (os.FileInfo, error) { return f, nil } // IsDir returns true if the file location represents a directory. -func (f *file) IsDir() bool { +func (f *httpFile) IsDir() bool { return f.isDir } -// Returns an empty slice of files, directory +// Readdir returns an empty slice of files, directory // listing is disabled. -func (f *file) Readdir(count int) ([]os.FileInfo, error) { - // directory listing is disabled. - return make([]os.FileInfo, 0), nil +func (f *httpFile) Readdir(count int) ([]os.FileInfo, error) { + var fis []os.FileInfo + if !f.isDir { + return fis, nil + } + di, ok := f.FileInfo.(dirInfo) + if !ok { + return nil, fmt.Errorf("failed to read directory: %q", f.Name()) + } + + // If count is positive, the specified number of files will be returned, + // and if non-positive, all remaining files will be returned. + // The reading position of which file is returned is held in dirIndex. + fnames := f.file.fs.dirs[di.name] + flen := len(fnames) + + // If dirIdx reaches the end and the count is a positive value, + // an io.EOF error is returned. + // In other cases, no error will be returned even if, for example, + // you specified more counts than the number of remaining files. + start := f.dirIdx + if start >= flen && count > 0 { + return fis, io.EOF + } + var end int + if count <= 0 { + end = flen + } else { + end = start + count + } + if end > flen { + end = flen + } + for i := start; i < end; i++ { + fis = append(fis, f.file.fs.files[path.Join(di.name, fnames[i])].FileInfo) + } + f.dirIdx += len(fis) + return fis, nil +} + +func (f *httpFile) Close() error { + return nil +} + +func unzip(zf *zip.File) ([]byte, error) { + rc, err := zf.Open() + if err != nil { + return nil, err + } + defer rc.Close() + return ioutil.ReadAll(rc) } diff --git a/vendor/github.com/rakyll/statik/fs/walk.go b/vendor/github.com/rakyll/statik/fs/walk.go new file mode 100644 index 000000000..f4eb37d1a --- /dev/null +++ b/vendor/github.com/rakyll/statik/fs/walk.go @@ -0,0 +1,79 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fs + +import ( + "bytes" + "io" + "net/http" + "path" + "path/filepath" +) + +// Walk walks the file tree rooted at root, +// calling walkFn for each file or directory in the tree, including root. +// All errors that arise visiting files and directories are filtered by walkFn. +// +// As with filepath.Walk, if the walkFn returns filepath.SkipDir, then the directory is skipped. +func Walk(hfs http.FileSystem, root string, walkFn filepath.WalkFunc) error { + dh, err := hfs.Open(root) + if err != nil { + return err + } + di, err := dh.Stat() + if err != nil { + return err + } + fis, err := dh.Readdir(-1) + dh.Close() + if err = walkFn(root, di, err); err != nil { + if err == filepath.SkipDir { + return nil + } + return err + } + for _, fi := range fis { + fn := path.Join(root, fi.Name()) + if fi.IsDir() { + if err = Walk(hfs, fn, walkFn); err != nil { + if err == filepath.SkipDir { + continue + } + return err + } + continue + } + if err = walkFn(fn, fi, nil); err != nil { + if err == filepath.SkipDir { + continue + } + return err + } + } + return nil +} + +// ReadFile reads the contents of the file of hfs specified by name. +// Just as ioutil.ReadFile does. +func ReadFile(hfs http.FileSystem, name string) ([]byte, error) { + fh, err := hfs.Open(name) + if err != nil { + return nil, err + } + var buf bytes.Buffer + _, err = io.Copy(&buf, fh) + fh.Close() + return buf.Bytes(), err +} diff --git a/vendor/github.com/rcrowley/go-metrics/.travis.yml b/vendor/github.com/rcrowley/go-metrics/.travis.yml index 20aa5d042..ce9afeaee 100644 --- a/vendor/github.com/rcrowley/go-metrics/.travis.yml +++ b/vendor/github.com/rcrowley/go-metrics/.travis.yml @@ -1,10 +1,19 @@ language: go go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 + - "1.3" + - "1.4" + - "1.5" + - "1.6" + - "1.7" + - "1.8" + - "1.9" + - "1.10" + - "1.11" + - "1.12" + - "1.13" + - "1.14" + - "1.15" script: - ./validate.sh diff --git a/vendor/github.com/rcrowley/go-metrics/README.md b/vendor/github.com/rcrowley/go-metrics/README.md index 66ba9cab5..27ddfee8b 100644 --- a/vendor/github.com/rcrowley/go-metrics/README.md +++ b/vendor/github.com/rcrowley/go-metrics/README.md @@ -21,6 +21,9 @@ g := metrics.NewGauge() metrics.Register("bar", g) g.Update(47) +r := NewRegistry() +g := metrics.NewRegisteredFunctionalGauge("cache-evictions", r, func() int64 { return cache.getEvictionsCount() }) + s := metrics.NewExpDecaySample(1028, 0.015) // or metrics.NewUniformSample(1028) h := metrics.NewHistogram(s) metrics.Register("baz", h) @@ -36,6 +39,25 @@ t.Time(func() {}) t.Update(47) ``` +Register() is not threadsafe. For threadsafe metric registration use +GetOrRegister: + +```go +t := metrics.GetOrRegisterTimer("account.create.latency", nil) +t.Time(func() {}) +t.Update(47) +``` + +**NOTE:** Be sure to unregister short-lived meters and timers otherwise they will +leak memory: + +```go +// Will call Stop() on the Meter to allow for garbage collection +metrics.Unregister("quux") +// Or similarly for a Timer that embeds a Meter +metrics.Unregister("bang") +``` + Periodically log every metric in human-readable form to standard error: ```go @@ -67,14 +89,15 @@ issues [#121](https://github.com/rcrowley/go-metrics/issues/121) and [#124](https://github.com/rcrowley/go-metrics/issues/124) for progress and details. ```go -import "github.com/rcrowley/go-metrics/influxdb" - -go influxdb.Influxdb(metrics.DefaultRegistry, 10e9, &influxdb.Config{ - Host: "127.0.0.1:8086", - Database: "metrics", - Username: "test", - Password: "test", -}) +import "github.com/vrischmann/go-metrics-influxdb" + +go influxdb.InfluxDB(metrics.DefaultRegistry, + 10e9, + "127.0.0.1:8086", + "database-name", + "username", + "password" +) ``` Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato): @@ -134,6 +157,15 @@ Publishing Metrics Clients are available for the following destinations: -* Librato - [https://github.com/mihasya/go-metrics-librato](https://github.com/mihasya/go-metrics-librato) -* Graphite - [https://github.com/cyberdelia/go-metrics-graphite](https://github.com/cyberdelia/go-metrics-graphite) -* InfluxDB - [https://github.com/vrischmann/go-metrics-influxdb](https://github.com/vrischmann/go-metrics-influxdb) +* AppOptics - https://github.com/ysamlan/go-metrics-appoptics +* Librato - https://github.com/mihasya/go-metrics-librato +* Graphite - https://github.com/cyberdelia/go-metrics-graphite +* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb +* Ganglia - https://github.com/appscode/metlia +* Prometheus - https://github.com/deathowl/go-metrics-prometheus +* DataDog - https://github.com/syntaqx/go-metrics-datadog +* SignalFX - https://github.com/pascallouisperez/go-metrics-signalfx +* Honeycomb - https://github.com/getspine/go-metrics-honeycomb +* Wavefront - https://github.com/wavefrontHQ/go-metrics-wavefront +* Open-Falcon - https://github.com/g4zhuj/go-metrics-falcon +* AWS CloudWatch - [https://github.com/savaki/cloudmetrics](https://github.com/savaki/cloudmetrics) diff --git a/vendor/github.com/rcrowley/go-metrics/debug.go b/vendor/github.com/rcrowley/go-metrics/debug.go index 043ccefab..179e5aae7 100644 --- a/vendor/github.com/rcrowley/go-metrics/debug.go +++ b/vendor/github.com/rcrowley/go-metrics/debug.go @@ -2,6 +2,7 @@ package metrics import ( "runtime/debug" + "sync" "time" ) @@ -16,7 +17,8 @@ var ( } ReadGCStats Timer } - gcStats debug.GCStats + gcStats debug.GCStats + registerDebugMetricsOnce = sync.Once{} ) // Capture new values for the Go garbage collector statistics exported in @@ -54,19 +56,21 @@ func CaptureDebugGCStatsOnce(r Registry) { // debug.GCStats. The metrics are named by their fully-qualified Go symbols, // i.e. debug.GCStats.PauseTotal. func RegisterDebugGCStats(r Registry) { - debugMetrics.GCStats.LastGC = NewGauge() - debugMetrics.GCStats.NumGC = NewGauge() - debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) - //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) - debugMetrics.GCStats.PauseTotal = NewGauge() - debugMetrics.ReadGCStats = NewTimer() + registerDebugMetricsOnce.Do(func() { + debugMetrics.GCStats.LastGC = NewGauge() + debugMetrics.GCStats.NumGC = NewGauge() + debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) + //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) + debugMetrics.GCStats.PauseTotal = NewGauge() + debugMetrics.ReadGCStats = NewTimer() - r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) - r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) - r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) - //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) - r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) - r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) + r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) + r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) + r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) + //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) + r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) + r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) + }) } // Allocate an initial slice for gcStats.Pause to avoid allocations during diff --git a/vendor/github.com/rcrowley/go-metrics/ewma.go b/vendor/github.com/rcrowley/go-metrics/ewma.go index 694a1d033..a8183dd7e 100644 --- a/vendor/github.com/rcrowley/go-metrics/ewma.go +++ b/vendor/github.com/rcrowley/go-metrics/ewma.go @@ -79,16 +79,15 @@ func (NilEWMA) Update(n int64) {} type StandardEWMA struct { uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment alpha float64 - rate float64 - init bool + rate uint64 + init uint32 mutex sync.Mutex } // Rate returns the moving average rate of events per second. func (a *StandardEWMA) Rate() float64 { - a.mutex.Lock() - defer a.mutex.Unlock() - return a.rate * float64(1e9) + currentRate := math.Float64frombits(atomic.LoadUint64(&a.rate)) * float64(1e9) + return currentRate } // Snapshot returns a read-only copy of the EWMA. @@ -99,17 +98,38 @@ func (a *StandardEWMA) Snapshot() EWMA { // Tick ticks the clock to update the moving average. It assumes it is called // every five seconds. func (a *StandardEWMA) Tick() { + // Optimization to avoid mutex locking in the hot-path. + if atomic.LoadUint32(&a.init) == 1 { + a.updateRate(a.fetchInstantRate()) + } else { + // Slow-path: this is only needed on the first Tick() and preserves transactional updating + // of init and rate in the else block. The first conditional is needed below because + // a different thread could have set a.init = 1 between the time of the first atomic load and when + // the lock was acquired. + a.mutex.Lock() + if atomic.LoadUint32(&a.init) == 1 { + // The fetchInstantRate() uses atomic loading, which is unecessary in this critical section + // but again, this section is only invoked on the first successful Tick() operation. + a.updateRate(a.fetchInstantRate()) + } else { + atomic.StoreUint32(&a.init, 1) + atomic.StoreUint64(&a.rate, math.Float64bits(a.fetchInstantRate())) + } + a.mutex.Unlock() + } +} + +func (a *StandardEWMA) fetchInstantRate() float64 { count := atomic.LoadInt64(&a.uncounted) atomic.AddInt64(&a.uncounted, -count) instantRate := float64(count) / float64(5e9) - a.mutex.Lock() - defer a.mutex.Unlock() - if a.init { - a.rate += a.alpha * (instantRate - a.rate) - } else { - a.init = true - a.rate = instantRate - } + return instantRate +} + +func (a *StandardEWMA) updateRate(instantRate float64) { + currentRate := math.Float64frombits(atomic.LoadUint64(&a.rate)) + currentRate += a.alpha * (instantRate - currentRate) + atomic.StoreUint64(&a.rate, math.Float64bits(currentRate)) } // Update adds n uncounted events. diff --git a/vendor/github.com/rcrowley/go-metrics/gauge.go b/vendor/github.com/rcrowley/go-metrics/gauge.go index 807638a31..cb57a9388 100644 --- a/vendor/github.com/rcrowley/go-metrics/gauge.go +++ b/vendor/github.com/rcrowley/go-metrics/gauge.go @@ -36,6 +36,24 @@ func NewRegisteredGauge(name string, r Registry) Gauge { return c } +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGauge(f func() int64) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &FunctionalGauge{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { + c := NewFunctionalGauge(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + // GaugeSnapshot is a read-only copy of another Gauge. type GaugeSnapshot int64 @@ -82,3 +100,21 @@ func (g *StandardGauge) Update(v int64) { func (g *StandardGauge) Value() int64 { return atomic.LoadInt64(&g.value) } + +// FunctionalGauge returns value from given function +type FunctionalGauge struct { + value func() int64 +} + +// Value returns the gauge's current value. +func (g FunctionalGauge) Value() int64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } + +// Update panics. +func (FunctionalGauge) Update(int64) { + panic("Update called on a FunctionalGauge") +} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge_float64.go b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go index 47c3566c2..3962e6db0 100644 --- a/vendor/github.com/rcrowley/go-metrics/gauge_float64.go +++ b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go @@ -1,6 +1,9 @@ package metrics -import "sync" +import ( + "math" + "sync/atomic" +) // GaugeFloat64s hold a float64 value that can be set arbitrarily. type GaugeFloat64 interface { @@ -38,6 +41,24 @@ func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { return c } +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &FunctionalGaugeFloat64{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { + c := NewFunctionalGaugeFloat64(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + // GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. type GaugeFloat64Snapshot float64 @@ -67,8 +88,7 @@ func (NilGaugeFloat64) Value() float64 { return 0.0 } // StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses // sync.Mutex to manage a single float64 value. type StandardGaugeFloat64 struct { - mutex sync.Mutex - value float64 + value uint64 } // Snapshot returns a read-only copy of the gauge. @@ -78,14 +98,28 @@ func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { // Update updates the gauge's value. func (g *StandardGaugeFloat64) Update(v float64) { - g.mutex.Lock() - defer g.mutex.Unlock() - g.value = v + atomic.StoreUint64(&g.value, math.Float64bits(v)) } // Value returns the gauge's current value. func (g *StandardGaugeFloat64) Value() float64 { - g.mutex.Lock() - defer g.mutex.Unlock() - return g.value + return math.Float64frombits(atomic.LoadUint64(&g.value)) +} + +// FunctionalGaugeFloat64 returns value from given function +type FunctionalGaugeFloat64 struct { + value func() float64 +} + +// Value returns the gauge's current value. +func (g FunctionalGaugeFloat64) Value() float64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } + +// Update panics. +func (FunctionalGaugeFloat64) Update(float64) { + panic("Update called on a FunctionalGaugeFloat64") } diff --git a/vendor/github.com/rcrowley/go-metrics/json.go b/vendor/github.com/rcrowley/go-metrics/json.go index 2676aeea5..174b9477e 100644 --- a/vendor/github.com/rcrowley/go-metrics/json.go +++ b/vendor/github.com/rcrowley/go-metrics/json.go @@ -9,63 +9,7 @@ import ( // MarshalJSON returns a byte slice containing a JSON representation of all // the metrics in the Registry. func (r *StandardRegistry) MarshalJSON() ([]byte, error) { - data := make(map[string]map[string]interface{}) - r.Each(func(name string, i interface{}) { - values := make(map[string]interface{}) - switch metric := i.(type) { - case Counter: - values["count"] = metric.Count() - case Gauge: - values["value"] = metric.Value() - case GaugeFloat64: - values["value"] = metric.Value() - case Healthcheck: - values["error"] = nil - metric.Check() - if err := metric.Error(); nil != err { - values["error"] = metric.Error().Error() - } - case Histogram: - h := metric.Snapshot() - ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) - values["count"] = h.Count() - values["min"] = h.Min() - values["max"] = h.Max() - values["mean"] = h.Mean() - values["stddev"] = h.StdDev() - values["median"] = ps[0] - values["75%"] = ps[1] - values["95%"] = ps[2] - values["99%"] = ps[3] - values["99.9%"] = ps[4] - case Meter: - m := metric.Snapshot() - values["count"] = m.Count() - values["1m.rate"] = m.Rate1() - values["5m.rate"] = m.Rate5() - values["15m.rate"] = m.Rate15() - values["mean.rate"] = m.RateMean() - case Timer: - t := metric.Snapshot() - ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) - values["count"] = t.Count() - values["min"] = t.Min() - values["max"] = t.Max() - values["mean"] = t.Mean() - values["stddev"] = t.StdDev() - values["median"] = ps[0] - values["75%"] = ps[1] - values["95%"] = ps[2] - values["99%"] = ps[3] - values["99.9%"] = ps[4] - values["1m.rate"] = t.Rate1() - values["5m.rate"] = t.Rate5() - values["15m.rate"] = t.Rate15() - values["mean.rate"] = t.RateMean() - } - data[name] = values - }) - return json.Marshal(data) + return json.Marshal(r.GetAll()) } // WriteJSON writes metrics from the given registry periodically to the @@ -81,3 +25,7 @@ func WriteJSON(r Registry, d time.Duration, w io.Writer) { func WriteJSONOnce(r Registry, w io.Writer) { json.NewEncoder(w).Encode(r) } + +func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(p.GetAll()) +} diff --git a/vendor/github.com/rcrowley/go-metrics/log.go b/vendor/github.com/rcrowley/go-metrics/log.go index f074eb03d..2614a0a33 100644 --- a/vendor/github.com/rcrowley/go-metrics/log.go +++ b/vendor/github.com/rcrowley/go-metrics/log.go @@ -1,21 +1,44 @@ package metrics import ( - "log" "time" ) -func Log(r Registry, freq time.Duration, l *log.Logger) { +type Logger interface { + Printf(format string, v ...interface{}) +} + +// Log outputs each metric in the given registry periodically using the given logger. +func Log(r Registry, freq time.Duration, l Logger) { LogScaled(r, freq, time.Nanosecond, l) } -// Output each metric in the given registry periodically using the given +// LogOnCue outputs each metric in the given registry on demand through the channel +// using the given logger +func LogOnCue(r Registry, ch chan interface{}, l Logger) { + LogScaledOnCue(r, ch, time.Nanosecond, l) +} + +// LogScaled outputs each metric in the given registry periodically using the given // logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. -func LogScaled(r Registry, freq time.Duration, scale time.Duration, l *log.Logger) { +func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { + ch := make(chan interface{}) + go func(channel chan interface{}) { + for _ = range time.Tick(freq) { + channel <- struct{}{} + } + }(ch) + LogScaledOnCue(r, ch, scale, l) +} + +// LogScaledOnCue outputs each metric in the given registry on demand through the channel +// using the given logger. Print timings in `scale` units (eg time.Millisecond) rather +// than nanos. +func LogScaledOnCue(r Registry, ch chan interface{}, scale time.Duration, l Logger) { du := float64(scale) duSuffix := scale.String()[1:] - for _ = range time.Tick(freq) { + for _ = range ch { r.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: diff --git a/vendor/github.com/rcrowley/go-metrics/meter.go b/vendor/github.com/rcrowley/go-metrics/meter.go index 0389ab0b8..223669bcb 100644 --- a/vendor/github.com/rcrowley/go-metrics/meter.go +++ b/vendor/github.com/rcrowley/go-metrics/meter.go @@ -1,7 +1,9 @@ package metrics import ( + "math" "sync" + "sync/atomic" "time" ) @@ -15,10 +17,13 @@ type Meter interface { Rate15() float64 RateMean() float64 Snapshot() Meter + Stop() } // GetOrRegisterMeter returns an existing Meter or constructs and registers a // new StandardMeter. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func GetOrRegisterMeter(name string, r Registry) Meter { if nil == r { r = DefaultRegistry @@ -27,6 +32,7 @@ func GetOrRegisterMeter(name string, r Registry) Meter { } // NewMeter constructs a new StandardMeter and launches a goroutine. +// Be sure to call Stop() once the meter is of no use to allow for garbage collection. func NewMeter() Meter { if UseNilMetrics { return NilMeter{} @@ -34,7 +40,7 @@ func NewMeter() Meter { m := newStandardMeter() arbiter.Lock() defer arbiter.Unlock() - arbiter.meters = append(arbiter.meters, m) + arbiter.meters[m] = struct{}{} if !arbiter.started { arbiter.started = true go arbiter.tick() @@ -44,6 +50,8 @@ func NewMeter() Meter { // NewMeter constructs and registers a new StandardMeter and launches a // goroutine. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func NewRegisteredMeter(name string, r Registry) Meter { c := NewMeter() if nil == r { @@ -56,7 +64,7 @@ func NewRegisteredMeter(name string, r Registry) Meter { // MeterSnapshot is a read-only copy of another Meter. type MeterSnapshot struct { count int64 - rate1, rate5, rate15, rateMean float64 + rate1, rate5, rate15, rateMean uint64 } // Count returns the count of events at the time the snapshot was taken. @@ -69,23 +77,26 @@ func (*MeterSnapshot) Mark(n int64) { // Rate1 returns the one-minute moving average rate of events per second at the // time the snapshot was taken. -func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } +func (m *MeterSnapshot) Rate1() float64 { return math.Float64frombits(m.rate1) } // Rate5 returns the five-minute moving average rate of events per second at // the time the snapshot was taken. -func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } +func (m *MeterSnapshot) Rate5() float64 { return math.Float64frombits(m.rate5) } // Rate15 returns the fifteen-minute moving average rate of events per second // at the time the snapshot was taken. -func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } +func (m *MeterSnapshot) Rate15() float64 { return math.Float64frombits(m.rate15) } // RateMean returns the meter's mean rate of events per second at the time the // snapshot was taken. -func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } +func (m *MeterSnapshot) RateMean() float64 { return math.Float64frombits(m.rateMean) } // Snapshot returns the snapshot. func (m *MeterSnapshot) Snapshot() Meter { return m } +// Stop is a no-op. +func (m *MeterSnapshot) Stop() {} + // NilMeter is a no-op Meter. type NilMeter struct{} @@ -110,12 +121,15 @@ func (NilMeter) RateMean() float64 { return 0.0 } // Snapshot is a no-op. func (NilMeter) Snapshot() Meter { return NilMeter{} } +// Stop is a no-op. +func (NilMeter) Stop() {} + // StandardMeter is the standard implementation of a Meter. type StandardMeter struct { - lock sync.RWMutex snapshot *MeterSnapshot a1, a5, a15 EWMA startTime time.Time + stopped uint32 } func newStandardMeter() *StandardMeter { @@ -128,19 +142,28 @@ func newStandardMeter() *StandardMeter { } } +// Stop stops the meter, Mark() will be a no-op if you use it after being stopped. +func (m *StandardMeter) Stop() { + if atomic.CompareAndSwapUint32(&m.stopped, 0, 1) { + arbiter.Lock() + delete(arbiter.meters, m) + arbiter.Unlock() + } +} + // Count returns the number of events recorded. func (m *StandardMeter) Count() int64 { - m.lock.RLock() - count := m.snapshot.count - m.lock.RUnlock() - return count + return atomic.LoadInt64(&m.snapshot.count) } // Mark records the occurance of n events. func (m *StandardMeter) Mark(n int64) { - m.lock.Lock() - defer m.lock.Unlock() - m.snapshot.count += n + if atomic.LoadUint32(&m.stopped) == 1 { + return + } + + atomic.AddInt64(&m.snapshot.count, n) + m.a1.Update(n) m.a5.Update(n) m.a15.Update(n) @@ -149,70 +172,65 @@ func (m *StandardMeter) Mark(n int64) { // Rate1 returns the one-minute moving average rate of events per second. func (m *StandardMeter) Rate1() float64 { - m.lock.RLock() - rate1 := m.snapshot.rate1 - m.lock.RUnlock() - return rate1 + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate1)) } // Rate5 returns the five-minute moving average rate of events per second. func (m *StandardMeter) Rate5() float64 { - m.lock.RLock() - rate5 := m.snapshot.rate5 - m.lock.RUnlock() - return rate5 + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate5)) } // Rate15 returns the fifteen-minute moving average rate of events per second. func (m *StandardMeter) Rate15() float64 { - m.lock.RLock() - rate15 := m.snapshot.rate15 - m.lock.RUnlock() - return rate15 + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate15)) } // RateMean returns the meter's mean rate of events per second. func (m *StandardMeter) RateMean() float64 { - m.lock.RLock() - rateMean := m.snapshot.rateMean - m.lock.RUnlock() - return rateMean + return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rateMean)) } // Snapshot returns a read-only copy of the meter. func (m *StandardMeter) Snapshot() Meter { - m.lock.RLock() - snapshot := *m.snapshot - m.lock.RUnlock() - return &snapshot + copiedSnapshot := MeterSnapshot{ + count: atomic.LoadInt64(&m.snapshot.count), + rate1: atomic.LoadUint64(&m.snapshot.rate1), + rate5: atomic.LoadUint64(&m.snapshot.rate5), + rate15: atomic.LoadUint64(&m.snapshot.rate15), + rateMean: atomic.LoadUint64(&m.snapshot.rateMean), + } + return &copiedSnapshot } func (m *StandardMeter) updateSnapshot() { - // should run with write lock held on m.lock - snapshot := m.snapshot - snapshot.rate1 = m.a1.Rate() - snapshot.rate5 = m.a5.Rate() - snapshot.rate15 = m.a15.Rate() - snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() + rate1 := math.Float64bits(m.a1.Rate()) + rate5 := math.Float64bits(m.a5.Rate()) + rate15 := math.Float64bits(m.a15.Rate()) + rateMean := math.Float64bits(float64(m.Count()) / time.Since(m.startTime).Seconds()) + + atomic.StoreUint64(&m.snapshot.rate1, rate1) + atomic.StoreUint64(&m.snapshot.rate5, rate5) + atomic.StoreUint64(&m.snapshot.rate15, rate15) + atomic.StoreUint64(&m.snapshot.rateMean, rateMean) } func (m *StandardMeter) tick() { - m.lock.Lock() - defer m.lock.Unlock() m.a1.Tick() m.a5.Tick() m.a15.Tick() m.updateSnapshot() } +// meterArbiter ticks meters every 5s from a single goroutine. +// meters are references in a set for future stopping. type meterArbiter struct { sync.RWMutex started bool - meters []*StandardMeter + meters map[*StandardMeter]struct{} ticker *time.Ticker } -var arbiter = meterArbiter{ticker: time.NewTicker(5e9)} +var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})} // Ticks meters on the scheduled interval func (ma *meterArbiter) tick() { @@ -227,7 +245,7 @@ func (ma *meterArbiter) tick() { func (ma *meterArbiter) tickMeters() { ma.RLock() defer ma.RUnlock() - for _, meter := range ma.meters { + for meter := range ma.meters { meter.tick() } } diff --git a/vendor/github.com/rcrowley/go-metrics/registry.go b/vendor/github.com/rcrowley/go-metrics/registry.go index e1f68a5dc..a8e67228a 100644 --- a/vendor/github.com/rcrowley/go-metrics/registry.go +++ b/vendor/github.com/rcrowley/go-metrics/registry.go @@ -3,6 +3,7 @@ package metrics import ( "fmt" "reflect" + "strings" "sync" ) @@ -28,6 +29,9 @@ type Registry interface { // Get the metric by the given name or nil if none is registered. Get(string) interface{} + // GetAll metrics in the Registry. + GetAll() map[string]map[string]interface{} + // Gets an existing metric or registers the given one. // The interface can be the metric to register if not found in registry, // or a function returning the metric for lazy instantiation. @@ -50,7 +54,7 @@ type Registry interface { // of names to metrics. type StandardRegistry struct { metrics map[string]interface{} - mutex sync.Mutex + mutex sync.RWMutex } // Create a new registry. @@ -60,15 +64,17 @@ func NewRegistry() Registry { // Call the given function for each registered metric. func (r *StandardRegistry) Each(f func(string, interface{})) { - for name, i := range r.registered() { - f(name, i) + metrics := r.registered() + for i := range metrics { + kv := &metrics[i] + f(kv.name, kv.value) } } // Get the metric by the given name or nil if none is registered. func (r *StandardRegistry) Get(name string) interface{} { - r.mutex.Lock() - defer r.mutex.Unlock() + r.mutex.RLock() + defer r.mutex.RUnlock() return r.metrics[name] } @@ -77,6 +83,15 @@ func (r *StandardRegistry) Get(name string) interface{} { // The interface can be the metric to register if not found in registry, // or a function returning the metric for lazy instantiation. func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { + // access the read lock first which should be re-entrant + r.mutex.RLock() + metric, ok := r.metrics[name] + r.mutex.RUnlock() + if ok { + return metric + } + + // only take the write lock if we'll be modifying the metrics map r.mutex.Lock() defer r.mutex.Unlock() if metric, ok := r.metrics[name]; ok { @@ -99,8 +114,8 @@ func (r *StandardRegistry) Register(name string, i interface{}) error { // Run all registered healthchecks. func (r *StandardRegistry) RunHealthchecks() { - r.mutex.Lock() - defer r.mutex.Unlock() + r.mutex.RLock() + defer r.mutex.RUnlock() for _, i := range r.metrics { if h, ok := i.(Healthcheck); ok { h.Check() @@ -108,10 +123,72 @@ func (r *StandardRegistry) RunHealthchecks() { } } +// GetAll metrics in the Registry +func (r *StandardRegistry) GetAll() map[string]map[string]interface{} { + data := make(map[string]map[string]interface{}) + r.Each(func(name string, i interface{}) { + values := make(map[string]interface{}) + switch metric := i.(type) { + case Counter: + values["count"] = metric.Count() + case Gauge: + values["value"] = metric.Value() + case GaugeFloat64: + values["value"] = metric.Value() + case Healthcheck: + values["error"] = nil + metric.Check() + if err := metric.Error(); nil != err { + values["error"] = metric.Error().Error() + } + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = h.Count() + values["min"] = h.Min() + values["max"] = h.Max() + values["mean"] = h.Mean() + values["stddev"] = h.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + case Meter: + m := metric.Snapshot() + values["count"] = m.Count() + values["1m.rate"] = m.Rate1() + values["5m.rate"] = m.Rate5() + values["15m.rate"] = m.Rate15() + values["mean.rate"] = m.RateMean() + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = t.Count() + values["min"] = t.Min() + values["max"] = t.Max() + values["mean"] = t.Mean() + values["stddev"] = t.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + values["1m.rate"] = t.Rate1() + values["5m.rate"] = t.Rate5() + values["15m.rate"] = t.Rate15() + values["mean.rate"] = t.RateMean() + } + data[name] = values + }) + return data +} + // Unregister the metric with the given name. func (r *StandardRegistry) Unregister(name string) { r.mutex.Lock() defer r.mutex.Unlock() + r.stop(name) delete(r.metrics, name) } @@ -120,6 +197,7 @@ func (r *StandardRegistry) UnregisterAll() { r.mutex.Lock() defer r.mutex.Unlock() for name, _ := range r.metrics { + r.stop(name) delete(r.metrics, name) } } @@ -135,16 +213,37 @@ func (r *StandardRegistry) register(name string, i interface{}) error { return nil } -func (r *StandardRegistry) registered() map[string]interface{} { - r.mutex.Lock() - defer r.mutex.Unlock() - metrics := make(map[string]interface{}, len(r.metrics)) +type metricKV struct { + name string + value interface{} +} + +func (r *StandardRegistry) registered() []metricKV { + r.mutex.RLock() + defer r.mutex.RUnlock() + metrics := make([]metricKV, 0, len(r.metrics)) for name, i := range r.metrics { - metrics[name] = i + metrics = append(metrics, metricKV{ + name: name, + value: i, + }) } return metrics } +func (r *StandardRegistry) stop(name string) { + if i, ok := r.metrics[name]; ok { + if s, ok := i.(Stoppable); ok { + s.Stop() + } + } +} + +// Stoppable defines the metrics which has to be stopped. +type Stoppable interface { + Stop() +} + type PrefixedRegistry struct { underlying Registry prefix string @@ -166,12 +265,34 @@ func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { // Call the given function for each registered metric. func (r *PrefixedRegistry) Each(fn func(string, interface{})) { - r.underlying.Each(fn) + wrappedFn := func(prefix string) func(string, interface{}) { + return func(name string, iface interface{}) { + if strings.HasPrefix(name, prefix) { + fn(name, iface) + } else { + return + } + } + } + + baseRegistry, prefix := findPrefix(r, "") + baseRegistry.Each(wrappedFn(prefix)) +} + +func findPrefix(registry Registry, prefix string) (Registry, string) { + switch r := registry.(type) { + case *PrefixedRegistry: + return findPrefix(r.underlying, r.prefix+prefix) + case *StandardRegistry: + return r, prefix + } + return nil, "" } // Get the metric by the given name or nil if none is registered. func (r *PrefixedRegistry) Get(name string) interface{} { - return r.underlying.Get(name) + realName := r.prefix + name + return r.underlying.Get(realName) } // Gets an existing metric or registers the given one. @@ -193,6 +314,11 @@ func (r *PrefixedRegistry) RunHealthchecks() { r.underlying.RunHealthchecks() } +// GetAll metrics in the Registry +func (r *PrefixedRegistry) GetAll() map[string]map[string]interface{} { + return r.underlying.GetAll() +} + // Unregister the metric with the given name. The name will be prefixed. func (r *PrefixedRegistry) Unregister(name string) { realName := r.prefix + name diff --git a/vendor/github.com/rcrowley/go-metrics/runtime.go b/vendor/github.com/rcrowley/go-metrics/runtime.go index 11c6b785a..4047ab3d3 100644 --- a/vendor/github.com/rcrowley/go-metrics/runtime.go +++ b/vendor/github.com/rcrowley/go-metrics/runtime.go @@ -3,6 +3,7 @@ package metrics import ( "runtime" "runtime/pprof" + "sync" "time" ) @@ -49,7 +50,8 @@ var ( numGC uint32 numCgoCalls int64 - threadCreateProfile = pprof.Lookup("threadcreate") + threadCreateProfile = pprof.Lookup("threadcreate") + registerRuntimeMetricsOnce = sync.Once{} ) // Capture new values for the Go runtime statistics exported in @@ -146,67 +148,69 @@ func CaptureRuntimeMemStatsOnce(r Registry) { // specifically runtime.MemStats. The runtimeMetrics are named by their // fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. func RegisterRuntimeMemStats(r Registry) { - runtimeMetrics.MemStats.Alloc = NewGauge() - runtimeMetrics.MemStats.BuckHashSys = NewGauge() - runtimeMetrics.MemStats.DebugGC = NewGauge() - runtimeMetrics.MemStats.EnableGC = NewGauge() - runtimeMetrics.MemStats.Frees = NewGauge() - runtimeMetrics.MemStats.HeapAlloc = NewGauge() - runtimeMetrics.MemStats.HeapIdle = NewGauge() - runtimeMetrics.MemStats.HeapInuse = NewGauge() - runtimeMetrics.MemStats.HeapObjects = NewGauge() - runtimeMetrics.MemStats.HeapReleased = NewGauge() - runtimeMetrics.MemStats.HeapSys = NewGauge() - runtimeMetrics.MemStats.LastGC = NewGauge() - runtimeMetrics.MemStats.Lookups = NewGauge() - runtimeMetrics.MemStats.Mallocs = NewGauge() - runtimeMetrics.MemStats.MCacheInuse = NewGauge() - runtimeMetrics.MemStats.MCacheSys = NewGauge() - runtimeMetrics.MemStats.MSpanInuse = NewGauge() - runtimeMetrics.MemStats.MSpanSys = NewGauge() - runtimeMetrics.MemStats.NextGC = NewGauge() - runtimeMetrics.MemStats.NumGC = NewGauge() - runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() - runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) - runtimeMetrics.MemStats.PauseTotalNs = NewGauge() - runtimeMetrics.MemStats.StackInuse = NewGauge() - runtimeMetrics.MemStats.StackSys = NewGauge() - runtimeMetrics.MemStats.Sys = NewGauge() - runtimeMetrics.MemStats.TotalAlloc = NewGauge() - runtimeMetrics.NumCgoCall = NewGauge() - runtimeMetrics.NumGoroutine = NewGauge() - runtimeMetrics.NumThread = NewGauge() - runtimeMetrics.ReadMemStats = NewTimer() + registerRuntimeMetricsOnce.Do(func() { + runtimeMetrics.MemStats.Alloc = NewGauge() + runtimeMetrics.MemStats.BuckHashSys = NewGauge() + runtimeMetrics.MemStats.DebugGC = NewGauge() + runtimeMetrics.MemStats.EnableGC = NewGauge() + runtimeMetrics.MemStats.Frees = NewGauge() + runtimeMetrics.MemStats.HeapAlloc = NewGauge() + runtimeMetrics.MemStats.HeapIdle = NewGauge() + runtimeMetrics.MemStats.HeapInuse = NewGauge() + runtimeMetrics.MemStats.HeapObjects = NewGauge() + runtimeMetrics.MemStats.HeapReleased = NewGauge() + runtimeMetrics.MemStats.HeapSys = NewGauge() + runtimeMetrics.MemStats.LastGC = NewGauge() + runtimeMetrics.MemStats.Lookups = NewGauge() + runtimeMetrics.MemStats.Mallocs = NewGauge() + runtimeMetrics.MemStats.MCacheInuse = NewGauge() + runtimeMetrics.MemStats.MCacheSys = NewGauge() + runtimeMetrics.MemStats.MSpanInuse = NewGauge() + runtimeMetrics.MemStats.MSpanSys = NewGauge() + runtimeMetrics.MemStats.NextGC = NewGauge() + runtimeMetrics.MemStats.NumGC = NewGauge() + runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() + runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) + runtimeMetrics.MemStats.PauseTotalNs = NewGauge() + runtimeMetrics.MemStats.StackInuse = NewGauge() + runtimeMetrics.MemStats.StackSys = NewGauge() + runtimeMetrics.MemStats.Sys = NewGauge() + runtimeMetrics.MemStats.TotalAlloc = NewGauge() + runtimeMetrics.NumCgoCall = NewGauge() + runtimeMetrics.NumGoroutine = NewGauge() + runtimeMetrics.NumThread = NewGauge() + runtimeMetrics.ReadMemStats = NewTimer() - r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) - r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) - r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) - r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) - r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) - r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) - r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) - r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) - r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) - r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) - r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) - r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) - r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) - r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) - r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) - r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) - r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) - r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) - r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) - r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) - r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) - r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) - r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) - r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) - r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) - r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) - r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) - r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) - r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) - r.Register("runtime.NumThread", runtimeMetrics.NumThread) - r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) + r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) + r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) + r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) + r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) + r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) + r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) + r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) + r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) + r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) + r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) + r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) + r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) + r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) + r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) + r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) + r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) + r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) + r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) + r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) + r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) + r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) + r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) + r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) + r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) + r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) + r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) + r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) + r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) + r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) + r.Register("runtime.NumThread", runtimeMetrics.NumThread) + r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) + }) } diff --git a/vendor/github.com/rcrowley/go-metrics/sample.go b/vendor/github.com/rcrowley/go-metrics/sample.go index 5f6a37788..fecee5ef6 100644 --- a/vendor/github.com/rcrowley/go-metrics/sample.go +++ b/vendor/github.com/rcrowley/go-metrics/sample.go @@ -33,7 +33,7 @@ type Sample interface { // priority reservoir. See Cormode et al's "Forward Decay: A Practical Time // Decay Model for Streaming Systems". // -// +// type ExpDecaySample struct { alpha float64 count int64 @@ -302,6 +302,13 @@ type SampleSnapshot struct { values []int64 } +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + // Clear panics. func (*SampleSnapshot) Clear() { panic("Clear called on a SampleSnapshot") diff --git a/vendor/github.com/rcrowley/go-metrics/timer.go b/vendor/github.com/rcrowley/go-metrics/timer.go index 17db8f8d2..d6ec4c626 100644 --- a/vendor/github.com/rcrowley/go-metrics/timer.go +++ b/vendor/github.com/rcrowley/go-metrics/timer.go @@ -19,6 +19,7 @@ type Timer interface { RateMean() float64 Snapshot() Timer StdDev() float64 + Stop() Sum() int64 Time(func()) Update(time.Duration) @@ -28,6 +29,8 @@ type Timer interface { // GetOrRegisterTimer returns an existing Timer or constructs and registers a // new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func GetOrRegisterTimer(name string, r Registry) Timer { if nil == r { r = DefaultRegistry @@ -36,6 +39,7 @@ func GetOrRegisterTimer(name string, r Registry) Timer { } // NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. func NewCustomTimer(h Histogram, m Meter) Timer { if UseNilMetrics { return NilTimer{} @@ -47,6 +51,8 @@ func NewCustomTimer(h Histogram, m Meter) Timer { } // NewRegisteredTimer constructs and registers a new StandardTimer. +// Be sure to unregister the meter from the registry once it is of no use to +// allow for garbage collection. func NewRegisteredTimer(name string, r Registry) Timer { c := NewTimer() if nil == r { @@ -58,6 +64,7 @@ func NewRegisteredTimer(name string, r Registry) Timer { // NewTimer constructs a new StandardTimer using an exponentially-decaying // sample with the same reservoir size and alpha as UNIX load averages. +// Be sure to call Stop() once the timer is of no use to allow for garbage collection. func NewTimer() Timer { if UseNilMetrics { return NilTimer{} @@ -112,6 +119,9 @@ func (NilTimer) Snapshot() Timer { return NilTimer{} } // StdDev is a no-op. func (NilTimer) StdDev() float64 { return 0.0 } +// Stop is a no-op. +func (NilTimer) Stop() {} + // Sum is a no-op. func (NilTimer) Sum() int64 { return 0 } @@ -201,6 +211,11 @@ func (t *StandardTimer) StdDev() float64 { return t.histogram.StdDev() } +// Stop stops the meter. +func (t *StandardTimer) Stop() { + t.meter.Stop() +} + // Sum returns the sum in the sample. func (t *StandardTimer) Sum() int64 { return t.histogram.Sum() @@ -288,6 +303,9 @@ func (t *TimerSnapshot) Snapshot() Timer { return t } // was taken. func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } +// Stop is a no-op. +func (t *TimerSnapshot) Stop() {} + // Sum returns the sum at the time the snapshot was taken. func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } diff --git a/vendor/github.com/rcrowley/go-metrics/validate.sh b/vendor/github.com/rcrowley/go-metrics/validate.sh index f6499982e..c4ae91e64 100644 --- a/vendor/github.com/rcrowley/go-metrics/validate.sh +++ b/vendor/github.com/rcrowley/go-metrics/validate.sh @@ -7,4 +7,4 @@ GOFMT_LINES=`gofmt -l . | wc -l | xargs` test $GOFMT_LINES -eq 0 || echo "gofmt needs to be run, ${GOFMT_LINES} files have issues" # run the tests for the root package -go test . +go test -race . diff --git a/vendor/github.com/rivo/uniseg/LICENSE.txt b/vendor/github.com/rivo/uniseg/LICENSE.txt new file mode 100644 index 000000000..5040f1ef8 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Oliver Kuederle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/rivo/uniseg/README.md b/vendor/github.com/rivo/uniseg/README.md new file mode 100644 index 000000000..a8191b815 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/README.md @@ -0,0 +1,137 @@ +# Unicode Text Segmentation for Go + +[![Go Reference](https://pkg.go.dev/badge/github.com/rivo/uniseg.svg)](https://pkg.go.dev/github.com/rivo/uniseg) +[![Go Report](https://img.shields.io/badge/go%20report-A%2B-brightgreen.svg)](https://goreportcard.com/report/github.com/rivo/uniseg) + +This Go package implements Unicode Text Segmentation according to [Unicode Standard Annex #29](https://unicode.org/reports/tr29/), Unicode Line Breaking according to [Unicode Standard Annex #14](https://unicode.org/reports/tr14/) (Unicode version 15.0.0), and monospace font string width calculation similar to [wcwidth](https://man7.org/linux/man-pages/man3/wcwidth.3.html). + +## Background + +### Grapheme Clusters + +In Go, [strings are read-only slices of bytes](https://go.dev/blog/strings). They can be turned into Unicode code points using the `for` loop or by casting: `[]rune(str)`. However, multiple code points may be combined into one user-perceived character or what the Unicode specification calls "grapheme cluster". Here are some examples: + +|String|Bytes (UTF-8)|Code points (runes)|Grapheme clusters| +|-|-|-|-| +|Käse|6 bytes: `4b 61 cc 88 73 65`|5 code points: `4b 61 308 73 65`|4 clusters: `[4b],[61 308],[73],[65]`| +|🏳️‍🌈|14 bytes: `f0 9f 8f b3 ef b8 8f e2 80 8d f0 9f 8c 88`|4 code points: `1f3f3 fe0f 200d 1f308`|1 cluster: `[1f3f3 fe0f 200d 1f308]`| +|🇩🇪|8 bytes: `f0 9f 87 a9 f0 9f 87 aa`|2 code points: `1f1e9 1f1ea`|1 cluster: `[1f1e9 1f1ea]`| + +This package provides tools to iterate over these grapheme clusters. This may be used to determine the number of user-perceived characters, to split strings in their intended places, or to extract individual characters which form a unit. + +### Word Boundaries + +Word boundaries are used in a number of different contexts. The most familiar ones are selection (double-click mouse selection), cursor movement ("move to next word" control-arrow keys), and the dialog option "Whole Word Search" for search and replace. They are also used in database queries, to determine whether elements are within a certain number of words of one another. Searching may also use word boundaries in determining matching items. This package provides tools to determine word boundaries within strings. + +### Sentence Boundaries + +Sentence boundaries are often used for triple-click or some other method of selecting or iterating through blocks of text that are larger than single words. They are also used to determine whether words occur within the same sentence in database queries. This package provides tools to determine sentence boundaries within strings. + +### Line Breaking + +Line breaking, also known as word wrapping, is the process of breaking a section of text into lines such that it will fit in the available width of a page, window or other display area. This package provides tools to determine where a string may or may not be broken and where it must be broken (for example after newline characters). + +### Monospace Width + +Most terminals or text displays / text editors using a monospace font (for example source code editors) use a fixed width for each character. Some characters such as emojis or characters found in Asian and other languages may take up more than one character cell. This package provides tools to determine the number of cells a string will take up when displayed in a monospace font. See [here](https://pkg.go.dev/github.com/rivo/uniseg#hdr-Monospace_Width) for more information. + +## Installation + +```bash +go get github.com/rivo/uniseg +``` + +## Examples + +### Counting Characters in a String + +```go +n := uniseg.GraphemeClusterCount("🇩🇪🏳️‍🌈") +fmt.Println(n) +// 2 +``` + +### Calculating the Monospace String Width + +```go +width := uniseg.StringWidth("🇩🇪🏳️‍🌈!") +fmt.Println(width) +// 5 +``` + +### Using the [`Graphemes`](https://pkg.go.dev/github.com/rivo/uniseg#Graphemes) Class + +This is the most convenient method of iterating over grapheme clusters: + +```go +gr := uniseg.NewGraphemes("👍🏼!") +for gr.Next() { + fmt.Printf("%x ", gr.Runes()) +} +// [1f44d 1f3fc] [21] +``` + +### Using the [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step) or [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString) Function + +This avoids allocating a new `Graphemes` object but it requires the handling of states and boundaries: + +```go +str := "🇩🇪🏳️‍🌈" +state := -1 +var c string +for len(str) > 0 { + c, str, _, state = uniseg.StepString(str, state) + fmt.Printf("%x ", []rune(c)) +} +// [1f1e9 1f1ea] [1f3f3 fe0f 200d 1f308] +``` + +### Advanced Examples + +The [`Graphemes`](https://pkg.go.dev/github.com/rivo/uniseg#Graphemes) class offers the most convenient way to access all functionality of this package. But in some cases, it may be better to use the specialized functions directly. For example, if you're only interested in word segmentation, use [`FirstWord`](https://pkg.go.dev/github.com/rivo/uniseg#FirstWord) or [`FirstWordInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstWordInString): + +```go +str := "Hello, world!" +state := -1 +var c string +for len(str) > 0 { + c, str, state = uniseg.FirstWordInString(str, state) + fmt.Printf("(%s)\n", c) +} +// (Hello) +// (,) +// ( ) +// (world) +// (!) +``` + +Similarly, use + +- [`FirstGraphemeCluster`](https://pkg.go.dev/github.com/rivo/uniseg#FirstGraphemeCluster) or [`FirstGraphemeClusterInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstGraphemeClusterInString) for grapheme cluster determination only, +- [`FirstSentence`](https://pkg.go.dev/github.com/rivo/uniseg#FirstSentence) or [`FirstSentenceInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstSentenceInString) for sentence segmentation only, and +- [`FirstLineSegment`](https://pkg.go.dev/github.com/rivo/uniseg#FirstLineSegment) or [`FirstLineSegmentInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstLineSegmentInString) for line breaking / word wrapping (although using [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step) or [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString) is preferred as it will observe grapheme cluster boundaries). + +If you're only interested in the width of characters, use [`FirstGraphemeCluster`](https://pkg.go.dev/github.com/rivo/uniseg#FirstGraphemeCluster) or [`FirstGraphemeClusterInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstGraphemeClusterInString). It is much faster than using [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step), [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString), or the [`Graphemes`](https://pkg.go.dev/github.com/rivo/uniseg#Graphemes) class because it does not include the logic for word / sentence / line boundaries. + +Finally, if you need to reverse a string while preserving grapheme clusters, use [`ReverseString`](https://pkg.go.dev/github.com/rivo/uniseg#ReverseString): + +```go +fmt.Println(uniseg.ReverseString("🇩🇪🏳️‍🌈")) +// 🏳️‍🌈🇩🇪 +``` + +## Documentation + +Refer to https://pkg.go.dev/github.com/rivo/uniseg for the package's documentation. + +## Dependencies + +This package does not depend on any packages outside the standard library. + +## Sponsor this Project + +[Become a Sponsor on GitHub](https://github.com/sponsors/rivo?metadata_source=uniseg_readme) to support this project! + +## Your Feedback + +Add your issue here on GitHub, preferably before submitting any PR's. Feel free to get in touch if you have any questions. \ No newline at end of file diff --git a/vendor/github.com/rivo/uniseg/doc.go b/vendor/github.com/rivo/uniseg/doc.go new file mode 100644 index 000000000..11224ae22 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/doc.go @@ -0,0 +1,108 @@ +/* +Package uniseg implements Unicode Text Segmentation, Unicode Line Breaking, and +string width calculation for monospace fonts. Unicode Text Segmentation conforms +to Unicode Standard Annex #29 (https://unicode.org/reports/tr29/) and Unicode +Line Breaking conforms to Unicode Standard Annex #14 +(https://unicode.org/reports/tr14/). + +In short, using this package, you can split a string into grapheme clusters +(what people would usually refer to as a "character"), into words, and into +sentences. Or, in its simplest case, this package allows you to count the number +of characters in a string, especially when it contains complex characters such +as emojis, combining characters, or characters from Asian, Arabic, Hebrew, or +other languages. Additionally, you can use it to implement line breaking (or +"word wrapping"), that is, to determine where text can be broken over to the +next line when the width of the line is not big enough to fit the entire text. +Finally, you can use it to calculate the display width of a string for monospace +fonts. + +# Getting Started + +If you just want to count the number of characters in a string, you can use +[GraphemeClusterCount]. If you want to determine the display width of a string, +you can use [StringWidth]. If you want to iterate over a string, you can use +[Step], [StepString], or the [Graphemes] class (more convenient but less +performant). This will provide you with all information: grapheme clusters, +word boundaries, sentence boundaries, line breaks, and monospace character +widths. The specialized functions [FirstGraphemeCluster], +[FirstGraphemeClusterInString], [FirstWord], [FirstWordInString], +[FirstSentence], and [FirstSentenceInString] can be used if only one type of +information is needed. + +# Grapheme Clusters + +Consider the rainbow flag emoji: 🏳️‍🌈. On most modern systems, it appears as one +character. But its string representation actually has 14 bytes, so counting +bytes (or using len("🏳️‍🌈")) will not work as expected. Counting runes won't, +either: The flag has 4 Unicode code points, thus 4 runes. The stdlib function +utf8.RuneCountInString("🏳️‍🌈") and len([]rune("🏳️‍🌈")) will both return 4. + +The [GraphemeClusterCount] function will return 1 for the rainbow flag emoji. +The Graphemes class and a variety of functions in this package will allow you to +split strings into its grapheme clusters. + +# Word Boundaries + +Word boundaries are used in a number of different contexts. The most familiar +ones are selection (double-click mouse selection), cursor movement ("move to +next word" control-arrow keys), and the dialog option "Whole Word Search" for +search and replace. This package provides methods for determining word +boundaries. + +# Sentence Boundaries + +Sentence boundaries are often used for triple-click or some other method of +selecting or iterating through blocks of text that are larger than single words. +They are also used to determine whether words occur within the same sentence in +database queries. This package provides methods for determining sentence +boundaries. + +# Line Breaking + +Line breaking, also known as word wrapping, is the process of breaking a section +of text into lines such that it will fit in the available width of a page, +window or other display area. This package provides methods to determine the +positions in a string where a line must be broken, may be broken, or must not be +broken. + +# Monospace Width + +Monospace width, as referred to in this package, is the width of a string in a +monospace font. This is commonly used in terminal user interfaces or text +displays or editors that don't support proportional fonts. A width of 1 +corresponds to a single character cell. The C function [wcswidth()] and its +implementation in other programming languages is in widespread use for the same +purpose. However, there is no standard for the calculation of such widths, and +this package differs from wcswidth() in a number of ways, presumably to generate +more visually pleasing results. + +To start, we assume that every code point has a width of 1, with the following +exceptions: + + - Code points with grapheme cluster break properties Control, CR, LF, Extend, + and ZWJ have a width of 0. + - U+2E3A, Two-Em Dash, has a width of 3. + - U+2E3B, Three-Em Dash, has a width of 4. + - Characters with the East-Asian Width properties "Fullwidth" (F) and "Wide" + (W) have a width of 2. (Properties "Ambiguous" (A) and "Neutral" (N) both + have a width of 1.) + - Code points with grapheme cluster break property Regional Indicator have a + width of 2. + - Code points with grapheme cluster break property Extended Pictographic have + a width of 2, unless their Emoji Presentation flag is "No", in which case + the width is 1. + +For Hangul grapheme clusters composed of conjoining Jamo and for Regional +Indicators (flags), all code points except the first one have a width of 0. For +grapheme clusters starting with an Extended Pictographic, any additional code +point will force a total width of 2, except if the Variation Selector-15 +(U+FE0E) is included, in which case the total width is always 1. Grapheme +clusters ending with Variation Selector-16 (U+FE0F) have a width of 2. + +Note that whether these widths appear correct depends on your application's +render engine, to which extent it conforms to the Unicode Standard, and its +choice of font. + +[wcswidth()]: https://man7.org/linux/man-pages/man3/wcswidth.3.html +*/ +package uniseg diff --git a/vendor/github.com/rivo/uniseg/eastasianwidth.go b/vendor/github.com/rivo/uniseg/eastasianwidth.go new file mode 100644 index 000000000..5fc54d991 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/eastasianwidth.go @@ -0,0 +1,2588 @@ +// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// eastAsianWidth are taken from +// https://www.unicode.org/Public/15.0.0/ucd/EastAsianWidth.txt +// and +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt +// ("Extended_Pictographic" only) +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var eastAsianWidth = [][3]int{ + {0x0000, 0x001F, prN}, // Cc [32] .. + {0x0020, 0x0020, prNa}, // Zs SPACE + {0x0021, 0x0023, prNa}, // Po [3] EXCLAMATION MARK..NUMBER SIGN + {0x0024, 0x0024, prNa}, // Sc DOLLAR SIGN + {0x0025, 0x0027, prNa}, // Po [3] PERCENT SIGN..APOSTROPHE + {0x0028, 0x0028, prNa}, // Ps LEFT PARENTHESIS + {0x0029, 0x0029, prNa}, // Pe RIGHT PARENTHESIS + {0x002A, 0x002A, prNa}, // Po ASTERISK + {0x002B, 0x002B, prNa}, // Sm PLUS SIGN + {0x002C, 0x002C, prNa}, // Po COMMA + {0x002D, 0x002D, prNa}, // Pd HYPHEN-MINUS + {0x002E, 0x002F, prNa}, // Po [2] FULL STOP..SOLIDUS + {0x0030, 0x0039, prNa}, // Nd [10] DIGIT ZERO..DIGIT NINE + {0x003A, 0x003B, prNa}, // Po [2] COLON..SEMICOLON + {0x003C, 0x003E, prNa}, // Sm [3] LESS-THAN SIGN..GREATER-THAN SIGN + {0x003F, 0x0040, prNa}, // Po [2] QUESTION MARK..COMMERCIAL AT + {0x0041, 0x005A, prNa}, // Lu [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z + {0x005B, 0x005B, prNa}, // Ps LEFT SQUARE BRACKET + {0x005C, 0x005C, prNa}, // Po REVERSE SOLIDUS + {0x005D, 0x005D, prNa}, // Pe RIGHT SQUARE BRACKET + {0x005E, 0x005E, prNa}, // Sk CIRCUMFLEX ACCENT + {0x005F, 0x005F, prNa}, // Pc LOW LINE + {0x0060, 0x0060, prNa}, // Sk GRAVE ACCENT + {0x0061, 0x007A, prNa}, // Ll [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z + {0x007B, 0x007B, prNa}, // Ps LEFT CURLY BRACKET + {0x007C, 0x007C, prNa}, // Sm VERTICAL LINE + {0x007D, 0x007D, prNa}, // Pe RIGHT CURLY BRACKET + {0x007E, 0x007E, prNa}, // Sm TILDE + {0x007F, 0x007F, prN}, // Cc + {0x0080, 0x009F, prN}, // Cc [32] .. + {0x00A0, 0x00A0, prN}, // Zs NO-BREAK SPACE + {0x00A1, 0x00A1, prA}, // Po INVERTED EXCLAMATION MARK + {0x00A2, 0x00A3, prNa}, // Sc [2] CENT SIGN..POUND SIGN + {0x00A4, 0x00A4, prA}, // Sc CURRENCY SIGN + {0x00A5, 0x00A5, prNa}, // Sc YEN SIGN + {0x00A6, 0x00A6, prNa}, // So BROKEN BAR + {0x00A7, 0x00A7, prA}, // Po SECTION SIGN + {0x00A8, 0x00A8, prA}, // Sk DIAERESIS + {0x00A9, 0x00A9, prN}, // So COPYRIGHT SIGN + {0x00AA, 0x00AA, prA}, // Lo FEMININE ORDINAL INDICATOR + {0x00AB, 0x00AB, prN}, // Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + {0x00AC, 0x00AC, prNa}, // Sm NOT SIGN + {0x00AD, 0x00AD, prA}, // Cf SOFT HYPHEN + {0x00AE, 0x00AE, prA}, // So REGISTERED SIGN + {0x00AF, 0x00AF, prNa}, // Sk MACRON + {0x00B0, 0x00B0, prA}, // So DEGREE SIGN + {0x00B1, 0x00B1, prA}, // Sm PLUS-MINUS SIGN + {0x00B2, 0x00B3, prA}, // No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE + {0x00B4, 0x00B4, prA}, // Sk ACUTE ACCENT + {0x00B5, 0x00B5, prN}, // Ll MICRO SIGN + {0x00B6, 0x00B7, prA}, // Po [2] PILCROW SIGN..MIDDLE DOT + {0x00B8, 0x00B8, prA}, // Sk CEDILLA + {0x00B9, 0x00B9, prA}, // No SUPERSCRIPT ONE + {0x00BA, 0x00BA, prA}, // Lo MASCULINE ORDINAL INDICATOR + {0x00BB, 0x00BB, prN}, // Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + {0x00BC, 0x00BE, prA}, // No [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS + {0x00BF, 0x00BF, prA}, // Po INVERTED QUESTION MARK + {0x00C0, 0x00C5, prN}, // Lu [6] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER A WITH RING ABOVE + {0x00C6, 0x00C6, prA}, // Lu LATIN CAPITAL LETTER AE + {0x00C7, 0x00CF, prN}, // Lu [9] LATIN CAPITAL LETTER C WITH CEDILLA..LATIN CAPITAL LETTER I WITH DIAERESIS + {0x00D0, 0x00D0, prA}, // Lu LATIN CAPITAL LETTER ETH + {0x00D1, 0x00D6, prN}, // Lu [6] LATIN CAPITAL LETTER N WITH TILDE..LATIN CAPITAL LETTER O WITH DIAERESIS + {0x00D7, 0x00D7, prA}, // Sm MULTIPLICATION SIGN + {0x00D8, 0x00D8, prA}, // Lu LATIN CAPITAL LETTER O WITH STROKE + {0x00D9, 0x00DD, prN}, // Lu [5] LATIN CAPITAL LETTER U WITH GRAVE..LATIN CAPITAL LETTER Y WITH ACUTE + {0x00DE, 0x00E1, prA}, // L& [4] LATIN CAPITAL LETTER THORN..LATIN SMALL LETTER A WITH ACUTE + {0x00E2, 0x00E5, prN}, // Ll [4] LATIN SMALL LETTER A WITH CIRCUMFLEX..LATIN SMALL LETTER A WITH RING ABOVE + {0x00E6, 0x00E6, prA}, // Ll LATIN SMALL LETTER AE + {0x00E7, 0x00E7, prN}, // Ll LATIN SMALL LETTER C WITH CEDILLA + {0x00E8, 0x00EA, prA}, // Ll [3] LATIN SMALL LETTER E WITH GRAVE..LATIN SMALL LETTER E WITH CIRCUMFLEX + {0x00EB, 0x00EB, prN}, // Ll LATIN SMALL LETTER E WITH DIAERESIS + {0x00EC, 0x00ED, prA}, // Ll [2] LATIN SMALL LETTER I WITH GRAVE..LATIN SMALL LETTER I WITH ACUTE + {0x00EE, 0x00EF, prN}, // Ll [2] LATIN SMALL LETTER I WITH CIRCUMFLEX..LATIN SMALL LETTER I WITH DIAERESIS + {0x00F0, 0x00F0, prA}, // Ll LATIN SMALL LETTER ETH + {0x00F1, 0x00F1, prN}, // Ll LATIN SMALL LETTER N WITH TILDE + {0x00F2, 0x00F3, prA}, // Ll [2] LATIN SMALL LETTER O WITH GRAVE..LATIN SMALL LETTER O WITH ACUTE + {0x00F4, 0x00F6, prN}, // Ll [3] LATIN SMALL LETTER O WITH CIRCUMFLEX..LATIN SMALL LETTER O WITH DIAERESIS + {0x00F7, 0x00F7, prA}, // Sm DIVISION SIGN + {0x00F8, 0x00FA, prA}, // Ll [3] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER U WITH ACUTE + {0x00FB, 0x00FB, prN}, // Ll LATIN SMALL LETTER U WITH CIRCUMFLEX + {0x00FC, 0x00FC, prA}, // Ll LATIN SMALL LETTER U WITH DIAERESIS + {0x00FD, 0x00FD, prN}, // Ll LATIN SMALL LETTER Y WITH ACUTE + {0x00FE, 0x00FE, prA}, // Ll LATIN SMALL LETTER THORN + {0x00FF, 0x00FF, prN}, // Ll LATIN SMALL LETTER Y WITH DIAERESIS + {0x0100, 0x0100, prN}, // Lu LATIN CAPITAL LETTER A WITH MACRON + {0x0101, 0x0101, prA}, // Ll LATIN SMALL LETTER A WITH MACRON + {0x0102, 0x0110, prN}, // L& [15] LATIN CAPITAL LETTER A WITH BREVE..LATIN CAPITAL LETTER D WITH STROKE + {0x0111, 0x0111, prA}, // Ll LATIN SMALL LETTER D WITH STROKE + {0x0112, 0x0112, prN}, // Lu LATIN CAPITAL LETTER E WITH MACRON + {0x0113, 0x0113, prA}, // Ll LATIN SMALL LETTER E WITH MACRON + {0x0114, 0x011A, prN}, // L& [7] LATIN CAPITAL LETTER E WITH BREVE..LATIN CAPITAL LETTER E WITH CARON + {0x011B, 0x011B, prA}, // Ll LATIN SMALL LETTER E WITH CARON + {0x011C, 0x0125, prN}, // L& [10] LATIN CAPITAL LETTER G WITH CIRCUMFLEX..LATIN SMALL LETTER H WITH CIRCUMFLEX + {0x0126, 0x0127, prA}, // L& [2] LATIN CAPITAL LETTER H WITH STROKE..LATIN SMALL LETTER H WITH STROKE + {0x0128, 0x012A, prN}, // L& [3] LATIN CAPITAL LETTER I WITH TILDE..LATIN CAPITAL LETTER I WITH MACRON + {0x012B, 0x012B, prA}, // Ll LATIN SMALL LETTER I WITH MACRON + {0x012C, 0x0130, prN}, // L& [5] LATIN CAPITAL LETTER I WITH BREVE..LATIN CAPITAL LETTER I WITH DOT ABOVE + {0x0131, 0x0133, prA}, // L& [3] LATIN SMALL LETTER DOTLESS I..LATIN SMALL LIGATURE IJ + {0x0134, 0x0137, prN}, // L& [4] LATIN CAPITAL LETTER J WITH CIRCUMFLEX..LATIN SMALL LETTER K WITH CEDILLA + {0x0138, 0x0138, prA}, // Ll LATIN SMALL LETTER KRA + {0x0139, 0x013E, prN}, // L& [6] LATIN CAPITAL LETTER L WITH ACUTE..LATIN SMALL LETTER L WITH CARON + {0x013F, 0x0142, prA}, // L& [4] LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN SMALL LETTER L WITH STROKE + {0x0143, 0x0143, prN}, // Lu LATIN CAPITAL LETTER N WITH ACUTE + {0x0144, 0x0144, prA}, // Ll LATIN SMALL LETTER N WITH ACUTE + {0x0145, 0x0147, prN}, // L& [3] LATIN CAPITAL LETTER N WITH CEDILLA..LATIN CAPITAL LETTER N WITH CARON + {0x0148, 0x014B, prA}, // L& [4] LATIN SMALL LETTER N WITH CARON..LATIN SMALL LETTER ENG + {0x014C, 0x014C, prN}, // Lu LATIN CAPITAL LETTER O WITH MACRON + {0x014D, 0x014D, prA}, // Ll LATIN SMALL LETTER O WITH MACRON + {0x014E, 0x0151, prN}, // L& [4] LATIN CAPITAL LETTER O WITH BREVE..LATIN SMALL LETTER O WITH DOUBLE ACUTE + {0x0152, 0x0153, prA}, // L& [2] LATIN CAPITAL LIGATURE OE..LATIN SMALL LIGATURE OE + {0x0154, 0x0165, prN}, // L& [18] LATIN CAPITAL LETTER R WITH ACUTE..LATIN SMALL LETTER T WITH CARON + {0x0166, 0x0167, prA}, // L& [2] LATIN CAPITAL LETTER T WITH STROKE..LATIN SMALL LETTER T WITH STROKE + {0x0168, 0x016A, prN}, // L& [3] LATIN CAPITAL LETTER U WITH TILDE..LATIN CAPITAL LETTER U WITH MACRON + {0x016B, 0x016B, prA}, // Ll LATIN SMALL LETTER U WITH MACRON + {0x016C, 0x017F, prN}, // L& [20] LATIN CAPITAL LETTER U WITH BREVE..LATIN SMALL LETTER LONG S + {0x0180, 0x01BA, prN}, // L& [59] LATIN SMALL LETTER B WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL + {0x01BB, 0x01BB, prN}, // Lo LATIN LETTER TWO WITH STROKE + {0x01BC, 0x01BF, prN}, // L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN + {0x01C0, 0x01C3, prN}, // Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK + {0x01C4, 0x01CD, prN}, // L& [10] LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER A WITH CARON + {0x01CE, 0x01CE, prA}, // Ll LATIN SMALL LETTER A WITH CARON + {0x01CF, 0x01CF, prN}, // Lu LATIN CAPITAL LETTER I WITH CARON + {0x01D0, 0x01D0, prA}, // Ll LATIN SMALL LETTER I WITH CARON + {0x01D1, 0x01D1, prN}, // Lu LATIN CAPITAL LETTER O WITH CARON + {0x01D2, 0x01D2, prA}, // Ll LATIN SMALL LETTER O WITH CARON + {0x01D3, 0x01D3, prN}, // Lu LATIN CAPITAL LETTER U WITH CARON + {0x01D4, 0x01D4, prA}, // Ll LATIN SMALL LETTER U WITH CARON + {0x01D5, 0x01D5, prN}, // Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON + {0x01D6, 0x01D6, prA}, // Ll LATIN SMALL LETTER U WITH DIAERESIS AND MACRON + {0x01D7, 0x01D7, prN}, // Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE + {0x01D8, 0x01D8, prA}, // Ll LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE + {0x01D9, 0x01D9, prN}, // Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON + {0x01DA, 0x01DA, prA}, // Ll LATIN SMALL LETTER U WITH DIAERESIS AND CARON + {0x01DB, 0x01DB, prN}, // Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE + {0x01DC, 0x01DC, prA}, // Ll LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE + {0x01DD, 0x024F, prN}, // L& [115] LATIN SMALL LETTER TURNED E..LATIN SMALL LETTER Y WITH STROKE + {0x0250, 0x0250, prN}, // Ll LATIN SMALL LETTER TURNED A + {0x0251, 0x0251, prA}, // Ll LATIN SMALL LETTER ALPHA + {0x0252, 0x0260, prN}, // Ll [15] LATIN SMALL LETTER TURNED ALPHA..LATIN SMALL LETTER G WITH HOOK + {0x0261, 0x0261, prA}, // Ll LATIN SMALL LETTER SCRIPT G + {0x0262, 0x0293, prN}, // Ll [50] LATIN LETTER SMALL CAPITAL G..LATIN SMALL LETTER EZH WITH CURL + {0x0294, 0x0294, prN}, // Lo LATIN LETTER GLOTTAL STOP + {0x0295, 0x02AF, prN}, // Ll [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL + {0x02B0, 0x02C1, prN}, // Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP + {0x02C2, 0x02C3, prN}, // Sk [2] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER RIGHT ARROWHEAD + {0x02C4, 0x02C4, prA}, // Sk MODIFIER LETTER UP ARROWHEAD + {0x02C5, 0x02C5, prN}, // Sk MODIFIER LETTER DOWN ARROWHEAD + {0x02C6, 0x02C6, prN}, // Lm MODIFIER LETTER CIRCUMFLEX ACCENT + {0x02C7, 0x02C7, prA}, // Lm CARON + {0x02C8, 0x02C8, prN}, // Lm MODIFIER LETTER VERTICAL LINE + {0x02C9, 0x02CB, prA}, // Lm [3] MODIFIER LETTER MACRON..MODIFIER LETTER GRAVE ACCENT + {0x02CC, 0x02CC, prN}, // Lm MODIFIER LETTER LOW VERTICAL LINE + {0x02CD, 0x02CD, prA}, // Lm MODIFIER LETTER LOW MACRON + {0x02CE, 0x02CF, prN}, // Lm [2] MODIFIER LETTER LOW GRAVE ACCENT..MODIFIER LETTER LOW ACUTE ACCENT + {0x02D0, 0x02D0, prA}, // Lm MODIFIER LETTER TRIANGULAR COLON + {0x02D1, 0x02D1, prN}, // Lm MODIFIER LETTER HALF TRIANGULAR COLON + {0x02D2, 0x02D7, prN}, // Sk [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN + {0x02D8, 0x02DB, prA}, // Sk [4] BREVE..OGONEK + {0x02DC, 0x02DC, prN}, // Sk SMALL TILDE + {0x02DD, 0x02DD, prA}, // Sk DOUBLE ACUTE ACCENT + {0x02DE, 0x02DE, prN}, // Sk MODIFIER LETTER RHOTIC HOOK + {0x02DF, 0x02DF, prA}, // Sk MODIFIER LETTER CROSS ACCENT + {0x02E0, 0x02E4, prN}, // Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP + {0x02E5, 0x02EB, prN}, // Sk [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK + {0x02EC, 0x02EC, prN}, // Lm MODIFIER LETTER VOICING + {0x02ED, 0x02ED, prN}, // Sk MODIFIER LETTER UNASPIRATED + {0x02EE, 0x02EE, prN}, // Lm MODIFIER LETTER DOUBLE APOSTROPHE + {0x02EF, 0x02FF, prN}, // Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW + {0x0300, 0x036F, prA}, // Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X + {0x0370, 0x0373, prN}, // L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI + {0x0374, 0x0374, prN}, // Lm GREEK NUMERAL SIGN + {0x0375, 0x0375, prN}, // Sk GREEK LOWER NUMERAL SIGN + {0x0376, 0x0377, prN}, // L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA + {0x037A, 0x037A, prN}, // Lm GREEK YPOGEGRAMMENI + {0x037B, 0x037D, prN}, // Ll [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL + {0x037E, 0x037E, prN}, // Po GREEK QUESTION MARK + {0x037F, 0x037F, prN}, // Lu GREEK CAPITAL LETTER YOT + {0x0384, 0x0385, prN}, // Sk [2] GREEK TONOS..GREEK DIALYTIKA TONOS + {0x0386, 0x0386, prN}, // Lu GREEK CAPITAL LETTER ALPHA WITH TONOS + {0x0387, 0x0387, prN}, // Po GREEK ANO TELEIA + {0x0388, 0x038A, prN}, // Lu [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS + {0x038C, 0x038C, prN}, // Lu GREEK CAPITAL LETTER OMICRON WITH TONOS + {0x038E, 0x0390, prN}, // L& [3] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + {0x0391, 0x03A1, prA}, // Lu [17] GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO + {0x03A3, 0x03A9, prA}, // Lu [7] GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER OMEGA + {0x03AA, 0x03B0, prN}, // L& [7] GREEK CAPITAL LETTER IOTA WITH DIALYTIKA..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + {0x03B1, 0x03C1, prA}, // Ll [17] GREEK SMALL LETTER ALPHA..GREEK SMALL LETTER RHO + {0x03C2, 0x03C2, prN}, // Ll GREEK SMALL LETTER FINAL SIGMA + {0x03C3, 0x03C9, prA}, // Ll [7] GREEK SMALL LETTER SIGMA..GREEK SMALL LETTER OMEGA + {0x03CA, 0x03F5, prN}, // L& [44] GREEK SMALL LETTER IOTA WITH DIALYTIKA..GREEK LUNATE EPSILON SYMBOL + {0x03F6, 0x03F6, prN}, // Sm GREEK REVERSED LUNATE EPSILON SYMBOL + {0x03F7, 0x03FF, prN}, // L& [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL + {0x0400, 0x0400, prN}, // Lu CYRILLIC CAPITAL LETTER IE WITH GRAVE + {0x0401, 0x0401, prA}, // Lu CYRILLIC CAPITAL LETTER IO + {0x0402, 0x040F, prN}, // Lu [14] CYRILLIC CAPITAL LETTER DJE..CYRILLIC CAPITAL LETTER DZHE + {0x0410, 0x044F, prA}, // L& [64] CYRILLIC CAPITAL LETTER A..CYRILLIC SMALL LETTER YA + {0x0450, 0x0450, prN}, // Ll CYRILLIC SMALL LETTER IE WITH GRAVE + {0x0451, 0x0451, prA}, // Ll CYRILLIC SMALL LETTER IO + {0x0452, 0x0481, prN}, // L& [48] CYRILLIC SMALL LETTER DJE..CYRILLIC SMALL LETTER KOPPA + {0x0482, 0x0482, prN}, // So CYRILLIC THOUSANDS SIGN + {0x0483, 0x0487, prN}, // Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE + {0x0488, 0x0489, prN}, // Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN + {0x048A, 0x04FF, prN}, // L& [118] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER HA WITH STROKE + {0x0500, 0x052F, prN}, // L& [48] CYRILLIC CAPITAL LETTER KOMI DE..CYRILLIC SMALL LETTER EL WITH DESCENDER + {0x0531, 0x0556, prN}, // Lu [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH + {0x0559, 0x0559, prN}, // Lm ARMENIAN MODIFIER LETTER LEFT HALF RING + {0x055A, 0x055F, prN}, // Po [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK + {0x0560, 0x0588, prN}, // Ll [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE + {0x0589, 0x0589, prN}, // Po ARMENIAN FULL STOP + {0x058A, 0x058A, prN}, // Pd ARMENIAN HYPHEN + {0x058D, 0x058E, prN}, // So [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN + {0x058F, 0x058F, prN}, // Sc ARMENIAN DRAM SIGN + {0x0591, 0x05BD, prN}, // Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG + {0x05BE, 0x05BE, prN}, // Pd HEBREW PUNCTUATION MAQAF + {0x05BF, 0x05BF, prN}, // Mn HEBREW POINT RAFE + {0x05C0, 0x05C0, prN}, // Po HEBREW PUNCTUATION PASEQ + {0x05C1, 0x05C2, prN}, // Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT + {0x05C3, 0x05C3, prN}, // Po HEBREW PUNCTUATION SOF PASUQ + {0x05C4, 0x05C5, prN}, // Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT + {0x05C6, 0x05C6, prN}, // Po HEBREW PUNCTUATION NUN HAFUKHA + {0x05C7, 0x05C7, prN}, // Mn HEBREW POINT QAMATS QATAN + {0x05D0, 0x05EA, prN}, // Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV + {0x05EF, 0x05F2, prN}, // Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD + {0x05F3, 0x05F4, prN}, // Po [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM + {0x0600, 0x0605, prN}, // Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE + {0x0606, 0x0608, prN}, // Sm [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY + {0x0609, 0x060A, prN}, // Po [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN + {0x060B, 0x060B, prN}, // Sc AFGHANI SIGN + {0x060C, 0x060D, prN}, // Po [2] ARABIC COMMA..ARABIC DATE SEPARATOR + {0x060E, 0x060F, prN}, // So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA + {0x0610, 0x061A, prN}, // Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA + {0x061B, 0x061B, prN}, // Po ARABIC SEMICOLON + {0x061C, 0x061C, prN}, // Cf ARABIC LETTER MARK + {0x061D, 0x061F, prN}, // Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK + {0x0620, 0x063F, prN}, // Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE + {0x0640, 0x0640, prN}, // Lm ARABIC TATWEEL + {0x0641, 0x064A, prN}, // Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH + {0x064B, 0x065F, prN}, // Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW + {0x0660, 0x0669, prN}, // Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE + {0x066A, 0x066D, prN}, // Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR + {0x066E, 0x066F, prN}, // Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF + {0x0670, 0x0670, prN}, // Mn ARABIC LETTER SUPERSCRIPT ALEF + {0x0671, 0x06D3, prN}, // Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE + {0x06D4, 0x06D4, prN}, // Po ARABIC FULL STOP + {0x06D5, 0x06D5, prN}, // Lo ARABIC LETTER AE + {0x06D6, 0x06DC, prN}, // Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN + {0x06DD, 0x06DD, prN}, // Cf ARABIC END OF AYAH + {0x06DE, 0x06DE, prN}, // So ARABIC START OF RUB EL HIZB + {0x06DF, 0x06E4, prN}, // Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA + {0x06E5, 0x06E6, prN}, // Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH + {0x06E7, 0x06E8, prN}, // Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON + {0x06E9, 0x06E9, prN}, // So ARABIC PLACE OF SAJDAH + {0x06EA, 0x06ED, prN}, // Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM + {0x06EE, 0x06EF, prN}, // Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V + {0x06F0, 0x06F9, prN}, // Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE + {0x06FA, 0x06FC, prN}, // Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW + {0x06FD, 0x06FE, prN}, // So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN + {0x06FF, 0x06FF, prN}, // Lo ARABIC LETTER HEH WITH INVERTED V + {0x0700, 0x070D, prN}, // Po [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS + {0x070F, 0x070F, prN}, // Cf SYRIAC ABBREVIATION MARK + {0x0710, 0x0710, prN}, // Lo SYRIAC LETTER ALAPH + {0x0711, 0x0711, prN}, // Mn SYRIAC LETTER SUPERSCRIPT ALAPH + {0x0712, 0x072F, prN}, // Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH + {0x0730, 0x074A, prN}, // Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH + {0x074D, 0x074F, prN}, // Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE + {0x0750, 0x077F, prN}, // Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE + {0x0780, 0x07A5, prN}, // Lo [38] THAANA LETTER HAA..THAANA LETTER WAAVU + {0x07A6, 0x07B0, prN}, // Mn [11] THAANA ABAFILI..THAANA SUKUN + {0x07B1, 0x07B1, prN}, // Lo THAANA LETTER NAA + {0x07C0, 0x07C9, prN}, // Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE + {0x07CA, 0x07EA, prN}, // Lo [33] NKO LETTER A..NKO LETTER JONA RA + {0x07EB, 0x07F3, prN}, // Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE + {0x07F4, 0x07F5, prN}, // Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE + {0x07F6, 0x07F6, prN}, // So NKO SYMBOL OO DENNEN + {0x07F7, 0x07F9, prN}, // Po [3] NKO SYMBOL GBAKURUNEN..NKO EXCLAMATION MARK + {0x07FA, 0x07FA, prN}, // Lm NKO LAJANYALAN + {0x07FD, 0x07FD, prN}, // Mn NKO DANTAYALAN + {0x07FE, 0x07FF, prN}, // Sc [2] NKO DOROME SIGN..NKO TAMAN SIGN + {0x0800, 0x0815, prN}, // Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF + {0x0816, 0x0819, prN}, // Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH + {0x081A, 0x081A, prN}, // Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT + {0x081B, 0x0823, prN}, // Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A + {0x0824, 0x0824, prN}, // Lm SAMARITAN MODIFIER LETTER SHORT A + {0x0825, 0x0827, prN}, // Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U + {0x0828, 0x0828, prN}, // Lm SAMARITAN MODIFIER LETTER I + {0x0829, 0x082D, prN}, // Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA + {0x0830, 0x083E, prN}, // Po [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU + {0x0840, 0x0858, prN}, // Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN + {0x0859, 0x085B, prN}, // Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK + {0x085E, 0x085E, prN}, // Po MANDAIC PUNCTUATION + {0x0860, 0x086A, prN}, // Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA + {0x0870, 0x0887, prN}, // Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT + {0x0888, 0x0888, prN}, // Sk ARABIC RAISED ROUND DOT + {0x0889, 0x088E, prN}, // Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL + {0x0890, 0x0891, prN}, // Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE + {0x0898, 0x089F, prN}, // Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA + {0x08A0, 0x08C8, prN}, // Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF + {0x08C9, 0x08C9, prN}, // Lm ARABIC SMALL FARSI YEH + {0x08CA, 0x08E1, prN}, // Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA + {0x08E2, 0x08E2, prN}, // Cf ARABIC DISPUTED END OF AYAH + {0x08E3, 0x08FF, prN}, // Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA + {0x0900, 0x0902, prN}, // Mn [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA + {0x0903, 0x0903, prN}, // Mc DEVANAGARI SIGN VISARGA + {0x0904, 0x0939, prN}, // Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA + {0x093A, 0x093A, prN}, // Mn DEVANAGARI VOWEL SIGN OE + {0x093B, 0x093B, prN}, // Mc DEVANAGARI VOWEL SIGN OOE + {0x093C, 0x093C, prN}, // Mn DEVANAGARI SIGN NUKTA + {0x093D, 0x093D, prN}, // Lo DEVANAGARI SIGN AVAGRAHA + {0x093E, 0x0940, prN}, // Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II + {0x0941, 0x0948, prN}, // Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI + {0x0949, 0x094C, prN}, // Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU + {0x094D, 0x094D, prN}, // Mn DEVANAGARI SIGN VIRAMA + {0x094E, 0x094F, prN}, // Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW + {0x0950, 0x0950, prN}, // Lo DEVANAGARI OM + {0x0951, 0x0957, prN}, // Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE + {0x0958, 0x0961, prN}, // Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL + {0x0962, 0x0963, prN}, // Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL + {0x0964, 0x0965, prN}, // Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA + {0x0966, 0x096F, prN}, // Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE + {0x0970, 0x0970, prN}, // Po DEVANAGARI ABBREVIATION SIGN + {0x0971, 0x0971, prN}, // Lm DEVANAGARI SIGN HIGH SPACING DOT + {0x0972, 0x097F, prN}, // Lo [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA + {0x0980, 0x0980, prN}, // Lo BENGALI ANJI + {0x0981, 0x0981, prN}, // Mn BENGALI SIGN CANDRABINDU + {0x0982, 0x0983, prN}, // Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA + {0x0985, 0x098C, prN}, // Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L + {0x098F, 0x0990, prN}, // Lo [2] BENGALI LETTER E..BENGALI LETTER AI + {0x0993, 0x09A8, prN}, // Lo [22] BENGALI LETTER O..BENGALI LETTER NA + {0x09AA, 0x09B0, prN}, // Lo [7] BENGALI LETTER PA..BENGALI LETTER RA + {0x09B2, 0x09B2, prN}, // Lo BENGALI LETTER LA + {0x09B6, 0x09B9, prN}, // Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA + {0x09BC, 0x09BC, prN}, // Mn BENGALI SIGN NUKTA + {0x09BD, 0x09BD, prN}, // Lo BENGALI SIGN AVAGRAHA + {0x09BE, 0x09C0, prN}, // Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II + {0x09C1, 0x09C4, prN}, // Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR + {0x09C7, 0x09C8, prN}, // Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI + {0x09CB, 0x09CC, prN}, // Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU + {0x09CD, 0x09CD, prN}, // Mn BENGALI SIGN VIRAMA + {0x09CE, 0x09CE, prN}, // Lo BENGALI LETTER KHANDA TA + {0x09D7, 0x09D7, prN}, // Mc BENGALI AU LENGTH MARK + {0x09DC, 0x09DD, prN}, // Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA + {0x09DF, 0x09E1, prN}, // Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL + {0x09E2, 0x09E3, prN}, // Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL + {0x09E6, 0x09EF, prN}, // Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE + {0x09F0, 0x09F1, prN}, // Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL + {0x09F2, 0x09F3, prN}, // Sc [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN + {0x09F4, 0x09F9, prN}, // No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN + {0x09FA, 0x09FA, prN}, // So BENGALI ISSHAR + {0x09FB, 0x09FB, prN}, // Sc BENGALI GANDA MARK + {0x09FC, 0x09FC, prN}, // Lo BENGALI LETTER VEDIC ANUSVARA + {0x09FD, 0x09FD, prN}, // Po BENGALI ABBREVIATION SIGN + {0x09FE, 0x09FE, prN}, // Mn BENGALI SANDHI MARK + {0x0A01, 0x0A02, prN}, // Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI + {0x0A03, 0x0A03, prN}, // Mc GURMUKHI SIGN VISARGA + {0x0A05, 0x0A0A, prN}, // Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU + {0x0A0F, 0x0A10, prN}, // Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI + {0x0A13, 0x0A28, prN}, // Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA + {0x0A2A, 0x0A30, prN}, // Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA + {0x0A32, 0x0A33, prN}, // Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA + {0x0A35, 0x0A36, prN}, // Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA + {0x0A38, 0x0A39, prN}, // Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA + {0x0A3C, 0x0A3C, prN}, // Mn GURMUKHI SIGN NUKTA + {0x0A3E, 0x0A40, prN}, // Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II + {0x0A41, 0x0A42, prN}, // Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU + {0x0A47, 0x0A48, prN}, // Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI + {0x0A4B, 0x0A4D, prN}, // Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA + {0x0A51, 0x0A51, prN}, // Mn GURMUKHI SIGN UDAAT + {0x0A59, 0x0A5C, prN}, // Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA + {0x0A5E, 0x0A5E, prN}, // Lo GURMUKHI LETTER FA + {0x0A66, 0x0A6F, prN}, // Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE + {0x0A70, 0x0A71, prN}, // Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK + {0x0A72, 0x0A74, prN}, // Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR + {0x0A75, 0x0A75, prN}, // Mn GURMUKHI SIGN YAKASH + {0x0A76, 0x0A76, prN}, // Po GURMUKHI ABBREVIATION SIGN + {0x0A81, 0x0A82, prN}, // Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA + {0x0A83, 0x0A83, prN}, // Mc GUJARATI SIGN VISARGA + {0x0A85, 0x0A8D, prN}, // Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E + {0x0A8F, 0x0A91, prN}, // Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O + {0x0A93, 0x0AA8, prN}, // Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA + {0x0AAA, 0x0AB0, prN}, // Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA + {0x0AB2, 0x0AB3, prN}, // Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA + {0x0AB5, 0x0AB9, prN}, // Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA + {0x0ABC, 0x0ABC, prN}, // Mn GUJARATI SIGN NUKTA + {0x0ABD, 0x0ABD, prN}, // Lo GUJARATI SIGN AVAGRAHA + {0x0ABE, 0x0AC0, prN}, // Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II + {0x0AC1, 0x0AC5, prN}, // Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E + {0x0AC7, 0x0AC8, prN}, // Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI + {0x0AC9, 0x0AC9, prN}, // Mc GUJARATI VOWEL SIGN CANDRA O + {0x0ACB, 0x0ACC, prN}, // Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU + {0x0ACD, 0x0ACD, prN}, // Mn GUJARATI SIGN VIRAMA + {0x0AD0, 0x0AD0, prN}, // Lo GUJARATI OM + {0x0AE0, 0x0AE1, prN}, // Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL + {0x0AE2, 0x0AE3, prN}, // Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL + {0x0AE6, 0x0AEF, prN}, // Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE + {0x0AF0, 0x0AF0, prN}, // Po GUJARATI ABBREVIATION SIGN + {0x0AF1, 0x0AF1, prN}, // Sc GUJARATI RUPEE SIGN + {0x0AF9, 0x0AF9, prN}, // Lo GUJARATI LETTER ZHA + {0x0AFA, 0x0AFF, prN}, // Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE + {0x0B01, 0x0B01, prN}, // Mn ORIYA SIGN CANDRABINDU + {0x0B02, 0x0B03, prN}, // Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA + {0x0B05, 0x0B0C, prN}, // Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L + {0x0B0F, 0x0B10, prN}, // Lo [2] ORIYA LETTER E..ORIYA LETTER AI + {0x0B13, 0x0B28, prN}, // Lo [22] ORIYA LETTER O..ORIYA LETTER NA + {0x0B2A, 0x0B30, prN}, // Lo [7] ORIYA LETTER PA..ORIYA LETTER RA + {0x0B32, 0x0B33, prN}, // Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA + {0x0B35, 0x0B39, prN}, // Lo [5] ORIYA LETTER VA..ORIYA LETTER HA + {0x0B3C, 0x0B3C, prN}, // Mn ORIYA SIGN NUKTA + {0x0B3D, 0x0B3D, prN}, // Lo ORIYA SIGN AVAGRAHA + {0x0B3E, 0x0B3E, prN}, // Mc ORIYA VOWEL SIGN AA + {0x0B3F, 0x0B3F, prN}, // Mn ORIYA VOWEL SIGN I + {0x0B40, 0x0B40, prN}, // Mc ORIYA VOWEL SIGN II + {0x0B41, 0x0B44, prN}, // Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR + {0x0B47, 0x0B48, prN}, // Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI + {0x0B4B, 0x0B4C, prN}, // Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU + {0x0B4D, 0x0B4D, prN}, // Mn ORIYA SIGN VIRAMA + {0x0B55, 0x0B56, prN}, // Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK + {0x0B57, 0x0B57, prN}, // Mc ORIYA AU LENGTH MARK + {0x0B5C, 0x0B5D, prN}, // Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA + {0x0B5F, 0x0B61, prN}, // Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL + {0x0B62, 0x0B63, prN}, // Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL + {0x0B66, 0x0B6F, prN}, // Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE + {0x0B70, 0x0B70, prN}, // So ORIYA ISSHAR + {0x0B71, 0x0B71, prN}, // Lo ORIYA LETTER WA + {0x0B72, 0x0B77, prN}, // No [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS + {0x0B82, 0x0B82, prN}, // Mn TAMIL SIGN ANUSVARA + {0x0B83, 0x0B83, prN}, // Lo TAMIL SIGN VISARGA + {0x0B85, 0x0B8A, prN}, // Lo [6] TAMIL LETTER A..TAMIL LETTER UU + {0x0B8E, 0x0B90, prN}, // Lo [3] TAMIL LETTER E..TAMIL LETTER AI + {0x0B92, 0x0B95, prN}, // Lo [4] TAMIL LETTER O..TAMIL LETTER KA + {0x0B99, 0x0B9A, prN}, // Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA + {0x0B9C, 0x0B9C, prN}, // Lo TAMIL LETTER JA + {0x0B9E, 0x0B9F, prN}, // Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA + {0x0BA3, 0x0BA4, prN}, // Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA + {0x0BA8, 0x0BAA, prN}, // Lo [3] TAMIL LETTER NA..TAMIL LETTER PA + {0x0BAE, 0x0BB9, prN}, // Lo [12] TAMIL LETTER MA..TAMIL LETTER HA + {0x0BBE, 0x0BBF, prN}, // Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I + {0x0BC0, 0x0BC0, prN}, // Mn TAMIL VOWEL SIGN II + {0x0BC1, 0x0BC2, prN}, // Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU + {0x0BC6, 0x0BC8, prN}, // Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI + {0x0BCA, 0x0BCC, prN}, // Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU + {0x0BCD, 0x0BCD, prN}, // Mn TAMIL SIGN VIRAMA + {0x0BD0, 0x0BD0, prN}, // Lo TAMIL OM + {0x0BD7, 0x0BD7, prN}, // Mc TAMIL AU LENGTH MARK + {0x0BE6, 0x0BEF, prN}, // Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE + {0x0BF0, 0x0BF2, prN}, // No [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND + {0x0BF3, 0x0BF8, prN}, // So [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN + {0x0BF9, 0x0BF9, prN}, // Sc TAMIL RUPEE SIGN + {0x0BFA, 0x0BFA, prN}, // So TAMIL NUMBER SIGN + {0x0C00, 0x0C00, prN}, // Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE + {0x0C01, 0x0C03, prN}, // Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA + {0x0C04, 0x0C04, prN}, // Mn TELUGU SIGN COMBINING ANUSVARA ABOVE + {0x0C05, 0x0C0C, prN}, // Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L + {0x0C0E, 0x0C10, prN}, // Lo [3] TELUGU LETTER E..TELUGU LETTER AI + {0x0C12, 0x0C28, prN}, // Lo [23] TELUGU LETTER O..TELUGU LETTER NA + {0x0C2A, 0x0C39, prN}, // Lo [16] TELUGU LETTER PA..TELUGU LETTER HA + {0x0C3C, 0x0C3C, prN}, // Mn TELUGU SIGN NUKTA + {0x0C3D, 0x0C3D, prN}, // Lo TELUGU SIGN AVAGRAHA + {0x0C3E, 0x0C40, prN}, // Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II + {0x0C41, 0x0C44, prN}, // Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR + {0x0C46, 0x0C48, prN}, // Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI + {0x0C4A, 0x0C4D, prN}, // Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA + {0x0C55, 0x0C56, prN}, // Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK + {0x0C58, 0x0C5A, prN}, // Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA + {0x0C5D, 0x0C5D, prN}, // Lo TELUGU LETTER NAKAARA POLLU + {0x0C60, 0x0C61, prN}, // Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL + {0x0C62, 0x0C63, prN}, // Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL + {0x0C66, 0x0C6F, prN}, // Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE + {0x0C77, 0x0C77, prN}, // Po TELUGU SIGN SIDDHAM + {0x0C78, 0x0C7E, prN}, // No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR + {0x0C7F, 0x0C7F, prN}, // So TELUGU SIGN TUUMU + {0x0C80, 0x0C80, prN}, // Lo KANNADA SIGN SPACING CANDRABINDU + {0x0C81, 0x0C81, prN}, // Mn KANNADA SIGN CANDRABINDU + {0x0C82, 0x0C83, prN}, // Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA + {0x0C84, 0x0C84, prN}, // Po KANNADA SIGN SIDDHAM + {0x0C85, 0x0C8C, prN}, // Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L + {0x0C8E, 0x0C90, prN}, // Lo [3] KANNADA LETTER E..KANNADA LETTER AI + {0x0C92, 0x0CA8, prN}, // Lo [23] KANNADA LETTER O..KANNADA LETTER NA + {0x0CAA, 0x0CB3, prN}, // Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA + {0x0CB5, 0x0CB9, prN}, // Lo [5] KANNADA LETTER VA..KANNADA LETTER HA + {0x0CBC, 0x0CBC, prN}, // Mn KANNADA SIGN NUKTA + {0x0CBD, 0x0CBD, prN}, // Lo KANNADA SIGN AVAGRAHA + {0x0CBE, 0x0CBE, prN}, // Mc KANNADA VOWEL SIGN AA + {0x0CBF, 0x0CBF, prN}, // Mn KANNADA VOWEL SIGN I + {0x0CC0, 0x0CC4, prN}, // Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR + {0x0CC6, 0x0CC6, prN}, // Mn KANNADA VOWEL SIGN E + {0x0CC7, 0x0CC8, prN}, // Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI + {0x0CCA, 0x0CCB, prN}, // Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO + {0x0CCC, 0x0CCD, prN}, // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA + {0x0CD5, 0x0CD6, prN}, // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK + {0x0CDD, 0x0CDE, prN}, // Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA + {0x0CE0, 0x0CE1, prN}, // Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL + {0x0CE2, 0x0CE3, prN}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0CE6, 0x0CEF, prN}, // Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE + {0x0CF1, 0x0CF2, prN}, // Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prN}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT + {0x0D00, 0x0D01, prN}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU + {0x0D02, 0x0D03, prN}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA + {0x0D04, 0x0D0C, prN}, // Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L + {0x0D0E, 0x0D10, prN}, // Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI + {0x0D12, 0x0D3A, prN}, // Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA + {0x0D3B, 0x0D3C, prN}, // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA + {0x0D3D, 0x0D3D, prN}, // Lo MALAYALAM SIGN AVAGRAHA + {0x0D3E, 0x0D40, prN}, // Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II + {0x0D41, 0x0D44, prN}, // Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR + {0x0D46, 0x0D48, prN}, // Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI + {0x0D4A, 0x0D4C, prN}, // Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU + {0x0D4D, 0x0D4D, prN}, // Mn MALAYALAM SIGN VIRAMA + {0x0D4E, 0x0D4E, prN}, // Lo MALAYALAM LETTER DOT REPH + {0x0D4F, 0x0D4F, prN}, // So MALAYALAM SIGN PARA + {0x0D54, 0x0D56, prN}, // Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL + {0x0D57, 0x0D57, prN}, // Mc MALAYALAM AU LENGTH MARK + {0x0D58, 0x0D5E, prN}, // No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH + {0x0D5F, 0x0D61, prN}, // Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL + {0x0D62, 0x0D63, prN}, // Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL + {0x0D66, 0x0D6F, prN}, // Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE + {0x0D70, 0x0D78, prN}, // No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS + {0x0D79, 0x0D79, prN}, // So MALAYALAM DATE MARK + {0x0D7A, 0x0D7F, prN}, // Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K + {0x0D81, 0x0D81, prN}, // Mn SINHALA SIGN CANDRABINDU + {0x0D82, 0x0D83, prN}, // Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA + {0x0D85, 0x0D96, prN}, // Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA + {0x0D9A, 0x0DB1, prN}, // Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA + {0x0DB3, 0x0DBB, prN}, // Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA + {0x0DBD, 0x0DBD, prN}, // Lo SINHALA LETTER DANTAJA LAYANNA + {0x0DC0, 0x0DC6, prN}, // Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA + {0x0DCA, 0x0DCA, prN}, // Mn SINHALA SIGN AL-LAKUNA + {0x0DCF, 0x0DD1, prN}, // Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA + {0x0DD2, 0x0DD4, prN}, // Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA + {0x0DD6, 0x0DD6, prN}, // Mn SINHALA VOWEL SIGN DIGA PAA-PILLA + {0x0DD8, 0x0DDF, prN}, // Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA + {0x0DE6, 0x0DEF, prN}, // Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE + {0x0DF2, 0x0DF3, prN}, // Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA + {0x0DF4, 0x0DF4, prN}, // Po SINHALA PUNCTUATION KUNDDALIYA + {0x0E01, 0x0E30, prN}, // Lo [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A + {0x0E31, 0x0E31, prN}, // Mn THAI CHARACTER MAI HAN-AKAT + {0x0E32, 0x0E33, prN}, // Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM + {0x0E34, 0x0E3A, prN}, // Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU + {0x0E3F, 0x0E3F, prN}, // Sc THAI CURRENCY SYMBOL BAHT + {0x0E40, 0x0E45, prN}, // Lo [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO + {0x0E46, 0x0E46, prN}, // Lm THAI CHARACTER MAIYAMOK + {0x0E47, 0x0E4E, prN}, // Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN + {0x0E4F, 0x0E4F, prN}, // Po THAI CHARACTER FONGMAN + {0x0E50, 0x0E59, prN}, // Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE + {0x0E5A, 0x0E5B, prN}, // Po [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT + {0x0E81, 0x0E82, prN}, // Lo [2] LAO LETTER KO..LAO LETTER KHO SUNG + {0x0E84, 0x0E84, prN}, // Lo LAO LETTER KHO TAM + {0x0E86, 0x0E8A, prN}, // Lo [5] LAO LETTER PALI GHA..LAO LETTER SO TAM + {0x0E8C, 0x0EA3, prN}, // Lo [24] LAO LETTER PALI JHA..LAO LETTER LO LING + {0x0EA5, 0x0EA5, prN}, // Lo LAO LETTER LO LOOT + {0x0EA7, 0x0EB0, prN}, // Lo [10] LAO LETTER WO..LAO VOWEL SIGN A + {0x0EB1, 0x0EB1, prN}, // Mn LAO VOWEL SIGN MAI KAN + {0x0EB2, 0x0EB3, prN}, // Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM + {0x0EB4, 0x0EBC, prN}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO + {0x0EBD, 0x0EBD, prN}, // Lo LAO SEMIVOWEL SIGN NYO + {0x0EC0, 0x0EC4, prN}, // Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI + {0x0EC6, 0x0EC6, prN}, // Lm LAO KO LA + {0x0EC8, 0x0ECE, prN}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN + {0x0ED0, 0x0ED9, prN}, // Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE + {0x0EDC, 0x0EDF, prN}, // Lo [4] LAO HO NO..LAO LETTER KHMU NYO + {0x0F00, 0x0F00, prN}, // Lo TIBETAN SYLLABLE OM + {0x0F01, 0x0F03, prN}, // So [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA + {0x0F04, 0x0F12, prN}, // Po [15] TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK RGYA GRAM SHAD + {0x0F13, 0x0F13, prN}, // So TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN + {0x0F14, 0x0F14, prN}, // Po TIBETAN MARK GTER TSHEG + {0x0F15, 0x0F17, prN}, // So [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS + {0x0F18, 0x0F19, prN}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS + {0x0F1A, 0x0F1F, prN}, // So [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG + {0x0F20, 0x0F29, prN}, // Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE + {0x0F2A, 0x0F33, prN}, // No [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO + {0x0F34, 0x0F34, prN}, // So TIBETAN MARK BSDUS RTAGS + {0x0F35, 0x0F35, prN}, // Mn TIBETAN MARK NGAS BZUNG NYI ZLA + {0x0F36, 0x0F36, prN}, // So TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN + {0x0F37, 0x0F37, prN}, // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS + {0x0F38, 0x0F38, prN}, // So TIBETAN MARK CHE MGO + {0x0F39, 0x0F39, prN}, // Mn TIBETAN MARK TSA -PHRU + {0x0F3A, 0x0F3A, prN}, // Ps TIBETAN MARK GUG RTAGS GYON + {0x0F3B, 0x0F3B, prN}, // Pe TIBETAN MARK GUG RTAGS GYAS + {0x0F3C, 0x0F3C, prN}, // Ps TIBETAN MARK ANG KHANG GYON + {0x0F3D, 0x0F3D, prN}, // Pe TIBETAN MARK ANG KHANG GYAS + {0x0F3E, 0x0F3F, prN}, // Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES + {0x0F40, 0x0F47, prN}, // Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA + {0x0F49, 0x0F6C, prN}, // Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA + {0x0F71, 0x0F7E, prN}, // Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO + {0x0F7F, 0x0F7F, prN}, // Mc TIBETAN SIGN RNAM BCAD + {0x0F80, 0x0F84, prN}, // Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA + {0x0F85, 0x0F85, prN}, // Po TIBETAN MARK PALUTA + {0x0F86, 0x0F87, prN}, // Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS + {0x0F88, 0x0F8C, prN}, // Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN + {0x0F8D, 0x0F97, prN}, // Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA + {0x0F99, 0x0FBC, prN}, // Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA + {0x0FBE, 0x0FC5, prN}, // So [8] TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE + {0x0FC6, 0x0FC6, prN}, // Mn TIBETAN SYMBOL PADMA GDAN + {0x0FC7, 0x0FCC, prN}, // So [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL + {0x0FCE, 0x0FCF, prN}, // So [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM + {0x0FD0, 0x0FD4, prN}, // Po [5] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA + {0x0FD5, 0x0FD8, prN}, // So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS + {0x0FD9, 0x0FDA, prN}, // Po [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS + {0x1000, 0x102A, prN}, // Lo [43] MYANMAR LETTER KA..MYANMAR LETTER AU + {0x102B, 0x102C, prN}, // Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA + {0x102D, 0x1030, prN}, // Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU + {0x1031, 0x1031, prN}, // Mc MYANMAR VOWEL SIGN E + {0x1032, 0x1037, prN}, // Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW + {0x1038, 0x1038, prN}, // Mc MYANMAR SIGN VISARGA + {0x1039, 0x103A, prN}, // Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT + {0x103B, 0x103C, prN}, // Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA + {0x103D, 0x103E, prN}, // Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA + {0x103F, 0x103F, prN}, // Lo MYANMAR LETTER GREAT SA + {0x1040, 0x1049, prN}, // Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE + {0x104A, 0x104F, prN}, // Po [6] MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE + {0x1050, 0x1055, prN}, // Lo [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL + {0x1056, 0x1057, prN}, // Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR + {0x1058, 0x1059, prN}, // Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL + {0x105A, 0x105D, prN}, // Lo [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE + {0x105E, 0x1060, prN}, // Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA + {0x1061, 0x1061, prN}, // Lo MYANMAR LETTER SGAW KAREN SHA + {0x1062, 0x1064, prN}, // Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO + {0x1065, 0x1066, prN}, // Lo [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA + {0x1067, 0x106D, prN}, // Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 + {0x106E, 0x1070, prN}, // Lo [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA + {0x1071, 0x1074, prN}, // Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE + {0x1075, 0x1081, prN}, // Lo [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA + {0x1082, 0x1082, prN}, // Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA + {0x1083, 0x1084, prN}, // Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E + {0x1085, 0x1086, prN}, // Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y + {0x1087, 0x108C, prN}, // Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 + {0x108D, 0x108D, prN}, // Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE + {0x108E, 0x108E, prN}, // Lo MYANMAR LETTER RUMAI PALAUNG FA + {0x108F, 0x108F, prN}, // Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 + {0x1090, 0x1099, prN}, // Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE + {0x109A, 0x109C, prN}, // Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A + {0x109D, 0x109D, prN}, // Mn MYANMAR VOWEL SIGN AITON AI + {0x109E, 0x109F, prN}, // So [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION + {0x10A0, 0x10C5, prN}, // Lu [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE + {0x10C7, 0x10C7, prN}, // Lu GEORGIAN CAPITAL LETTER YN + {0x10CD, 0x10CD, prN}, // Lu GEORGIAN CAPITAL LETTER AEN + {0x10D0, 0x10FA, prN}, // Ll [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN + {0x10FB, 0x10FB, prN}, // Po GEORGIAN PARAGRAPH SEPARATOR + {0x10FC, 0x10FC, prN}, // Lm MODIFIER LETTER GEORGIAN NAR + {0x10FD, 0x10FF, prN}, // Ll [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN + {0x1100, 0x115F, prW}, // Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER + {0x1160, 0x11FF, prN}, // Lo [160] HANGUL JUNGSEONG FILLER..HANGUL JONGSEONG SSANGNIEUN + {0x1200, 0x1248, prN}, // Lo [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA + {0x124A, 0x124D, prN}, // Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE + {0x1250, 0x1256, prN}, // Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO + {0x1258, 0x1258, prN}, // Lo ETHIOPIC SYLLABLE QHWA + {0x125A, 0x125D, prN}, // Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE + {0x1260, 0x1288, prN}, // Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA + {0x128A, 0x128D, prN}, // Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE + {0x1290, 0x12B0, prN}, // Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA + {0x12B2, 0x12B5, prN}, // Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE + {0x12B8, 0x12BE, prN}, // Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO + {0x12C0, 0x12C0, prN}, // Lo ETHIOPIC SYLLABLE KXWA + {0x12C2, 0x12C5, prN}, // Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE + {0x12C8, 0x12D6, prN}, // Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O + {0x12D8, 0x1310, prN}, // Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA + {0x1312, 0x1315, prN}, // Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE + {0x1318, 0x135A, prN}, // Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA + {0x135D, 0x135F, prN}, // Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK + {0x1360, 0x1368, prN}, // Po [9] ETHIOPIC SECTION MARK..ETHIOPIC PARAGRAPH SEPARATOR + {0x1369, 0x137C, prN}, // No [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND + {0x1380, 0x138F, prN}, // Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE + {0x1390, 0x1399, prN}, // So [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT + {0x13A0, 0x13F5, prN}, // Lu [86] CHEROKEE LETTER A..CHEROKEE LETTER MV + {0x13F8, 0x13FD, prN}, // Ll [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV + {0x1400, 0x1400, prN}, // Pd CANADIAN SYLLABICS HYPHEN + {0x1401, 0x166C, prN}, // Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA + {0x166D, 0x166D, prN}, // So CANADIAN SYLLABICS CHI SIGN + {0x166E, 0x166E, prN}, // Po CANADIAN SYLLABICS FULL STOP + {0x166F, 0x167F, prN}, // Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W + {0x1680, 0x1680, prN}, // Zs OGHAM SPACE MARK + {0x1681, 0x169A, prN}, // Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH + {0x169B, 0x169B, prN}, // Ps OGHAM FEATHER MARK + {0x169C, 0x169C, prN}, // Pe OGHAM REVERSED FEATHER MARK + {0x16A0, 0x16EA, prN}, // Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X + {0x16EB, 0x16ED, prN}, // Po [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION + {0x16EE, 0x16F0, prN}, // Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL + {0x16F1, 0x16F8, prN}, // Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC + {0x1700, 0x1711, prN}, // Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA + {0x1712, 0x1714, prN}, // Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + {0x1715, 0x1715, prN}, // Mc TAGALOG SIGN PAMUDPOD + {0x171F, 0x171F, prN}, // Lo TAGALOG LETTER ARCHAIC RA + {0x1720, 0x1731, prN}, // Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA + {0x1732, 0x1733, prN}, // Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U + {0x1734, 0x1734, prN}, // Mc HANUNOO SIGN PAMUDPOD + {0x1735, 0x1736, prN}, // Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION + {0x1740, 0x1751, prN}, // Lo [18] BUHID LETTER A..BUHID LETTER HA + {0x1752, 0x1753, prN}, // Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + {0x1760, 0x176C, prN}, // Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA + {0x176E, 0x1770, prN}, // Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA + {0x1772, 0x1773, prN}, // Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + {0x1780, 0x17B3, prN}, // Lo [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU + {0x17B4, 0x17B5, prN}, // Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA + {0x17B6, 0x17B6, prN}, // Mc KHMER VOWEL SIGN AA + {0x17B7, 0x17BD, prN}, // Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA + {0x17BE, 0x17C5, prN}, // Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU + {0x17C6, 0x17C6, prN}, // Mn KHMER SIGN NIKAHIT + {0x17C7, 0x17C8, prN}, // Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU + {0x17C9, 0x17D3, prN}, // Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT + {0x17D4, 0x17D6, prN}, // Po [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH + {0x17D7, 0x17D7, prN}, // Lm KHMER SIGN LEK TOO + {0x17D8, 0x17DA, prN}, // Po [3] KHMER SIGN BEYYAL..KHMER SIGN KOOMUUT + {0x17DB, 0x17DB, prN}, // Sc KHMER CURRENCY SYMBOL RIEL + {0x17DC, 0x17DC, prN}, // Lo KHMER SIGN AVAKRAHASANYA + {0x17DD, 0x17DD, prN}, // Mn KHMER SIGN ATTHACAN + {0x17E0, 0x17E9, prN}, // Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE + {0x17F0, 0x17F9, prN}, // No [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON + {0x1800, 0x1805, prN}, // Po [6] MONGOLIAN BIRGA..MONGOLIAN FOUR DOTS + {0x1806, 0x1806, prN}, // Pd MONGOLIAN TODO SOFT HYPHEN + {0x1807, 0x180A, prN}, // Po [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU + {0x180B, 0x180D, prN}, // Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE + {0x180E, 0x180E, prN}, // Cf MONGOLIAN VOWEL SEPARATOR + {0x180F, 0x180F, prN}, // Mn MONGOLIAN FREE VARIATION SELECTOR FOUR + {0x1810, 0x1819, prN}, // Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE + {0x1820, 0x1842, prN}, // Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI + {0x1843, 0x1843, prN}, // Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN + {0x1844, 0x1878, prN}, // Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS + {0x1880, 0x1884, prN}, // Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA + {0x1885, 0x1886, prN}, // Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA + {0x1887, 0x18A8, prN}, // Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA + {0x18A9, 0x18A9, prN}, // Mn MONGOLIAN LETTER ALI GALI DAGALGA + {0x18AA, 0x18AA, prN}, // Lo MONGOLIAN LETTER MANCHU ALI GALI LHA + {0x18B0, 0x18F5, prN}, // Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S + {0x1900, 0x191E, prN}, // Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA + {0x1920, 0x1922, prN}, // Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U + {0x1923, 0x1926, prN}, // Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU + {0x1927, 0x1928, prN}, // Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O + {0x1929, 0x192B, prN}, // Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA + {0x1930, 0x1931, prN}, // Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA + {0x1932, 0x1932, prN}, // Mn LIMBU SMALL LETTER ANUSVARA + {0x1933, 0x1938, prN}, // Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA + {0x1939, 0x193B, prN}, // Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I + {0x1940, 0x1940, prN}, // So LIMBU SIGN LOO + {0x1944, 0x1945, prN}, // Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK + {0x1946, 0x194F, prN}, // Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE + {0x1950, 0x196D, prN}, // Lo [30] TAI LE LETTER KA..TAI LE LETTER AI + {0x1970, 0x1974, prN}, // Lo [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6 + {0x1980, 0x19AB, prN}, // Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA + {0x19B0, 0x19C9, prN}, // Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2 + {0x19D0, 0x19D9, prN}, // Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE + {0x19DA, 0x19DA, prN}, // No NEW TAI LUE THAM DIGIT ONE + {0x19DE, 0x19DF, prN}, // So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV + {0x19E0, 0x19FF, prN}, // So [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC + {0x1A00, 0x1A16, prN}, // Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA + {0x1A17, 0x1A18, prN}, // Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U + {0x1A19, 0x1A1A, prN}, // Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O + {0x1A1B, 0x1A1B, prN}, // Mn BUGINESE VOWEL SIGN AE + {0x1A1E, 0x1A1F, prN}, // Po [2] BUGINESE PALLAWA..BUGINESE END OF SECTION + {0x1A20, 0x1A54, prN}, // Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA + {0x1A55, 0x1A55, prN}, // Mc TAI THAM CONSONANT SIGN MEDIAL RA + {0x1A56, 0x1A56, prN}, // Mn TAI THAM CONSONANT SIGN MEDIAL LA + {0x1A57, 0x1A57, prN}, // Mc TAI THAM CONSONANT SIGN LA TANG LAI + {0x1A58, 0x1A5E, prN}, // Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA + {0x1A60, 0x1A60, prN}, // Mn TAI THAM SIGN SAKOT + {0x1A61, 0x1A61, prN}, // Mc TAI THAM VOWEL SIGN A + {0x1A62, 0x1A62, prN}, // Mn TAI THAM VOWEL SIGN MAI SAT + {0x1A63, 0x1A64, prN}, // Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA + {0x1A65, 0x1A6C, prN}, // Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW + {0x1A6D, 0x1A72, prN}, // Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI + {0x1A73, 0x1A7C, prN}, // Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN + {0x1A7F, 0x1A7F, prN}, // Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT + {0x1A80, 0x1A89, prN}, // Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE + {0x1A90, 0x1A99, prN}, // Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE + {0x1AA0, 0x1AA6, prN}, // Po [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA + {0x1AA7, 0x1AA7, prN}, // Lm TAI THAM SIGN MAI YAMOK + {0x1AA8, 0x1AAD, prN}, // Po [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG + {0x1AB0, 0x1ABD, prN}, // Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW + {0x1ABE, 0x1ABE, prN}, // Me COMBINING PARENTHESES OVERLAY + {0x1ABF, 0x1ACE, prN}, // Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T + {0x1B00, 0x1B03, prN}, // Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG + {0x1B04, 0x1B04, prN}, // Mc BALINESE SIGN BISAH + {0x1B05, 0x1B33, prN}, // Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA + {0x1B34, 0x1B34, prN}, // Mn BALINESE SIGN REREKAN + {0x1B35, 0x1B35, prN}, // Mc BALINESE VOWEL SIGN TEDUNG + {0x1B36, 0x1B3A, prN}, // Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA + {0x1B3B, 0x1B3B, prN}, // Mc BALINESE VOWEL SIGN RA REPA TEDUNG + {0x1B3C, 0x1B3C, prN}, // Mn BALINESE VOWEL SIGN LA LENGA + {0x1B3D, 0x1B41, prN}, // Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG + {0x1B42, 0x1B42, prN}, // Mn BALINESE VOWEL SIGN PEPET + {0x1B43, 0x1B44, prN}, // Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG + {0x1B45, 0x1B4C, prN}, // Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA + {0x1B50, 0x1B59, prN}, // Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE + {0x1B5A, 0x1B60, prN}, // Po [7] BALINESE PANTI..BALINESE PAMENENG + {0x1B61, 0x1B6A, prN}, // So [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE + {0x1B6B, 0x1B73, prN}, // Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG + {0x1B74, 0x1B7C, prN}, // So [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING + {0x1B7D, 0x1B7E, prN}, // Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG + {0x1B80, 0x1B81, prN}, // Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR + {0x1B82, 0x1B82, prN}, // Mc SUNDANESE SIGN PANGWISAD + {0x1B83, 0x1BA0, prN}, // Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA + {0x1BA1, 0x1BA1, prN}, // Mc SUNDANESE CONSONANT SIGN PAMINGKAL + {0x1BA2, 0x1BA5, prN}, // Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU + {0x1BA6, 0x1BA7, prN}, // Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG + {0x1BA8, 0x1BA9, prN}, // Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG + {0x1BAA, 0x1BAA, prN}, // Mc SUNDANESE SIGN PAMAAEH + {0x1BAB, 0x1BAD, prN}, // Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA + {0x1BAE, 0x1BAF, prN}, // Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA + {0x1BB0, 0x1BB9, prN}, // Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE + {0x1BBA, 0x1BBF, prN}, // Lo [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M + {0x1BC0, 0x1BE5, prN}, // Lo [38] BATAK LETTER A..BATAK LETTER U + {0x1BE6, 0x1BE6, prN}, // Mn BATAK SIGN TOMPI + {0x1BE7, 0x1BE7, prN}, // Mc BATAK VOWEL SIGN E + {0x1BE8, 0x1BE9, prN}, // Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE + {0x1BEA, 0x1BEC, prN}, // Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O + {0x1BED, 0x1BED, prN}, // Mn BATAK VOWEL SIGN KARO O + {0x1BEE, 0x1BEE, prN}, // Mc BATAK VOWEL SIGN U + {0x1BEF, 0x1BF1, prN}, // Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H + {0x1BF2, 0x1BF3, prN}, // Mc [2] BATAK PANGOLAT..BATAK PANONGONAN + {0x1BFC, 0x1BFF, prN}, // Po [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT + {0x1C00, 0x1C23, prN}, // Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A + {0x1C24, 0x1C2B, prN}, // Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU + {0x1C2C, 0x1C33, prN}, // Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T + {0x1C34, 0x1C35, prN}, // Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG + {0x1C36, 0x1C37, prN}, // Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA + {0x1C3B, 0x1C3F, prN}, // Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK + {0x1C40, 0x1C49, prN}, // Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE + {0x1C4D, 0x1C4F, prN}, // Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA + {0x1C50, 0x1C59, prN}, // Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE + {0x1C5A, 0x1C77, prN}, // Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH + {0x1C78, 0x1C7D, prN}, // Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD + {0x1C7E, 0x1C7F, prN}, // Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD + {0x1C80, 0x1C88, prN}, // Ll [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK + {0x1C90, 0x1CBA, prN}, // Lu [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN + {0x1CBD, 0x1CBF, prN}, // Lu [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN + {0x1CC0, 0x1CC7, prN}, // Po [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA + {0x1CD0, 0x1CD2, prN}, // Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA + {0x1CD3, 0x1CD3, prN}, // Po VEDIC SIGN NIHSHVASA + {0x1CD4, 0x1CE0, prN}, // Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA + {0x1CE1, 0x1CE1, prN}, // Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA + {0x1CE2, 0x1CE8, prN}, // Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL + {0x1CE9, 0x1CEC, prN}, // Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL + {0x1CED, 0x1CED, prN}, // Mn VEDIC SIGN TIRYAK + {0x1CEE, 0x1CF3, prN}, // Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA + {0x1CF4, 0x1CF4, prN}, // Mn VEDIC TONE CANDRA ABOVE + {0x1CF5, 0x1CF6, prN}, // Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA + {0x1CF7, 0x1CF7, prN}, // Mc VEDIC SIGN ATIKRAMA + {0x1CF8, 0x1CF9, prN}, // Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE + {0x1CFA, 0x1CFA, prN}, // Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA + {0x1D00, 0x1D2B, prN}, // Ll [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL + {0x1D2C, 0x1D6A, prN}, // Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI + {0x1D6B, 0x1D77, prN}, // Ll [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G + {0x1D78, 0x1D78, prN}, // Lm MODIFIER LETTER CYRILLIC EN + {0x1D79, 0x1D7F, prN}, // Ll [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE + {0x1D80, 0x1D9A, prN}, // Ll [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK + {0x1D9B, 0x1DBF, prN}, // Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA + {0x1DC0, 0x1DFF, prN}, // Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x1E00, 0x1EFF, prN}, // L& [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP + {0x1F00, 0x1F15, prN}, // L& [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA + {0x1F18, 0x1F1D, prN}, // Lu [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA + {0x1F20, 0x1F45, prN}, // L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA + {0x1F48, 0x1F4D, prN}, // Lu [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA + {0x1F50, 0x1F57, prN}, // Ll [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI + {0x1F59, 0x1F59, prN}, // Lu GREEK CAPITAL LETTER UPSILON WITH DASIA + {0x1F5B, 0x1F5B, prN}, // Lu GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA + {0x1F5D, 0x1F5D, prN}, // Lu GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA + {0x1F5F, 0x1F7D, prN}, // L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA + {0x1F80, 0x1FB4, prN}, // L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI + {0x1FB6, 0x1FBC, prN}, // L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI + {0x1FBD, 0x1FBD, prN}, // Sk GREEK KORONIS + {0x1FBE, 0x1FBE, prN}, // Ll GREEK PROSGEGRAMMENI + {0x1FBF, 0x1FC1, prN}, // Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI + {0x1FC2, 0x1FC4, prN}, // Ll [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI + {0x1FC6, 0x1FCC, prN}, // L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI + {0x1FCD, 0x1FCF, prN}, // Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI + {0x1FD0, 0x1FD3, prN}, // Ll [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA + {0x1FD6, 0x1FDB, prN}, // L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA + {0x1FDD, 0x1FDF, prN}, // Sk [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI + {0x1FE0, 0x1FEC, prN}, // L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA + {0x1FED, 0x1FEF, prN}, // Sk [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA + {0x1FF2, 0x1FF4, prN}, // Ll [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + {0x1FF6, 0x1FFC, prN}, // L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + {0x1FFD, 0x1FFE, prN}, // Sk [2] GREEK OXIA..GREEK DASIA + {0x2000, 0x200A, prN}, // Zs [11] EN QUAD..HAIR SPACE + {0x200B, 0x200F, prN}, // Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK + {0x2010, 0x2010, prA}, // Pd HYPHEN + {0x2011, 0x2012, prN}, // Pd [2] NON-BREAKING HYPHEN..FIGURE DASH + {0x2013, 0x2015, prA}, // Pd [3] EN DASH..HORIZONTAL BAR + {0x2016, 0x2016, prA}, // Po DOUBLE VERTICAL LINE + {0x2017, 0x2017, prN}, // Po DOUBLE LOW LINE + {0x2018, 0x2018, prA}, // Pi LEFT SINGLE QUOTATION MARK + {0x2019, 0x2019, prA}, // Pf RIGHT SINGLE QUOTATION MARK + {0x201A, 0x201A, prN}, // Ps SINGLE LOW-9 QUOTATION MARK + {0x201B, 0x201B, prN}, // Pi SINGLE HIGH-REVERSED-9 QUOTATION MARK + {0x201C, 0x201C, prA}, // Pi LEFT DOUBLE QUOTATION MARK + {0x201D, 0x201D, prA}, // Pf RIGHT DOUBLE QUOTATION MARK + {0x201E, 0x201E, prN}, // Ps DOUBLE LOW-9 QUOTATION MARK + {0x201F, 0x201F, prN}, // Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK + {0x2020, 0x2022, prA}, // Po [3] DAGGER..BULLET + {0x2023, 0x2023, prN}, // Po TRIANGULAR BULLET + {0x2024, 0x2027, prA}, // Po [4] ONE DOT LEADER..HYPHENATION POINT + {0x2028, 0x2028, prN}, // Zl LINE SEPARATOR + {0x2029, 0x2029, prN}, // Zp PARAGRAPH SEPARATOR + {0x202A, 0x202E, prN}, // Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE + {0x202F, 0x202F, prN}, // Zs NARROW NO-BREAK SPACE + {0x2030, 0x2030, prA}, // Po PER MILLE SIGN + {0x2031, 0x2031, prN}, // Po PER TEN THOUSAND SIGN + {0x2032, 0x2033, prA}, // Po [2] PRIME..DOUBLE PRIME + {0x2034, 0x2034, prN}, // Po TRIPLE PRIME + {0x2035, 0x2035, prA}, // Po REVERSED PRIME + {0x2036, 0x2038, prN}, // Po [3] REVERSED DOUBLE PRIME..CARET + {0x2039, 0x2039, prN}, // Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK + {0x203A, 0x203A, prN}, // Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + {0x203B, 0x203B, prA}, // Po REFERENCE MARK + {0x203C, 0x203D, prN}, // Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG + {0x203E, 0x203E, prA}, // Po OVERLINE + {0x203F, 0x2040, prN}, // Pc [2] UNDERTIE..CHARACTER TIE + {0x2041, 0x2043, prN}, // Po [3] CARET INSERTION POINT..HYPHEN BULLET + {0x2044, 0x2044, prN}, // Sm FRACTION SLASH + {0x2045, 0x2045, prN}, // Ps LEFT SQUARE BRACKET WITH QUILL + {0x2046, 0x2046, prN}, // Pe RIGHT SQUARE BRACKET WITH QUILL + {0x2047, 0x2051, prN}, // Po [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY + {0x2052, 0x2052, prN}, // Sm COMMERCIAL MINUS SIGN + {0x2053, 0x2053, prN}, // Po SWUNG DASH + {0x2054, 0x2054, prN}, // Pc INVERTED UNDERTIE + {0x2055, 0x205E, prN}, // Po [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS + {0x205F, 0x205F, prN}, // Zs MEDIUM MATHEMATICAL SPACE + {0x2060, 0x2064, prN}, // Cf [5] WORD JOINER..INVISIBLE PLUS + {0x2066, 0x206F, prN}, // Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES + {0x2070, 0x2070, prN}, // No SUPERSCRIPT ZERO + {0x2071, 0x2071, prN}, // Lm SUPERSCRIPT LATIN SMALL LETTER I + {0x2074, 0x2074, prA}, // No SUPERSCRIPT FOUR + {0x2075, 0x2079, prN}, // No [5] SUPERSCRIPT FIVE..SUPERSCRIPT NINE + {0x207A, 0x207C, prN}, // Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN + {0x207D, 0x207D, prN}, // Ps SUPERSCRIPT LEFT PARENTHESIS + {0x207E, 0x207E, prN}, // Pe SUPERSCRIPT RIGHT PARENTHESIS + {0x207F, 0x207F, prA}, // Lm SUPERSCRIPT LATIN SMALL LETTER N + {0x2080, 0x2080, prN}, // No SUBSCRIPT ZERO + {0x2081, 0x2084, prA}, // No [4] SUBSCRIPT ONE..SUBSCRIPT FOUR + {0x2085, 0x2089, prN}, // No [5] SUBSCRIPT FIVE..SUBSCRIPT NINE + {0x208A, 0x208C, prN}, // Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN + {0x208D, 0x208D, prN}, // Ps SUBSCRIPT LEFT PARENTHESIS + {0x208E, 0x208E, prN}, // Pe SUBSCRIPT RIGHT PARENTHESIS + {0x2090, 0x209C, prN}, // Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T + {0x20A0, 0x20A8, prN}, // Sc [9] EURO-CURRENCY SIGN..RUPEE SIGN + {0x20A9, 0x20A9, prH}, // Sc WON SIGN + {0x20AA, 0x20AB, prN}, // Sc [2] NEW SHEQEL SIGN..DONG SIGN + {0x20AC, 0x20AC, prA}, // Sc EURO SIGN + {0x20AD, 0x20C0, prN}, // Sc [20] KIP SIGN..SOM SIGN + {0x20D0, 0x20DC, prN}, // Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE + {0x20DD, 0x20E0, prN}, // Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH + {0x20E1, 0x20E1, prN}, // Mn COMBINING LEFT RIGHT ARROW ABOVE + {0x20E2, 0x20E4, prN}, // Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE + {0x20E5, 0x20F0, prN}, // Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE + {0x2100, 0x2101, prN}, // So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT + {0x2102, 0x2102, prN}, // Lu DOUBLE-STRUCK CAPITAL C + {0x2103, 0x2103, prA}, // So DEGREE CELSIUS + {0x2104, 0x2104, prN}, // So CENTRE LINE SYMBOL + {0x2105, 0x2105, prA}, // So CARE OF + {0x2106, 0x2106, prN}, // So CADA UNA + {0x2107, 0x2107, prN}, // Lu EULER CONSTANT + {0x2108, 0x2108, prN}, // So SCRUPLE + {0x2109, 0x2109, prA}, // So DEGREE FAHRENHEIT + {0x210A, 0x2112, prN}, // L& [9] SCRIPT SMALL G..SCRIPT CAPITAL L + {0x2113, 0x2113, prA}, // Ll SCRIPT SMALL L + {0x2114, 0x2114, prN}, // So L B BAR SYMBOL + {0x2115, 0x2115, prN}, // Lu DOUBLE-STRUCK CAPITAL N + {0x2116, 0x2116, prA}, // So NUMERO SIGN + {0x2117, 0x2117, prN}, // So SOUND RECORDING COPYRIGHT + {0x2118, 0x2118, prN}, // Sm SCRIPT CAPITAL P + {0x2119, 0x211D, prN}, // Lu [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R + {0x211E, 0x2120, prN}, // So [3] PRESCRIPTION TAKE..SERVICE MARK + {0x2121, 0x2122, prA}, // So [2] TELEPHONE SIGN..TRADE MARK SIGN + {0x2123, 0x2123, prN}, // So VERSICLE + {0x2124, 0x2124, prN}, // Lu DOUBLE-STRUCK CAPITAL Z + {0x2125, 0x2125, prN}, // So OUNCE SIGN + {0x2126, 0x2126, prA}, // Lu OHM SIGN + {0x2127, 0x2127, prN}, // So INVERTED OHM SIGN + {0x2128, 0x2128, prN}, // Lu BLACK-LETTER CAPITAL Z + {0x2129, 0x2129, prN}, // So TURNED GREEK SMALL LETTER IOTA + {0x212A, 0x212A, prN}, // Lu KELVIN SIGN + {0x212B, 0x212B, prA}, // Lu ANGSTROM SIGN + {0x212C, 0x212D, prN}, // Lu [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C + {0x212E, 0x212E, prN}, // So ESTIMATED SYMBOL + {0x212F, 0x2134, prN}, // L& [6] SCRIPT SMALL E..SCRIPT SMALL O + {0x2135, 0x2138, prN}, // Lo [4] ALEF SYMBOL..DALET SYMBOL + {0x2139, 0x2139, prN}, // Ll INFORMATION SOURCE + {0x213A, 0x213B, prN}, // So [2] ROTATED CAPITAL Q..FACSIMILE SIGN + {0x213C, 0x213F, prN}, // L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI + {0x2140, 0x2144, prN}, // Sm [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y + {0x2145, 0x2149, prN}, // L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J + {0x214A, 0x214A, prN}, // So PROPERTY LINE + {0x214B, 0x214B, prN}, // Sm TURNED AMPERSAND + {0x214C, 0x214D, prN}, // So [2] PER SIGN..AKTIESELSKAB + {0x214E, 0x214E, prN}, // Ll TURNED SMALL F + {0x214F, 0x214F, prN}, // So SYMBOL FOR SAMARITAN SOURCE + {0x2150, 0x2152, prN}, // No [3] VULGAR FRACTION ONE SEVENTH..VULGAR FRACTION ONE TENTH + {0x2153, 0x2154, prA}, // No [2] VULGAR FRACTION ONE THIRD..VULGAR FRACTION TWO THIRDS + {0x2155, 0x215A, prN}, // No [6] VULGAR FRACTION ONE FIFTH..VULGAR FRACTION FIVE SIXTHS + {0x215B, 0x215E, prA}, // No [4] VULGAR FRACTION ONE EIGHTH..VULGAR FRACTION SEVEN EIGHTHS + {0x215F, 0x215F, prN}, // No FRACTION NUMERATOR ONE + {0x2160, 0x216B, prA}, // Nl [12] ROMAN NUMERAL ONE..ROMAN NUMERAL TWELVE + {0x216C, 0x216F, prN}, // Nl [4] ROMAN NUMERAL FIFTY..ROMAN NUMERAL ONE THOUSAND + {0x2170, 0x2179, prA}, // Nl [10] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL TEN + {0x217A, 0x2182, prN}, // Nl [9] SMALL ROMAN NUMERAL ELEVEN..ROMAN NUMERAL TEN THOUSAND + {0x2183, 0x2184, prN}, // L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C + {0x2185, 0x2188, prN}, // Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND + {0x2189, 0x2189, prA}, // No VULGAR FRACTION ZERO THIRDS + {0x218A, 0x218B, prN}, // So [2] TURNED DIGIT TWO..TURNED DIGIT THREE + {0x2190, 0x2194, prA}, // Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW + {0x2195, 0x2199, prA}, // So [5] UP DOWN ARROW..SOUTH WEST ARROW + {0x219A, 0x219B, prN}, // Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE + {0x219C, 0x219F, prN}, // So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW + {0x21A0, 0x21A0, prN}, // Sm RIGHTWARDS TWO HEADED ARROW + {0x21A1, 0x21A2, prN}, // So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL + {0x21A3, 0x21A3, prN}, // Sm RIGHTWARDS ARROW WITH TAIL + {0x21A4, 0x21A5, prN}, // So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR + {0x21A6, 0x21A6, prN}, // Sm RIGHTWARDS ARROW FROM BAR + {0x21A7, 0x21AD, prN}, // So [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW + {0x21AE, 0x21AE, prN}, // Sm LEFT RIGHT ARROW WITH STROKE + {0x21AF, 0x21B7, prN}, // So [9] DOWNWARDS ZIGZAG ARROW..CLOCKWISE TOP SEMICIRCLE ARROW + {0x21B8, 0x21B9, prA}, // So [2] NORTH WEST ARROW TO LONG BAR..LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR + {0x21BA, 0x21CD, prN}, // So [20] ANTICLOCKWISE OPEN CIRCLE ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE + {0x21CE, 0x21CF, prN}, // Sm [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE + {0x21D0, 0x21D1, prN}, // So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW + {0x21D2, 0x21D2, prA}, // Sm RIGHTWARDS DOUBLE ARROW + {0x21D3, 0x21D3, prN}, // So DOWNWARDS DOUBLE ARROW + {0x21D4, 0x21D4, prA}, // Sm LEFT RIGHT DOUBLE ARROW + {0x21D5, 0x21E6, prN}, // So [18] UP DOWN DOUBLE ARROW..LEFTWARDS WHITE ARROW + {0x21E7, 0x21E7, prA}, // So UPWARDS WHITE ARROW + {0x21E8, 0x21F3, prN}, // So [12] RIGHTWARDS WHITE ARROW..UP DOWN WHITE ARROW + {0x21F4, 0x21FF, prN}, // Sm [12] RIGHT ARROW WITH SMALL CIRCLE..LEFT RIGHT OPEN-HEADED ARROW + {0x2200, 0x2200, prA}, // Sm FOR ALL + {0x2201, 0x2201, prN}, // Sm COMPLEMENT + {0x2202, 0x2203, prA}, // Sm [2] PARTIAL DIFFERENTIAL..THERE EXISTS + {0x2204, 0x2206, prN}, // Sm [3] THERE DOES NOT EXIST..INCREMENT + {0x2207, 0x2208, prA}, // Sm [2] NABLA..ELEMENT OF + {0x2209, 0x220A, prN}, // Sm [2] NOT AN ELEMENT OF..SMALL ELEMENT OF + {0x220B, 0x220B, prA}, // Sm CONTAINS AS MEMBER + {0x220C, 0x220E, prN}, // Sm [3] DOES NOT CONTAIN AS MEMBER..END OF PROOF + {0x220F, 0x220F, prA}, // Sm N-ARY PRODUCT + {0x2210, 0x2210, prN}, // Sm N-ARY COPRODUCT + {0x2211, 0x2211, prA}, // Sm N-ARY SUMMATION + {0x2212, 0x2214, prN}, // Sm [3] MINUS SIGN..DOT PLUS + {0x2215, 0x2215, prA}, // Sm DIVISION SLASH + {0x2216, 0x2219, prN}, // Sm [4] SET MINUS..BULLET OPERATOR + {0x221A, 0x221A, prA}, // Sm SQUARE ROOT + {0x221B, 0x221C, prN}, // Sm [2] CUBE ROOT..FOURTH ROOT + {0x221D, 0x2220, prA}, // Sm [4] PROPORTIONAL TO..ANGLE + {0x2221, 0x2222, prN}, // Sm [2] MEASURED ANGLE..SPHERICAL ANGLE + {0x2223, 0x2223, prA}, // Sm DIVIDES + {0x2224, 0x2224, prN}, // Sm DOES NOT DIVIDE + {0x2225, 0x2225, prA}, // Sm PARALLEL TO + {0x2226, 0x2226, prN}, // Sm NOT PARALLEL TO + {0x2227, 0x222C, prA}, // Sm [6] LOGICAL AND..DOUBLE INTEGRAL + {0x222D, 0x222D, prN}, // Sm TRIPLE INTEGRAL + {0x222E, 0x222E, prA}, // Sm CONTOUR INTEGRAL + {0x222F, 0x2233, prN}, // Sm [5] SURFACE INTEGRAL..ANTICLOCKWISE CONTOUR INTEGRAL + {0x2234, 0x2237, prA}, // Sm [4] THEREFORE..PROPORTION + {0x2238, 0x223B, prN}, // Sm [4] DOT MINUS..HOMOTHETIC + {0x223C, 0x223D, prA}, // Sm [2] TILDE OPERATOR..REVERSED TILDE + {0x223E, 0x2247, prN}, // Sm [10] INVERTED LAZY S..NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO + {0x2248, 0x2248, prA}, // Sm ALMOST EQUAL TO + {0x2249, 0x224B, prN}, // Sm [3] NOT ALMOST EQUAL TO..TRIPLE TILDE + {0x224C, 0x224C, prA}, // Sm ALL EQUAL TO + {0x224D, 0x2251, prN}, // Sm [5] EQUIVALENT TO..GEOMETRICALLY EQUAL TO + {0x2252, 0x2252, prA}, // Sm APPROXIMATELY EQUAL TO OR THE IMAGE OF + {0x2253, 0x225F, prN}, // Sm [13] IMAGE OF OR APPROXIMATELY EQUAL TO..QUESTIONED EQUAL TO + {0x2260, 0x2261, prA}, // Sm [2] NOT EQUAL TO..IDENTICAL TO + {0x2262, 0x2263, prN}, // Sm [2] NOT IDENTICAL TO..STRICTLY EQUIVALENT TO + {0x2264, 0x2267, prA}, // Sm [4] LESS-THAN OR EQUAL TO..GREATER-THAN OVER EQUAL TO + {0x2268, 0x2269, prN}, // Sm [2] LESS-THAN BUT NOT EQUAL TO..GREATER-THAN BUT NOT EQUAL TO + {0x226A, 0x226B, prA}, // Sm [2] MUCH LESS-THAN..MUCH GREATER-THAN + {0x226C, 0x226D, prN}, // Sm [2] BETWEEN..NOT EQUIVALENT TO + {0x226E, 0x226F, prA}, // Sm [2] NOT LESS-THAN..NOT GREATER-THAN + {0x2270, 0x2281, prN}, // Sm [18] NEITHER LESS-THAN NOR EQUAL TO..DOES NOT SUCCEED + {0x2282, 0x2283, prA}, // Sm [2] SUBSET OF..SUPERSET OF + {0x2284, 0x2285, prN}, // Sm [2] NOT A SUBSET OF..NOT A SUPERSET OF + {0x2286, 0x2287, prA}, // Sm [2] SUBSET OF OR EQUAL TO..SUPERSET OF OR EQUAL TO + {0x2288, 0x2294, prN}, // Sm [13] NEITHER A SUBSET OF NOR EQUAL TO..SQUARE CUP + {0x2295, 0x2295, prA}, // Sm CIRCLED PLUS + {0x2296, 0x2298, prN}, // Sm [3] CIRCLED MINUS..CIRCLED DIVISION SLASH + {0x2299, 0x2299, prA}, // Sm CIRCLED DOT OPERATOR + {0x229A, 0x22A4, prN}, // Sm [11] CIRCLED RING OPERATOR..DOWN TACK + {0x22A5, 0x22A5, prA}, // Sm UP TACK + {0x22A6, 0x22BE, prN}, // Sm [25] ASSERTION..RIGHT ANGLE WITH ARC + {0x22BF, 0x22BF, prA}, // Sm RIGHT TRIANGLE + {0x22C0, 0x22FF, prN}, // Sm [64] N-ARY LOGICAL AND..Z NOTATION BAG MEMBERSHIP + {0x2300, 0x2307, prN}, // So [8] DIAMETER SIGN..WAVY LINE + {0x2308, 0x2308, prN}, // Ps LEFT CEILING + {0x2309, 0x2309, prN}, // Pe RIGHT CEILING + {0x230A, 0x230A, prN}, // Ps LEFT FLOOR + {0x230B, 0x230B, prN}, // Pe RIGHT FLOOR + {0x230C, 0x2311, prN}, // So [6] BOTTOM RIGHT CROP..SQUARE LOZENGE + {0x2312, 0x2312, prA}, // So ARC + {0x2313, 0x2319, prN}, // So [7] SEGMENT..TURNED NOT SIGN + {0x231A, 0x231B, prW}, // So [2] WATCH..HOURGLASS + {0x231C, 0x231F, prN}, // So [4] TOP LEFT CORNER..BOTTOM RIGHT CORNER + {0x2320, 0x2321, prN}, // Sm [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL + {0x2322, 0x2328, prN}, // So [7] FROWN..KEYBOARD + {0x2329, 0x2329, prW}, // Ps LEFT-POINTING ANGLE BRACKET + {0x232A, 0x232A, prW}, // Pe RIGHT-POINTING ANGLE BRACKET + {0x232B, 0x237B, prN}, // So [81] ERASE TO THE LEFT..NOT CHECK MARK + {0x237C, 0x237C, prN}, // Sm RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW + {0x237D, 0x239A, prN}, // So [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL + {0x239B, 0x23B3, prN}, // Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM + {0x23B4, 0x23DB, prN}, // So [40] TOP SQUARE BRACKET..FUSE + {0x23DC, 0x23E1, prN}, // Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET + {0x23E2, 0x23E8, prN}, // So [7] WHITE TRAPEZIUM..DECIMAL EXPONENT SYMBOL + {0x23E9, 0x23EC, prW}, // So [4] BLACK RIGHT-POINTING DOUBLE TRIANGLE..BLACK DOWN-POINTING DOUBLE TRIANGLE + {0x23ED, 0x23EF, prN}, // So [3] BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR..BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR + {0x23F0, 0x23F0, prW}, // So ALARM CLOCK + {0x23F1, 0x23F2, prN}, // So [2] STOPWATCH..TIMER CLOCK + {0x23F3, 0x23F3, prW}, // So HOURGLASS WITH FLOWING SAND + {0x23F4, 0x23FF, prN}, // So [12] BLACK MEDIUM LEFT-POINTING TRIANGLE..OBSERVER EYE SYMBOL + {0x2400, 0x2426, prN}, // So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO + {0x2440, 0x244A, prN}, // So [11] OCR HOOK..OCR DOUBLE BACKSLASH + {0x2460, 0x249B, prA}, // No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP + {0x249C, 0x24E9, prA}, // So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z + {0x24EA, 0x24EA, prN}, // No CIRCLED DIGIT ZERO + {0x24EB, 0x24FF, prA}, // No [21] NEGATIVE CIRCLED NUMBER ELEVEN..NEGATIVE CIRCLED DIGIT ZERO + {0x2500, 0x254B, prA}, // So [76] BOX DRAWINGS LIGHT HORIZONTAL..BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL + {0x254C, 0x254F, prN}, // So [4] BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL..BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL + {0x2550, 0x2573, prA}, // So [36] BOX DRAWINGS DOUBLE HORIZONTAL..BOX DRAWINGS LIGHT DIAGONAL CROSS + {0x2574, 0x257F, prN}, // So [12] BOX DRAWINGS LIGHT LEFT..BOX DRAWINGS HEAVY UP AND LIGHT DOWN + {0x2580, 0x258F, prA}, // So [16] UPPER HALF BLOCK..LEFT ONE EIGHTH BLOCK + {0x2590, 0x2591, prN}, // So [2] RIGHT HALF BLOCK..LIGHT SHADE + {0x2592, 0x2595, prA}, // So [4] MEDIUM SHADE..RIGHT ONE EIGHTH BLOCK + {0x2596, 0x259F, prN}, // So [10] QUADRANT LOWER LEFT..QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT + {0x25A0, 0x25A1, prA}, // So [2] BLACK SQUARE..WHITE SQUARE + {0x25A2, 0x25A2, prN}, // So WHITE SQUARE WITH ROUNDED CORNERS + {0x25A3, 0x25A9, prA}, // So [7] WHITE SQUARE CONTAINING BLACK SMALL SQUARE..SQUARE WITH DIAGONAL CROSSHATCH FILL + {0x25AA, 0x25B1, prN}, // So [8] BLACK SMALL SQUARE..WHITE PARALLELOGRAM + {0x25B2, 0x25B3, prA}, // So [2] BLACK UP-POINTING TRIANGLE..WHITE UP-POINTING TRIANGLE + {0x25B4, 0x25B5, prN}, // So [2] BLACK UP-POINTING SMALL TRIANGLE..WHITE UP-POINTING SMALL TRIANGLE + {0x25B6, 0x25B6, prA}, // So BLACK RIGHT-POINTING TRIANGLE + {0x25B7, 0x25B7, prA}, // Sm WHITE RIGHT-POINTING TRIANGLE + {0x25B8, 0x25BB, prN}, // So [4] BLACK RIGHT-POINTING SMALL TRIANGLE..WHITE RIGHT-POINTING POINTER + {0x25BC, 0x25BD, prA}, // So [2] BLACK DOWN-POINTING TRIANGLE..WHITE DOWN-POINTING TRIANGLE + {0x25BE, 0x25BF, prN}, // So [2] BLACK DOWN-POINTING SMALL TRIANGLE..WHITE DOWN-POINTING SMALL TRIANGLE + {0x25C0, 0x25C0, prA}, // So BLACK LEFT-POINTING TRIANGLE + {0x25C1, 0x25C1, prA}, // Sm WHITE LEFT-POINTING TRIANGLE + {0x25C2, 0x25C5, prN}, // So [4] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE LEFT-POINTING POINTER + {0x25C6, 0x25C8, prA}, // So [3] BLACK DIAMOND..WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND + {0x25C9, 0x25CA, prN}, // So [2] FISHEYE..LOZENGE + {0x25CB, 0x25CB, prA}, // So WHITE CIRCLE + {0x25CC, 0x25CD, prN}, // So [2] DOTTED CIRCLE..CIRCLE WITH VERTICAL FILL + {0x25CE, 0x25D1, prA}, // So [4] BULLSEYE..CIRCLE WITH RIGHT HALF BLACK + {0x25D2, 0x25E1, prN}, // So [16] CIRCLE WITH LOWER HALF BLACK..LOWER HALF CIRCLE + {0x25E2, 0x25E5, prA}, // So [4] BLACK LOWER RIGHT TRIANGLE..BLACK UPPER RIGHT TRIANGLE + {0x25E6, 0x25EE, prN}, // So [9] WHITE BULLET..UP-POINTING TRIANGLE WITH RIGHT HALF BLACK + {0x25EF, 0x25EF, prA}, // So LARGE CIRCLE + {0x25F0, 0x25F7, prN}, // So [8] WHITE SQUARE WITH UPPER LEFT QUADRANT..WHITE CIRCLE WITH UPPER RIGHT QUADRANT + {0x25F8, 0x25FC, prN}, // Sm [5] UPPER LEFT TRIANGLE..BLACK MEDIUM SQUARE + {0x25FD, 0x25FE, prW}, // Sm [2] WHITE MEDIUM SMALL SQUARE..BLACK MEDIUM SMALL SQUARE + {0x25FF, 0x25FF, prN}, // Sm LOWER RIGHT TRIANGLE + {0x2600, 0x2604, prN}, // So [5] BLACK SUN WITH RAYS..COMET + {0x2605, 0x2606, prA}, // So [2] BLACK STAR..WHITE STAR + {0x2607, 0x2608, prN}, // So [2] LIGHTNING..THUNDERSTORM + {0x2609, 0x2609, prA}, // So SUN + {0x260A, 0x260D, prN}, // So [4] ASCENDING NODE..OPPOSITION + {0x260E, 0x260F, prA}, // So [2] BLACK TELEPHONE..WHITE TELEPHONE + {0x2610, 0x2613, prN}, // So [4] BALLOT BOX..SALTIRE + {0x2614, 0x2615, prW}, // So [2] UMBRELLA WITH RAIN DROPS..HOT BEVERAGE + {0x2616, 0x261B, prN}, // So [6] WHITE SHOGI PIECE..BLACK RIGHT POINTING INDEX + {0x261C, 0x261C, prA}, // So WHITE LEFT POINTING INDEX + {0x261D, 0x261D, prN}, // So WHITE UP POINTING INDEX + {0x261E, 0x261E, prA}, // So WHITE RIGHT POINTING INDEX + {0x261F, 0x263F, prN}, // So [33] WHITE DOWN POINTING INDEX..MERCURY + {0x2640, 0x2640, prA}, // So FEMALE SIGN + {0x2641, 0x2641, prN}, // So EARTH + {0x2642, 0x2642, prA}, // So MALE SIGN + {0x2643, 0x2647, prN}, // So [5] JUPITER..PLUTO + {0x2648, 0x2653, prW}, // So [12] ARIES..PISCES + {0x2654, 0x265F, prN}, // So [12] WHITE CHESS KING..BLACK CHESS PAWN + {0x2660, 0x2661, prA}, // So [2] BLACK SPADE SUIT..WHITE HEART SUIT + {0x2662, 0x2662, prN}, // So WHITE DIAMOND SUIT + {0x2663, 0x2665, prA}, // So [3] BLACK CLUB SUIT..BLACK HEART SUIT + {0x2666, 0x2666, prN}, // So BLACK DIAMOND SUIT + {0x2667, 0x266A, prA}, // So [4] WHITE CLUB SUIT..EIGHTH NOTE + {0x266B, 0x266B, prN}, // So BEAMED EIGHTH NOTES + {0x266C, 0x266D, prA}, // So [2] BEAMED SIXTEENTH NOTES..MUSIC FLAT SIGN + {0x266E, 0x266E, prN}, // So MUSIC NATURAL SIGN + {0x266F, 0x266F, prA}, // Sm MUSIC SHARP SIGN + {0x2670, 0x267E, prN}, // So [15] WEST SYRIAC CROSS..PERMANENT PAPER SIGN + {0x267F, 0x267F, prW}, // So WHEELCHAIR SYMBOL + {0x2680, 0x2692, prN}, // So [19] DIE FACE-1..HAMMER AND PICK + {0x2693, 0x2693, prW}, // So ANCHOR + {0x2694, 0x269D, prN}, // So [10] CROSSED SWORDS..OUTLINED WHITE STAR + {0x269E, 0x269F, prA}, // So [2] THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT + {0x26A0, 0x26A0, prN}, // So WARNING SIGN + {0x26A1, 0x26A1, prW}, // So HIGH VOLTAGE SIGN + {0x26A2, 0x26A9, prN}, // So [8] DOUBLED FEMALE SIGN..HORIZONTAL MALE WITH STROKE SIGN + {0x26AA, 0x26AB, prW}, // So [2] MEDIUM WHITE CIRCLE..MEDIUM BLACK CIRCLE + {0x26AC, 0x26BC, prN}, // So [17] MEDIUM SMALL WHITE CIRCLE..SESQUIQUADRATE + {0x26BD, 0x26BE, prW}, // So [2] SOCCER BALL..BASEBALL + {0x26BF, 0x26BF, prA}, // So SQUARED KEY + {0x26C0, 0x26C3, prN}, // So [4] WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING + {0x26C4, 0x26C5, prW}, // So [2] SNOWMAN WITHOUT SNOW..SUN BEHIND CLOUD + {0x26C6, 0x26CD, prA}, // So [8] RAIN..DISABLED CAR + {0x26CE, 0x26CE, prW}, // So OPHIUCHUS + {0x26CF, 0x26D3, prA}, // So [5] PICK..CHAINS + {0x26D4, 0x26D4, prW}, // So NO ENTRY + {0x26D5, 0x26E1, prA}, // So [13] ALTERNATE ONE-WAY LEFT WAY TRAFFIC..RESTRICTED LEFT ENTRY-2 + {0x26E2, 0x26E2, prN}, // So ASTRONOMICAL SYMBOL FOR URANUS + {0x26E3, 0x26E3, prA}, // So HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE + {0x26E4, 0x26E7, prN}, // So [4] PENTAGRAM..INVERTED PENTAGRAM + {0x26E8, 0x26E9, prA}, // So [2] BLACK CROSS ON SHIELD..SHINTO SHRINE + {0x26EA, 0x26EA, prW}, // So CHURCH + {0x26EB, 0x26F1, prA}, // So [7] CASTLE..UMBRELLA ON GROUND + {0x26F2, 0x26F3, prW}, // So [2] FOUNTAIN..FLAG IN HOLE + {0x26F4, 0x26F4, prA}, // So FERRY + {0x26F5, 0x26F5, prW}, // So SAILBOAT + {0x26F6, 0x26F9, prA}, // So [4] SQUARE FOUR CORNERS..PERSON WITH BALL + {0x26FA, 0x26FA, prW}, // So TENT + {0x26FB, 0x26FC, prA}, // So [2] JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL + {0x26FD, 0x26FD, prW}, // So FUEL PUMP + {0x26FE, 0x26FF, prA}, // So [2] CUP ON BLACK SQUARE..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE + {0x2700, 0x2704, prN}, // So [5] BLACK SAFETY SCISSORS..WHITE SCISSORS + {0x2705, 0x2705, prW}, // So WHITE HEAVY CHECK MARK + {0x2706, 0x2709, prN}, // So [4] TELEPHONE LOCATION SIGN..ENVELOPE + {0x270A, 0x270B, prW}, // So [2] RAISED FIST..RAISED HAND + {0x270C, 0x2727, prN}, // So [28] VICTORY HAND..WHITE FOUR POINTED STAR + {0x2728, 0x2728, prW}, // So SPARKLES + {0x2729, 0x273C, prN}, // So [20] STRESS OUTLINED WHITE STAR..OPEN CENTRE TEARDROP-SPOKED ASTERISK + {0x273D, 0x273D, prA}, // So HEAVY TEARDROP-SPOKED ASTERISK + {0x273E, 0x274B, prN}, // So [14] SIX PETALLED BLACK AND WHITE FLORETTE..HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK + {0x274C, 0x274C, prW}, // So CROSS MARK + {0x274D, 0x274D, prN}, // So SHADOWED WHITE CIRCLE + {0x274E, 0x274E, prW}, // So NEGATIVE SQUARED CROSS MARK + {0x274F, 0x2752, prN}, // So [4] LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPER RIGHT SHADOWED WHITE SQUARE + {0x2753, 0x2755, prW}, // So [3] BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT + {0x2756, 0x2756, prN}, // So BLACK DIAMOND MINUS WHITE X + {0x2757, 0x2757, prW}, // So HEAVY EXCLAMATION MARK SYMBOL + {0x2758, 0x2767, prN}, // So [16] LIGHT VERTICAL BAR..ROTATED FLORAL HEART BULLET + {0x2768, 0x2768, prN}, // Ps MEDIUM LEFT PARENTHESIS ORNAMENT + {0x2769, 0x2769, prN}, // Pe MEDIUM RIGHT PARENTHESIS ORNAMENT + {0x276A, 0x276A, prN}, // Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT + {0x276B, 0x276B, prN}, // Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT + {0x276C, 0x276C, prN}, // Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT + {0x276D, 0x276D, prN}, // Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT + {0x276E, 0x276E, prN}, // Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT + {0x276F, 0x276F, prN}, // Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT + {0x2770, 0x2770, prN}, // Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT + {0x2771, 0x2771, prN}, // Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT + {0x2772, 0x2772, prN}, // Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT + {0x2773, 0x2773, prN}, // Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT + {0x2774, 0x2774, prN}, // Ps MEDIUM LEFT CURLY BRACKET ORNAMENT + {0x2775, 0x2775, prN}, // Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT + {0x2776, 0x277F, prA}, // No [10] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED NUMBER TEN + {0x2780, 0x2793, prN}, // No [20] DINGBAT CIRCLED SANS-SERIF DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN + {0x2794, 0x2794, prN}, // So HEAVY WIDE-HEADED RIGHTWARDS ARROW + {0x2795, 0x2797, prW}, // So [3] HEAVY PLUS SIGN..HEAVY DIVISION SIGN + {0x2798, 0x27AF, prN}, // So [24] HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW + {0x27B0, 0x27B0, prW}, // So CURLY LOOP + {0x27B1, 0x27BE, prN}, // So [14] NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW..OPEN-OUTLINED RIGHTWARDS ARROW + {0x27BF, 0x27BF, prW}, // So DOUBLE CURLY LOOP + {0x27C0, 0x27C4, prN}, // Sm [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET + {0x27C5, 0x27C5, prN}, // Ps LEFT S-SHAPED BAG DELIMITER + {0x27C6, 0x27C6, prN}, // Pe RIGHT S-SHAPED BAG DELIMITER + {0x27C7, 0x27E5, prN}, // Sm [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK + {0x27E6, 0x27E6, prNa}, // Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET + {0x27E7, 0x27E7, prNa}, // Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET + {0x27E8, 0x27E8, prNa}, // Ps MATHEMATICAL LEFT ANGLE BRACKET + {0x27E9, 0x27E9, prNa}, // Pe MATHEMATICAL RIGHT ANGLE BRACKET + {0x27EA, 0x27EA, prNa}, // Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET + {0x27EB, 0x27EB, prNa}, // Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET + {0x27EC, 0x27EC, prNa}, // Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET + {0x27ED, 0x27ED, prNa}, // Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET + {0x27EE, 0x27EE, prN}, // Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS + {0x27EF, 0x27EF, prN}, // Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS + {0x27F0, 0x27FF, prN}, // Sm [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW + {0x2800, 0x28FF, prN}, // So [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678 + {0x2900, 0x297F, prN}, // Sm [128] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..DOWN FISH TAIL + {0x2980, 0x2982, prN}, // Sm [3] TRIPLE VERTICAL BAR DELIMITER..Z NOTATION TYPE COLON + {0x2983, 0x2983, prN}, // Ps LEFT WHITE CURLY BRACKET + {0x2984, 0x2984, prN}, // Pe RIGHT WHITE CURLY BRACKET + {0x2985, 0x2985, prNa}, // Ps LEFT WHITE PARENTHESIS + {0x2986, 0x2986, prNa}, // Pe RIGHT WHITE PARENTHESIS + {0x2987, 0x2987, prN}, // Ps Z NOTATION LEFT IMAGE BRACKET + {0x2988, 0x2988, prN}, // Pe Z NOTATION RIGHT IMAGE BRACKET + {0x2989, 0x2989, prN}, // Ps Z NOTATION LEFT BINDING BRACKET + {0x298A, 0x298A, prN}, // Pe Z NOTATION RIGHT BINDING BRACKET + {0x298B, 0x298B, prN}, // Ps LEFT SQUARE BRACKET WITH UNDERBAR + {0x298C, 0x298C, prN}, // Pe RIGHT SQUARE BRACKET WITH UNDERBAR + {0x298D, 0x298D, prN}, // Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER + {0x298E, 0x298E, prN}, // Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {0x298F, 0x298F, prN}, // Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {0x2990, 0x2990, prN}, // Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER + {0x2991, 0x2991, prN}, // Ps LEFT ANGLE BRACKET WITH DOT + {0x2992, 0x2992, prN}, // Pe RIGHT ANGLE BRACKET WITH DOT + {0x2993, 0x2993, prN}, // Ps LEFT ARC LESS-THAN BRACKET + {0x2994, 0x2994, prN}, // Pe RIGHT ARC GREATER-THAN BRACKET + {0x2995, 0x2995, prN}, // Ps DOUBLE LEFT ARC GREATER-THAN BRACKET + {0x2996, 0x2996, prN}, // Pe DOUBLE RIGHT ARC LESS-THAN BRACKET + {0x2997, 0x2997, prN}, // Ps LEFT BLACK TORTOISE SHELL BRACKET + {0x2998, 0x2998, prN}, // Pe RIGHT BLACK TORTOISE SHELL BRACKET + {0x2999, 0x29D7, prN}, // Sm [63] DOTTED FENCE..BLACK HOURGLASS + {0x29D8, 0x29D8, prN}, // Ps LEFT WIGGLY FENCE + {0x29D9, 0x29D9, prN}, // Pe RIGHT WIGGLY FENCE + {0x29DA, 0x29DA, prN}, // Ps LEFT DOUBLE WIGGLY FENCE + {0x29DB, 0x29DB, prN}, // Pe RIGHT DOUBLE WIGGLY FENCE + {0x29DC, 0x29FB, prN}, // Sm [32] INCOMPLETE INFINITY..TRIPLE PLUS + {0x29FC, 0x29FC, prN}, // Ps LEFT-POINTING CURVED ANGLE BRACKET + {0x29FD, 0x29FD, prN}, // Pe RIGHT-POINTING CURVED ANGLE BRACKET + {0x29FE, 0x29FF, prN}, // Sm [2] TINY..MINY + {0x2A00, 0x2AFF, prN}, // Sm [256] N-ARY CIRCLED DOT OPERATOR..N-ARY WHITE VERTICAL BAR + {0x2B00, 0x2B1A, prN}, // So [27] NORTH EAST WHITE ARROW..DOTTED SQUARE + {0x2B1B, 0x2B1C, prW}, // So [2] BLACK LARGE SQUARE..WHITE LARGE SQUARE + {0x2B1D, 0x2B2F, prN}, // So [19] BLACK VERY SMALL SQUARE..WHITE VERTICAL ELLIPSE + {0x2B30, 0x2B44, prN}, // Sm [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET + {0x2B45, 0x2B46, prN}, // So [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW + {0x2B47, 0x2B4C, prN}, // Sm [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR + {0x2B4D, 0x2B4F, prN}, // So [3] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..SHORT BACKSLANTED SOUTH ARROW + {0x2B50, 0x2B50, prW}, // So WHITE MEDIUM STAR + {0x2B51, 0x2B54, prN}, // So [4] BLACK SMALL STAR..WHITE RIGHT-POINTING PENTAGON + {0x2B55, 0x2B55, prW}, // So HEAVY LARGE CIRCLE + {0x2B56, 0x2B59, prA}, // So [4] HEAVY OVAL WITH OVAL INSIDE..HEAVY CIRCLED SALTIRE + {0x2B5A, 0x2B73, prN}, // So [26] SLANTED NORTH ARROW WITH HOOKED HEAD..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR + {0x2B76, 0x2B95, prN}, // So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW + {0x2B97, 0x2BFF, prN}, // So [105] SYMBOL FOR TYPE A ELECTRONICS..HELLSCHREIBER PAUSE SYMBOL + {0x2C00, 0x2C5F, prN}, // L& [96] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI + {0x2C60, 0x2C7B, prN}, // L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E + {0x2C7C, 0x2C7D, prN}, // Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V + {0x2C7E, 0x2C7F, prN}, // Lu [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL + {0x2C80, 0x2CE4, prN}, // L& [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI + {0x2CE5, 0x2CEA, prN}, // So [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA + {0x2CEB, 0x2CEE, prN}, // L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA + {0x2CEF, 0x2CF1, prN}, // Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS + {0x2CF2, 0x2CF3, prN}, // L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI + {0x2CF9, 0x2CFC, prN}, // Po [4] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN VERSE DIVIDER + {0x2CFD, 0x2CFD, prN}, // No COPTIC FRACTION ONE HALF + {0x2CFE, 0x2CFF, prN}, // Po [2] COPTIC FULL STOP..COPTIC MORPHOLOGICAL DIVIDER + {0x2D00, 0x2D25, prN}, // Ll [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE + {0x2D27, 0x2D27, prN}, // Ll GEORGIAN SMALL LETTER YN + {0x2D2D, 0x2D2D, prN}, // Ll GEORGIAN SMALL LETTER AEN + {0x2D30, 0x2D67, prN}, // Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO + {0x2D6F, 0x2D6F, prN}, // Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK + {0x2D70, 0x2D70, prN}, // Po TIFINAGH SEPARATOR MARK + {0x2D7F, 0x2D7F, prN}, // Mn TIFINAGH CONSONANT JOINER + {0x2D80, 0x2D96, prN}, // Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE + {0x2DA0, 0x2DA6, prN}, // Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO + {0x2DA8, 0x2DAE, prN}, // Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO + {0x2DB0, 0x2DB6, prN}, // Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO + {0x2DB8, 0x2DBE, prN}, // Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO + {0x2DC0, 0x2DC6, prN}, // Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO + {0x2DC8, 0x2DCE, prN}, // Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO + {0x2DD0, 0x2DD6, prN}, // Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO + {0x2DD8, 0x2DDE, prN}, // Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO + {0x2DE0, 0x2DFF, prN}, // Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS + {0x2E00, 0x2E01, prN}, // Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER + {0x2E02, 0x2E02, prN}, // Pi LEFT SUBSTITUTION BRACKET + {0x2E03, 0x2E03, prN}, // Pf RIGHT SUBSTITUTION BRACKET + {0x2E04, 0x2E04, prN}, // Pi LEFT DOTTED SUBSTITUTION BRACKET + {0x2E05, 0x2E05, prN}, // Pf RIGHT DOTTED SUBSTITUTION BRACKET + {0x2E06, 0x2E08, prN}, // Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER + {0x2E09, 0x2E09, prN}, // Pi LEFT TRANSPOSITION BRACKET + {0x2E0A, 0x2E0A, prN}, // Pf RIGHT TRANSPOSITION BRACKET + {0x2E0B, 0x2E0B, prN}, // Po RAISED SQUARE + {0x2E0C, 0x2E0C, prN}, // Pi LEFT RAISED OMISSION BRACKET + {0x2E0D, 0x2E0D, prN}, // Pf RIGHT RAISED OMISSION BRACKET + {0x2E0E, 0x2E16, prN}, // Po [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE + {0x2E17, 0x2E17, prN}, // Pd DOUBLE OBLIQUE HYPHEN + {0x2E18, 0x2E19, prN}, // Po [2] INVERTED INTERROBANG..PALM BRANCH + {0x2E1A, 0x2E1A, prN}, // Pd HYPHEN WITH DIAERESIS + {0x2E1B, 0x2E1B, prN}, // Po TILDE WITH RING ABOVE + {0x2E1C, 0x2E1C, prN}, // Pi LEFT LOW PARAPHRASE BRACKET + {0x2E1D, 0x2E1D, prN}, // Pf RIGHT LOW PARAPHRASE BRACKET + {0x2E1E, 0x2E1F, prN}, // Po [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW + {0x2E20, 0x2E20, prN}, // Pi LEFT VERTICAL BAR WITH QUILL + {0x2E21, 0x2E21, prN}, // Pf RIGHT VERTICAL BAR WITH QUILL + {0x2E22, 0x2E22, prN}, // Ps TOP LEFT HALF BRACKET + {0x2E23, 0x2E23, prN}, // Pe TOP RIGHT HALF BRACKET + {0x2E24, 0x2E24, prN}, // Ps BOTTOM LEFT HALF BRACKET + {0x2E25, 0x2E25, prN}, // Pe BOTTOM RIGHT HALF BRACKET + {0x2E26, 0x2E26, prN}, // Ps LEFT SIDEWAYS U BRACKET + {0x2E27, 0x2E27, prN}, // Pe RIGHT SIDEWAYS U BRACKET + {0x2E28, 0x2E28, prN}, // Ps LEFT DOUBLE PARENTHESIS + {0x2E29, 0x2E29, prN}, // Pe RIGHT DOUBLE PARENTHESIS + {0x2E2A, 0x2E2E, prN}, // Po [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK + {0x2E2F, 0x2E2F, prN}, // Lm VERTICAL TILDE + {0x2E30, 0x2E39, prN}, // Po [10] RING POINT..TOP HALF SECTION SIGN + {0x2E3A, 0x2E3B, prN}, // Pd [2] TWO-EM DASH..THREE-EM DASH + {0x2E3C, 0x2E3F, prN}, // Po [4] STENOGRAPHIC FULL STOP..CAPITULUM + {0x2E40, 0x2E40, prN}, // Pd DOUBLE HYPHEN + {0x2E41, 0x2E41, prN}, // Po REVERSED COMMA + {0x2E42, 0x2E42, prN}, // Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK + {0x2E43, 0x2E4F, prN}, // Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER + {0x2E50, 0x2E51, prN}, // So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR + {0x2E52, 0x2E54, prN}, // Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK + {0x2E55, 0x2E55, prN}, // Ps LEFT SQUARE BRACKET WITH STROKE + {0x2E56, 0x2E56, prN}, // Pe RIGHT SQUARE BRACKET WITH STROKE + {0x2E57, 0x2E57, prN}, // Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE + {0x2E58, 0x2E58, prN}, // Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE + {0x2E59, 0x2E59, prN}, // Ps TOP HALF LEFT PARENTHESIS + {0x2E5A, 0x2E5A, prN}, // Pe TOP HALF RIGHT PARENTHESIS + {0x2E5B, 0x2E5B, prN}, // Ps BOTTOM HALF LEFT PARENTHESIS + {0x2E5C, 0x2E5C, prN}, // Pe BOTTOM HALF RIGHT PARENTHESIS + {0x2E5D, 0x2E5D, prN}, // Pd OBLIQUE HYPHEN + {0x2E80, 0x2E99, prW}, // So [26] CJK RADICAL REPEAT..CJK RADICAL RAP + {0x2E9B, 0x2EF3, prW}, // So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE + {0x2F00, 0x2FD5, prW}, // So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE + {0x2FF0, 0x2FFB, prW}, // So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID + {0x3000, 0x3000, prF}, // Zs IDEOGRAPHIC SPACE + {0x3001, 0x3003, prW}, // Po [3] IDEOGRAPHIC COMMA..DITTO MARK + {0x3004, 0x3004, prW}, // So JAPANESE INDUSTRIAL STANDARD SYMBOL + {0x3005, 0x3005, prW}, // Lm IDEOGRAPHIC ITERATION MARK + {0x3006, 0x3006, prW}, // Lo IDEOGRAPHIC CLOSING MARK + {0x3007, 0x3007, prW}, // Nl IDEOGRAPHIC NUMBER ZERO + {0x3008, 0x3008, prW}, // Ps LEFT ANGLE BRACKET + {0x3009, 0x3009, prW}, // Pe RIGHT ANGLE BRACKET + {0x300A, 0x300A, prW}, // Ps LEFT DOUBLE ANGLE BRACKET + {0x300B, 0x300B, prW}, // Pe RIGHT DOUBLE ANGLE BRACKET + {0x300C, 0x300C, prW}, // Ps LEFT CORNER BRACKET + {0x300D, 0x300D, prW}, // Pe RIGHT CORNER BRACKET + {0x300E, 0x300E, prW}, // Ps LEFT WHITE CORNER BRACKET + {0x300F, 0x300F, prW}, // Pe RIGHT WHITE CORNER BRACKET + {0x3010, 0x3010, prW}, // Ps LEFT BLACK LENTICULAR BRACKET + {0x3011, 0x3011, prW}, // Pe RIGHT BLACK LENTICULAR BRACKET + {0x3012, 0x3013, prW}, // So [2] POSTAL MARK..GETA MARK + {0x3014, 0x3014, prW}, // Ps LEFT TORTOISE SHELL BRACKET + {0x3015, 0x3015, prW}, // Pe RIGHT TORTOISE SHELL BRACKET + {0x3016, 0x3016, prW}, // Ps LEFT WHITE LENTICULAR BRACKET + {0x3017, 0x3017, prW}, // Pe RIGHT WHITE LENTICULAR BRACKET + {0x3018, 0x3018, prW}, // Ps LEFT WHITE TORTOISE SHELL BRACKET + {0x3019, 0x3019, prW}, // Pe RIGHT WHITE TORTOISE SHELL BRACKET + {0x301A, 0x301A, prW}, // Ps LEFT WHITE SQUARE BRACKET + {0x301B, 0x301B, prW}, // Pe RIGHT WHITE SQUARE BRACKET + {0x301C, 0x301C, prW}, // Pd WAVE DASH + {0x301D, 0x301D, prW}, // Ps REVERSED DOUBLE PRIME QUOTATION MARK + {0x301E, 0x301F, prW}, // Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK + {0x3020, 0x3020, prW}, // So POSTAL MARK FACE + {0x3021, 0x3029, prW}, // Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE + {0x302A, 0x302D, prW}, // Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK + {0x302E, 0x302F, prW}, // Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK + {0x3030, 0x3030, prW}, // Pd WAVY DASH + {0x3031, 0x3035, prW}, // Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF + {0x3036, 0x3037, prW}, // So [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL + {0x3038, 0x303A, prW}, // Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY + {0x303B, 0x303B, prW}, // Lm VERTICAL IDEOGRAPHIC ITERATION MARK + {0x303C, 0x303C, prW}, // Lo MASU MARK + {0x303D, 0x303D, prW}, // Po PART ALTERNATION MARK + {0x303E, 0x303E, prW}, // So IDEOGRAPHIC VARIATION INDICATOR + {0x303F, 0x303F, prN}, // So IDEOGRAPHIC HALF FILL SPACE + {0x3041, 0x3096, prW}, // Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE + {0x3099, 0x309A, prW}, // Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x309B, 0x309C, prW}, // Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x309D, 0x309E, prW}, // Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK + {0x309F, 0x309F, prW}, // Lo HIRAGANA DIGRAPH YORI + {0x30A0, 0x30A0, prW}, // Pd KATAKANA-HIRAGANA DOUBLE HYPHEN + {0x30A1, 0x30FA, prW}, // Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO + {0x30FB, 0x30FB, prW}, // Po KATAKANA MIDDLE DOT + {0x30FC, 0x30FE, prW}, // Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK + {0x30FF, 0x30FF, prW}, // Lo KATAKANA DIGRAPH KOTO + {0x3105, 0x312F, prW}, // Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN + {0x3131, 0x318E, prW}, // Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE + {0x3190, 0x3191, prW}, // So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK + {0x3192, 0x3195, prW}, // No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK + {0x3196, 0x319F, prW}, // So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK + {0x31A0, 0x31BF, prW}, // Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH + {0x31C0, 0x31E3, prW}, // So [36] CJK STROKE T..CJK STROKE Q + {0x31F0, 0x31FF, prW}, // Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO + {0x3200, 0x321E, prW}, // So [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU + {0x3220, 0x3229, prW}, // No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN + {0x322A, 0x3247, prW}, // So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO + {0x3248, 0x324F, prA}, // No [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE + {0x3250, 0x3250, prW}, // So PARTNERSHIP SIGN + {0x3251, 0x325F, prW}, // No [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE + {0x3260, 0x327F, prW}, // So [32] CIRCLED HANGUL KIYEOK..KOREAN STANDARD SYMBOL + {0x3280, 0x3289, prW}, // No [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN + {0x328A, 0x32B0, prW}, // So [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT + {0x32B1, 0x32BF, prW}, // No [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY + {0x32C0, 0x32FF, prW}, // So [64] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..SQUARE ERA NAME REIWA + {0x3300, 0x33FF, prW}, // So [256] SQUARE APAATO..SQUARE GAL + {0x3400, 0x4DBF, prW}, // Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF + {0x4DC0, 0x4DFF, prN}, // So [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION + {0x4E00, 0x9FFF, prW}, // Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF + {0xA000, 0xA014, prW}, // Lo [21] YI SYLLABLE IT..YI SYLLABLE E + {0xA015, 0xA015, prW}, // Lm YI SYLLABLE WU + {0xA016, 0xA48C, prW}, // Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR + {0xA490, 0xA4C6, prW}, // So [55] YI RADICAL QOT..YI RADICAL KE + {0xA4D0, 0xA4F7, prN}, // Lo [40] LISU LETTER BA..LISU LETTER OE + {0xA4F8, 0xA4FD, prN}, // Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU + {0xA4FE, 0xA4FF, prN}, // Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP + {0xA500, 0xA60B, prN}, // Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG + {0xA60C, 0xA60C, prN}, // Lm VAI SYLLABLE LENGTHENER + {0xA60D, 0xA60F, prN}, // Po [3] VAI COMMA..VAI QUESTION MARK + {0xA610, 0xA61F, prN}, // Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG + {0xA620, 0xA629, prN}, // Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE + {0xA62A, 0xA62B, prN}, // Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO + {0xA640, 0xA66D, prN}, // L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O + {0xA66E, 0xA66E, prN}, // Lo CYRILLIC LETTER MULTIOCULAR O + {0xA66F, 0xA66F, prN}, // Mn COMBINING CYRILLIC VZMET + {0xA670, 0xA672, prN}, // Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN + {0xA673, 0xA673, prN}, // Po SLAVONIC ASTERISK + {0xA674, 0xA67D, prN}, // Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK + {0xA67E, 0xA67E, prN}, // Po CYRILLIC KAVYKA + {0xA67F, 0xA67F, prN}, // Lm CYRILLIC PAYEROK + {0xA680, 0xA69B, prN}, // L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O + {0xA69C, 0xA69D, prN}, // Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN + {0xA69E, 0xA69F, prN}, // Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E + {0xA6A0, 0xA6E5, prN}, // Lo [70] BAMUM LETTER A..BAMUM LETTER KI + {0xA6E6, 0xA6EF, prN}, // Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM + {0xA6F0, 0xA6F1, prN}, // Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS + {0xA6F2, 0xA6F7, prN}, // Po [6] BAMUM NJAEMLI..BAMUM QUESTION MARK + {0xA700, 0xA716, prN}, // Sk [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR + {0xA717, 0xA71F, prN}, // Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK + {0xA720, 0xA721, prN}, // Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE + {0xA722, 0xA76F, prN}, // L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON + {0xA770, 0xA770, prN}, // Lm MODIFIER LETTER US + {0xA771, 0xA787, prN}, // L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T + {0xA788, 0xA788, prN}, // Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT + {0xA789, 0xA78A, prN}, // Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN + {0xA78B, 0xA78E, prN}, // L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT + {0xA78F, 0xA78F, prN}, // Lo LATIN LETTER SINOLOGICAL DOT + {0xA790, 0xA7CA, prN}, // L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY + {0xA7D0, 0xA7D1, prN}, // L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G + {0xA7D3, 0xA7D3, prN}, // Ll LATIN SMALL LETTER DOUBLE THORN + {0xA7D5, 0xA7D9, prN}, // L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S + {0xA7F2, 0xA7F4, prN}, // Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q + {0xA7F5, 0xA7F6, prN}, // L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H + {0xA7F7, 0xA7F7, prN}, // Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I + {0xA7F8, 0xA7F9, prN}, // Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE + {0xA7FA, 0xA7FA, prN}, // Ll LATIN LETTER SMALL CAPITAL TURNED M + {0xA7FB, 0xA7FF, prN}, // Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M + {0xA800, 0xA801, prN}, // Lo [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I + {0xA802, 0xA802, prN}, // Mn SYLOTI NAGRI SIGN DVISVARA + {0xA803, 0xA805, prN}, // Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O + {0xA806, 0xA806, prN}, // Mn SYLOTI NAGRI SIGN HASANTA + {0xA807, 0xA80A, prN}, // Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO + {0xA80B, 0xA80B, prN}, // Mn SYLOTI NAGRI SIGN ANUSVARA + {0xA80C, 0xA822, prN}, // Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO + {0xA823, 0xA824, prN}, // Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I + {0xA825, 0xA826, prN}, // Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E + {0xA827, 0xA827, prN}, // Mc SYLOTI NAGRI VOWEL SIGN OO + {0xA828, 0xA82B, prN}, // So [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4 + {0xA82C, 0xA82C, prN}, // Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA + {0xA830, 0xA835, prN}, // No [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS + {0xA836, 0xA837, prN}, // So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK + {0xA838, 0xA838, prN}, // Sc NORTH INDIC RUPEE MARK + {0xA839, 0xA839, prN}, // So NORTH INDIC QUANTITY MARK + {0xA840, 0xA873, prN}, // Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU + {0xA874, 0xA877, prN}, // Po [4] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD + {0xA880, 0xA881, prN}, // Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA + {0xA882, 0xA8B3, prN}, // Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA + {0xA8B4, 0xA8C3, prN}, // Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU + {0xA8C4, 0xA8C5, prN}, // Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU + {0xA8CE, 0xA8CF, prN}, // Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA + {0xA8D0, 0xA8D9, prN}, // Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE + {0xA8E0, 0xA8F1, prN}, // Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA + {0xA8F2, 0xA8F7, prN}, // Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA + {0xA8F8, 0xA8FA, prN}, // Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET + {0xA8FB, 0xA8FB, prN}, // Lo DEVANAGARI HEADSTROKE + {0xA8FC, 0xA8FC, prN}, // Po DEVANAGARI SIGN SIDDHAM + {0xA8FD, 0xA8FE, prN}, // Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY + {0xA8FF, 0xA8FF, prN}, // Mn DEVANAGARI VOWEL SIGN AY + {0xA900, 0xA909, prN}, // Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE + {0xA90A, 0xA925, prN}, // Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO + {0xA926, 0xA92D, prN}, // Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU + {0xA92E, 0xA92F, prN}, // Po [2] KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA + {0xA930, 0xA946, prN}, // Lo [23] REJANG LETTER KA..REJANG LETTER A + {0xA947, 0xA951, prN}, // Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R + {0xA952, 0xA953, prN}, // Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA + {0xA95F, 0xA95F, prN}, // Po REJANG SECTION MARK + {0xA960, 0xA97C, prW}, // Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH + {0xA980, 0xA982, prN}, // Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR + {0xA983, 0xA983, prN}, // Mc JAVANESE SIGN WIGNYAN + {0xA984, 0xA9B2, prN}, // Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA + {0xA9B3, 0xA9B3, prN}, // Mn JAVANESE SIGN CECAK TELU + {0xA9B4, 0xA9B5, prN}, // Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG + {0xA9B6, 0xA9B9, prN}, // Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT + {0xA9BA, 0xA9BB, prN}, // Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE + {0xA9BC, 0xA9BD, prN}, // Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET + {0xA9BE, 0xA9C0, prN}, // Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON + {0xA9C1, 0xA9CD, prN}, // Po [13] JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH + {0xA9CF, 0xA9CF, prN}, // Lm JAVANESE PANGRANGKEP + {0xA9D0, 0xA9D9, prN}, // Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE + {0xA9DE, 0xA9DF, prN}, // Po [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN + {0xA9E0, 0xA9E4, prN}, // Lo [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA + {0xA9E5, 0xA9E5, prN}, // Mn MYANMAR SIGN SHAN SAW + {0xA9E6, 0xA9E6, prN}, // Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION + {0xA9E7, 0xA9EF, prN}, // Lo [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA + {0xA9F0, 0xA9F9, prN}, // Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE + {0xA9FA, 0xA9FE, prN}, // Lo [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA + {0xAA00, 0xAA28, prN}, // Lo [41] CHAM LETTER A..CHAM LETTER HA + {0xAA29, 0xAA2E, prN}, // Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE + {0xAA2F, 0xAA30, prN}, // Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI + {0xAA31, 0xAA32, prN}, // Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE + {0xAA33, 0xAA34, prN}, // Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA + {0xAA35, 0xAA36, prN}, // Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA + {0xAA40, 0xAA42, prN}, // Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG + {0xAA43, 0xAA43, prN}, // Mn CHAM CONSONANT SIGN FINAL NG + {0xAA44, 0xAA4B, prN}, // Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS + {0xAA4C, 0xAA4C, prN}, // Mn CHAM CONSONANT SIGN FINAL M + {0xAA4D, 0xAA4D, prN}, // Mc CHAM CONSONANT SIGN FINAL H + {0xAA50, 0xAA59, prN}, // Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE + {0xAA5C, 0xAA5F, prN}, // Po [4] CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA + {0xAA60, 0xAA6F, prN}, // Lo [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA + {0xAA70, 0xAA70, prN}, // Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION + {0xAA71, 0xAA76, prN}, // Lo [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM + {0xAA77, 0xAA79, prN}, // So [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO + {0xAA7A, 0xAA7A, prN}, // Lo MYANMAR LETTER AITON RA + {0xAA7B, 0xAA7B, prN}, // Mc MYANMAR SIGN PAO KAREN TONE + {0xAA7C, 0xAA7C, prN}, // Mn MYANMAR SIGN TAI LAING TONE-2 + {0xAA7D, 0xAA7D, prN}, // Mc MYANMAR SIGN TAI LAING TONE-5 + {0xAA7E, 0xAA7F, prN}, // Lo [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA + {0xAA80, 0xAAAF, prN}, // Lo [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O + {0xAAB0, 0xAAB0, prN}, // Mn TAI VIET MAI KANG + {0xAAB1, 0xAAB1, prN}, // Lo TAI VIET VOWEL AA + {0xAAB2, 0xAAB4, prN}, // Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U + {0xAAB5, 0xAAB6, prN}, // Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O + {0xAAB7, 0xAAB8, prN}, // Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA + {0xAAB9, 0xAABD, prN}, // Lo [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN + {0xAABE, 0xAABF, prN}, // Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK + {0xAAC0, 0xAAC0, prN}, // Lo TAI VIET TONE MAI NUENG + {0xAAC1, 0xAAC1, prN}, // Mn TAI VIET TONE MAI THO + {0xAAC2, 0xAAC2, prN}, // Lo TAI VIET TONE MAI SONG + {0xAADB, 0xAADC, prN}, // Lo [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG + {0xAADD, 0xAADD, prN}, // Lm TAI VIET SYMBOL SAM + {0xAADE, 0xAADF, prN}, // Po [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI + {0xAAE0, 0xAAEA, prN}, // Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA + {0xAAEB, 0xAAEB, prN}, // Mc MEETEI MAYEK VOWEL SIGN II + {0xAAEC, 0xAAED, prN}, // Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI + {0xAAEE, 0xAAEF, prN}, // Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU + {0xAAF0, 0xAAF1, prN}, // Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM + {0xAAF2, 0xAAF2, prN}, // Lo MEETEI MAYEK ANJI + {0xAAF3, 0xAAF4, prN}, // Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK + {0xAAF5, 0xAAF5, prN}, // Mc MEETEI MAYEK VOWEL SIGN VISARGA + {0xAAF6, 0xAAF6, prN}, // Mn MEETEI MAYEK VIRAMA + {0xAB01, 0xAB06, prN}, // Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO + {0xAB09, 0xAB0E, prN}, // Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO + {0xAB11, 0xAB16, prN}, // Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO + {0xAB20, 0xAB26, prN}, // Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO + {0xAB28, 0xAB2E, prN}, // Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO + {0xAB30, 0xAB5A, prN}, // Ll [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG + {0xAB5B, 0xAB5B, prN}, // Sk MODIFIER BREVE WITH INVERTED BREVE + {0xAB5C, 0xAB5F, prN}, // Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK + {0xAB60, 0xAB68, prN}, // Ll [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE + {0xAB69, 0xAB69, prN}, // Lm MODIFIER LETTER SMALL TURNED W + {0xAB6A, 0xAB6B, prN}, // Sk [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK + {0xAB70, 0xABBF, prN}, // Ll [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA + {0xABC0, 0xABE2, prN}, // Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM + {0xABE3, 0xABE4, prN}, // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP + {0xABE5, 0xABE5, prN}, // Mn MEETEI MAYEK VOWEL SIGN ANAP + {0xABE6, 0xABE7, prN}, // Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP + {0xABE8, 0xABE8, prN}, // Mn MEETEI MAYEK VOWEL SIGN UNAP + {0xABE9, 0xABEA, prN}, // Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG + {0xABEB, 0xABEB, prN}, // Po MEETEI MAYEK CHEIKHEI + {0xABEC, 0xABEC, prN}, // Mc MEETEI MAYEK LUM IYEK + {0xABED, 0xABED, prN}, // Mn MEETEI MAYEK APUN IYEK + {0xABF0, 0xABF9, prN}, // Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE + {0xAC00, 0xD7A3, prW}, // Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH + {0xD7B0, 0xD7C6, prN}, // Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E + {0xD7CB, 0xD7FB, prN}, // Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH + {0xD800, 0xDB7F, prN}, // Cs [896] .. + {0xDB80, 0xDBFF, prN}, // Cs [128] .. + {0xDC00, 0xDFFF, prN}, // Cs [1024] .. + {0xE000, 0xF8FF, prA}, // Co [6400] .. + {0xF900, 0xFA6D, prW}, // Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D + {0xFA6E, 0xFA6F, prW}, // Cn [2] .. + {0xFA70, 0xFAD9, prW}, // Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 + {0xFADA, 0xFAFF, prW}, // Cn [38] .. + {0xFB00, 0xFB06, prN}, // Ll [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST + {0xFB13, 0xFB17, prN}, // Ll [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH + {0xFB1D, 0xFB1D, prN}, // Lo HEBREW LETTER YOD WITH HIRIQ + {0xFB1E, 0xFB1E, prN}, // Mn HEBREW POINT JUDEO-SPANISH VARIKA + {0xFB1F, 0xFB28, prN}, // Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV + {0xFB29, 0xFB29, prN}, // Sm HEBREW LETTER ALTERNATIVE PLUS SIGN + {0xFB2A, 0xFB36, prN}, // Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH + {0xFB38, 0xFB3C, prN}, // Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH + {0xFB3E, 0xFB3E, prN}, // Lo HEBREW LETTER MEM WITH DAGESH + {0xFB40, 0xFB41, prN}, // Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH + {0xFB43, 0xFB44, prN}, // Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH + {0xFB46, 0xFB4F, prN}, // Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED + {0xFB50, 0xFBB1, prN}, // Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM + {0xFBB2, 0xFBC2, prN}, // Sk [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE + {0xFBD3, 0xFD3D, prN}, // Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM + {0xFD3E, 0xFD3E, prN}, // Pe ORNATE LEFT PARENTHESIS + {0xFD3F, 0xFD3F, prN}, // Ps ORNATE RIGHT PARENTHESIS + {0xFD40, 0xFD4F, prN}, // So [16] ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH + {0xFD50, 0xFD8F, prN}, // Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM + {0xFD92, 0xFDC7, prN}, // Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM + {0xFDCF, 0xFDCF, prN}, // So ARABIC LIGATURE SALAAMUHU ALAYNAA + {0xFDF0, 0xFDFB, prN}, // Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU + {0xFDFC, 0xFDFC, prN}, // Sc RIAL SIGN + {0xFDFD, 0xFDFF, prN}, // So [3] ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM..ARABIC LIGATURE AZZA WA JALL + {0xFE00, 0xFE0F, prA}, // Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 + {0xFE10, 0xFE16, prW}, // Po [7] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL QUESTION MARK + {0xFE17, 0xFE17, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET + {0xFE18, 0xFE18, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET + {0xFE19, 0xFE19, prW}, // Po PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS + {0xFE20, 0xFE2F, prN}, // Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + {0xFE30, 0xFE30, prW}, // Po PRESENTATION FORM FOR VERTICAL TWO DOT LEADER + {0xFE31, 0xFE32, prW}, // Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH + {0xFE33, 0xFE34, prW}, // Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE + {0xFE35, 0xFE35, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS + {0xFE36, 0xFE36, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS + {0xFE37, 0xFE37, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET + {0xFE38, 0xFE38, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET + {0xFE39, 0xFE39, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET + {0xFE3A, 0xFE3A, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET + {0xFE3B, 0xFE3B, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET + {0xFE3C, 0xFE3C, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET + {0xFE3D, 0xFE3D, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET + {0xFE3E, 0xFE3E, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET + {0xFE3F, 0xFE3F, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET + {0xFE40, 0xFE40, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET + {0xFE41, 0xFE41, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET + {0xFE42, 0xFE42, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET + {0xFE43, 0xFE43, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET + {0xFE44, 0xFE44, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET + {0xFE45, 0xFE46, prW}, // Po [2] SESAME DOT..WHITE SESAME DOT + {0xFE47, 0xFE47, prW}, // Ps PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET + {0xFE48, 0xFE48, prW}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET + {0xFE49, 0xFE4C, prW}, // Po [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE + {0xFE4D, 0xFE4F, prW}, // Pc [3] DASHED LOW LINE..WAVY LOW LINE + {0xFE50, 0xFE52, prW}, // Po [3] SMALL COMMA..SMALL FULL STOP + {0xFE54, 0xFE57, prW}, // Po [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK + {0xFE58, 0xFE58, prW}, // Pd SMALL EM DASH + {0xFE59, 0xFE59, prW}, // Ps SMALL LEFT PARENTHESIS + {0xFE5A, 0xFE5A, prW}, // Pe SMALL RIGHT PARENTHESIS + {0xFE5B, 0xFE5B, prW}, // Ps SMALL LEFT CURLY BRACKET + {0xFE5C, 0xFE5C, prW}, // Pe SMALL RIGHT CURLY BRACKET + {0xFE5D, 0xFE5D, prW}, // Ps SMALL LEFT TORTOISE SHELL BRACKET + {0xFE5E, 0xFE5E, prW}, // Pe SMALL RIGHT TORTOISE SHELL BRACKET + {0xFE5F, 0xFE61, prW}, // Po [3] SMALL NUMBER SIGN..SMALL ASTERISK + {0xFE62, 0xFE62, prW}, // Sm SMALL PLUS SIGN + {0xFE63, 0xFE63, prW}, // Pd SMALL HYPHEN-MINUS + {0xFE64, 0xFE66, prW}, // Sm [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN + {0xFE68, 0xFE68, prW}, // Po SMALL REVERSE SOLIDUS + {0xFE69, 0xFE69, prW}, // Sc SMALL DOLLAR SIGN + {0xFE6A, 0xFE6B, prW}, // Po [2] SMALL PERCENT SIGN..SMALL COMMERCIAL AT + {0xFE70, 0xFE74, prN}, // Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM + {0xFE76, 0xFEFC, prN}, // Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM + {0xFEFF, 0xFEFF, prN}, // Cf ZERO WIDTH NO-BREAK SPACE + {0xFF01, 0xFF03, prF}, // Po [3] FULLWIDTH EXCLAMATION MARK..FULLWIDTH NUMBER SIGN + {0xFF04, 0xFF04, prF}, // Sc FULLWIDTH DOLLAR SIGN + {0xFF05, 0xFF07, prF}, // Po [3] FULLWIDTH PERCENT SIGN..FULLWIDTH APOSTROPHE + {0xFF08, 0xFF08, prF}, // Ps FULLWIDTH LEFT PARENTHESIS + {0xFF09, 0xFF09, prF}, // Pe FULLWIDTH RIGHT PARENTHESIS + {0xFF0A, 0xFF0A, prF}, // Po FULLWIDTH ASTERISK + {0xFF0B, 0xFF0B, prF}, // Sm FULLWIDTH PLUS SIGN + {0xFF0C, 0xFF0C, prF}, // Po FULLWIDTH COMMA + {0xFF0D, 0xFF0D, prF}, // Pd FULLWIDTH HYPHEN-MINUS + {0xFF0E, 0xFF0F, prF}, // Po [2] FULLWIDTH FULL STOP..FULLWIDTH SOLIDUS + {0xFF10, 0xFF19, prF}, // Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE + {0xFF1A, 0xFF1B, prF}, // Po [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON + {0xFF1C, 0xFF1E, prF}, // Sm [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN + {0xFF1F, 0xFF20, prF}, // Po [2] FULLWIDTH QUESTION MARK..FULLWIDTH COMMERCIAL AT + {0xFF21, 0xFF3A, prF}, // Lu [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z + {0xFF3B, 0xFF3B, prF}, // Ps FULLWIDTH LEFT SQUARE BRACKET + {0xFF3C, 0xFF3C, prF}, // Po FULLWIDTH REVERSE SOLIDUS + {0xFF3D, 0xFF3D, prF}, // Pe FULLWIDTH RIGHT SQUARE BRACKET + {0xFF3E, 0xFF3E, prF}, // Sk FULLWIDTH CIRCUMFLEX ACCENT + {0xFF3F, 0xFF3F, prF}, // Pc FULLWIDTH LOW LINE + {0xFF40, 0xFF40, prF}, // Sk FULLWIDTH GRAVE ACCENT + {0xFF41, 0xFF5A, prF}, // Ll [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z + {0xFF5B, 0xFF5B, prF}, // Ps FULLWIDTH LEFT CURLY BRACKET + {0xFF5C, 0xFF5C, prF}, // Sm FULLWIDTH VERTICAL LINE + {0xFF5D, 0xFF5D, prF}, // Pe FULLWIDTH RIGHT CURLY BRACKET + {0xFF5E, 0xFF5E, prF}, // Sm FULLWIDTH TILDE + {0xFF5F, 0xFF5F, prF}, // Ps FULLWIDTH LEFT WHITE PARENTHESIS + {0xFF60, 0xFF60, prF}, // Pe FULLWIDTH RIGHT WHITE PARENTHESIS + {0xFF61, 0xFF61, prH}, // Po HALFWIDTH IDEOGRAPHIC FULL STOP + {0xFF62, 0xFF62, prH}, // Ps HALFWIDTH LEFT CORNER BRACKET + {0xFF63, 0xFF63, prH}, // Pe HALFWIDTH RIGHT CORNER BRACKET + {0xFF64, 0xFF65, prH}, // Po [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT + {0xFF66, 0xFF6F, prH}, // Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU + {0xFF70, 0xFF70, prH}, // Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK + {0xFF71, 0xFF9D, prH}, // Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N + {0xFF9E, 0xFF9F, prH}, // Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + {0xFFA0, 0xFFBE, prH}, // Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH + {0xFFC2, 0xFFC7, prH}, // Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E + {0xFFCA, 0xFFCF, prH}, // Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE + {0xFFD2, 0xFFD7, prH}, // Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU + {0xFFDA, 0xFFDC, prH}, // Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I + {0xFFE0, 0xFFE1, prF}, // Sc [2] FULLWIDTH CENT SIGN..FULLWIDTH POUND SIGN + {0xFFE2, 0xFFE2, prF}, // Sm FULLWIDTH NOT SIGN + {0xFFE3, 0xFFE3, prF}, // Sk FULLWIDTH MACRON + {0xFFE4, 0xFFE4, prF}, // So FULLWIDTH BROKEN BAR + {0xFFE5, 0xFFE6, prF}, // Sc [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN + {0xFFE8, 0xFFE8, prH}, // So HALFWIDTH FORMS LIGHT VERTICAL + {0xFFE9, 0xFFEC, prH}, // Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW + {0xFFED, 0xFFEE, prH}, // So [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE + {0xFFF9, 0xFFFB, prN}, // Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR + {0xFFFC, 0xFFFC, prN}, // So OBJECT REPLACEMENT CHARACTER + {0xFFFD, 0xFFFD, prA}, // So REPLACEMENT CHARACTER + {0x10000, 0x1000B, prN}, // Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE + {0x1000D, 0x10026, prN}, // Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO + {0x10028, 0x1003A, prN}, // Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO + {0x1003C, 0x1003D, prN}, // Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE + {0x1003F, 0x1004D, prN}, // Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO + {0x10050, 0x1005D, prN}, // Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089 + {0x10080, 0x100FA, prN}, // Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305 + {0x10100, 0x10102, prN}, // Po [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK + {0x10107, 0x10133, prN}, // No [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND + {0x10137, 0x1013F, prN}, // So [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT + {0x10140, 0x10174, prN}, // Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS + {0x10175, 0x10178, prN}, // No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN + {0x10179, 0x10189, prN}, // So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN + {0x1018A, 0x1018B, prN}, // No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN + {0x1018C, 0x1018E, prN}, // So [3] GREEK SINUSOID SIGN..NOMISMA SIGN + {0x10190, 0x1019C, prN}, // So [13] ROMAN SEXTANS SIGN..ASCIA SYMBOL + {0x101A0, 0x101A0, prN}, // So GREEK SYMBOL TAU RHO + {0x101D0, 0x101FC, prN}, // So [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND + {0x101FD, 0x101FD, prN}, // Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE + {0x10280, 0x1029C, prN}, // Lo [29] LYCIAN LETTER A..LYCIAN LETTER X + {0x102A0, 0x102D0, prN}, // Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3 + {0x102E0, 0x102E0, prN}, // Mn COPTIC EPACT THOUSANDS MARK + {0x102E1, 0x102FB, prN}, // No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED + {0x10300, 0x1031F, prN}, // Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS + {0x10320, 0x10323, prN}, // No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY + {0x1032D, 0x1032F, prN}, // Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE + {0x10330, 0x10340, prN}, // Lo [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA + {0x10341, 0x10341, prN}, // Nl GOTHIC LETTER NINETY + {0x10342, 0x10349, prN}, // Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL + {0x1034A, 0x1034A, prN}, // Nl GOTHIC LETTER NINE HUNDRED + {0x10350, 0x10375, prN}, // Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA + {0x10376, 0x1037A, prN}, // Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + {0x10380, 0x1039D, prN}, // Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU + {0x1039F, 0x1039F, prN}, // Po UGARITIC WORD DIVIDER + {0x103A0, 0x103C3, prN}, // Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA + {0x103C8, 0x103CF, prN}, // Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH + {0x103D0, 0x103D0, prN}, // Po OLD PERSIAN WORD DIVIDER + {0x103D1, 0x103D5, prN}, // Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED + {0x10400, 0x1044F, prN}, // L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW + {0x10450, 0x1047F, prN}, // Lo [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW + {0x10480, 0x1049D, prN}, // Lo [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO + {0x104A0, 0x104A9, prN}, // Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE + {0x104B0, 0x104D3, prN}, // Lu [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA + {0x104D8, 0x104FB, prN}, // Ll [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + {0x10500, 0x10527, prN}, // Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE + {0x10530, 0x10563, prN}, // Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW + {0x1056F, 0x1056F, prN}, // Po CAUCASIAN ALBANIAN CITATION MARK + {0x10570, 0x1057A, prN}, // Lu [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA + {0x1057C, 0x1058A, prN}, // Lu [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE + {0x1058C, 0x10592, prN}, // Lu [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE + {0x10594, 0x10595, prN}, // Lu [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE + {0x10597, 0x105A1, prN}, // Ll [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA + {0x105A3, 0x105B1, prN}, // Ll [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE + {0x105B3, 0x105B9, prN}, // Ll [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE + {0x105BB, 0x105BC, prN}, // Ll [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE + {0x10600, 0x10736, prN}, // Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 + {0x10740, 0x10755, prN}, // Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE + {0x10760, 0x10767, prN}, // Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 + {0x10780, 0x10785, prN}, // Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK + {0x10787, 0x107B0, prN}, // Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK + {0x107B2, 0x107BA, prN}, // Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL + {0x10800, 0x10805, prN}, // Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA + {0x10808, 0x10808, prN}, // Lo CYPRIOT SYLLABLE JO + {0x1080A, 0x10835, prN}, // Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO + {0x10837, 0x10838, prN}, // Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE + {0x1083C, 0x1083C, prN}, // Lo CYPRIOT SYLLABLE ZA + {0x1083F, 0x1083F, prN}, // Lo CYPRIOT SYLLABLE ZO + {0x10840, 0x10855, prN}, // Lo [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW + {0x10857, 0x10857, prN}, // Po IMPERIAL ARAMAIC SECTION SIGN + {0x10858, 0x1085F, prN}, // No [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND + {0x10860, 0x10876, prN}, // Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW + {0x10877, 0x10878, prN}, // So [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON + {0x10879, 0x1087F, prN}, // No [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY + {0x10880, 0x1089E, prN}, // Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW + {0x108A7, 0x108AF, prN}, // No [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED + {0x108E0, 0x108F2, prN}, // Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH + {0x108F4, 0x108F5, prN}, // Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW + {0x108FB, 0x108FF, prN}, // No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED + {0x10900, 0x10915, prN}, // Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU + {0x10916, 0x1091B, prN}, // No [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE + {0x1091F, 0x1091F, prN}, // Po PHOENICIAN WORD SEPARATOR + {0x10920, 0x10939, prN}, // Lo [26] LYDIAN LETTER A..LYDIAN LETTER C + {0x1093F, 0x1093F, prN}, // Po LYDIAN TRIANGULAR MARK + {0x10980, 0x1099F, prN}, // Lo [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2 + {0x109A0, 0x109B7, prN}, // Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA + {0x109BC, 0x109BD, prN}, // No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF + {0x109BE, 0x109BF, prN}, // Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN + {0x109C0, 0x109CF, prN}, // No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY + {0x109D2, 0x109FF, prN}, // No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS + {0x10A00, 0x10A00, prN}, // Lo KHAROSHTHI LETTER A + {0x10A01, 0x10A03, prN}, // Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R + {0x10A05, 0x10A06, prN}, // Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O + {0x10A0C, 0x10A0F, prN}, // Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA + {0x10A10, 0x10A13, prN}, // Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA + {0x10A15, 0x10A17, prN}, // Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA + {0x10A19, 0x10A35, prN}, // Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA + {0x10A38, 0x10A3A, prN}, // Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW + {0x10A3F, 0x10A3F, prN}, // Mn KHAROSHTHI VIRAMA + {0x10A40, 0x10A48, prN}, // No [9] KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF + {0x10A50, 0x10A58, prN}, // Po [9] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES + {0x10A60, 0x10A7C, prN}, // Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH + {0x10A7D, 0x10A7E, prN}, // No [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY + {0x10A7F, 0x10A7F, prN}, // Po OLD SOUTH ARABIAN NUMERIC INDICATOR + {0x10A80, 0x10A9C, prN}, // Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH + {0x10A9D, 0x10A9F, prN}, // No [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY + {0x10AC0, 0x10AC7, prN}, // Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW + {0x10AC8, 0x10AC8, prN}, // So MANICHAEAN SIGN UD + {0x10AC9, 0x10AE4, prN}, // Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW + {0x10AE5, 0x10AE6, prN}, // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW + {0x10AEB, 0x10AEF, prN}, // No [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED + {0x10AF0, 0x10AF6, prN}, // Po [7] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION LINE FILLER + {0x10B00, 0x10B35, prN}, // Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE + {0x10B39, 0x10B3F, prN}, // Po [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION + {0x10B40, 0x10B55, prN}, // Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW + {0x10B58, 0x10B5F, prN}, // No [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND + {0x10B60, 0x10B72, prN}, // Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW + {0x10B78, 0x10B7F, prN}, // No [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND + {0x10B80, 0x10B91, prN}, // Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW + {0x10B99, 0x10B9C, prN}, // Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT + {0x10BA9, 0x10BAF, prN}, // No [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED + {0x10C00, 0x10C48, prN}, // Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH + {0x10C80, 0x10CB2, prN}, // Lu [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US + {0x10CC0, 0x10CF2, prN}, // Ll [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US + {0x10CFA, 0x10CFF, prN}, // No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND + {0x10D00, 0x10D23, prN}, // Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA + {0x10D24, 0x10D27, prN}, // Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI + {0x10D30, 0x10D39, prN}, // Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE + {0x10E60, 0x10E7E, prN}, // No [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS + {0x10E80, 0x10EA9, prN}, // Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET + {0x10EAB, 0x10EAC, prN}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK + {0x10EAD, 0x10EAD, prN}, // Pd YEZIDI HYPHENATION MARK + {0x10EB0, 0x10EB1, prN}, // Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prN}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA + {0x10F00, 0x10F1C, prN}, // Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL + {0x10F1D, 0x10F26, prN}, // No [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF + {0x10F27, 0x10F27, prN}, // Lo OLD SOGDIAN LIGATURE AYIN-DALETH + {0x10F30, 0x10F45, prN}, // Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN + {0x10F46, 0x10F50, prN}, // Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW + {0x10F51, 0x10F54, prN}, // No [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED + {0x10F55, 0x10F59, prN}, // Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT + {0x10F70, 0x10F81, prN}, // Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH + {0x10F82, 0x10F85, prN}, // Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW + {0x10F86, 0x10F89, prN}, // Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS + {0x10FB0, 0x10FC4, prN}, // Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW + {0x10FC5, 0x10FCB, prN}, // No [7] CHORASMIAN NUMBER ONE..CHORASMIAN NUMBER ONE HUNDRED + {0x10FE0, 0x10FF6, prN}, // Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH + {0x11000, 0x11000, prN}, // Mc BRAHMI SIGN CANDRABINDU + {0x11001, 0x11001, prN}, // Mn BRAHMI SIGN ANUSVARA + {0x11002, 0x11002, prN}, // Mc BRAHMI SIGN VISARGA + {0x11003, 0x11037, prN}, // Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA + {0x11038, 0x11046, prN}, // Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA + {0x11047, 0x1104D, prN}, // Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS + {0x11052, 0x11065, prN}, // No [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND + {0x11066, 0x1106F, prN}, // Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE + {0x11070, 0x11070, prN}, // Mn BRAHMI SIGN OLD TAMIL VIRAMA + {0x11071, 0x11072, prN}, // Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O + {0x11073, 0x11074, prN}, // Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O + {0x11075, 0x11075, prN}, // Lo BRAHMI LETTER OLD TAMIL LLA + {0x1107F, 0x1107F, prN}, // Mn BRAHMI NUMBER JOINER + {0x11080, 0x11081, prN}, // Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA + {0x11082, 0x11082, prN}, // Mc KAITHI SIGN VISARGA + {0x11083, 0x110AF, prN}, // Lo [45] KAITHI LETTER A..KAITHI LETTER HA + {0x110B0, 0x110B2, prN}, // Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II + {0x110B3, 0x110B6, prN}, // Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI + {0x110B7, 0x110B8, prN}, // Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU + {0x110B9, 0x110BA, prN}, // Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA + {0x110BB, 0x110BC, prN}, // Po [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN + {0x110BD, 0x110BD, prN}, // Cf KAITHI NUMBER SIGN + {0x110BE, 0x110C1, prN}, // Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA + {0x110C2, 0x110C2, prN}, // Mn KAITHI VOWEL SIGN VOCALIC R + {0x110CD, 0x110CD, prN}, // Cf KAITHI NUMBER SIGN ABOVE + {0x110D0, 0x110E8, prN}, // Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE + {0x110F0, 0x110F9, prN}, // Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE + {0x11100, 0x11102, prN}, // Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA + {0x11103, 0x11126, prN}, // Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA + {0x11127, 0x1112B, prN}, // Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU + {0x1112C, 0x1112C, prN}, // Mc CHAKMA VOWEL SIGN E + {0x1112D, 0x11134, prN}, // Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA + {0x11136, 0x1113F, prN}, // Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE + {0x11140, 0x11143, prN}, // Po [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK + {0x11144, 0x11144, prN}, // Lo CHAKMA LETTER LHAA + {0x11145, 0x11146, prN}, // Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI + {0x11147, 0x11147, prN}, // Lo CHAKMA LETTER VAA + {0x11150, 0x11172, prN}, // Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA + {0x11173, 0x11173, prN}, // Mn MAHAJANI SIGN NUKTA + {0x11174, 0x11175, prN}, // Po [2] MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK + {0x11176, 0x11176, prN}, // Lo MAHAJANI LIGATURE SHRI + {0x11180, 0x11181, prN}, // Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA + {0x11182, 0x11182, prN}, // Mc SHARADA SIGN VISARGA + {0x11183, 0x111B2, prN}, // Lo [48] SHARADA LETTER A..SHARADA LETTER HA + {0x111B3, 0x111B5, prN}, // Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II + {0x111B6, 0x111BE, prN}, // Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O + {0x111BF, 0x111C0, prN}, // Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA + {0x111C1, 0x111C4, prN}, // Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM + {0x111C5, 0x111C8, prN}, // Po [4] SHARADA DANDA..SHARADA SEPARATOR + {0x111C9, 0x111CC, prN}, // Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK + {0x111CD, 0x111CD, prN}, // Po SHARADA SUTRA MARK + {0x111CE, 0x111CE, prN}, // Mc SHARADA VOWEL SIGN PRISHTHAMATRA E + {0x111CF, 0x111CF, prN}, // Mn SHARADA SIGN INVERTED CANDRABINDU + {0x111D0, 0x111D9, prN}, // Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE + {0x111DA, 0x111DA, prN}, // Lo SHARADA EKAM + {0x111DB, 0x111DB, prN}, // Po SHARADA SIGN SIDDHAM + {0x111DC, 0x111DC, prN}, // Lo SHARADA HEADSTROKE + {0x111DD, 0x111DF, prN}, // Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2 + {0x111E1, 0x111F4, prN}, // No [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND + {0x11200, 0x11211, prN}, // Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA + {0x11213, 0x1122B, prN}, // Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA + {0x1122C, 0x1122E, prN}, // Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II + {0x1122F, 0x11231, prN}, // Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI + {0x11232, 0x11233, prN}, // Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU + {0x11234, 0x11234, prN}, // Mn KHOJKI SIGN ANUSVARA + {0x11235, 0x11235, prN}, // Mc KHOJKI SIGN VIRAMA + {0x11236, 0x11237, prN}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA + {0x11238, 0x1123D, prN}, // Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN + {0x1123E, 0x1123E, prN}, // Mn KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prN}, // Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prN}, // Mn KHOJKI VOWEL SIGN VOCALIC R + {0x11280, 0x11286, prN}, // Lo [7] MULTANI LETTER A..MULTANI LETTER GA + {0x11288, 0x11288, prN}, // Lo MULTANI LETTER GHA + {0x1128A, 0x1128D, prN}, // Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA + {0x1128F, 0x1129D, prN}, // Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA + {0x1129F, 0x112A8, prN}, // Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA + {0x112A9, 0x112A9, prN}, // Po MULTANI SECTION MARK + {0x112B0, 0x112DE, prN}, // Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA + {0x112DF, 0x112DF, prN}, // Mn KHUDAWADI SIGN ANUSVARA + {0x112E0, 0x112E2, prN}, // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II + {0x112E3, 0x112EA, prN}, // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA + {0x112F0, 0x112F9, prN}, // Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE + {0x11300, 0x11301, prN}, // Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU + {0x11302, 0x11303, prN}, // Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA + {0x11305, 0x1130C, prN}, // Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L + {0x1130F, 0x11310, prN}, // Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI + {0x11313, 0x11328, prN}, // Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA + {0x1132A, 0x11330, prN}, // Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA + {0x11332, 0x11333, prN}, // Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA + {0x11335, 0x11339, prN}, // Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA + {0x1133B, 0x1133C, prN}, // Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA + {0x1133D, 0x1133D, prN}, // Lo GRANTHA SIGN AVAGRAHA + {0x1133E, 0x1133F, prN}, // Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I + {0x11340, 0x11340, prN}, // Mn GRANTHA VOWEL SIGN II + {0x11341, 0x11344, prN}, // Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR + {0x11347, 0x11348, prN}, // Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI + {0x1134B, 0x1134D, prN}, // Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA + {0x11350, 0x11350, prN}, // Lo GRANTHA OM + {0x11357, 0x11357, prN}, // Mc GRANTHA AU LENGTH MARK + {0x1135D, 0x11361, prN}, // Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL + {0x11362, 0x11363, prN}, // Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL + {0x11366, 0x1136C, prN}, // Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX + {0x11370, 0x11374, prN}, // Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + {0x11400, 0x11434, prN}, // Lo [53] NEWA LETTER A..NEWA LETTER HA + {0x11435, 0x11437, prN}, // Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II + {0x11438, 0x1143F, prN}, // Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI + {0x11440, 0x11441, prN}, // Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU + {0x11442, 0x11444, prN}, // Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA + {0x11445, 0x11445, prN}, // Mc NEWA SIGN VISARGA + {0x11446, 0x11446, prN}, // Mn NEWA SIGN NUKTA + {0x11447, 0x1144A, prN}, // Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI + {0x1144B, 0x1144F, prN}, // Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN + {0x11450, 0x11459, prN}, // Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE + {0x1145A, 0x1145B, prN}, // Po [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK + {0x1145D, 0x1145D, prN}, // Po NEWA INSERTION SIGN + {0x1145E, 0x1145E, prN}, // Mn NEWA SANDHI MARK + {0x1145F, 0x11461, prN}, // Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA + {0x11480, 0x114AF, prN}, // Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA + {0x114B0, 0x114B2, prN}, // Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II + {0x114B3, 0x114B8, prN}, // Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL + {0x114B9, 0x114B9, prN}, // Mc TIRHUTA VOWEL SIGN E + {0x114BA, 0x114BA, prN}, // Mn TIRHUTA VOWEL SIGN SHORT E + {0x114BB, 0x114BE, prN}, // Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU + {0x114BF, 0x114C0, prN}, // Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA + {0x114C1, 0x114C1, prN}, // Mc TIRHUTA SIGN VISARGA + {0x114C2, 0x114C3, prN}, // Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA + {0x114C4, 0x114C5, prN}, // Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG + {0x114C6, 0x114C6, prN}, // Po TIRHUTA ABBREVIATION SIGN + {0x114C7, 0x114C7, prN}, // Lo TIRHUTA OM + {0x114D0, 0x114D9, prN}, // Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE + {0x11580, 0x115AE, prN}, // Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA + {0x115AF, 0x115B1, prN}, // Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II + {0x115B2, 0x115B5, prN}, // Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR + {0x115B8, 0x115BB, prN}, // Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU + {0x115BC, 0x115BD, prN}, // Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA + {0x115BE, 0x115BE, prN}, // Mc SIDDHAM SIGN VISARGA + {0x115BF, 0x115C0, prN}, // Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA + {0x115C1, 0x115D7, prN}, // Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES + {0x115D8, 0x115DB, prN}, // Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U + {0x115DC, 0x115DD, prN}, // Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + {0x11600, 0x1162F, prN}, // Lo [48] MODI LETTER A..MODI LETTER LLA + {0x11630, 0x11632, prN}, // Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II + {0x11633, 0x1163A, prN}, // Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI + {0x1163B, 0x1163C, prN}, // Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU + {0x1163D, 0x1163D, prN}, // Mn MODI SIGN ANUSVARA + {0x1163E, 0x1163E, prN}, // Mc MODI SIGN VISARGA + {0x1163F, 0x11640, prN}, // Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA + {0x11641, 0x11643, prN}, // Po [3] MODI DANDA..MODI ABBREVIATION SIGN + {0x11644, 0x11644, prN}, // Lo MODI SIGN HUVA + {0x11650, 0x11659, prN}, // Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE + {0x11660, 0x1166C, prN}, // Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT + {0x11680, 0x116AA, prN}, // Lo [43] TAKRI LETTER A..TAKRI LETTER RRA + {0x116AB, 0x116AB, prN}, // Mn TAKRI SIGN ANUSVARA + {0x116AC, 0x116AC, prN}, // Mc TAKRI SIGN VISARGA + {0x116AD, 0x116AD, prN}, // Mn TAKRI VOWEL SIGN AA + {0x116AE, 0x116AF, prN}, // Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II + {0x116B0, 0x116B5, prN}, // Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU + {0x116B6, 0x116B6, prN}, // Mc TAKRI SIGN VIRAMA + {0x116B7, 0x116B7, prN}, // Mn TAKRI SIGN NUKTA + {0x116B8, 0x116B8, prN}, // Lo TAKRI LETTER ARCHAIC KHA + {0x116B9, 0x116B9, prN}, // Po TAKRI ABBREVIATION SIGN + {0x116C0, 0x116C9, prN}, // Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE + {0x11700, 0x1171A, prN}, // Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA + {0x1171D, 0x1171F, prN}, // Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA + {0x11720, 0x11721, prN}, // Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA + {0x11722, 0x11725, prN}, // Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU + {0x11726, 0x11726, prN}, // Mc AHOM VOWEL SIGN E + {0x11727, 0x1172B, prN}, // Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER + {0x11730, 0x11739, prN}, // Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE + {0x1173A, 0x1173B, prN}, // No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY + {0x1173C, 0x1173E, prN}, // Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI + {0x1173F, 0x1173F, prN}, // So AHOM SYMBOL VI + {0x11740, 0x11746, prN}, // Lo [7] AHOM LETTER CA..AHOM LETTER LLA + {0x11800, 0x1182B, prN}, // Lo [44] DOGRA LETTER A..DOGRA LETTER RRA + {0x1182C, 0x1182E, prN}, // Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II + {0x1182F, 0x11837, prN}, // Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA + {0x11838, 0x11838, prN}, // Mc DOGRA SIGN VISARGA + {0x11839, 0x1183A, prN}, // Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA + {0x1183B, 0x1183B, prN}, // Po DOGRA ABBREVIATION SIGN + {0x118A0, 0x118DF, prN}, // L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO + {0x118E0, 0x118E9, prN}, // Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE + {0x118EA, 0x118F2, prN}, // No [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY + {0x118FF, 0x118FF, prN}, // Lo WARANG CITI OM + {0x11900, 0x11906, prN}, // Lo [7] DIVES AKURU LETTER A..DIVES AKURU LETTER E + {0x11909, 0x11909, prN}, // Lo DIVES AKURU LETTER O + {0x1190C, 0x11913, prN}, // Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA + {0x11915, 0x11916, prN}, // Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA + {0x11918, 0x1192F, prN}, // Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA + {0x11930, 0x11935, prN}, // Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E + {0x11937, 0x11938, prN}, // Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O + {0x1193B, 0x1193C, prN}, // Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU + {0x1193D, 0x1193D, prN}, // Mc DIVES AKURU SIGN HALANTA + {0x1193E, 0x1193E, prN}, // Mn DIVES AKURU VIRAMA + {0x1193F, 0x1193F, prN}, // Lo DIVES AKURU PREFIXED NASAL SIGN + {0x11940, 0x11940, prN}, // Mc DIVES AKURU MEDIAL YA + {0x11941, 0x11941, prN}, // Lo DIVES AKURU INITIAL RA + {0x11942, 0x11942, prN}, // Mc DIVES AKURU MEDIAL RA + {0x11943, 0x11943, prN}, // Mn DIVES AKURU SIGN NUKTA + {0x11944, 0x11946, prN}, // Po [3] DIVES AKURU DOUBLE DANDA..DIVES AKURU END OF TEXT MARK + {0x11950, 0x11959, prN}, // Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE + {0x119A0, 0x119A7, prN}, // Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR + {0x119AA, 0x119D0, prN}, // Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA + {0x119D1, 0x119D3, prN}, // Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II + {0x119D4, 0x119D7, prN}, // Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR + {0x119DA, 0x119DB, prN}, // Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI + {0x119DC, 0x119DF, prN}, // Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA + {0x119E0, 0x119E0, prN}, // Mn NANDINAGARI SIGN VIRAMA + {0x119E1, 0x119E1, prN}, // Lo NANDINAGARI SIGN AVAGRAHA + {0x119E2, 0x119E2, prN}, // Po NANDINAGARI SIGN SIDDHAM + {0x119E3, 0x119E3, prN}, // Lo NANDINAGARI HEADSTROKE + {0x119E4, 0x119E4, prN}, // Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E + {0x11A00, 0x11A00, prN}, // Lo ZANABAZAR SQUARE LETTER A + {0x11A01, 0x11A0A, prN}, // Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK + {0x11A0B, 0x11A32, prN}, // Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA + {0x11A33, 0x11A38, prN}, // Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA + {0x11A39, 0x11A39, prN}, // Mc ZANABAZAR SQUARE SIGN VISARGA + {0x11A3A, 0x11A3A, prN}, // Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA + {0x11A3B, 0x11A3E, prN}, // Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA + {0x11A3F, 0x11A46, prN}, // Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK + {0x11A47, 0x11A47, prN}, // Mn ZANABAZAR SQUARE SUBJOINER + {0x11A50, 0x11A50, prN}, // Lo SOYOMBO LETTER A + {0x11A51, 0x11A56, prN}, // Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE + {0x11A57, 0x11A58, prN}, // Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU + {0x11A59, 0x11A5B, prN}, // Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK + {0x11A5C, 0x11A89, prN}, // Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA + {0x11A8A, 0x11A96, prN}, // Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA + {0x11A97, 0x11A97, prN}, // Mc SOYOMBO SIGN VISARGA + {0x11A98, 0x11A99, prN}, // Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER + {0x11A9A, 0x11A9C, prN}, // Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD + {0x11A9D, 0x11A9D, prN}, // Lo SOYOMBO MARK PLUTA + {0x11A9E, 0x11AA2, prN}, // Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2 + {0x11AB0, 0x11ABF, prN}, // Lo [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA + {0x11AC0, 0x11AF8, prN}, // Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL + {0x11B00, 0x11B09, prN}, // Po [10] DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU + {0x11C00, 0x11C08, prN}, // Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L + {0x11C0A, 0x11C2E, prN}, // Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA + {0x11C2F, 0x11C2F, prN}, // Mc BHAIKSUKI VOWEL SIGN AA + {0x11C30, 0x11C36, prN}, // Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L + {0x11C38, 0x11C3D, prN}, // Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA + {0x11C3E, 0x11C3E, prN}, // Mc BHAIKSUKI SIGN VISARGA + {0x11C3F, 0x11C3F, prN}, // Mn BHAIKSUKI SIGN VIRAMA + {0x11C40, 0x11C40, prN}, // Lo BHAIKSUKI SIGN AVAGRAHA + {0x11C41, 0x11C45, prN}, // Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2 + {0x11C50, 0x11C59, prN}, // Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE + {0x11C5A, 0x11C6C, prN}, // No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK + {0x11C70, 0x11C71, prN}, // Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD + {0x11C72, 0x11C8F, prN}, // Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A + {0x11C92, 0x11CA7, prN}, // Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA + {0x11CA9, 0x11CA9, prN}, // Mc MARCHEN SUBJOINED LETTER YA + {0x11CAA, 0x11CB0, prN}, // Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA + {0x11CB1, 0x11CB1, prN}, // Mc MARCHEN VOWEL SIGN I + {0x11CB2, 0x11CB3, prN}, // Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E + {0x11CB4, 0x11CB4, prN}, // Mc MARCHEN VOWEL SIGN O + {0x11CB5, 0x11CB6, prN}, // Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + {0x11D00, 0x11D06, prN}, // Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E + {0x11D08, 0x11D09, prN}, // Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O + {0x11D0B, 0x11D30, prN}, // Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA + {0x11D31, 0x11D36, prN}, // Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R + {0x11D3A, 0x11D3A, prN}, // Mn MASARAM GONDI VOWEL SIGN E + {0x11D3C, 0x11D3D, prN}, // Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O + {0x11D3F, 0x11D45, prN}, // Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA + {0x11D46, 0x11D46, prN}, // Lo MASARAM GONDI REPHA + {0x11D47, 0x11D47, prN}, // Mn MASARAM GONDI RA-KARA + {0x11D50, 0x11D59, prN}, // Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE + {0x11D60, 0x11D65, prN}, // Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU + {0x11D67, 0x11D68, prN}, // Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI + {0x11D6A, 0x11D89, prN}, // Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA + {0x11D8A, 0x11D8E, prN}, // Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU + {0x11D90, 0x11D91, prN}, // Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI + {0x11D93, 0x11D94, prN}, // Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU + {0x11D95, 0x11D95, prN}, // Mn GUNJALA GONDI SIGN ANUSVARA + {0x11D96, 0x11D96, prN}, // Mc GUNJALA GONDI SIGN VISARGA + {0x11D97, 0x11D97, prN}, // Mn GUNJALA GONDI VIRAMA + {0x11D98, 0x11D98, prN}, // Lo GUNJALA GONDI OM + {0x11DA0, 0x11DA9, prN}, // Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE + {0x11EE0, 0x11EF2, prN}, // Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA + {0x11EF3, 0x11EF4, prN}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U + {0x11EF5, 0x11EF6, prN}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x11EF7, 0x11EF8, prN}, // Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION + {0x11F00, 0x11F01, prN}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prN}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prN}, // Mc KAWI SIGN VISARGA + {0x11F04, 0x11F10, prN}, // Lo [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prN}, // Lo [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prN}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prN}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prN}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prN}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prN}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prN}, // Mn KAWI CONJOINER + {0x11F43, 0x11F4F, prN}, // Po [13] KAWI DANDA..KAWI PUNCTUATION CLOSING SPIRAL + {0x11F50, 0x11F59, prN}, // Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE + {0x11FB0, 0x11FB0, prN}, // Lo LISU LETTER YHA + {0x11FC0, 0x11FD4, prN}, // No [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH + {0x11FD5, 0x11FDC, prN}, // So [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI + {0x11FDD, 0x11FE0, prN}, // Sc [4] TAMIL SIGN KAACU..TAMIL SIGN VARAAKAN + {0x11FE1, 0x11FF1, prN}, // So [17] TAMIL SIGN PAARAM..TAMIL SIGN VAKAIYARAA + {0x11FFF, 0x11FFF, prN}, // Po TAMIL PUNCTUATION END OF TEXT + {0x12000, 0x12399, prN}, // Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U + {0x12400, 0x1246E, prN}, // Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM + {0x12470, 0x12474, prN}, // Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON + {0x12480, 0x12543, prN}, // Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU + {0x12F90, 0x12FF0, prN}, // Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 + {0x12FF1, 0x12FF2, prN}, // Po [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302 + {0x13000, 0x1342F, prN}, // Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x1343F, prN}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prN}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prN}, // Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prN}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED + {0x14400, 0x14646, prN}, // Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 + {0x16800, 0x16A38, prN}, // Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ + {0x16A40, 0x16A5E, prN}, // Lo [31] MRO LETTER TA..MRO LETTER TEK + {0x16A60, 0x16A69, prN}, // Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE + {0x16A6E, 0x16A6F, prN}, // Po [2] MRO DANDA..MRO DOUBLE DANDA + {0x16A70, 0x16ABE, prN}, // Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA + {0x16AC0, 0x16AC9, prN}, // Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE + {0x16AD0, 0x16AED, prN}, // Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I + {0x16AF0, 0x16AF4, prN}, // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE + {0x16AF5, 0x16AF5, prN}, // Po BASSA VAH FULL STOP + {0x16B00, 0x16B2F, prN}, // Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU + {0x16B30, 0x16B36, prN}, // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM + {0x16B37, 0x16B3B, prN}, // Po [5] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS FEEM + {0x16B3C, 0x16B3F, prN}, // So [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB + {0x16B40, 0x16B43, prN}, // Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM + {0x16B44, 0x16B44, prN}, // Po PAHAWH HMONG SIGN XAUS + {0x16B45, 0x16B45, prN}, // So PAHAWH HMONG SIGN CIM TSOV ROG + {0x16B50, 0x16B59, prN}, // Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE + {0x16B5B, 0x16B61, prN}, // No [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS + {0x16B63, 0x16B77, prN}, // Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS + {0x16B7D, 0x16B8F, prN}, // Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ + {0x16E40, 0x16E7F, prN}, // L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y + {0x16E80, 0x16E96, prN}, // No [23] MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN DIGIT THREE ALTERNATE FORM + {0x16E97, 0x16E9A, prN}, // Po [4] MEDEFAIDRIN COMMA..MEDEFAIDRIN EXCLAMATION OH + {0x16F00, 0x16F4A, prN}, // Lo [75] MIAO LETTER PA..MIAO LETTER RTE + {0x16F4F, 0x16F4F, prN}, // Mn MIAO SIGN CONSONANT MODIFIER BAR + {0x16F50, 0x16F50, prN}, // Lo MIAO LETTER NASALIZATION + {0x16F51, 0x16F87, prN}, // Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI + {0x16F8F, 0x16F92, prN}, // Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW + {0x16F93, 0x16F9F, prN}, // Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 + {0x16FE0, 0x16FE1, prW}, // Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK + {0x16FE2, 0x16FE2, prW}, // Po OLD CHINESE HOOK MARK + {0x16FE3, 0x16FE3, prW}, // Lm OLD CHINESE ITERATION MARK + {0x16FE4, 0x16FE4, prW}, // Mn KHITAN SMALL SCRIPT FILLER + {0x16FF0, 0x16FF1, prW}, // Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY + {0x17000, 0x187F7, prW}, // Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 + {0x18800, 0x18AFF, prW}, // Lo [768] TANGUT COMPONENT-001..TANGUT COMPONENT-768 + {0x18B00, 0x18CD5, prW}, // Lo [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5 + {0x18D00, 0x18D08, prW}, // Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 + {0x1AFF0, 0x1AFF3, prW}, // Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 + {0x1AFF5, 0x1AFFB, prW}, // Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 + {0x1AFFD, 0x1AFFE, prW}, // Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 + {0x1B000, 0x1B0FF, prW}, // Lo [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2 + {0x1B100, 0x1B122, prW}, // Lo [35] HENTAIGANA LETTER RE-3..KATAKANA LETTER ARCHAIC WU + {0x1B132, 0x1B132, prW}, // Lo HIRAGANA LETTER SMALL KO + {0x1B150, 0x1B152, prW}, // Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO + {0x1B155, 0x1B155, prW}, // Lo KATAKANA LETTER SMALL KO + {0x1B164, 0x1B167, prW}, // Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N + {0x1B170, 0x1B2FB, prW}, // Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB + {0x1BC00, 0x1BC6A, prN}, // Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M + {0x1BC70, 0x1BC7C, prN}, // Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK + {0x1BC80, 0x1BC88, prN}, // Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL + {0x1BC90, 0x1BC99, prN}, // Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW + {0x1BC9C, 0x1BC9C, prN}, // So DUPLOYAN SIGN O WITH CROSS + {0x1BC9D, 0x1BC9E, prN}, // Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK + {0x1BC9F, 0x1BC9F, prN}, // Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP + {0x1BCA0, 0x1BCA3, prN}, // Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP + {0x1CF00, 0x1CF2D, prN}, // Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT + {0x1CF30, 0x1CF46, prN}, // Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG + {0x1CF50, 0x1CFC3, prN}, // So [116] ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK + {0x1D000, 0x1D0F5, prN}, // So [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO + {0x1D100, 0x1D126, prN}, // So [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2 + {0x1D129, 0x1D164, prN}, // So [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE + {0x1D165, 0x1D166, prN}, // Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM + {0x1D167, 0x1D169, prN}, // Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 + {0x1D16A, 0x1D16C, prN}, // So [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3 + {0x1D16D, 0x1D172, prN}, // Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 + {0x1D173, 0x1D17A, prN}, // Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE + {0x1D17B, 0x1D182, prN}, // Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE + {0x1D183, 0x1D184, prN}, // So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN + {0x1D185, 0x1D18B, prN}, // Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE + {0x1D18C, 0x1D1A9, prN}, // So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH + {0x1D1AA, 0x1D1AD, prN}, // Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO + {0x1D1AE, 0x1D1EA, prN}, // So [61] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KORON + {0x1D200, 0x1D241, prN}, // So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 + {0x1D242, 0x1D244, prN}, // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME + {0x1D245, 0x1D245, prN}, // So GREEK MUSICAL LEIMMA + {0x1D2C0, 0x1D2D3, prN}, // No [20] KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN + {0x1D2E0, 0x1D2F3, prN}, // No [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN + {0x1D300, 0x1D356, prN}, // So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING + {0x1D360, 0x1D378, prN}, // No [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE + {0x1D400, 0x1D454, prN}, // L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G + {0x1D456, 0x1D49C, prN}, // L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A + {0x1D49E, 0x1D49F, prN}, // Lu [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D + {0x1D4A2, 0x1D4A2, prN}, // Lu MATHEMATICAL SCRIPT CAPITAL G + {0x1D4A5, 0x1D4A6, prN}, // Lu [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K + {0x1D4A9, 0x1D4AC, prN}, // Lu [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q + {0x1D4AE, 0x1D4B9, prN}, // L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D + {0x1D4BB, 0x1D4BB, prN}, // Ll MATHEMATICAL SCRIPT SMALL F + {0x1D4BD, 0x1D4C3, prN}, // Ll [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N + {0x1D4C5, 0x1D505, prN}, // L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B + {0x1D507, 0x1D50A, prN}, // Lu [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G + {0x1D50D, 0x1D514, prN}, // Lu [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q + {0x1D516, 0x1D51C, prN}, // Lu [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y + {0x1D51E, 0x1D539, prN}, // L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B + {0x1D53B, 0x1D53E, prN}, // Lu [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G + {0x1D540, 0x1D544, prN}, // Lu [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M + {0x1D546, 0x1D546, prN}, // Lu MATHEMATICAL DOUBLE-STRUCK CAPITAL O + {0x1D54A, 0x1D550, prN}, // Lu [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y + {0x1D552, 0x1D6A5, prN}, // L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J + {0x1D6A8, 0x1D6C0, prN}, // Lu [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA + {0x1D6C1, 0x1D6C1, prN}, // Sm MATHEMATICAL BOLD NABLA + {0x1D6C2, 0x1D6DA, prN}, // Ll [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA + {0x1D6DB, 0x1D6DB, prN}, // Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL + {0x1D6DC, 0x1D6FA, prN}, // L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA + {0x1D6FB, 0x1D6FB, prN}, // Sm MATHEMATICAL ITALIC NABLA + {0x1D6FC, 0x1D714, prN}, // Ll [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA + {0x1D715, 0x1D715, prN}, // Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL + {0x1D716, 0x1D734, prN}, // L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA + {0x1D735, 0x1D735, prN}, // Sm MATHEMATICAL BOLD ITALIC NABLA + {0x1D736, 0x1D74E, prN}, // Ll [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA + {0x1D74F, 0x1D74F, prN}, // Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL + {0x1D750, 0x1D76E, prN}, // L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA + {0x1D76F, 0x1D76F, prN}, // Sm MATHEMATICAL SANS-SERIF BOLD NABLA + {0x1D770, 0x1D788, prN}, // Ll [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA + {0x1D789, 0x1D789, prN}, // Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL + {0x1D78A, 0x1D7A8, prN}, // L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA + {0x1D7A9, 0x1D7A9, prN}, // Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA + {0x1D7AA, 0x1D7C2, prN}, // Ll [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA + {0x1D7C3, 0x1D7C3, prN}, // Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL + {0x1D7C4, 0x1D7CB, prN}, // L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA + {0x1D7CE, 0x1D7FF, prN}, // Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE + {0x1D800, 0x1D9FF, prN}, // So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD + {0x1DA00, 0x1DA36, prN}, // Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN + {0x1DA37, 0x1DA3A, prN}, // So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE + {0x1DA3B, 0x1DA6C, prN}, // Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT + {0x1DA6D, 0x1DA74, prN}, // So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING + {0x1DA75, 0x1DA75, prN}, // Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS + {0x1DA76, 0x1DA83, prN}, // So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH + {0x1DA84, 0x1DA84, prN}, // Mn SIGNWRITING LOCATION HEAD NECK + {0x1DA85, 0x1DA86, prN}, // So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS + {0x1DA87, 0x1DA8B, prN}, // Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS + {0x1DA9B, 0x1DA9F, prN}, // Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 + {0x1DAA1, 0x1DAAF, prN}, // Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + {0x1DF00, 0x1DF09, prN}, // Ll [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK + {0x1DF0A, 0x1DF0A, prN}, // Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK + {0x1DF0B, 0x1DF1E, prN}, // Ll [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prN}, // Ll [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK + {0x1E000, 0x1E006, prN}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE + {0x1E008, 0x1E018, prN}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU + {0x1E01B, 0x1E021, prN}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI + {0x1E023, 0x1E024, prN}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS + {0x1E026, 0x1E02A, prN}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prN}, // Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prN}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + {0x1E100, 0x1E12C, prN}, // Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W + {0x1E130, 0x1E136, prN}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D + {0x1E137, 0x1E13D, prN}, // Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER + {0x1E140, 0x1E149, prN}, // Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE + {0x1E14E, 0x1E14E, prN}, // Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ + {0x1E14F, 0x1E14F, prN}, // So NYIAKENG PUACHUE HMONG CIRCLED CA + {0x1E290, 0x1E2AD, prN}, // Lo [30] TOTO LETTER PA..TOTO LETTER A + {0x1E2AE, 0x1E2AE, prN}, // Mn TOTO SIGN RISING TONE + {0x1E2C0, 0x1E2EB, prN}, // Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH + {0x1E2EC, 0x1E2EF, prN}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E2F0, 0x1E2F9, prN}, // Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE + {0x1E2FF, 0x1E2FF, prN}, // Sc WANCHO NGUN SIGN + {0x1E4D0, 0x1E4EA, prN}, // Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prN}, // Lm NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prN}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prN}, // Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE + {0x1E7E0, 0x1E7E6, prN}, // Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO + {0x1E7E8, 0x1E7EB, prN}, // Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE + {0x1E7ED, 0x1E7EE, prN}, // Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE + {0x1E7F0, 0x1E7FE, prN}, // Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE + {0x1E800, 0x1E8C4, prN}, // Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON + {0x1E8C7, 0x1E8CF, prN}, // No [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE + {0x1E8D0, 0x1E8D6, prN}, // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + {0x1E900, 0x1E943, prN}, // L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA + {0x1E944, 0x1E94A, prN}, // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA + {0x1E94B, 0x1E94B, prN}, // Lm ADLAM NASALIZATION MARK + {0x1E950, 0x1E959, prN}, // Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE + {0x1E95E, 0x1E95F, prN}, // Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK + {0x1EC71, 0x1ECAB, prN}, // No [59] INDIC SIYAQ NUMBER ONE..INDIC SIYAQ NUMBER PREFIXED NINE + {0x1ECAC, 0x1ECAC, prN}, // So INDIC SIYAQ PLACEHOLDER + {0x1ECAD, 0x1ECAF, prN}, // No [3] INDIC SIYAQ FRACTION ONE QUARTER..INDIC SIYAQ FRACTION THREE QUARTERS + {0x1ECB0, 0x1ECB0, prN}, // Sc INDIC SIYAQ RUPEE MARK + {0x1ECB1, 0x1ECB4, prN}, // No [4] INDIC SIYAQ NUMBER ALTERNATE ONE..INDIC SIYAQ ALTERNATE LAKH MARK + {0x1ED01, 0x1ED2D, prN}, // No [45] OTTOMAN SIYAQ NUMBER ONE..OTTOMAN SIYAQ NUMBER NINETY THOUSAND + {0x1ED2E, 0x1ED2E, prN}, // So OTTOMAN SIYAQ MARRATAN + {0x1ED2F, 0x1ED3D, prN}, // No [15] OTTOMAN SIYAQ ALTERNATE NUMBER TWO..OTTOMAN SIYAQ FRACTION ONE SIXTH + {0x1EE00, 0x1EE03, prN}, // Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL + {0x1EE05, 0x1EE1F, prN}, // Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF + {0x1EE21, 0x1EE22, prN}, // Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM + {0x1EE24, 0x1EE24, prN}, // Lo ARABIC MATHEMATICAL INITIAL HEH + {0x1EE27, 0x1EE27, prN}, // Lo ARABIC MATHEMATICAL INITIAL HAH + {0x1EE29, 0x1EE32, prN}, // Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF + {0x1EE34, 0x1EE37, prN}, // Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH + {0x1EE39, 0x1EE39, prN}, // Lo ARABIC MATHEMATICAL INITIAL DAD + {0x1EE3B, 0x1EE3B, prN}, // Lo ARABIC MATHEMATICAL INITIAL GHAIN + {0x1EE42, 0x1EE42, prN}, // Lo ARABIC MATHEMATICAL TAILED JEEM + {0x1EE47, 0x1EE47, prN}, // Lo ARABIC MATHEMATICAL TAILED HAH + {0x1EE49, 0x1EE49, prN}, // Lo ARABIC MATHEMATICAL TAILED YEH + {0x1EE4B, 0x1EE4B, prN}, // Lo ARABIC MATHEMATICAL TAILED LAM + {0x1EE4D, 0x1EE4F, prN}, // Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN + {0x1EE51, 0x1EE52, prN}, // Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF + {0x1EE54, 0x1EE54, prN}, // Lo ARABIC MATHEMATICAL TAILED SHEEN + {0x1EE57, 0x1EE57, prN}, // Lo ARABIC MATHEMATICAL TAILED KHAH + {0x1EE59, 0x1EE59, prN}, // Lo ARABIC MATHEMATICAL TAILED DAD + {0x1EE5B, 0x1EE5B, prN}, // Lo ARABIC MATHEMATICAL TAILED GHAIN + {0x1EE5D, 0x1EE5D, prN}, // Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON + {0x1EE5F, 0x1EE5F, prN}, // Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF + {0x1EE61, 0x1EE62, prN}, // Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM + {0x1EE64, 0x1EE64, prN}, // Lo ARABIC MATHEMATICAL STRETCHED HEH + {0x1EE67, 0x1EE6A, prN}, // Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF + {0x1EE6C, 0x1EE72, prN}, // Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF + {0x1EE74, 0x1EE77, prN}, // Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH + {0x1EE79, 0x1EE7C, prN}, // Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH + {0x1EE7E, 0x1EE7E, prN}, // Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH + {0x1EE80, 0x1EE89, prN}, // Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH + {0x1EE8B, 0x1EE9B, prN}, // Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN + {0x1EEA1, 0x1EEA3, prN}, // Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL + {0x1EEA5, 0x1EEA9, prN}, // Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH + {0x1EEAB, 0x1EEBB, prN}, // Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN + {0x1EEF0, 0x1EEF1, prN}, // Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL + {0x1F000, 0x1F003, prN}, // So [4] MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND + {0x1F004, 0x1F004, prW}, // So MAHJONG TILE RED DRAGON + {0x1F005, 0x1F02B, prN}, // So [39] MAHJONG TILE GREEN DRAGON..MAHJONG TILE BACK + {0x1F030, 0x1F093, prN}, // So [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06 + {0x1F0A0, 0x1F0AE, prN}, // So [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES + {0x1F0B1, 0x1F0BF, prN}, // So [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER + {0x1F0C1, 0x1F0CE, prN}, // So [14] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD KING OF DIAMONDS + {0x1F0CF, 0x1F0CF, prW}, // So PLAYING CARD BLACK JOKER + {0x1F0D1, 0x1F0F5, prN}, // So [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21 + {0x1F100, 0x1F10A, prA}, // No [11] DIGIT ZERO FULL STOP..DIGIT NINE COMMA + {0x1F10B, 0x1F10C, prN}, // No [2] DINGBAT CIRCLED SANS-SERIF DIGIT ZERO..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO + {0x1F10D, 0x1F10F, prN}, // So [3] CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH + {0x1F110, 0x1F12D, prA}, // So [30] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED CD + {0x1F12E, 0x1F12F, prN}, // So [2] CIRCLED WZ..COPYLEFT SYMBOL + {0x1F130, 0x1F169, prA}, // So [58] SQUARED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z + {0x1F16A, 0x1F16F, prN}, // So [6] RAISED MC SIGN..CIRCLED HUMAN FIGURE + {0x1F170, 0x1F18D, prA}, // So [30] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED SA + {0x1F18E, 0x1F18E, prW}, // So NEGATIVE SQUARED AB + {0x1F18F, 0x1F190, prA}, // So [2] NEGATIVE SQUARED WC..SQUARE DJ + {0x1F191, 0x1F19A, prW}, // So [10] SQUARED CL..SQUARED VS + {0x1F19B, 0x1F1AC, prA}, // So [18] SQUARED THREE D..SQUARED VOD + {0x1F1AD, 0x1F1AD, prN}, // So MASK WORK SYMBOL + {0x1F1E6, 0x1F1FF, prN}, // So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + {0x1F200, 0x1F202, prW}, // So [3] SQUARE HIRAGANA HOKA..SQUARED KATAKANA SA + {0x1F210, 0x1F23B, prW}, // So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D + {0x1F240, 0x1F248, prW}, // So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 + {0x1F250, 0x1F251, prW}, // So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT + {0x1F260, 0x1F265, prW}, // So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI + {0x1F300, 0x1F320, prW}, // So [33] CYCLONE..SHOOTING STAR + {0x1F321, 0x1F32C, prN}, // So [12] THERMOMETER..WIND BLOWING FACE + {0x1F32D, 0x1F335, prW}, // So [9] HOT DOG..CACTUS + {0x1F336, 0x1F336, prN}, // So HOT PEPPER + {0x1F337, 0x1F37C, prW}, // So [70] TULIP..BABY BOTTLE + {0x1F37D, 0x1F37D, prN}, // So FORK AND KNIFE WITH PLATE + {0x1F37E, 0x1F393, prW}, // So [22] BOTTLE WITH POPPING CORK..GRADUATION CAP + {0x1F394, 0x1F39F, prN}, // So [12] HEART WITH TIP ON THE LEFT..ADMISSION TICKETS + {0x1F3A0, 0x1F3CA, prW}, // So [43] CAROUSEL HORSE..SWIMMER + {0x1F3CB, 0x1F3CE, prN}, // So [4] WEIGHT LIFTER..RACING CAR + {0x1F3CF, 0x1F3D3, prW}, // So [5] CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL + {0x1F3D4, 0x1F3DF, prN}, // So [12] SNOW CAPPED MOUNTAIN..STADIUM + {0x1F3E0, 0x1F3F0, prW}, // So [17] HOUSE BUILDING..EUROPEAN CASTLE + {0x1F3F1, 0x1F3F3, prN}, // So [3] WHITE PENNANT..WAVING WHITE FLAG + {0x1F3F4, 0x1F3F4, prW}, // So WAVING BLACK FLAG + {0x1F3F5, 0x1F3F7, prN}, // So [3] ROSETTE..LABEL + {0x1F3F8, 0x1F3FA, prW}, // So [3] BADMINTON RACQUET AND SHUTTLECOCK..AMPHORA + {0x1F3FB, 0x1F3FF, prW}, // Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 + {0x1F400, 0x1F43E, prW}, // So [63] RAT..PAW PRINTS + {0x1F43F, 0x1F43F, prN}, // So CHIPMUNK + {0x1F440, 0x1F440, prW}, // So EYES + {0x1F441, 0x1F441, prN}, // So EYE + {0x1F442, 0x1F4FC, prW}, // So [187] EAR..VIDEOCASSETTE + {0x1F4FD, 0x1F4FE, prN}, // So [2] FILM PROJECTOR..PORTABLE STEREO + {0x1F4FF, 0x1F53D, prW}, // So [63] PRAYER BEADS..DOWN-POINTING SMALL RED TRIANGLE + {0x1F53E, 0x1F54A, prN}, // So [13] LOWER RIGHT SHADOWED WHITE CIRCLE..DOVE OF PEACE + {0x1F54B, 0x1F54E, prW}, // So [4] KAABA..MENORAH WITH NINE BRANCHES + {0x1F54F, 0x1F54F, prN}, // So BOWL OF HYGIEIA + {0x1F550, 0x1F567, prW}, // So [24] CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY + {0x1F568, 0x1F579, prN}, // So [18] RIGHT SPEAKER..JOYSTICK + {0x1F57A, 0x1F57A, prW}, // So MAN DANCING + {0x1F57B, 0x1F594, prN}, // So [26] LEFT HAND TELEPHONE RECEIVER..REVERSED VICTORY HAND + {0x1F595, 0x1F596, prW}, // So [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS + {0x1F597, 0x1F5A3, prN}, // So [13] WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX + {0x1F5A4, 0x1F5A4, prW}, // So BLACK HEART + {0x1F5A5, 0x1F5FA, prN}, // So [86] DESKTOP COMPUTER..WORLD MAP + {0x1F5FB, 0x1F5FF, prW}, // So [5] MOUNT FUJI..MOYAI + {0x1F600, 0x1F64F, prW}, // So [80] GRINNING FACE..PERSON WITH FOLDED HANDS + {0x1F650, 0x1F67F, prN}, // So [48] NORTH WEST POINTING LEAF..REVERSE CHECKER BOARD + {0x1F680, 0x1F6C5, prW}, // So [70] ROCKET..LEFT LUGGAGE + {0x1F6C6, 0x1F6CB, prN}, // So [6] TRIANGLE WITH ROUNDED CORNERS..COUCH AND LAMP + {0x1F6CC, 0x1F6CC, prW}, // So SLEEPING ACCOMMODATION + {0x1F6CD, 0x1F6CF, prN}, // So [3] SHOPPING BAGS..BED + {0x1F6D0, 0x1F6D2, prW}, // So [3] PLACE OF WORSHIP..SHOPPING TROLLEY + {0x1F6D3, 0x1F6D4, prN}, // So [2] STUPA..PAGODA + {0x1F6D5, 0x1F6D7, prW}, // So [3] HINDU TEMPLE..ELEVATOR + {0x1F6DC, 0x1F6DF, prW}, // So [4] WIRELESS..RING BUOY + {0x1F6E0, 0x1F6EA, prN}, // So [11] HAMMER AND WRENCH..NORTHEAST-POINTING AIRPLANE + {0x1F6EB, 0x1F6EC, prW}, // So [2] AIRPLANE DEPARTURE..AIRPLANE ARRIVING + {0x1F6F0, 0x1F6F3, prN}, // So [4] SATELLITE..PASSENGER SHIP + {0x1F6F4, 0x1F6FC, prW}, // So [9] SCOOTER..ROLLER SKATE + {0x1F700, 0x1F776, prN}, // So [119] ALCHEMICAL SYMBOL FOR QUINTESSENCE..LUNAR ECLIPSE + {0x1F77B, 0x1F77F, prN}, // So [5] HAUMEA..ORCUS + {0x1F780, 0x1F7D9, prN}, // So [90] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NINE POINTED WHITE STAR + {0x1F7E0, 0x1F7EB, prW}, // So [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE + {0x1F7F0, 0x1F7F0, prW}, // So HEAVY EQUALS SIGN + {0x1F800, 0x1F80B, prN}, // So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD + {0x1F810, 0x1F847, prN}, // So [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW + {0x1F850, 0x1F859, prN}, // So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW + {0x1F860, 0x1F887, prN}, // So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW + {0x1F890, 0x1F8AD, prN}, // So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS + {0x1F8B0, 0x1F8B1, prN}, // So [2] ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST + {0x1F900, 0x1F90B, prN}, // So [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT + {0x1F90C, 0x1F93A, prW}, // So [47] PINCHED FINGERS..FENCER + {0x1F93B, 0x1F93B, prN}, // So MODERN PENTATHLON + {0x1F93C, 0x1F945, prW}, // So [10] WRESTLERS..GOAL NET + {0x1F946, 0x1F946, prN}, // So RIFLE + {0x1F947, 0x1F9FF, prW}, // So [185] FIRST PLACE MEDAL..NAZAR AMULET + {0x1FA00, 0x1FA53, prN}, // So [84] NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP + {0x1FA60, 0x1FA6D, prN}, // So [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER + {0x1FA70, 0x1FA7C, prW}, // So [13] BALLET SHOES..CRUTCH + {0x1FA80, 0x1FA88, prW}, // So [9] YO-YO..FLUTE + {0x1FA90, 0x1FABD, prW}, // So [46] RINGED PLANET..WING + {0x1FABF, 0x1FAC5, prW}, // So [7] GOOSE..PERSON WITH CROWN + {0x1FACE, 0x1FADB, prW}, // So [14] MOOSE..PEA POD + {0x1FAE0, 0x1FAE8, prW}, // So [9] MELTING FACE..SHAKING FACE + {0x1FAF0, 0x1FAF8, prW}, // So [9] HAND WITH INDEX FINGER AND THUMB CROSSED..RIGHTWARDS PUSHING HAND + {0x1FB00, 0x1FB92, prN}, // So [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK + {0x1FB94, 0x1FBCA, prN}, // So [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON + {0x1FBF0, 0x1FBF9, prN}, // Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE + {0x20000, 0x2A6DF, prW}, // Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF + {0x2A6E0, 0x2A6FF, prW}, // Cn [32] .. + {0x2A700, 0x2B739, prW}, // Lo [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739 + {0x2B73A, 0x2B73F, prW}, // Cn [6] .. + {0x2B740, 0x2B81D, prW}, // Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D + {0x2B81E, 0x2B81F, prW}, // Cn [2] .. + {0x2B820, 0x2CEA1, prW}, // Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 + {0x2CEA2, 0x2CEAF, prW}, // Cn [14] .. + {0x2CEB0, 0x2EBE0, prW}, // Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 + {0x2EBE1, 0x2F7FF, prW}, // Cn [3103] .. + {0x2F800, 0x2FA1D, prW}, // Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D + {0x2FA1E, 0x2FA1F, prW}, // Cn [2] .. + {0x2FA20, 0x2FFFD, prW}, // Cn [1502] .. + {0x30000, 0x3134A, prW}, // Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A + {0x3134B, 0x3134F, prW}, // Cn [5] .. + {0x31350, 0x323AF, prW}, // Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF + {0x323B0, 0x3FFFD, prW}, // Cn [56398] .. + {0xE0001, 0xE0001, prN}, // Cf LANGUAGE TAG + {0xE0020, 0xE007F, prN}, // Cf [96] TAG SPACE..CANCEL TAG + {0xE0100, 0xE01EF, prA}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + {0xF0000, 0xFFFFD, prA}, // Co [65534] .. + {0x100000, 0x10FFFD, prA}, // Co [65534] .. +} diff --git a/vendor/github.com/rivo/uniseg/emojipresentation.go b/vendor/github.com/rivo/uniseg/emojipresentation.go new file mode 100644 index 000000000..9b5f499c4 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/emojipresentation.go @@ -0,0 +1,295 @@ +// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// emojiPresentation are taken from +// +// and +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt +// ("Extended_Pictographic" only) +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var emojiPresentation = [][3]int{ + {0x231A, 0x231B, prEmojiPresentation}, // E0.6 [2] (⌚..⌛) watch..hourglass done + {0x23E9, 0x23EC, prEmojiPresentation}, // E0.6 [4] (⏩..⏬) fast-forward button..fast down button + {0x23F0, 0x23F0, prEmojiPresentation}, // E0.6 [1] (⏰) alarm clock + {0x23F3, 0x23F3, prEmojiPresentation}, // E0.6 [1] (⏳) hourglass not done + {0x25FD, 0x25FE, prEmojiPresentation}, // E0.6 [2] (◽..◾) white medium-small square..black medium-small square + {0x2614, 0x2615, prEmojiPresentation}, // E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage + {0x2648, 0x2653, prEmojiPresentation}, // E0.6 [12] (♈..♓) Aries..Pisces + {0x267F, 0x267F, prEmojiPresentation}, // E0.6 [1] (♿) wheelchair symbol + {0x2693, 0x2693, prEmojiPresentation}, // E0.6 [1] (⚓) anchor + {0x26A1, 0x26A1, prEmojiPresentation}, // E0.6 [1] (⚡) high voltage + {0x26AA, 0x26AB, prEmojiPresentation}, // E0.6 [2] (⚪..⚫) white circle..black circle + {0x26BD, 0x26BE, prEmojiPresentation}, // E0.6 [2] (⚽..⚾) soccer ball..baseball + {0x26C4, 0x26C5, prEmojiPresentation}, // E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud + {0x26CE, 0x26CE, prEmojiPresentation}, // E0.6 [1] (⛎) Ophiuchus + {0x26D4, 0x26D4, prEmojiPresentation}, // E0.6 [1] (⛔) no entry + {0x26EA, 0x26EA, prEmojiPresentation}, // E0.6 [1] (⛪) church + {0x26F2, 0x26F3, prEmojiPresentation}, // E0.6 [2] (⛲..⛳) fountain..flag in hole + {0x26F5, 0x26F5, prEmojiPresentation}, // E0.6 [1] (⛵) sailboat + {0x26FA, 0x26FA, prEmojiPresentation}, // E0.6 [1] (⛺) tent + {0x26FD, 0x26FD, prEmojiPresentation}, // E0.6 [1] (⛽) fuel pump + {0x2705, 0x2705, prEmojiPresentation}, // E0.6 [1] (✅) check mark button + {0x270A, 0x270B, prEmojiPresentation}, // E0.6 [2] (✊..✋) raised fist..raised hand + {0x2728, 0x2728, prEmojiPresentation}, // E0.6 [1] (✨) sparkles + {0x274C, 0x274C, prEmojiPresentation}, // E0.6 [1] (❌) cross mark + {0x274E, 0x274E, prEmojiPresentation}, // E0.6 [1] (❎) cross mark button + {0x2753, 0x2755, prEmojiPresentation}, // E0.6 [3] (❓..❕) red question mark..white exclamation mark + {0x2757, 0x2757, prEmojiPresentation}, // E0.6 [1] (❗) red exclamation mark + {0x2795, 0x2797, prEmojiPresentation}, // E0.6 [3] (➕..➗) plus..divide + {0x27B0, 0x27B0, prEmojiPresentation}, // E0.6 [1] (➰) curly loop + {0x27BF, 0x27BF, prEmojiPresentation}, // E1.0 [1] (➿) double curly loop + {0x2B1B, 0x2B1C, prEmojiPresentation}, // E0.6 [2] (⬛..⬜) black large square..white large square + {0x2B50, 0x2B50, prEmojiPresentation}, // E0.6 [1] (⭐) star + {0x2B55, 0x2B55, prEmojiPresentation}, // E0.6 [1] (⭕) hollow red circle + {0x1F004, 0x1F004, prEmojiPresentation}, // E0.6 [1] (🀄) mahjong red dragon + {0x1F0CF, 0x1F0CF, prEmojiPresentation}, // E0.6 [1] (🃏) joker + {0x1F18E, 0x1F18E, prEmojiPresentation}, // E0.6 [1] (🆎) AB button (blood type) + {0x1F191, 0x1F19A, prEmojiPresentation}, // E0.6 [10] (🆑..🆚) CL button..VS button + {0x1F1E6, 0x1F1FF, prEmojiPresentation}, // E0.0 [26] (🇦..🇿) regional indicator symbol letter a..regional indicator symbol letter z + {0x1F201, 0x1F201, prEmojiPresentation}, // E0.6 [1] (🈁) Japanese “here” button + {0x1F21A, 0x1F21A, prEmojiPresentation}, // E0.6 [1] (🈚) Japanese “free of charge” button + {0x1F22F, 0x1F22F, prEmojiPresentation}, // E0.6 [1] (🈯) Japanese “reserved” button + {0x1F232, 0x1F236, prEmojiPresentation}, // E0.6 [5] (🈲..🈶) Japanese “prohibited” button..Japanese “not free of charge” button + {0x1F238, 0x1F23A, prEmojiPresentation}, // E0.6 [3] (🈸..🈺) Japanese “application” button..Japanese “open for business” button + {0x1F250, 0x1F251, prEmojiPresentation}, // E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button + {0x1F300, 0x1F30C, prEmojiPresentation}, // E0.6 [13] (🌀..🌌) cyclone..milky way + {0x1F30D, 0x1F30E, prEmojiPresentation}, // E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas + {0x1F30F, 0x1F30F, prEmojiPresentation}, // E0.6 [1] (🌏) globe showing Asia-Australia + {0x1F310, 0x1F310, prEmojiPresentation}, // E1.0 [1] (🌐) globe with meridians + {0x1F311, 0x1F311, prEmojiPresentation}, // E0.6 [1] (🌑) new moon + {0x1F312, 0x1F312, prEmojiPresentation}, // E1.0 [1] (🌒) waxing crescent moon + {0x1F313, 0x1F315, prEmojiPresentation}, // E0.6 [3] (🌓..🌕) first quarter moon..full moon + {0x1F316, 0x1F318, prEmojiPresentation}, // E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon + {0x1F319, 0x1F319, prEmojiPresentation}, // E0.6 [1] (🌙) crescent moon + {0x1F31A, 0x1F31A, prEmojiPresentation}, // E1.0 [1] (🌚) new moon face + {0x1F31B, 0x1F31B, prEmojiPresentation}, // E0.6 [1] (🌛) first quarter moon face + {0x1F31C, 0x1F31C, prEmojiPresentation}, // E0.7 [1] (🌜) last quarter moon face + {0x1F31D, 0x1F31E, prEmojiPresentation}, // E1.0 [2] (🌝..🌞) full moon face..sun with face + {0x1F31F, 0x1F320, prEmojiPresentation}, // E0.6 [2] (🌟..🌠) glowing star..shooting star + {0x1F32D, 0x1F32F, prEmojiPresentation}, // E1.0 [3] (🌭..🌯) hot dog..burrito + {0x1F330, 0x1F331, prEmojiPresentation}, // E0.6 [2] (🌰..🌱) chestnut..seedling + {0x1F332, 0x1F333, prEmojiPresentation}, // E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree + {0x1F334, 0x1F335, prEmojiPresentation}, // E0.6 [2] (🌴..🌵) palm tree..cactus + {0x1F337, 0x1F34A, prEmojiPresentation}, // E0.6 [20] (🌷..🍊) tulip..tangerine + {0x1F34B, 0x1F34B, prEmojiPresentation}, // E1.0 [1] (🍋) lemon + {0x1F34C, 0x1F34F, prEmojiPresentation}, // E0.6 [4] (🍌..🍏) banana..green apple + {0x1F350, 0x1F350, prEmojiPresentation}, // E1.0 [1] (🍐) pear + {0x1F351, 0x1F37B, prEmojiPresentation}, // E0.6 [43] (🍑..🍻) peach..clinking beer mugs + {0x1F37C, 0x1F37C, prEmojiPresentation}, // E1.0 [1] (🍼) baby bottle + {0x1F37E, 0x1F37F, prEmojiPresentation}, // E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn + {0x1F380, 0x1F393, prEmojiPresentation}, // E0.6 [20] (🎀..🎓) ribbon..graduation cap + {0x1F3A0, 0x1F3C4, prEmojiPresentation}, // E0.6 [37] (🎠..🏄) carousel horse..person surfing + {0x1F3C5, 0x1F3C5, prEmojiPresentation}, // E1.0 [1] (🏅) sports medal + {0x1F3C6, 0x1F3C6, prEmojiPresentation}, // E0.6 [1] (🏆) trophy + {0x1F3C7, 0x1F3C7, prEmojiPresentation}, // E1.0 [1] (🏇) horse racing + {0x1F3C8, 0x1F3C8, prEmojiPresentation}, // E0.6 [1] (🏈) american football + {0x1F3C9, 0x1F3C9, prEmojiPresentation}, // E1.0 [1] (🏉) rugby football + {0x1F3CA, 0x1F3CA, prEmojiPresentation}, // E0.6 [1] (🏊) person swimming + {0x1F3CF, 0x1F3D3, prEmojiPresentation}, // E1.0 [5] (🏏..🏓) cricket game..ping pong + {0x1F3E0, 0x1F3E3, prEmojiPresentation}, // E0.6 [4] (🏠..🏣) house..Japanese post office + {0x1F3E4, 0x1F3E4, prEmojiPresentation}, // E1.0 [1] (🏤) post office + {0x1F3E5, 0x1F3F0, prEmojiPresentation}, // E0.6 [12] (🏥..🏰) hospital..castle + {0x1F3F4, 0x1F3F4, prEmojiPresentation}, // E1.0 [1] (🏴) black flag + {0x1F3F8, 0x1F407, prEmojiPresentation}, // E1.0 [16] (🏸..🐇) badminton..rabbit + {0x1F408, 0x1F408, prEmojiPresentation}, // E0.7 [1] (🐈) cat + {0x1F409, 0x1F40B, prEmojiPresentation}, // E1.0 [3] (🐉..🐋) dragon..whale + {0x1F40C, 0x1F40E, prEmojiPresentation}, // E0.6 [3] (🐌..🐎) snail..horse + {0x1F40F, 0x1F410, prEmojiPresentation}, // E1.0 [2] (🐏..🐐) ram..goat + {0x1F411, 0x1F412, prEmojiPresentation}, // E0.6 [2] (🐑..🐒) ewe..monkey + {0x1F413, 0x1F413, prEmojiPresentation}, // E1.0 [1] (🐓) rooster + {0x1F414, 0x1F414, prEmojiPresentation}, // E0.6 [1] (🐔) chicken + {0x1F415, 0x1F415, prEmojiPresentation}, // E0.7 [1] (🐕) dog + {0x1F416, 0x1F416, prEmojiPresentation}, // E1.0 [1] (🐖) pig + {0x1F417, 0x1F429, prEmojiPresentation}, // E0.6 [19] (🐗..🐩) boar..poodle + {0x1F42A, 0x1F42A, prEmojiPresentation}, // E1.0 [1] (🐪) camel + {0x1F42B, 0x1F43E, prEmojiPresentation}, // E0.6 [20] (🐫..🐾) two-hump camel..paw prints + {0x1F440, 0x1F440, prEmojiPresentation}, // E0.6 [1] (👀) eyes + {0x1F442, 0x1F464, prEmojiPresentation}, // E0.6 [35] (👂..👤) ear..bust in silhouette + {0x1F465, 0x1F465, prEmojiPresentation}, // E1.0 [1] (👥) busts in silhouette + {0x1F466, 0x1F46B, prEmojiPresentation}, // E0.6 [6] (👦..👫) boy..woman and man holding hands + {0x1F46C, 0x1F46D, prEmojiPresentation}, // E1.0 [2] (👬..👭) men holding hands..women holding hands + {0x1F46E, 0x1F4AC, prEmojiPresentation}, // E0.6 [63] (👮..💬) police officer..speech balloon + {0x1F4AD, 0x1F4AD, prEmojiPresentation}, // E1.0 [1] (💭) thought balloon + {0x1F4AE, 0x1F4B5, prEmojiPresentation}, // E0.6 [8] (💮..💵) white flower..dollar banknote + {0x1F4B6, 0x1F4B7, prEmojiPresentation}, // E1.0 [2] (💶..💷) euro banknote..pound banknote + {0x1F4B8, 0x1F4EB, prEmojiPresentation}, // E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag + {0x1F4EC, 0x1F4ED, prEmojiPresentation}, // E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag + {0x1F4EE, 0x1F4EE, prEmojiPresentation}, // E0.6 [1] (📮) postbox + {0x1F4EF, 0x1F4EF, prEmojiPresentation}, // E1.0 [1] (📯) postal horn + {0x1F4F0, 0x1F4F4, prEmojiPresentation}, // E0.6 [5] (📰..📴) newspaper..mobile phone off + {0x1F4F5, 0x1F4F5, prEmojiPresentation}, // E1.0 [1] (📵) no mobile phones + {0x1F4F6, 0x1F4F7, prEmojiPresentation}, // E0.6 [2] (📶..📷) antenna bars..camera + {0x1F4F8, 0x1F4F8, prEmojiPresentation}, // E1.0 [1] (📸) camera with flash + {0x1F4F9, 0x1F4FC, prEmojiPresentation}, // E0.6 [4] (📹..📼) video camera..videocassette + {0x1F4FF, 0x1F502, prEmojiPresentation}, // E1.0 [4] (📿..🔂) prayer beads..repeat single button + {0x1F503, 0x1F503, prEmojiPresentation}, // E0.6 [1] (🔃) clockwise vertical arrows + {0x1F504, 0x1F507, prEmojiPresentation}, // E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker + {0x1F508, 0x1F508, prEmojiPresentation}, // E0.7 [1] (🔈) speaker low volume + {0x1F509, 0x1F509, prEmojiPresentation}, // E1.0 [1] (🔉) speaker medium volume + {0x1F50A, 0x1F514, prEmojiPresentation}, // E0.6 [11] (🔊..🔔) speaker high volume..bell + {0x1F515, 0x1F515, prEmojiPresentation}, // E1.0 [1] (🔕) bell with slash + {0x1F516, 0x1F52B, prEmojiPresentation}, // E0.6 [22] (🔖..🔫) bookmark..water pistol + {0x1F52C, 0x1F52D, prEmojiPresentation}, // E1.0 [2] (🔬..🔭) microscope..telescope + {0x1F52E, 0x1F53D, prEmojiPresentation}, // E0.6 [16] (🔮..🔽) crystal ball..downwards button + {0x1F54B, 0x1F54E, prEmojiPresentation}, // E1.0 [4] (🕋..🕎) kaaba..menorah + {0x1F550, 0x1F55B, prEmojiPresentation}, // E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock + {0x1F55C, 0x1F567, prEmojiPresentation}, // E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty + {0x1F57A, 0x1F57A, prEmojiPresentation}, // E3.0 [1] (🕺) man dancing + {0x1F595, 0x1F596, prEmojiPresentation}, // E1.0 [2] (🖕..🖖) middle finger..vulcan salute + {0x1F5A4, 0x1F5A4, prEmojiPresentation}, // E3.0 [1] (🖤) black heart + {0x1F5FB, 0x1F5FF, prEmojiPresentation}, // E0.6 [5] (🗻..🗿) mount fuji..moai + {0x1F600, 0x1F600, prEmojiPresentation}, // E1.0 [1] (😀) grinning face + {0x1F601, 0x1F606, prEmojiPresentation}, // E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face + {0x1F607, 0x1F608, prEmojiPresentation}, // E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns + {0x1F609, 0x1F60D, prEmojiPresentation}, // E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes + {0x1F60E, 0x1F60E, prEmojiPresentation}, // E1.0 [1] (😎) smiling face with sunglasses + {0x1F60F, 0x1F60F, prEmojiPresentation}, // E0.6 [1] (😏) smirking face + {0x1F610, 0x1F610, prEmojiPresentation}, // E0.7 [1] (😐) neutral face + {0x1F611, 0x1F611, prEmojiPresentation}, // E1.0 [1] (😑) expressionless face + {0x1F612, 0x1F614, prEmojiPresentation}, // E0.6 [3] (😒..😔) unamused face..pensive face + {0x1F615, 0x1F615, prEmojiPresentation}, // E1.0 [1] (😕) confused face + {0x1F616, 0x1F616, prEmojiPresentation}, // E0.6 [1] (😖) confounded face + {0x1F617, 0x1F617, prEmojiPresentation}, // E1.0 [1] (😗) kissing face + {0x1F618, 0x1F618, prEmojiPresentation}, // E0.6 [1] (😘) face blowing a kiss + {0x1F619, 0x1F619, prEmojiPresentation}, // E1.0 [1] (😙) kissing face with smiling eyes + {0x1F61A, 0x1F61A, prEmojiPresentation}, // E0.6 [1] (😚) kissing face with closed eyes + {0x1F61B, 0x1F61B, prEmojiPresentation}, // E1.0 [1] (😛) face with tongue + {0x1F61C, 0x1F61E, prEmojiPresentation}, // E0.6 [3] (😜..😞) winking face with tongue..disappointed face + {0x1F61F, 0x1F61F, prEmojiPresentation}, // E1.0 [1] (😟) worried face + {0x1F620, 0x1F625, prEmojiPresentation}, // E0.6 [6] (😠..😥) angry face..sad but relieved face + {0x1F626, 0x1F627, prEmojiPresentation}, // E1.0 [2] (😦..😧) frowning face with open mouth..anguished face + {0x1F628, 0x1F62B, prEmojiPresentation}, // E0.6 [4] (😨..😫) fearful face..tired face + {0x1F62C, 0x1F62C, prEmojiPresentation}, // E1.0 [1] (😬) grimacing face + {0x1F62D, 0x1F62D, prEmojiPresentation}, // E0.6 [1] (😭) loudly crying face + {0x1F62E, 0x1F62F, prEmojiPresentation}, // E1.0 [2] (😮..😯) face with open mouth..hushed face + {0x1F630, 0x1F633, prEmojiPresentation}, // E0.6 [4] (😰..😳) anxious face with sweat..flushed face + {0x1F634, 0x1F634, prEmojiPresentation}, // E1.0 [1] (😴) sleeping face + {0x1F635, 0x1F635, prEmojiPresentation}, // E0.6 [1] (😵) face with crossed-out eyes + {0x1F636, 0x1F636, prEmojiPresentation}, // E1.0 [1] (😶) face without mouth + {0x1F637, 0x1F640, prEmojiPresentation}, // E0.6 [10] (😷..🙀) face with medical mask..weary cat + {0x1F641, 0x1F644, prEmojiPresentation}, // E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes + {0x1F645, 0x1F64F, prEmojiPresentation}, // E0.6 [11] (🙅..🙏) person gesturing NO..folded hands + {0x1F680, 0x1F680, prEmojiPresentation}, // E0.6 [1] (🚀) rocket + {0x1F681, 0x1F682, prEmojiPresentation}, // E1.0 [2] (🚁..🚂) helicopter..locomotive + {0x1F683, 0x1F685, prEmojiPresentation}, // E0.6 [3] (🚃..🚅) railway car..bullet train + {0x1F686, 0x1F686, prEmojiPresentation}, // E1.0 [1] (🚆) train + {0x1F687, 0x1F687, prEmojiPresentation}, // E0.6 [1] (🚇) metro + {0x1F688, 0x1F688, prEmojiPresentation}, // E1.0 [1] (🚈) light rail + {0x1F689, 0x1F689, prEmojiPresentation}, // E0.6 [1] (🚉) station + {0x1F68A, 0x1F68B, prEmojiPresentation}, // E1.0 [2] (🚊..🚋) tram..tram car + {0x1F68C, 0x1F68C, prEmojiPresentation}, // E0.6 [1] (🚌) bus + {0x1F68D, 0x1F68D, prEmojiPresentation}, // E0.7 [1] (🚍) oncoming bus + {0x1F68E, 0x1F68E, prEmojiPresentation}, // E1.0 [1] (🚎) trolleybus + {0x1F68F, 0x1F68F, prEmojiPresentation}, // E0.6 [1] (🚏) bus stop + {0x1F690, 0x1F690, prEmojiPresentation}, // E1.0 [1] (🚐) minibus + {0x1F691, 0x1F693, prEmojiPresentation}, // E0.6 [3] (🚑..🚓) ambulance..police car + {0x1F694, 0x1F694, prEmojiPresentation}, // E0.7 [1] (🚔) oncoming police car + {0x1F695, 0x1F695, prEmojiPresentation}, // E0.6 [1] (🚕) taxi + {0x1F696, 0x1F696, prEmojiPresentation}, // E1.0 [1] (🚖) oncoming taxi + {0x1F697, 0x1F697, prEmojiPresentation}, // E0.6 [1] (🚗) automobile + {0x1F698, 0x1F698, prEmojiPresentation}, // E0.7 [1] (🚘) oncoming automobile + {0x1F699, 0x1F69A, prEmojiPresentation}, // E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck + {0x1F69B, 0x1F6A1, prEmojiPresentation}, // E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway + {0x1F6A2, 0x1F6A2, prEmojiPresentation}, // E0.6 [1] (🚢) ship + {0x1F6A3, 0x1F6A3, prEmojiPresentation}, // E1.0 [1] (🚣) person rowing boat + {0x1F6A4, 0x1F6A5, prEmojiPresentation}, // E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light + {0x1F6A6, 0x1F6A6, prEmojiPresentation}, // E1.0 [1] (🚦) vertical traffic light + {0x1F6A7, 0x1F6AD, prEmojiPresentation}, // E0.6 [7] (🚧..🚭) construction..no smoking + {0x1F6AE, 0x1F6B1, prEmojiPresentation}, // E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water + {0x1F6B2, 0x1F6B2, prEmojiPresentation}, // E0.6 [1] (🚲) bicycle + {0x1F6B3, 0x1F6B5, prEmojiPresentation}, // E1.0 [3] (🚳..🚵) no bicycles..person mountain biking + {0x1F6B6, 0x1F6B6, prEmojiPresentation}, // E0.6 [1] (🚶) person walking + {0x1F6B7, 0x1F6B8, prEmojiPresentation}, // E1.0 [2] (🚷..🚸) no pedestrians..children crossing + {0x1F6B9, 0x1F6BE, prEmojiPresentation}, // E0.6 [6] (🚹..🚾) men’s room..water closet + {0x1F6BF, 0x1F6BF, prEmojiPresentation}, // E1.0 [1] (🚿) shower + {0x1F6C0, 0x1F6C0, prEmojiPresentation}, // E0.6 [1] (🛀) person taking bath + {0x1F6C1, 0x1F6C5, prEmojiPresentation}, // E1.0 [5] (🛁..🛅) bathtub..left luggage + {0x1F6CC, 0x1F6CC, prEmojiPresentation}, // E1.0 [1] (🛌) person in bed + {0x1F6D0, 0x1F6D0, prEmojiPresentation}, // E1.0 [1] (🛐) place of worship + {0x1F6D1, 0x1F6D2, prEmojiPresentation}, // E3.0 [2] (🛑..🛒) stop sign..shopping cart + {0x1F6D5, 0x1F6D5, prEmojiPresentation}, // E12.0 [1] (🛕) hindu temple + {0x1F6D6, 0x1F6D7, prEmojiPresentation}, // E13.0 [2] (🛖..🛗) hut..elevator + {0x1F6DC, 0x1F6DC, prEmojiPresentation}, // E15.0 [1] (🛜) wireless + {0x1F6DD, 0x1F6DF, prEmojiPresentation}, // E14.0 [3] (🛝..🛟) playground slide..ring buoy + {0x1F6EB, 0x1F6EC, prEmojiPresentation}, // E1.0 [2] (🛫..🛬) airplane departure..airplane arrival + {0x1F6F4, 0x1F6F6, prEmojiPresentation}, // E3.0 [3] (🛴..🛶) kick scooter..canoe + {0x1F6F7, 0x1F6F8, prEmojiPresentation}, // E5.0 [2] (🛷..🛸) sled..flying saucer + {0x1F6F9, 0x1F6F9, prEmojiPresentation}, // E11.0 [1] (🛹) skateboard + {0x1F6FA, 0x1F6FA, prEmojiPresentation}, // E12.0 [1] (🛺) auto rickshaw + {0x1F6FB, 0x1F6FC, prEmojiPresentation}, // E13.0 [2] (🛻..🛼) pickup truck..roller skate + {0x1F7E0, 0x1F7EB, prEmojiPresentation}, // E12.0 [12] (🟠..🟫) orange circle..brown square + {0x1F7F0, 0x1F7F0, prEmojiPresentation}, // E14.0 [1] (🟰) heavy equals sign + {0x1F90C, 0x1F90C, prEmojiPresentation}, // E13.0 [1] (🤌) pinched fingers + {0x1F90D, 0x1F90F, prEmojiPresentation}, // E12.0 [3] (🤍..🤏) white heart..pinching hand + {0x1F910, 0x1F918, prEmojiPresentation}, // E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns + {0x1F919, 0x1F91E, prEmojiPresentation}, // E3.0 [6] (🤙..🤞) call me hand..crossed fingers + {0x1F91F, 0x1F91F, prEmojiPresentation}, // E5.0 [1] (🤟) love-you gesture + {0x1F920, 0x1F927, prEmojiPresentation}, // E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face + {0x1F928, 0x1F92F, prEmojiPresentation}, // E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head + {0x1F930, 0x1F930, prEmojiPresentation}, // E3.0 [1] (🤰) pregnant woman + {0x1F931, 0x1F932, prEmojiPresentation}, // E5.0 [2] (🤱..🤲) breast-feeding..palms up together + {0x1F933, 0x1F93A, prEmojiPresentation}, // E3.0 [8] (🤳..🤺) selfie..person fencing + {0x1F93C, 0x1F93E, prEmojiPresentation}, // E3.0 [3] (🤼..🤾) people wrestling..person playing handball + {0x1F93F, 0x1F93F, prEmojiPresentation}, // E12.0 [1] (🤿) diving mask + {0x1F940, 0x1F945, prEmojiPresentation}, // E3.0 [6] (🥀..🥅) wilted flower..goal net + {0x1F947, 0x1F94B, prEmojiPresentation}, // E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform + {0x1F94C, 0x1F94C, prEmojiPresentation}, // E5.0 [1] (🥌) curling stone + {0x1F94D, 0x1F94F, prEmojiPresentation}, // E11.0 [3] (🥍..🥏) lacrosse..flying disc + {0x1F950, 0x1F95E, prEmojiPresentation}, // E3.0 [15] (🥐..🥞) croissant..pancakes + {0x1F95F, 0x1F96B, prEmojiPresentation}, // E5.0 [13] (🥟..🥫) dumpling..canned food + {0x1F96C, 0x1F970, prEmojiPresentation}, // E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts + {0x1F971, 0x1F971, prEmojiPresentation}, // E12.0 [1] (🥱) yawning face + {0x1F972, 0x1F972, prEmojiPresentation}, // E13.0 [1] (🥲) smiling face with tear + {0x1F973, 0x1F976, prEmojiPresentation}, // E11.0 [4] (🥳..🥶) partying face..cold face + {0x1F977, 0x1F978, prEmojiPresentation}, // E13.0 [2] (🥷..🥸) ninja..disguised face + {0x1F979, 0x1F979, prEmojiPresentation}, // E14.0 [1] (🥹) face holding back tears + {0x1F97A, 0x1F97A, prEmojiPresentation}, // E11.0 [1] (🥺) pleading face + {0x1F97B, 0x1F97B, prEmojiPresentation}, // E12.0 [1] (🥻) sari + {0x1F97C, 0x1F97F, prEmojiPresentation}, // E11.0 [4] (🥼..🥿) lab coat..flat shoe + {0x1F980, 0x1F984, prEmojiPresentation}, // E1.0 [5] (🦀..🦄) crab..unicorn + {0x1F985, 0x1F991, prEmojiPresentation}, // E3.0 [13] (🦅..🦑) eagle..squid + {0x1F992, 0x1F997, prEmojiPresentation}, // E5.0 [6] (🦒..🦗) giraffe..cricket + {0x1F998, 0x1F9A2, prEmojiPresentation}, // E11.0 [11] (🦘..🦢) kangaroo..swan + {0x1F9A3, 0x1F9A4, prEmojiPresentation}, // E13.0 [2] (🦣..🦤) mammoth..dodo + {0x1F9A5, 0x1F9AA, prEmojiPresentation}, // E12.0 [6] (🦥..🦪) sloth..oyster + {0x1F9AB, 0x1F9AD, prEmojiPresentation}, // E13.0 [3] (🦫..🦭) beaver..seal + {0x1F9AE, 0x1F9AF, prEmojiPresentation}, // E12.0 [2] (🦮..🦯) guide dog..white cane + {0x1F9B0, 0x1F9B9, prEmojiPresentation}, // E11.0 [10] (🦰..🦹) red hair..supervillain + {0x1F9BA, 0x1F9BF, prEmojiPresentation}, // E12.0 [6] (🦺..🦿) safety vest..mechanical leg + {0x1F9C0, 0x1F9C0, prEmojiPresentation}, // E1.0 [1] (🧀) cheese wedge + {0x1F9C1, 0x1F9C2, prEmojiPresentation}, // E11.0 [2] (🧁..🧂) cupcake..salt + {0x1F9C3, 0x1F9CA, prEmojiPresentation}, // E12.0 [8] (🧃..🧊) beverage box..ice + {0x1F9CB, 0x1F9CB, prEmojiPresentation}, // E13.0 [1] (🧋) bubble tea + {0x1F9CC, 0x1F9CC, prEmojiPresentation}, // E14.0 [1] (🧌) troll + {0x1F9CD, 0x1F9CF, prEmojiPresentation}, // E12.0 [3] (🧍..🧏) person standing..deaf person + {0x1F9D0, 0x1F9E6, prEmojiPresentation}, // E5.0 [23] (🧐..🧦) face with monocle..socks + {0x1F9E7, 0x1F9FF, prEmojiPresentation}, // E11.0 [25] (🧧..🧿) red envelope..nazar amulet + {0x1FA70, 0x1FA73, prEmojiPresentation}, // E12.0 [4] (🩰..🩳) ballet shoes..shorts + {0x1FA74, 0x1FA74, prEmojiPresentation}, // E13.0 [1] (🩴) thong sandal + {0x1FA75, 0x1FA77, prEmojiPresentation}, // E15.0 [3] (🩵..🩷) light blue heart..pink heart + {0x1FA78, 0x1FA7A, prEmojiPresentation}, // E12.0 [3] (🩸..🩺) drop of blood..stethoscope + {0x1FA7B, 0x1FA7C, prEmojiPresentation}, // E14.0 [2] (🩻..🩼) x-ray..crutch + {0x1FA80, 0x1FA82, prEmojiPresentation}, // E12.0 [3] (🪀..🪂) yo-yo..parachute + {0x1FA83, 0x1FA86, prEmojiPresentation}, // E13.0 [4] (🪃..🪆) boomerang..nesting dolls + {0x1FA87, 0x1FA88, prEmojiPresentation}, // E15.0 [2] (🪇..🪈) maracas..flute + {0x1FA90, 0x1FA95, prEmojiPresentation}, // E12.0 [6] (🪐..🪕) ringed planet..banjo + {0x1FA96, 0x1FAA8, prEmojiPresentation}, // E13.0 [19] (🪖..🪨) military helmet..rock + {0x1FAA9, 0x1FAAC, prEmojiPresentation}, // E14.0 [4] (🪩..🪬) mirror ball..hamsa + {0x1FAAD, 0x1FAAF, prEmojiPresentation}, // E15.0 [3] (🪭..🪯) folding hand fan..khanda + {0x1FAB0, 0x1FAB6, prEmojiPresentation}, // E13.0 [7] (🪰..🪶) fly..feather + {0x1FAB7, 0x1FABA, prEmojiPresentation}, // E14.0 [4] (🪷..🪺) lotus..nest with eggs + {0x1FABB, 0x1FABD, prEmojiPresentation}, // E15.0 [3] (🪻..🪽) hyacinth..wing + {0x1FABF, 0x1FABF, prEmojiPresentation}, // E15.0 [1] (🪿) goose + {0x1FAC0, 0x1FAC2, prEmojiPresentation}, // E13.0 [3] (🫀..🫂) anatomical heart..people hugging + {0x1FAC3, 0x1FAC5, prEmojiPresentation}, // E14.0 [3] (🫃..🫅) pregnant man..person with crown + {0x1FACE, 0x1FACF, prEmojiPresentation}, // E15.0 [2] (🫎..🫏) moose..donkey + {0x1FAD0, 0x1FAD6, prEmojiPresentation}, // E13.0 [7] (🫐..🫖) blueberries..teapot + {0x1FAD7, 0x1FAD9, prEmojiPresentation}, // E14.0 [3] (🫗..🫙) pouring liquid..jar + {0x1FADA, 0x1FADB, prEmojiPresentation}, // E15.0 [2] (🫚..🫛) ginger root..pea pod + {0x1FAE0, 0x1FAE7, prEmojiPresentation}, // E14.0 [8] (🫠..🫧) melting face..bubbles + {0x1FAE8, 0x1FAE8, prEmojiPresentation}, // E15.0 [1] (🫨) shaking face + {0x1FAF0, 0x1FAF6, prEmojiPresentation}, // E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands + {0x1FAF7, 0x1FAF8, prEmojiPresentation}, // E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand +} diff --git a/vendor/github.com/rivo/uniseg/gen_breaktest.go b/vendor/github.com/rivo/uniseg/gen_breaktest.go new file mode 100644 index 000000000..6bfbeb5e7 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/gen_breaktest.go @@ -0,0 +1,215 @@ +//go:build generate + +// This program generates a Go containing a slice of test cases based on the +// Unicode Character Database auxiliary data files. The command line arguments +// are as follows: +// +// 1. The name of the Unicode data file (just the filename, without extension). +// 2. The name of the locally generated Go file. +// 3. The name of the slice containing the test cases. +// 4. The name of the generator, for logging purposes. +// +//go:generate go run gen_breaktest.go GraphemeBreakTest graphemebreak_test.go graphemeBreakTestCases graphemes +//go:generate go run gen_breaktest.go WordBreakTest wordbreak_test.go wordBreakTestCases words +//go:generate go run gen_breaktest.go SentenceBreakTest sentencebreak_test.go sentenceBreakTestCases sentences +//go:generate go run gen_breaktest.go LineBreakTest linebreak_test.go lineBreakTestCases lines + +package main + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "go/format" + "io/ioutil" + "log" + "net/http" + "os" + "time" +) + +// We want to test against a specific version rather than the latest. When the +// package is upgraded to a new version, change these to generate new tests. +const ( + testCaseURL = `https://www.unicode.org/Public/15.0.0/ucd/auxiliary/%s.txt` +) + +func main() { + if len(os.Args) < 5 { + fmt.Println("Not enough arguments, see code for details") + os.Exit(1) + } + + log.SetPrefix("gen_breaktest (" + os.Args[4] + "): ") + log.SetFlags(0) + + // Read text of testcases and parse into Go source code. + src, err := parse(fmt.Sprintf(testCaseURL, os.Args[1])) + if err != nil { + log.Fatal(err) + } + + // Format the Go code. + formatted, err := format.Source(src) + if err != nil { + log.Fatalln("gofmt:", err) + } + + // Write it out. + log.Print("Writing to ", os.Args[2]) + if err := ioutil.WriteFile(os.Args[2], formatted, 0644); err != nil { + log.Fatal(err) + } +} + +// parse reads a break text file, either from a local file or from a URL. It +// parses the file data into Go source code representing the test cases. +func parse(url string) ([]byte, error) { + log.Printf("Parsing %s", url) + res, err := http.Get(url) + if err != nil { + return nil, err + } + body := res.Body + defer body.Close() + + buf := new(bytes.Buffer) + buf.Grow(120 << 10) + buf.WriteString(`// Code generated via go generate from gen_breaktest.go. DO NOT EDIT. + +package uniseg + +// ` + os.Args[3] + ` are Grapheme testcases taken from +// ` + url + ` +// on ` + time.Now().Format("January 2, 2006") + `. See +// https://www.unicode.org/license.html for the Unicode license agreement. +var ` + os.Args[3] + ` = []testCase { +`) + + sc := bufio.NewScanner(body) + num := 1 + var line []byte + original := make([]byte, 0, 64) + expected := make([]byte, 0, 64) + for sc.Scan() { + num++ + line = sc.Bytes() + if len(line) == 0 || line[0] == '#' { + continue + } + var comment []byte + if i := bytes.IndexByte(line, '#'); i >= 0 { + comment = bytes.TrimSpace(line[i+1:]) + line = bytes.TrimSpace(line[:i]) + } + original, expected, err := parseRuneSequence(line, original[:0], expected[:0]) + if err != nil { + return nil, fmt.Errorf(`line %d: %v: %q`, num, err, line) + } + fmt.Fprintf(buf, "\t{original: \"%s\", expected: %s}, // %s\n", original, expected, comment) + } + if err := sc.Err(); err != nil { + return nil, err + } + + // Check for final "# EOF", useful check if we're streaming via HTTP + if !bytes.Equal(line, []byte("# EOF")) { + return nil, fmt.Errorf(`line %d: exected "# EOF" as final line, got %q`, num, line) + } + buf.WriteString("}\n") + return buf.Bytes(), nil +} + +// Used by parseRuneSequence to match input via bytes.HasPrefix. +var ( + prefixBreak = []byte("÷ ") + prefixDontBreak = []byte("× ") + breakOk = []byte("÷") + breakNo = []byte("×") +) + +// parseRuneSequence parses a rune + breaking opportunity sequence from b +// and appends the Go code for testcase.original to orig +// and appends the Go code for testcase.expected to exp. +// It retuns the new orig and exp slices. +// +// E.g. for the input b="÷ 0020 × 0308 ÷ 1F1E6 ÷" +// it will append +// +// "\u0020\u0308\U0001F1E6" +// +// and "[][]rune{{0x0020,0x0308},{0x1F1E6},}" +// to orig and exp respectively. +// +// The formatting of exp is expected to be cleaned up by gofmt or format.Source. +// Note we explicitly require the sequence to start with ÷ and we implicitly +// require it to end with ÷. +func parseRuneSequence(b, orig, exp []byte) ([]byte, []byte, error) { + // Check for and remove first ÷ or ×. + if !bytes.HasPrefix(b, prefixBreak) && !bytes.HasPrefix(b, prefixDontBreak) { + return nil, nil, errors.New("expected ÷ or × as first character") + } + if bytes.HasPrefix(b, prefixBreak) { + b = b[len(prefixBreak):] + } else { + b = b[len(prefixDontBreak):] + } + + boundary := true + exp = append(exp, "[][]rune{"...) + for len(b) > 0 { + if boundary { + exp = append(exp, '{') + } + exp = append(exp, "0x"...) + // Find end of hex digits. + var i int + for i = 0; i < len(b) && b[i] != ' '; i++ { + if d := b[i]; ('0' <= d || d <= '9') || + ('A' <= d || d <= 'F') || + ('a' <= d || d <= 'f') { + continue + } + return nil, nil, errors.New("bad hex digit") + } + switch i { + case 4: + orig = append(orig, "\\u"...) + case 5: + orig = append(orig, "\\U000"...) + default: + return nil, nil, errors.New("unsupport code point hex length") + } + orig = append(orig, b[:i]...) + exp = append(exp, b[:i]...) + b = b[i:] + + // Check for space between hex and ÷ or ×. + if len(b) < 1 || b[0] != ' ' { + return nil, nil, errors.New("bad input") + } + b = b[1:] + + // Check for next boundary. + switch { + case bytes.HasPrefix(b, breakOk): + boundary = true + b = b[len(breakOk):] + case bytes.HasPrefix(b, breakNo): + boundary = false + b = b[len(breakNo):] + default: + return nil, nil, errors.New("missing ÷ or ×") + } + if boundary { + exp = append(exp, '}') + } + exp = append(exp, ',') + if len(b) > 0 && b[0] == ' ' { + b = b[1:] + } + } + exp = append(exp, '}') + return orig, exp, nil +} diff --git a/vendor/github.com/rivo/uniseg/gen_properties.go b/vendor/github.com/rivo/uniseg/gen_properties.go new file mode 100644 index 000000000..8992d2c5f --- /dev/null +++ b/vendor/github.com/rivo/uniseg/gen_properties.go @@ -0,0 +1,261 @@ +//go:build generate + +// This program generates a property file in Go file from Unicode Character +// Database auxiliary data files. The command line arguments are as follows: +// +// 1. The name of the Unicode data file (just the filename, without extension). +// Can be "-" (to skip) if the emoji flag is included. +// 2. The name of the locally generated Go file. +// 3. The name of the slice mapping code points to properties. +// 4. The name of the generator, for logging purposes. +// 5. (Optional) Flags, comma-separated. The following flags are available: +// - "emojis=": include the specified emoji properties (e.g. +// "Extended_Pictographic"). +// - "gencat": include general category properties. +// +//go:generate go run gen_properties.go auxiliary/GraphemeBreakProperty graphemeproperties.go graphemeCodePoints graphemes emojis=Extended_Pictographic +//go:generate go run gen_properties.go auxiliary/WordBreakProperty wordproperties.go workBreakCodePoints words emojis=Extended_Pictographic +//go:generate go run gen_properties.go auxiliary/SentenceBreakProperty sentenceproperties.go sentenceBreakCodePoints sentences +//go:generate go run gen_properties.go LineBreak lineproperties.go lineBreakCodePoints lines gencat +//go:generate go run gen_properties.go EastAsianWidth eastasianwidth.go eastAsianWidth eastasianwidth +//go:generate go run gen_properties.go - emojipresentation.go emojiPresentation emojipresentation emojis=Emoji_Presentation +package main + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "go/format" + "io/ioutil" + "log" + "net/http" + "os" + "regexp" + "sort" + "strconv" + "strings" + "time" +) + +// We want to test against a specific version rather than the latest. When the +// package is upgraded to a new version, change these to generate new tests. +const ( + propertyURL = `https://www.unicode.org/Public/15.0.0/ucd/%s.txt` + emojiURL = `https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt` +) + +// The regular expression for a line containing a code point range property. +var propertyPattern = regexp.MustCompile(`^([0-9A-F]{4,6})(\.\.([0-9A-F]{4,6}))?\s*;\s*([A-Za-z0-9_]+)\s*#\s(.+)$`) + +func main() { + if len(os.Args) < 5 { + fmt.Println("Not enough arguments, see code for details") + os.Exit(1) + } + + log.SetPrefix("gen_properties (" + os.Args[4] + "): ") + log.SetFlags(0) + + // Parse flags. + flags := make(map[string]string) + if len(os.Args) >= 6 { + for _, flag := range strings.Split(os.Args[5], ",") { + flagFields := strings.Split(flag, "=") + if len(flagFields) == 1 { + flags[flagFields[0]] = "yes" + } else { + flags[flagFields[0]] = flagFields[1] + } + } + } + + // Parse the text file and generate Go source code from it. + _, includeGeneralCategory := flags["gencat"] + var mainURL string + if os.Args[1] != "-" { + mainURL = fmt.Sprintf(propertyURL, os.Args[1]) + } + src, err := parse(mainURL, flags["emojis"], includeGeneralCategory) + if err != nil { + log.Fatal(err) + } + + // Format the Go code. + formatted, err := format.Source([]byte(src)) + if err != nil { + log.Fatal("gofmt:", err) + } + + // Save it to the (local) target file. + log.Print("Writing to ", os.Args[2]) + if err := ioutil.WriteFile(os.Args[2], formatted, 0644); err != nil { + log.Fatal(err) + } +} + +// parse parses the Unicode Properties text files located at the given URLs and +// returns their equivalent Go source code to be used in the uniseg package. If +// "emojiProperty" is not an empty string, emoji code points for that emoji +// property (e.g. "Extended_Pictographic") will be included. In those cases, you +// may pass an empty "propertyURL" to skip parsing the main properties file. If +// "includeGeneralCategory" is true, the Unicode General Category property will +// be extracted from the comments and included in the output. +func parse(propertyURL, emojiProperty string, includeGeneralCategory bool) (string, error) { + if propertyURL == "" && emojiProperty == "" { + return "", errors.New("no properties to parse") + } + + // Temporary buffer to hold properties. + var properties [][4]string + + // Open the first URL. + if propertyURL != "" { + log.Printf("Parsing %s", propertyURL) + res, err := http.Get(propertyURL) + if err != nil { + return "", err + } + in1 := res.Body + defer in1.Close() + + // Parse it. + scanner := bufio.NewScanner(in1) + num := 0 + for scanner.Scan() { + num++ + line := strings.TrimSpace(scanner.Text()) + + // Skip comments and empty lines. + if strings.HasPrefix(line, "#") || line == "" { + continue + } + + // Everything else must be a code point range, a property and a comment. + from, to, property, comment, err := parseProperty(line) + if err != nil { + return "", fmt.Errorf("%s line %d: %v", os.Args[4], num, err) + } + properties = append(properties, [4]string{from, to, property, comment}) + } + if err := scanner.Err(); err != nil { + return "", err + } + } + + // Open the second URL. + if emojiProperty != "" { + log.Printf("Parsing %s", emojiURL) + res, err := http.Get(emojiURL) + if err != nil { + return "", err + } + in2 := res.Body + defer in2.Close() + + // Parse it. + scanner := bufio.NewScanner(in2) + num := 0 + for scanner.Scan() { + num++ + line := scanner.Text() + + // Skip comments, empty lines, and everything not containing + // "Extended_Pictographic". + if strings.HasPrefix(line, "#") || line == "" || !strings.Contains(line, emojiProperty) { + continue + } + + // Everything else must be a code point range, a property and a comment. + from, to, property, comment, err := parseProperty(line) + if err != nil { + return "", fmt.Errorf("emojis line %d: %v", num, err) + } + properties = append(properties, [4]string{from, to, property, comment}) + } + if err := scanner.Err(); err != nil { + return "", err + } + } + + // Avoid overflow during binary search. + if len(properties) >= 1<<31 { + return "", errors.New("too many properties") + } + + // Sort properties. + sort.Slice(properties, func(i, j int) bool { + left, _ := strconv.ParseUint(properties[i][0], 16, 64) + right, _ := strconv.ParseUint(properties[j][0], 16, 64) + return left < right + }) + + // Header. + var ( + buf bytes.Buffer + emojiComment string + ) + columns := 3 + if includeGeneralCategory { + columns = 4 + } + if emojiURL != "" { + emojiComment = ` +// and +// ` + emojiURL + ` +// ("Extended_Pictographic" only)` + } + buf.WriteString(`// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// ` + os.Args[3] + ` are taken from +// ` + propertyURL + emojiComment + ` +// on ` + time.Now().Format("January 2, 2006") + `. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var ` + os.Args[3] + ` = [][` + strconv.Itoa(columns) + `]int{ + `) + + // Properties. + for _, prop := range properties { + if includeGeneralCategory { + generalCategory := "gc" + prop[3][:2] + if generalCategory == "gcL&" { + generalCategory = "gcLC" + } + prop[3] = prop[3][3:] + fmt.Fprintf(&buf, "{0x%s,0x%s,%s,%s}, // %s\n", prop[0], prop[1], translateProperty("pr", prop[2]), generalCategory, prop[3]) + } else { + fmt.Fprintf(&buf, "{0x%s,0x%s,%s}, // %s\n", prop[0], prop[1], translateProperty("pr", prop[2]), prop[3]) + } + } + + // Tail. + buf.WriteString("}") + + return buf.String(), nil +} + +// parseProperty parses a line of the Unicode properties text file containing a +// property for a code point range and returns it along with its comment. +func parseProperty(line string) (from, to, property, comment string, err error) { + fields := propertyPattern.FindStringSubmatch(line) + if fields == nil { + err = errors.New("no property found") + return + } + from = fields[1] + to = fields[3] + if to == "" { + to = from + } + property = fields[4] + comment = fields[5] + return +} + +// translateProperty translates a property name as used in the Unicode data file +// to a variable used in the Go code. +func translateProperty(prefix, property string) string { + return prefix + strings.ReplaceAll(property, "_", "") +} diff --git a/vendor/github.com/rivo/uniseg/grapheme.go b/vendor/github.com/rivo/uniseg/grapheme.go new file mode 100644 index 000000000..b12403d43 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/grapheme.go @@ -0,0 +1,331 @@ +package uniseg + +import "unicode/utf8" + +// Graphemes implements an iterator over Unicode grapheme clusters, or +// user-perceived characters. While iterating, it also provides information +// about word boundaries, sentence boundaries, line breaks, and monospace +// character widths. +// +// After constructing the class via [NewGraphemes] for a given string "str", +// [Graphemes.Next] is called for every grapheme cluster in a loop until it +// returns false. Inside the loop, information about the grapheme cluster as +// well as boundary information and character width is available via the various +// methods (see examples below). +// +// This class basically wraps the [StepString] parser and provides a convenient +// interface to it. If you are only interested in some parts of this package's +// functionality, using the specialized functions starting with "First" is +// almost always faster. +type Graphemes struct { + // The original string. + original string + + // The remaining string to be parsed. + remaining string + + // The current grapheme cluster. + cluster string + + // The byte offset of the current grapheme cluster relative to the original + // string. + offset int + + // The current boundary information of the [Step] parser. + boundaries int + + // The current state of the [Step] parser. + state int +} + +// NewGraphemes returns a new grapheme cluster iterator. +func NewGraphemes(str string) *Graphemes { + return &Graphemes{ + original: str, + remaining: str, + state: -1, + } +} + +// Next advances the iterator by one grapheme cluster and returns false if no +// clusters are left. This function must be called before the first cluster is +// accessed. +func (g *Graphemes) Next() bool { + if len(g.remaining) == 0 { + // We're already past the end. + g.state = -2 + g.cluster = "" + return false + } + g.offset += len(g.cluster) + g.cluster, g.remaining, g.boundaries, g.state = StepString(g.remaining, g.state) + return true +} + +// Runes returns a slice of runes (code points) which corresponds to the current +// grapheme cluster. If the iterator is already past the end or [Graphemes.Next] +// has not yet been called, nil is returned. +func (g *Graphemes) Runes() []rune { + if g.state < 0 { + return nil + } + return []rune(g.cluster) +} + +// Str returns a substring of the original string which corresponds to the +// current grapheme cluster. If the iterator is already past the end or +// [Graphemes.Next] has not yet been called, an empty string is returned. +func (g *Graphemes) Str() string { + return g.cluster +} + +// Bytes returns a byte slice which corresponds to the current grapheme cluster. +// If the iterator is already past the end or [Graphemes.Next] has not yet been +// called, nil is returned. +func (g *Graphemes) Bytes() []byte { + if g.state < 0 { + return nil + } + return []byte(g.cluster) +} + +// Positions returns the interval of the current grapheme cluster as byte +// positions into the original string. The first returned value "from" indexes +// the first byte and the second returned value "to" indexes the first byte that +// is not included anymore, i.e. str[from:to] is the current grapheme cluster of +// the original string "str". If [Graphemes.Next] has not yet been called, both +// values are 0. If the iterator is already past the end, both values are 1. +func (g *Graphemes) Positions() (int, int) { + if g.state == -1 { + return 0, 0 + } else if g.state == -2 { + return 1, 1 + } + return g.offset, g.offset + len(g.cluster) +} + +// IsWordBoundary returns true if a word ends after the current grapheme +// cluster. +func (g *Graphemes) IsWordBoundary() bool { + if g.state < 0 { + return true + } + return g.boundaries&MaskWord != 0 +} + +// IsSentenceBoundary returns true if a sentence ends after the current +// grapheme cluster. +func (g *Graphemes) IsSentenceBoundary() bool { + if g.state < 0 { + return true + } + return g.boundaries&MaskSentence != 0 +} + +// LineBreak returns whether the line can be broken after the current grapheme +// cluster. A value of [LineDontBreak] means the line may not be broken, a value +// of [LineMustBreak] means the line must be broken, and a value of +// [LineCanBreak] means the line may or may not be broken. +func (g *Graphemes) LineBreak() int { + if g.state == -1 { + return LineDontBreak + } + if g.state == -2 { + return LineMustBreak + } + return g.boundaries & MaskLine +} + +// Width returns the monospace width of the current grapheme cluster. +func (g *Graphemes) Width() int { + if g.state < 0 { + return 0 + } + return g.boundaries >> ShiftWidth +} + +// Reset puts the iterator into its initial state such that the next call to +// [Graphemes.Next] sets it to the first grapheme cluster again. +func (g *Graphemes) Reset() { + g.state = -1 + g.offset = 0 + g.cluster = "" + g.remaining = g.original +} + +// GraphemeClusterCount returns the number of user-perceived characters +// (grapheme clusters) for the given string. +func GraphemeClusterCount(s string) (n int) { + state := -1 + for len(s) > 0 { + _, s, _, state = FirstGraphemeClusterInString(s, state) + n++ + } + return +} + +// ReverseString reverses the given string while observing grapheme cluster +// boundaries. +func ReverseString(s string) string { + str := []byte(s) + reversed := make([]byte, len(str)) + state := -1 + index := len(str) + for len(str) > 0 { + var cluster []byte + cluster, str, _, state = FirstGraphemeCluster(str, state) + index -= len(cluster) + copy(reversed[index:], cluster) + if index <= len(str)/2 { + break + } + } + return string(reversed) +} + +// The number of bits the grapheme property must be shifted to make place for +// grapheme states. +const shiftGraphemePropState = 4 + +// FirstGraphemeCluster returns the first grapheme cluster found in the given +// byte slice according to the rules of [Unicode Standard Annex #29, Grapheme +// Cluster Boundaries]. This function can be called continuously to extract all +// grapheme clusters from a byte slice, as illustrated in the example below. +// +// If you don't know the current state, for example when calling the function +// for the first time, you must pass -1. For consecutive calls, pass the state +// and rest slice returned by the previous call. +// +// The "rest" slice is the sub-slice of the original byte slice "b" starting +// after the last byte of the identified grapheme cluster. If the length of the +// "rest" slice is 0, the entire byte slice "b" has been processed. The +// "cluster" byte slice is the sub-slice of the input slice containing the +// identified grapheme cluster. +// +// The returned width is the width of the grapheme cluster for most monospace +// fonts where a value of 1 represents one character cell. +// +// Given an empty byte slice "b", the function returns nil values. +// +// While slightly less convenient than using the Graphemes class, this function +// has much better performance and makes no allocations. It lends itself well to +// large byte slices. +// +// [Unicode Standard Annex #29, Grapheme Cluster Boundaries]: http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries +func FirstGraphemeCluster(b []byte, state int) (cluster, rest []byte, width, newState int) { + // An empty byte slice returns nothing. + if len(b) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRune(b) + if len(b) <= length { // If we're already past the end, there is nothing else to parse. + var prop int + if state < 0 { + prop = propertyGraphemes(r) + } else { + prop = state >> shiftGraphemePropState + } + return b, nil, runeWidth(r, prop), grAny | (prop << shiftGraphemePropState) + } + + // If we don't know the state, determine it now. + var firstProp int + if state < 0 { + state, firstProp, _ = transitionGraphemeState(state, r) + } else { + firstProp = state >> shiftGraphemePropState + } + width += runeWidth(r, firstProp) + + // Transition until we find a boundary. + for { + var ( + prop int + boundary bool + ) + + r, l := utf8.DecodeRune(b[length:]) + state, prop, boundary = transitionGraphemeState(state&maskGraphemeState, r) + + if boundary { + return b[:length], b[length:], width, state | (prop << shiftGraphemePropState) + } + + if firstProp == prExtendedPictographic { + if r == vs15 { + width = 1 + } else if r == vs16 { + width = 2 + } + } else if firstProp != prRegionalIndicator && firstProp != prL { + width += runeWidth(r, prop) + } + + length += l + if len(b) <= length { + return b, nil, width, grAny | (prop << shiftGraphemePropState) + } + } +} + +// FirstGraphemeClusterInString is like [FirstGraphemeCluster] but its input and +// outputs are strings. +func FirstGraphemeClusterInString(str string, state int) (cluster, rest string, width, newState int) { + // An empty string returns nothing. + if len(str) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRuneInString(str) + if len(str) <= length { // If we're already past the end, there is nothing else to parse. + var prop int + if state < 0 { + prop = propertyGraphemes(r) + } else { + prop = state >> shiftGraphemePropState + } + return str, "", runeWidth(r, prop), grAny | (prop << shiftGraphemePropState) + } + + // If we don't know the state, determine it now. + var firstProp int + if state < 0 { + state, firstProp, _ = transitionGraphemeState(state, r) + } else { + firstProp = state >> shiftGraphemePropState + } + width += runeWidth(r, firstProp) + + // Transition until we find a boundary. + for { + var ( + prop int + boundary bool + ) + + r, l := utf8.DecodeRuneInString(str[length:]) + state, prop, boundary = transitionGraphemeState(state&maskGraphemeState, r) + + if boundary { + return str[:length], str[length:], width, state | (prop << shiftGraphemePropState) + } + + if firstProp == prExtendedPictographic { + if r == vs15 { + width = 1 + } else if r == vs16 { + width = 2 + } + } else if firstProp != prRegionalIndicator && firstProp != prL { + width += runeWidth(r, prop) + } + + length += l + if len(str) <= length { + return str, "", width, grAny | (prop << shiftGraphemePropState) + } + } +} diff --git a/vendor/github.com/rivo/uniseg/graphemeproperties.go b/vendor/github.com/rivo/uniseg/graphemeproperties.go new file mode 100644 index 000000000..0aff4a619 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/graphemeproperties.go @@ -0,0 +1,1915 @@ +// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// graphemeCodePoints are taken from +// https://www.unicode.org/Public/15.0.0/ucd/auxiliary/GraphemeBreakProperty.txt +// and +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt +// ("Extended_Pictographic" only) +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var graphemeCodePoints = [][3]int{ + {0x0000, 0x0009, prControl}, // Cc [10] .. + {0x000A, 0x000A, prLF}, // Cc + {0x000B, 0x000C, prControl}, // Cc [2] .. + {0x000D, 0x000D, prCR}, // Cc + {0x000E, 0x001F, prControl}, // Cc [18] .. + {0x007F, 0x009F, prControl}, // Cc [33] .. + {0x00A9, 0x00A9, prExtendedPictographic}, // E0.6 [1] (©️) copyright + {0x00AD, 0x00AD, prControl}, // Cf SOFT HYPHEN + {0x00AE, 0x00AE, prExtendedPictographic}, // E0.6 [1] (®️) registered + {0x0300, 0x036F, prExtend}, // Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X + {0x0483, 0x0487, prExtend}, // Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE + {0x0488, 0x0489, prExtend}, // Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN + {0x0591, 0x05BD, prExtend}, // Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG + {0x05BF, 0x05BF, prExtend}, // Mn HEBREW POINT RAFE + {0x05C1, 0x05C2, prExtend}, // Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT + {0x05C4, 0x05C5, prExtend}, // Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT + {0x05C7, 0x05C7, prExtend}, // Mn HEBREW POINT QAMATS QATAN + {0x0600, 0x0605, prPrepend}, // Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE + {0x0610, 0x061A, prExtend}, // Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA + {0x061C, 0x061C, prControl}, // Cf ARABIC LETTER MARK + {0x064B, 0x065F, prExtend}, // Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW + {0x0670, 0x0670, prExtend}, // Mn ARABIC LETTER SUPERSCRIPT ALEF + {0x06D6, 0x06DC, prExtend}, // Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN + {0x06DD, 0x06DD, prPrepend}, // Cf ARABIC END OF AYAH + {0x06DF, 0x06E4, prExtend}, // Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA + {0x06E7, 0x06E8, prExtend}, // Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON + {0x06EA, 0x06ED, prExtend}, // Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM + {0x070F, 0x070F, prPrepend}, // Cf SYRIAC ABBREVIATION MARK + {0x0711, 0x0711, prExtend}, // Mn SYRIAC LETTER SUPERSCRIPT ALAPH + {0x0730, 0x074A, prExtend}, // Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH + {0x07A6, 0x07B0, prExtend}, // Mn [11] THAANA ABAFILI..THAANA SUKUN + {0x07EB, 0x07F3, prExtend}, // Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE + {0x07FD, 0x07FD, prExtend}, // Mn NKO DANTAYALAN + {0x0816, 0x0819, prExtend}, // Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH + {0x081B, 0x0823, prExtend}, // Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A + {0x0825, 0x0827, prExtend}, // Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U + {0x0829, 0x082D, prExtend}, // Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA + {0x0859, 0x085B, prExtend}, // Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK + {0x0890, 0x0891, prPrepend}, // Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE + {0x0898, 0x089F, prExtend}, // Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA + {0x08CA, 0x08E1, prExtend}, // Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA + {0x08E2, 0x08E2, prPrepend}, // Cf ARABIC DISPUTED END OF AYAH + {0x08E3, 0x0902, prExtend}, // Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA + {0x0903, 0x0903, prSpacingMark}, // Mc DEVANAGARI SIGN VISARGA + {0x093A, 0x093A, prExtend}, // Mn DEVANAGARI VOWEL SIGN OE + {0x093B, 0x093B, prSpacingMark}, // Mc DEVANAGARI VOWEL SIGN OOE + {0x093C, 0x093C, prExtend}, // Mn DEVANAGARI SIGN NUKTA + {0x093E, 0x0940, prSpacingMark}, // Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II + {0x0941, 0x0948, prExtend}, // Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI + {0x0949, 0x094C, prSpacingMark}, // Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU + {0x094D, 0x094D, prExtend}, // Mn DEVANAGARI SIGN VIRAMA + {0x094E, 0x094F, prSpacingMark}, // Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW + {0x0951, 0x0957, prExtend}, // Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE + {0x0962, 0x0963, prExtend}, // Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL + {0x0981, 0x0981, prExtend}, // Mn BENGALI SIGN CANDRABINDU + {0x0982, 0x0983, prSpacingMark}, // Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA + {0x09BC, 0x09BC, prExtend}, // Mn BENGALI SIGN NUKTA + {0x09BE, 0x09BE, prExtend}, // Mc BENGALI VOWEL SIGN AA + {0x09BF, 0x09C0, prSpacingMark}, // Mc [2] BENGALI VOWEL SIGN I..BENGALI VOWEL SIGN II + {0x09C1, 0x09C4, prExtend}, // Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR + {0x09C7, 0x09C8, prSpacingMark}, // Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI + {0x09CB, 0x09CC, prSpacingMark}, // Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU + {0x09CD, 0x09CD, prExtend}, // Mn BENGALI SIGN VIRAMA + {0x09D7, 0x09D7, prExtend}, // Mc BENGALI AU LENGTH MARK + {0x09E2, 0x09E3, prExtend}, // Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL + {0x09FE, 0x09FE, prExtend}, // Mn BENGALI SANDHI MARK + {0x0A01, 0x0A02, prExtend}, // Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI + {0x0A03, 0x0A03, prSpacingMark}, // Mc GURMUKHI SIGN VISARGA + {0x0A3C, 0x0A3C, prExtend}, // Mn GURMUKHI SIGN NUKTA + {0x0A3E, 0x0A40, prSpacingMark}, // Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II + {0x0A41, 0x0A42, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU + {0x0A47, 0x0A48, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI + {0x0A4B, 0x0A4D, prExtend}, // Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA + {0x0A51, 0x0A51, prExtend}, // Mn GURMUKHI SIGN UDAAT + {0x0A70, 0x0A71, prExtend}, // Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK + {0x0A75, 0x0A75, prExtend}, // Mn GURMUKHI SIGN YAKASH + {0x0A81, 0x0A82, prExtend}, // Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA + {0x0A83, 0x0A83, prSpacingMark}, // Mc GUJARATI SIGN VISARGA + {0x0ABC, 0x0ABC, prExtend}, // Mn GUJARATI SIGN NUKTA + {0x0ABE, 0x0AC0, prSpacingMark}, // Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II + {0x0AC1, 0x0AC5, prExtend}, // Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E + {0x0AC7, 0x0AC8, prExtend}, // Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI + {0x0AC9, 0x0AC9, prSpacingMark}, // Mc GUJARATI VOWEL SIGN CANDRA O + {0x0ACB, 0x0ACC, prSpacingMark}, // Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU + {0x0ACD, 0x0ACD, prExtend}, // Mn GUJARATI SIGN VIRAMA + {0x0AE2, 0x0AE3, prExtend}, // Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL + {0x0AFA, 0x0AFF, prExtend}, // Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE + {0x0B01, 0x0B01, prExtend}, // Mn ORIYA SIGN CANDRABINDU + {0x0B02, 0x0B03, prSpacingMark}, // Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA + {0x0B3C, 0x0B3C, prExtend}, // Mn ORIYA SIGN NUKTA + {0x0B3E, 0x0B3E, prExtend}, // Mc ORIYA VOWEL SIGN AA + {0x0B3F, 0x0B3F, prExtend}, // Mn ORIYA VOWEL SIGN I + {0x0B40, 0x0B40, prSpacingMark}, // Mc ORIYA VOWEL SIGN II + {0x0B41, 0x0B44, prExtend}, // Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR + {0x0B47, 0x0B48, prSpacingMark}, // Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI + {0x0B4B, 0x0B4C, prSpacingMark}, // Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU + {0x0B4D, 0x0B4D, prExtend}, // Mn ORIYA SIGN VIRAMA + {0x0B55, 0x0B56, prExtend}, // Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK + {0x0B57, 0x0B57, prExtend}, // Mc ORIYA AU LENGTH MARK + {0x0B62, 0x0B63, prExtend}, // Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL + {0x0B82, 0x0B82, prExtend}, // Mn TAMIL SIGN ANUSVARA + {0x0BBE, 0x0BBE, prExtend}, // Mc TAMIL VOWEL SIGN AA + {0x0BBF, 0x0BBF, prSpacingMark}, // Mc TAMIL VOWEL SIGN I + {0x0BC0, 0x0BC0, prExtend}, // Mn TAMIL VOWEL SIGN II + {0x0BC1, 0x0BC2, prSpacingMark}, // Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU + {0x0BC6, 0x0BC8, prSpacingMark}, // Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI + {0x0BCA, 0x0BCC, prSpacingMark}, // Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU + {0x0BCD, 0x0BCD, prExtend}, // Mn TAMIL SIGN VIRAMA + {0x0BD7, 0x0BD7, prExtend}, // Mc TAMIL AU LENGTH MARK + {0x0C00, 0x0C00, prExtend}, // Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE + {0x0C01, 0x0C03, prSpacingMark}, // Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA + {0x0C04, 0x0C04, prExtend}, // Mn TELUGU SIGN COMBINING ANUSVARA ABOVE + {0x0C3C, 0x0C3C, prExtend}, // Mn TELUGU SIGN NUKTA + {0x0C3E, 0x0C40, prExtend}, // Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II + {0x0C41, 0x0C44, prSpacingMark}, // Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR + {0x0C46, 0x0C48, prExtend}, // Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI + {0x0C4A, 0x0C4D, prExtend}, // Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA + {0x0C55, 0x0C56, prExtend}, // Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK + {0x0C62, 0x0C63, prExtend}, // Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL + {0x0C81, 0x0C81, prExtend}, // Mn KANNADA SIGN CANDRABINDU + {0x0C82, 0x0C83, prSpacingMark}, // Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA + {0x0CBC, 0x0CBC, prExtend}, // Mn KANNADA SIGN NUKTA + {0x0CBE, 0x0CBE, prSpacingMark}, // Mc KANNADA VOWEL SIGN AA + {0x0CBF, 0x0CBF, prExtend}, // Mn KANNADA VOWEL SIGN I + {0x0CC0, 0x0CC1, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN U + {0x0CC2, 0x0CC2, prExtend}, // Mc KANNADA VOWEL SIGN UU + {0x0CC3, 0x0CC4, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN VOCALIC R..KANNADA VOWEL SIGN VOCALIC RR + {0x0CC6, 0x0CC6, prExtend}, // Mn KANNADA VOWEL SIGN E + {0x0CC7, 0x0CC8, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI + {0x0CCA, 0x0CCB, prSpacingMark}, // Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO + {0x0CCC, 0x0CCD, prExtend}, // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA + {0x0CD5, 0x0CD6, prExtend}, // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK + {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0CF3, 0x0CF3, prSpacingMark}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT + {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU + {0x0D02, 0x0D03, prSpacingMark}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA + {0x0D3B, 0x0D3C, prExtend}, // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA + {0x0D3E, 0x0D3E, prExtend}, // Mc MALAYALAM VOWEL SIGN AA + {0x0D3F, 0x0D40, prSpacingMark}, // Mc [2] MALAYALAM VOWEL SIGN I..MALAYALAM VOWEL SIGN II + {0x0D41, 0x0D44, prExtend}, // Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR + {0x0D46, 0x0D48, prSpacingMark}, // Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI + {0x0D4A, 0x0D4C, prSpacingMark}, // Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU + {0x0D4D, 0x0D4D, prExtend}, // Mn MALAYALAM SIGN VIRAMA + {0x0D4E, 0x0D4E, prPrepend}, // Lo MALAYALAM LETTER DOT REPH + {0x0D57, 0x0D57, prExtend}, // Mc MALAYALAM AU LENGTH MARK + {0x0D62, 0x0D63, prExtend}, // Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL + {0x0D81, 0x0D81, prExtend}, // Mn SINHALA SIGN CANDRABINDU + {0x0D82, 0x0D83, prSpacingMark}, // Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA + {0x0DCA, 0x0DCA, prExtend}, // Mn SINHALA SIGN AL-LAKUNA + {0x0DCF, 0x0DCF, prExtend}, // Mc SINHALA VOWEL SIGN AELA-PILLA + {0x0DD0, 0x0DD1, prSpacingMark}, // Mc [2] SINHALA VOWEL SIGN KETTI AEDA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA + {0x0DD2, 0x0DD4, prExtend}, // Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA + {0x0DD6, 0x0DD6, prExtend}, // Mn SINHALA VOWEL SIGN DIGA PAA-PILLA + {0x0DD8, 0x0DDE, prSpacingMark}, // Mc [7] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA + {0x0DDF, 0x0DDF, prExtend}, // Mc SINHALA VOWEL SIGN GAYANUKITTA + {0x0DF2, 0x0DF3, prSpacingMark}, // Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA + {0x0E31, 0x0E31, prExtend}, // Mn THAI CHARACTER MAI HAN-AKAT + {0x0E33, 0x0E33, prSpacingMark}, // Lo THAI CHARACTER SARA AM + {0x0E34, 0x0E3A, prExtend}, // Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU + {0x0E47, 0x0E4E, prExtend}, // Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN + {0x0EB1, 0x0EB1, prExtend}, // Mn LAO VOWEL SIGN MAI KAN + {0x0EB3, 0x0EB3, prSpacingMark}, // Lo LAO VOWEL SIGN AM + {0x0EB4, 0x0EBC, prExtend}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO + {0x0EC8, 0x0ECE, prExtend}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN + {0x0F18, 0x0F19, prExtend}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS + {0x0F35, 0x0F35, prExtend}, // Mn TIBETAN MARK NGAS BZUNG NYI ZLA + {0x0F37, 0x0F37, prExtend}, // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS + {0x0F39, 0x0F39, prExtend}, // Mn TIBETAN MARK TSA -PHRU + {0x0F3E, 0x0F3F, prSpacingMark}, // Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES + {0x0F71, 0x0F7E, prExtend}, // Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO + {0x0F7F, 0x0F7F, prSpacingMark}, // Mc TIBETAN SIGN RNAM BCAD + {0x0F80, 0x0F84, prExtend}, // Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA + {0x0F86, 0x0F87, prExtend}, // Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS + {0x0F8D, 0x0F97, prExtend}, // Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA + {0x0F99, 0x0FBC, prExtend}, // Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA + {0x0FC6, 0x0FC6, prExtend}, // Mn TIBETAN SYMBOL PADMA GDAN + {0x102D, 0x1030, prExtend}, // Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU + {0x1031, 0x1031, prSpacingMark}, // Mc MYANMAR VOWEL SIGN E + {0x1032, 0x1037, prExtend}, // Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW + {0x1039, 0x103A, prExtend}, // Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT + {0x103B, 0x103C, prSpacingMark}, // Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA + {0x103D, 0x103E, prExtend}, // Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA + {0x1056, 0x1057, prSpacingMark}, // Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR + {0x1058, 0x1059, prExtend}, // Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL + {0x105E, 0x1060, prExtend}, // Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA + {0x1071, 0x1074, prExtend}, // Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE + {0x1082, 0x1082, prExtend}, // Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA + {0x1084, 0x1084, prSpacingMark}, // Mc MYANMAR VOWEL SIGN SHAN E + {0x1085, 0x1086, prExtend}, // Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y + {0x108D, 0x108D, prExtend}, // Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE + {0x109D, 0x109D, prExtend}, // Mn MYANMAR VOWEL SIGN AITON AI + {0x1100, 0x115F, prL}, // Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER + {0x1160, 0x11A7, prV}, // Lo [72] HANGUL JUNGSEONG FILLER..HANGUL JUNGSEONG O-YAE + {0x11A8, 0x11FF, prT}, // Lo [88] HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN + {0x135D, 0x135F, prExtend}, // Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK + {0x1712, 0x1714, prExtend}, // Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + {0x1715, 0x1715, prSpacingMark}, // Mc TAGALOG SIGN PAMUDPOD + {0x1732, 0x1733, prExtend}, // Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U + {0x1734, 0x1734, prSpacingMark}, // Mc HANUNOO SIGN PAMUDPOD + {0x1752, 0x1753, prExtend}, // Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + {0x1772, 0x1773, prExtend}, // Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + {0x17B4, 0x17B5, prExtend}, // Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA + {0x17B6, 0x17B6, prSpacingMark}, // Mc KHMER VOWEL SIGN AA + {0x17B7, 0x17BD, prExtend}, // Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA + {0x17BE, 0x17C5, prSpacingMark}, // Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU + {0x17C6, 0x17C6, prExtend}, // Mn KHMER SIGN NIKAHIT + {0x17C7, 0x17C8, prSpacingMark}, // Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU + {0x17C9, 0x17D3, prExtend}, // Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT + {0x17DD, 0x17DD, prExtend}, // Mn KHMER SIGN ATTHACAN + {0x180B, 0x180D, prExtend}, // Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE + {0x180E, 0x180E, prControl}, // Cf MONGOLIAN VOWEL SEPARATOR + {0x180F, 0x180F, prExtend}, // Mn MONGOLIAN FREE VARIATION SELECTOR FOUR + {0x1885, 0x1886, prExtend}, // Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA + {0x18A9, 0x18A9, prExtend}, // Mn MONGOLIAN LETTER ALI GALI DAGALGA + {0x1920, 0x1922, prExtend}, // Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U + {0x1923, 0x1926, prSpacingMark}, // Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU + {0x1927, 0x1928, prExtend}, // Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O + {0x1929, 0x192B, prSpacingMark}, // Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA + {0x1930, 0x1931, prSpacingMark}, // Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA + {0x1932, 0x1932, prExtend}, // Mn LIMBU SMALL LETTER ANUSVARA + {0x1933, 0x1938, prSpacingMark}, // Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA + {0x1939, 0x193B, prExtend}, // Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I + {0x1A17, 0x1A18, prExtend}, // Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U + {0x1A19, 0x1A1A, prSpacingMark}, // Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O + {0x1A1B, 0x1A1B, prExtend}, // Mn BUGINESE VOWEL SIGN AE + {0x1A55, 0x1A55, prSpacingMark}, // Mc TAI THAM CONSONANT SIGN MEDIAL RA + {0x1A56, 0x1A56, prExtend}, // Mn TAI THAM CONSONANT SIGN MEDIAL LA + {0x1A57, 0x1A57, prSpacingMark}, // Mc TAI THAM CONSONANT SIGN LA TANG LAI + {0x1A58, 0x1A5E, prExtend}, // Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA + {0x1A60, 0x1A60, prExtend}, // Mn TAI THAM SIGN SAKOT + {0x1A62, 0x1A62, prExtend}, // Mn TAI THAM VOWEL SIGN MAI SAT + {0x1A65, 0x1A6C, prExtend}, // Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW + {0x1A6D, 0x1A72, prSpacingMark}, // Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI + {0x1A73, 0x1A7C, prExtend}, // Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN + {0x1A7F, 0x1A7F, prExtend}, // Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT + {0x1AB0, 0x1ABD, prExtend}, // Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW + {0x1ABE, 0x1ABE, prExtend}, // Me COMBINING PARENTHESES OVERLAY + {0x1ABF, 0x1ACE, prExtend}, // Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T + {0x1B00, 0x1B03, prExtend}, // Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG + {0x1B04, 0x1B04, prSpacingMark}, // Mc BALINESE SIGN BISAH + {0x1B34, 0x1B34, prExtend}, // Mn BALINESE SIGN REREKAN + {0x1B35, 0x1B35, prExtend}, // Mc BALINESE VOWEL SIGN TEDUNG + {0x1B36, 0x1B3A, prExtend}, // Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA + {0x1B3B, 0x1B3B, prSpacingMark}, // Mc BALINESE VOWEL SIGN RA REPA TEDUNG + {0x1B3C, 0x1B3C, prExtend}, // Mn BALINESE VOWEL SIGN LA LENGA + {0x1B3D, 0x1B41, prSpacingMark}, // Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG + {0x1B42, 0x1B42, prExtend}, // Mn BALINESE VOWEL SIGN PEPET + {0x1B43, 0x1B44, prSpacingMark}, // Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG + {0x1B6B, 0x1B73, prExtend}, // Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG + {0x1B80, 0x1B81, prExtend}, // Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR + {0x1B82, 0x1B82, prSpacingMark}, // Mc SUNDANESE SIGN PANGWISAD + {0x1BA1, 0x1BA1, prSpacingMark}, // Mc SUNDANESE CONSONANT SIGN PAMINGKAL + {0x1BA2, 0x1BA5, prExtend}, // Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU + {0x1BA6, 0x1BA7, prSpacingMark}, // Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG + {0x1BA8, 0x1BA9, prExtend}, // Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG + {0x1BAA, 0x1BAA, prSpacingMark}, // Mc SUNDANESE SIGN PAMAAEH + {0x1BAB, 0x1BAD, prExtend}, // Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA + {0x1BE6, 0x1BE6, prExtend}, // Mn BATAK SIGN TOMPI + {0x1BE7, 0x1BE7, prSpacingMark}, // Mc BATAK VOWEL SIGN E + {0x1BE8, 0x1BE9, prExtend}, // Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE + {0x1BEA, 0x1BEC, prSpacingMark}, // Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O + {0x1BED, 0x1BED, prExtend}, // Mn BATAK VOWEL SIGN KARO O + {0x1BEE, 0x1BEE, prSpacingMark}, // Mc BATAK VOWEL SIGN U + {0x1BEF, 0x1BF1, prExtend}, // Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H + {0x1BF2, 0x1BF3, prSpacingMark}, // Mc [2] BATAK PANGOLAT..BATAK PANONGONAN + {0x1C24, 0x1C2B, prSpacingMark}, // Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU + {0x1C2C, 0x1C33, prExtend}, // Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T + {0x1C34, 0x1C35, prSpacingMark}, // Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG + {0x1C36, 0x1C37, prExtend}, // Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA + {0x1CD0, 0x1CD2, prExtend}, // Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA + {0x1CD4, 0x1CE0, prExtend}, // Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA + {0x1CE1, 0x1CE1, prSpacingMark}, // Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA + {0x1CE2, 0x1CE8, prExtend}, // Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL + {0x1CED, 0x1CED, prExtend}, // Mn VEDIC SIGN TIRYAK + {0x1CF4, 0x1CF4, prExtend}, // Mn VEDIC TONE CANDRA ABOVE + {0x1CF7, 0x1CF7, prSpacingMark}, // Mc VEDIC SIGN ATIKRAMA + {0x1CF8, 0x1CF9, prExtend}, // Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE + {0x1DC0, 0x1DFF, prExtend}, // Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x200B, 0x200B, prControl}, // Cf ZERO WIDTH SPACE + {0x200C, 0x200C, prExtend}, // Cf ZERO WIDTH NON-JOINER + {0x200D, 0x200D, prZWJ}, // Cf ZERO WIDTH JOINER + {0x200E, 0x200F, prControl}, // Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK + {0x2028, 0x2028, prControl}, // Zl LINE SEPARATOR + {0x2029, 0x2029, prControl}, // Zp PARAGRAPH SEPARATOR + {0x202A, 0x202E, prControl}, // Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE + {0x203C, 0x203C, prExtendedPictographic}, // E0.6 [1] (‼️) double exclamation mark + {0x2049, 0x2049, prExtendedPictographic}, // E0.6 [1] (⁉️) exclamation question mark + {0x2060, 0x2064, prControl}, // Cf [5] WORD JOINER..INVISIBLE PLUS + {0x2065, 0x2065, prControl}, // Cn + {0x2066, 0x206F, prControl}, // Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES + {0x20D0, 0x20DC, prExtend}, // Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE + {0x20DD, 0x20E0, prExtend}, // Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH + {0x20E1, 0x20E1, prExtend}, // Mn COMBINING LEFT RIGHT ARROW ABOVE + {0x20E2, 0x20E4, prExtend}, // Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE + {0x20E5, 0x20F0, prExtend}, // Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE + {0x2122, 0x2122, prExtendedPictographic}, // E0.6 [1] (™️) trade mark + {0x2139, 0x2139, prExtendedPictographic}, // E0.6 [1] (ℹ️) information + {0x2194, 0x2199, prExtendedPictographic}, // E0.6 [6] (↔️..↙️) left-right arrow..down-left arrow + {0x21A9, 0x21AA, prExtendedPictographic}, // E0.6 [2] (↩️..↪️) right arrow curving left..left arrow curving right + {0x231A, 0x231B, prExtendedPictographic}, // E0.6 [2] (⌚..⌛) watch..hourglass done + {0x2328, 0x2328, prExtendedPictographic}, // E1.0 [1] (⌨️) keyboard + {0x2388, 0x2388, prExtendedPictographic}, // E0.0 [1] (⎈) HELM SYMBOL + {0x23CF, 0x23CF, prExtendedPictographic}, // E1.0 [1] (⏏️) eject button + {0x23E9, 0x23EC, prExtendedPictographic}, // E0.6 [4] (⏩..⏬) fast-forward button..fast down button + {0x23ED, 0x23EE, prExtendedPictographic}, // E0.7 [2] (⏭️..⏮️) next track button..last track button + {0x23EF, 0x23EF, prExtendedPictographic}, // E1.0 [1] (⏯️) play or pause button + {0x23F0, 0x23F0, prExtendedPictographic}, // E0.6 [1] (⏰) alarm clock + {0x23F1, 0x23F2, prExtendedPictographic}, // E1.0 [2] (⏱️..⏲️) stopwatch..timer clock + {0x23F3, 0x23F3, prExtendedPictographic}, // E0.6 [1] (⏳) hourglass not done + {0x23F8, 0x23FA, prExtendedPictographic}, // E0.7 [3] (⏸️..⏺️) pause button..record button + {0x24C2, 0x24C2, prExtendedPictographic}, // E0.6 [1] (Ⓜ️) circled M + {0x25AA, 0x25AB, prExtendedPictographic}, // E0.6 [2] (▪️..▫️) black small square..white small square + {0x25B6, 0x25B6, prExtendedPictographic}, // E0.6 [1] (▶️) play button + {0x25C0, 0x25C0, prExtendedPictographic}, // E0.6 [1] (◀️) reverse button + {0x25FB, 0x25FE, prExtendedPictographic}, // E0.6 [4] (◻️..◾) white medium square..black medium-small square + {0x2600, 0x2601, prExtendedPictographic}, // E0.6 [2] (☀️..☁️) sun..cloud + {0x2602, 0x2603, prExtendedPictographic}, // E0.7 [2] (☂️..☃️) umbrella..snowman + {0x2604, 0x2604, prExtendedPictographic}, // E1.0 [1] (☄️) comet + {0x2605, 0x2605, prExtendedPictographic}, // E0.0 [1] (★) BLACK STAR + {0x2607, 0x260D, prExtendedPictographic}, // E0.0 [7] (☇..☍) LIGHTNING..OPPOSITION + {0x260E, 0x260E, prExtendedPictographic}, // E0.6 [1] (☎️) telephone + {0x260F, 0x2610, prExtendedPictographic}, // E0.0 [2] (☏..☐) WHITE TELEPHONE..BALLOT BOX + {0x2611, 0x2611, prExtendedPictographic}, // E0.6 [1] (☑️) check box with check + {0x2612, 0x2612, prExtendedPictographic}, // E0.0 [1] (☒) BALLOT BOX WITH X + {0x2614, 0x2615, prExtendedPictographic}, // E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage + {0x2616, 0x2617, prExtendedPictographic}, // E0.0 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE + {0x2618, 0x2618, prExtendedPictographic}, // E1.0 [1] (☘️) shamrock + {0x2619, 0x261C, prExtendedPictographic}, // E0.0 [4] (☙..☜) REVERSED ROTATED FLORAL HEART BULLET..WHITE LEFT POINTING INDEX + {0x261D, 0x261D, prExtendedPictographic}, // E0.6 [1] (☝️) index pointing up + {0x261E, 0x261F, prExtendedPictographic}, // E0.0 [2] (☞..☟) WHITE RIGHT POINTING INDEX..WHITE DOWN POINTING INDEX + {0x2620, 0x2620, prExtendedPictographic}, // E1.0 [1] (☠️) skull and crossbones + {0x2621, 0x2621, prExtendedPictographic}, // E0.0 [1] (☡) CAUTION SIGN + {0x2622, 0x2623, prExtendedPictographic}, // E1.0 [2] (☢️..☣️) radioactive..biohazard + {0x2624, 0x2625, prExtendedPictographic}, // E0.0 [2] (☤..☥) CADUCEUS..ANKH + {0x2626, 0x2626, prExtendedPictographic}, // E1.0 [1] (☦️) orthodox cross + {0x2627, 0x2629, prExtendedPictographic}, // E0.0 [3] (☧..☩) CHI RHO..CROSS OF JERUSALEM + {0x262A, 0x262A, prExtendedPictographic}, // E0.7 [1] (☪️) star and crescent + {0x262B, 0x262D, prExtendedPictographic}, // E0.0 [3] (☫..☭) FARSI SYMBOL..HAMMER AND SICKLE + {0x262E, 0x262E, prExtendedPictographic}, // E1.0 [1] (☮️) peace symbol + {0x262F, 0x262F, prExtendedPictographic}, // E0.7 [1] (☯️) yin yang + {0x2630, 0x2637, prExtendedPictographic}, // E0.0 [8] (☰..☷) TRIGRAM FOR HEAVEN..TRIGRAM FOR EARTH + {0x2638, 0x2639, prExtendedPictographic}, // E0.7 [2] (☸️..☹️) wheel of dharma..frowning face + {0x263A, 0x263A, prExtendedPictographic}, // E0.6 [1] (☺️) smiling face + {0x263B, 0x263F, prExtendedPictographic}, // E0.0 [5] (☻..☿) BLACK SMILING FACE..MERCURY + {0x2640, 0x2640, prExtendedPictographic}, // E4.0 [1] (♀️) female sign + {0x2641, 0x2641, prExtendedPictographic}, // E0.0 [1] (♁) EARTH + {0x2642, 0x2642, prExtendedPictographic}, // E4.0 [1] (♂️) male sign + {0x2643, 0x2647, prExtendedPictographic}, // E0.0 [5] (♃..♇) JUPITER..PLUTO + {0x2648, 0x2653, prExtendedPictographic}, // E0.6 [12] (♈..♓) Aries..Pisces + {0x2654, 0x265E, prExtendedPictographic}, // E0.0 [11] (♔..♞) WHITE CHESS KING..BLACK CHESS KNIGHT + {0x265F, 0x265F, prExtendedPictographic}, // E11.0 [1] (♟️) chess pawn + {0x2660, 0x2660, prExtendedPictographic}, // E0.6 [1] (♠️) spade suit + {0x2661, 0x2662, prExtendedPictographic}, // E0.0 [2] (♡..♢) WHITE HEART SUIT..WHITE DIAMOND SUIT + {0x2663, 0x2663, prExtendedPictographic}, // E0.6 [1] (♣️) club suit + {0x2664, 0x2664, prExtendedPictographic}, // E0.0 [1] (♤) WHITE SPADE SUIT + {0x2665, 0x2666, prExtendedPictographic}, // E0.6 [2] (♥️..♦️) heart suit..diamond suit + {0x2667, 0x2667, prExtendedPictographic}, // E0.0 [1] (♧) WHITE CLUB SUIT + {0x2668, 0x2668, prExtendedPictographic}, // E0.6 [1] (♨️) hot springs + {0x2669, 0x267A, prExtendedPictographic}, // E0.0 [18] (♩..♺) QUARTER NOTE..RECYCLING SYMBOL FOR GENERIC MATERIALS + {0x267B, 0x267B, prExtendedPictographic}, // E0.6 [1] (♻️) recycling symbol + {0x267C, 0x267D, prExtendedPictographic}, // E0.0 [2] (♼..♽) RECYCLED PAPER SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL + {0x267E, 0x267E, prExtendedPictographic}, // E11.0 [1] (♾️) infinity + {0x267F, 0x267F, prExtendedPictographic}, // E0.6 [1] (♿) wheelchair symbol + {0x2680, 0x2685, prExtendedPictographic}, // E0.0 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6 + {0x2690, 0x2691, prExtendedPictographic}, // E0.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG + {0x2692, 0x2692, prExtendedPictographic}, // E1.0 [1] (⚒️) hammer and pick + {0x2693, 0x2693, prExtendedPictographic}, // E0.6 [1] (⚓) anchor + {0x2694, 0x2694, prExtendedPictographic}, // E1.0 [1] (⚔️) crossed swords + {0x2695, 0x2695, prExtendedPictographic}, // E4.0 [1] (⚕️) medical symbol + {0x2696, 0x2697, prExtendedPictographic}, // E1.0 [2] (⚖️..⚗️) balance scale..alembic + {0x2698, 0x2698, prExtendedPictographic}, // E0.0 [1] (⚘) FLOWER + {0x2699, 0x2699, prExtendedPictographic}, // E1.0 [1] (⚙️) gear + {0x269A, 0x269A, prExtendedPictographic}, // E0.0 [1] (⚚) STAFF OF HERMES + {0x269B, 0x269C, prExtendedPictographic}, // E1.0 [2] (⚛️..⚜️) atom symbol..fleur-de-lis + {0x269D, 0x269F, prExtendedPictographic}, // E0.0 [3] (⚝..⚟) OUTLINED WHITE STAR..THREE LINES CONVERGING LEFT + {0x26A0, 0x26A1, prExtendedPictographic}, // E0.6 [2] (⚠️..⚡) warning..high voltage + {0x26A2, 0x26A6, prExtendedPictographic}, // E0.0 [5] (⚢..⚦) DOUBLED FEMALE SIGN..MALE WITH STROKE SIGN + {0x26A7, 0x26A7, prExtendedPictographic}, // E13.0 [1] (⚧️) transgender symbol + {0x26A8, 0x26A9, prExtendedPictographic}, // E0.0 [2] (⚨..⚩) VERTICAL MALE WITH STROKE SIGN..HORIZONTAL MALE WITH STROKE SIGN + {0x26AA, 0x26AB, prExtendedPictographic}, // E0.6 [2] (⚪..⚫) white circle..black circle + {0x26AC, 0x26AF, prExtendedPictographic}, // E0.0 [4] (⚬..⚯) MEDIUM SMALL WHITE CIRCLE..UNMARRIED PARTNERSHIP SYMBOL + {0x26B0, 0x26B1, prExtendedPictographic}, // E1.0 [2] (⚰️..⚱️) coffin..funeral urn + {0x26B2, 0x26BC, prExtendedPictographic}, // E0.0 [11] (⚲..⚼) NEUTER..SESQUIQUADRATE + {0x26BD, 0x26BE, prExtendedPictographic}, // E0.6 [2] (⚽..⚾) soccer ball..baseball + {0x26BF, 0x26C3, prExtendedPictographic}, // E0.0 [5] (⚿..⛃) SQUARED KEY..BLACK DRAUGHTS KING + {0x26C4, 0x26C5, prExtendedPictographic}, // E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud + {0x26C6, 0x26C7, prExtendedPictographic}, // E0.0 [2] (⛆..⛇) RAIN..BLACK SNOWMAN + {0x26C8, 0x26C8, prExtendedPictographic}, // E0.7 [1] (⛈️) cloud with lightning and rain + {0x26C9, 0x26CD, prExtendedPictographic}, // E0.0 [5] (⛉..⛍) TURNED WHITE SHOGI PIECE..DISABLED CAR + {0x26CE, 0x26CE, prExtendedPictographic}, // E0.6 [1] (⛎) Ophiuchus + {0x26CF, 0x26CF, prExtendedPictographic}, // E0.7 [1] (⛏️) pick + {0x26D0, 0x26D0, prExtendedPictographic}, // E0.0 [1] (⛐) CAR SLIDING + {0x26D1, 0x26D1, prExtendedPictographic}, // E0.7 [1] (⛑️) rescue worker’s helmet + {0x26D2, 0x26D2, prExtendedPictographic}, // E0.0 [1] (⛒) CIRCLED CROSSING LANES + {0x26D3, 0x26D3, prExtendedPictographic}, // E0.7 [1] (⛓️) chains + {0x26D4, 0x26D4, prExtendedPictographic}, // E0.6 [1] (⛔) no entry + {0x26D5, 0x26E8, prExtendedPictographic}, // E0.0 [20] (⛕..⛨) ALTERNATE ONE-WAY LEFT WAY TRAFFIC..BLACK CROSS ON SHIELD + {0x26E9, 0x26E9, prExtendedPictographic}, // E0.7 [1] (⛩️) shinto shrine + {0x26EA, 0x26EA, prExtendedPictographic}, // E0.6 [1] (⛪) church + {0x26EB, 0x26EF, prExtendedPictographic}, // E0.0 [5] (⛫..⛯) CASTLE..MAP SYMBOL FOR LIGHTHOUSE + {0x26F0, 0x26F1, prExtendedPictographic}, // E0.7 [2] (⛰️..⛱️) mountain..umbrella on ground + {0x26F2, 0x26F3, prExtendedPictographic}, // E0.6 [2] (⛲..⛳) fountain..flag in hole + {0x26F4, 0x26F4, prExtendedPictographic}, // E0.7 [1] (⛴️) ferry + {0x26F5, 0x26F5, prExtendedPictographic}, // E0.6 [1] (⛵) sailboat + {0x26F6, 0x26F6, prExtendedPictographic}, // E0.0 [1] (⛶) SQUARE FOUR CORNERS + {0x26F7, 0x26F9, prExtendedPictographic}, // E0.7 [3] (⛷️..⛹️) skier..person bouncing ball + {0x26FA, 0x26FA, prExtendedPictographic}, // E0.6 [1] (⛺) tent + {0x26FB, 0x26FC, prExtendedPictographic}, // E0.0 [2] (⛻..⛼) JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL + {0x26FD, 0x26FD, prExtendedPictographic}, // E0.6 [1] (⛽) fuel pump + {0x26FE, 0x2701, prExtendedPictographic}, // E0.0 [4] (⛾..✁) CUP ON BLACK SQUARE..UPPER BLADE SCISSORS + {0x2702, 0x2702, prExtendedPictographic}, // E0.6 [1] (✂️) scissors + {0x2703, 0x2704, prExtendedPictographic}, // E0.0 [2] (✃..✄) LOWER BLADE SCISSORS..WHITE SCISSORS + {0x2705, 0x2705, prExtendedPictographic}, // E0.6 [1] (✅) check mark button + {0x2708, 0x270C, prExtendedPictographic}, // E0.6 [5] (✈️..✌️) airplane..victory hand + {0x270D, 0x270D, prExtendedPictographic}, // E0.7 [1] (✍️) writing hand + {0x270E, 0x270E, prExtendedPictographic}, // E0.0 [1] (✎) LOWER RIGHT PENCIL + {0x270F, 0x270F, prExtendedPictographic}, // E0.6 [1] (✏️) pencil + {0x2710, 0x2711, prExtendedPictographic}, // E0.0 [2] (✐..✑) UPPER RIGHT PENCIL..WHITE NIB + {0x2712, 0x2712, prExtendedPictographic}, // E0.6 [1] (✒️) black nib + {0x2714, 0x2714, prExtendedPictographic}, // E0.6 [1] (✔️) check mark + {0x2716, 0x2716, prExtendedPictographic}, // E0.6 [1] (✖️) multiply + {0x271D, 0x271D, prExtendedPictographic}, // E0.7 [1] (✝️) latin cross + {0x2721, 0x2721, prExtendedPictographic}, // E0.7 [1] (✡️) star of David + {0x2728, 0x2728, prExtendedPictographic}, // E0.6 [1] (✨) sparkles + {0x2733, 0x2734, prExtendedPictographic}, // E0.6 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star + {0x2744, 0x2744, prExtendedPictographic}, // E0.6 [1] (❄️) snowflake + {0x2747, 0x2747, prExtendedPictographic}, // E0.6 [1] (❇️) sparkle + {0x274C, 0x274C, prExtendedPictographic}, // E0.6 [1] (❌) cross mark + {0x274E, 0x274E, prExtendedPictographic}, // E0.6 [1] (❎) cross mark button + {0x2753, 0x2755, prExtendedPictographic}, // E0.6 [3] (❓..❕) red question mark..white exclamation mark + {0x2757, 0x2757, prExtendedPictographic}, // E0.6 [1] (❗) red exclamation mark + {0x2763, 0x2763, prExtendedPictographic}, // E1.0 [1] (❣️) heart exclamation + {0x2764, 0x2764, prExtendedPictographic}, // E0.6 [1] (❤️) red heart + {0x2765, 0x2767, prExtendedPictographic}, // E0.0 [3] (❥..❧) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET + {0x2795, 0x2797, prExtendedPictographic}, // E0.6 [3] (➕..➗) plus..divide + {0x27A1, 0x27A1, prExtendedPictographic}, // E0.6 [1] (➡️) right arrow + {0x27B0, 0x27B0, prExtendedPictographic}, // E0.6 [1] (➰) curly loop + {0x27BF, 0x27BF, prExtendedPictographic}, // E1.0 [1] (➿) double curly loop + {0x2934, 0x2935, prExtendedPictographic}, // E0.6 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down + {0x2B05, 0x2B07, prExtendedPictographic}, // E0.6 [3] (⬅️..⬇️) left arrow..down arrow + {0x2B1B, 0x2B1C, prExtendedPictographic}, // E0.6 [2] (⬛..⬜) black large square..white large square + {0x2B50, 0x2B50, prExtendedPictographic}, // E0.6 [1] (⭐) star + {0x2B55, 0x2B55, prExtendedPictographic}, // E0.6 [1] (⭕) hollow red circle + {0x2CEF, 0x2CF1, prExtend}, // Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS + {0x2D7F, 0x2D7F, prExtend}, // Mn TIFINAGH CONSONANT JOINER + {0x2DE0, 0x2DFF, prExtend}, // Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS + {0x302A, 0x302D, prExtend}, // Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK + {0x302E, 0x302F, prExtend}, // Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK + {0x3030, 0x3030, prExtendedPictographic}, // E0.6 [1] (〰️) wavy dash + {0x303D, 0x303D, prExtendedPictographic}, // E0.6 [1] (〽️) part alternation mark + {0x3099, 0x309A, prExtend}, // Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x3297, 0x3297, prExtendedPictographic}, // E0.6 [1] (㊗️) Japanese “congratulations” button + {0x3299, 0x3299, prExtendedPictographic}, // E0.6 [1] (㊙️) Japanese “secret” button + {0xA66F, 0xA66F, prExtend}, // Mn COMBINING CYRILLIC VZMET + {0xA670, 0xA672, prExtend}, // Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN + {0xA674, 0xA67D, prExtend}, // Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK + {0xA69E, 0xA69F, prExtend}, // Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E + {0xA6F0, 0xA6F1, prExtend}, // Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS + {0xA802, 0xA802, prExtend}, // Mn SYLOTI NAGRI SIGN DVISVARA + {0xA806, 0xA806, prExtend}, // Mn SYLOTI NAGRI SIGN HASANTA + {0xA80B, 0xA80B, prExtend}, // Mn SYLOTI NAGRI SIGN ANUSVARA + {0xA823, 0xA824, prSpacingMark}, // Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I + {0xA825, 0xA826, prExtend}, // Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E + {0xA827, 0xA827, prSpacingMark}, // Mc SYLOTI NAGRI VOWEL SIGN OO + {0xA82C, 0xA82C, prExtend}, // Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA + {0xA880, 0xA881, prSpacingMark}, // Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA + {0xA8B4, 0xA8C3, prSpacingMark}, // Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU + {0xA8C4, 0xA8C5, prExtend}, // Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU + {0xA8E0, 0xA8F1, prExtend}, // Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA + {0xA8FF, 0xA8FF, prExtend}, // Mn DEVANAGARI VOWEL SIGN AY + {0xA926, 0xA92D, prExtend}, // Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU + {0xA947, 0xA951, prExtend}, // Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R + {0xA952, 0xA953, prSpacingMark}, // Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA + {0xA960, 0xA97C, prL}, // Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH + {0xA980, 0xA982, prExtend}, // Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR + {0xA983, 0xA983, prSpacingMark}, // Mc JAVANESE SIGN WIGNYAN + {0xA9B3, 0xA9B3, prExtend}, // Mn JAVANESE SIGN CECAK TELU + {0xA9B4, 0xA9B5, prSpacingMark}, // Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG + {0xA9B6, 0xA9B9, prExtend}, // Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT + {0xA9BA, 0xA9BB, prSpacingMark}, // Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE + {0xA9BC, 0xA9BD, prExtend}, // Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET + {0xA9BE, 0xA9C0, prSpacingMark}, // Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON + {0xA9E5, 0xA9E5, prExtend}, // Mn MYANMAR SIGN SHAN SAW + {0xAA29, 0xAA2E, prExtend}, // Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE + {0xAA2F, 0xAA30, prSpacingMark}, // Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI + {0xAA31, 0xAA32, prExtend}, // Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE + {0xAA33, 0xAA34, prSpacingMark}, // Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA + {0xAA35, 0xAA36, prExtend}, // Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA + {0xAA43, 0xAA43, prExtend}, // Mn CHAM CONSONANT SIGN FINAL NG + {0xAA4C, 0xAA4C, prExtend}, // Mn CHAM CONSONANT SIGN FINAL M + {0xAA4D, 0xAA4D, prSpacingMark}, // Mc CHAM CONSONANT SIGN FINAL H + {0xAA7C, 0xAA7C, prExtend}, // Mn MYANMAR SIGN TAI LAING TONE-2 + {0xAAB0, 0xAAB0, prExtend}, // Mn TAI VIET MAI KANG + {0xAAB2, 0xAAB4, prExtend}, // Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U + {0xAAB7, 0xAAB8, prExtend}, // Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA + {0xAABE, 0xAABF, prExtend}, // Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK + {0xAAC1, 0xAAC1, prExtend}, // Mn TAI VIET TONE MAI THO + {0xAAEB, 0xAAEB, prSpacingMark}, // Mc MEETEI MAYEK VOWEL SIGN II + {0xAAEC, 0xAAED, prExtend}, // Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI + {0xAAEE, 0xAAEF, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU + {0xAAF5, 0xAAF5, prSpacingMark}, // Mc MEETEI MAYEK VOWEL SIGN VISARGA + {0xAAF6, 0xAAF6, prExtend}, // Mn MEETEI MAYEK VIRAMA + {0xABE3, 0xABE4, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP + {0xABE5, 0xABE5, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN ANAP + {0xABE6, 0xABE7, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP + {0xABE8, 0xABE8, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN UNAP + {0xABE9, 0xABEA, prSpacingMark}, // Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG + {0xABEC, 0xABEC, prSpacingMark}, // Mc MEETEI MAYEK LUM IYEK + {0xABED, 0xABED, prExtend}, // Mn MEETEI MAYEK APUN IYEK + {0xAC00, 0xAC00, prLV}, // Lo HANGUL SYLLABLE GA + {0xAC01, 0xAC1B, prLVT}, // Lo [27] HANGUL SYLLABLE GAG..HANGUL SYLLABLE GAH + {0xAC1C, 0xAC1C, prLV}, // Lo HANGUL SYLLABLE GAE + {0xAC1D, 0xAC37, prLVT}, // Lo [27] HANGUL SYLLABLE GAEG..HANGUL SYLLABLE GAEH + {0xAC38, 0xAC38, prLV}, // Lo HANGUL SYLLABLE GYA + {0xAC39, 0xAC53, prLVT}, // Lo [27] HANGUL SYLLABLE GYAG..HANGUL SYLLABLE GYAH + {0xAC54, 0xAC54, prLV}, // Lo HANGUL SYLLABLE GYAE + {0xAC55, 0xAC6F, prLVT}, // Lo [27] HANGUL SYLLABLE GYAEG..HANGUL SYLLABLE GYAEH + {0xAC70, 0xAC70, prLV}, // Lo HANGUL SYLLABLE GEO + {0xAC71, 0xAC8B, prLVT}, // Lo [27] HANGUL SYLLABLE GEOG..HANGUL SYLLABLE GEOH + {0xAC8C, 0xAC8C, prLV}, // Lo HANGUL SYLLABLE GE + {0xAC8D, 0xACA7, prLVT}, // Lo [27] HANGUL SYLLABLE GEG..HANGUL SYLLABLE GEH + {0xACA8, 0xACA8, prLV}, // Lo HANGUL SYLLABLE GYEO + {0xACA9, 0xACC3, prLVT}, // Lo [27] HANGUL SYLLABLE GYEOG..HANGUL SYLLABLE GYEOH + {0xACC4, 0xACC4, prLV}, // Lo HANGUL SYLLABLE GYE + {0xACC5, 0xACDF, prLVT}, // Lo [27] HANGUL SYLLABLE GYEG..HANGUL SYLLABLE GYEH + {0xACE0, 0xACE0, prLV}, // Lo HANGUL SYLLABLE GO + {0xACE1, 0xACFB, prLVT}, // Lo [27] HANGUL SYLLABLE GOG..HANGUL SYLLABLE GOH + {0xACFC, 0xACFC, prLV}, // Lo HANGUL SYLLABLE GWA + {0xACFD, 0xAD17, prLVT}, // Lo [27] HANGUL SYLLABLE GWAG..HANGUL SYLLABLE GWAH + {0xAD18, 0xAD18, prLV}, // Lo HANGUL SYLLABLE GWAE + {0xAD19, 0xAD33, prLVT}, // Lo [27] HANGUL SYLLABLE GWAEG..HANGUL SYLLABLE GWAEH + {0xAD34, 0xAD34, prLV}, // Lo HANGUL SYLLABLE GOE + {0xAD35, 0xAD4F, prLVT}, // Lo [27] HANGUL SYLLABLE GOEG..HANGUL SYLLABLE GOEH + {0xAD50, 0xAD50, prLV}, // Lo HANGUL SYLLABLE GYO + {0xAD51, 0xAD6B, prLVT}, // Lo [27] HANGUL SYLLABLE GYOG..HANGUL SYLLABLE GYOH + {0xAD6C, 0xAD6C, prLV}, // Lo HANGUL SYLLABLE GU + {0xAD6D, 0xAD87, prLVT}, // Lo [27] HANGUL SYLLABLE GUG..HANGUL SYLLABLE GUH + {0xAD88, 0xAD88, prLV}, // Lo HANGUL SYLLABLE GWEO + {0xAD89, 0xADA3, prLVT}, // Lo [27] HANGUL SYLLABLE GWEOG..HANGUL SYLLABLE GWEOH + {0xADA4, 0xADA4, prLV}, // Lo HANGUL SYLLABLE GWE + {0xADA5, 0xADBF, prLVT}, // Lo [27] HANGUL SYLLABLE GWEG..HANGUL SYLLABLE GWEH + {0xADC0, 0xADC0, prLV}, // Lo HANGUL SYLLABLE GWI + {0xADC1, 0xADDB, prLVT}, // Lo [27] HANGUL SYLLABLE GWIG..HANGUL SYLLABLE GWIH + {0xADDC, 0xADDC, prLV}, // Lo HANGUL SYLLABLE GYU + {0xADDD, 0xADF7, prLVT}, // Lo [27] HANGUL SYLLABLE GYUG..HANGUL SYLLABLE GYUH + {0xADF8, 0xADF8, prLV}, // Lo HANGUL SYLLABLE GEU + {0xADF9, 0xAE13, prLVT}, // Lo [27] HANGUL SYLLABLE GEUG..HANGUL SYLLABLE GEUH + {0xAE14, 0xAE14, prLV}, // Lo HANGUL SYLLABLE GYI + {0xAE15, 0xAE2F, prLVT}, // Lo [27] HANGUL SYLLABLE GYIG..HANGUL SYLLABLE GYIH + {0xAE30, 0xAE30, prLV}, // Lo HANGUL SYLLABLE GI + {0xAE31, 0xAE4B, prLVT}, // Lo [27] HANGUL SYLLABLE GIG..HANGUL SYLLABLE GIH + {0xAE4C, 0xAE4C, prLV}, // Lo HANGUL SYLLABLE GGA + {0xAE4D, 0xAE67, prLVT}, // Lo [27] HANGUL SYLLABLE GGAG..HANGUL SYLLABLE GGAH + {0xAE68, 0xAE68, prLV}, // Lo HANGUL SYLLABLE GGAE + {0xAE69, 0xAE83, prLVT}, // Lo [27] HANGUL SYLLABLE GGAEG..HANGUL SYLLABLE GGAEH + {0xAE84, 0xAE84, prLV}, // Lo HANGUL SYLLABLE GGYA + {0xAE85, 0xAE9F, prLVT}, // Lo [27] HANGUL SYLLABLE GGYAG..HANGUL SYLLABLE GGYAH + {0xAEA0, 0xAEA0, prLV}, // Lo HANGUL SYLLABLE GGYAE + {0xAEA1, 0xAEBB, prLVT}, // Lo [27] HANGUL SYLLABLE GGYAEG..HANGUL SYLLABLE GGYAEH + {0xAEBC, 0xAEBC, prLV}, // Lo HANGUL SYLLABLE GGEO + {0xAEBD, 0xAED7, prLVT}, // Lo [27] HANGUL SYLLABLE GGEOG..HANGUL SYLLABLE GGEOH + {0xAED8, 0xAED8, prLV}, // Lo HANGUL SYLLABLE GGE + {0xAED9, 0xAEF3, prLVT}, // Lo [27] HANGUL SYLLABLE GGEG..HANGUL SYLLABLE GGEH + {0xAEF4, 0xAEF4, prLV}, // Lo HANGUL SYLLABLE GGYEO + {0xAEF5, 0xAF0F, prLVT}, // Lo [27] HANGUL SYLLABLE GGYEOG..HANGUL SYLLABLE GGYEOH + {0xAF10, 0xAF10, prLV}, // Lo HANGUL SYLLABLE GGYE + {0xAF11, 0xAF2B, prLVT}, // Lo [27] HANGUL SYLLABLE GGYEG..HANGUL SYLLABLE GGYEH + {0xAF2C, 0xAF2C, prLV}, // Lo HANGUL SYLLABLE GGO + {0xAF2D, 0xAF47, prLVT}, // Lo [27] HANGUL SYLLABLE GGOG..HANGUL SYLLABLE GGOH + {0xAF48, 0xAF48, prLV}, // Lo HANGUL SYLLABLE GGWA + {0xAF49, 0xAF63, prLVT}, // Lo [27] HANGUL SYLLABLE GGWAG..HANGUL SYLLABLE GGWAH + {0xAF64, 0xAF64, prLV}, // Lo HANGUL SYLLABLE GGWAE + {0xAF65, 0xAF7F, prLVT}, // Lo [27] HANGUL SYLLABLE GGWAEG..HANGUL SYLLABLE GGWAEH + {0xAF80, 0xAF80, prLV}, // Lo HANGUL SYLLABLE GGOE + {0xAF81, 0xAF9B, prLVT}, // Lo [27] HANGUL SYLLABLE GGOEG..HANGUL SYLLABLE GGOEH + {0xAF9C, 0xAF9C, prLV}, // Lo HANGUL SYLLABLE GGYO + {0xAF9D, 0xAFB7, prLVT}, // Lo [27] HANGUL SYLLABLE GGYOG..HANGUL SYLLABLE GGYOH + {0xAFB8, 0xAFB8, prLV}, // Lo HANGUL SYLLABLE GGU + {0xAFB9, 0xAFD3, prLVT}, // Lo [27] HANGUL SYLLABLE GGUG..HANGUL SYLLABLE GGUH + {0xAFD4, 0xAFD4, prLV}, // Lo HANGUL SYLLABLE GGWEO + {0xAFD5, 0xAFEF, prLVT}, // Lo [27] HANGUL SYLLABLE GGWEOG..HANGUL SYLLABLE GGWEOH + {0xAFF0, 0xAFF0, prLV}, // Lo HANGUL SYLLABLE GGWE + {0xAFF1, 0xB00B, prLVT}, // Lo [27] HANGUL SYLLABLE GGWEG..HANGUL SYLLABLE GGWEH + {0xB00C, 0xB00C, prLV}, // Lo HANGUL SYLLABLE GGWI + {0xB00D, 0xB027, prLVT}, // Lo [27] HANGUL SYLLABLE GGWIG..HANGUL SYLLABLE GGWIH + {0xB028, 0xB028, prLV}, // Lo HANGUL SYLLABLE GGYU + {0xB029, 0xB043, prLVT}, // Lo [27] HANGUL SYLLABLE GGYUG..HANGUL SYLLABLE GGYUH + {0xB044, 0xB044, prLV}, // Lo HANGUL SYLLABLE GGEU + {0xB045, 0xB05F, prLVT}, // Lo [27] HANGUL SYLLABLE GGEUG..HANGUL SYLLABLE GGEUH + {0xB060, 0xB060, prLV}, // Lo HANGUL SYLLABLE GGYI + {0xB061, 0xB07B, prLVT}, // Lo [27] HANGUL SYLLABLE GGYIG..HANGUL SYLLABLE GGYIH + {0xB07C, 0xB07C, prLV}, // Lo HANGUL SYLLABLE GGI + {0xB07D, 0xB097, prLVT}, // Lo [27] HANGUL SYLLABLE GGIG..HANGUL SYLLABLE GGIH + {0xB098, 0xB098, prLV}, // Lo HANGUL SYLLABLE NA + {0xB099, 0xB0B3, prLVT}, // Lo [27] HANGUL SYLLABLE NAG..HANGUL SYLLABLE NAH + {0xB0B4, 0xB0B4, prLV}, // Lo HANGUL SYLLABLE NAE + {0xB0B5, 0xB0CF, prLVT}, // Lo [27] HANGUL SYLLABLE NAEG..HANGUL SYLLABLE NAEH + {0xB0D0, 0xB0D0, prLV}, // Lo HANGUL SYLLABLE NYA + {0xB0D1, 0xB0EB, prLVT}, // Lo [27] HANGUL SYLLABLE NYAG..HANGUL SYLLABLE NYAH + {0xB0EC, 0xB0EC, prLV}, // Lo HANGUL SYLLABLE NYAE + {0xB0ED, 0xB107, prLVT}, // Lo [27] HANGUL SYLLABLE NYAEG..HANGUL SYLLABLE NYAEH + {0xB108, 0xB108, prLV}, // Lo HANGUL SYLLABLE NEO + {0xB109, 0xB123, prLVT}, // Lo [27] HANGUL SYLLABLE NEOG..HANGUL SYLLABLE NEOH + {0xB124, 0xB124, prLV}, // Lo HANGUL SYLLABLE NE + {0xB125, 0xB13F, prLVT}, // Lo [27] HANGUL SYLLABLE NEG..HANGUL SYLLABLE NEH + {0xB140, 0xB140, prLV}, // Lo HANGUL SYLLABLE NYEO + {0xB141, 0xB15B, prLVT}, // Lo [27] HANGUL SYLLABLE NYEOG..HANGUL SYLLABLE NYEOH + {0xB15C, 0xB15C, prLV}, // Lo HANGUL SYLLABLE NYE + {0xB15D, 0xB177, prLVT}, // Lo [27] HANGUL SYLLABLE NYEG..HANGUL SYLLABLE NYEH + {0xB178, 0xB178, prLV}, // Lo HANGUL SYLLABLE NO + {0xB179, 0xB193, prLVT}, // Lo [27] HANGUL SYLLABLE NOG..HANGUL SYLLABLE NOH + {0xB194, 0xB194, prLV}, // Lo HANGUL SYLLABLE NWA + {0xB195, 0xB1AF, prLVT}, // Lo [27] HANGUL SYLLABLE NWAG..HANGUL SYLLABLE NWAH + {0xB1B0, 0xB1B0, prLV}, // Lo HANGUL SYLLABLE NWAE + {0xB1B1, 0xB1CB, prLVT}, // Lo [27] HANGUL SYLLABLE NWAEG..HANGUL SYLLABLE NWAEH + {0xB1CC, 0xB1CC, prLV}, // Lo HANGUL SYLLABLE NOE + {0xB1CD, 0xB1E7, prLVT}, // Lo [27] HANGUL SYLLABLE NOEG..HANGUL SYLLABLE NOEH + {0xB1E8, 0xB1E8, prLV}, // Lo HANGUL SYLLABLE NYO + {0xB1E9, 0xB203, prLVT}, // Lo [27] HANGUL SYLLABLE NYOG..HANGUL SYLLABLE NYOH + {0xB204, 0xB204, prLV}, // Lo HANGUL SYLLABLE NU + {0xB205, 0xB21F, prLVT}, // Lo [27] HANGUL SYLLABLE NUG..HANGUL SYLLABLE NUH + {0xB220, 0xB220, prLV}, // Lo HANGUL SYLLABLE NWEO + {0xB221, 0xB23B, prLVT}, // Lo [27] HANGUL SYLLABLE NWEOG..HANGUL SYLLABLE NWEOH + {0xB23C, 0xB23C, prLV}, // Lo HANGUL SYLLABLE NWE + {0xB23D, 0xB257, prLVT}, // Lo [27] HANGUL SYLLABLE NWEG..HANGUL SYLLABLE NWEH + {0xB258, 0xB258, prLV}, // Lo HANGUL SYLLABLE NWI + {0xB259, 0xB273, prLVT}, // Lo [27] HANGUL SYLLABLE NWIG..HANGUL SYLLABLE NWIH + {0xB274, 0xB274, prLV}, // Lo HANGUL SYLLABLE NYU + {0xB275, 0xB28F, prLVT}, // Lo [27] HANGUL SYLLABLE NYUG..HANGUL SYLLABLE NYUH + {0xB290, 0xB290, prLV}, // Lo HANGUL SYLLABLE NEU + {0xB291, 0xB2AB, prLVT}, // Lo [27] HANGUL SYLLABLE NEUG..HANGUL SYLLABLE NEUH + {0xB2AC, 0xB2AC, prLV}, // Lo HANGUL SYLLABLE NYI + {0xB2AD, 0xB2C7, prLVT}, // Lo [27] HANGUL SYLLABLE NYIG..HANGUL SYLLABLE NYIH + {0xB2C8, 0xB2C8, prLV}, // Lo HANGUL SYLLABLE NI + {0xB2C9, 0xB2E3, prLVT}, // Lo [27] HANGUL SYLLABLE NIG..HANGUL SYLLABLE NIH + {0xB2E4, 0xB2E4, prLV}, // Lo HANGUL SYLLABLE DA + {0xB2E5, 0xB2FF, prLVT}, // Lo [27] HANGUL SYLLABLE DAG..HANGUL SYLLABLE DAH + {0xB300, 0xB300, prLV}, // Lo HANGUL SYLLABLE DAE + {0xB301, 0xB31B, prLVT}, // Lo [27] HANGUL SYLLABLE DAEG..HANGUL SYLLABLE DAEH + {0xB31C, 0xB31C, prLV}, // Lo HANGUL SYLLABLE DYA + {0xB31D, 0xB337, prLVT}, // Lo [27] HANGUL SYLLABLE DYAG..HANGUL SYLLABLE DYAH + {0xB338, 0xB338, prLV}, // Lo HANGUL SYLLABLE DYAE + {0xB339, 0xB353, prLVT}, // Lo [27] HANGUL SYLLABLE DYAEG..HANGUL SYLLABLE DYAEH + {0xB354, 0xB354, prLV}, // Lo HANGUL SYLLABLE DEO + {0xB355, 0xB36F, prLVT}, // Lo [27] HANGUL SYLLABLE DEOG..HANGUL SYLLABLE DEOH + {0xB370, 0xB370, prLV}, // Lo HANGUL SYLLABLE DE + {0xB371, 0xB38B, prLVT}, // Lo [27] HANGUL SYLLABLE DEG..HANGUL SYLLABLE DEH + {0xB38C, 0xB38C, prLV}, // Lo HANGUL SYLLABLE DYEO + {0xB38D, 0xB3A7, prLVT}, // Lo [27] HANGUL SYLLABLE DYEOG..HANGUL SYLLABLE DYEOH + {0xB3A8, 0xB3A8, prLV}, // Lo HANGUL SYLLABLE DYE + {0xB3A9, 0xB3C3, prLVT}, // Lo [27] HANGUL SYLLABLE DYEG..HANGUL SYLLABLE DYEH + {0xB3C4, 0xB3C4, prLV}, // Lo HANGUL SYLLABLE DO + {0xB3C5, 0xB3DF, prLVT}, // Lo [27] HANGUL SYLLABLE DOG..HANGUL SYLLABLE DOH + {0xB3E0, 0xB3E0, prLV}, // Lo HANGUL SYLLABLE DWA + {0xB3E1, 0xB3FB, prLVT}, // Lo [27] HANGUL SYLLABLE DWAG..HANGUL SYLLABLE DWAH + {0xB3FC, 0xB3FC, prLV}, // Lo HANGUL SYLLABLE DWAE + {0xB3FD, 0xB417, prLVT}, // Lo [27] HANGUL SYLLABLE DWAEG..HANGUL SYLLABLE DWAEH + {0xB418, 0xB418, prLV}, // Lo HANGUL SYLLABLE DOE + {0xB419, 0xB433, prLVT}, // Lo [27] HANGUL SYLLABLE DOEG..HANGUL SYLLABLE DOEH + {0xB434, 0xB434, prLV}, // Lo HANGUL SYLLABLE DYO + {0xB435, 0xB44F, prLVT}, // Lo [27] HANGUL SYLLABLE DYOG..HANGUL SYLLABLE DYOH + {0xB450, 0xB450, prLV}, // Lo HANGUL SYLLABLE DU + {0xB451, 0xB46B, prLVT}, // Lo [27] HANGUL SYLLABLE DUG..HANGUL SYLLABLE DUH + {0xB46C, 0xB46C, prLV}, // Lo HANGUL SYLLABLE DWEO + {0xB46D, 0xB487, prLVT}, // Lo [27] HANGUL SYLLABLE DWEOG..HANGUL SYLLABLE DWEOH + {0xB488, 0xB488, prLV}, // Lo HANGUL SYLLABLE DWE + {0xB489, 0xB4A3, prLVT}, // Lo [27] HANGUL SYLLABLE DWEG..HANGUL SYLLABLE DWEH + {0xB4A4, 0xB4A4, prLV}, // Lo HANGUL SYLLABLE DWI + {0xB4A5, 0xB4BF, prLVT}, // Lo [27] HANGUL SYLLABLE DWIG..HANGUL SYLLABLE DWIH + {0xB4C0, 0xB4C0, prLV}, // Lo HANGUL SYLLABLE DYU + {0xB4C1, 0xB4DB, prLVT}, // Lo [27] HANGUL SYLLABLE DYUG..HANGUL SYLLABLE DYUH + {0xB4DC, 0xB4DC, prLV}, // Lo HANGUL SYLLABLE DEU + {0xB4DD, 0xB4F7, prLVT}, // Lo [27] HANGUL SYLLABLE DEUG..HANGUL SYLLABLE DEUH + {0xB4F8, 0xB4F8, prLV}, // Lo HANGUL SYLLABLE DYI + {0xB4F9, 0xB513, prLVT}, // Lo [27] HANGUL SYLLABLE DYIG..HANGUL SYLLABLE DYIH + {0xB514, 0xB514, prLV}, // Lo HANGUL SYLLABLE DI + {0xB515, 0xB52F, prLVT}, // Lo [27] HANGUL SYLLABLE DIG..HANGUL SYLLABLE DIH + {0xB530, 0xB530, prLV}, // Lo HANGUL SYLLABLE DDA + {0xB531, 0xB54B, prLVT}, // Lo [27] HANGUL SYLLABLE DDAG..HANGUL SYLLABLE DDAH + {0xB54C, 0xB54C, prLV}, // Lo HANGUL SYLLABLE DDAE + {0xB54D, 0xB567, prLVT}, // Lo [27] HANGUL SYLLABLE DDAEG..HANGUL SYLLABLE DDAEH + {0xB568, 0xB568, prLV}, // Lo HANGUL SYLLABLE DDYA + {0xB569, 0xB583, prLVT}, // Lo [27] HANGUL SYLLABLE DDYAG..HANGUL SYLLABLE DDYAH + {0xB584, 0xB584, prLV}, // Lo HANGUL SYLLABLE DDYAE + {0xB585, 0xB59F, prLVT}, // Lo [27] HANGUL SYLLABLE DDYAEG..HANGUL SYLLABLE DDYAEH + {0xB5A0, 0xB5A0, prLV}, // Lo HANGUL SYLLABLE DDEO + {0xB5A1, 0xB5BB, prLVT}, // Lo [27] HANGUL SYLLABLE DDEOG..HANGUL SYLLABLE DDEOH + {0xB5BC, 0xB5BC, prLV}, // Lo HANGUL SYLLABLE DDE + {0xB5BD, 0xB5D7, prLVT}, // Lo [27] HANGUL SYLLABLE DDEG..HANGUL SYLLABLE DDEH + {0xB5D8, 0xB5D8, prLV}, // Lo HANGUL SYLLABLE DDYEO + {0xB5D9, 0xB5F3, prLVT}, // Lo [27] HANGUL SYLLABLE DDYEOG..HANGUL SYLLABLE DDYEOH + {0xB5F4, 0xB5F4, prLV}, // Lo HANGUL SYLLABLE DDYE + {0xB5F5, 0xB60F, prLVT}, // Lo [27] HANGUL SYLLABLE DDYEG..HANGUL SYLLABLE DDYEH + {0xB610, 0xB610, prLV}, // Lo HANGUL SYLLABLE DDO + {0xB611, 0xB62B, prLVT}, // Lo [27] HANGUL SYLLABLE DDOG..HANGUL SYLLABLE DDOH + {0xB62C, 0xB62C, prLV}, // Lo HANGUL SYLLABLE DDWA + {0xB62D, 0xB647, prLVT}, // Lo [27] HANGUL SYLLABLE DDWAG..HANGUL SYLLABLE DDWAH + {0xB648, 0xB648, prLV}, // Lo HANGUL SYLLABLE DDWAE + {0xB649, 0xB663, prLVT}, // Lo [27] HANGUL SYLLABLE DDWAEG..HANGUL SYLLABLE DDWAEH + {0xB664, 0xB664, prLV}, // Lo HANGUL SYLLABLE DDOE + {0xB665, 0xB67F, prLVT}, // Lo [27] HANGUL SYLLABLE DDOEG..HANGUL SYLLABLE DDOEH + {0xB680, 0xB680, prLV}, // Lo HANGUL SYLLABLE DDYO + {0xB681, 0xB69B, prLVT}, // Lo [27] HANGUL SYLLABLE DDYOG..HANGUL SYLLABLE DDYOH + {0xB69C, 0xB69C, prLV}, // Lo HANGUL SYLLABLE DDU + {0xB69D, 0xB6B7, prLVT}, // Lo [27] HANGUL SYLLABLE DDUG..HANGUL SYLLABLE DDUH + {0xB6B8, 0xB6B8, prLV}, // Lo HANGUL SYLLABLE DDWEO + {0xB6B9, 0xB6D3, prLVT}, // Lo [27] HANGUL SYLLABLE DDWEOG..HANGUL SYLLABLE DDWEOH + {0xB6D4, 0xB6D4, prLV}, // Lo HANGUL SYLLABLE DDWE + {0xB6D5, 0xB6EF, prLVT}, // Lo [27] HANGUL SYLLABLE DDWEG..HANGUL SYLLABLE DDWEH + {0xB6F0, 0xB6F0, prLV}, // Lo HANGUL SYLLABLE DDWI + {0xB6F1, 0xB70B, prLVT}, // Lo [27] HANGUL SYLLABLE DDWIG..HANGUL SYLLABLE DDWIH + {0xB70C, 0xB70C, prLV}, // Lo HANGUL SYLLABLE DDYU + {0xB70D, 0xB727, prLVT}, // Lo [27] HANGUL SYLLABLE DDYUG..HANGUL SYLLABLE DDYUH + {0xB728, 0xB728, prLV}, // Lo HANGUL SYLLABLE DDEU + {0xB729, 0xB743, prLVT}, // Lo [27] HANGUL SYLLABLE DDEUG..HANGUL SYLLABLE DDEUH + {0xB744, 0xB744, prLV}, // Lo HANGUL SYLLABLE DDYI + {0xB745, 0xB75F, prLVT}, // Lo [27] HANGUL SYLLABLE DDYIG..HANGUL SYLLABLE DDYIH + {0xB760, 0xB760, prLV}, // Lo HANGUL SYLLABLE DDI + {0xB761, 0xB77B, prLVT}, // Lo [27] HANGUL SYLLABLE DDIG..HANGUL SYLLABLE DDIH + {0xB77C, 0xB77C, prLV}, // Lo HANGUL SYLLABLE RA + {0xB77D, 0xB797, prLVT}, // Lo [27] HANGUL SYLLABLE RAG..HANGUL SYLLABLE RAH + {0xB798, 0xB798, prLV}, // Lo HANGUL SYLLABLE RAE + {0xB799, 0xB7B3, prLVT}, // Lo [27] HANGUL SYLLABLE RAEG..HANGUL SYLLABLE RAEH + {0xB7B4, 0xB7B4, prLV}, // Lo HANGUL SYLLABLE RYA + {0xB7B5, 0xB7CF, prLVT}, // Lo [27] HANGUL SYLLABLE RYAG..HANGUL SYLLABLE RYAH + {0xB7D0, 0xB7D0, prLV}, // Lo HANGUL SYLLABLE RYAE + {0xB7D1, 0xB7EB, prLVT}, // Lo [27] HANGUL SYLLABLE RYAEG..HANGUL SYLLABLE RYAEH + {0xB7EC, 0xB7EC, prLV}, // Lo HANGUL SYLLABLE REO + {0xB7ED, 0xB807, prLVT}, // Lo [27] HANGUL SYLLABLE REOG..HANGUL SYLLABLE REOH + {0xB808, 0xB808, prLV}, // Lo HANGUL SYLLABLE RE + {0xB809, 0xB823, prLVT}, // Lo [27] HANGUL SYLLABLE REG..HANGUL SYLLABLE REH + {0xB824, 0xB824, prLV}, // Lo HANGUL SYLLABLE RYEO + {0xB825, 0xB83F, prLVT}, // Lo [27] HANGUL SYLLABLE RYEOG..HANGUL SYLLABLE RYEOH + {0xB840, 0xB840, prLV}, // Lo HANGUL SYLLABLE RYE + {0xB841, 0xB85B, prLVT}, // Lo [27] HANGUL SYLLABLE RYEG..HANGUL SYLLABLE RYEH + {0xB85C, 0xB85C, prLV}, // Lo HANGUL SYLLABLE RO + {0xB85D, 0xB877, prLVT}, // Lo [27] HANGUL SYLLABLE ROG..HANGUL SYLLABLE ROH + {0xB878, 0xB878, prLV}, // Lo HANGUL SYLLABLE RWA + {0xB879, 0xB893, prLVT}, // Lo [27] HANGUL SYLLABLE RWAG..HANGUL SYLLABLE RWAH + {0xB894, 0xB894, prLV}, // Lo HANGUL SYLLABLE RWAE + {0xB895, 0xB8AF, prLVT}, // Lo [27] HANGUL SYLLABLE RWAEG..HANGUL SYLLABLE RWAEH + {0xB8B0, 0xB8B0, prLV}, // Lo HANGUL SYLLABLE ROE + {0xB8B1, 0xB8CB, prLVT}, // Lo [27] HANGUL SYLLABLE ROEG..HANGUL SYLLABLE ROEH + {0xB8CC, 0xB8CC, prLV}, // Lo HANGUL SYLLABLE RYO + {0xB8CD, 0xB8E7, prLVT}, // Lo [27] HANGUL SYLLABLE RYOG..HANGUL SYLLABLE RYOH + {0xB8E8, 0xB8E8, prLV}, // Lo HANGUL SYLLABLE RU + {0xB8E9, 0xB903, prLVT}, // Lo [27] HANGUL SYLLABLE RUG..HANGUL SYLLABLE RUH + {0xB904, 0xB904, prLV}, // Lo HANGUL SYLLABLE RWEO + {0xB905, 0xB91F, prLVT}, // Lo [27] HANGUL SYLLABLE RWEOG..HANGUL SYLLABLE RWEOH + {0xB920, 0xB920, prLV}, // Lo HANGUL SYLLABLE RWE + {0xB921, 0xB93B, prLVT}, // Lo [27] HANGUL SYLLABLE RWEG..HANGUL SYLLABLE RWEH + {0xB93C, 0xB93C, prLV}, // Lo HANGUL SYLLABLE RWI + {0xB93D, 0xB957, prLVT}, // Lo [27] HANGUL SYLLABLE RWIG..HANGUL SYLLABLE RWIH + {0xB958, 0xB958, prLV}, // Lo HANGUL SYLLABLE RYU + {0xB959, 0xB973, prLVT}, // Lo [27] HANGUL SYLLABLE RYUG..HANGUL SYLLABLE RYUH + {0xB974, 0xB974, prLV}, // Lo HANGUL SYLLABLE REU + {0xB975, 0xB98F, prLVT}, // Lo [27] HANGUL SYLLABLE REUG..HANGUL SYLLABLE REUH + {0xB990, 0xB990, prLV}, // Lo HANGUL SYLLABLE RYI + {0xB991, 0xB9AB, prLVT}, // Lo [27] HANGUL SYLLABLE RYIG..HANGUL SYLLABLE RYIH + {0xB9AC, 0xB9AC, prLV}, // Lo HANGUL SYLLABLE RI + {0xB9AD, 0xB9C7, prLVT}, // Lo [27] HANGUL SYLLABLE RIG..HANGUL SYLLABLE RIH + {0xB9C8, 0xB9C8, prLV}, // Lo HANGUL SYLLABLE MA + {0xB9C9, 0xB9E3, prLVT}, // Lo [27] HANGUL SYLLABLE MAG..HANGUL SYLLABLE MAH + {0xB9E4, 0xB9E4, prLV}, // Lo HANGUL SYLLABLE MAE + {0xB9E5, 0xB9FF, prLVT}, // Lo [27] HANGUL SYLLABLE MAEG..HANGUL SYLLABLE MAEH + {0xBA00, 0xBA00, prLV}, // Lo HANGUL SYLLABLE MYA + {0xBA01, 0xBA1B, prLVT}, // Lo [27] HANGUL SYLLABLE MYAG..HANGUL SYLLABLE MYAH + {0xBA1C, 0xBA1C, prLV}, // Lo HANGUL SYLLABLE MYAE + {0xBA1D, 0xBA37, prLVT}, // Lo [27] HANGUL SYLLABLE MYAEG..HANGUL SYLLABLE MYAEH + {0xBA38, 0xBA38, prLV}, // Lo HANGUL SYLLABLE MEO + {0xBA39, 0xBA53, prLVT}, // Lo [27] HANGUL SYLLABLE MEOG..HANGUL SYLLABLE MEOH + {0xBA54, 0xBA54, prLV}, // Lo HANGUL SYLLABLE ME + {0xBA55, 0xBA6F, prLVT}, // Lo [27] HANGUL SYLLABLE MEG..HANGUL SYLLABLE MEH + {0xBA70, 0xBA70, prLV}, // Lo HANGUL SYLLABLE MYEO + {0xBA71, 0xBA8B, prLVT}, // Lo [27] HANGUL SYLLABLE MYEOG..HANGUL SYLLABLE MYEOH + {0xBA8C, 0xBA8C, prLV}, // Lo HANGUL SYLLABLE MYE + {0xBA8D, 0xBAA7, prLVT}, // Lo [27] HANGUL SYLLABLE MYEG..HANGUL SYLLABLE MYEH + {0xBAA8, 0xBAA8, prLV}, // Lo HANGUL SYLLABLE MO + {0xBAA9, 0xBAC3, prLVT}, // Lo [27] HANGUL SYLLABLE MOG..HANGUL SYLLABLE MOH + {0xBAC4, 0xBAC4, prLV}, // Lo HANGUL SYLLABLE MWA + {0xBAC5, 0xBADF, prLVT}, // Lo [27] HANGUL SYLLABLE MWAG..HANGUL SYLLABLE MWAH + {0xBAE0, 0xBAE0, prLV}, // Lo HANGUL SYLLABLE MWAE + {0xBAE1, 0xBAFB, prLVT}, // Lo [27] HANGUL SYLLABLE MWAEG..HANGUL SYLLABLE MWAEH + {0xBAFC, 0xBAFC, prLV}, // Lo HANGUL SYLLABLE MOE + {0xBAFD, 0xBB17, prLVT}, // Lo [27] HANGUL SYLLABLE MOEG..HANGUL SYLLABLE MOEH + {0xBB18, 0xBB18, prLV}, // Lo HANGUL SYLLABLE MYO + {0xBB19, 0xBB33, prLVT}, // Lo [27] HANGUL SYLLABLE MYOG..HANGUL SYLLABLE MYOH + {0xBB34, 0xBB34, prLV}, // Lo HANGUL SYLLABLE MU + {0xBB35, 0xBB4F, prLVT}, // Lo [27] HANGUL SYLLABLE MUG..HANGUL SYLLABLE MUH + {0xBB50, 0xBB50, prLV}, // Lo HANGUL SYLLABLE MWEO + {0xBB51, 0xBB6B, prLVT}, // Lo [27] HANGUL SYLLABLE MWEOG..HANGUL SYLLABLE MWEOH + {0xBB6C, 0xBB6C, prLV}, // Lo HANGUL SYLLABLE MWE + {0xBB6D, 0xBB87, prLVT}, // Lo [27] HANGUL SYLLABLE MWEG..HANGUL SYLLABLE MWEH + {0xBB88, 0xBB88, prLV}, // Lo HANGUL SYLLABLE MWI + {0xBB89, 0xBBA3, prLVT}, // Lo [27] HANGUL SYLLABLE MWIG..HANGUL SYLLABLE MWIH + {0xBBA4, 0xBBA4, prLV}, // Lo HANGUL SYLLABLE MYU + {0xBBA5, 0xBBBF, prLVT}, // Lo [27] HANGUL SYLLABLE MYUG..HANGUL SYLLABLE MYUH + {0xBBC0, 0xBBC0, prLV}, // Lo HANGUL SYLLABLE MEU + {0xBBC1, 0xBBDB, prLVT}, // Lo [27] HANGUL SYLLABLE MEUG..HANGUL SYLLABLE MEUH + {0xBBDC, 0xBBDC, prLV}, // Lo HANGUL SYLLABLE MYI + {0xBBDD, 0xBBF7, prLVT}, // Lo [27] HANGUL SYLLABLE MYIG..HANGUL SYLLABLE MYIH + {0xBBF8, 0xBBF8, prLV}, // Lo HANGUL SYLLABLE MI + {0xBBF9, 0xBC13, prLVT}, // Lo [27] HANGUL SYLLABLE MIG..HANGUL SYLLABLE MIH + {0xBC14, 0xBC14, prLV}, // Lo HANGUL SYLLABLE BA + {0xBC15, 0xBC2F, prLVT}, // Lo [27] HANGUL SYLLABLE BAG..HANGUL SYLLABLE BAH + {0xBC30, 0xBC30, prLV}, // Lo HANGUL SYLLABLE BAE + {0xBC31, 0xBC4B, prLVT}, // Lo [27] HANGUL SYLLABLE BAEG..HANGUL SYLLABLE BAEH + {0xBC4C, 0xBC4C, prLV}, // Lo HANGUL SYLLABLE BYA + {0xBC4D, 0xBC67, prLVT}, // Lo [27] HANGUL SYLLABLE BYAG..HANGUL SYLLABLE BYAH + {0xBC68, 0xBC68, prLV}, // Lo HANGUL SYLLABLE BYAE + {0xBC69, 0xBC83, prLVT}, // Lo [27] HANGUL SYLLABLE BYAEG..HANGUL SYLLABLE BYAEH + {0xBC84, 0xBC84, prLV}, // Lo HANGUL SYLLABLE BEO + {0xBC85, 0xBC9F, prLVT}, // Lo [27] HANGUL SYLLABLE BEOG..HANGUL SYLLABLE BEOH + {0xBCA0, 0xBCA0, prLV}, // Lo HANGUL SYLLABLE BE + {0xBCA1, 0xBCBB, prLVT}, // Lo [27] HANGUL SYLLABLE BEG..HANGUL SYLLABLE BEH + {0xBCBC, 0xBCBC, prLV}, // Lo HANGUL SYLLABLE BYEO + {0xBCBD, 0xBCD7, prLVT}, // Lo [27] HANGUL SYLLABLE BYEOG..HANGUL SYLLABLE BYEOH + {0xBCD8, 0xBCD8, prLV}, // Lo HANGUL SYLLABLE BYE + {0xBCD9, 0xBCF3, prLVT}, // Lo [27] HANGUL SYLLABLE BYEG..HANGUL SYLLABLE BYEH + {0xBCF4, 0xBCF4, prLV}, // Lo HANGUL SYLLABLE BO + {0xBCF5, 0xBD0F, prLVT}, // Lo [27] HANGUL SYLLABLE BOG..HANGUL SYLLABLE BOH + {0xBD10, 0xBD10, prLV}, // Lo HANGUL SYLLABLE BWA + {0xBD11, 0xBD2B, prLVT}, // Lo [27] HANGUL SYLLABLE BWAG..HANGUL SYLLABLE BWAH + {0xBD2C, 0xBD2C, prLV}, // Lo HANGUL SYLLABLE BWAE + {0xBD2D, 0xBD47, prLVT}, // Lo [27] HANGUL SYLLABLE BWAEG..HANGUL SYLLABLE BWAEH + {0xBD48, 0xBD48, prLV}, // Lo HANGUL SYLLABLE BOE + {0xBD49, 0xBD63, prLVT}, // Lo [27] HANGUL SYLLABLE BOEG..HANGUL SYLLABLE BOEH + {0xBD64, 0xBD64, prLV}, // Lo HANGUL SYLLABLE BYO + {0xBD65, 0xBD7F, prLVT}, // Lo [27] HANGUL SYLLABLE BYOG..HANGUL SYLLABLE BYOH + {0xBD80, 0xBD80, prLV}, // Lo HANGUL SYLLABLE BU + {0xBD81, 0xBD9B, prLVT}, // Lo [27] HANGUL SYLLABLE BUG..HANGUL SYLLABLE BUH + {0xBD9C, 0xBD9C, prLV}, // Lo HANGUL SYLLABLE BWEO + {0xBD9D, 0xBDB7, prLVT}, // Lo [27] HANGUL SYLLABLE BWEOG..HANGUL SYLLABLE BWEOH + {0xBDB8, 0xBDB8, prLV}, // Lo HANGUL SYLLABLE BWE + {0xBDB9, 0xBDD3, prLVT}, // Lo [27] HANGUL SYLLABLE BWEG..HANGUL SYLLABLE BWEH + {0xBDD4, 0xBDD4, prLV}, // Lo HANGUL SYLLABLE BWI + {0xBDD5, 0xBDEF, prLVT}, // Lo [27] HANGUL SYLLABLE BWIG..HANGUL SYLLABLE BWIH + {0xBDF0, 0xBDF0, prLV}, // Lo HANGUL SYLLABLE BYU + {0xBDF1, 0xBE0B, prLVT}, // Lo [27] HANGUL SYLLABLE BYUG..HANGUL SYLLABLE BYUH + {0xBE0C, 0xBE0C, prLV}, // Lo HANGUL SYLLABLE BEU + {0xBE0D, 0xBE27, prLVT}, // Lo [27] HANGUL SYLLABLE BEUG..HANGUL SYLLABLE BEUH + {0xBE28, 0xBE28, prLV}, // Lo HANGUL SYLLABLE BYI + {0xBE29, 0xBE43, prLVT}, // Lo [27] HANGUL SYLLABLE BYIG..HANGUL SYLLABLE BYIH + {0xBE44, 0xBE44, prLV}, // Lo HANGUL SYLLABLE BI + {0xBE45, 0xBE5F, prLVT}, // Lo [27] HANGUL SYLLABLE BIG..HANGUL SYLLABLE BIH + {0xBE60, 0xBE60, prLV}, // Lo HANGUL SYLLABLE BBA + {0xBE61, 0xBE7B, prLVT}, // Lo [27] HANGUL SYLLABLE BBAG..HANGUL SYLLABLE BBAH + {0xBE7C, 0xBE7C, prLV}, // Lo HANGUL SYLLABLE BBAE + {0xBE7D, 0xBE97, prLVT}, // Lo [27] HANGUL SYLLABLE BBAEG..HANGUL SYLLABLE BBAEH + {0xBE98, 0xBE98, prLV}, // Lo HANGUL SYLLABLE BBYA + {0xBE99, 0xBEB3, prLVT}, // Lo [27] HANGUL SYLLABLE BBYAG..HANGUL SYLLABLE BBYAH + {0xBEB4, 0xBEB4, prLV}, // Lo HANGUL SYLLABLE BBYAE + {0xBEB5, 0xBECF, prLVT}, // Lo [27] HANGUL SYLLABLE BBYAEG..HANGUL SYLLABLE BBYAEH + {0xBED0, 0xBED0, prLV}, // Lo HANGUL SYLLABLE BBEO + {0xBED1, 0xBEEB, prLVT}, // Lo [27] HANGUL SYLLABLE BBEOG..HANGUL SYLLABLE BBEOH + {0xBEEC, 0xBEEC, prLV}, // Lo HANGUL SYLLABLE BBE + {0xBEED, 0xBF07, prLVT}, // Lo [27] HANGUL SYLLABLE BBEG..HANGUL SYLLABLE BBEH + {0xBF08, 0xBF08, prLV}, // Lo HANGUL SYLLABLE BBYEO + {0xBF09, 0xBF23, prLVT}, // Lo [27] HANGUL SYLLABLE BBYEOG..HANGUL SYLLABLE BBYEOH + {0xBF24, 0xBF24, prLV}, // Lo HANGUL SYLLABLE BBYE + {0xBF25, 0xBF3F, prLVT}, // Lo [27] HANGUL SYLLABLE BBYEG..HANGUL SYLLABLE BBYEH + {0xBF40, 0xBF40, prLV}, // Lo HANGUL SYLLABLE BBO + {0xBF41, 0xBF5B, prLVT}, // Lo [27] HANGUL SYLLABLE BBOG..HANGUL SYLLABLE BBOH + {0xBF5C, 0xBF5C, prLV}, // Lo HANGUL SYLLABLE BBWA + {0xBF5D, 0xBF77, prLVT}, // Lo [27] HANGUL SYLLABLE BBWAG..HANGUL SYLLABLE BBWAH + {0xBF78, 0xBF78, prLV}, // Lo HANGUL SYLLABLE BBWAE + {0xBF79, 0xBF93, prLVT}, // Lo [27] HANGUL SYLLABLE BBWAEG..HANGUL SYLLABLE BBWAEH + {0xBF94, 0xBF94, prLV}, // Lo HANGUL SYLLABLE BBOE + {0xBF95, 0xBFAF, prLVT}, // Lo [27] HANGUL SYLLABLE BBOEG..HANGUL SYLLABLE BBOEH + {0xBFB0, 0xBFB0, prLV}, // Lo HANGUL SYLLABLE BBYO + {0xBFB1, 0xBFCB, prLVT}, // Lo [27] HANGUL SYLLABLE BBYOG..HANGUL SYLLABLE BBYOH + {0xBFCC, 0xBFCC, prLV}, // Lo HANGUL SYLLABLE BBU + {0xBFCD, 0xBFE7, prLVT}, // Lo [27] HANGUL SYLLABLE BBUG..HANGUL SYLLABLE BBUH + {0xBFE8, 0xBFE8, prLV}, // Lo HANGUL SYLLABLE BBWEO + {0xBFE9, 0xC003, prLVT}, // Lo [27] HANGUL SYLLABLE BBWEOG..HANGUL SYLLABLE BBWEOH + {0xC004, 0xC004, prLV}, // Lo HANGUL SYLLABLE BBWE + {0xC005, 0xC01F, prLVT}, // Lo [27] HANGUL SYLLABLE BBWEG..HANGUL SYLLABLE BBWEH + {0xC020, 0xC020, prLV}, // Lo HANGUL SYLLABLE BBWI + {0xC021, 0xC03B, prLVT}, // Lo [27] HANGUL SYLLABLE BBWIG..HANGUL SYLLABLE BBWIH + {0xC03C, 0xC03C, prLV}, // Lo HANGUL SYLLABLE BBYU + {0xC03D, 0xC057, prLVT}, // Lo [27] HANGUL SYLLABLE BBYUG..HANGUL SYLLABLE BBYUH + {0xC058, 0xC058, prLV}, // Lo HANGUL SYLLABLE BBEU + {0xC059, 0xC073, prLVT}, // Lo [27] HANGUL SYLLABLE BBEUG..HANGUL SYLLABLE BBEUH + {0xC074, 0xC074, prLV}, // Lo HANGUL SYLLABLE BBYI + {0xC075, 0xC08F, prLVT}, // Lo [27] HANGUL SYLLABLE BBYIG..HANGUL SYLLABLE BBYIH + {0xC090, 0xC090, prLV}, // Lo HANGUL SYLLABLE BBI + {0xC091, 0xC0AB, prLVT}, // Lo [27] HANGUL SYLLABLE BBIG..HANGUL SYLLABLE BBIH + {0xC0AC, 0xC0AC, prLV}, // Lo HANGUL SYLLABLE SA + {0xC0AD, 0xC0C7, prLVT}, // Lo [27] HANGUL SYLLABLE SAG..HANGUL SYLLABLE SAH + {0xC0C8, 0xC0C8, prLV}, // Lo HANGUL SYLLABLE SAE + {0xC0C9, 0xC0E3, prLVT}, // Lo [27] HANGUL SYLLABLE SAEG..HANGUL SYLLABLE SAEH + {0xC0E4, 0xC0E4, prLV}, // Lo HANGUL SYLLABLE SYA + {0xC0E5, 0xC0FF, prLVT}, // Lo [27] HANGUL SYLLABLE SYAG..HANGUL SYLLABLE SYAH + {0xC100, 0xC100, prLV}, // Lo HANGUL SYLLABLE SYAE + {0xC101, 0xC11B, prLVT}, // Lo [27] HANGUL SYLLABLE SYAEG..HANGUL SYLLABLE SYAEH + {0xC11C, 0xC11C, prLV}, // Lo HANGUL SYLLABLE SEO + {0xC11D, 0xC137, prLVT}, // Lo [27] HANGUL SYLLABLE SEOG..HANGUL SYLLABLE SEOH + {0xC138, 0xC138, prLV}, // Lo HANGUL SYLLABLE SE + {0xC139, 0xC153, prLVT}, // Lo [27] HANGUL SYLLABLE SEG..HANGUL SYLLABLE SEH + {0xC154, 0xC154, prLV}, // Lo HANGUL SYLLABLE SYEO + {0xC155, 0xC16F, prLVT}, // Lo [27] HANGUL SYLLABLE SYEOG..HANGUL SYLLABLE SYEOH + {0xC170, 0xC170, prLV}, // Lo HANGUL SYLLABLE SYE + {0xC171, 0xC18B, prLVT}, // Lo [27] HANGUL SYLLABLE SYEG..HANGUL SYLLABLE SYEH + {0xC18C, 0xC18C, prLV}, // Lo HANGUL SYLLABLE SO + {0xC18D, 0xC1A7, prLVT}, // Lo [27] HANGUL SYLLABLE SOG..HANGUL SYLLABLE SOH + {0xC1A8, 0xC1A8, prLV}, // Lo HANGUL SYLLABLE SWA + {0xC1A9, 0xC1C3, prLVT}, // Lo [27] HANGUL SYLLABLE SWAG..HANGUL SYLLABLE SWAH + {0xC1C4, 0xC1C4, prLV}, // Lo HANGUL SYLLABLE SWAE + {0xC1C5, 0xC1DF, prLVT}, // Lo [27] HANGUL SYLLABLE SWAEG..HANGUL SYLLABLE SWAEH + {0xC1E0, 0xC1E0, prLV}, // Lo HANGUL SYLLABLE SOE + {0xC1E1, 0xC1FB, prLVT}, // Lo [27] HANGUL SYLLABLE SOEG..HANGUL SYLLABLE SOEH + {0xC1FC, 0xC1FC, prLV}, // Lo HANGUL SYLLABLE SYO + {0xC1FD, 0xC217, prLVT}, // Lo [27] HANGUL SYLLABLE SYOG..HANGUL SYLLABLE SYOH + {0xC218, 0xC218, prLV}, // Lo HANGUL SYLLABLE SU + {0xC219, 0xC233, prLVT}, // Lo [27] HANGUL SYLLABLE SUG..HANGUL SYLLABLE SUH + {0xC234, 0xC234, prLV}, // Lo HANGUL SYLLABLE SWEO + {0xC235, 0xC24F, prLVT}, // Lo [27] HANGUL SYLLABLE SWEOG..HANGUL SYLLABLE SWEOH + {0xC250, 0xC250, prLV}, // Lo HANGUL SYLLABLE SWE + {0xC251, 0xC26B, prLVT}, // Lo [27] HANGUL SYLLABLE SWEG..HANGUL SYLLABLE SWEH + {0xC26C, 0xC26C, prLV}, // Lo HANGUL SYLLABLE SWI + {0xC26D, 0xC287, prLVT}, // Lo [27] HANGUL SYLLABLE SWIG..HANGUL SYLLABLE SWIH + {0xC288, 0xC288, prLV}, // Lo HANGUL SYLLABLE SYU + {0xC289, 0xC2A3, prLVT}, // Lo [27] HANGUL SYLLABLE SYUG..HANGUL SYLLABLE SYUH + {0xC2A4, 0xC2A4, prLV}, // Lo HANGUL SYLLABLE SEU + {0xC2A5, 0xC2BF, prLVT}, // Lo [27] HANGUL SYLLABLE SEUG..HANGUL SYLLABLE SEUH + {0xC2C0, 0xC2C0, prLV}, // Lo HANGUL SYLLABLE SYI + {0xC2C1, 0xC2DB, prLVT}, // Lo [27] HANGUL SYLLABLE SYIG..HANGUL SYLLABLE SYIH + {0xC2DC, 0xC2DC, prLV}, // Lo HANGUL SYLLABLE SI + {0xC2DD, 0xC2F7, prLVT}, // Lo [27] HANGUL SYLLABLE SIG..HANGUL SYLLABLE SIH + {0xC2F8, 0xC2F8, prLV}, // Lo HANGUL SYLLABLE SSA + {0xC2F9, 0xC313, prLVT}, // Lo [27] HANGUL SYLLABLE SSAG..HANGUL SYLLABLE SSAH + {0xC314, 0xC314, prLV}, // Lo HANGUL SYLLABLE SSAE + {0xC315, 0xC32F, prLVT}, // Lo [27] HANGUL SYLLABLE SSAEG..HANGUL SYLLABLE SSAEH + {0xC330, 0xC330, prLV}, // Lo HANGUL SYLLABLE SSYA + {0xC331, 0xC34B, prLVT}, // Lo [27] HANGUL SYLLABLE SSYAG..HANGUL SYLLABLE SSYAH + {0xC34C, 0xC34C, prLV}, // Lo HANGUL SYLLABLE SSYAE + {0xC34D, 0xC367, prLVT}, // Lo [27] HANGUL SYLLABLE SSYAEG..HANGUL SYLLABLE SSYAEH + {0xC368, 0xC368, prLV}, // Lo HANGUL SYLLABLE SSEO + {0xC369, 0xC383, prLVT}, // Lo [27] HANGUL SYLLABLE SSEOG..HANGUL SYLLABLE SSEOH + {0xC384, 0xC384, prLV}, // Lo HANGUL SYLLABLE SSE + {0xC385, 0xC39F, prLVT}, // Lo [27] HANGUL SYLLABLE SSEG..HANGUL SYLLABLE SSEH + {0xC3A0, 0xC3A0, prLV}, // Lo HANGUL SYLLABLE SSYEO + {0xC3A1, 0xC3BB, prLVT}, // Lo [27] HANGUL SYLLABLE SSYEOG..HANGUL SYLLABLE SSYEOH + {0xC3BC, 0xC3BC, prLV}, // Lo HANGUL SYLLABLE SSYE + {0xC3BD, 0xC3D7, prLVT}, // Lo [27] HANGUL SYLLABLE SSYEG..HANGUL SYLLABLE SSYEH + {0xC3D8, 0xC3D8, prLV}, // Lo HANGUL SYLLABLE SSO + {0xC3D9, 0xC3F3, prLVT}, // Lo [27] HANGUL SYLLABLE SSOG..HANGUL SYLLABLE SSOH + {0xC3F4, 0xC3F4, prLV}, // Lo HANGUL SYLLABLE SSWA + {0xC3F5, 0xC40F, prLVT}, // Lo [27] HANGUL SYLLABLE SSWAG..HANGUL SYLLABLE SSWAH + {0xC410, 0xC410, prLV}, // Lo HANGUL SYLLABLE SSWAE + {0xC411, 0xC42B, prLVT}, // Lo [27] HANGUL SYLLABLE SSWAEG..HANGUL SYLLABLE SSWAEH + {0xC42C, 0xC42C, prLV}, // Lo HANGUL SYLLABLE SSOE + {0xC42D, 0xC447, prLVT}, // Lo [27] HANGUL SYLLABLE SSOEG..HANGUL SYLLABLE SSOEH + {0xC448, 0xC448, prLV}, // Lo HANGUL SYLLABLE SSYO + {0xC449, 0xC463, prLVT}, // Lo [27] HANGUL SYLLABLE SSYOG..HANGUL SYLLABLE SSYOH + {0xC464, 0xC464, prLV}, // Lo HANGUL SYLLABLE SSU + {0xC465, 0xC47F, prLVT}, // Lo [27] HANGUL SYLLABLE SSUG..HANGUL SYLLABLE SSUH + {0xC480, 0xC480, prLV}, // Lo HANGUL SYLLABLE SSWEO + {0xC481, 0xC49B, prLVT}, // Lo [27] HANGUL SYLLABLE SSWEOG..HANGUL SYLLABLE SSWEOH + {0xC49C, 0xC49C, prLV}, // Lo HANGUL SYLLABLE SSWE + {0xC49D, 0xC4B7, prLVT}, // Lo [27] HANGUL SYLLABLE SSWEG..HANGUL SYLLABLE SSWEH + {0xC4B8, 0xC4B8, prLV}, // Lo HANGUL SYLLABLE SSWI + {0xC4B9, 0xC4D3, prLVT}, // Lo [27] HANGUL SYLLABLE SSWIG..HANGUL SYLLABLE SSWIH + {0xC4D4, 0xC4D4, prLV}, // Lo HANGUL SYLLABLE SSYU + {0xC4D5, 0xC4EF, prLVT}, // Lo [27] HANGUL SYLLABLE SSYUG..HANGUL SYLLABLE SSYUH + {0xC4F0, 0xC4F0, prLV}, // Lo HANGUL SYLLABLE SSEU + {0xC4F1, 0xC50B, prLVT}, // Lo [27] HANGUL SYLLABLE SSEUG..HANGUL SYLLABLE SSEUH + {0xC50C, 0xC50C, prLV}, // Lo HANGUL SYLLABLE SSYI + {0xC50D, 0xC527, prLVT}, // Lo [27] HANGUL SYLLABLE SSYIG..HANGUL SYLLABLE SSYIH + {0xC528, 0xC528, prLV}, // Lo HANGUL SYLLABLE SSI + {0xC529, 0xC543, prLVT}, // Lo [27] HANGUL SYLLABLE SSIG..HANGUL SYLLABLE SSIH + {0xC544, 0xC544, prLV}, // Lo HANGUL SYLLABLE A + {0xC545, 0xC55F, prLVT}, // Lo [27] HANGUL SYLLABLE AG..HANGUL SYLLABLE AH + {0xC560, 0xC560, prLV}, // Lo HANGUL SYLLABLE AE + {0xC561, 0xC57B, prLVT}, // Lo [27] HANGUL SYLLABLE AEG..HANGUL SYLLABLE AEH + {0xC57C, 0xC57C, prLV}, // Lo HANGUL SYLLABLE YA + {0xC57D, 0xC597, prLVT}, // Lo [27] HANGUL SYLLABLE YAG..HANGUL SYLLABLE YAH + {0xC598, 0xC598, prLV}, // Lo HANGUL SYLLABLE YAE + {0xC599, 0xC5B3, prLVT}, // Lo [27] HANGUL SYLLABLE YAEG..HANGUL SYLLABLE YAEH + {0xC5B4, 0xC5B4, prLV}, // Lo HANGUL SYLLABLE EO + {0xC5B5, 0xC5CF, prLVT}, // Lo [27] HANGUL SYLLABLE EOG..HANGUL SYLLABLE EOH + {0xC5D0, 0xC5D0, prLV}, // Lo HANGUL SYLLABLE E + {0xC5D1, 0xC5EB, prLVT}, // Lo [27] HANGUL SYLLABLE EG..HANGUL SYLLABLE EH + {0xC5EC, 0xC5EC, prLV}, // Lo HANGUL SYLLABLE YEO + {0xC5ED, 0xC607, prLVT}, // Lo [27] HANGUL SYLLABLE YEOG..HANGUL SYLLABLE YEOH + {0xC608, 0xC608, prLV}, // Lo HANGUL SYLLABLE YE + {0xC609, 0xC623, prLVT}, // Lo [27] HANGUL SYLLABLE YEG..HANGUL SYLLABLE YEH + {0xC624, 0xC624, prLV}, // Lo HANGUL SYLLABLE O + {0xC625, 0xC63F, prLVT}, // Lo [27] HANGUL SYLLABLE OG..HANGUL SYLLABLE OH + {0xC640, 0xC640, prLV}, // Lo HANGUL SYLLABLE WA + {0xC641, 0xC65B, prLVT}, // Lo [27] HANGUL SYLLABLE WAG..HANGUL SYLLABLE WAH + {0xC65C, 0xC65C, prLV}, // Lo HANGUL SYLLABLE WAE + {0xC65D, 0xC677, prLVT}, // Lo [27] HANGUL SYLLABLE WAEG..HANGUL SYLLABLE WAEH + {0xC678, 0xC678, prLV}, // Lo HANGUL SYLLABLE OE + {0xC679, 0xC693, prLVT}, // Lo [27] HANGUL SYLLABLE OEG..HANGUL SYLLABLE OEH + {0xC694, 0xC694, prLV}, // Lo HANGUL SYLLABLE YO + {0xC695, 0xC6AF, prLVT}, // Lo [27] HANGUL SYLLABLE YOG..HANGUL SYLLABLE YOH + {0xC6B0, 0xC6B0, prLV}, // Lo HANGUL SYLLABLE U + {0xC6B1, 0xC6CB, prLVT}, // Lo [27] HANGUL SYLLABLE UG..HANGUL SYLLABLE UH + {0xC6CC, 0xC6CC, prLV}, // Lo HANGUL SYLLABLE WEO + {0xC6CD, 0xC6E7, prLVT}, // Lo [27] HANGUL SYLLABLE WEOG..HANGUL SYLLABLE WEOH + {0xC6E8, 0xC6E8, prLV}, // Lo HANGUL SYLLABLE WE + {0xC6E9, 0xC703, prLVT}, // Lo [27] HANGUL SYLLABLE WEG..HANGUL SYLLABLE WEH + {0xC704, 0xC704, prLV}, // Lo HANGUL SYLLABLE WI + {0xC705, 0xC71F, prLVT}, // Lo [27] HANGUL SYLLABLE WIG..HANGUL SYLLABLE WIH + {0xC720, 0xC720, prLV}, // Lo HANGUL SYLLABLE YU + {0xC721, 0xC73B, prLVT}, // Lo [27] HANGUL SYLLABLE YUG..HANGUL SYLLABLE YUH + {0xC73C, 0xC73C, prLV}, // Lo HANGUL SYLLABLE EU + {0xC73D, 0xC757, prLVT}, // Lo [27] HANGUL SYLLABLE EUG..HANGUL SYLLABLE EUH + {0xC758, 0xC758, prLV}, // Lo HANGUL SYLLABLE YI + {0xC759, 0xC773, prLVT}, // Lo [27] HANGUL SYLLABLE YIG..HANGUL SYLLABLE YIH + {0xC774, 0xC774, prLV}, // Lo HANGUL SYLLABLE I + {0xC775, 0xC78F, prLVT}, // Lo [27] HANGUL SYLLABLE IG..HANGUL SYLLABLE IH + {0xC790, 0xC790, prLV}, // Lo HANGUL SYLLABLE JA + {0xC791, 0xC7AB, prLVT}, // Lo [27] HANGUL SYLLABLE JAG..HANGUL SYLLABLE JAH + {0xC7AC, 0xC7AC, prLV}, // Lo HANGUL SYLLABLE JAE + {0xC7AD, 0xC7C7, prLVT}, // Lo [27] HANGUL SYLLABLE JAEG..HANGUL SYLLABLE JAEH + {0xC7C8, 0xC7C8, prLV}, // Lo HANGUL SYLLABLE JYA + {0xC7C9, 0xC7E3, prLVT}, // Lo [27] HANGUL SYLLABLE JYAG..HANGUL SYLLABLE JYAH + {0xC7E4, 0xC7E4, prLV}, // Lo HANGUL SYLLABLE JYAE + {0xC7E5, 0xC7FF, prLVT}, // Lo [27] HANGUL SYLLABLE JYAEG..HANGUL SYLLABLE JYAEH + {0xC800, 0xC800, prLV}, // Lo HANGUL SYLLABLE JEO + {0xC801, 0xC81B, prLVT}, // Lo [27] HANGUL SYLLABLE JEOG..HANGUL SYLLABLE JEOH + {0xC81C, 0xC81C, prLV}, // Lo HANGUL SYLLABLE JE + {0xC81D, 0xC837, prLVT}, // Lo [27] HANGUL SYLLABLE JEG..HANGUL SYLLABLE JEH + {0xC838, 0xC838, prLV}, // Lo HANGUL SYLLABLE JYEO + {0xC839, 0xC853, prLVT}, // Lo [27] HANGUL SYLLABLE JYEOG..HANGUL SYLLABLE JYEOH + {0xC854, 0xC854, prLV}, // Lo HANGUL SYLLABLE JYE + {0xC855, 0xC86F, prLVT}, // Lo [27] HANGUL SYLLABLE JYEG..HANGUL SYLLABLE JYEH + {0xC870, 0xC870, prLV}, // Lo HANGUL SYLLABLE JO + {0xC871, 0xC88B, prLVT}, // Lo [27] HANGUL SYLLABLE JOG..HANGUL SYLLABLE JOH + {0xC88C, 0xC88C, prLV}, // Lo HANGUL SYLLABLE JWA + {0xC88D, 0xC8A7, prLVT}, // Lo [27] HANGUL SYLLABLE JWAG..HANGUL SYLLABLE JWAH + {0xC8A8, 0xC8A8, prLV}, // Lo HANGUL SYLLABLE JWAE + {0xC8A9, 0xC8C3, prLVT}, // Lo [27] HANGUL SYLLABLE JWAEG..HANGUL SYLLABLE JWAEH + {0xC8C4, 0xC8C4, prLV}, // Lo HANGUL SYLLABLE JOE + {0xC8C5, 0xC8DF, prLVT}, // Lo [27] HANGUL SYLLABLE JOEG..HANGUL SYLLABLE JOEH + {0xC8E0, 0xC8E0, prLV}, // Lo HANGUL SYLLABLE JYO + {0xC8E1, 0xC8FB, prLVT}, // Lo [27] HANGUL SYLLABLE JYOG..HANGUL SYLLABLE JYOH + {0xC8FC, 0xC8FC, prLV}, // Lo HANGUL SYLLABLE JU + {0xC8FD, 0xC917, prLVT}, // Lo [27] HANGUL SYLLABLE JUG..HANGUL SYLLABLE JUH + {0xC918, 0xC918, prLV}, // Lo HANGUL SYLLABLE JWEO + {0xC919, 0xC933, prLVT}, // Lo [27] HANGUL SYLLABLE JWEOG..HANGUL SYLLABLE JWEOH + {0xC934, 0xC934, prLV}, // Lo HANGUL SYLLABLE JWE + {0xC935, 0xC94F, prLVT}, // Lo [27] HANGUL SYLLABLE JWEG..HANGUL SYLLABLE JWEH + {0xC950, 0xC950, prLV}, // Lo HANGUL SYLLABLE JWI + {0xC951, 0xC96B, prLVT}, // Lo [27] HANGUL SYLLABLE JWIG..HANGUL SYLLABLE JWIH + {0xC96C, 0xC96C, prLV}, // Lo HANGUL SYLLABLE JYU + {0xC96D, 0xC987, prLVT}, // Lo [27] HANGUL SYLLABLE JYUG..HANGUL SYLLABLE JYUH + {0xC988, 0xC988, prLV}, // Lo HANGUL SYLLABLE JEU + {0xC989, 0xC9A3, prLVT}, // Lo [27] HANGUL SYLLABLE JEUG..HANGUL SYLLABLE JEUH + {0xC9A4, 0xC9A4, prLV}, // Lo HANGUL SYLLABLE JYI + {0xC9A5, 0xC9BF, prLVT}, // Lo [27] HANGUL SYLLABLE JYIG..HANGUL SYLLABLE JYIH + {0xC9C0, 0xC9C0, prLV}, // Lo HANGUL SYLLABLE JI + {0xC9C1, 0xC9DB, prLVT}, // Lo [27] HANGUL SYLLABLE JIG..HANGUL SYLLABLE JIH + {0xC9DC, 0xC9DC, prLV}, // Lo HANGUL SYLLABLE JJA + {0xC9DD, 0xC9F7, prLVT}, // Lo [27] HANGUL SYLLABLE JJAG..HANGUL SYLLABLE JJAH + {0xC9F8, 0xC9F8, prLV}, // Lo HANGUL SYLLABLE JJAE + {0xC9F9, 0xCA13, prLVT}, // Lo [27] HANGUL SYLLABLE JJAEG..HANGUL SYLLABLE JJAEH + {0xCA14, 0xCA14, prLV}, // Lo HANGUL SYLLABLE JJYA + {0xCA15, 0xCA2F, prLVT}, // Lo [27] HANGUL SYLLABLE JJYAG..HANGUL SYLLABLE JJYAH + {0xCA30, 0xCA30, prLV}, // Lo HANGUL SYLLABLE JJYAE + {0xCA31, 0xCA4B, prLVT}, // Lo [27] HANGUL SYLLABLE JJYAEG..HANGUL SYLLABLE JJYAEH + {0xCA4C, 0xCA4C, prLV}, // Lo HANGUL SYLLABLE JJEO + {0xCA4D, 0xCA67, prLVT}, // Lo [27] HANGUL SYLLABLE JJEOG..HANGUL SYLLABLE JJEOH + {0xCA68, 0xCA68, prLV}, // Lo HANGUL SYLLABLE JJE + {0xCA69, 0xCA83, prLVT}, // Lo [27] HANGUL SYLLABLE JJEG..HANGUL SYLLABLE JJEH + {0xCA84, 0xCA84, prLV}, // Lo HANGUL SYLLABLE JJYEO + {0xCA85, 0xCA9F, prLVT}, // Lo [27] HANGUL SYLLABLE JJYEOG..HANGUL SYLLABLE JJYEOH + {0xCAA0, 0xCAA0, prLV}, // Lo HANGUL SYLLABLE JJYE + {0xCAA1, 0xCABB, prLVT}, // Lo [27] HANGUL SYLLABLE JJYEG..HANGUL SYLLABLE JJYEH + {0xCABC, 0xCABC, prLV}, // Lo HANGUL SYLLABLE JJO + {0xCABD, 0xCAD7, prLVT}, // Lo [27] HANGUL SYLLABLE JJOG..HANGUL SYLLABLE JJOH + {0xCAD8, 0xCAD8, prLV}, // Lo HANGUL SYLLABLE JJWA + {0xCAD9, 0xCAF3, prLVT}, // Lo [27] HANGUL SYLLABLE JJWAG..HANGUL SYLLABLE JJWAH + {0xCAF4, 0xCAF4, prLV}, // Lo HANGUL SYLLABLE JJWAE + {0xCAF5, 0xCB0F, prLVT}, // Lo [27] HANGUL SYLLABLE JJWAEG..HANGUL SYLLABLE JJWAEH + {0xCB10, 0xCB10, prLV}, // Lo HANGUL SYLLABLE JJOE + {0xCB11, 0xCB2B, prLVT}, // Lo [27] HANGUL SYLLABLE JJOEG..HANGUL SYLLABLE JJOEH + {0xCB2C, 0xCB2C, prLV}, // Lo HANGUL SYLLABLE JJYO + {0xCB2D, 0xCB47, prLVT}, // Lo [27] HANGUL SYLLABLE JJYOG..HANGUL SYLLABLE JJYOH + {0xCB48, 0xCB48, prLV}, // Lo HANGUL SYLLABLE JJU + {0xCB49, 0xCB63, prLVT}, // Lo [27] HANGUL SYLLABLE JJUG..HANGUL SYLLABLE JJUH + {0xCB64, 0xCB64, prLV}, // Lo HANGUL SYLLABLE JJWEO + {0xCB65, 0xCB7F, prLVT}, // Lo [27] HANGUL SYLLABLE JJWEOG..HANGUL SYLLABLE JJWEOH + {0xCB80, 0xCB80, prLV}, // Lo HANGUL SYLLABLE JJWE + {0xCB81, 0xCB9B, prLVT}, // Lo [27] HANGUL SYLLABLE JJWEG..HANGUL SYLLABLE JJWEH + {0xCB9C, 0xCB9C, prLV}, // Lo HANGUL SYLLABLE JJWI + {0xCB9D, 0xCBB7, prLVT}, // Lo [27] HANGUL SYLLABLE JJWIG..HANGUL SYLLABLE JJWIH + {0xCBB8, 0xCBB8, prLV}, // Lo HANGUL SYLLABLE JJYU + {0xCBB9, 0xCBD3, prLVT}, // Lo [27] HANGUL SYLLABLE JJYUG..HANGUL SYLLABLE JJYUH + {0xCBD4, 0xCBD4, prLV}, // Lo HANGUL SYLLABLE JJEU + {0xCBD5, 0xCBEF, prLVT}, // Lo [27] HANGUL SYLLABLE JJEUG..HANGUL SYLLABLE JJEUH + {0xCBF0, 0xCBF0, prLV}, // Lo HANGUL SYLLABLE JJYI + {0xCBF1, 0xCC0B, prLVT}, // Lo [27] HANGUL SYLLABLE JJYIG..HANGUL SYLLABLE JJYIH + {0xCC0C, 0xCC0C, prLV}, // Lo HANGUL SYLLABLE JJI + {0xCC0D, 0xCC27, prLVT}, // Lo [27] HANGUL SYLLABLE JJIG..HANGUL SYLLABLE JJIH + {0xCC28, 0xCC28, prLV}, // Lo HANGUL SYLLABLE CA + {0xCC29, 0xCC43, prLVT}, // Lo [27] HANGUL SYLLABLE CAG..HANGUL SYLLABLE CAH + {0xCC44, 0xCC44, prLV}, // Lo HANGUL SYLLABLE CAE + {0xCC45, 0xCC5F, prLVT}, // Lo [27] HANGUL SYLLABLE CAEG..HANGUL SYLLABLE CAEH + {0xCC60, 0xCC60, prLV}, // Lo HANGUL SYLLABLE CYA + {0xCC61, 0xCC7B, prLVT}, // Lo [27] HANGUL SYLLABLE CYAG..HANGUL SYLLABLE CYAH + {0xCC7C, 0xCC7C, prLV}, // Lo HANGUL SYLLABLE CYAE + {0xCC7D, 0xCC97, prLVT}, // Lo [27] HANGUL SYLLABLE CYAEG..HANGUL SYLLABLE CYAEH + {0xCC98, 0xCC98, prLV}, // Lo HANGUL SYLLABLE CEO + {0xCC99, 0xCCB3, prLVT}, // Lo [27] HANGUL SYLLABLE CEOG..HANGUL SYLLABLE CEOH + {0xCCB4, 0xCCB4, prLV}, // Lo HANGUL SYLLABLE CE + {0xCCB5, 0xCCCF, prLVT}, // Lo [27] HANGUL SYLLABLE CEG..HANGUL SYLLABLE CEH + {0xCCD0, 0xCCD0, prLV}, // Lo HANGUL SYLLABLE CYEO + {0xCCD1, 0xCCEB, prLVT}, // Lo [27] HANGUL SYLLABLE CYEOG..HANGUL SYLLABLE CYEOH + {0xCCEC, 0xCCEC, prLV}, // Lo HANGUL SYLLABLE CYE + {0xCCED, 0xCD07, prLVT}, // Lo [27] HANGUL SYLLABLE CYEG..HANGUL SYLLABLE CYEH + {0xCD08, 0xCD08, prLV}, // Lo HANGUL SYLLABLE CO + {0xCD09, 0xCD23, prLVT}, // Lo [27] HANGUL SYLLABLE COG..HANGUL SYLLABLE COH + {0xCD24, 0xCD24, prLV}, // Lo HANGUL SYLLABLE CWA + {0xCD25, 0xCD3F, prLVT}, // Lo [27] HANGUL SYLLABLE CWAG..HANGUL SYLLABLE CWAH + {0xCD40, 0xCD40, prLV}, // Lo HANGUL SYLLABLE CWAE + {0xCD41, 0xCD5B, prLVT}, // Lo [27] HANGUL SYLLABLE CWAEG..HANGUL SYLLABLE CWAEH + {0xCD5C, 0xCD5C, prLV}, // Lo HANGUL SYLLABLE COE + {0xCD5D, 0xCD77, prLVT}, // Lo [27] HANGUL SYLLABLE COEG..HANGUL SYLLABLE COEH + {0xCD78, 0xCD78, prLV}, // Lo HANGUL SYLLABLE CYO + {0xCD79, 0xCD93, prLVT}, // Lo [27] HANGUL SYLLABLE CYOG..HANGUL SYLLABLE CYOH + {0xCD94, 0xCD94, prLV}, // Lo HANGUL SYLLABLE CU + {0xCD95, 0xCDAF, prLVT}, // Lo [27] HANGUL SYLLABLE CUG..HANGUL SYLLABLE CUH + {0xCDB0, 0xCDB0, prLV}, // Lo HANGUL SYLLABLE CWEO + {0xCDB1, 0xCDCB, prLVT}, // Lo [27] HANGUL SYLLABLE CWEOG..HANGUL SYLLABLE CWEOH + {0xCDCC, 0xCDCC, prLV}, // Lo HANGUL SYLLABLE CWE + {0xCDCD, 0xCDE7, prLVT}, // Lo [27] HANGUL SYLLABLE CWEG..HANGUL SYLLABLE CWEH + {0xCDE8, 0xCDE8, prLV}, // Lo HANGUL SYLLABLE CWI + {0xCDE9, 0xCE03, prLVT}, // Lo [27] HANGUL SYLLABLE CWIG..HANGUL SYLLABLE CWIH + {0xCE04, 0xCE04, prLV}, // Lo HANGUL SYLLABLE CYU + {0xCE05, 0xCE1F, prLVT}, // Lo [27] HANGUL SYLLABLE CYUG..HANGUL SYLLABLE CYUH + {0xCE20, 0xCE20, prLV}, // Lo HANGUL SYLLABLE CEU + {0xCE21, 0xCE3B, prLVT}, // Lo [27] HANGUL SYLLABLE CEUG..HANGUL SYLLABLE CEUH + {0xCE3C, 0xCE3C, prLV}, // Lo HANGUL SYLLABLE CYI + {0xCE3D, 0xCE57, prLVT}, // Lo [27] HANGUL SYLLABLE CYIG..HANGUL SYLLABLE CYIH + {0xCE58, 0xCE58, prLV}, // Lo HANGUL SYLLABLE CI + {0xCE59, 0xCE73, prLVT}, // Lo [27] HANGUL SYLLABLE CIG..HANGUL SYLLABLE CIH + {0xCE74, 0xCE74, prLV}, // Lo HANGUL SYLLABLE KA + {0xCE75, 0xCE8F, prLVT}, // Lo [27] HANGUL SYLLABLE KAG..HANGUL SYLLABLE KAH + {0xCE90, 0xCE90, prLV}, // Lo HANGUL SYLLABLE KAE + {0xCE91, 0xCEAB, prLVT}, // Lo [27] HANGUL SYLLABLE KAEG..HANGUL SYLLABLE KAEH + {0xCEAC, 0xCEAC, prLV}, // Lo HANGUL SYLLABLE KYA + {0xCEAD, 0xCEC7, prLVT}, // Lo [27] HANGUL SYLLABLE KYAG..HANGUL SYLLABLE KYAH + {0xCEC8, 0xCEC8, prLV}, // Lo HANGUL SYLLABLE KYAE + {0xCEC9, 0xCEE3, prLVT}, // Lo [27] HANGUL SYLLABLE KYAEG..HANGUL SYLLABLE KYAEH + {0xCEE4, 0xCEE4, prLV}, // Lo HANGUL SYLLABLE KEO + {0xCEE5, 0xCEFF, prLVT}, // Lo [27] HANGUL SYLLABLE KEOG..HANGUL SYLLABLE KEOH + {0xCF00, 0xCF00, prLV}, // Lo HANGUL SYLLABLE KE + {0xCF01, 0xCF1B, prLVT}, // Lo [27] HANGUL SYLLABLE KEG..HANGUL SYLLABLE KEH + {0xCF1C, 0xCF1C, prLV}, // Lo HANGUL SYLLABLE KYEO + {0xCF1D, 0xCF37, prLVT}, // Lo [27] HANGUL SYLLABLE KYEOG..HANGUL SYLLABLE KYEOH + {0xCF38, 0xCF38, prLV}, // Lo HANGUL SYLLABLE KYE + {0xCF39, 0xCF53, prLVT}, // Lo [27] HANGUL SYLLABLE KYEG..HANGUL SYLLABLE KYEH + {0xCF54, 0xCF54, prLV}, // Lo HANGUL SYLLABLE KO + {0xCF55, 0xCF6F, prLVT}, // Lo [27] HANGUL SYLLABLE KOG..HANGUL SYLLABLE KOH + {0xCF70, 0xCF70, prLV}, // Lo HANGUL SYLLABLE KWA + {0xCF71, 0xCF8B, prLVT}, // Lo [27] HANGUL SYLLABLE KWAG..HANGUL SYLLABLE KWAH + {0xCF8C, 0xCF8C, prLV}, // Lo HANGUL SYLLABLE KWAE + {0xCF8D, 0xCFA7, prLVT}, // Lo [27] HANGUL SYLLABLE KWAEG..HANGUL SYLLABLE KWAEH + {0xCFA8, 0xCFA8, prLV}, // Lo HANGUL SYLLABLE KOE + {0xCFA9, 0xCFC3, prLVT}, // Lo [27] HANGUL SYLLABLE KOEG..HANGUL SYLLABLE KOEH + {0xCFC4, 0xCFC4, prLV}, // Lo HANGUL SYLLABLE KYO + {0xCFC5, 0xCFDF, prLVT}, // Lo [27] HANGUL SYLLABLE KYOG..HANGUL SYLLABLE KYOH + {0xCFE0, 0xCFE0, prLV}, // Lo HANGUL SYLLABLE KU + {0xCFE1, 0xCFFB, prLVT}, // Lo [27] HANGUL SYLLABLE KUG..HANGUL SYLLABLE KUH + {0xCFFC, 0xCFFC, prLV}, // Lo HANGUL SYLLABLE KWEO + {0xCFFD, 0xD017, prLVT}, // Lo [27] HANGUL SYLLABLE KWEOG..HANGUL SYLLABLE KWEOH + {0xD018, 0xD018, prLV}, // Lo HANGUL SYLLABLE KWE + {0xD019, 0xD033, prLVT}, // Lo [27] HANGUL SYLLABLE KWEG..HANGUL SYLLABLE KWEH + {0xD034, 0xD034, prLV}, // Lo HANGUL SYLLABLE KWI + {0xD035, 0xD04F, prLVT}, // Lo [27] HANGUL SYLLABLE KWIG..HANGUL SYLLABLE KWIH + {0xD050, 0xD050, prLV}, // Lo HANGUL SYLLABLE KYU + {0xD051, 0xD06B, prLVT}, // Lo [27] HANGUL SYLLABLE KYUG..HANGUL SYLLABLE KYUH + {0xD06C, 0xD06C, prLV}, // Lo HANGUL SYLLABLE KEU + {0xD06D, 0xD087, prLVT}, // Lo [27] HANGUL SYLLABLE KEUG..HANGUL SYLLABLE KEUH + {0xD088, 0xD088, prLV}, // Lo HANGUL SYLLABLE KYI + {0xD089, 0xD0A3, prLVT}, // Lo [27] HANGUL SYLLABLE KYIG..HANGUL SYLLABLE KYIH + {0xD0A4, 0xD0A4, prLV}, // Lo HANGUL SYLLABLE KI + {0xD0A5, 0xD0BF, prLVT}, // Lo [27] HANGUL SYLLABLE KIG..HANGUL SYLLABLE KIH + {0xD0C0, 0xD0C0, prLV}, // Lo HANGUL SYLLABLE TA + {0xD0C1, 0xD0DB, prLVT}, // Lo [27] HANGUL SYLLABLE TAG..HANGUL SYLLABLE TAH + {0xD0DC, 0xD0DC, prLV}, // Lo HANGUL SYLLABLE TAE + {0xD0DD, 0xD0F7, prLVT}, // Lo [27] HANGUL SYLLABLE TAEG..HANGUL SYLLABLE TAEH + {0xD0F8, 0xD0F8, prLV}, // Lo HANGUL SYLLABLE TYA + {0xD0F9, 0xD113, prLVT}, // Lo [27] HANGUL SYLLABLE TYAG..HANGUL SYLLABLE TYAH + {0xD114, 0xD114, prLV}, // Lo HANGUL SYLLABLE TYAE + {0xD115, 0xD12F, prLVT}, // Lo [27] HANGUL SYLLABLE TYAEG..HANGUL SYLLABLE TYAEH + {0xD130, 0xD130, prLV}, // Lo HANGUL SYLLABLE TEO + {0xD131, 0xD14B, prLVT}, // Lo [27] HANGUL SYLLABLE TEOG..HANGUL SYLLABLE TEOH + {0xD14C, 0xD14C, prLV}, // Lo HANGUL SYLLABLE TE + {0xD14D, 0xD167, prLVT}, // Lo [27] HANGUL SYLLABLE TEG..HANGUL SYLLABLE TEH + {0xD168, 0xD168, prLV}, // Lo HANGUL SYLLABLE TYEO + {0xD169, 0xD183, prLVT}, // Lo [27] HANGUL SYLLABLE TYEOG..HANGUL SYLLABLE TYEOH + {0xD184, 0xD184, prLV}, // Lo HANGUL SYLLABLE TYE + {0xD185, 0xD19F, prLVT}, // Lo [27] HANGUL SYLLABLE TYEG..HANGUL SYLLABLE TYEH + {0xD1A0, 0xD1A0, prLV}, // Lo HANGUL SYLLABLE TO + {0xD1A1, 0xD1BB, prLVT}, // Lo [27] HANGUL SYLLABLE TOG..HANGUL SYLLABLE TOH + {0xD1BC, 0xD1BC, prLV}, // Lo HANGUL SYLLABLE TWA + {0xD1BD, 0xD1D7, prLVT}, // Lo [27] HANGUL SYLLABLE TWAG..HANGUL SYLLABLE TWAH + {0xD1D8, 0xD1D8, prLV}, // Lo HANGUL SYLLABLE TWAE + {0xD1D9, 0xD1F3, prLVT}, // Lo [27] HANGUL SYLLABLE TWAEG..HANGUL SYLLABLE TWAEH + {0xD1F4, 0xD1F4, prLV}, // Lo HANGUL SYLLABLE TOE + {0xD1F5, 0xD20F, prLVT}, // Lo [27] HANGUL SYLLABLE TOEG..HANGUL SYLLABLE TOEH + {0xD210, 0xD210, prLV}, // Lo HANGUL SYLLABLE TYO + {0xD211, 0xD22B, prLVT}, // Lo [27] HANGUL SYLLABLE TYOG..HANGUL SYLLABLE TYOH + {0xD22C, 0xD22C, prLV}, // Lo HANGUL SYLLABLE TU + {0xD22D, 0xD247, prLVT}, // Lo [27] HANGUL SYLLABLE TUG..HANGUL SYLLABLE TUH + {0xD248, 0xD248, prLV}, // Lo HANGUL SYLLABLE TWEO + {0xD249, 0xD263, prLVT}, // Lo [27] HANGUL SYLLABLE TWEOG..HANGUL SYLLABLE TWEOH + {0xD264, 0xD264, prLV}, // Lo HANGUL SYLLABLE TWE + {0xD265, 0xD27F, prLVT}, // Lo [27] HANGUL SYLLABLE TWEG..HANGUL SYLLABLE TWEH + {0xD280, 0xD280, prLV}, // Lo HANGUL SYLLABLE TWI + {0xD281, 0xD29B, prLVT}, // Lo [27] HANGUL SYLLABLE TWIG..HANGUL SYLLABLE TWIH + {0xD29C, 0xD29C, prLV}, // Lo HANGUL SYLLABLE TYU + {0xD29D, 0xD2B7, prLVT}, // Lo [27] HANGUL SYLLABLE TYUG..HANGUL SYLLABLE TYUH + {0xD2B8, 0xD2B8, prLV}, // Lo HANGUL SYLLABLE TEU + {0xD2B9, 0xD2D3, prLVT}, // Lo [27] HANGUL SYLLABLE TEUG..HANGUL SYLLABLE TEUH + {0xD2D4, 0xD2D4, prLV}, // Lo HANGUL SYLLABLE TYI + {0xD2D5, 0xD2EF, prLVT}, // Lo [27] HANGUL SYLLABLE TYIG..HANGUL SYLLABLE TYIH + {0xD2F0, 0xD2F0, prLV}, // Lo HANGUL SYLLABLE TI + {0xD2F1, 0xD30B, prLVT}, // Lo [27] HANGUL SYLLABLE TIG..HANGUL SYLLABLE TIH + {0xD30C, 0xD30C, prLV}, // Lo HANGUL SYLLABLE PA + {0xD30D, 0xD327, prLVT}, // Lo [27] HANGUL SYLLABLE PAG..HANGUL SYLLABLE PAH + {0xD328, 0xD328, prLV}, // Lo HANGUL SYLLABLE PAE + {0xD329, 0xD343, prLVT}, // Lo [27] HANGUL SYLLABLE PAEG..HANGUL SYLLABLE PAEH + {0xD344, 0xD344, prLV}, // Lo HANGUL SYLLABLE PYA + {0xD345, 0xD35F, prLVT}, // Lo [27] HANGUL SYLLABLE PYAG..HANGUL SYLLABLE PYAH + {0xD360, 0xD360, prLV}, // Lo HANGUL SYLLABLE PYAE + {0xD361, 0xD37B, prLVT}, // Lo [27] HANGUL SYLLABLE PYAEG..HANGUL SYLLABLE PYAEH + {0xD37C, 0xD37C, prLV}, // Lo HANGUL SYLLABLE PEO + {0xD37D, 0xD397, prLVT}, // Lo [27] HANGUL SYLLABLE PEOG..HANGUL SYLLABLE PEOH + {0xD398, 0xD398, prLV}, // Lo HANGUL SYLLABLE PE + {0xD399, 0xD3B3, prLVT}, // Lo [27] HANGUL SYLLABLE PEG..HANGUL SYLLABLE PEH + {0xD3B4, 0xD3B4, prLV}, // Lo HANGUL SYLLABLE PYEO + {0xD3B5, 0xD3CF, prLVT}, // Lo [27] HANGUL SYLLABLE PYEOG..HANGUL SYLLABLE PYEOH + {0xD3D0, 0xD3D0, prLV}, // Lo HANGUL SYLLABLE PYE + {0xD3D1, 0xD3EB, prLVT}, // Lo [27] HANGUL SYLLABLE PYEG..HANGUL SYLLABLE PYEH + {0xD3EC, 0xD3EC, prLV}, // Lo HANGUL SYLLABLE PO + {0xD3ED, 0xD407, prLVT}, // Lo [27] HANGUL SYLLABLE POG..HANGUL SYLLABLE POH + {0xD408, 0xD408, prLV}, // Lo HANGUL SYLLABLE PWA + {0xD409, 0xD423, prLVT}, // Lo [27] HANGUL SYLLABLE PWAG..HANGUL SYLLABLE PWAH + {0xD424, 0xD424, prLV}, // Lo HANGUL SYLLABLE PWAE + {0xD425, 0xD43F, prLVT}, // Lo [27] HANGUL SYLLABLE PWAEG..HANGUL SYLLABLE PWAEH + {0xD440, 0xD440, prLV}, // Lo HANGUL SYLLABLE POE + {0xD441, 0xD45B, prLVT}, // Lo [27] HANGUL SYLLABLE POEG..HANGUL SYLLABLE POEH + {0xD45C, 0xD45C, prLV}, // Lo HANGUL SYLLABLE PYO + {0xD45D, 0xD477, prLVT}, // Lo [27] HANGUL SYLLABLE PYOG..HANGUL SYLLABLE PYOH + {0xD478, 0xD478, prLV}, // Lo HANGUL SYLLABLE PU + {0xD479, 0xD493, prLVT}, // Lo [27] HANGUL SYLLABLE PUG..HANGUL SYLLABLE PUH + {0xD494, 0xD494, prLV}, // Lo HANGUL SYLLABLE PWEO + {0xD495, 0xD4AF, prLVT}, // Lo [27] HANGUL SYLLABLE PWEOG..HANGUL SYLLABLE PWEOH + {0xD4B0, 0xD4B0, prLV}, // Lo HANGUL SYLLABLE PWE + {0xD4B1, 0xD4CB, prLVT}, // Lo [27] HANGUL SYLLABLE PWEG..HANGUL SYLLABLE PWEH + {0xD4CC, 0xD4CC, prLV}, // Lo HANGUL SYLLABLE PWI + {0xD4CD, 0xD4E7, prLVT}, // Lo [27] HANGUL SYLLABLE PWIG..HANGUL SYLLABLE PWIH + {0xD4E8, 0xD4E8, prLV}, // Lo HANGUL SYLLABLE PYU + {0xD4E9, 0xD503, prLVT}, // Lo [27] HANGUL SYLLABLE PYUG..HANGUL SYLLABLE PYUH + {0xD504, 0xD504, prLV}, // Lo HANGUL SYLLABLE PEU + {0xD505, 0xD51F, prLVT}, // Lo [27] HANGUL SYLLABLE PEUG..HANGUL SYLLABLE PEUH + {0xD520, 0xD520, prLV}, // Lo HANGUL SYLLABLE PYI + {0xD521, 0xD53B, prLVT}, // Lo [27] HANGUL SYLLABLE PYIG..HANGUL SYLLABLE PYIH + {0xD53C, 0xD53C, prLV}, // Lo HANGUL SYLLABLE PI + {0xD53D, 0xD557, prLVT}, // Lo [27] HANGUL SYLLABLE PIG..HANGUL SYLLABLE PIH + {0xD558, 0xD558, prLV}, // Lo HANGUL SYLLABLE HA + {0xD559, 0xD573, prLVT}, // Lo [27] HANGUL SYLLABLE HAG..HANGUL SYLLABLE HAH + {0xD574, 0xD574, prLV}, // Lo HANGUL SYLLABLE HAE + {0xD575, 0xD58F, prLVT}, // Lo [27] HANGUL SYLLABLE HAEG..HANGUL SYLLABLE HAEH + {0xD590, 0xD590, prLV}, // Lo HANGUL SYLLABLE HYA + {0xD591, 0xD5AB, prLVT}, // Lo [27] HANGUL SYLLABLE HYAG..HANGUL SYLLABLE HYAH + {0xD5AC, 0xD5AC, prLV}, // Lo HANGUL SYLLABLE HYAE + {0xD5AD, 0xD5C7, prLVT}, // Lo [27] HANGUL SYLLABLE HYAEG..HANGUL SYLLABLE HYAEH + {0xD5C8, 0xD5C8, prLV}, // Lo HANGUL SYLLABLE HEO + {0xD5C9, 0xD5E3, prLVT}, // Lo [27] HANGUL SYLLABLE HEOG..HANGUL SYLLABLE HEOH + {0xD5E4, 0xD5E4, prLV}, // Lo HANGUL SYLLABLE HE + {0xD5E5, 0xD5FF, prLVT}, // Lo [27] HANGUL SYLLABLE HEG..HANGUL SYLLABLE HEH + {0xD600, 0xD600, prLV}, // Lo HANGUL SYLLABLE HYEO + {0xD601, 0xD61B, prLVT}, // Lo [27] HANGUL SYLLABLE HYEOG..HANGUL SYLLABLE HYEOH + {0xD61C, 0xD61C, prLV}, // Lo HANGUL SYLLABLE HYE + {0xD61D, 0xD637, prLVT}, // Lo [27] HANGUL SYLLABLE HYEG..HANGUL SYLLABLE HYEH + {0xD638, 0xD638, prLV}, // Lo HANGUL SYLLABLE HO + {0xD639, 0xD653, prLVT}, // Lo [27] HANGUL SYLLABLE HOG..HANGUL SYLLABLE HOH + {0xD654, 0xD654, prLV}, // Lo HANGUL SYLLABLE HWA + {0xD655, 0xD66F, prLVT}, // Lo [27] HANGUL SYLLABLE HWAG..HANGUL SYLLABLE HWAH + {0xD670, 0xD670, prLV}, // Lo HANGUL SYLLABLE HWAE + {0xD671, 0xD68B, prLVT}, // Lo [27] HANGUL SYLLABLE HWAEG..HANGUL SYLLABLE HWAEH + {0xD68C, 0xD68C, prLV}, // Lo HANGUL SYLLABLE HOE + {0xD68D, 0xD6A7, prLVT}, // Lo [27] HANGUL SYLLABLE HOEG..HANGUL SYLLABLE HOEH + {0xD6A8, 0xD6A8, prLV}, // Lo HANGUL SYLLABLE HYO + {0xD6A9, 0xD6C3, prLVT}, // Lo [27] HANGUL SYLLABLE HYOG..HANGUL SYLLABLE HYOH + {0xD6C4, 0xD6C4, prLV}, // Lo HANGUL SYLLABLE HU + {0xD6C5, 0xD6DF, prLVT}, // Lo [27] HANGUL SYLLABLE HUG..HANGUL SYLLABLE HUH + {0xD6E0, 0xD6E0, prLV}, // Lo HANGUL SYLLABLE HWEO + {0xD6E1, 0xD6FB, prLVT}, // Lo [27] HANGUL SYLLABLE HWEOG..HANGUL SYLLABLE HWEOH + {0xD6FC, 0xD6FC, prLV}, // Lo HANGUL SYLLABLE HWE + {0xD6FD, 0xD717, prLVT}, // Lo [27] HANGUL SYLLABLE HWEG..HANGUL SYLLABLE HWEH + {0xD718, 0xD718, prLV}, // Lo HANGUL SYLLABLE HWI + {0xD719, 0xD733, prLVT}, // Lo [27] HANGUL SYLLABLE HWIG..HANGUL SYLLABLE HWIH + {0xD734, 0xD734, prLV}, // Lo HANGUL SYLLABLE HYU + {0xD735, 0xD74F, prLVT}, // Lo [27] HANGUL SYLLABLE HYUG..HANGUL SYLLABLE HYUH + {0xD750, 0xD750, prLV}, // Lo HANGUL SYLLABLE HEU + {0xD751, 0xD76B, prLVT}, // Lo [27] HANGUL SYLLABLE HEUG..HANGUL SYLLABLE HEUH + {0xD76C, 0xD76C, prLV}, // Lo HANGUL SYLLABLE HYI + {0xD76D, 0xD787, prLVT}, // Lo [27] HANGUL SYLLABLE HYIG..HANGUL SYLLABLE HYIH + {0xD788, 0xD788, prLV}, // Lo HANGUL SYLLABLE HI + {0xD789, 0xD7A3, prLVT}, // Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH + {0xD7B0, 0xD7C6, prV}, // Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E + {0xD7CB, 0xD7FB, prT}, // Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH + {0xFB1E, 0xFB1E, prExtend}, // Mn HEBREW POINT JUDEO-SPANISH VARIKA + {0xFE00, 0xFE0F, prExtend}, // Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 + {0xFE20, 0xFE2F, prExtend}, // Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + {0xFEFF, 0xFEFF, prControl}, // Cf ZERO WIDTH NO-BREAK SPACE + {0xFF9E, 0xFF9F, prExtend}, // Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + {0xFFF0, 0xFFF8, prControl}, // Cn [9] .. + {0xFFF9, 0xFFFB, prControl}, // Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR + {0x101FD, 0x101FD, prExtend}, // Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE + {0x102E0, 0x102E0, prExtend}, // Mn COPTIC EPACT THOUSANDS MARK + {0x10376, 0x1037A, prExtend}, // Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + {0x10A01, 0x10A03, prExtend}, // Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R + {0x10A05, 0x10A06, prExtend}, // Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O + {0x10A0C, 0x10A0F, prExtend}, // Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA + {0x10A38, 0x10A3A, prExtend}, // Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW + {0x10A3F, 0x10A3F, prExtend}, // Mn KHAROSHTHI VIRAMA + {0x10AE5, 0x10AE6, prExtend}, // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW + {0x10D24, 0x10D27, prExtend}, // Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI + {0x10EAB, 0x10EAC, prExtend}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK + {0x10EFD, 0x10EFF, prExtend}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA + {0x10F46, 0x10F50, prExtend}, // Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW + {0x10F82, 0x10F85, prExtend}, // Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW + {0x11000, 0x11000, prSpacingMark}, // Mc BRAHMI SIGN CANDRABINDU + {0x11001, 0x11001, prExtend}, // Mn BRAHMI SIGN ANUSVARA + {0x11002, 0x11002, prSpacingMark}, // Mc BRAHMI SIGN VISARGA + {0x11038, 0x11046, prExtend}, // Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA + {0x11070, 0x11070, prExtend}, // Mn BRAHMI SIGN OLD TAMIL VIRAMA + {0x11073, 0x11074, prExtend}, // Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O + {0x1107F, 0x11081, prExtend}, // Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA + {0x11082, 0x11082, prSpacingMark}, // Mc KAITHI SIGN VISARGA + {0x110B0, 0x110B2, prSpacingMark}, // Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II + {0x110B3, 0x110B6, prExtend}, // Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI + {0x110B7, 0x110B8, prSpacingMark}, // Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU + {0x110B9, 0x110BA, prExtend}, // Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA + {0x110BD, 0x110BD, prPrepend}, // Cf KAITHI NUMBER SIGN + {0x110C2, 0x110C2, prExtend}, // Mn KAITHI VOWEL SIGN VOCALIC R + {0x110CD, 0x110CD, prPrepend}, // Cf KAITHI NUMBER SIGN ABOVE + {0x11100, 0x11102, prExtend}, // Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA + {0x11127, 0x1112B, prExtend}, // Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU + {0x1112C, 0x1112C, prSpacingMark}, // Mc CHAKMA VOWEL SIGN E + {0x1112D, 0x11134, prExtend}, // Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA + {0x11145, 0x11146, prSpacingMark}, // Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI + {0x11173, 0x11173, prExtend}, // Mn MAHAJANI SIGN NUKTA + {0x11180, 0x11181, prExtend}, // Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA + {0x11182, 0x11182, prSpacingMark}, // Mc SHARADA SIGN VISARGA + {0x111B3, 0x111B5, prSpacingMark}, // Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II + {0x111B6, 0x111BE, prExtend}, // Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O + {0x111BF, 0x111C0, prSpacingMark}, // Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA + {0x111C2, 0x111C3, prPrepend}, // Lo [2] SHARADA SIGN JIHVAMULIYA..SHARADA SIGN UPADHMANIYA + {0x111C9, 0x111CC, prExtend}, // Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK + {0x111CE, 0x111CE, prSpacingMark}, // Mc SHARADA VOWEL SIGN PRISHTHAMATRA E + {0x111CF, 0x111CF, prExtend}, // Mn SHARADA SIGN INVERTED CANDRABINDU + {0x1122C, 0x1122E, prSpacingMark}, // Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II + {0x1122F, 0x11231, prExtend}, // Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI + {0x11232, 0x11233, prSpacingMark}, // Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU + {0x11234, 0x11234, prExtend}, // Mn KHOJKI SIGN ANUSVARA + {0x11235, 0x11235, prSpacingMark}, // Mc KHOJKI SIGN VIRAMA + {0x11236, 0x11237, prExtend}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA + {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x11241, 0x11241, prExtend}, // Mn KHOJKI VOWEL SIGN VOCALIC R + {0x112DF, 0x112DF, prExtend}, // Mn KHUDAWADI SIGN ANUSVARA + {0x112E0, 0x112E2, prSpacingMark}, // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II + {0x112E3, 0x112EA, prExtend}, // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA + {0x11300, 0x11301, prExtend}, // Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU + {0x11302, 0x11303, prSpacingMark}, // Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA + {0x1133B, 0x1133C, prExtend}, // Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA + {0x1133E, 0x1133E, prExtend}, // Mc GRANTHA VOWEL SIGN AA + {0x1133F, 0x1133F, prSpacingMark}, // Mc GRANTHA VOWEL SIGN I + {0x11340, 0x11340, prExtend}, // Mn GRANTHA VOWEL SIGN II + {0x11341, 0x11344, prSpacingMark}, // Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR + {0x11347, 0x11348, prSpacingMark}, // Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI + {0x1134B, 0x1134D, prSpacingMark}, // Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA + {0x11357, 0x11357, prExtend}, // Mc GRANTHA AU LENGTH MARK + {0x11362, 0x11363, prSpacingMark}, // Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL + {0x11366, 0x1136C, prExtend}, // Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX + {0x11370, 0x11374, prExtend}, // Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + {0x11435, 0x11437, prSpacingMark}, // Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II + {0x11438, 0x1143F, prExtend}, // Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI + {0x11440, 0x11441, prSpacingMark}, // Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU + {0x11442, 0x11444, prExtend}, // Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA + {0x11445, 0x11445, prSpacingMark}, // Mc NEWA SIGN VISARGA + {0x11446, 0x11446, prExtend}, // Mn NEWA SIGN NUKTA + {0x1145E, 0x1145E, prExtend}, // Mn NEWA SANDHI MARK + {0x114B0, 0x114B0, prExtend}, // Mc TIRHUTA VOWEL SIGN AA + {0x114B1, 0x114B2, prSpacingMark}, // Mc [2] TIRHUTA VOWEL SIGN I..TIRHUTA VOWEL SIGN II + {0x114B3, 0x114B8, prExtend}, // Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL + {0x114B9, 0x114B9, prSpacingMark}, // Mc TIRHUTA VOWEL SIGN E + {0x114BA, 0x114BA, prExtend}, // Mn TIRHUTA VOWEL SIGN SHORT E + {0x114BB, 0x114BC, prSpacingMark}, // Mc [2] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN O + {0x114BD, 0x114BD, prExtend}, // Mc TIRHUTA VOWEL SIGN SHORT O + {0x114BE, 0x114BE, prSpacingMark}, // Mc TIRHUTA VOWEL SIGN AU + {0x114BF, 0x114C0, prExtend}, // Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA + {0x114C1, 0x114C1, prSpacingMark}, // Mc TIRHUTA SIGN VISARGA + {0x114C2, 0x114C3, prExtend}, // Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA + {0x115AF, 0x115AF, prExtend}, // Mc SIDDHAM VOWEL SIGN AA + {0x115B0, 0x115B1, prSpacingMark}, // Mc [2] SIDDHAM VOWEL SIGN I..SIDDHAM VOWEL SIGN II + {0x115B2, 0x115B5, prExtend}, // Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR + {0x115B8, 0x115BB, prSpacingMark}, // Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU + {0x115BC, 0x115BD, prExtend}, // Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA + {0x115BE, 0x115BE, prSpacingMark}, // Mc SIDDHAM SIGN VISARGA + {0x115BF, 0x115C0, prExtend}, // Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA + {0x115DC, 0x115DD, prExtend}, // Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + {0x11630, 0x11632, prSpacingMark}, // Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II + {0x11633, 0x1163A, prExtend}, // Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI + {0x1163B, 0x1163C, prSpacingMark}, // Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU + {0x1163D, 0x1163D, prExtend}, // Mn MODI SIGN ANUSVARA + {0x1163E, 0x1163E, prSpacingMark}, // Mc MODI SIGN VISARGA + {0x1163F, 0x11640, prExtend}, // Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA + {0x116AB, 0x116AB, prExtend}, // Mn TAKRI SIGN ANUSVARA + {0x116AC, 0x116AC, prSpacingMark}, // Mc TAKRI SIGN VISARGA + {0x116AD, 0x116AD, prExtend}, // Mn TAKRI VOWEL SIGN AA + {0x116AE, 0x116AF, prSpacingMark}, // Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II + {0x116B0, 0x116B5, prExtend}, // Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU + {0x116B6, 0x116B6, prSpacingMark}, // Mc TAKRI SIGN VIRAMA + {0x116B7, 0x116B7, prExtend}, // Mn TAKRI SIGN NUKTA + {0x1171D, 0x1171F, prExtend}, // Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA + {0x11722, 0x11725, prExtend}, // Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU + {0x11726, 0x11726, prSpacingMark}, // Mc AHOM VOWEL SIGN E + {0x11727, 0x1172B, prExtend}, // Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER + {0x1182C, 0x1182E, prSpacingMark}, // Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II + {0x1182F, 0x11837, prExtend}, // Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA + {0x11838, 0x11838, prSpacingMark}, // Mc DOGRA SIGN VISARGA + {0x11839, 0x1183A, prExtend}, // Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA + {0x11930, 0x11930, prExtend}, // Mc DIVES AKURU VOWEL SIGN AA + {0x11931, 0x11935, prSpacingMark}, // Mc [5] DIVES AKURU VOWEL SIGN I..DIVES AKURU VOWEL SIGN E + {0x11937, 0x11938, prSpacingMark}, // Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O + {0x1193B, 0x1193C, prExtend}, // Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU + {0x1193D, 0x1193D, prSpacingMark}, // Mc DIVES AKURU SIGN HALANTA + {0x1193E, 0x1193E, prExtend}, // Mn DIVES AKURU VIRAMA + {0x1193F, 0x1193F, prPrepend}, // Lo DIVES AKURU PREFIXED NASAL SIGN + {0x11940, 0x11940, prSpacingMark}, // Mc DIVES AKURU MEDIAL YA + {0x11941, 0x11941, prPrepend}, // Lo DIVES AKURU INITIAL RA + {0x11942, 0x11942, prSpacingMark}, // Mc DIVES AKURU MEDIAL RA + {0x11943, 0x11943, prExtend}, // Mn DIVES AKURU SIGN NUKTA + {0x119D1, 0x119D3, prSpacingMark}, // Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II + {0x119D4, 0x119D7, prExtend}, // Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR + {0x119DA, 0x119DB, prExtend}, // Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI + {0x119DC, 0x119DF, prSpacingMark}, // Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA + {0x119E0, 0x119E0, prExtend}, // Mn NANDINAGARI SIGN VIRAMA + {0x119E4, 0x119E4, prSpacingMark}, // Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E + {0x11A01, 0x11A0A, prExtend}, // Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK + {0x11A33, 0x11A38, prExtend}, // Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA + {0x11A39, 0x11A39, prSpacingMark}, // Mc ZANABAZAR SQUARE SIGN VISARGA + {0x11A3A, 0x11A3A, prPrepend}, // Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA + {0x11A3B, 0x11A3E, prExtend}, // Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA + {0x11A47, 0x11A47, prExtend}, // Mn ZANABAZAR SQUARE SUBJOINER + {0x11A51, 0x11A56, prExtend}, // Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE + {0x11A57, 0x11A58, prSpacingMark}, // Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU + {0x11A59, 0x11A5B, prExtend}, // Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK + {0x11A84, 0x11A89, prPrepend}, // Lo [6] SOYOMBO SIGN JIHVAMULIYA..SOYOMBO CLUSTER-INITIAL LETTER SA + {0x11A8A, 0x11A96, prExtend}, // Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA + {0x11A97, 0x11A97, prSpacingMark}, // Mc SOYOMBO SIGN VISARGA + {0x11A98, 0x11A99, prExtend}, // Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER + {0x11C2F, 0x11C2F, prSpacingMark}, // Mc BHAIKSUKI VOWEL SIGN AA + {0x11C30, 0x11C36, prExtend}, // Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L + {0x11C38, 0x11C3D, prExtend}, // Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA + {0x11C3E, 0x11C3E, prSpacingMark}, // Mc BHAIKSUKI SIGN VISARGA + {0x11C3F, 0x11C3F, prExtend}, // Mn BHAIKSUKI SIGN VIRAMA + {0x11C92, 0x11CA7, prExtend}, // Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA + {0x11CA9, 0x11CA9, prSpacingMark}, // Mc MARCHEN SUBJOINED LETTER YA + {0x11CAA, 0x11CB0, prExtend}, // Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA + {0x11CB1, 0x11CB1, prSpacingMark}, // Mc MARCHEN VOWEL SIGN I + {0x11CB2, 0x11CB3, prExtend}, // Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E + {0x11CB4, 0x11CB4, prSpacingMark}, // Mc MARCHEN VOWEL SIGN O + {0x11CB5, 0x11CB6, prExtend}, // Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + {0x11D31, 0x11D36, prExtend}, // Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R + {0x11D3A, 0x11D3A, prExtend}, // Mn MASARAM GONDI VOWEL SIGN E + {0x11D3C, 0x11D3D, prExtend}, // Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O + {0x11D3F, 0x11D45, prExtend}, // Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA + {0x11D46, 0x11D46, prPrepend}, // Lo MASARAM GONDI REPHA + {0x11D47, 0x11D47, prExtend}, // Mn MASARAM GONDI RA-KARA + {0x11D8A, 0x11D8E, prSpacingMark}, // Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU + {0x11D90, 0x11D91, prExtend}, // Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI + {0x11D93, 0x11D94, prSpacingMark}, // Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU + {0x11D95, 0x11D95, prExtend}, // Mn GUNJALA GONDI SIGN ANUSVARA + {0x11D96, 0x11D96, prSpacingMark}, // Mc GUNJALA GONDI SIGN VISARGA + {0x11D97, 0x11D97, prExtend}, // Mn GUNJALA GONDI VIRAMA + {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U + {0x11EF5, 0x11EF6, prSpacingMark}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x11F00, 0x11F01, prExtend}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prPrepend}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prSpacingMark}, // Mc KAWI SIGN VISARGA + {0x11F34, 0x11F35, prSpacingMark}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prExtend}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prSpacingMark}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prExtend}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prSpacingMark}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prExtend}, // Mn KAWI CONJOINER + {0x13430, 0x1343F, prControl}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prExtend}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13447, 0x13455, prExtend}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED + {0x16AF0, 0x16AF4, prExtend}, // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE + {0x16B30, 0x16B36, prExtend}, // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM + {0x16F4F, 0x16F4F, prExtend}, // Mn MIAO SIGN CONSONANT MODIFIER BAR + {0x16F51, 0x16F87, prSpacingMark}, // Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI + {0x16F8F, 0x16F92, prExtend}, // Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW + {0x16FE4, 0x16FE4, prExtend}, // Mn KHITAN SMALL SCRIPT FILLER + {0x16FF0, 0x16FF1, prSpacingMark}, // Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY + {0x1BC9D, 0x1BC9E, prExtend}, // Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK + {0x1BCA0, 0x1BCA3, prControl}, // Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP + {0x1CF00, 0x1CF2D, prExtend}, // Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT + {0x1CF30, 0x1CF46, prExtend}, // Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG + {0x1D165, 0x1D165, prExtend}, // Mc MUSICAL SYMBOL COMBINING STEM + {0x1D166, 0x1D166, prSpacingMark}, // Mc MUSICAL SYMBOL COMBINING SPRECHGESANG STEM + {0x1D167, 0x1D169, prExtend}, // Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 + {0x1D16D, 0x1D16D, prSpacingMark}, // Mc MUSICAL SYMBOL COMBINING AUGMENTATION DOT + {0x1D16E, 0x1D172, prExtend}, // Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5 + {0x1D173, 0x1D17A, prControl}, // Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE + {0x1D17B, 0x1D182, prExtend}, // Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE + {0x1D185, 0x1D18B, prExtend}, // Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE + {0x1D1AA, 0x1D1AD, prExtend}, // Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO + {0x1D242, 0x1D244, prExtend}, // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME + {0x1DA00, 0x1DA36, prExtend}, // Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN + {0x1DA3B, 0x1DA6C, prExtend}, // Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT + {0x1DA75, 0x1DA75, prExtend}, // Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS + {0x1DA84, 0x1DA84, prExtend}, // Mn SIGNWRITING LOCATION HEAD NECK + {0x1DA9B, 0x1DA9F, prExtend}, // Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 + {0x1DAA1, 0x1DAAF, prExtend}, // Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + {0x1E000, 0x1E006, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE + {0x1E008, 0x1E018, prExtend}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU + {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI + {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS + {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E08F, 0x1E08F, prExtend}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D + {0x1E2AE, 0x1E2AE, prExtend}, // Mn TOTO SIGN RISING TONE + {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E4EC, 0x1E4EF, prExtend}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E8D0, 0x1E8D6, prExtend}, // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + {0x1E944, 0x1E94A, prExtend}, // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA + {0x1F000, 0x1F003, prExtendedPictographic}, // E0.0 [4] (🀀..🀃) MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND + {0x1F004, 0x1F004, prExtendedPictographic}, // E0.6 [1] (🀄) mahjong red dragon + {0x1F005, 0x1F0CE, prExtendedPictographic}, // E0.0 [202] (🀅..🃎) MAHJONG TILE GREEN DRAGON..PLAYING CARD KING OF DIAMONDS + {0x1F0CF, 0x1F0CF, prExtendedPictographic}, // E0.6 [1] (🃏) joker + {0x1F0D0, 0x1F0FF, prExtendedPictographic}, // E0.0 [48] (🃐..🃿) .. + {0x1F10D, 0x1F10F, prExtendedPictographic}, // E0.0 [3] (🄍..🄏) CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH + {0x1F12F, 0x1F12F, prExtendedPictographic}, // E0.0 [1] (🄯) COPYLEFT SYMBOL + {0x1F16C, 0x1F16F, prExtendedPictographic}, // E0.0 [4] (🅬..🅯) RAISED MR SIGN..CIRCLED HUMAN FIGURE + {0x1F170, 0x1F171, prExtendedPictographic}, // E0.6 [2] (🅰️..🅱️) A button (blood type)..B button (blood type) + {0x1F17E, 0x1F17F, prExtendedPictographic}, // E0.6 [2] (🅾️..🅿️) O button (blood type)..P button + {0x1F18E, 0x1F18E, prExtendedPictographic}, // E0.6 [1] (🆎) AB button (blood type) + {0x1F191, 0x1F19A, prExtendedPictographic}, // E0.6 [10] (🆑..🆚) CL button..VS button + {0x1F1AD, 0x1F1E5, prExtendedPictographic}, // E0.0 [57] (🆭..🇥) MASK WORK SYMBOL.. + {0x1F1E6, 0x1F1FF, prRegionalIndicator}, // So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + {0x1F201, 0x1F202, prExtendedPictographic}, // E0.6 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button + {0x1F203, 0x1F20F, prExtendedPictographic}, // E0.0 [13] (🈃..🈏) .. + {0x1F21A, 0x1F21A, prExtendedPictographic}, // E0.6 [1] (🈚) Japanese “free of charge” button + {0x1F22F, 0x1F22F, prExtendedPictographic}, // E0.6 [1] (🈯) Japanese “reserved” button + {0x1F232, 0x1F23A, prExtendedPictographic}, // E0.6 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button + {0x1F23C, 0x1F23F, prExtendedPictographic}, // E0.0 [4] (🈼..🈿) .. + {0x1F249, 0x1F24F, prExtendedPictographic}, // E0.0 [7] (🉉..🉏) .. + {0x1F250, 0x1F251, prExtendedPictographic}, // E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button + {0x1F252, 0x1F2FF, prExtendedPictographic}, // E0.0 [174] (🉒..🋿) .. + {0x1F300, 0x1F30C, prExtendedPictographic}, // E0.6 [13] (🌀..🌌) cyclone..milky way + {0x1F30D, 0x1F30E, prExtendedPictographic}, // E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas + {0x1F30F, 0x1F30F, prExtendedPictographic}, // E0.6 [1] (🌏) globe showing Asia-Australia + {0x1F310, 0x1F310, prExtendedPictographic}, // E1.0 [1] (🌐) globe with meridians + {0x1F311, 0x1F311, prExtendedPictographic}, // E0.6 [1] (🌑) new moon + {0x1F312, 0x1F312, prExtendedPictographic}, // E1.0 [1] (🌒) waxing crescent moon + {0x1F313, 0x1F315, prExtendedPictographic}, // E0.6 [3] (🌓..🌕) first quarter moon..full moon + {0x1F316, 0x1F318, prExtendedPictographic}, // E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon + {0x1F319, 0x1F319, prExtendedPictographic}, // E0.6 [1] (🌙) crescent moon + {0x1F31A, 0x1F31A, prExtendedPictographic}, // E1.0 [1] (🌚) new moon face + {0x1F31B, 0x1F31B, prExtendedPictographic}, // E0.6 [1] (🌛) first quarter moon face + {0x1F31C, 0x1F31C, prExtendedPictographic}, // E0.7 [1] (🌜) last quarter moon face + {0x1F31D, 0x1F31E, prExtendedPictographic}, // E1.0 [2] (🌝..🌞) full moon face..sun with face + {0x1F31F, 0x1F320, prExtendedPictographic}, // E0.6 [2] (🌟..🌠) glowing star..shooting star + {0x1F321, 0x1F321, prExtendedPictographic}, // E0.7 [1] (🌡️) thermometer + {0x1F322, 0x1F323, prExtendedPictographic}, // E0.0 [2] (🌢..🌣) BLACK DROPLET..WHITE SUN + {0x1F324, 0x1F32C, prExtendedPictographic}, // E0.7 [9] (🌤️..🌬️) sun behind small cloud..wind face + {0x1F32D, 0x1F32F, prExtendedPictographic}, // E1.0 [3] (🌭..🌯) hot dog..burrito + {0x1F330, 0x1F331, prExtendedPictographic}, // E0.6 [2] (🌰..🌱) chestnut..seedling + {0x1F332, 0x1F333, prExtendedPictographic}, // E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree + {0x1F334, 0x1F335, prExtendedPictographic}, // E0.6 [2] (🌴..🌵) palm tree..cactus + {0x1F336, 0x1F336, prExtendedPictographic}, // E0.7 [1] (🌶️) hot pepper + {0x1F337, 0x1F34A, prExtendedPictographic}, // E0.6 [20] (🌷..🍊) tulip..tangerine + {0x1F34B, 0x1F34B, prExtendedPictographic}, // E1.0 [1] (🍋) lemon + {0x1F34C, 0x1F34F, prExtendedPictographic}, // E0.6 [4] (🍌..🍏) banana..green apple + {0x1F350, 0x1F350, prExtendedPictographic}, // E1.0 [1] (🍐) pear + {0x1F351, 0x1F37B, prExtendedPictographic}, // E0.6 [43] (🍑..🍻) peach..clinking beer mugs + {0x1F37C, 0x1F37C, prExtendedPictographic}, // E1.0 [1] (🍼) baby bottle + {0x1F37D, 0x1F37D, prExtendedPictographic}, // E0.7 [1] (🍽️) fork and knife with plate + {0x1F37E, 0x1F37F, prExtendedPictographic}, // E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn + {0x1F380, 0x1F393, prExtendedPictographic}, // E0.6 [20] (🎀..🎓) ribbon..graduation cap + {0x1F394, 0x1F395, prExtendedPictographic}, // E0.0 [2] (🎔..🎕) HEART WITH TIP ON THE LEFT..BOUQUET OF FLOWERS + {0x1F396, 0x1F397, prExtendedPictographic}, // E0.7 [2] (🎖️..🎗️) military medal..reminder ribbon + {0x1F398, 0x1F398, prExtendedPictographic}, // E0.0 [1] (🎘) MUSICAL KEYBOARD WITH JACKS + {0x1F399, 0x1F39B, prExtendedPictographic}, // E0.7 [3] (🎙️..🎛️) studio microphone..control knobs + {0x1F39C, 0x1F39D, prExtendedPictographic}, // E0.0 [2] (🎜..🎝) BEAMED ASCENDING MUSICAL NOTES..BEAMED DESCENDING MUSICAL NOTES + {0x1F39E, 0x1F39F, prExtendedPictographic}, // E0.7 [2] (🎞️..🎟️) film frames..admission tickets + {0x1F3A0, 0x1F3C4, prExtendedPictographic}, // E0.6 [37] (🎠..🏄) carousel horse..person surfing + {0x1F3C5, 0x1F3C5, prExtendedPictographic}, // E1.0 [1] (🏅) sports medal + {0x1F3C6, 0x1F3C6, prExtendedPictographic}, // E0.6 [1] (🏆) trophy + {0x1F3C7, 0x1F3C7, prExtendedPictographic}, // E1.0 [1] (🏇) horse racing + {0x1F3C8, 0x1F3C8, prExtendedPictographic}, // E0.6 [1] (🏈) american football + {0x1F3C9, 0x1F3C9, prExtendedPictographic}, // E1.0 [1] (🏉) rugby football + {0x1F3CA, 0x1F3CA, prExtendedPictographic}, // E0.6 [1] (🏊) person swimming + {0x1F3CB, 0x1F3CE, prExtendedPictographic}, // E0.7 [4] (🏋️..🏎️) person lifting weights..racing car + {0x1F3CF, 0x1F3D3, prExtendedPictographic}, // E1.0 [5] (🏏..🏓) cricket game..ping pong + {0x1F3D4, 0x1F3DF, prExtendedPictographic}, // E0.7 [12] (🏔️..🏟️) snow-capped mountain..stadium + {0x1F3E0, 0x1F3E3, prExtendedPictographic}, // E0.6 [4] (🏠..🏣) house..Japanese post office + {0x1F3E4, 0x1F3E4, prExtendedPictographic}, // E1.0 [1] (🏤) post office + {0x1F3E5, 0x1F3F0, prExtendedPictographic}, // E0.6 [12] (🏥..🏰) hospital..castle + {0x1F3F1, 0x1F3F2, prExtendedPictographic}, // E0.0 [2] (🏱..🏲) WHITE PENNANT..BLACK PENNANT + {0x1F3F3, 0x1F3F3, prExtendedPictographic}, // E0.7 [1] (🏳️) white flag + {0x1F3F4, 0x1F3F4, prExtendedPictographic}, // E1.0 [1] (🏴) black flag + {0x1F3F5, 0x1F3F5, prExtendedPictographic}, // E0.7 [1] (🏵️) rosette + {0x1F3F6, 0x1F3F6, prExtendedPictographic}, // E0.0 [1] (🏶) BLACK ROSETTE + {0x1F3F7, 0x1F3F7, prExtendedPictographic}, // E0.7 [1] (🏷️) label + {0x1F3F8, 0x1F3FA, prExtendedPictographic}, // E1.0 [3] (🏸..🏺) badminton..amphora + {0x1F3FB, 0x1F3FF, prExtend}, // Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 + {0x1F400, 0x1F407, prExtendedPictographic}, // E1.0 [8] (🐀..🐇) rat..rabbit + {0x1F408, 0x1F408, prExtendedPictographic}, // E0.7 [1] (🐈) cat + {0x1F409, 0x1F40B, prExtendedPictographic}, // E1.0 [3] (🐉..🐋) dragon..whale + {0x1F40C, 0x1F40E, prExtendedPictographic}, // E0.6 [3] (🐌..🐎) snail..horse + {0x1F40F, 0x1F410, prExtendedPictographic}, // E1.0 [2] (🐏..🐐) ram..goat + {0x1F411, 0x1F412, prExtendedPictographic}, // E0.6 [2] (🐑..🐒) ewe..monkey + {0x1F413, 0x1F413, prExtendedPictographic}, // E1.0 [1] (🐓) rooster + {0x1F414, 0x1F414, prExtendedPictographic}, // E0.6 [1] (🐔) chicken + {0x1F415, 0x1F415, prExtendedPictographic}, // E0.7 [1] (🐕) dog + {0x1F416, 0x1F416, prExtendedPictographic}, // E1.0 [1] (🐖) pig + {0x1F417, 0x1F429, prExtendedPictographic}, // E0.6 [19] (🐗..🐩) boar..poodle + {0x1F42A, 0x1F42A, prExtendedPictographic}, // E1.0 [1] (🐪) camel + {0x1F42B, 0x1F43E, prExtendedPictographic}, // E0.6 [20] (🐫..🐾) two-hump camel..paw prints + {0x1F43F, 0x1F43F, prExtendedPictographic}, // E0.7 [1] (🐿️) chipmunk + {0x1F440, 0x1F440, prExtendedPictographic}, // E0.6 [1] (👀) eyes + {0x1F441, 0x1F441, prExtendedPictographic}, // E0.7 [1] (👁️) eye + {0x1F442, 0x1F464, prExtendedPictographic}, // E0.6 [35] (👂..👤) ear..bust in silhouette + {0x1F465, 0x1F465, prExtendedPictographic}, // E1.0 [1] (👥) busts in silhouette + {0x1F466, 0x1F46B, prExtendedPictographic}, // E0.6 [6] (👦..👫) boy..woman and man holding hands + {0x1F46C, 0x1F46D, prExtendedPictographic}, // E1.0 [2] (👬..👭) men holding hands..women holding hands + {0x1F46E, 0x1F4AC, prExtendedPictographic}, // E0.6 [63] (👮..💬) police officer..speech balloon + {0x1F4AD, 0x1F4AD, prExtendedPictographic}, // E1.0 [1] (💭) thought balloon + {0x1F4AE, 0x1F4B5, prExtendedPictographic}, // E0.6 [8] (💮..💵) white flower..dollar banknote + {0x1F4B6, 0x1F4B7, prExtendedPictographic}, // E1.0 [2] (💶..💷) euro banknote..pound banknote + {0x1F4B8, 0x1F4EB, prExtendedPictographic}, // E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag + {0x1F4EC, 0x1F4ED, prExtendedPictographic}, // E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag + {0x1F4EE, 0x1F4EE, prExtendedPictographic}, // E0.6 [1] (📮) postbox + {0x1F4EF, 0x1F4EF, prExtendedPictographic}, // E1.0 [1] (📯) postal horn + {0x1F4F0, 0x1F4F4, prExtendedPictographic}, // E0.6 [5] (📰..📴) newspaper..mobile phone off + {0x1F4F5, 0x1F4F5, prExtendedPictographic}, // E1.0 [1] (📵) no mobile phones + {0x1F4F6, 0x1F4F7, prExtendedPictographic}, // E0.6 [2] (📶..📷) antenna bars..camera + {0x1F4F8, 0x1F4F8, prExtendedPictographic}, // E1.0 [1] (📸) camera with flash + {0x1F4F9, 0x1F4FC, prExtendedPictographic}, // E0.6 [4] (📹..📼) video camera..videocassette + {0x1F4FD, 0x1F4FD, prExtendedPictographic}, // E0.7 [1] (📽️) film projector + {0x1F4FE, 0x1F4FE, prExtendedPictographic}, // E0.0 [1] (📾) PORTABLE STEREO + {0x1F4FF, 0x1F502, prExtendedPictographic}, // E1.0 [4] (📿..🔂) prayer beads..repeat single button + {0x1F503, 0x1F503, prExtendedPictographic}, // E0.6 [1] (🔃) clockwise vertical arrows + {0x1F504, 0x1F507, prExtendedPictographic}, // E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker + {0x1F508, 0x1F508, prExtendedPictographic}, // E0.7 [1] (🔈) speaker low volume + {0x1F509, 0x1F509, prExtendedPictographic}, // E1.0 [1] (🔉) speaker medium volume + {0x1F50A, 0x1F514, prExtendedPictographic}, // E0.6 [11] (🔊..🔔) speaker high volume..bell + {0x1F515, 0x1F515, prExtendedPictographic}, // E1.0 [1] (🔕) bell with slash + {0x1F516, 0x1F52B, prExtendedPictographic}, // E0.6 [22] (🔖..🔫) bookmark..water pistol + {0x1F52C, 0x1F52D, prExtendedPictographic}, // E1.0 [2] (🔬..🔭) microscope..telescope + {0x1F52E, 0x1F53D, prExtendedPictographic}, // E0.6 [16] (🔮..🔽) crystal ball..downwards button + {0x1F546, 0x1F548, prExtendedPictographic}, // E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS + {0x1F549, 0x1F54A, prExtendedPictographic}, // E0.7 [2] (🕉️..🕊️) om..dove + {0x1F54B, 0x1F54E, prExtendedPictographic}, // E1.0 [4] (🕋..🕎) kaaba..menorah + {0x1F54F, 0x1F54F, prExtendedPictographic}, // E0.0 [1] (🕏) BOWL OF HYGIEIA + {0x1F550, 0x1F55B, prExtendedPictographic}, // E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock + {0x1F55C, 0x1F567, prExtendedPictographic}, // E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty + {0x1F568, 0x1F56E, prExtendedPictographic}, // E0.0 [7] (🕨..🕮) RIGHT SPEAKER..BOOK + {0x1F56F, 0x1F570, prExtendedPictographic}, // E0.7 [2] (🕯️..🕰️) candle..mantelpiece clock + {0x1F571, 0x1F572, prExtendedPictographic}, // E0.0 [2] (🕱..🕲) BLACK SKULL AND CROSSBONES..NO PIRACY + {0x1F573, 0x1F579, prExtendedPictographic}, // E0.7 [7] (🕳️..🕹️) hole..joystick + {0x1F57A, 0x1F57A, prExtendedPictographic}, // E3.0 [1] (🕺) man dancing + {0x1F57B, 0x1F586, prExtendedPictographic}, // E0.0 [12] (🕻..🖆) LEFT HAND TELEPHONE RECEIVER..PEN OVER STAMPED ENVELOPE + {0x1F587, 0x1F587, prExtendedPictographic}, // E0.7 [1] (🖇️) linked paperclips + {0x1F588, 0x1F589, prExtendedPictographic}, // E0.0 [2] (🖈..🖉) BLACK PUSHPIN..LOWER LEFT PENCIL + {0x1F58A, 0x1F58D, prExtendedPictographic}, // E0.7 [4] (🖊️..🖍️) pen..crayon + {0x1F58E, 0x1F58F, prExtendedPictographic}, // E0.0 [2] (🖎..🖏) LEFT WRITING HAND..TURNED OK HAND SIGN + {0x1F590, 0x1F590, prExtendedPictographic}, // E0.7 [1] (🖐️) hand with fingers splayed + {0x1F591, 0x1F594, prExtendedPictographic}, // E0.0 [4] (🖑..🖔) REVERSED RAISED HAND WITH FINGERS SPLAYED..REVERSED VICTORY HAND + {0x1F595, 0x1F596, prExtendedPictographic}, // E1.0 [2] (🖕..🖖) middle finger..vulcan salute + {0x1F597, 0x1F5A3, prExtendedPictographic}, // E0.0 [13] (🖗..🖣) WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX + {0x1F5A4, 0x1F5A4, prExtendedPictographic}, // E3.0 [1] (🖤) black heart + {0x1F5A5, 0x1F5A5, prExtendedPictographic}, // E0.7 [1] (🖥️) desktop computer + {0x1F5A6, 0x1F5A7, prExtendedPictographic}, // E0.0 [2] (🖦..🖧) KEYBOARD AND MOUSE..THREE NETWORKED COMPUTERS + {0x1F5A8, 0x1F5A8, prExtendedPictographic}, // E0.7 [1] (🖨️) printer + {0x1F5A9, 0x1F5B0, prExtendedPictographic}, // E0.0 [8] (🖩..🖰) POCKET CALCULATOR..TWO BUTTON MOUSE + {0x1F5B1, 0x1F5B2, prExtendedPictographic}, // E0.7 [2] (🖱️..🖲️) computer mouse..trackball + {0x1F5B3, 0x1F5BB, prExtendedPictographic}, // E0.0 [9] (🖳..🖻) OLD PERSONAL COMPUTER..DOCUMENT WITH PICTURE + {0x1F5BC, 0x1F5BC, prExtendedPictographic}, // E0.7 [1] (🖼️) framed picture + {0x1F5BD, 0x1F5C1, prExtendedPictographic}, // E0.0 [5] (🖽..🗁) FRAME WITH TILES..OPEN FOLDER + {0x1F5C2, 0x1F5C4, prExtendedPictographic}, // E0.7 [3] (🗂️..🗄️) card index dividers..file cabinet + {0x1F5C5, 0x1F5D0, prExtendedPictographic}, // E0.0 [12] (🗅..🗐) EMPTY NOTE..PAGES + {0x1F5D1, 0x1F5D3, prExtendedPictographic}, // E0.7 [3] (🗑️..🗓️) wastebasket..spiral calendar + {0x1F5D4, 0x1F5DB, prExtendedPictographic}, // E0.0 [8] (🗔..🗛) DESKTOP WINDOW..DECREASE FONT SIZE SYMBOL + {0x1F5DC, 0x1F5DE, prExtendedPictographic}, // E0.7 [3] (🗜️..🗞️) clamp..rolled-up newspaper + {0x1F5DF, 0x1F5E0, prExtendedPictographic}, // E0.0 [2] (🗟..🗠) PAGE WITH CIRCLED TEXT..STOCK CHART + {0x1F5E1, 0x1F5E1, prExtendedPictographic}, // E0.7 [1] (🗡️) dagger + {0x1F5E2, 0x1F5E2, prExtendedPictographic}, // E0.0 [1] (🗢) LIPS + {0x1F5E3, 0x1F5E3, prExtendedPictographic}, // E0.7 [1] (🗣️) speaking head + {0x1F5E4, 0x1F5E7, prExtendedPictographic}, // E0.0 [4] (🗤..🗧) THREE RAYS ABOVE..THREE RAYS RIGHT + {0x1F5E8, 0x1F5E8, prExtendedPictographic}, // E2.0 [1] (🗨️) left speech bubble + {0x1F5E9, 0x1F5EE, prExtendedPictographic}, // E0.0 [6] (🗩..🗮) RIGHT SPEECH BUBBLE..LEFT ANGER BUBBLE + {0x1F5EF, 0x1F5EF, prExtendedPictographic}, // E0.7 [1] (🗯️) right anger bubble + {0x1F5F0, 0x1F5F2, prExtendedPictographic}, // E0.0 [3] (🗰..🗲) MOOD BUBBLE..LIGHTNING MOOD + {0x1F5F3, 0x1F5F3, prExtendedPictographic}, // E0.7 [1] (🗳️) ballot box with ballot + {0x1F5F4, 0x1F5F9, prExtendedPictographic}, // E0.0 [6] (🗴..🗹) BALLOT SCRIPT X..BALLOT BOX WITH BOLD CHECK + {0x1F5FA, 0x1F5FA, prExtendedPictographic}, // E0.7 [1] (🗺️) world map + {0x1F5FB, 0x1F5FF, prExtendedPictographic}, // E0.6 [5] (🗻..🗿) mount fuji..moai + {0x1F600, 0x1F600, prExtendedPictographic}, // E1.0 [1] (😀) grinning face + {0x1F601, 0x1F606, prExtendedPictographic}, // E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face + {0x1F607, 0x1F608, prExtendedPictographic}, // E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns + {0x1F609, 0x1F60D, prExtendedPictographic}, // E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes + {0x1F60E, 0x1F60E, prExtendedPictographic}, // E1.0 [1] (😎) smiling face with sunglasses + {0x1F60F, 0x1F60F, prExtendedPictographic}, // E0.6 [1] (😏) smirking face + {0x1F610, 0x1F610, prExtendedPictographic}, // E0.7 [1] (😐) neutral face + {0x1F611, 0x1F611, prExtendedPictographic}, // E1.0 [1] (😑) expressionless face + {0x1F612, 0x1F614, prExtendedPictographic}, // E0.6 [3] (😒..😔) unamused face..pensive face + {0x1F615, 0x1F615, prExtendedPictographic}, // E1.0 [1] (😕) confused face + {0x1F616, 0x1F616, prExtendedPictographic}, // E0.6 [1] (😖) confounded face + {0x1F617, 0x1F617, prExtendedPictographic}, // E1.0 [1] (😗) kissing face + {0x1F618, 0x1F618, prExtendedPictographic}, // E0.6 [1] (😘) face blowing a kiss + {0x1F619, 0x1F619, prExtendedPictographic}, // E1.0 [1] (😙) kissing face with smiling eyes + {0x1F61A, 0x1F61A, prExtendedPictographic}, // E0.6 [1] (😚) kissing face with closed eyes + {0x1F61B, 0x1F61B, prExtendedPictographic}, // E1.0 [1] (😛) face with tongue + {0x1F61C, 0x1F61E, prExtendedPictographic}, // E0.6 [3] (😜..😞) winking face with tongue..disappointed face + {0x1F61F, 0x1F61F, prExtendedPictographic}, // E1.0 [1] (😟) worried face + {0x1F620, 0x1F625, prExtendedPictographic}, // E0.6 [6] (😠..😥) angry face..sad but relieved face + {0x1F626, 0x1F627, prExtendedPictographic}, // E1.0 [2] (😦..😧) frowning face with open mouth..anguished face + {0x1F628, 0x1F62B, prExtendedPictographic}, // E0.6 [4] (😨..😫) fearful face..tired face + {0x1F62C, 0x1F62C, prExtendedPictographic}, // E1.0 [1] (😬) grimacing face + {0x1F62D, 0x1F62D, prExtendedPictographic}, // E0.6 [1] (😭) loudly crying face + {0x1F62E, 0x1F62F, prExtendedPictographic}, // E1.0 [2] (😮..😯) face with open mouth..hushed face + {0x1F630, 0x1F633, prExtendedPictographic}, // E0.6 [4] (😰..😳) anxious face with sweat..flushed face + {0x1F634, 0x1F634, prExtendedPictographic}, // E1.0 [1] (😴) sleeping face + {0x1F635, 0x1F635, prExtendedPictographic}, // E0.6 [1] (😵) face with crossed-out eyes + {0x1F636, 0x1F636, prExtendedPictographic}, // E1.0 [1] (😶) face without mouth + {0x1F637, 0x1F640, prExtendedPictographic}, // E0.6 [10] (😷..🙀) face with medical mask..weary cat + {0x1F641, 0x1F644, prExtendedPictographic}, // E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes + {0x1F645, 0x1F64F, prExtendedPictographic}, // E0.6 [11] (🙅..🙏) person gesturing NO..folded hands + {0x1F680, 0x1F680, prExtendedPictographic}, // E0.6 [1] (🚀) rocket + {0x1F681, 0x1F682, prExtendedPictographic}, // E1.0 [2] (🚁..🚂) helicopter..locomotive + {0x1F683, 0x1F685, prExtendedPictographic}, // E0.6 [3] (🚃..🚅) railway car..bullet train + {0x1F686, 0x1F686, prExtendedPictographic}, // E1.0 [1] (🚆) train + {0x1F687, 0x1F687, prExtendedPictographic}, // E0.6 [1] (🚇) metro + {0x1F688, 0x1F688, prExtendedPictographic}, // E1.0 [1] (🚈) light rail + {0x1F689, 0x1F689, prExtendedPictographic}, // E0.6 [1] (🚉) station + {0x1F68A, 0x1F68B, prExtendedPictographic}, // E1.0 [2] (🚊..🚋) tram..tram car + {0x1F68C, 0x1F68C, prExtendedPictographic}, // E0.6 [1] (🚌) bus + {0x1F68D, 0x1F68D, prExtendedPictographic}, // E0.7 [1] (🚍) oncoming bus + {0x1F68E, 0x1F68E, prExtendedPictographic}, // E1.0 [1] (🚎) trolleybus + {0x1F68F, 0x1F68F, prExtendedPictographic}, // E0.6 [1] (🚏) bus stop + {0x1F690, 0x1F690, prExtendedPictographic}, // E1.0 [1] (🚐) minibus + {0x1F691, 0x1F693, prExtendedPictographic}, // E0.6 [3] (🚑..🚓) ambulance..police car + {0x1F694, 0x1F694, prExtendedPictographic}, // E0.7 [1] (🚔) oncoming police car + {0x1F695, 0x1F695, prExtendedPictographic}, // E0.6 [1] (🚕) taxi + {0x1F696, 0x1F696, prExtendedPictographic}, // E1.0 [1] (🚖) oncoming taxi + {0x1F697, 0x1F697, prExtendedPictographic}, // E0.6 [1] (🚗) automobile + {0x1F698, 0x1F698, prExtendedPictographic}, // E0.7 [1] (🚘) oncoming automobile + {0x1F699, 0x1F69A, prExtendedPictographic}, // E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck + {0x1F69B, 0x1F6A1, prExtendedPictographic}, // E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway + {0x1F6A2, 0x1F6A2, prExtendedPictographic}, // E0.6 [1] (🚢) ship + {0x1F6A3, 0x1F6A3, prExtendedPictographic}, // E1.0 [1] (🚣) person rowing boat + {0x1F6A4, 0x1F6A5, prExtendedPictographic}, // E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light + {0x1F6A6, 0x1F6A6, prExtendedPictographic}, // E1.0 [1] (🚦) vertical traffic light + {0x1F6A7, 0x1F6AD, prExtendedPictographic}, // E0.6 [7] (🚧..🚭) construction..no smoking + {0x1F6AE, 0x1F6B1, prExtendedPictographic}, // E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water + {0x1F6B2, 0x1F6B2, prExtendedPictographic}, // E0.6 [1] (🚲) bicycle + {0x1F6B3, 0x1F6B5, prExtendedPictographic}, // E1.0 [3] (🚳..🚵) no bicycles..person mountain biking + {0x1F6B6, 0x1F6B6, prExtendedPictographic}, // E0.6 [1] (🚶) person walking + {0x1F6B7, 0x1F6B8, prExtendedPictographic}, // E1.0 [2] (🚷..🚸) no pedestrians..children crossing + {0x1F6B9, 0x1F6BE, prExtendedPictographic}, // E0.6 [6] (🚹..🚾) men’s room..water closet + {0x1F6BF, 0x1F6BF, prExtendedPictographic}, // E1.0 [1] (🚿) shower + {0x1F6C0, 0x1F6C0, prExtendedPictographic}, // E0.6 [1] (🛀) person taking bath + {0x1F6C1, 0x1F6C5, prExtendedPictographic}, // E1.0 [5] (🛁..🛅) bathtub..left luggage + {0x1F6C6, 0x1F6CA, prExtendedPictographic}, // E0.0 [5] (🛆..🛊) TRIANGLE WITH ROUNDED CORNERS..GIRLS SYMBOL + {0x1F6CB, 0x1F6CB, prExtendedPictographic}, // E0.7 [1] (🛋️) couch and lamp + {0x1F6CC, 0x1F6CC, prExtendedPictographic}, // E1.0 [1] (🛌) person in bed + {0x1F6CD, 0x1F6CF, prExtendedPictographic}, // E0.7 [3] (🛍️..🛏️) shopping bags..bed + {0x1F6D0, 0x1F6D0, prExtendedPictographic}, // E1.0 [1] (🛐) place of worship + {0x1F6D1, 0x1F6D2, prExtendedPictographic}, // E3.0 [2] (🛑..🛒) stop sign..shopping cart + {0x1F6D3, 0x1F6D4, prExtendedPictographic}, // E0.0 [2] (🛓..🛔) STUPA..PAGODA + {0x1F6D5, 0x1F6D5, prExtendedPictographic}, // E12.0 [1] (🛕) hindu temple + {0x1F6D6, 0x1F6D7, prExtendedPictographic}, // E13.0 [2] (🛖..🛗) hut..elevator + {0x1F6D8, 0x1F6DB, prExtendedPictographic}, // E0.0 [4] (🛘..🛛) .. + {0x1F6DC, 0x1F6DC, prExtendedPictographic}, // E15.0 [1] (🛜) wireless + {0x1F6DD, 0x1F6DF, prExtendedPictographic}, // E14.0 [3] (🛝..🛟) playground slide..ring buoy + {0x1F6E0, 0x1F6E5, prExtendedPictographic}, // E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat + {0x1F6E6, 0x1F6E8, prExtendedPictographic}, // E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE + {0x1F6E9, 0x1F6E9, prExtendedPictographic}, // E0.7 [1] (🛩️) small airplane + {0x1F6EA, 0x1F6EA, prExtendedPictographic}, // E0.0 [1] (🛪) NORTHEAST-POINTING AIRPLANE + {0x1F6EB, 0x1F6EC, prExtendedPictographic}, // E1.0 [2] (🛫..🛬) airplane departure..airplane arrival + {0x1F6ED, 0x1F6EF, prExtendedPictographic}, // E0.0 [3] (🛭..🛯) .. + {0x1F6F0, 0x1F6F0, prExtendedPictographic}, // E0.7 [1] (🛰️) satellite + {0x1F6F1, 0x1F6F2, prExtendedPictographic}, // E0.0 [2] (🛱..🛲) ONCOMING FIRE ENGINE..DIESEL LOCOMOTIVE + {0x1F6F3, 0x1F6F3, prExtendedPictographic}, // E0.7 [1] (🛳️) passenger ship + {0x1F6F4, 0x1F6F6, prExtendedPictographic}, // E3.0 [3] (🛴..🛶) kick scooter..canoe + {0x1F6F7, 0x1F6F8, prExtendedPictographic}, // E5.0 [2] (🛷..🛸) sled..flying saucer + {0x1F6F9, 0x1F6F9, prExtendedPictographic}, // E11.0 [1] (🛹) skateboard + {0x1F6FA, 0x1F6FA, prExtendedPictographic}, // E12.0 [1] (🛺) auto rickshaw + {0x1F6FB, 0x1F6FC, prExtendedPictographic}, // E13.0 [2] (🛻..🛼) pickup truck..roller skate + {0x1F6FD, 0x1F6FF, prExtendedPictographic}, // E0.0 [3] (🛽..🛿) .. + {0x1F774, 0x1F77F, prExtendedPictographic}, // E0.0 [12] (🝴..🝿) LOT OF FORTUNE..ORCUS + {0x1F7D5, 0x1F7DF, prExtendedPictographic}, // E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE.. + {0x1F7E0, 0x1F7EB, prExtendedPictographic}, // E12.0 [12] (🟠..🟫) orange circle..brown square + {0x1F7EC, 0x1F7EF, prExtendedPictographic}, // E0.0 [4] (🟬..🟯) .. + {0x1F7F0, 0x1F7F0, prExtendedPictographic}, // E14.0 [1] (🟰) heavy equals sign + {0x1F7F1, 0x1F7FF, prExtendedPictographic}, // E0.0 [15] (🟱..🟿) .. + {0x1F80C, 0x1F80F, prExtendedPictographic}, // E0.0 [4] (🠌..🠏) .. + {0x1F848, 0x1F84F, prExtendedPictographic}, // E0.0 [8] (🡈..🡏) .. + {0x1F85A, 0x1F85F, prExtendedPictographic}, // E0.0 [6] (🡚..🡟) .. + {0x1F888, 0x1F88F, prExtendedPictographic}, // E0.0 [8] (🢈..🢏) .. + {0x1F8AE, 0x1F8FF, prExtendedPictographic}, // E0.0 [82] (🢮..🣿) .. + {0x1F90C, 0x1F90C, prExtendedPictographic}, // E13.0 [1] (🤌) pinched fingers + {0x1F90D, 0x1F90F, prExtendedPictographic}, // E12.0 [3] (🤍..🤏) white heart..pinching hand + {0x1F910, 0x1F918, prExtendedPictographic}, // E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns + {0x1F919, 0x1F91E, prExtendedPictographic}, // E3.0 [6] (🤙..🤞) call me hand..crossed fingers + {0x1F91F, 0x1F91F, prExtendedPictographic}, // E5.0 [1] (🤟) love-you gesture + {0x1F920, 0x1F927, prExtendedPictographic}, // E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face + {0x1F928, 0x1F92F, prExtendedPictographic}, // E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head + {0x1F930, 0x1F930, prExtendedPictographic}, // E3.0 [1] (🤰) pregnant woman + {0x1F931, 0x1F932, prExtendedPictographic}, // E5.0 [2] (🤱..🤲) breast-feeding..palms up together + {0x1F933, 0x1F93A, prExtendedPictographic}, // E3.0 [8] (🤳..🤺) selfie..person fencing + {0x1F93C, 0x1F93E, prExtendedPictographic}, // E3.0 [3] (🤼..🤾) people wrestling..person playing handball + {0x1F93F, 0x1F93F, prExtendedPictographic}, // E12.0 [1] (🤿) diving mask + {0x1F940, 0x1F945, prExtendedPictographic}, // E3.0 [6] (🥀..🥅) wilted flower..goal net + {0x1F947, 0x1F94B, prExtendedPictographic}, // E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform + {0x1F94C, 0x1F94C, prExtendedPictographic}, // E5.0 [1] (🥌) curling stone + {0x1F94D, 0x1F94F, prExtendedPictographic}, // E11.0 [3] (🥍..🥏) lacrosse..flying disc + {0x1F950, 0x1F95E, prExtendedPictographic}, // E3.0 [15] (🥐..🥞) croissant..pancakes + {0x1F95F, 0x1F96B, prExtendedPictographic}, // E5.0 [13] (🥟..🥫) dumpling..canned food + {0x1F96C, 0x1F970, prExtendedPictographic}, // E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts + {0x1F971, 0x1F971, prExtendedPictographic}, // E12.0 [1] (🥱) yawning face + {0x1F972, 0x1F972, prExtendedPictographic}, // E13.0 [1] (🥲) smiling face with tear + {0x1F973, 0x1F976, prExtendedPictographic}, // E11.0 [4] (🥳..🥶) partying face..cold face + {0x1F977, 0x1F978, prExtendedPictographic}, // E13.0 [2] (🥷..🥸) ninja..disguised face + {0x1F979, 0x1F979, prExtendedPictographic}, // E14.0 [1] (🥹) face holding back tears + {0x1F97A, 0x1F97A, prExtendedPictographic}, // E11.0 [1] (🥺) pleading face + {0x1F97B, 0x1F97B, prExtendedPictographic}, // E12.0 [1] (🥻) sari + {0x1F97C, 0x1F97F, prExtendedPictographic}, // E11.0 [4] (🥼..🥿) lab coat..flat shoe + {0x1F980, 0x1F984, prExtendedPictographic}, // E1.0 [5] (🦀..🦄) crab..unicorn + {0x1F985, 0x1F991, prExtendedPictographic}, // E3.0 [13] (🦅..🦑) eagle..squid + {0x1F992, 0x1F997, prExtendedPictographic}, // E5.0 [6] (🦒..🦗) giraffe..cricket + {0x1F998, 0x1F9A2, prExtendedPictographic}, // E11.0 [11] (🦘..🦢) kangaroo..swan + {0x1F9A3, 0x1F9A4, prExtendedPictographic}, // E13.0 [2] (🦣..🦤) mammoth..dodo + {0x1F9A5, 0x1F9AA, prExtendedPictographic}, // E12.0 [6] (🦥..🦪) sloth..oyster + {0x1F9AB, 0x1F9AD, prExtendedPictographic}, // E13.0 [3] (🦫..🦭) beaver..seal + {0x1F9AE, 0x1F9AF, prExtendedPictographic}, // E12.0 [2] (🦮..🦯) guide dog..white cane + {0x1F9B0, 0x1F9B9, prExtendedPictographic}, // E11.0 [10] (🦰..🦹) red hair..supervillain + {0x1F9BA, 0x1F9BF, prExtendedPictographic}, // E12.0 [6] (🦺..🦿) safety vest..mechanical leg + {0x1F9C0, 0x1F9C0, prExtendedPictographic}, // E1.0 [1] (🧀) cheese wedge + {0x1F9C1, 0x1F9C2, prExtendedPictographic}, // E11.0 [2] (🧁..🧂) cupcake..salt + {0x1F9C3, 0x1F9CA, prExtendedPictographic}, // E12.0 [8] (🧃..🧊) beverage box..ice + {0x1F9CB, 0x1F9CB, prExtendedPictographic}, // E13.0 [1] (🧋) bubble tea + {0x1F9CC, 0x1F9CC, prExtendedPictographic}, // E14.0 [1] (🧌) troll + {0x1F9CD, 0x1F9CF, prExtendedPictographic}, // E12.0 [3] (🧍..🧏) person standing..deaf person + {0x1F9D0, 0x1F9E6, prExtendedPictographic}, // E5.0 [23] (🧐..🧦) face with monocle..socks + {0x1F9E7, 0x1F9FF, prExtendedPictographic}, // E11.0 [25] (🧧..🧿) red envelope..nazar amulet + {0x1FA00, 0x1FA6F, prExtendedPictographic}, // E0.0 [112] (🨀..🩯) NEUTRAL CHESS KING.. + {0x1FA70, 0x1FA73, prExtendedPictographic}, // E12.0 [4] (🩰..🩳) ballet shoes..shorts + {0x1FA74, 0x1FA74, prExtendedPictographic}, // E13.0 [1] (🩴) thong sandal + {0x1FA75, 0x1FA77, prExtendedPictographic}, // E15.0 [3] (🩵..🩷) light blue heart..pink heart + {0x1FA78, 0x1FA7A, prExtendedPictographic}, // E12.0 [3] (🩸..🩺) drop of blood..stethoscope + {0x1FA7B, 0x1FA7C, prExtendedPictographic}, // E14.0 [2] (🩻..🩼) x-ray..crutch + {0x1FA7D, 0x1FA7F, prExtendedPictographic}, // E0.0 [3] (🩽..🩿) .. + {0x1FA80, 0x1FA82, prExtendedPictographic}, // E12.0 [3] (🪀..🪂) yo-yo..parachute + {0x1FA83, 0x1FA86, prExtendedPictographic}, // E13.0 [4] (🪃..🪆) boomerang..nesting dolls + {0x1FA87, 0x1FA88, prExtendedPictographic}, // E15.0 [2] (🪇..🪈) maracas..flute + {0x1FA89, 0x1FA8F, prExtendedPictographic}, // E0.0 [7] (🪉..🪏) .. + {0x1FA90, 0x1FA95, prExtendedPictographic}, // E12.0 [6] (🪐..🪕) ringed planet..banjo + {0x1FA96, 0x1FAA8, prExtendedPictographic}, // E13.0 [19] (🪖..🪨) military helmet..rock + {0x1FAA9, 0x1FAAC, prExtendedPictographic}, // E14.0 [4] (🪩..🪬) mirror ball..hamsa + {0x1FAAD, 0x1FAAF, prExtendedPictographic}, // E15.0 [3] (🪭..🪯) folding hand fan..khanda + {0x1FAB0, 0x1FAB6, prExtendedPictographic}, // E13.0 [7] (🪰..🪶) fly..feather + {0x1FAB7, 0x1FABA, prExtendedPictographic}, // E14.0 [4] (🪷..🪺) lotus..nest with eggs + {0x1FABB, 0x1FABD, prExtendedPictographic}, // E15.0 [3] (🪻..🪽) hyacinth..wing + {0x1FABE, 0x1FABE, prExtendedPictographic}, // E0.0 [1] (🪾) + {0x1FABF, 0x1FABF, prExtendedPictographic}, // E15.0 [1] (🪿) goose + {0x1FAC0, 0x1FAC2, prExtendedPictographic}, // E13.0 [3] (🫀..🫂) anatomical heart..people hugging + {0x1FAC3, 0x1FAC5, prExtendedPictographic}, // E14.0 [3] (🫃..🫅) pregnant man..person with crown + {0x1FAC6, 0x1FACD, prExtendedPictographic}, // E0.0 [8] (🫆..🫍) .. + {0x1FACE, 0x1FACF, prExtendedPictographic}, // E15.0 [2] (🫎..🫏) moose..donkey + {0x1FAD0, 0x1FAD6, prExtendedPictographic}, // E13.0 [7] (🫐..🫖) blueberries..teapot + {0x1FAD7, 0x1FAD9, prExtendedPictographic}, // E14.0 [3] (🫗..🫙) pouring liquid..jar + {0x1FADA, 0x1FADB, prExtendedPictographic}, // E15.0 [2] (🫚..🫛) ginger root..pea pod + {0x1FADC, 0x1FADF, prExtendedPictographic}, // E0.0 [4] (🫜..🫟) .. + {0x1FAE0, 0x1FAE7, prExtendedPictographic}, // E14.0 [8] (🫠..🫧) melting face..bubbles + {0x1FAE8, 0x1FAE8, prExtendedPictographic}, // E15.0 [1] (🫨) shaking face + {0x1FAE9, 0x1FAEF, prExtendedPictographic}, // E0.0 [7] (🫩..🫯) .. + {0x1FAF0, 0x1FAF6, prExtendedPictographic}, // E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands + {0x1FAF7, 0x1FAF8, prExtendedPictographic}, // E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + {0x1FAF9, 0x1FAFF, prExtendedPictographic}, // E0.0 [7] (🫹..🫿) .. + {0x1FC00, 0x1FFFD, prExtendedPictographic}, // E0.0[1022] (🰀..🿽) .. + {0xE0000, 0xE0000, prControl}, // Cn + {0xE0001, 0xE0001, prControl}, // Cf LANGUAGE TAG + {0xE0002, 0xE001F, prControl}, // Cn [30] .. + {0xE0020, 0xE007F, prExtend}, // Cf [96] TAG SPACE..CANCEL TAG + {0xE0080, 0xE00FF, prControl}, // Cn [128] .. + {0xE0100, 0xE01EF, prExtend}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + {0xE01F0, 0xE0FFF, prControl}, // Cn [3600] .. +} diff --git a/vendor/github.com/rivo/uniseg/graphemerules.go b/vendor/github.com/rivo/uniseg/graphemerules.go new file mode 100644 index 000000000..5d399d29c --- /dev/null +++ b/vendor/github.com/rivo/uniseg/graphemerules.go @@ -0,0 +1,176 @@ +package uniseg + +// The states of the grapheme cluster parser. +const ( + grAny = iota + grCR + grControlLF + grL + grLVV + grLVTT + grPrepend + grExtendedPictographic + grExtendedPictographicZWJ + grRIOdd + grRIEven +) + +// The grapheme cluster parser's breaking instructions. +const ( + grNoBoundary = iota + grBoundary +) + +// grTransitions implements the grapheme cluster parser's state transitions. +// Maps state and property to a new state, a breaking instruction, and rule +// number. The breaking instruction always refers to the boundary between the +// last and next code point. Returns negative values if no transition is found. +// +// This function is used as follows: +// +// 1. Find specific state + specific property. Stop if found. +// 2. Find specific state + any property. +// 3. Find any state + specific property. +// 4. If only (2) or (3) (but not both) was found, stop. +// 5. If both (2) and (3) were found, use state from (3) and breaking instruction +// from the transition with the lower rule number, prefer (3) if rule numbers +// are equal. Stop. +// 6. Assume grAny and grBoundary. +// +// Unicode version 15.0.0. +func grTransitions(state, prop int) (newState int, newProp int, boundary int) { + // It turns out that using a big switch statement is much faster than using + // a map. + + switch uint64(state) | uint64(prop)<<32 { + // GB5 + case grAny | prCR<<32: + return grCR, grBoundary, 50 + case grAny | prLF<<32: + return grControlLF, grBoundary, 50 + case grAny | prControl<<32: + return grControlLF, grBoundary, 50 + + // GB4 + case grCR | prAny<<32: + return grAny, grBoundary, 40 + case grControlLF | prAny<<32: + return grAny, grBoundary, 40 + + // GB3 + case grCR | prLF<<32: + return grControlLF, grNoBoundary, 30 + + // GB6 + case grAny | prL<<32: + return grL, grBoundary, 9990 + case grL | prL<<32: + return grL, grNoBoundary, 60 + case grL | prV<<32: + return grLVV, grNoBoundary, 60 + case grL | prLV<<32: + return grLVV, grNoBoundary, 60 + case grL | prLVT<<32: + return grLVTT, grNoBoundary, 60 + + // GB7 + case grAny | prLV<<32: + return grLVV, grBoundary, 9990 + case grAny | prV<<32: + return grLVV, grBoundary, 9990 + case grLVV | prV<<32: + return grLVV, grNoBoundary, 70 + case grLVV | prT<<32: + return grLVTT, grNoBoundary, 70 + + // GB8 + case grAny | prLVT<<32: + return grLVTT, grBoundary, 9990 + case grAny | prT<<32: + return grLVTT, grBoundary, 9990 + case grLVTT | prT<<32: + return grLVTT, grNoBoundary, 80 + + // GB9 + case grAny | prExtend<<32: + return grAny, grNoBoundary, 90 + case grAny | prZWJ<<32: + return grAny, grNoBoundary, 90 + + // GB9a + case grAny | prSpacingMark<<32: + return grAny, grNoBoundary, 91 + + // GB9b + case grAny | prPrepend<<32: + return grPrepend, grBoundary, 9990 + case grPrepend | prAny<<32: + return grAny, grNoBoundary, 92 + + // GB11 + case grAny | prExtendedPictographic<<32: + return grExtendedPictographic, grBoundary, 9990 + case grExtendedPictographic | prExtend<<32: + return grExtendedPictographic, grNoBoundary, 110 + case grExtendedPictographic | prZWJ<<32: + return grExtendedPictographicZWJ, grNoBoundary, 110 + case grExtendedPictographicZWJ | prExtendedPictographic<<32: + return grExtendedPictographic, grNoBoundary, 110 + + // GB12 / GB13 + case grAny | prRegionalIndicator<<32: + return grRIOdd, grBoundary, 9990 + case grRIOdd | prRegionalIndicator<<32: + return grRIEven, grNoBoundary, 120 + case grRIEven | prRegionalIndicator<<32: + return grRIOdd, grBoundary, 120 + default: + return -1, -1, -1 + } +} + +// transitionGraphemeState determines the new state of the grapheme cluster +// parser given the current state and the next code point. It also returns the +// code point's grapheme property (the value mapped by the [graphemeCodePoints] +// table) and whether a cluster boundary was detected. +func transitionGraphemeState(state int, r rune) (newState, prop int, boundary bool) { + // Determine the property of the next character. + prop = propertyGraphemes(r) + + // Find the applicable transition. + nextState, nextProp, _ := grTransitions(state, prop) + if nextState >= 0 { + // We have a specific transition. We'll use it. + return nextState, prop, nextProp == grBoundary + } + + // No specific transition found. Try the less specific ones. + anyPropState, anyPropProp, anyPropRule := grTransitions(state, prAny) + anyStateState, anyStateProp, anyStateRule := grTransitions(grAny, prop) + if anyPropState >= 0 && anyStateState >= 0 { + // Both apply. We'll use a mix (see comments for grTransitions). + newState = anyStateState + boundary = anyStateProp == grBoundary + if anyPropRule < anyStateRule { + boundary = anyPropProp == grBoundary + } + return + } + + if anyPropState >= 0 { + // We only have a specific state. + return anyPropState, prop, anyPropProp == grBoundary + // This branch will probably never be reached because okAnyState will + // always be true given the current transition map. But we keep it here + // for future modifications to the transition map where this may not be + // true anymore. + } + + if anyStateState >= 0 { + // We only have a specific property. + return anyStateState, prop, anyStateProp == grBoundary + } + + // No known transition. GB999: Any ÷ Any. + return grAny, prop, true +} diff --git a/vendor/github.com/rivo/uniseg/line.go b/vendor/github.com/rivo/uniseg/line.go new file mode 100644 index 000000000..7a46318d9 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/line.go @@ -0,0 +1,134 @@ +package uniseg + +import "unicode/utf8" + +// FirstLineSegment returns the prefix of the given byte slice after which a +// decision to break the string over to the next line can or must be made, +// according to the rules of [Unicode Standard Annex #14]. This is used to +// implement line breaking. +// +// Line breaking, also known as word wrapping, is the process of breaking a +// section of text into lines such that it will fit in the available width of a +// page, window or other display area. +// +// The returned "segment" may not be broken into smaller parts, unless no other +// breaking opportunities present themselves, in which case you may break by +// grapheme clusters (using the [FirstGraphemeCluster] function to determine the +// grapheme clusters). +// +// The "mustBreak" flag indicates whether you MUST break the line after the +// given segment (true), for example after newline characters, or you MAY break +// the line after the given segment (false). +// +// This function can be called continuously to extract all non-breaking sub-sets +// from a byte slice, as illustrated in the example below. +// +// If you don't know the current state, for example when calling the function +// for the first time, you must pass -1. For consecutive calls, pass the state +// and rest slice returned by the previous call. +// +// The "rest" slice is the sub-slice of the original byte slice "b" starting +// after the last byte of the identified line segment. If the length of the +// "rest" slice is 0, the entire byte slice "b" has been processed. The +// "segment" byte slice is the sub-slice of the input slice containing the +// identified line segment. +// +// Given an empty byte slice "b", the function returns nil values. +// +// Note that in accordance with [UAX #14 LB3], the final segment will end with +// "mustBreak" set to true. You can choose to ignore this by checking if the +// length of the "rest" slice is 0 and calling [HasTrailingLineBreak] or +// [HasTrailingLineBreakInString] on the last rune. +// +// Note also that this algorithm may break within grapheme clusters. This is +// addressed in Section 8.2 Example 6 of UAX #14. To avoid this, you can use +// the [Step] function instead. +// +// [Unicode Standard Annex #14]: https://www.unicode.org/reports/tr14/ +// [UAX #14 LB3]: https://www.unicode.org/reports/tr14/#Algorithm +func FirstLineSegment(b []byte, state int) (segment, rest []byte, mustBreak bool, newState int) { + // An empty byte slice returns nothing. + if len(b) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRune(b) + if len(b) <= length { // If we're already past the end, there is nothing else to parse. + return b, nil, true, lbAny // LB3. + } + + // If we don't know the state, determine it now. + if state < 0 { + state, _ = transitionLineBreakState(state, r, b[length:], "") + } + + // Transition until we find a boundary. + var boundary int + for { + r, l := utf8.DecodeRune(b[length:]) + state, boundary = transitionLineBreakState(state, r, b[length+l:], "") + + if boundary != LineDontBreak { + return b[:length], b[length:], boundary == LineMustBreak, state + } + + length += l + if len(b) <= length { + return b, nil, true, lbAny // LB3 + } + } +} + +// FirstLineSegmentInString is like [FirstLineSegment] but its input and outputs +// are strings. +func FirstLineSegmentInString(str string, state int) (segment, rest string, mustBreak bool, newState int) { + // An empty byte slice returns nothing. + if len(str) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRuneInString(str) + if len(str) <= length { // If we're already past the end, there is nothing else to parse. + return str, "", true, lbAny // LB3. + } + + // If we don't know the state, determine it now. + if state < 0 { + state, _ = transitionLineBreakState(state, r, nil, str[length:]) + } + + // Transition until we find a boundary. + var boundary int + for { + r, l := utf8.DecodeRuneInString(str[length:]) + state, boundary = transitionLineBreakState(state, r, nil, str[length+l:]) + + if boundary != LineDontBreak { + return str[:length], str[length:], boundary == LineMustBreak, state + } + + length += l + if len(str) <= length { + return str, "", true, lbAny // LB3. + } + } +} + +// HasTrailingLineBreak returns true if the last rune in the given byte slice is +// one of the hard line break code points defined in LB4 and LB5 of [UAX #14]. +// +// [UAX #14]: https://www.unicode.org/reports/tr14/#Algorithm +func HasTrailingLineBreak(b []byte) bool { + r, _ := utf8.DecodeLastRune(b) + property, _ := propertyLineBreak(r) + return property == prBK || property == prCR || property == prLF || property == prNL +} + +// HasTrailingLineBreakInString is like [HasTrailingLineBreak] but for a string. +func HasTrailingLineBreakInString(str string) bool { + r, _ := utf8.DecodeLastRuneInString(str) + property, _ := propertyLineBreak(r) + return property == prBK || property == prCR || property == prLF || property == prNL +} diff --git a/vendor/github.com/rivo/uniseg/lineproperties.go b/vendor/github.com/rivo/uniseg/lineproperties.go new file mode 100644 index 000000000..ac7fac4c0 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/lineproperties.go @@ -0,0 +1,3554 @@ +// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// lineBreakCodePoints are taken from +// https://www.unicode.org/Public/15.0.0/ucd/LineBreak.txt +// and +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt +// ("Extended_Pictographic" only) +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var lineBreakCodePoints = [][4]int{ + {0x0000, 0x0008, prCM, gcCc}, // [9] .. + {0x0009, 0x0009, prBA, gcCc}, // + {0x000A, 0x000A, prLF, gcCc}, // + {0x000B, 0x000C, prBK, gcCc}, // [2] .. + {0x000D, 0x000D, prCR, gcCc}, // + {0x000E, 0x001F, prCM, gcCc}, // [18] .. + {0x0020, 0x0020, prSP, gcZs}, // SPACE + {0x0021, 0x0021, prEX, gcPo}, // EXCLAMATION MARK + {0x0022, 0x0022, prQU, gcPo}, // QUOTATION MARK + {0x0023, 0x0023, prAL, gcPo}, // NUMBER SIGN + {0x0024, 0x0024, prPR, gcSc}, // DOLLAR SIGN + {0x0025, 0x0025, prPO, gcPo}, // PERCENT SIGN + {0x0026, 0x0026, prAL, gcPo}, // AMPERSAND + {0x0027, 0x0027, prQU, gcPo}, // APOSTROPHE + {0x0028, 0x0028, prOP, gcPs}, // LEFT PARENTHESIS + {0x0029, 0x0029, prCP, gcPe}, // RIGHT PARENTHESIS + {0x002A, 0x002A, prAL, gcPo}, // ASTERISK + {0x002B, 0x002B, prPR, gcSm}, // PLUS SIGN + {0x002C, 0x002C, prIS, gcPo}, // COMMA + {0x002D, 0x002D, prHY, gcPd}, // HYPHEN-MINUS + {0x002E, 0x002E, prIS, gcPo}, // FULL STOP + {0x002F, 0x002F, prSY, gcPo}, // SOLIDUS + {0x0030, 0x0039, prNU, gcNd}, // [10] DIGIT ZERO..DIGIT NINE + {0x003A, 0x003B, prIS, gcPo}, // [2] COLON..SEMICOLON + {0x003C, 0x003E, prAL, gcSm}, // [3] LESS-THAN SIGN..GREATER-THAN SIGN + {0x003F, 0x003F, prEX, gcPo}, // QUESTION MARK + {0x0040, 0x0040, prAL, gcPo}, // COMMERCIAL AT + {0x0041, 0x005A, prAL, gcLu}, // [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z + {0x005B, 0x005B, prOP, gcPs}, // LEFT SQUARE BRACKET + {0x005C, 0x005C, prPR, gcPo}, // REVERSE SOLIDUS + {0x005D, 0x005D, prCP, gcPe}, // RIGHT SQUARE BRACKET + {0x005E, 0x005E, prAL, gcSk}, // CIRCUMFLEX ACCENT + {0x005F, 0x005F, prAL, gcPc}, // LOW LINE + {0x0060, 0x0060, prAL, gcSk}, // GRAVE ACCENT + {0x0061, 0x007A, prAL, gcLl}, // [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z + {0x007B, 0x007B, prOP, gcPs}, // LEFT CURLY BRACKET + {0x007C, 0x007C, prBA, gcSm}, // VERTICAL LINE + {0x007D, 0x007D, prCL, gcPe}, // RIGHT CURLY BRACKET + {0x007E, 0x007E, prAL, gcSm}, // TILDE + {0x007F, 0x007F, prCM, gcCc}, // + {0x0080, 0x0084, prCM, gcCc}, // [5] .. + {0x0085, 0x0085, prNL, gcCc}, // + {0x0086, 0x009F, prCM, gcCc}, // [26] .. + {0x00A0, 0x00A0, prGL, gcZs}, // NO-BREAK SPACE + {0x00A1, 0x00A1, prOP, gcPo}, // INVERTED EXCLAMATION MARK + {0x00A2, 0x00A2, prPO, gcSc}, // CENT SIGN + {0x00A3, 0x00A5, prPR, gcSc}, // [3] POUND SIGN..YEN SIGN + {0x00A6, 0x00A6, prAL, gcSo}, // BROKEN BAR + {0x00A7, 0x00A7, prAI, gcPo}, // SECTION SIGN + {0x00A8, 0x00A8, prAI, gcSk}, // DIAERESIS + {0x00A9, 0x00A9, prAL, gcSo}, // COPYRIGHT SIGN + {0x00AA, 0x00AA, prAI, gcLo}, // FEMININE ORDINAL INDICATOR + {0x00AB, 0x00AB, prQU, gcPi}, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + {0x00AC, 0x00AC, prAL, gcSm}, // NOT SIGN + {0x00AD, 0x00AD, prBA, gcCf}, // SOFT HYPHEN + {0x00AE, 0x00AE, prAL, gcSo}, // REGISTERED SIGN + {0x00AF, 0x00AF, prAL, gcSk}, // MACRON + {0x00B0, 0x00B0, prPO, gcSo}, // DEGREE SIGN + {0x00B1, 0x00B1, prPR, gcSm}, // PLUS-MINUS SIGN + {0x00B2, 0x00B3, prAI, gcNo}, // [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE + {0x00B4, 0x00B4, prBB, gcSk}, // ACUTE ACCENT + {0x00B5, 0x00B5, prAL, gcLl}, // MICRO SIGN + {0x00B6, 0x00B7, prAI, gcPo}, // [2] PILCROW SIGN..MIDDLE DOT + {0x00B8, 0x00B8, prAI, gcSk}, // CEDILLA + {0x00B9, 0x00B9, prAI, gcNo}, // SUPERSCRIPT ONE + {0x00BA, 0x00BA, prAI, gcLo}, // MASCULINE ORDINAL INDICATOR + {0x00BB, 0x00BB, prQU, gcPf}, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + {0x00BC, 0x00BE, prAI, gcNo}, // [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS + {0x00BF, 0x00BF, prOP, gcPo}, // INVERTED QUESTION MARK + {0x00C0, 0x00D6, prAL, gcLu}, // [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS + {0x00D7, 0x00D7, prAI, gcSm}, // MULTIPLICATION SIGN + {0x00D8, 0x00F6, prAL, gcLC}, // [31] LATIN CAPITAL LETTER O WITH STROKE..LATIN SMALL LETTER O WITH DIAERESIS + {0x00F7, 0x00F7, prAI, gcSm}, // DIVISION SIGN + {0x00F8, 0x00FF, prAL, gcLl}, // [8] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER Y WITH DIAERESIS + {0x0100, 0x017F, prAL, gcLC}, // [128] LATIN CAPITAL LETTER A WITH MACRON..LATIN SMALL LETTER LONG S + {0x0180, 0x01BA, prAL, gcLC}, // [59] LATIN SMALL LETTER B WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL + {0x01BB, 0x01BB, prAL, gcLo}, // LATIN LETTER TWO WITH STROKE + {0x01BC, 0x01BF, prAL, gcLC}, // [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN + {0x01C0, 0x01C3, prAL, gcLo}, // [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK + {0x01C4, 0x024F, prAL, gcLC}, // [140] LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER Y WITH STROKE + {0x0250, 0x0293, prAL, gcLl}, // [68] LATIN SMALL LETTER TURNED A..LATIN SMALL LETTER EZH WITH CURL + {0x0294, 0x0294, prAL, gcLo}, // LATIN LETTER GLOTTAL STOP + {0x0295, 0x02AF, prAL, gcLl}, // [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL + {0x02B0, 0x02C1, prAL, gcLm}, // [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP + {0x02C2, 0x02C5, prAL, gcSk}, // [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD + {0x02C6, 0x02C6, prAL, gcLm}, // MODIFIER LETTER CIRCUMFLEX ACCENT + {0x02C7, 0x02C7, prAI, gcLm}, // CARON + {0x02C8, 0x02C8, prBB, gcLm}, // MODIFIER LETTER VERTICAL LINE + {0x02C9, 0x02CB, prAI, gcLm}, // [3] MODIFIER LETTER MACRON..MODIFIER LETTER GRAVE ACCENT + {0x02CC, 0x02CC, prBB, gcLm}, // MODIFIER LETTER LOW VERTICAL LINE + {0x02CD, 0x02CD, prAI, gcLm}, // MODIFIER LETTER LOW MACRON + {0x02CE, 0x02CF, prAL, gcLm}, // [2] MODIFIER LETTER LOW GRAVE ACCENT..MODIFIER LETTER LOW ACUTE ACCENT + {0x02D0, 0x02D0, prAI, gcLm}, // MODIFIER LETTER TRIANGULAR COLON + {0x02D1, 0x02D1, prAL, gcLm}, // MODIFIER LETTER HALF TRIANGULAR COLON + {0x02D2, 0x02D7, prAL, gcSk}, // [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN + {0x02D8, 0x02DB, prAI, gcSk}, // [4] BREVE..OGONEK + {0x02DC, 0x02DC, prAL, gcSk}, // SMALL TILDE + {0x02DD, 0x02DD, prAI, gcSk}, // DOUBLE ACUTE ACCENT + {0x02DE, 0x02DE, prAL, gcSk}, // MODIFIER LETTER RHOTIC HOOK + {0x02DF, 0x02DF, prBB, gcSk}, // MODIFIER LETTER CROSS ACCENT + {0x02E0, 0x02E4, prAL, gcLm}, // [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP + {0x02E5, 0x02EB, prAL, gcSk}, // [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK + {0x02EC, 0x02EC, prAL, gcLm}, // MODIFIER LETTER VOICING + {0x02ED, 0x02ED, prAL, gcSk}, // MODIFIER LETTER UNASPIRATED + {0x02EE, 0x02EE, prAL, gcLm}, // MODIFIER LETTER DOUBLE APOSTROPHE + {0x02EF, 0x02FF, prAL, gcSk}, // [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW + {0x0300, 0x034E, prCM, gcMn}, // [79] COMBINING GRAVE ACCENT..COMBINING UPWARDS ARROW BELOW + {0x034F, 0x034F, prGL, gcMn}, // COMBINING GRAPHEME JOINER + {0x0350, 0x035B, prCM, gcMn}, // [12] COMBINING RIGHT ARROWHEAD ABOVE..COMBINING ZIGZAG ABOVE + {0x035C, 0x0362, prGL, gcMn}, // [7] COMBINING DOUBLE BREVE BELOW..COMBINING DOUBLE RIGHTWARDS ARROW BELOW + {0x0363, 0x036F, prCM, gcMn}, // [13] COMBINING LATIN SMALL LETTER A..COMBINING LATIN SMALL LETTER X + {0x0370, 0x0373, prAL, gcLC}, // [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI + {0x0374, 0x0374, prAL, gcLm}, // GREEK NUMERAL SIGN + {0x0375, 0x0375, prAL, gcSk}, // GREEK LOWER NUMERAL SIGN + {0x0376, 0x0377, prAL, gcLC}, // [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA + {0x037A, 0x037A, prAL, gcLm}, // GREEK YPOGEGRAMMENI + {0x037B, 0x037D, prAL, gcLl}, // [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL + {0x037E, 0x037E, prIS, gcPo}, // GREEK QUESTION MARK + {0x037F, 0x037F, prAL, gcLu}, // GREEK CAPITAL LETTER YOT + {0x0384, 0x0385, prAL, gcSk}, // [2] GREEK TONOS..GREEK DIALYTIKA TONOS + {0x0386, 0x0386, prAL, gcLu}, // GREEK CAPITAL LETTER ALPHA WITH TONOS + {0x0387, 0x0387, prAL, gcPo}, // GREEK ANO TELEIA + {0x0388, 0x038A, prAL, gcLu}, // [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS + {0x038C, 0x038C, prAL, gcLu}, // GREEK CAPITAL LETTER OMICRON WITH TONOS + {0x038E, 0x03A1, prAL, gcLC}, // [20] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER RHO + {0x03A3, 0x03F5, prAL, gcLC}, // [83] GREEK CAPITAL LETTER SIGMA..GREEK LUNATE EPSILON SYMBOL + {0x03F6, 0x03F6, prAL, gcSm}, // GREEK REVERSED LUNATE EPSILON SYMBOL + {0x03F7, 0x03FF, prAL, gcLC}, // [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL + {0x0400, 0x0481, prAL, gcLC}, // [130] CYRILLIC CAPITAL LETTER IE WITH GRAVE..CYRILLIC SMALL LETTER KOPPA + {0x0482, 0x0482, prAL, gcSo}, // CYRILLIC THOUSANDS SIGN + {0x0483, 0x0487, prCM, gcMn}, // [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE + {0x0488, 0x0489, prCM, gcMe}, // [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN + {0x048A, 0x04FF, prAL, gcLC}, // [118] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER HA WITH STROKE + {0x0500, 0x052F, prAL, gcLC}, // [48] CYRILLIC CAPITAL LETTER KOMI DE..CYRILLIC SMALL LETTER EL WITH DESCENDER + {0x0531, 0x0556, prAL, gcLu}, // [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH + {0x0559, 0x0559, prAL, gcLm}, // ARMENIAN MODIFIER LETTER LEFT HALF RING + {0x055A, 0x055F, prAL, gcPo}, // [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK + {0x0560, 0x0588, prAL, gcLl}, // [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE + {0x0589, 0x0589, prIS, gcPo}, // ARMENIAN FULL STOP + {0x058A, 0x058A, prBA, gcPd}, // ARMENIAN HYPHEN + {0x058D, 0x058E, prAL, gcSo}, // [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN + {0x058F, 0x058F, prPR, gcSc}, // ARMENIAN DRAM SIGN + {0x0591, 0x05BD, prCM, gcMn}, // [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG + {0x05BE, 0x05BE, prBA, gcPd}, // HEBREW PUNCTUATION MAQAF + {0x05BF, 0x05BF, prCM, gcMn}, // HEBREW POINT RAFE + {0x05C0, 0x05C0, prAL, gcPo}, // HEBREW PUNCTUATION PASEQ + {0x05C1, 0x05C2, prCM, gcMn}, // [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT + {0x05C3, 0x05C3, prAL, gcPo}, // HEBREW PUNCTUATION SOF PASUQ + {0x05C4, 0x05C5, prCM, gcMn}, // [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT + {0x05C6, 0x05C6, prEX, gcPo}, // HEBREW PUNCTUATION NUN HAFUKHA + {0x05C7, 0x05C7, prCM, gcMn}, // HEBREW POINT QAMATS QATAN + {0x05D0, 0x05EA, prHL, gcLo}, // [27] HEBREW LETTER ALEF..HEBREW LETTER TAV + {0x05EF, 0x05F2, prHL, gcLo}, // [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD + {0x05F3, 0x05F4, prAL, gcPo}, // [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM + {0x0600, 0x0605, prAL, gcCf}, // [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE + {0x0606, 0x0608, prAL, gcSm}, // [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY + {0x0609, 0x060A, prPO, gcPo}, // [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN + {0x060B, 0x060B, prPO, gcSc}, // AFGHANI SIGN + {0x060C, 0x060D, prIS, gcPo}, // [2] ARABIC COMMA..ARABIC DATE SEPARATOR + {0x060E, 0x060F, prAL, gcSo}, // [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA + {0x0610, 0x061A, prCM, gcMn}, // [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA + {0x061B, 0x061B, prEX, gcPo}, // ARABIC SEMICOLON + {0x061C, 0x061C, prCM, gcCf}, // ARABIC LETTER MARK + {0x061D, 0x061F, prEX, gcPo}, // [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK + {0x0620, 0x063F, prAL, gcLo}, // [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE + {0x0640, 0x0640, prAL, gcLm}, // ARABIC TATWEEL + {0x0641, 0x064A, prAL, gcLo}, // [10] ARABIC LETTER FEH..ARABIC LETTER YEH + {0x064B, 0x065F, prCM, gcMn}, // [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW + {0x0660, 0x0669, prNU, gcNd}, // [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE + {0x066A, 0x066A, prPO, gcPo}, // ARABIC PERCENT SIGN + {0x066B, 0x066C, prNU, gcPo}, // [2] ARABIC DECIMAL SEPARATOR..ARABIC THOUSANDS SEPARATOR + {0x066D, 0x066D, prAL, gcPo}, // ARABIC FIVE POINTED STAR + {0x066E, 0x066F, prAL, gcLo}, // [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF + {0x0670, 0x0670, prCM, gcMn}, // ARABIC LETTER SUPERSCRIPT ALEF + {0x0671, 0x06D3, prAL, gcLo}, // [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE + {0x06D4, 0x06D4, prEX, gcPo}, // ARABIC FULL STOP + {0x06D5, 0x06D5, prAL, gcLo}, // ARABIC LETTER AE + {0x06D6, 0x06DC, prCM, gcMn}, // [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN + {0x06DD, 0x06DD, prAL, gcCf}, // ARABIC END OF AYAH + {0x06DE, 0x06DE, prAL, gcSo}, // ARABIC START OF RUB EL HIZB + {0x06DF, 0x06E4, prCM, gcMn}, // [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA + {0x06E5, 0x06E6, prAL, gcLm}, // [2] ARABIC SMALL WAW..ARABIC SMALL YEH + {0x06E7, 0x06E8, prCM, gcMn}, // [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON + {0x06E9, 0x06E9, prAL, gcSo}, // ARABIC PLACE OF SAJDAH + {0x06EA, 0x06ED, prCM, gcMn}, // [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM + {0x06EE, 0x06EF, prAL, gcLo}, // [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V + {0x06F0, 0x06F9, prNU, gcNd}, // [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE + {0x06FA, 0x06FC, prAL, gcLo}, // [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW + {0x06FD, 0x06FE, prAL, gcSo}, // [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN + {0x06FF, 0x06FF, prAL, gcLo}, // ARABIC LETTER HEH WITH INVERTED V + {0x0700, 0x070D, prAL, gcPo}, // [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS + {0x070F, 0x070F, prAL, gcCf}, // SYRIAC ABBREVIATION MARK + {0x0710, 0x0710, prAL, gcLo}, // SYRIAC LETTER ALAPH + {0x0711, 0x0711, prCM, gcMn}, // SYRIAC LETTER SUPERSCRIPT ALAPH + {0x0712, 0x072F, prAL, gcLo}, // [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH + {0x0730, 0x074A, prCM, gcMn}, // [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH + {0x074D, 0x074F, prAL, gcLo}, // [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE + {0x0750, 0x077F, prAL, gcLo}, // [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE + {0x0780, 0x07A5, prAL, gcLo}, // [38] THAANA LETTER HAA..THAANA LETTER WAAVU + {0x07A6, 0x07B0, prCM, gcMn}, // [11] THAANA ABAFILI..THAANA SUKUN + {0x07B1, 0x07B1, prAL, gcLo}, // THAANA LETTER NAA + {0x07C0, 0x07C9, prNU, gcNd}, // [10] NKO DIGIT ZERO..NKO DIGIT NINE + {0x07CA, 0x07EA, prAL, gcLo}, // [33] NKO LETTER A..NKO LETTER JONA RA + {0x07EB, 0x07F3, prCM, gcMn}, // [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE + {0x07F4, 0x07F5, prAL, gcLm}, // [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE + {0x07F6, 0x07F6, prAL, gcSo}, // NKO SYMBOL OO DENNEN + {0x07F7, 0x07F7, prAL, gcPo}, // NKO SYMBOL GBAKURUNEN + {0x07F8, 0x07F8, prIS, gcPo}, // NKO COMMA + {0x07F9, 0x07F9, prEX, gcPo}, // NKO EXCLAMATION MARK + {0x07FA, 0x07FA, prAL, gcLm}, // NKO LAJANYALAN + {0x07FD, 0x07FD, prCM, gcMn}, // NKO DANTAYALAN + {0x07FE, 0x07FF, prPR, gcSc}, // [2] NKO DOROME SIGN..NKO TAMAN SIGN + {0x0800, 0x0815, prAL, gcLo}, // [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF + {0x0816, 0x0819, prCM, gcMn}, // [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH + {0x081A, 0x081A, prAL, gcLm}, // SAMARITAN MODIFIER LETTER EPENTHETIC YUT + {0x081B, 0x0823, prCM, gcMn}, // [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A + {0x0824, 0x0824, prAL, gcLm}, // SAMARITAN MODIFIER LETTER SHORT A + {0x0825, 0x0827, prCM, gcMn}, // [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U + {0x0828, 0x0828, prAL, gcLm}, // SAMARITAN MODIFIER LETTER I + {0x0829, 0x082D, prCM, gcMn}, // [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA + {0x0830, 0x083E, prAL, gcPo}, // [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU + {0x0840, 0x0858, prAL, gcLo}, // [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN + {0x0859, 0x085B, prCM, gcMn}, // [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK + {0x085E, 0x085E, prAL, gcPo}, // MANDAIC PUNCTUATION + {0x0860, 0x086A, prAL, gcLo}, // [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA + {0x0870, 0x0887, prAL, gcLo}, // [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT + {0x0888, 0x0888, prAL, gcSk}, // ARABIC RAISED ROUND DOT + {0x0889, 0x088E, prAL, gcLo}, // [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL + {0x0890, 0x0891, prAL, gcCf}, // [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE + {0x0898, 0x089F, prCM, gcMn}, // [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA + {0x08A0, 0x08C8, prAL, gcLo}, // [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF + {0x08C9, 0x08C9, prAL, gcLm}, // ARABIC SMALL FARSI YEH + {0x08CA, 0x08E1, prCM, gcMn}, // [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA + {0x08E2, 0x08E2, prAL, gcCf}, // ARABIC DISPUTED END OF AYAH + {0x08E3, 0x08FF, prCM, gcMn}, // [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA + {0x0900, 0x0902, prCM, gcMn}, // [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA + {0x0903, 0x0903, prCM, gcMc}, // DEVANAGARI SIGN VISARGA + {0x0904, 0x0939, prAL, gcLo}, // [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA + {0x093A, 0x093A, prCM, gcMn}, // DEVANAGARI VOWEL SIGN OE + {0x093B, 0x093B, prCM, gcMc}, // DEVANAGARI VOWEL SIGN OOE + {0x093C, 0x093C, prCM, gcMn}, // DEVANAGARI SIGN NUKTA + {0x093D, 0x093D, prAL, gcLo}, // DEVANAGARI SIGN AVAGRAHA + {0x093E, 0x0940, prCM, gcMc}, // [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II + {0x0941, 0x0948, prCM, gcMn}, // [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI + {0x0949, 0x094C, prCM, gcMc}, // [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU + {0x094D, 0x094D, prCM, gcMn}, // DEVANAGARI SIGN VIRAMA + {0x094E, 0x094F, prCM, gcMc}, // [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW + {0x0950, 0x0950, prAL, gcLo}, // DEVANAGARI OM + {0x0951, 0x0957, prCM, gcMn}, // [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE + {0x0958, 0x0961, prAL, gcLo}, // [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL + {0x0962, 0x0963, prCM, gcMn}, // [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL + {0x0964, 0x0965, prBA, gcPo}, // [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA + {0x0966, 0x096F, prNU, gcNd}, // [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE + {0x0970, 0x0970, prAL, gcPo}, // DEVANAGARI ABBREVIATION SIGN + {0x0971, 0x0971, prAL, gcLm}, // DEVANAGARI SIGN HIGH SPACING DOT + {0x0972, 0x097F, prAL, gcLo}, // [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA + {0x0980, 0x0980, prAL, gcLo}, // BENGALI ANJI + {0x0981, 0x0981, prCM, gcMn}, // BENGALI SIGN CANDRABINDU + {0x0982, 0x0983, prCM, gcMc}, // [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA + {0x0985, 0x098C, prAL, gcLo}, // [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L + {0x098F, 0x0990, prAL, gcLo}, // [2] BENGALI LETTER E..BENGALI LETTER AI + {0x0993, 0x09A8, prAL, gcLo}, // [22] BENGALI LETTER O..BENGALI LETTER NA + {0x09AA, 0x09B0, prAL, gcLo}, // [7] BENGALI LETTER PA..BENGALI LETTER RA + {0x09B2, 0x09B2, prAL, gcLo}, // BENGALI LETTER LA + {0x09B6, 0x09B9, prAL, gcLo}, // [4] BENGALI LETTER SHA..BENGALI LETTER HA + {0x09BC, 0x09BC, prCM, gcMn}, // BENGALI SIGN NUKTA + {0x09BD, 0x09BD, prAL, gcLo}, // BENGALI SIGN AVAGRAHA + {0x09BE, 0x09C0, prCM, gcMc}, // [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II + {0x09C1, 0x09C4, prCM, gcMn}, // [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR + {0x09C7, 0x09C8, prCM, gcMc}, // [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI + {0x09CB, 0x09CC, prCM, gcMc}, // [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU + {0x09CD, 0x09CD, prCM, gcMn}, // BENGALI SIGN VIRAMA + {0x09CE, 0x09CE, prAL, gcLo}, // BENGALI LETTER KHANDA TA + {0x09D7, 0x09D7, prCM, gcMc}, // BENGALI AU LENGTH MARK + {0x09DC, 0x09DD, prAL, gcLo}, // [2] BENGALI LETTER RRA..BENGALI LETTER RHA + {0x09DF, 0x09E1, prAL, gcLo}, // [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL + {0x09E2, 0x09E3, prCM, gcMn}, // [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL + {0x09E6, 0x09EF, prNU, gcNd}, // [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE + {0x09F0, 0x09F1, prAL, gcLo}, // [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL + {0x09F2, 0x09F3, prPO, gcSc}, // [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN + {0x09F4, 0x09F8, prAL, gcNo}, // [5] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR + {0x09F9, 0x09F9, prPO, gcNo}, // BENGALI CURRENCY DENOMINATOR SIXTEEN + {0x09FA, 0x09FA, prAL, gcSo}, // BENGALI ISSHAR + {0x09FB, 0x09FB, prPR, gcSc}, // BENGALI GANDA MARK + {0x09FC, 0x09FC, prAL, gcLo}, // BENGALI LETTER VEDIC ANUSVARA + {0x09FD, 0x09FD, prAL, gcPo}, // BENGALI ABBREVIATION SIGN + {0x09FE, 0x09FE, prCM, gcMn}, // BENGALI SANDHI MARK + {0x0A01, 0x0A02, prCM, gcMn}, // [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI + {0x0A03, 0x0A03, prCM, gcMc}, // GURMUKHI SIGN VISARGA + {0x0A05, 0x0A0A, prAL, gcLo}, // [6] GURMUKHI LETTER A..GURMUKHI LETTER UU + {0x0A0F, 0x0A10, prAL, gcLo}, // [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI + {0x0A13, 0x0A28, prAL, gcLo}, // [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA + {0x0A2A, 0x0A30, prAL, gcLo}, // [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA + {0x0A32, 0x0A33, prAL, gcLo}, // [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA + {0x0A35, 0x0A36, prAL, gcLo}, // [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA + {0x0A38, 0x0A39, prAL, gcLo}, // [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA + {0x0A3C, 0x0A3C, prCM, gcMn}, // GURMUKHI SIGN NUKTA + {0x0A3E, 0x0A40, prCM, gcMc}, // [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II + {0x0A41, 0x0A42, prCM, gcMn}, // [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU + {0x0A47, 0x0A48, prCM, gcMn}, // [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI + {0x0A4B, 0x0A4D, prCM, gcMn}, // [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA + {0x0A51, 0x0A51, prCM, gcMn}, // GURMUKHI SIGN UDAAT + {0x0A59, 0x0A5C, prAL, gcLo}, // [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA + {0x0A5E, 0x0A5E, prAL, gcLo}, // GURMUKHI LETTER FA + {0x0A66, 0x0A6F, prNU, gcNd}, // [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE + {0x0A70, 0x0A71, prCM, gcMn}, // [2] GURMUKHI TIPPI..GURMUKHI ADDAK + {0x0A72, 0x0A74, prAL, gcLo}, // [3] GURMUKHI IRI..GURMUKHI EK ONKAR + {0x0A75, 0x0A75, prCM, gcMn}, // GURMUKHI SIGN YAKASH + {0x0A76, 0x0A76, prAL, gcPo}, // GURMUKHI ABBREVIATION SIGN + {0x0A81, 0x0A82, prCM, gcMn}, // [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA + {0x0A83, 0x0A83, prCM, gcMc}, // GUJARATI SIGN VISARGA + {0x0A85, 0x0A8D, prAL, gcLo}, // [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E + {0x0A8F, 0x0A91, prAL, gcLo}, // [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O + {0x0A93, 0x0AA8, prAL, gcLo}, // [22] GUJARATI LETTER O..GUJARATI LETTER NA + {0x0AAA, 0x0AB0, prAL, gcLo}, // [7] GUJARATI LETTER PA..GUJARATI LETTER RA + {0x0AB2, 0x0AB3, prAL, gcLo}, // [2] GUJARATI LETTER LA..GUJARATI LETTER LLA + {0x0AB5, 0x0AB9, prAL, gcLo}, // [5] GUJARATI LETTER VA..GUJARATI LETTER HA + {0x0ABC, 0x0ABC, prCM, gcMn}, // GUJARATI SIGN NUKTA + {0x0ABD, 0x0ABD, prAL, gcLo}, // GUJARATI SIGN AVAGRAHA + {0x0ABE, 0x0AC0, prCM, gcMc}, // [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II + {0x0AC1, 0x0AC5, prCM, gcMn}, // [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E + {0x0AC7, 0x0AC8, prCM, gcMn}, // [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI + {0x0AC9, 0x0AC9, prCM, gcMc}, // GUJARATI VOWEL SIGN CANDRA O + {0x0ACB, 0x0ACC, prCM, gcMc}, // [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU + {0x0ACD, 0x0ACD, prCM, gcMn}, // GUJARATI SIGN VIRAMA + {0x0AD0, 0x0AD0, prAL, gcLo}, // GUJARATI OM + {0x0AE0, 0x0AE1, prAL, gcLo}, // [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL + {0x0AE2, 0x0AE3, prCM, gcMn}, // [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL + {0x0AE6, 0x0AEF, prNU, gcNd}, // [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE + {0x0AF0, 0x0AF0, prAL, gcPo}, // GUJARATI ABBREVIATION SIGN + {0x0AF1, 0x0AF1, prPR, gcSc}, // GUJARATI RUPEE SIGN + {0x0AF9, 0x0AF9, prAL, gcLo}, // GUJARATI LETTER ZHA + {0x0AFA, 0x0AFF, prCM, gcMn}, // [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE + {0x0B01, 0x0B01, prCM, gcMn}, // ORIYA SIGN CANDRABINDU + {0x0B02, 0x0B03, prCM, gcMc}, // [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA + {0x0B05, 0x0B0C, prAL, gcLo}, // [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L + {0x0B0F, 0x0B10, prAL, gcLo}, // [2] ORIYA LETTER E..ORIYA LETTER AI + {0x0B13, 0x0B28, prAL, gcLo}, // [22] ORIYA LETTER O..ORIYA LETTER NA + {0x0B2A, 0x0B30, prAL, gcLo}, // [7] ORIYA LETTER PA..ORIYA LETTER RA + {0x0B32, 0x0B33, prAL, gcLo}, // [2] ORIYA LETTER LA..ORIYA LETTER LLA + {0x0B35, 0x0B39, prAL, gcLo}, // [5] ORIYA LETTER VA..ORIYA LETTER HA + {0x0B3C, 0x0B3C, prCM, gcMn}, // ORIYA SIGN NUKTA + {0x0B3D, 0x0B3D, prAL, gcLo}, // ORIYA SIGN AVAGRAHA + {0x0B3E, 0x0B3E, prCM, gcMc}, // ORIYA VOWEL SIGN AA + {0x0B3F, 0x0B3F, prCM, gcMn}, // ORIYA VOWEL SIGN I + {0x0B40, 0x0B40, prCM, gcMc}, // ORIYA VOWEL SIGN II + {0x0B41, 0x0B44, prCM, gcMn}, // [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR + {0x0B47, 0x0B48, prCM, gcMc}, // [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI + {0x0B4B, 0x0B4C, prCM, gcMc}, // [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU + {0x0B4D, 0x0B4D, prCM, gcMn}, // ORIYA SIGN VIRAMA + {0x0B55, 0x0B56, prCM, gcMn}, // [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK + {0x0B57, 0x0B57, prCM, gcMc}, // ORIYA AU LENGTH MARK + {0x0B5C, 0x0B5D, prAL, gcLo}, // [2] ORIYA LETTER RRA..ORIYA LETTER RHA + {0x0B5F, 0x0B61, prAL, gcLo}, // [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL + {0x0B62, 0x0B63, prCM, gcMn}, // [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL + {0x0B66, 0x0B6F, prNU, gcNd}, // [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE + {0x0B70, 0x0B70, prAL, gcSo}, // ORIYA ISSHAR + {0x0B71, 0x0B71, prAL, gcLo}, // ORIYA LETTER WA + {0x0B72, 0x0B77, prAL, gcNo}, // [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS + {0x0B82, 0x0B82, prCM, gcMn}, // TAMIL SIGN ANUSVARA + {0x0B83, 0x0B83, prAL, gcLo}, // TAMIL SIGN VISARGA + {0x0B85, 0x0B8A, prAL, gcLo}, // [6] TAMIL LETTER A..TAMIL LETTER UU + {0x0B8E, 0x0B90, prAL, gcLo}, // [3] TAMIL LETTER E..TAMIL LETTER AI + {0x0B92, 0x0B95, prAL, gcLo}, // [4] TAMIL LETTER O..TAMIL LETTER KA + {0x0B99, 0x0B9A, prAL, gcLo}, // [2] TAMIL LETTER NGA..TAMIL LETTER CA + {0x0B9C, 0x0B9C, prAL, gcLo}, // TAMIL LETTER JA + {0x0B9E, 0x0B9F, prAL, gcLo}, // [2] TAMIL LETTER NYA..TAMIL LETTER TTA + {0x0BA3, 0x0BA4, prAL, gcLo}, // [2] TAMIL LETTER NNA..TAMIL LETTER TA + {0x0BA8, 0x0BAA, prAL, gcLo}, // [3] TAMIL LETTER NA..TAMIL LETTER PA + {0x0BAE, 0x0BB9, prAL, gcLo}, // [12] TAMIL LETTER MA..TAMIL LETTER HA + {0x0BBE, 0x0BBF, prCM, gcMc}, // [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I + {0x0BC0, 0x0BC0, prCM, gcMn}, // TAMIL VOWEL SIGN II + {0x0BC1, 0x0BC2, prCM, gcMc}, // [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU + {0x0BC6, 0x0BC8, prCM, gcMc}, // [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI + {0x0BCA, 0x0BCC, prCM, gcMc}, // [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU + {0x0BCD, 0x0BCD, prCM, gcMn}, // TAMIL SIGN VIRAMA + {0x0BD0, 0x0BD0, prAL, gcLo}, // TAMIL OM + {0x0BD7, 0x0BD7, prCM, gcMc}, // TAMIL AU LENGTH MARK + {0x0BE6, 0x0BEF, prNU, gcNd}, // [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE + {0x0BF0, 0x0BF2, prAL, gcNo}, // [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND + {0x0BF3, 0x0BF8, prAL, gcSo}, // [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN + {0x0BF9, 0x0BF9, prPR, gcSc}, // TAMIL RUPEE SIGN + {0x0BFA, 0x0BFA, prAL, gcSo}, // TAMIL NUMBER SIGN + {0x0C00, 0x0C00, prCM, gcMn}, // TELUGU SIGN COMBINING CANDRABINDU ABOVE + {0x0C01, 0x0C03, prCM, gcMc}, // [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA + {0x0C04, 0x0C04, prCM, gcMn}, // TELUGU SIGN COMBINING ANUSVARA ABOVE + {0x0C05, 0x0C0C, prAL, gcLo}, // [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L + {0x0C0E, 0x0C10, prAL, gcLo}, // [3] TELUGU LETTER E..TELUGU LETTER AI + {0x0C12, 0x0C28, prAL, gcLo}, // [23] TELUGU LETTER O..TELUGU LETTER NA + {0x0C2A, 0x0C39, prAL, gcLo}, // [16] TELUGU LETTER PA..TELUGU LETTER HA + {0x0C3C, 0x0C3C, prCM, gcMn}, // TELUGU SIGN NUKTA + {0x0C3D, 0x0C3D, prAL, gcLo}, // TELUGU SIGN AVAGRAHA + {0x0C3E, 0x0C40, prCM, gcMn}, // [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II + {0x0C41, 0x0C44, prCM, gcMc}, // [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR + {0x0C46, 0x0C48, prCM, gcMn}, // [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI + {0x0C4A, 0x0C4D, prCM, gcMn}, // [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA + {0x0C55, 0x0C56, prCM, gcMn}, // [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK + {0x0C58, 0x0C5A, prAL, gcLo}, // [3] TELUGU LETTER TSA..TELUGU LETTER RRRA + {0x0C5D, 0x0C5D, prAL, gcLo}, // TELUGU LETTER NAKAARA POLLU + {0x0C60, 0x0C61, prAL, gcLo}, // [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL + {0x0C62, 0x0C63, prCM, gcMn}, // [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL + {0x0C66, 0x0C6F, prNU, gcNd}, // [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE + {0x0C77, 0x0C77, prBB, gcPo}, // TELUGU SIGN SIDDHAM + {0x0C78, 0x0C7E, prAL, gcNo}, // [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR + {0x0C7F, 0x0C7F, prAL, gcSo}, // TELUGU SIGN TUUMU + {0x0C80, 0x0C80, prAL, gcLo}, // KANNADA SIGN SPACING CANDRABINDU + {0x0C81, 0x0C81, prCM, gcMn}, // KANNADA SIGN CANDRABINDU + {0x0C82, 0x0C83, prCM, gcMc}, // [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA + {0x0C84, 0x0C84, prBB, gcPo}, // KANNADA SIGN SIDDHAM + {0x0C85, 0x0C8C, prAL, gcLo}, // [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L + {0x0C8E, 0x0C90, prAL, gcLo}, // [3] KANNADA LETTER E..KANNADA LETTER AI + {0x0C92, 0x0CA8, prAL, gcLo}, // [23] KANNADA LETTER O..KANNADA LETTER NA + {0x0CAA, 0x0CB3, prAL, gcLo}, // [10] KANNADA LETTER PA..KANNADA LETTER LLA + {0x0CB5, 0x0CB9, prAL, gcLo}, // [5] KANNADA LETTER VA..KANNADA LETTER HA + {0x0CBC, 0x0CBC, prCM, gcMn}, // KANNADA SIGN NUKTA + {0x0CBD, 0x0CBD, prAL, gcLo}, // KANNADA SIGN AVAGRAHA + {0x0CBE, 0x0CBE, prCM, gcMc}, // KANNADA VOWEL SIGN AA + {0x0CBF, 0x0CBF, prCM, gcMn}, // KANNADA VOWEL SIGN I + {0x0CC0, 0x0CC4, prCM, gcMc}, // [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR + {0x0CC6, 0x0CC6, prCM, gcMn}, // KANNADA VOWEL SIGN E + {0x0CC7, 0x0CC8, prCM, gcMc}, // [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI + {0x0CCA, 0x0CCB, prCM, gcMc}, // [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO + {0x0CCC, 0x0CCD, prCM, gcMn}, // [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA + {0x0CD5, 0x0CD6, prCM, gcMc}, // [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK + {0x0CDD, 0x0CDE, prAL, gcLo}, // [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA + {0x0CE0, 0x0CE1, prAL, gcLo}, // [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL + {0x0CE2, 0x0CE3, prCM, gcMn}, // [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0CE6, 0x0CEF, prNU, gcNd}, // [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE + {0x0CF1, 0x0CF2, prAL, gcLo}, // [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prCM, gcMc}, // KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT + {0x0D00, 0x0D01, prCM, gcMn}, // [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU + {0x0D02, 0x0D03, prCM, gcMc}, // [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA + {0x0D04, 0x0D0C, prAL, gcLo}, // [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L + {0x0D0E, 0x0D10, prAL, gcLo}, // [3] MALAYALAM LETTER E..MALAYALAM LETTER AI + {0x0D12, 0x0D3A, prAL, gcLo}, // [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA + {0x0D3B, 0x0D3C, prCM, gcMn}, // [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA + {0x0D3D, 0x0D3D, prAL, gcLo}, // MALAYALAM SIGN AVAGRAHA + {0x0D3E, 0x0D40, prCM, gcMc}, // [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II + {0x0D41, 0x0D44, prCM, gcMn}, // [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR + {0x0D46, 0x0D48, prCM, gcMc}, // [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI + {0x0D4A, 0x0D4C, prCM, gcMc}, // [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU + {0x0D4D, 0x0D4D, prCM, gcMn}, // MALAYALAM SIGN VIRAMA + {0x0D4E, 0x0D4E, prAL, gcLo}, // MALAYALAM LETTER DOT REPH + {0x0D4F, 0x0D4F, prAL, gcSo}, // MALAYALAM SIGN PARA + {0x0D54, 0x0D56, prAL, gcLo}, // [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL + {0x0D57, 0x0D57, prCM, gcMc}, // MALAYALAM AU LENGTH MARK + {0x0D58, 0x0D5E, prAL, gcNo}, // [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH + {0x0D5F, 0x0D61, prAL, gcLo}, // [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL + {0x0D62, 0x0D63, prCM, gcMn}, // [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL + {0x0D66, 0x0D6F, prNU, gcNd}, // [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE + {0x0D70, 0x0D78, prAL, gcNo}, // [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS + {0x0D79, 0x0D79, prPO, gcSo}, // MALAYALAM DATE MARK + {0x0D7A, 0x0D7F, prAL, gcLo}, // [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K + {0x0D81, 0x0D81, prCM, gcMn}, // SINHALA SIGN CANDRABINDU + {0x0D82, 0x0D83, prCM, gcMc}, // [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA + {0x0D85, 0x0D96, prAL, gcLo}, // [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA + {0x0D9A, 0x0DB1, prAL, gcLo}, // [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA + {0x0DB3, 0x0DBB, prAL, gcLo}, // [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA + {0x0DBD, 0x0DBD, prAL, gcLo}, // SINHALA LETTER DANTAJA LAYANNA + {0x0DC0, 0x0DC6, prAL, gcLo}, // [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA + {0x0DCA, 0x0DCA, prCM, gcMn}, // SINHALA SIGN AL-LAKUNA + {0x0DCF, 0x0DD1, prCM, gcMc}, // [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA + {0x0DD2, 0x0DD4, prCM, gcMn}, // [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA + {0x0DD6, 0x0DD6, prCM, gcMn}, // SINHALA VOWEL SIGN DIGA PAA-PILLA + {0x0DD8, 0x0DDF, prCM, gcMc}, // [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA + {0x0DE6, 0x0DEF, prNU, gcNd}, // [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE + {0x0DF2, 0x0DF3, prCM, gcMc}, // [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA + {0x0DF4, 0x0DF4, prAL, gcPo}, // SINHALA PUNCTUATION KUNDDALIYA + {0x0E01, 0x0E30, prSA, gcLo}, // [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A + {0x0E31, 0x0E31, prSA, gcMn}, // THAI CHARACTER MAI HAN-AKAT + {0x0E32, 0x0E33, prSA, gcLo}, // [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM + {0x0E34, 0x0E3A, prSA, gcMn}, // [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU + {0x0E3F, 0x0E3F, prPR, gcSc}, // THAI CURRENCY SYMBOL BAHT + {0x0E40, 0x0E45, prSA, gcLo}, // [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO + {0x0E46, 0x0E46, prSA, gcLm}, // THAI CHARACTER MAIYAMOK + {0x0E47, 0x0E4E, prSA, gcMn}, // [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN + {0x0E4F, 0x0E4F, prAL, gcPo}, // THAI CHARACTER FONGMAN + {0x0E50, 0x0E59, prNU, gcNd}, // [10] THAI DIGIT ZERO..THAI DIGIT NINE + {0x0E5A, 0x0E5B, prBA, gcPo}, // [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT + {0x0E81, 0x0E82, prSA, gcLo}, // [2] LAO LETTER KO..LAO LETTER KHO SUNG + {0x0E84, 0x0E84, prSA, gcLo}, // LAO LETTER KHO TAM + {0x0E86, 0x0E8A, prSA, gcLo}, // [5] LAO LETTER PALI GHA..LAO LETTER SO TAM + {0x0E8C, 0x0EA3, prSA, gcLo}, // [24] LAO LETTER PALI JHA..LAO LETTER LO LING + {0x0EA5, 0x0EA5, prSA, gcLo}, // LAO LETTER LO LOOT + {0x0EA7, 0x0EB0, prSA, gcLo}, // [10] LAO LETTER WO..LAO VOWEL SIGN A + {0x0EB1, 0x0EB1, prSA, gcMn}, // LAO VOWEL SIGN MAI KAN + {0x0EB2, 0x0EB3, prSA, gcLo}, // [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM + {0x0EB4, 0x0EBC, prSA, gcMn}, // [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO + {0x0EBD, 0x0EBD, prSA, gcLo}, // LAO SEMIVOWEL SIGN NYO + {0x0EC0, 0x0EC4, prSA, gcLo}, // [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI + {0x0EC6, 0x0EC6, prSA, gcLm}, // LAO KO LA + {0x0EC8, 0x0ECE, prSA, gcMn}, // [7] LAO TONE MAI EK..LAO YAMAKKAN + {0x0ED0, 0x0ED9, prNU, gcNd}, // [10] LAO DIGIT ZERO..LAO DIGIT NINE + {0x0EDC, 0x0EDF, prSA, gcLo}, // [4] LAO HO NO..LAO LETTER KHMU NYO + {0x0F00, 0x0F00, prAL, gcLo}, // TIBETAN SYLLABLE OM + {0x0F01, 0x0F03, prBB, gcSo}, // [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA + {0x0F04, 0x0F04, prBB, gcPo}, // TIBETAN MARK INITIAL YIG MGO MDUN MA + {0x0F05, 0x0F05, prAL, gcPo}, // TIBETAN MARK CLOSING YIG MGO SGAB MA + {0x0F06, 0x0F07, prBB, gcPo}, // [2] TIBETAN MARK CARET YIG MGO PHUR SHAD MA..TIBETAN MARK YIG MGO TSHEG SHAD MA + {0x0F08, 0x0F08, prGL, gcPo}, // TIBETAN MARK SBRUL SHAD + {0x0F09, 0x0F0A, prBB, gcPo}, // [2] TIBETAN MARK BSKUR YIG MGO..TIBETAN MARK BKA- SHOG YIG MGO + {0x0F0B, 0x0F0B, prBA, gcPo}, // TIBETAN MARK INTERSYLLABIC TSHEG + {0x0F0C, 0x0F0C, prGL, gcPo}, // TIBETAN MARK DELIMITER TSHEG BSTAR + {0x0F0D, 0x0F11, prEX, gcPo}, // [5] TIBETAN MARK SHAD..TIBETAN MARK RIN CHEN SPUNGS SHAD + {0x0F12, 0x0F12, prGL, gcPo}, // TIBETAN MARK RGYA GRAM SHAD + {0x0F13, 0x0F13, prAL, gcSo}, // TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN + {0x0F14, 0x0F14, prEX, gcPo}, // TIBETAN MARK GTER TSHEG + {0x0F15, 0x0F17, prAL, gcSo}, // [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS + {0x0F18, 0x0F19, prCM, gcMn}, // [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS + {0x0F1A, 0x0F1F, prAL, gcSo}, // [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG + {0x0F20, 0x0F29, prNU, gcNd}, // [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE + {0x0F2A, 0x0F33, prAL, gcNo}, // [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO + {0x0F34, 0x0F34, prBA, gcSo}, // TIBETAN MARK BSDUS RTAGS + {0x0F35, 0x0F35, prCM, gcMn}, // TIBETAN MARK NGAS BZUNG NYI ZLA + {0x0F36, 0x0F36, prAL, gcSo}, // TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN + {0x0F37, 0x0F37, prCM, gcMn}, // TIBETAN MARK NGAS BZUNG SGOR RTAGS + {0x0F38, 0x0F38, prAL, gcSo}, // TIBETAN MARK CHE MGO + {0x0F39, 0x0F39, prCM, gcMn}, // TIBETAN MARK TSA -PHRU + {0x0F3A, 0x0F3A, prOP, gcPs}, // TIBETAN MARK GUG RTAGS GYON + {0x0F3B, 0x0F3B, prCL, gcPe}, // TIBETAN MARK GUG RTAGS GYAS + {0x0F3C, 0x0F3C, prOP, gcPs}, // TIBETAN MARK ANG KHANG GYON + {0x0F3D, 0x0F3D, prCL, gcPe}, // TIBETAN MARK ANG KHANG GYAS + {0x0F3E, 0x0F3F, prCM, gcMc}, // [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES + {0x0F40, 0x0F47, prAL, gcLo}, // [8] TIBETAN LETTER KA..TIBETAN LETTER JA + {0x0F49, 0x0F6C, prAL, gcLo}, // [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA + {0x0F71, 0x0F7E, prCM, gcMn}, // [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO + {0x0F7F, 0x0F7F, prBA, gcMc}, // TIBETAN SIGN RNAM BCAD + {0x0F80, 0x0F84, prCM, gcMn}, // [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA + {0x0F85, 0x0F85, prBA, gcPo}, // TIBETAN MARK PALUTA + {0x0F86, 0x0F87, prCM, gcMn}, // [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS + {0x0F88, 0x0F8C, prAL, gcLo}, // [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN + {0x0F8D, 0x0F97, prCM, gcMn}, // [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA + {0x0F99, 0x0FBC, prCM, gcMn}, // [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA + {0x0FBE, 0x0FBF, prBA, gcSo}, // [2] TIBETAN KU RU KHA..TIBETAN KU RU KHA BZHI MIG CAN + {0x0FC0, 0x0FC5, prAL, gcSo}, // [6] TIBETAN CANTILLATION SIGN HEAVY BEAT..TIBETAN SYMBOL RDO RJE + {0x0FC6, 0x0FC6, prCM, gcMn}, // TIBETAN SYMBOL PADMA GDAN + {0x0FC7, 0x0FCC, prAL, gcSo}, // [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL + {0x0FCE, 0x0FCF, prAL, gcSo}, // [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM + {0x0FD0, 0x0FD1, prBB, gcPo}, // [2] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK MNYAM YIG GI MGO RGYAN + {0x0FD2, 0x0FD2, prBA, gcPo}, // TIBETAN MARK NYIS TSHEG + {0x0FD3, 0x0FD3, prBB, gcPo}, // TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA + {0x0FD4, 0x0FD4, prAL, gcPo}, // TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA + {0x0FD5, 0x0FD8, prAL, gcSo}, // [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS + {0x0FD9, 0x0FDA, prGL, gcPo}, // [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS + {0x1000, 0x102A, prSA, gcLo}, // [43] MYANMAR LETTER KA..MYANMAR LETTER AU + {0x102B, 0x102C, prSA, gcMc}, // [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA + {0x102D, 0x1030, prSA, gcMn}, // [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU + {0x1031, 0x1031, prSA, gcMc}, // MYANMAR VOWEL SIGN E + {0x1032, 0x1037, prSA, gcMn}, // [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW + {0x1038, 0x1038, prSA, gcMc}, // MYANMAR SIGN VISARGA + {0x1039, 0x103A, prSA, gcMn}, // [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT + {0x103B, 0x103C, prSA, gcMc}, // [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA + {0x103D, 0x103E, prSA, gcMn}, // [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA + {0x103F, 0x103F, prSA, gcLo}, // MYANMAR LETTER GREAT SA + {0x1040, 0x1049, prNU, gcNd}, // [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE + {0x104A, 0x104B, prBA, gcPo}, // [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION + {0x104C, 0x104F, prAL, gcPo}, // [4] MYANMAR SYMBOL LOCATIVE..MYANMAR SYMBOL GENITIVE + {0x1050, 0x1055, prSA, gcLo}, // [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL + {0x1056, 0x1057, prSA, gcMc}, // [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR + {0x1058, 0x1059, prSA, gcMn}, // [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL + {0x105A, 0x105D, prSA, gcLo}, // [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE + {0x105E, 0x1060, prSA, gcMn}, // [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA + {0x1061, 0x1061, prSA, gcLo}, // MYANMAR LETTER SGAW KAREN SHA + {0x1062, 0x1064, prSA, gcMc}, // [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO + {0x1065, 0x1066, prSA, gcLo}, // [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA + {0x1067, 0x106D, prSA, gcMc}, // [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 + {0x106E, 0x1070, prSA, gcLo}, // [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA + {0x1071, 0x1074, prSA, gcMn}, // [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE + {0x1075, 0x1081, prSA, gcLo}, // [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA + {0x1082, 0x1082, prSA, gcMn}, // MYANMAR CONSONANT SIGN SHAN MEDIAL WA + {0x1083, 0x1084, prSA, gcMc}, // [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E + {0x1085, 0x1086, prSA, gcMn}, // [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y + {0x1087, 0x108C, prSA, gcMc}, // [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 + {0x108D, 0x108D, prSA, gcMn}, // MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE + {0x108E, 0x108E, prSA, gcLo}, // MYANMAR LETTER RUMAI PALAUNG FA + {0x108F, 0x108F, prSA, gcMc}, // MYANMAR SIGN RUMAI PALAUNG TONE-5 + {0x1090, 0x1099, prNU, gcNd}, // [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE + {0x109A, 0x109C, prSA, gcMc}, // [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A + {0x109D, 0x109D, prSA, gcMn}, // MYANMAR VOWEL SIGN AITON AI + {0x109E, 0x109F, prSA, gcSo}, // [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION + {0x10A0, 0x10C5, prAL, gcLu}, // [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE + {0x10C7, 0x10C7, prAL, gcLu}, // GEORGIAN CAPITAL LETTER YN + {0x10CD, 0x10CD, prAL, gcLu}, // GEORGIAN CAPITAL LETTER AEN + {0x10D0, 0x10FA, prAL, gcLl}, // [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN + {0x10FB, 0x10FB, prAL, gcPo}, // GEORGIAN PARAGRAPH SEPARATOR + {0x10FC, 0x10FC, prAL, gcLm}, // MODIFIER LETTER GEORGIAN NAR + {0x10FD, 0x10FF, prAL, gcLl}, // [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN + {0x1100, 0x115F, prJL, gcLo}, // [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER + {0x1160, 0x11A7, prJV, gcLo}, // [72] HANGUL JUNGSEONG FILLER..HANGUL JUNGSEONG O-YAE + {0x11A8, 0x11FF, prJT, gcLo}, // [88] HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN + {0x1200, 0x1248, prAL, gcLo}, // [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA + {0x124A, 0x124D, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE + {0x1250, 0x1256, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO + {0x1258, 0x1258, prAL, gcLo}, // ETHIOPIC SYLLABLE QHWA + {0x125A, 0x125D, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE + {0x1260, 0x1288, prAL, gcLo}, // [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA + {0x128A, 0x128D, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE + {0x1290, 0x12B0, prAL, gcLo}, // [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA + {0x12B2, 0x12B5, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE + {0x12B8, 0x12BE, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO + {0x12C0, 0x12C0, prAL, gcLo}, // ETHIOPIC SYLLABLE KXWA + {0x12C2, 0x12C5, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE + {0x12C8, 0x12D6, prAL, gcLo}, // [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O + {0x12D8, 0x1310, prAL, gcLo}, // [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA + {0x1312, 0x1315, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE + {0x1318, 0x135A, prAL, gcLo}, // [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA + {0x135D, 0x135F, prCM, gcMn}, // [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK + {0x1360, 0x1360, prAL, gcPo}, // ETHIOPIC SECTION MARK + {0x1361, 0x1361, prBA, gcPo}, // ETHIOPIC WORDSPACE + {0x1362, 0x1368, prAL, gcPo}, // [7] ETHIOPIC FULL STOP..ETHIOPIC PARAGRAPH SEPARATOR + {0x1369, 0x137C, prAL, gcNo}, // [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND + {0x1380, 0x138F, prAL, gcLo}, // [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE + {0x1390, 0x1399, prAL, gcSo}, // [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT + {0x13A0, 0x13F5, prAL, gcLu}, // [86] CHEROKEE LETTER A..CHEROKEE LETTER MV + {0x13F8, 0x13FD, prAL, gcLl}, // [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV + {0x1400, 0x1400, prBA, gcPd}, // CANADIAN SYLLABICS HYPHEN + {0x1401, 0x166C, prAL, gcLo}, // [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA + {0x166D, 0x166D, prAL, gcSo}, // CANADIAN SYLLABICS CHI SIGN + {0x166E, 0x166E, prAL, gcPo}, // CANADIAN SYLLABICS FULL STOP + {0x166F, 0x167F, prAL, gcLo}, // [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W + {0x1680, 0x1680, prBA, gcZs}, // OGHAM SPACE MARK + {0x1681, 0x169A, prAL, gcLo}, // [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH + {0x169B, 0x169B, prOP, gcPs}, // OGHAM FEATHER MARK + {0x169C, 0x169C, prCL, gcPe}, // OGHAM REVERSED FEATHER MARK + {0x16A0, 0x16EA, prAL, gcLo}, // [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X + {0x16EB, 0x16ED, prBA, gcPo}, // [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION + {0x16EE, 0x16F0, prAL, gcNl}, // [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL + {0x16F1, 0x16F8, prAL, gcLo}, // [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC + {0x1700, 0x1711, prAL, gcLo}, // [18] TAGALOG LETTER A..TAGALOG LETTER HA + {0x1712, 0x1714, prCM, gcMn}, // [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + {0x1715, 0x1715, prCM, gcMc}, // TAGALOG SIGN PAMUDPOD + {0x171F, 0x171F, prAL, gcLo}, // TAGALOG LETTER ARCHAIC RA + {0x1720, 0x1731, prAL, gcLo}, // [18] HANUNOO LETTER A..HANUNOO LETTER HA + {0x1732, 0x1733, prCM, gcMn}, // [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U + {0x1734, 0x1734, prCM, gcMc}, // HANUNOO SIGN PAMUDPOD + {0x1735, 0x1736, prBA, gcPo}, // [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION + {0x1740, 0x1751, prAL, gcLo}, // [18] BUHID LETTER A..BUHID LETTER HA + {0x1752, 0x1753, prCM, gcMn}, // [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + {0x1760, 0x176C, prAL, gcLo}, // [13] TAGBANWA LETTER A..TAGBANWA LETTER YA + {0x176E, 0x1770, prAL, gcLo}, // [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA + {0x1772, 0x1773, prCM, gcMn}, // [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + {0x1780, 0x17B3, prSA, gcLo}, // [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU + {0x17B4, 0x17B5, prSA, gcMn}, // [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA + {0x17B6, 0x17B6, prSA, gcMc}, // KHMER VOWEL SIGN AA + {0x17B7, 0x17BD, prSA, gcMn}, // [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA + {0x17BE, 0x17C5, prSA, gcMc}, // [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU + {0x17C6, 0x17C6, prSA, gcMn}, // KHMER SIGN NIKAHIT + {0x17C7, 0x17C8, prSA, gcMc}, // [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU + {0x17C9, 0x17D3, prSA, gcMn}, // [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT + {0x17D4, 0x17D5, prBA, gcPo}, // [2] KHMER SIGN KHAN..KHMER SIGN BARIYOOSAN + {0x17D6, 0x17D6, prNS, gcPo}, // KHMER SIGN CAMNUC PII KUUH + {0x17D7, 0x17D7, prSA, gcLm}, // KHMER SIGN LEK TOO + {0x17D8, 0x17D8, prBA, gcPo}, // KHMER SIGN BEYYAL + {0x17D9, 0x17D9, prAL, gcPo}, // KHMER SIGN PHNAEK MUAN + {0x17DA, 0x17DA, prBA, gcPo}, // KHMER SIGN KOOMUUT + {0x17DB, 0x17DB, prPR, gcSc}, // KHMER CURRENCY SYMBOL RIEL + {0x17DC, 0x17DC, prSA, gcLo}, // KHMER SIGN AVAKRAHASANYA + {0x17DD, 0x17DD, prSA, gcMn}, // KHMER SIGN ATTHACAN + {0x17E0, 0x17E9, prNU, gcNd}, // [10] KHMER DIGIT ZERO..KHMER DIGIT NINE + {0x17F0, 0x17F9, prAL, gcNo}, // [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON + {0x1800, 0x1801, prAL, gcPo}, // [2] MONGOLIAN BIRGA..MONGOLIAN ELLIPSIS + {0x1802, 0x1803, prEX, gcPo}, // [2] MONGOLIAN COMMA..MONGOLIAN FULL STOP + {0x1804, 0x1805, prBA, gcPo}, // [2] MONGOLIAN COLON..MONGOLIAN FOUR DOTS + {0x1806, 0x1806, prBB, gcPd}, // MONGOLIAN TODO SOFT HYPHEN + {0x1807, 0x1807, prAL, gcPo}, // MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER + {0x1808, 0x1809, prEX, gcPo}, // [2] MONGOLIAN MANCHU COMMA..MONGOLIAN MANCHU FULL STOP + {0x180A, 0x180A, prAL, gcPo}, // MONGOLIAN NIRUGU + {0x180B, 0x180D, prCM, gcMn}, // [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE + {0x180E, 0x180E, prGL, gcCf}, // MONGOLIAN VOWEL SEPARATOR + {0x180F, 0x180F, prCM, gcMn}, // MONGOLIAN FREE VARIATION SELECTOR FOUR + {0x1810, 0x1819, prNU, gcNd}, // [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE + {0x1820, 0x1842, prAL, gcLo}, // [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI + {0x1843, 0x1843, prAL, gcLm}, // MONGOLIAN LETTER TODO LONG VOWEL SIGN + {0x1844, 0x1878, prAL, gcLo}, // [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS + {0x1880, 0x1884, prAL, gcLo}, // [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA + {0x1885, 0x1886, prCM, gcMn}, // [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA + {0x1887, 0x18A8, prAL, gcLo}, // [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA + {0x18A9, 0x18A9, prCM, gcMn}, // MONGOLIAN LETTER ALI GALI DAGALGA + {0x18AA, 0x18AA, prAL, gcLo}, // MONGOLIAN LETTER MANCHU ALI GALI LHA + {0x18B0, 0x18F5, prAL, gcLo}, // [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S + {0x1900, 0x191E, prAL, gcLo}, // [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA + {0x1920, 0x1922, prCM, gcMn}, // [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U + {0x1923, 0x1926, prCM, gcMc}, // [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU + {0x1927, 0x1928, prCM, gcMn}, // [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O + {0x1929, 0x192B, prCM, gcMc}, // [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA + {0x1930, 0x1931, prCM, gcMc}, // [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA + {0x1932, 0x1932, prCM, gcMn}, // LIMBU SMALL LETTER ANUSVARA + {0x1933, 0x1938, prCM, gcMc}, // [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA + {0x1939, 0x193B, prCM, gcMn}, // [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I + {0x1940, 0x1940, prAL, gcSo}, // LIMBU SIGN LOO + {0x1944, 0x1945, prEX, gcPo}, // [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK + {0x1946, 0x194F, prNU, gcNd}, // [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE + {0x1950, 0x196D, prSA, gcLo}, // [30] TAI LE LETTER KA..TAI LE LETTER AI + {0x1970, 0x1974, prSA, gcLo}, // [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6 + {0x1980, 0x19AB, prSA, gcLo}, // [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA + {0x19B0, 0x19C9, prSA, gcLo}, // [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2 + {0x19D0, 0x19D9, prNU, gcNd}, // [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE + {0x19DA, 0x19DA, prSA, gcNo}, // NEW TAI LUE THAM DIGIT ONE + {0x19DE, 0x19DF, prSA, gcSo}, // [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV + {0x19E0, 0x19FF, prAL, gcSo}, // [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC + {0x1A00, 0x1A16, prAL, gcLo}, // [23] BUGINESE LETTER KA..BUGINESE LETTER HA + {0x1A17, 0x1A18, prCM, gcMn}, // [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U + {0x1A19, 0x1A1A, prCM, gcMc}, // [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O + {0x1A1B, 0x1A1B, prCM, gcMn}, // BUGINESE VOWEL SIGN AE + {0x1A1E, 0x1A1F, prAL, gcPo}, // [2] BUGINESE PALLAWA..BUGINESE END OF SECTION + {0x1A20, 0x1A54, prSA, gcLo}, // [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA + {0x1A55, 0x1A55, prSA, gcMc}, // TAI THAM CONSONANT SIGN MEDIAL RA + {0x1A56, 0x1A56, prSA, gcMn}, // TAI THAM CONSONANT SIGN MEDIAL LA + {0x1A57, 0x1A57, prSA, gcMc}, // TAI THAM CONSONANT SIGN LA TANG LAI + {0x1A58, 0x1A5E, prSA, gcMn}, // [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA + {0x1A60, 0x1A60, prSA, gcMn}, // TAI THAM SIGN SAKOT + {0x1A61, 0x1A61, prSA, gcMc}, // TAI THAM VOWEL SIGN A + {0x1A62, 0x1A62, prSA, gcMn}, // TAI THAM VOWEL SIGN MAI SAT + {0x1A63, 0x1A64, prSA, gcMc}, // [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA + {0x1A65, 0x1A6C, prSA, gcMn}, // [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW + {0x1A6D, 0x1A72, prSA, gcMc}, // [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI + {0x1A73, 0x1A7C, prSA, gcMn}, // [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN + {0x1A7F, 0x1A7F, prCM, gcMn}, // TAI THAM COMBINING CRYPTOGRAMMIC DOT + {0x1A80, 0x1A89, prNU, gcNd}, // [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE + {0x1A90, 0x1A99, prNU, gcNd}, // [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE + {0x1AA0, 0x1AA6, prSA, gcPo}, // [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA + {0x1AA7, 0x1AA7, prSA, gcLm}, // TAI THAM SIGN MAI YAMOK + {0x1AA8, 0x1AAD, prSA, gcPo}, // [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG + {0x1AB0, 0x1ABD, prCM, gcMn}, // [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW + {0x1ABE, 0x1ABE, prCM, gcMe}, // COMBINING PARENTHESES OVERLAY + {0x1ABF, 0x1ACE, prCM, gcMn}, // [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T + {0x1B00, 0x1B03, prCM, gcMn}, // [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG + {0x1B04, 0x1B04, prCM, gcMc}, // BALINESE SIGN BISAH + {0x1B05, 0x1B33, prAL, gcLo}, // [47] BALINESE LETTER AKARA..BALINESE LETTER HA + {0x1B34, 0x1B34, prCM, gcMn}, // BALINESE SIGN REREKAN + {0x1B35, 0x1B35, prCM, gcMc}, // BALINESE VOWEL SIGN TEDUNG + {0x1B36, 0x1B3A, prCM, gcMn}, // [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA + {0x1B3B, 0x1B3B, prCM, gcMc}, // BALINESE VOWEL SIGN RA REPA TEDUNG + {0x1B3C, 0x1B3C, prCM, gcMn}, // BALINESE VOWEL SIGN LA LENGA + {0x1B3D, 0x1B41, prCM, gcMc}, // [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG + {0x1B42, 0x1B42, prCM, gcMn}, // BALINESE VOWEL SIGN PEPET + {0x1B43, 0x1B44, prCM, gcMc}, // [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG + {0x1B45, 0x1B4C, prAL, gcLo}, // [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA + {0x1B50, 0x1B59, prNU, gcNd}, // [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE + {0x1B5A, 0x1B5B, prBA, gcPo}, // [2] BALINESE PANTI..BALINESE PAMADA + {0x1B5C, 0x1B5C, prAL, gcPo}, // BALINESE WINDU + {0x1B5D, 0x1B60, prBA, gcPo}, // [4] BALINESE CARIK PAMUNGKAH..BALINESE PAMENENG + {0x1B61, 0x1B6A, prAL, gcSo}, // [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE + {0x1B6B, 0x1B73, prCM, gcMn}, // [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG + {0x1B74, 0x1B7C, prAL, gcSo}, // [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING + {0x1B7D, 0x1B7E, prBA, gcPo}, // [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG + {0x1B80, 0x1B81, prCM, gcMn}, // [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR + {0x1B82, 0x1B82, prCM, gcMc}, // SUNDANESE SIGN PANGWISAD + {0x1B83, 0x1BA0, prAL, gcLo}, // [30] SUNDANESE LETTER A..SUNDANESE LETTER HA + {0x1BA1, 0x1BA1, prCM, gcMc}, // SUNDANESE CONSONANT SIGN PAMINGKAL + {0x1BA2, 0x1BA5, prCM, gcMn}, // [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU + {0x1BA6, 0x1BA7, prCM, gcMc}, // [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG + {0x1BA8, 0x1BA9, prCM, gcMn}, // [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG + {0x1BAA, 0x1BAA, prCM, gcMc}, // SUNDANESE SIGN PAMAAEH + {0x1BAB, 0x1BAD, prCM, gcMn}, // [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA + {0x1BAE, 0x1BAF, prAL, gcLo}, // [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA + {0x1BB0, 0x1BB9, prNU, gcNd}, // [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE + {0x1BBA, 0x1BBF, prAL, gcLo}, // [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M + {0x1BC0, 0x1BE5, prAL, gcLo}, // [38] BATAK LETTER A..BATAK LETTER U + {0x1BE6, 0x1BE6, prCM, gcMn}, // BATAK SIGN TOMPI + {0x1BE7, 0x1BE7, prCM, gcMc}, // BATAK VOWEL SIGN E + {0x1BE8, 0x1BE9, prCM, gcMn}, // [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE + {0x1BEA, 0x1BEC, prCM, gcMc}, // [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O + {0x1BED, 0x1BED, prCM, gcMn}, // BATAK VOWEL SIGN KARO O + {0x1BEE, 0x1BEE, prCM, gcMc}, // BATAK VOWEL SIGN U + {0x1BEF, 0x1BF1, prCM, gcMn}, // [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H + {0x1BF2, 0x1BF3, prCM, gcMc}, // [2] BATAK PANGOLAT..BATAK PANONGONAN + {0x1BFC, 0x1BFF, prAL, gcPo}, // [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT + {0x1C00, 0x1C23, prAL, gcLo}, // [36] LEPCHA LETTER KA..LEPCHA LETTER A + {0x1C24, 0x1C2B, prCM, gcMc}, // [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU + {0x1C2C, 0x1C33, prCM, gcMn}, // [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T + {0x1C34, 0x1C35, prCM, gcMc}, // [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG + {0x1C36, 0x1C37, prCM, gcMn}, // [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA + {0x1C3B, 0x1C3F, prBA, gcPo}, // [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK + {0x1C40, 0x1C49, prNU, gcNd}, // [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE + {0x1C4D, 0x1C4F, prAL, gcLo}, // [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA + {0x1C50, 0x1C59, prNU, gcNd}, // [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE + {0x1C5A, 0x1C77, prAL, gcLo}, // [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH + {0x1C78, 0x1C7D, prAL, gcLm}, // [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD + {0x1C7E, 0x1C7F, prBA, gcPo}, // [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD + {0x1C80, 0x1C88, prAL, gcLl}, // [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK + {0x1C90, 0x1CBA, prAL, gcLu}, // [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN + {0x1CBD, 0x1CBF, prAL, gcLu}, // [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN + {0x1CC0, 0x1CC7, prAL, gcPo}, // [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA + {0x1CD0, 0x1CD2, prCM, gcMn}, // [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA + {0x1CD3, 0x1CD3, prAL, gcPo}, // VEDIC SIGN NIHSHVASA + {0x1CD4, 0x1CE0, prCM, gcMn}, // [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA + {0x1CE1, 0x1CE1, prCM, gcMc}, // VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA + {0x1CE2, 0x1CE8, prCM, gcMn}, // [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL + {0x1CE9, 0x1CEC, prAL, gcLo}, // [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL + {0x1CED, 0x1CED, prCM, gcMn}, // VEDIC SIGN TIRYAK + {0x1CEE, 0x1CF3, prAL, gcLo}, // [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA + {0x1CF4, 0x1CF4, prCM, gcMn}, // VEDIC TONE CANDRA ABOVE + {0x1CF5, 0x1CF6, prAL, gcLo}, // [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA + {0x1CF7, 0x1CF7, prCM, gcMc}, // VEDIC SIGN ATIKRAMA + {0x1CF8, 0x1CF9, prCM, gcMn}, // [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE + {0x1CFA, 0x1CFA, prAL, gcLo}, // VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA + {0x1D00, 0x1D2B, prAL, gcLl}, // [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL + {0x1D2C, 0x1D6A, prAL, gcLm}, // [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI + {0x1D6B, 0x1D77, prAL, gcLl}, // [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G + {0x1D78, 0x1D78, prAL, gcLm}, // MODIFIER LETTER CYRILLIC EN + {0x1D79, 0x1D7F, prAL, gcLl}, // [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE + {0x1D80, 0x1D9A, prAL, gcLl}, // [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK + {0x1D9B, 0x1DBF, prAL, gcLm}, // [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA + {0x1DC0, 0x1DCC, prCM, gcMn}, // [13] COMBINING DOTTED GRAVE ACCENT..COMBINING MACRON-BREVE + {0x1DCD, 0x1DCD, prGL, gcMn}, // COMBINING DOUBLE CIRCUMFLEX ABOVE + {0x1DCE, 0x1DFB, prCM, gcMn}, // [46] COMBINING OGONEK ABOVE..COMBINING DELETION MARK + {0x1DFC, 0x1DFC, prGL, gcMn}, // COMBINING DOUBLE INVERTED BREVE BELOW + {0x1DFD, 0x1DFF, prCM, gcMn}, // [3] COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x1E00, 0x1EFF, prAL, gcLC}, // [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP + {0x1F00, 0x1F15, prAL, gcLC}, // [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA + {0x1F18, 0x1F1D, prAL, gcLu}, // [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA + {0x1F20, 0x1F45, prAL, gcLC}, // [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA + {0x1F48, 0x1F4D, prAL, gcLu}, // [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA + {0x1F50, 0x1F57, prAL, gcLl}, // [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI + {0x1F59, 0x1F59, prAL, gcLu}, // GREEK CAPITAL LETTER UPSILON WITH DASIA + {0x1F5B, 0x1F5B, prAL, gcLu}, // GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA + {0x1F5D, 0x1F5D, prAL, gcLu}, // GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA + {0x1F5F, 0x1F7D, prAL, gcLC}, // [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA + {0x1F80, 0x1FB4, prAL, gcLC}, // [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI + {0x1FB6, 0x1FBC, prAL, gcLC}, // [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI + {0x1FBD, 0x1FBD, prAL, gcSk}, // GREEK KORONIS + {0x1FBE, 0x1FBE, prAL, gcLl}, // GREEK PROSGEGRAMMENI + {0x1FBF, 0x1FC1, prAL, gcSk}, // [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI + {0x1FC2, 0x1FC4, prAL, gcLl}, // [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI + {0x1FC6, 0x1FCC, prAL, gcLC}, // [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI + {0x1FCD, 0x1FCF, prAL, gcSk}, // [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI + {0x1FD0, 0x1FD3, prAL, gcLl}, // [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA + {0x1FD6, 0x1FDB, prAL, gcLC}, // [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA + {0x1FDD, 0x1FDF, prAL, gcSk}, // [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI + {0x1FE0, 0x1FEC, prAL, gcLC}, // [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA + {0x1FED, 0x1FEF, prAL, gcSk}, // [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA + {0x1FF2, 0x1FF4, prAL, gcLl}, // [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + {0x1FF6, 0x1FFC, prAL, gcLC}, // [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + {0x1FFD, 0x1FFD, prBB, gcSk}, // GREEK OXIA + {0x1FFE, 0x1FFE, prAL, gcSk}, // GREEK DASIA + {0x2000, 0x2006, prBA, gcZs}, // [7] EN QUAD..SIX-PER-EM SPACE + {0x2007, 0x2007, prGL, gcZs}, // FIGURE SPACE + {0x2008, 0x200A, prBA, gcZs}, // [3] PUNCTUATION SPACE..HAIR SPACE + {0x200B, 0x200B, prZW, gcCf}, // ZERO WIDTH SPACE + {0x200C, 0x200C, prCM, gcCf}, // ZERO WIDTH NON-JOINER + {0x200D, 0x200D, prZWJ, gcCf}, // ZERO WIDTH JOINER + {0x200E, 0x200F, prCM, gcCf}, // [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK + {0x2010, 0x2010, prBA, gcPd}, // HYPHEN + {0x2011, 0x2011, prGL, gcPd}, // NON-BREAKING HYPHEN + {0x2012, 0x2013, prBA, gcPd}, // [2] FIGURE DASH..EN DASH + {0x2014, 0x2014, prB2, gcPd}, // EM DASH + {0x2015, 0x2015, prAI, gcPd}, // HORIZONTAL BAR + {0x2016, 0x2016, prAI, gcPo}, // DOUBLE VERTICAL LINE + {0x2017, 0x2017, prAL, gcPo}, // DOUBLE LOW LINE + {0x2018, 0x2018, prQU, gcPi}, // LEFT SINGLE QUOTATION MARK + {0x2019, 0x2019, prQU, gcPf}, // RIGHT SINGLE QUOTATION MARK + {0x201A, 0x201A, prOP, gcPs}, // SINGLE LOW-9 QUOTATION MARK + {0x201B, 0x201C, prQU, gcPi}, // [2] SINGLE HIGH-REVERSED-9 QUOTATION MARK..LEFT DOUBLE QUOTATION MARK + {0x201D, 0x201D, prQU, gcPf}, // RIGHT DOUBLE QUOTATION MARK + {0x201E, 0x201E, prOP, gcPs}, // DOUBLE LOW-9 QUOTATION MARK + {0x201F, 0x201F, prQU, gcPi}, // DOUBLE HIGH-REVERSED-9 QUOTATION MARK + {0x2020, 0x2021, prAI, gcPo}, // [2] DAGGER..DOUBLE DAGGER + {0x2022, 0x2023, prAL, gcPo}, // [2] BULLET..TRIANGULAR BULLET + {0x2024, 0x2026, prIN, gcPo}, // [3] ONE DOT LEADER..HORIZONTAL ELLIPSIS + {0x2027, 0x2027, prBA, gcPo}, // HYPHENATION POINT + {0x2028, 0x2028, prBK, gcZl}, // LINE SEPARATOR + {0x2029, 0x2029, prBK, gcZp}, // PARAGRAPH SEPARATOR + {0x202A, 0x202E, prCM, gcCf}, // [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE + {0x202F, 0x202F, prGL, gcZs}, // NARROW NO-BREAK SPACE + {0x2030, 0x2037, prPO, gcPo}, // [8] PER MILLE SIGN..REVERSED TRIPLE PRIME + {0x2038, 0x2038, prAL, gcPo}, // CARET + {0x2039, 0x2039, prQU, gcPi}, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + {0x203A, 0x203A, prQU, gcPf}, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + {0x203B, 0x203B, prAI, gcPo}, // REFERENCE MARK + {0x203C, 0x203D, prNS, gcPo}, // [2] DOUBLE EXCLAMATION MARK..INTERROBANG + {0x203E, 0x203E, prAL, gcPo}, // OVERLINE + {0x203F, 0x2040, prAL, gcPc}, // [2] UNDERTIE..CHARACTER TIE + {0x2041, 0x2043, prAL, gcPo}, // [3] CARET INSERTION POINT..HYPHEN BULLET + {0x2044, 0x2044, prIS, gcSm}, // FRACTION SLASH + {0x2045, 0x2045, prOP, gcPs}, // LEFT SQUARE BRACKET WITH QUILL + {0x2046, 0x2046, prCL, gcPe}, // RIGHT SQUARE BRACKET WITH QUILL + {0x2047, 0x2049, prNS, gcPo}, // [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK + {0x204A, 0x2051, prAL, gcPo}, // [8] TIRONIAN SIGN ET..TWO ASTERISKS ALIGNED VERTICALLY + {0x2052, 0x2052, prAL, gcSm}, // COMMERCIAL MINUS SIGN + {0x2053, 0x2053, prAL, gcPo}, // SWUNG DASH + {0x2054, 0x2054, prAL, gcPc}, // INVERTED UNDERTIE + {0x2055, 0x2055, prAL, gcPo}, // FLOWER PUNCTUATION MARK + {0x2056, 0x2056, prBA, gcPo}, // THREE DOT PUNCTUATION + {0x2057, 0x2057, prPO, gcPo}, // QUADRUPLE PRIME + {0x2058, 0x205B, prBA, gcPo}, // [4] FOUR DOT PUNCTUATION..FOUR DOT MARK + {0x205C, 0x205C, prAL, gcPo}, // DOTTED CROSS + {0x205D, 0x205E, prBA, gcPo}, // [2] TRICOLON..VERTICAL FOUR DOTS + {0x205F, 0x205F, prBA, gcZs}, // MEDIUM MATHEMATICAL SPACE + {0x2060, 0x2060, prWJ, gcCf}, // WORD JOINER + {0x2061, 0x2064, prAL, gcCf}, // [4] FUNCTION APPLICATION..INVISIBLE PLUS + {0x2066, 0x206F, prCM, gcCf}, // [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES + {0x2070, 0x2070, prAL, gcNo}, // SUPERSCRIPT ZERO + {0x2071, 0x2071, prAL, gcLm}, // SUPERSCRIPT LATIN SMALL LETTER I + {0x2074, 0x2074, prAI, gcNo}, // SUPERSCRIPT FOUR + {0x2075, 0x2079, prAL, gcNo}, // [5] SUPERSCRIPT FIVE..SUPERSCRIPT NINE + {0x207A, 0x207C, prAL, gcSm}, // [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN + {0x207D, 0x207D, prOP, gcPs}, // SUPERSCRIPT LEFT PARENTHESIS + {0x207E, 0x207E, prCL, gcPe}, // SUPERSCRIPT RIGHT PARENTHESIS + {0x207F, 0x207F, prAI, gcLm}, // SUPERSCRIPT LATIN SMALL LETTER N + {0x2080, 0x2080, prAL, gcNo}, // SUBSCRIPT ZERO + {0x2081, 0x2084, prAI, gcNo}, // [4] SUBSCRIPT ONE..SUBSCRIPT FOUR + {0x2085, 0x2089, prAL, gcNo}, // [5] SUBSCRIPT FIVE..SUBSCRIPT NINE + {0x208A, 0x208C, prAL, gcSm}, // [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN + {0x208D, 0x208D, prOP, gcPs}, // SUBSCRIPT LEFT PARENTHESIS + {0x208E, 0x208E, prCL, gcPe}, // SUBSCRIPT RIGHT PARENTHESIS + {0x2090, 0x209C, prAL, gcLm}, // [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T + {0x20A0, 0x20A6, prPR, gcSc}, // [7] EURO-CURRENCY SIGN..NAIRA SIGN + {0x20A7, 0x20A7, prPO, gcSc}, // PESETA SIGN + {0x20A8, 0x20B5, prPR, gcSc}, // [14] RUPEE SIGN..CEDI SIGN + {0x20B6, 0x20B6, prPO, gcSc}, // LIVRE TOURNOIS SIGN + {0x20B7, 0x20BA, prPR, gcSc}, // [4] SPESMILO SIGN..TURKISH LIRA SIGN + {0x20BB, 0x20BB, prPO, gcSc}, // NORDIC MARK SIGN + {0x20BC, 0x20BD, prPR, gcSc}, // [2] MANAT SIGN..RUBLE SIGN + {0x20BE, 0x20BE, prPO, gcSc}, // LARI SIGN + {0x20BF, 0x20BF, prPR, gcSc}, // BITCOIN SIGN + {0x20C0, 0x20C0, prPO, gcSc}, // SOM SIGN + {0x20C1, 0x20CF, prPR, gcCn}, // [15] .. + {0x20D0, 0x20DC, prCM, gcMn}, // [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE + {0x20DD, 0x20E0, prCM, gcMe}, // [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH + {0x20E1, 0x20E1, prCM, gcMn}, // COMBINING LEFT RIGHT ARROW ABOVE + {0x20E2, 0x20E4, prCM, gcMe}, // [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE + {0x20E5, 0x20F0, prCM, gcMn}, // [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE + {0x2100, 0x2101, prAL, gcSo}, // [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT + {0x2102, 0x2102, prAL, gcLu}, // DOUBLE-STRUCK CAPITAL C + {0x2103, 0x2103, prPO, gcSo}, // DEGREE CELSIUS + {0x2104, 0x2104, prAL, gcSo}, // CENTRE LINE SYMBOL + {0x2105, 0x2105, prAI, gcSo}, // CARE OF + {0x2106, 0x2106, prAL, gcSo}, // CADA UNA + {0x2107, 0x2107, prAL, gcLu}, // EULER CONSTANT + {0x2108, 0x2108, prAL, gcSo}, // SCRUPLE + {0x2109, 0x2109, prPO, gcSo}, // DEGREE FAHRENHEIT + {0x210A, 0x2112, prAL, gcLC}, // [9] SCRIPT SMALL G..SCRIPT CAPITAL L + {0x2113, 0x2113, prAI, gcLl}, // SCRIPT SMALL L + {0x2114, 0x2114, prAL, gcSo}, // L B BAR SYMBOL + {0x2115, 0x2115, prAL, gcLu}, // DOUBLE-STRUCK CAPITAL N + {0x2116, 0x2116, prPR, gcSo}, // NUMERO SIGN + {0x2117, 0x2117, prAL, gcSo}, // SOUND RECORDING COPYRIGHT + {0x2118, 0x2118, prAL, gcSm}, // SCRIPT CAPITAL P + {0x2119, 0x211D, prAL, gcLu}, // [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R + {0x211E, 0x2120, prAL, gcSo}, // [3] PRESCRIPTION TAKE..SERVICE MARK + {0x2121, 0x2122, prAI, gcSo}, // [2] TELEPHONE SIGN..TRADE MARK SIGN + {0x2123, 0x2123, prAL, gcSo}, // VERSICLE + {0x2124, 0x2124, prAL, gcLu}, // DOUBLE-STRUCK CAPITAL Z + {0x2125, 0x2125, prAL, gcSo}, // OUNCE SIGN + {0x2126, 0x2126, prAL, gcLu}, // OHM SIGN + {0x2127, 0x2127, prAL, gcSo}, // INVERTED OHM SIGN + {0x2128, 0x2128, prAL, gcLu}, // BLACK-LETTER CAPITAL Z + {0x2129, 0x2129, prAL, gcSo}, // TURNED GREEK SMALL LETTER IOTA + {0x212A, 0x212A, prAL, gcLu}, // KELVIN SIGN + {0x212B, 0x212B, prAI, gcLu}, // ANGSTROM SIGN + {0x212C, 0x212D, prAL, gcLu}, // [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C + {0x212E, 0x212E, prAL, gcSo}, // ESTIMATED SYMBOL + {0x212F, 0x2134, prAL, gcLC}, // [6] SCRIPT SMALL E..SCRIPT SMALL O + {0x2135, 0x2138, prAL, gcLo}, // [4] ALEF SYMBOL..DALET SYMBOL + {0x2139, 0x2139, prAL, gcLl}, // INFORMATION SOURCE + {0x213A, 0x213B, prAL, gcSo}, // [2] ROTATED CAPITAL Q..FACSIMILE SIGN + {0x213C, 0x213F, prAL, gcLC}, // [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI + {0x2140, 0x2144, prAL, gcSm}, // [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y + {0x2145, 0x2149, prAL, gcLC}, // [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J + {0x214A, 0x214A, prAL, gcSo}, // PROPERTY LINE + {0x214B, 0x214B, prAL, gcSm}, // TURNED AMPERSAND + {0x214C, 0x214D, prAL, gcSo}, // [2] PER SIGN..AKTIESELSKAB + {0x214E, 0x214E, prAL, gcLl}, // TURNED SMALL F + {0x214F, 0x214F, prAL, gcSo}, // SYMBOL FOR SAMARITAN SOURCE + {0x2150, 0x2153, prAL, gcNo}, // [4] VULGAR FRACTION ONE SEVENTH..VULGAR FRACTION ONE THIRD + {0x2154, 0x2155, prAI, gcNo}, // [2] VULGAR FRACTION TWO THIRDS..VULGAR FRACTION ONE FIFTH + {0x2156, 0x215A, prAL, gcNo}, // [5] VULGAR FRACTION TWO FIFTHS..VULGAR FRACTION FIVE SIXTHS + {0x215B, 0x215B, prAI, gcNo}, // VULGAR FRACTION ONE EIGHTH + {0x215C, 0x215D, prAL, gcNo}, // [2] VULGAR FRACTION THREE EIGHTHS..VULGAR FRACTION FIVE EIGHTHS + {0x215E, 0x215E, prAI, gcNo}, // VULGAR FRACTION SEVEN EIGHTHS + {0x215F, 0x215F, prAL, gcNo}, // FRACTION NUMERATOR ONE + {0x2160, 0x216B, prAI, gcNl}, // [12] ROMAN NUMERAL ONE..ROMAN NUMERAL TWELVE + {0x216C, 0x216F, prAL, gcNl}, // [4] ROMAN NUMERAL FIFTY..ROMAN NUMERAL ONE THOUSAND + {0x2170, 0x2179, prAI, gcNl}, // [10] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL TEN + {0x217A, 0x2182, prAL, gcNl}, // [9] SMALL ROMAN NUMERAL ELEVEN..ROMAN NUMERAL TEN THOUSAND + {0x2183, 0x2184, prAL, gcLC}, // [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C + {0x2185, 0x2188, prAL, gcNl}, // [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND + {0x2189, 0x2189, prAI, gcNo}, // VULGAR FRACTION ZERO THIRDS + {0x218A, 0x218B, prAL, gcSo}, // [2] TURNED DIGIT TWO..TURNED DIGIT THREE + {0x2190, 0x2194, prAI, gcSm}, // [5] LEFTWARDS ARROW..LEFT RIGHT ARROW + {0x2195, 0x2199, prAI, gcSo}, // [5] UP DOWN ARROW..SOUTH WEST ARROW + {0x219A, 0x219B, prAL, gcSm}, // [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE + {0x219C, 0x219F, prAL, gcSo}, // [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW + {0x21A0, 0x21A0, prAL, gcSm}, // RIGHTWARDS TWO HEADED ARROW + {0x21A1, 0x21A2, prAL, gcSo}, // [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL + {0x21A3, 0x21A3, prAL, gcSm}, // RIGHTWARDS ARROW WITH TAIL + {0x21A4, 0x21A5, prAL, gcSo}, // [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR + {0x21A6, 0x21A6, prAL, gcSm}, // RIGHTWARDS ARROW FROM BAR + {0x21A7, 0x21AD, prAL, gcSo}, // [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW + {0x21AE, 0x21AE, prAL, gcSm}, // LEFT RIGHT ARROW WITH STROKE + {0x21AF, 0x21CD, prAL, gcSo}, // [31] DOWNWARDS ZIGZAG ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE + {0x21CE, 0x21CF, prAL, gcSm}, // [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE + {0x21D0, 0x21D1, prAL, gcSo}, // [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW + {0x21D2, 0x21D2, prAI, gcSm}, // RIGHTWARDS DOUBLE ARROW + {0x21D3, 0x21D3, prAL, gcSo}, // DOWNWARDS DOUBLE ARROW + {0x21D4, 0x21D4, prAI, gcSm}, // LEFT RIGHT DOUBLE ARROW + {0x21D5, 0x21F3, prAL, gcSo}, // [31] UP DOWN DOUBLE ARROW..UP DOWN WHITE ARROW + {0x21F4, 0x21FF, prAL, gcSm}, // [12] RIGHT ARROW WITH SMALL CIRCLE..LEFT RIGHT OPEN-HEADED ARROW + {0x2200, 0x2200, prAI, gcSm}, // FOR ALL + {0x2201, 0x2201, prAL, gcSm}, // COMPLEMENT + {0x2202, 0x2203, prAI, gcSm}, // [2] PARTIAL DIFFERENTIAL..THERE EXISTS + {0x2204, 0x2206, prAL, gcSm}, // [3] THERE DOES NOT EXIST..INCREMENT + {0x2207, 0x2208, prAI, gcSm}, // [2] NABLA..ELEMENT OF + {0x2209, 0x220A, prAL, gcSm}, // [2] NOT AN ELEMENT OF..SMALL ELEMENT OF + {0x220B, 0x220B, prAI, gcSm}, // CONTAINS AS MEMBER + {0x220C, 0x220E, prAL, gcSm}, // [3] DOES NOT CONTAIN AS MEMBER..END OF PROOF + {0x220F, 0x220F, prAI, gcSm}, // N-ARY PRODUCT + {0x2210, 0x2210, prAL, gcSm}, // N-ARY COPRODUCT + {0x2211, 0x2211, prAI, gcSm}, // N-ARY SUMMATION + {0x2212, 0x2213, prPR, gcSm}, // [2] MINUS SIGN..MINUS-OR-PLUS SIGN + {0x2214, 0x2214, prAL, gcSm}, // DOT PLUS + {0x2215, 0x2215, prAI, gcSm}, // DIVISION SLASH + {0x2216, 0x2219, prAL, gcSm}, // [4] SET MINUS..BULLET OPERATOR + {0x221A, 0x221A, prAI, gcSm}, // SQUARE ROOT + {0x221B, 0x221C, prAL, gcSm}, // [2] CUBE ROOT..FOURTH ROOT + {0x221D, 0x2220, prAI, gcSm}, // [4] PROPORTIONAL TO..ANGLE + {0x2221, 0x2222, prAL, gcSm}, // [2] MEASURED ANGLE..SPHERICAL ANGLE + {0x2223, 0x2223, prAI, gcSm}, // DIVIDES + {0x2224, 0x2224, prAL, gcSm}, // DOES NOT DIVIDE + {0x2225, 0x2225, prAI, gcSm}, // PARALLEL TO + {0x2226, 0x2226, prAL, gcSm}, // NOT PARALLEL TO + {0x2227, 0x222C, prAI, gcSm}, // [6] LOGICAL AND..DOUBLE INTEGRAL + {0x222D, 0x222D, prAL, gcSm}, // TRIPLE INTEGRAL + {0x222E, 0x222E, prAI, gcSm}, // CONTOUR INTEGRAL + {0x222F, 0x2233, prAL, gcSm}, // [5] SURFACE INTEGRAL..ANTICLOCKWISE CONTOUR INTEGRAL + {0x2234, 0x2237, prAI, gcSm}, // [4] THEREFORE..PROPORTION + {0x2238, 0x223B, prAL, gcSm}, // [4] DOT MINUS..HOMOTHETIC + {0x223C, 0x223D, prAI, gcSm}, // [2] TILDE OPERATOR..REVERSED TILDE + {0x223E, 0x2247, prAL, gcSm}, // [10] INVERTED LAZY S..NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO + {0x2248, 0x2248, prAI, gcSm}, // ALMOST EQUAL TO + {0x2249, 0x224B, prAL, gcSm}, // [3] NOT ALMOST EQUAL TO..TRIPLE TILDE + {0x224C, 0x224C, prAI, gcSm}, // ALL EQUAL TO + {0x224D, 0x2251, prAL, gcSm}, // [5] EQUIVALENT TO..GEOMETRICALLY EQUAL TO + {0x2252, 0x2252, prAI, gcSm}, // APPROXIMATELY EQUAL TO OR THE IMAGE OF + {0x2253, 0x225F, prAL, gcSm}, // [13] IMAGE OF OR APPROXIMATELY EQUAL TO..QUESTIONED EQUAL TO + {0x2260, 0x2261, prAI, gcSm}, // [2] NOT EQUAL TO..IDENTICAL TO + {0x2262, 0x2263, prAL, gcSm}, // [2] NOT IDENTICAL TO..STRICTLY EQUIVALENT TO + {0x2264, 0x2267, prAI, gcSm}, // [4] LESS-THAN OR EQUAL TO..GREATER-THAN OVER EQUAL TO + {0x2268, 0x2269, prAL, gcSm}, // [2] LESS-THAN BUT NOT EQUAL TO..GREATER-THAN BUT NOT EQUAL TO + {0x226A, 0x226B, prAI, gcSm}, // [2] MUCH LESS-THAN..MUCH GREATER-THAN + {0x226C, 0x226D, prAL, gcSm}, // [2] BETWEEN..NOT EQUIVALENT TO + {0x226E, 0x226F, prAI, gcSm}, // [2] NOT LESS-THAN..NOT GREATER-THAN + {0x2270, 0x2281, prAL, gcSm}, // [18] NEITHER LESS-THAN NOR EQUAL TO..DOES NOT SUCCEED + {0x2282, 0x2283, prAI, gcSm}, // [2] SUBSET OF..SUPERSET OF + {0x2284, 0x2285, prAL, gcSm}, // [2] NOT A SUBSET OF..NOT A SUPERSET OF + {0x2286, 0x2287, prAI, gcSm}, // [2] SUBSET OF OR EQUAL TO..SUPERSET OF OR EQUAL TO + {0x2288, 0x2294, prAL, gcSm}, // [13] NEITHER A SUBSET OF NOR EQUAL TO..SQUARE CUP + {0x2295, 0x2295, prAI, gcSm}, // CIRCLED PLUS + {0x2296, 0x2298, prAL, gcSm}, // [3] CIRCLED MINUS..CIRCLED DIVISION SLASH + {0x2299, 0x2299, prAI, gcSm}, // CIRCLED DOT OPERATOR + {0x229A, 0x22A4, prAL, gcSm}, // [11] CIRCLED RING OPERATOR..DOWN TACK + {0x22A5, 0x22A5, prAI, gcSm}, // UP TACK + {0x22A6, 0x22BE, prAL, gcSm}, // [25] ASSERTION..RIGHT ANGLE WITH ARC + {0x22BF, 0x22BF, prAI, gcSm}, // RIGHT TRIANGLE + {0x22C0, 0x22EE, prAL, gcSm}, // [47] N-ARY LOGICAL AND..VERTICAL ELLIPSIS + {0x22EF, 0x22EF, prIN, gcSm}, // MIDLINE HORIZONTAL ELLIPSIS + {0x22F0, 0x22FF, prAL, gcSm}, // [16] UP RIGHT DIAGONAL ELLIPSIS..Z NOTATION BAG MEMBERSHIP + {0x2300, 0x2307, prAL, gcSo}, // [8] DIAMETER SIGN..WAVY LINE + {0x2308, 0x2308, prOP, gcPs}, // LEFT CEILING + {0x2309, 0x2309, prCL, gcPe}, // RIGHT CEILING + {0x230A, 0x230A, prOP, gcPs}, // LEFT FLOOR + {0x230B, 0x230B, prCL, gcPe}, // RIGHT FLOOR + {0x230C, 0x2311, prAL, gcSo}, // [6] BOTTOM RIGHT CROP..SQUARE LOZENGE + {0x2312, 0x2312, prAI, gcSo}, // ARC + {0x2313, 0x2319, prAL, gcSo}, // [7] SEGMENT..TURNED NOT SIGN + {0x231A, 0x231B, prID, gcSo}, // [2] WATCH..HOURGLASS + {0x231C, 0x231F, prAL, gcSo}, // [4] TOP LEFT CORNER..BOTTOM RIGHT CORNER + {0x2320, 0x2321, prAL, gcSm}, // [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL + {0x2322, 0x2328, prAL, gcSo}, // [7] FROWN..KEYBOARD + {0x2329, 0x2329, prOP, gcPs}, // LEFT-POINTING ANGLE BRACKET + {0x232A, 0x232A, prCL, gcPe}, // RIGHT-POINTING ANGLE BRACKET + {0x232B, 0x237B, prAL, gcSo}, // [81] ERASE TO THE LEFT..NOT CHECK MARK + {0x237C, 0x237C, prAL, gcSm}, // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW + {0x237D, 0x239A, prAL, gcSo}, // [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL + {0x239B, 0x23B3, prAL, gcSm}, // [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM + {0x23B4, 0x23DB, prAL, gcSo}, // [40] TOP SQUARE BRACKET..FUSE + {0x23DC, 0x23E1, prAL, gcSm}, // [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET + {0x23E2, 0x23EF, prAL, gcSo}, // [14] WHITE TRAPEZIUM..BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR + {0x23F0, 0x23F3, prID, gcSo}, // [4] ALARM CLOCK..HOURGLASS WITH FLOWING SAND + {0x23F4, 0x23FF, prAL, gcSo}, // [12] BLACK MEDIUM LEFT-POINTING TRIANGLE..OBSERVER EYE SYMBOL + {0x2400, 0x2426, prAL, gcSo}, // [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO + {0x2440, 0x244A, prAL, gcSo}, // [11] OCR HOOK..OCR DOUBLE BACKSLASH + {0x2460, 0x249B, prAI, gcNo}, // [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP + {0x249C, 0x24E9, prAI, gcSo}, // [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z + {0x24EA, 0x24FE, prAI, gcNo}, // [21] CIRCLED DIGIT ZERO..DOUBLE CIRCLED NUMBER TEN + {0x24FF, 0x24FF, prAL, gcNo}, // NEGATIVE CIRCLED DIGIT ZERO + {0x2500, 0x254B, prAI, gcSo}, // [76] BOX DRAWINGS LIGHT HORIZONTAL..BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL + {0x254C, 0x254F, prAL, gcSo}, // [4] BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL..BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL + {0x2550, 0x2574, prAI, gcSo}, // [37] BOX DRAWINGS DOUBLE HORIZONTAL..BOX DRAWINGS LIGHT LEFT + {0x2575, 0x257F, prAL, gcSo}, // [11] BOX DRAWINGS LIGHT UP..BOX DRAWINGS HEAVY UP AND LIGHT DOWN + {0x2580, 0x258F, prAI, gcSo}, // [16] UPPER HALF BLOCK..LEFT ONE EIGHTH BLOCK + {0x2590, 0x2591, prAL, gcSo}, // [2] RIGHT HALF BLOCK..LIGHT SHADE + {0x2592, 0x2595, prAI, gcSo}, // [4] MEDIUM SHADE..RIGHT ONE EIGHTH BLOCK + {0x2596, 0x259F, prAL, gcSo}, // [10] QUADRANT LOWER LEFT..QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT + {0x25A0, 0x25A1, prAI, gcSo}, // [2] BLACK SQUARE..WHITE SQUARE + {0x25A2, 0x25A2, prAL, gcSo}, // WHITE SQUARE WITH ROUNDED CORNERS + {0x25A3, 0x25A9, prAI, gcSo}, // [7] WHITE SQUARE CONTAINING BLACK SMALL SQUARE..SQUARE WITH DIAGONAL CROSSHATCH FILL + {0x25AA, 0x25B1, prAL, gcSo}, // [8] BLACK SMALL SQUARE..WHITE PARALLELOGRAM + {0x25B2, 0x25B3, prAI, gcSo}, // [2] BLACK UP-POINTING TRIANGLE..WHITE UP-POINTING TRIANGLE + {0x25B4, 0x25B5, prAL, gcSo}, // [2] BLACK UP-POINTING SMALL TRIANGLE..WHITE UP-POINTING SMALL TRIANGLE + {0x25B6, 0x25B6, prAI, gcSo}, // BLACK RIGHT-POINTING TRIANGLE + {0x25B7, 0x25B7, prAI, gcSm}, // WHITE RIGHT-POINTING TRIANGLE + {0x25B8, 0x25BB, prAL, gcSo}, // [4] BLACK RIGHT-POINTING SMALL TRIANGLE..WHITE RIGHT-POINTING POINTER + {0x25BC, 0x25BD, prAI, gcSo}, // [2] BLACK DOWN-POINTING TRIANGLE..WHITE DOWN-POINTING TRIANGLE + {0x25BE, 0x25BF, prAL, gcSo}, // [2] BLACK DOWN-POINTING SMALL TRIANGLE..WHITE DOWN-POINTING SMALL TRIANGLE + {0x25C0, 0x25C0, prAI, gcSo}, // BLACK LEFT-POINTING TRIANGLE + {0x25C1, 0x25C1, prAI, gcSm}, // WHITE LEFT-POINTING TRIANGLE + {0x25C2, 0x25C5, prAL, gcSo}, // [4] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE LEFT-POINTING POINTER + {0x25C6, 0x25C8, prAI, gcSo}, // [3] BLACK DIAMOND..WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND + {0x25C9, 0x25CA, prAL, gcSo}, // [2] FISHEYE..LOZENGE + {0x25CB, 0x25CB, prAI, gcSo}, // WHITE CIRCLE + {0x25CC, 0x25CD, prAL, gcSo}, // [2] DOTTED CIRCLE..CIRCLE WITH VERTICAL FILL + {0x25CE, 0x25D1, prAI, gcSo}, // [4] BULLSEYE..CIRCLE WITH RIGHT HALF BLACK + {0x25D2, 0x25E1, prAL, gcSo}, // [16] CIRCLE WITH LOWER HALF BLACK..LOWER HALF CIRCLE + {0x25E2, 0x25E5, prAI, gcSo}, // [4] BLACK LOWER RIGHT TRIANGLE..BLACK UPPER RIGHT TRIANGLE + {0x25E6, 0x25EE, prAL, gcSo}, // [9] WHITE BULLET..UP-POINTING TRIANGLE WITH RIGHT HALF BLACK + {0x25EF, 0x25EF, prAI, gcSo}, // LARGE CIRCLE + {0x25F0, 0x25F7, prAL, gcSo}, // [8] WHITE SQUARE WITH UPPER LEFT QUADRANT..WHITE CIRCLE WITH UPPER RIGHT QUADRANT + {0x25F8, 0x25FF, prAL, gcSm}, // [8] UPPER LEFT TRIANGLE..LOWER RIGHT TRIANGLE + {0x2600, 0x2603, prID, gcSo}, // [4] BLACK SUN WITH RAYS..SNOWMAN + {0x2604, 0x2604, prAL, gcSo}, // COMET + {0x2605, 0x2606, prAI, gcSo}, // [2] BLACK STAR..WHITE STAR + {0x2607, 0x2608, prAL, gcSo}, // [2] LIGHTNING..THUNDERSTORM + {0x2609, 0x2609, prAI, gcSo}, // SUN + {0x260A, 0x260D, prAL, gcSo}, // [4] ASCENDING NODE..OPPOSITION + {0x260E, 0x260F, prAI, gcSo}, // [2] BLACK TELEPHONE..WHITE TELEPHONE + {0x2610, 0x2613, prAL, gcSo}, // [4] BALLOT BOX..SALTIRE + {0x2614, 0x2615, prID, gcSo}, // [2] UMBRELLA WITH RAIN DROPS..HOT BEVERAGE + {0x2616, 0x2617, prAI, gcSo}, // [2] WHITE SHOGI PIECE..BLACK SHOGI PIECE + {0x2618, 0x2618, prID, gcSo}, // SHAMROCK + {0x2619, 0x2619, prAL, gcSo}, // REVERSED ROTATED FLORAL HEART BULLET + {0x261A, 0x261C, prID, gcSo}, // [3] BLACK LEFT POINTING INDEX..WHITE LEFT POINTING INDEX + {0x261D, 0x261D, prEB, gcSo}, // WHITE UP POINTING INDEX + {0x261E, 0x261F, prID, gcSo}, // [2] WHITE RIGHT POINTING INDEX..WHITE DOWN POINTING INDEX + {0x2620, 0x2638, prAL, gcSo}, // [25] SKULL AND CROSSBONES..WHEEL OF DHARMA + {0x2639, 0x263B, prID, gcSo}, // [3] WHITE FROWNING FACE..BLACK SMILING FACE + {0x263C, 0x263F, prAL, gcSo}, // [4] WHITE SUN WITH RAYS..MERCURY + {0x2640, 0x2640, prAI, gcSo}, // FEMALE SIGN + {0x2641, 0x2641, prAL, gcSo}, // EARTH + {0x2642, 0x2642, prAI, gcSo}, // MALE SIGN + {0x2643, 0x265F, prAL, gcSo}, // [29] JUPITER..BLACK CHESS PAWN + {0x2660, 0x2661, prAI, gcSo}, // [2] BLACK SPADE SUIT..WHITE HEART SUIT + {0x2662, 0x2662, prAL, gcSo}, // WHITE DIAMOND SUIT + {0x2663, 0x2665, prAI, gcSo}, // [3] BLACK CLUB SUIT..BLACK HEART SUIT + {0x2666, 0x2666, prAL, gcSo}, // BLACK DIAMOND SUIT + {0x2667, 0x2667, prAI, gcSo}, // WHITE CLUB SUIT + {0x2668, 0x2668, prID, gcSo}, // HOT SPRINGS + {0x2669, 0x266A, prAI, gcSo}, // [2] QUARTER NOTE..EIGHTH NOTE + {0x266B, 0x266B, prAL, gcSo}, // BEAMED EIGHTH NOTES + {0x266C, 0x266D, prAI, gcSo}, // [2] BEAMED SIXTEENTH NOTES..MUSIC FLAT SIGN + {0x266E, 0x266E, prAL, gcSo}, // MUSIC NATURAL SIGN + {0x266F, 0x266F, prAI, gcSm}, // MUSIC SHARP SIGN + {0x2670, 0x267E, prAL, gcSo}, // [15] WEST SYRIAC CROSS..PERMANENT PAPER SIGN + {0x267F, 0x267F, prID, gcSo}, // WHEELCHAIR SYMBOL + {0x2680, 0x269D, prAL, gcSo}, // [30] DIE FACE-1..OUTLINED WHITE STAR + {0x269E, 0x269F, prAI, gcSo}, // [2] THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT + {0x26A0, 0x26BC, prAL, gcSo}, // [29] WARNING SIGN..SESQUIQUADRATE + {0x26BD, 0x26C8, prID, gcSo}, // [12] SOCCER BALL..THUNDER CLOUD AND RAIN + {0x26C9, 0x26CC, prAI, gcSo}, // [4] TURNED WHITE SHOGI PIECE..CROSSING LANES + {0x26CD, 0x26CD, prID, gcSo}, // DISABLED CAR + {0x26CE, 0x26CE, prAL, gcSo}, // OPHIUCHUS + {0x26CF, 0x26D1, prID, gcSo}, // [3] PICK..HELMET WITH WHITE CROSS + {0x26D2, 0x26D2, prAI, gcSo}, // CIRCLED CROSSING LANES + {0x26D3, 0x26D4, prID, gcSo}, // [2] CHAINS..NO ENTRY + {0x26D5, 0x26D7, prAI, gcSo}, // [3] ALTERNATE ONE-WAY LEFT WAY TRAFFIC..WHITE TWO-WAY LEFT WAY TRAFFIC + {0x26D8, 0x26D9, prID, gcSo}, // [2] BLACK LEFT LANE MERGE..WHITE LEFT LANE MERGE + {0x26DA, 0x26DB, prAI, gcSo}, // [2] DRIVE SLOW SIGN..HEAVY WHITE DOWN-POINTING TRIANGLE + {0x26DC, 0x26DC, prID, gcSo}, // LEFT CLOSED ENTRY + {0x26DD, 0x26DE, prAI, gcSo}, // [2] SQUARED SALTIRE..FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE + {0x26DF, 0x26E1, prID, gcSo}, // [3] BLACK TRUCK..RESTRICTED LEFT ENTRY-2 + {0x26E2, 0x26E2, prAL, gcSo}, // ASTRONOMICAL SYMBOL FOR URANUS + {0x26E3, 0x26E3, prAI, gcSo}, // HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE + {0x26E4, 0x26E7, prAL, gcSo}, // [4] PENTAGRAM..INVERTED PENTAGRAM + {0x26E8, 0x26E9, prAI, gcSo}, // [2] BLACK CROSS ON SHIELD..SHINTO SHRINE + {0x26EA, 0x26EA, prID, gcSo}, // CHURCH + {0x26EB, 0x26F0, prAI, gcSo}, // [6] CASTLE..MOUNTAIN + {0x26F1, 0x26F5, prID, gcSo}, // [5] UMBRELLA ON GROUND..SAILBOAT + {0x26F6, 0x26F6, prAI, gcSo}, // SQUARE FOUR CORNERS + {0x26F7, 0x26F8, prID, gcSo}, // [2] SKIER..ICE SKATE + {0x26F9, 0x26F9, prEB, gcSo}, // PERSON WITH BALL + {0x26FA, 0x26FA, prID, gcSo}, // TENT + {0x26FB, 0x26FC, prAI, gcSo}, // [2] JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL + {0x26FD, 0x26FF, prID, gcSo}, // [3] FUEL PUMP..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE + {0x2700, 0x2704, prID, gcSo}, // [5] BLACK SAFETY SCISSORS..WHITE SCISSORS + {0x2705, 0x2707, prAL, gcSo}, // [3] WHITE HEAVY CHECK MARK..TAPE DRIVE + {0x2708, 0x2709, prID, gcSo}, // [2] AIRPLANE..ENVELOPE + {0x270A, 0x270D, prEB, gcSo}, // [4] RAISED FIST..WRITING HAND + {0x270E, 0x2756, prAL, gcSo}, // [73] LOWER RIGHT PENCIL..BLACK DIAMOND MINUS WHITE X + {0x2757, 0x2757, prAI, gcSo}, // HEAVY EXCLAMATION MARK SYMBOL + {0x2758, 0x275A, prAL, gcSo}, // [3] LIGHT VERTICAL BAR..HEAVY VERTICAL BAR + {0x275B, 0x2760, prQU, gcSo}, // [6] HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT..HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT + {0x2761, 0x2761, prAL, gcSo}, // CURVED STEM PARAGRAPH SIGN ORNAMENT + {0x2762, 0x2763, prEX, gcSo}, // [2] HEAVY EXCLAMATION MARK ORNAMENT..HEAVY HEART EXCLAMATION MARK ORNAMENT + {0x2764, 0x2764, prID, gcSo}, // HEAVY BLACK HEART + {0x2765, 0x2767, prAL, gcSo}, // [3] ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET + {0x2768, 0x2768, prOP, gcPs}, // MEDIUM LEFT PARENTHESIS ORNAMENT + {0x2769, 0x2769, prCL, gcPe}, // MEDIUM RIGHT PARENTHESIS ORNAMENT + {0x276A, 0x276A, prOP, gcPs}, // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT + {0x276B, 0x276B, prCL, gcPe}, // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT + {0x276C, 0x276C, prOP, gcPs}, // MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT + {0x276D, 0x276D, prCL, gcPe}, // MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT + {0x276E, 0x276E, prOP, gcPs}, // HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT + {0x276F, 0x276F, prCL, gcPe}, // HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT + {0x2770, 0x2770, prOP, gcPs}, // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT + {0x2771, 0x2771, prCL, gcPe}, // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT + {0x2772, 0x2772, prOP, gcPs}, // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT + {0x2773, 0x2773, prCL, gcPe}, // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT + {0x2774, 0x2774, prOP, gcPs}, // MEDIUM LEFT CURLY BRACKET ORNAMENT + {0x2775, 0x2775, prCL, gcPe}, // MEDIUM RIGHT CURLY BRACKET ORNAMENT + {0x2776, 0x2793, prAI, gcNo}, // [30] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN + {0x2794, 0x27BF, prAL, gcSo}, // [44] HEAVY WIDE-HEADED RIGHTWARDS ARROW..DOUBLE CURLY LOOP + {0x27C0, 0x27C4, prAL, gcSm}, // [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET + {0x27C5, 0x27C5, prOP, gcPs}, // LEFT S-SHAPED BAG DELIMITER + {0x27C6, 0x27C6, prCL, gcPe}, // RIGHT S-SHAPED BAG DELIMITER + {0x27C7, 0x27E5, prAL, gcSm}, // [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK + {0x27E6, 0x27E6, prOP, gcPs}, // MATHEMATICAL LEFT WHITE SQUARE BRACKET + {0x27E7, 0x27E7, prCL, gcPe}, // MATHEMATICAL RIGHT WHITE SQUARE BRACKET + {0x27E8, 0x27E8, prOP, gcPs}, // MATHEMATICAL LEFT ANGLE BRACKET + {0x27E9, 0x27E9, prCL, gcPe}, // MATHEMATICAL RIGHT ANGLE BRACKET + {0x27EA, 0x27EA, prOP, gcPs}, // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET + {0x27EB, 0x27EB, prCL, gcPe}, // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET + {0x27EC, 0x27EC, prOP, gcPs}, // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET + {0x27ED, 0x27ED, prCL, gcPe}, // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET + {0x27EE, 0x27EE, prOP, gcPs}, // MATHEMATICAL LEFT FLATTENED PARENTHESIS + {0x27EF, 0x27EF, prCL, gcPe}, // MATHEMATICAL RIGHT FLATTENED PARENTHESIS + {0x27F0, 0x27FF, prAL, gcSm}, // [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW + {0x2800, 0x28FF, prAL, gcSo}, // [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678 + {0x2900, 0x297F, prAL, gcSm}, // [128] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..DOWN FISH TAIL + {0x2980, 0x2982, prAL, gcSm}, // [3] TRIPLE VERTICAL BAR DELIMITER..Z NOTATION TYPE COLON + {0x2983, 0x2983, prOP, gcPs}, // LEFT WHITE CURLY BRACKET + {0x2984, 0x2984, prCL, gcPe}, // RIGHT WHITE CURLY BRACKET + {0x2985, 0x2985, prOP, gcPs}, // LEFT WHITE PARENTHESIS + {0x2986, 0x2986, prCL, gcPe}, // RIGHT WHITE PARENTHESIS + {0x2987, 0x2987, prOP, gcPs}, // Z NOTATION LEFT IMAGE BRACKET + {0x2988, 0x2988, prCL, gcPe}, // Z NOTATION RIGHT IMAGE BRACKET + {0x2989, 0x2989, prOP, gcPs}, // Z NOTATION LEFT BINDING BRACKET + {0x298A, 0x298A, prCL, gcPe}, // Z NOTATION RIGHT BINDING BRACKET + {0x298B, 0x298B, prOP, gcPs}, // LEFT SQUARE BRACKET WITH UNDERBAR + {0x298C, 0x298C, prCL, gcPe}, // RIGHT SQUARE BRACKET WITH UNDERBAR + {0x298D, 0x298D, prOP, gcPs}, // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER + {0x298E, 0x298E, prCL, gcPe}, // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {0x298F, 0x298F, prOP, gcPs}, // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {0x2990, 0x2990, prCL, gcPe}, // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER + {0x2991, 0x2991, prOP, gcPs}, // LEFT ANGLE BRACKET WITH DOT + {0x2992, 0x2992, prCL, gcPe}, // RIGHT ANGLE BRACKET WITH DOT + {0x2993, 0x2993, prOP, gcPs}, // LEFT ARC LESS-THAN BRACKET + {0x2994, 0x2994, prCL, gcPe}, // RIGHT ARC GREATER-THAN BRACKET + {0x2995, 0x2995, prOP, gcPs}, // DOUBLE LEFT ARC GREATER-THAN BRACKET + {0x2996, 0x2996, prCL, gcPe}, // DOUBLE RIGHT ARC LESS-THAN BRACKET + {0x2997, 0x2997, prOP, gcPs}, // LEFT BLACK TORTOISE SHELL BRACKET + {0x2998, 0x2998, prCL, gcPe}, // RIGHT BLACK TORTOISE SHELL BRACKET + {0x2999, 0x29D7, prAL, gcSm}, // [63] DOTTED FENCE..BLACK HOURGLASS + {0x29D8, 0x29D8, prOP, gcPs}, // LEFT WIGGLY FENCE + {0x29D9, 0x29D9, prCL, gcPe}, // RIGHT WIGGLY FENCE + {0x29DA, 0x29DA, prOP, gcPs}, // LEFT DOUBLE WIGGLY FENCE + {0x29DB, 0x29DB, prCL, gcPe}, // RIGHT DOUBLE WIGGLY FENCE + {0x29DC, 0x29FB, prAL, gcSm}, // [32] INCOMPLETE INFINITY..TRIPLE PLUS + {0x29FC, 0x29FC, prOP, gcPs}, // LEFT-POINTING CURVED ANGLE BRACKET + {0x29FD, 0x29FD, prCL, gcPe}, // RIGHT-POINTING CURVED ANGLE BRACKET + {0x29FE, 0x29FF, prAL, gcSm}, // [2] TINY..MINY + {0x2A00, 0x2AFF, prAL, gcSm}, // [256] N-ARY CIRCLED DOT OPERATOR..N-ARY WHITE VERTICAL BAR + {0x2B00, 0x2B2F, prAL, gcSo}, // [48] NORTH EAST WHITE ARROW..WHITE VERTICAL ELLIPSE + {0x2B30, 0x2B44, prAL, gcSm}, // [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET + {0x2B45, 0x2B46, prAL, gcSo}, // [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW + {0x2B47, 0x2B4C, prAL, gcSm}, // [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR + {0x2B4D, 0x2B54, prAL, gcSo}, // [8] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..WHITE RIGHT-POINTING PENTAGON + {0x2B55, 0x2B59, prAI, gcSo}, // [5] HEAVY LARGE CIRCLE..HEAVY CIRCLED SALTIRE + {0x2B5A, 0x2B73, prAL, gcSo}, // [26] SLANTED NORTH ARROW WITH HOOKED HEAD..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR + {0x2B76, 0x2B95, prAL, gcSo}, // [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW + {0x2B97, 0x2BFF, prAL, gcSo}, // [105] SYMBOL FOR TYPE A ELECTRONICS..HELLSCHREIBER PAUSE SYMBOL + {0x2C00, 0x2C5F, prAL, gcLC}, // [96] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI + {0x2C60, 0x2C7B, prAL, gcLC}, // [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E + {0x2C7C, 0x2C7D, prAL, gcLm}, // [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V + {0x2C7E, 0x2C7F, prAL, gcLu}, // [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL + {0x2C80, 0x2CE4, prAL, gcLC}, // [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI + {0x2CE5, 0x2CEA, prAL, gcSo}, // [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA + {0x2CEB, 0x2CEE, prAL, gcLC}, // [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA + {0x2CEF, 0x2CF1, prCM, gcMn}, // [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS + {0x2CF2, 0x2CF3, prAL, gcLC}, // [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI + {0x2CF9, 0x2CF9, prEX, gcPo}, // COPTIC OLD NUBIAN FULL STOP + {0x2CFA, 0x2CFC, prBA, gcPo}, // [3] COPTIC OLD NUBIAN DIRECT QUESTION MARK..COPTIC OLD NUBIAN VERSE DIVIDER + {0x2CFD, 0x2CFD, prAL, gcNo}, // COPTIC FRACTION ONE HALF + {0x2CFE, 0x2CFE, prEX, gcPo}, // COPTIC FULL STOP + {0x2CFF, 0x2CFF, prBA, gcPo}, // COPTIC MORPHOLOGICAL DIVIDER + {0x2D00, 0x2D25, prAL, gcLl}, // [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE + {0x2D27, 0x2D27, prAL, gcLl}, // GEORGIAN SMALL LETTER YN + {0x2D2D, 0x2D2D, prAL, gcLl}, // GEORGIAN SMALL LETTER AEN + {0x2D30, 0x2D67, prAL, gcLo}, // [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO + {0x2D6F, 0x2D6F, prAL, gcLm}, // TIFINAGH MODIFIER LETTER LABIALIZATION MARK + {0x2D70, 0x2D70, prBA, gcPo}, // TIFINAGH SEPARATOR MARK + {0x2D7F, 0x2D7F, prCM, gcMn}, // TIFINAGH CONSONANT JOINER + {0x2D80, 0x2D96, prAL, gcLo}, // [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE + {0x2DA0, 0x2DA6, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO + {0x2DA8, 0x2DAE, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO + {0x2DB0, 0x2DB6, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO + {0x2DB8, 0x2DBE, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO + {0x2DC0, 0x2DC6, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO + {0x2DC8, 0x2DCE, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO + {0x2DD0, 0x2DD6, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO + {0x2DD8, 0x2DDE, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO + {0x2DE0, 0x2DFF, prCM, gcMn}, // [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS + {0x2E00, 0x2E01, prQU, gcPo}, // [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER + {0x2E02, 0x2E02, prQU, gcPi}, // LEFT SUBSTITUTION BRACKET + {0x2E03, 0x2E03, prQU, gcPf}, // RIGHT SUBSTITUTION BRACKET + {0x2E04, 0x2E04, prQU, gcPi}, // LEFT DOTTED SUBSTITUTION BRACKET + {0x2E05, 0x2E05, prQU, gcPf}, // RIGHT DOTTED SUBSTITUTION BRACKET + {0x2E06, 0x2E08, prQU, gcPo}, // [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER + {0x2E09, 0x2E09, prQU, gcPi}, // LEFT TRANSPOSITION BRACKET + {0x2E0A, 0x2E0A, prQU, gcPf}, // RIGHT TRANSPOSITION BRACKET + {0x2E0B, 0x2E0B, prQU, gcPo}, // RAISED SQUARE + {0x2E0C, 0x2E0C, prQU, gcPi}, // LEFT RAISED OMISSION BRACKET + {0x2E0D, 0x2E0D, prQU, gcPf}, // RIGHT RAISED OMISSION BRACKET + {0x2E0E, 0x2E15, prBA, gcPo}, // [8] EDITORIAL CORONIS..UPWARDS ANCORA + {0x2E16, 0x2E16, prAL, gcPo}, // DOTTED RIGHT-POINTING ANGLE + {0x2E17, 0x2E17, prBA, gcPd}, // DOUBLE OBLIQUE HYPHEN + {0x2E18, 0x2E18, prOP, gcPo}, // INVERTED INTERROBANG + {0x2E19, 0x2E19, prBA, gcPo}, // PALM BRANCH + {0x2E1A, 0x2E1A, prAL, gcPd}, // HYPHEN WITH DIAERESIS + {0x2E1B, 0x2E1B, prAL, gcPo}, // TILDE WITH RING ABOVE + {0x2E1C, 0x2E1C, prQU, gcPi}, // LEFT LOW PARAPHRASE BRACKET + {0x2E1D, 0x2E1D, prQU, gcPf}, // RIGHT LOW PARAPHRASE BRACKET + {0x2E1E, 0x2E1F, prAL, gcPo}, // [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW + {0x2E20, 0x2E20, prQU, gcPi}, // LEFT VERTICAL BAR WITH QUILL + {0x2E21, 0x2E21, prQU, gcPf}, // RIGHT VERTICAL BAR WITH QUILL + {0x2E22, 0x2E22, prOP, gcPs}, // TOP LEFT HALF BRACKET + {0x2E23, 0x2E23, prCL, gcPe}, // TOP RIGHT HALF BRACKET + {0x2E24, 0x2E24, prOP, gcPs}, // BOTTOM LEFT HALF BRACKET + {0x2E25, 0x2E25, prCL, gcPe}, // BOTTOM RIGHT HALF BRACKET + {0x2E26, 0x2E26, prOP, gcPs}, // LEFT SIDEWAYS U BRACKET + {0x2E27, 0x2E27, prCL, gcPe}, // RIGHT SIDEWAYS U BRACKET + {0x2E28, 0x2E28, prOP, gcPs}, // LEFT DOUBLE PARENTHESIS + {0x2E29, 0x2E29, prCL, gcPe}, // RIGHT DOUBLE PARENTHESIS + {0x2E2A, 0x2E2D, prBA, gcPo}, // [4] TWO DOTS OVER ONE DOT PUNCTUATION..FIVE DOT MARK + {0x2E2E, 0x2E2E, prEX, gcPo}, // REVERSED QUESTION MARK + {0x2E2F, 0x2E2F, prAL, gcLm}, // VERTICAL TILDE + {0x2E30, 0x2E31, prBA, gcPo}, // [2] RING POINT..WORD SEPARATOR MIDDLE DOT + {0x2E32, 0x2E32, prAL, gcPo}, // TURNED COMMA + {0x2E33, 0x2E34, prBA, gcPo}, // [2] RAISED DOT..RAISED COMMA + {0x2E35, 0x2E39, prAL, gcPo}, // [5] TURNED SEMICOLON..TOP HALF SECTION SIGN + {0x2E3A, 0x2E3B, prB2, gcPd}, // [2] TWO-EM DASH..THREE-EM DASH + {0x2E3C, 0x2E3E, prBA, gcPo}, // [3] STENOGRAPHIC FULL STOP..WIGGLY VERTICAL LINE + {0x2E3F, 0x2E3F, prAL, gcPo}, // CAPITULUM + {0x2E40, 0x2E40, prBA, gcPd}, // DOUBLE HYPHEN + {0x2E41, 0x2E41, prBA, gcPo}, // REVERSED COMMA + {0x2E42, 0x2E42, prOP, gcPs}, // DOUBLE LOW-REVERSED-9 QUOTATION MARK + {0x2E43, 0x2E4A, prBA, gcPo}, // [8] DASH WITH LEFT UPTURN..DOTTED SOLIDUS + {0x2E4B, 0x2E4B, prAL, gcPo}, // TRIPLE DAGGER + {0x2E4C, 0x2E4C, prBA, gcPo}, // MEDIEVAL COMMA + {0x2E4D, 0x2E4D, prAL, gcPo}, // PARAGRAPHUS MARK + {0x2E4E, 0x2E4F, prBA, gcPo}, // [2] PUNCTUS ELEVATUS MARK..CORNISH VERSE DIVIDER + {0x2E50, 0x2E51, prAL, gcSo}, // [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR + {0x2E52, 0x2E52, prAL, gcPo}, // TIRONIAN SIGN CAPITAL ET + {0x2E53, 0x2E54, prEX, gcPo}, // [2] MEDIEVAL EXCLAMATION MARK..MEDIEVAL QUESTION MARK + {0x2E55, 0x2E55, prOP, gcPs}, // LEFT SQUARE BRACKET WITH STROKE + {0x2E56, 0x2E56, prCL, gcPe}, // RIGHT SQUARE BRACKET WITH STROKE + {0x2E57, 0x2E57, prOP, gcPs}, // LEFT SQUARE BRACKET WITH DOUBLE STROKE + {0x2E58, 0x2E58, prCL, gcPe}, // RIGHT SQUARE BRACKET WITH DOUBLE STROKE + {0x2E59, 0x2E59, prOP, gcPs}, // TOP HALF LEFT PARENTHESIS + {0x2E5A, 0x2E5A, prCL, gcPe}, // TOP HALF RIGHT PARENTHESIS + {0x2E5B, 0x2E5B, prOP, gcPs}, // BOTTOM HALF LEFT PARENTHESIS + {0x2E5C, 0x2E5C, prCL, gcPe}, // BOTTOM HALF RIGHT PARENTHESIS + {0x2E5D, 0x2E5D, prBA, gcPd}, // OBLIQUE HYPHEN + {0x2E80, 0x2E99, prID, gcSo}, // [26] CJK RADICAL REPEAT..CJK RADICAL RAP + {0x2E9B, 0x2EF3, prID, gcSo}, // [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE + {0x2F00, 0x2FD5, prID, gcSo}, // [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE + {0x2FF0, 0x2FFB, prID, gcSo}, // [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID + {0x3000, 0x3000, prBA, gcZs}, // IDEOGRAPHIC SPACE + {0x3001, 0x3002, prCL, gcPo}, // [2] IDEOGRAPHIC COMMA..IDEOGRAPHIC FULL STOP + {0x3003, 0x3003, prID, gcPo}, // DITTO MARK + {0x3004, 0x3004, prID, gcSo}, // JAPANESE INDUSTRIAL STANDARD SYMBOL + {0x3005, 0x3005, prNS, gcLm}, // IDEOGRAPHIC ITERATION MARK + {0x3006, 0x3006, prID, gcLo}, // IDEOGRAPHIC CLOSING MARK + {0x3007, 0x3007, prID, gcNl}, // IDEOGRAPHIC NUMBER ZERO + {0x3008, 0x3008, prOP, gcPs}, // LEFT ANGLE BRACKET + {0x3009, 0x3009, prCL, gcPe}, // RIGHT ANGLE BRACKET + {0x300A, 0x300A, prOP, gcPs}, // LEFT DOUBLE ANGLE BRACKET + {0x300B, 0x300B, prCL, gcPe}, // RIGHT DOUBLE ANGLE BRACKET + {0x300C, 0x300C, prOP, gcPs}, // LEFT CORNER BRACKET + {0x300D, 0x300D, prCL, gcPe}, // RIGHT CORNER BRACKET + {0x300E, 0x300E, prOP, gcPs}, // LEFT WHITE CORNER BRACKET + {0x300F, 0x300F, prCL, gcPe}, // RIGHT WHITE CORNER BRACKET + {0x3010, 0x3010, prOP, gcPs}, // LEFT BLACK LENTICULAR BRACKET + {0x3011, 0x3011, prCL, gcPe}, // RIGHT BLACK LENTICULAR BRACKET + {0x3012, 0x3013, prID, gcSo}, // [2] POSTAL MARK..GETA MARK + {0x3014, 0x3014, prOP, gcPs}, // LEFT TORTOISE SHELL BRACKET + {0x3015, 0x3015, prCL, gcPe}, // RIGHT TORTOISE SHELL BRACKET + {0x3016, 0x3016, prOP, gcPs}, // LEFT WHITE LENTICULAR BRACKET + {0x3017, 0x3017, prCL, gcPe}, // RIGHT WHITE LENTICULAR BRACKET + {0x3018, 0x3018, prOP, gcPs}, // LEFT WHITE TORTOISE SHELL BRACKET + {0x3019, 0x3019, prCL, gcPe}, // RIGHT WHITE TORTOISE SHELL BRACKET + {0x301A, 0x301A, prOP, gcPs}, // LEFT WHITE SQUARE BRACKET + {0x301B, 0x301B, prCL, gcPe}, // RIGHT WHITE SQUARE BRACKET + {0x301C, 0x301C, prNS, gcPd}, // WAVE DASH + {0x301D, 0x301D, prOP, gcPs}, // REVERSED DOUBLE PRIME QUOTATION MARK + {0x301E, 0x301F, prCL, gcPe}, // [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK + {0x3020, 0x3020, prID, gcSo}, // POSTAL MARK FACE + {0x3021, 0x3029, prID, gcNl}, // [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE + {0x302A, 0x302D, prCM, gcMn}, // [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK + {0x302E, 0x302F, prCM, gcMc}, // [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK + {0x3030, 0x3030, prID, gcPd}, // WAVY DASH + {0x3031, 0x3034, prID, gcLm}, // [4] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF + {0x3035, 0x3035, prCM, gcLm}, // VERTICAL KANA REPEAT MARK LOWER HALF + {0x3036, 0x3037, prID, gcSo}, // [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL + {0x3038, 0x303A, prID, gcNl}, // [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY + {0x303B, 0x303B, prNS, gcLm}, // VERTICAL IDEOGRAPHIC ITERATION MARK + {0x303C, 0x303C, prNS, gcLo}, // MASU MARK + {0x303D, 0x303D, prID, gcPo}, // PART ALTERNATION MARK + {0x303E, 0x303F, prID, gcSo}, // [2] IDEOGRAPHIC VARIATION INDICATOR..IDEOGRAPHIC HALF FILL SPACE + {0x3041, 0x3041, prCJ, gcLo}, // HIRAGANA LETTER SMALL A + {0x3042, 0x3042, prID, gcLo}, // HIRAGANA LETTER A + {0x3043, 0x3043, prCJ, gcLo}, // HIRAGANA LETTER SMALL I + {0x3044, 0x3044, prID, gcLo}, // HIRAGANA LETTER I + {0x3045, 0x3045, prCJ, gcLo}, // HIRAGANA LETTER SMALL U + {0x3046, 0x3046, prID, gcLo}, // HIRAGANA LETTER U + {0x3047, 0x3047, prCJ, gcLo}, // HIRAGANA LETTER SMALL E + {0x3048, 0x3048, prID, gcLo}, // HIRAGANA LETTER E + {0x3049, 0x3049, prCJ, gcLo}, // HIRAGANA LETTER SMALL O + {0x304A, 0x3062, prID, gcLo}, // [25] HIRAGANA LETTER O..HIRAGANA LETTER DI + {0x3063, 0x3063, prCJ, gcLo}, // HIRAGANA LETTER SMALL TU + {0x3064, 0x3082, prID, gcLo}, // [31] HIRAGANA LETTER TU..HIRAGANA LETTER MO + {0x3083, 0x3083, prCJ, gcLo}, // HIRAGANA LETTER SMALL YA + {0x3084, 0x3084, prID, gcLo}, // HIRAGANA LETTER YA + {0x3085, 0x3085, prCJ, gcLo}, // HIRAGANA LETTER SMALL YU + {0x3086, 0x3086, prID, gcLo}, // HIRAGANA LETTER YU + {0x3087, 0x3087, prCJ, gcLo}, // HIRAGANA LETTER SMALL YO + {0x3088, 0x308D, prID, gcLo}, // [6] HIRAGANA LETTER YO..HIRAGANA LETTER RO + {0x308E, 0x308E, prCJ, gcLo}, // HIRAGANA LETTER SMALL WA + {0x308F, 0x3094, prID, gcLo}, // [6] HIRAGANA LETTER WA..HIRAGANA LETTER VU + {0x3095, 0x3096, prCJ, gcLo}, // [2] HIRAGANA LETTER SMALL KA..HIRAGANA LETTER SMALL KE + {0x3099, 0x309A, prCM, gcMn}, // [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x309B, 0x309C, prNS, gcSk}, // [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x309D, 0x309E, prNS, gcLm}, // [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK + {0x309F, 0x309F, prID, gcLo}, // HIRAGANA DIGRAPH YORI + {0x30A0, 0x30A0, prNS, gcPd}, // KATAKANA-HIRAGANA DOUBLE HYPHEN + {0x30A1, 0x30A1, prCJ, gcLo}, // KATAKANA LETTER SMALL A + {0x30A2, 0x30A2, prID, gcLo}, // KATAKANA LETTER A + {0x30A3, 0x30A3, prCJ, gcLo}, // KATAKANA LETTER SMALL I + {0x30A4, 0x30A4, prID, gcLo}, // KATAKANA LETTER I + {0x30A5, 0x30A5, prCJ, gcLo}, // KATAKANA LETTER SMALL U + {0x30A6, 0x30A6, prID, gcLo}, // KATAKANA LETTER U + {0x30A7, 0x30A7, prCJ, gcLo}, // KATAKANA LETTER SMALL E + {0x30A8, 0x30A8, prID, gcLo}, // KATAKANA LETTER E + {0x30A9, 0x30A9, prCJ, gcLo}, // KATAKANA LETTER SMALL O + {0x30AA, 0x30C2, prID, gcLo}, // [25] KATAKANA LETTER O..KATAKANA LETTER DI + {0x30C3, 0x30C3, prCJ, gcLo}, // KATAKANA LETTER SMALL TU + {0x30C4, 0x30E2, prID, gcLo}, // [31] KATAKANA LETTER TU..KATAKANA LETTER MO + {0x30E3, 0x30E3, prCJ, gcLo}, // KATAKANA LETTER SMALL YA + {0x30E4, 0x30E4, prID, gcLo}, // KATAKANA LETTER YA + {0x30E5, 0x30E5, prCJ, gcLo}, // KATAKANA LETTER SMALL YU + {0x30E6, 0x30E6, prID, gcLo}, // KATAKANA LETTER YU + {0x30E7, 0x30E7, prCJ, gcLo}, // KATAKANA LETTER SMALL YO + {0x30E8, 0x30ED, prID, gcLo}, // [6] KATAKANA LETTER YO..KATAKANA LETTER RO + {0x30EE, 0x30EE, prCJ, gcLo}, // KATAKANA LETTER SMALL WA + {0x30EF, 0x30F4, prID, gcLo}, // [6] KATAKANA LETTER WA..KATAKANA LETTER VU + {0x30F5, 0x30F6, prCJ, gcLo}, // [2] KATAKANA LETTER SMALL KA..KATAKANA LETTER SMALL KE + {0x30F7, 0x30FA, prID, gcLo}, // [4] KATAKANA LETTER VA..KATAKANA LETTER VO + {0x30FB, 0x30FB, prNS, gcPo}, // KATAKANA MIDDLE DOT + {0x30FC, 0x30FC, prCJ, gcLm}, // KATAKANA-HIRAGANA PROLONGED SOUND MARK + {0x30FD, 0x30FE, prNS, gcLm}, // [2] KATAKANA ITERATION MARK..KATAKANA VOICED ITERATION MARK + {0x30FF, 0x30FF, prID, gcLo}, // KATAKANA DIGRAPH KOTO + {0x3105, 0x312F, prID, gcLo}, // [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN + {0x3131, 0x318E, prID, gcLo}, // [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE + {0x3190, 0x3191, prID, gcSo}, // [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK + {0x3192, 0x3195, prID, gcNo}, // [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK + {0x3196, 0x319F, prID, gcSo}, // [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK + {0x31A0, 0x31BF, prID, gcLo}, // [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH + {0x31C0, 0x31E3, prID, gcSo}, // [36] CJK STROKE T..CJK STROKE Q + {0x31F0, 0x31FF, prCJ, gcLo}, // [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO + {0x3200, 0x321E, prID, gcSo}, // [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU + {0x3220, 0x3229, prID, gcNo}, // [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN + {0x322A, 0x3247, prID, gcSo}, // [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO + {0x3248, 0x324F, prAI, gcNo}, // [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE + {0x3250, 0x3250, prID, gcSo}, // PARTNERSHIP SIGN + {0x3251, 0x325F, prID, gcNo}, // [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE + {0x3260, 0x327F, prID, gcSo}, // [32] CIRCLED HANGUL KIYEOK..KOREAN STANDARD SYMBOL + {0x3280, 0x3289, prID, gcNo}, // [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN + {0x328A, 0x32B0, prID, gcSo}, // [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT + {0x32B1, 0x32BF, prID, gcNo}, // [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY + {0x32C0, 0x32FF, prID, gcSo}, // [64] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..SQUARE ERA NAME REIWA + {0x3300, 0x33FF, prID, gcSo}, // [256] SQUARE APAATO..SQUARE GAL + {0x3400, 0x4DBF, prID, gcLo}, // [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF + {0x4DC0, 0x4DFF, prAL, gcSo}, // [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION + {0x4E00, 0x9FFF, prID, gcLo}, // [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF + {0xA000, 0xA014, prID, gcLo}, // [21] YI SYLLABLE IT..YI SYLLABLE E + {0xA015, 0xA015, prNS, gcLm}, // YI SYLLABLE WU + {0xA016, 0xA48C, prID, gcLo}, // [1143] YI SYLLABLE BIT..YI SYLLABLE YYR + {0xA490, 0xA4C6, prID, gcSo}, // [55] YI RADICAL QOT..YI RADICAL KE + {0xA4D0, 0xA4F7, prAL, gcLo}, // [40] LISU LETTER BA..LISU LETTER OE + {0xA4F8, 0xA4FD, prAL, gcLm}, // [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU + {0xA4FE, 0xA4FF, prBA, gcPo}, // [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP + {0xA500, 0xA60B, prAL, gcLo}, // [268] VAI SYLLABLE EE..VAI SYLLABLE NG + {0xA60C, 0xA60C, prAL, gcLm}, // VAI SYLLABLE LENGTHENER + {0xA60D, 0xA60D, prBA, gcPo}, // VAI COMMA + {0xA60E, 0xA60E, prEX, gcPo}, // VAI FULL STOP + {0xA60F, 0xA60F, prBA, gcPo}, // VAI QUESTION MARK + {0xA610, 0xA61F, prAL, gcLo}, // [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG + {0xA620, 0xA629, prNU, gcNd}, // [10] VAI DIGIT ZERO..VAI DIGIT NINE + {0xA62A, 0xA62B, prAL, gcLo}, // [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO + {0xA640, 0xA66D, prAL, gcLC}, // [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O + {0xA66E, 0xA66E, prAL, gcLo}, // CYRILLIC LETTER MULTIOCULAR O + {0xA66F, 0xA66F, prCM, gcMn}, // COMBINING CYRILLIC VZMET + {0xA670, 0xA672, prCM, gcMe}, // [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN + {0xA673, 0xA673, prAL, gcPo}, // SLAVONIC ASTERISK + {0xA674, 0xA67D, prCM, gcMn}, // [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK + {0xA67E, 0xA67E, prAL, gcPo}, // CYRILLIC KAVYKA + {0xA67F, 0xA67F, prAL, gcLm}, // CYRILLIC PAYEROK + {0xA680, 0xA69B, prAL, gcLC}, // [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O + {0xA69C, 0xA69D, prAL, gcLm}, // [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN + {0xA69E, 0xA69F, prCM, gcMn}, // [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E + {0xA6A0, 0xA6E5, prAL, gcLo}, // [70] BAMUM LETTER A..BAMUM LETTER KI + {0xA6E6, 0xA6EF, prAL, gcNl}, // [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM + {0xA6F0, 0xA6F1, prCM, gcMn}, // [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS + {0xA6F2, 0xA6F2, prAL, gcPo}, // BAMUM NJAEMLI + {0xA6F3, 0xA6F7, prBA, gcPo}, // [5] BAMUM FULL STOP..BAMUM QUESTION MARK + {0xA700, 0xA716, prAL, gcSk}, // [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR + {0xA717, 0xA71F, prAL, gcLm}, // [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK + {0xA720, 0xA721, prAL, gcSk}, // [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE + {0xA722, 0xA76F, prAL, gcLC}, // [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON + {0xA770, 0xA770, prAL, gcLm}, // MODIFIER LETTER US + {0xA771, 0xA787, prAL, gcLC}, // [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T + {0xA788, 0xA788, prAL, gcLm}, // MODIFIER LETTER LOW CIRCUMFLEX ACCENT + {0xA789, 0xA78A, prAL, gcSk}, // [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN + {0xA78B, 0xA78E, prAL, gcLC}, // [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT + {0xA78F, 0xA78F, prAL, gcLo}, // LATIN LETTER SINOLOGICAL DOT + {0xA790, 0xA7CA, prAL, gcLC}, // [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY + {0xA7D0, 0xA7D1, prAL, gcLC}, // [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G + {0xA7D3, 0xA7D3, prAL, gcLl}, // LATIN SMALL LETTER DOUBLE THORN + {0xA7D5, 0xA7D9, prAL, gcLC}, // [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S + {0xA7F2, 0xA7F4, prAL, gcLm}, // [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q + {0xA7F5, 0xA7F6, prAL, gcLC}, // [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H + {0xA7F7, 0xA7F7, prAL, gcLo}, // LATIN EPIGRAPHIC LETTER SIDEWAYS I + {0xA7F8, 0xA7F9, prAL, gcLm}, // [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE + {0xA7FA, 0xA7FA, prAL, gcLl}, // LATIN LETTER SMALL CAPITAL TURNED M + {0xA7FB, 0xA7FF, prAL, gcLo}, // [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M + {0xA800, 0xA801, prAL, gcLo}, // [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I + {0xA802, 0xA802, prCM, gcMn}, // SYLOTI NAGRI SIGN DVISVARA + {0xA803, 0xA805, prAL, gcLo}, // [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O + {0xA806, 0xA806, prCM, gcMn}, // SYLOTI NAGRI SIGN HASANTA + {0xA807, 0xA80A, prAL, gcLo}, // [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO + {0xA80B, 0xA80B, prCM, gcMn}, // SYLOTI NAGRI SIGN ANUSVARA + {0xA80C, 0xA822, prAL, gcLo}, // [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO + {0xA823, 0xA824, prCM, gcMc}, // [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I + {0xA825, 0xA826, prCM, gcMn}, // [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E + {0xA827, 0xA827, prCM, gcMc}, // SYLOTI NAGRI VOWEL SIGN OO + {0xA828, 0xA82B, prAL, gcSo}, // [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4 + {0xA82C, 0xA82C, prCM, gcMn}, // SYLOTI NAGRI SIGN ALTERNATE HASANTA + {0xA830, 0xA835, prAL, gcNo}, // [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS + {0xA836, 0xA837, prAL, gcSo}, // [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK + {0xA838, 0xA838, prPO, gcSc}, // NORTH INDIC RUPEE MARK + {0xA839, 0xA839, prAL, gcSo}, // NORTH INDIC QUANTITY MARK + {0xA840, 0xA873, prAL, gcLo}, // [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU + {0xA874, 0xA875, prBB, gcPo}, // [2] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA DOUBLE HEAD MARK + {0xA876, 0xA877, prEX, gcPo}, // [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD + {0xA880, 0xA881, prCM, gcMc}, // [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA + {0xA882, 0xA8B3, prAL, gcLo}, // [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA + {0xA8B4, 0xA8C3, prCM, gcMc}, // [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU + {0xA8C4, 0xA8C5, prCM, gcMn}, // [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU + {0xA8CE, 0xA8CF, prBA, gcPo}, // [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA + {0xA8D0, 0xA8D9, prNU, gcNd}, // [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE + {0xA8E0, 0xA8F1, prCM, gcMn}, // [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA + {0xA8F2, 0xA8F7, prAL, gcLo}, // [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA + {0xA8F8, 0xA8FA, prAL, gcPo}, // [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET + {0xA8FB, 0xA8FB, prAL, gcLo}, // DEVANAGARI HEADSTROKE + {0xA8FC, 0xA8FC, prBB, gcPo}, // DEVANAGARI SIGN SIDDHAM + {0xA8FD, 0xA8FE, prAL, gcLo}, // [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY + {0xA8FF, 0xA8FF, prCM, gcMn}, // DEVANAGARI VOWEL SIGN AY + {0xA900, 0xA909, prNU, gcNd}, // [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE + {0xA90A, 0xA925, prAL, gcLo}, // [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO + {0xA926, 0xA92D, prCM, gcMn}, // [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU + {0xA92E, 0xA92F, prBA, gcPo}, // [2] KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA + {0xA930, 0xA946, prAL, gcLo}, // [23] REJANG LETTER KA..REJANG LETTER A + {0xA947, 0xA951, prCM, gcMn}, // [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R + {0xA952, 0xA953, prCM, gcMc}, // [2] REJANG CONSONANT SIGN H..REJANG VIRAMA + {0xA95F, 0xA95F, prAL, gcPo}, // REJANG SECTION MARK + {0xA960, 0xA97C, prJL, gcLo}, // [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH + {0xA980, 0xA982, prCM, gcMn}, // [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR + {0xA983, 0xA983, prCM, gcMc}, // JAVANESE SIGN WIGNYAN + {0xA984, 0xA9B2, prAL, gcLo}, // [47] JAVANESE LETTER A..JAVANESE LETTER HA + {0xA9B3, 0xA9B3, prCM, gcMn}, // JAVANESE SIGN CECAK TELU + {0xA9B4, 0xA9B5, prCM, gcMc}, // [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG + {0xA9B6, 0xA9B9, prCM, gcMn}, // [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT + {0xA9BA, 0xA9BB, prCM, gcMc}, // [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE + {0xA9BC, 0xA9BD, prCM, gcMn}, // [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET + {0xA9BE, 0xA9C0, prCM, gcMc}, // [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON + {0xA9C1, 0xA9C6, prAL, gcPo}, // [6] JAVANESE LEFT RERENGGAN..JAVANESE PADA WINDU + {0xA9C7, 0xA9C9, prBA, gcPo}, // [3] JAVANESE PADA PANGKAT..JAVANESE PADA LUNGSI + {0xA9CA, 0xA9CD, prAL, gcPo}, // [4] JAVANESE PADA ADEG..JAVANESE TURNED PADA PISELEH + {0xA9CF, 0xA9CF, prAL, gcLm}, // JAVANESE PANGRANGKEP + {0xA9D0, 0xA9D9, prNU, gcNd}, // [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE + {0xA9DE, 0xA9DF, prAL, gcPo}, // [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN + {0xA9E0, 0xA9E4, prSA, gcLo}, // [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA + {0xA9E5, 0xA9E5, prSA, gcMn}, // MYANMAR SIGN SHAN SAW + {0xA9E6, 0xA9E6, prSA, gcLm}, // MYANMAR MODIFIER LETTER SHAN REDUPLICATION + {0xA9E7, 0xA9EF, prSA, gcLo}, // [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA + {0xA9F0, 0xA9F9, prNU, gcNd}, // [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE + {0xA9FA, 0xA9FE, prSA, gcLo}, // [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA + {0xAA00, 0xAA28, prAL, gcLo}, // [41] CHAM LETTER A..CHAM LETTER HA + {0xAA29, 0xAA2E, prCM, gcMn}, // [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE + {0xAA2F, 0xAA30, prCM, gcMc}, // [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI + {0xAA31, 0xAA32, prCM, gcMn}, // [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE + {0xAA33, 0xAA34, prCM, gcMc}, // [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA + {0xAA35, 0xAA36, prCM, gcMn}, // [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA + {0xAA40, 0xAA42, prAL, gcLo}, // [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG + {0xAA43, 0xAA43, prCM, gcMn}, // CHAM CONSONANT SIGN FINAL NG + {0xAA44, 0xAA4B, prAL, gcLo}, // [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS + {0xAA4C, 0xAA4C, prCM, gcMn}, // CHAM CONSONANT SIGN FINAL M + {0xAA4D, 0xAA4D, prCM, gcMc}, // CHAM CONSONANT SIGN FINAL H + {0xAA50, 0xAA59, prNU, gcNd}, // [10] CHAM DIGIT ZERO..CHAM DIGIT NINE + {0xAA5C, 0xAA5C, prAL, gcPo}, // CHAM PUNCTUATION SPIRAL + {0xAA5D, 0xAA5F, prBA, gcPo}, // [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA + {0xAA60, 0xAA6F, prSA, gcLo}, // [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA + {0xAA70, 0xAA70, prSA, gcLm}, // MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION + {0xAA71, 0xAA76, prSA, gcLo}, // [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM + {0xAA77, 0xAA79, prSA, gcSo}, // [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO + {0xAA7A, 0xAA7A, prSA, gcLo}, // MYANMAR LETTER AITON RA + {0xAA7B, 0xAA7B, prSA, gcMc}, // MYANMAR SIGN PAO KAREN TONE + {0xAA7C, 0xAA7C, prSA, gcMn}, // MYANMAR SIGN TAI LAING TONE-2 + {0xAA7D, 0xAA7D, prSA, gcMc}, // MYANMAR SIGN TAI LAING TONE-5 + {0xAA7E, 0xAA7F, prSA, gcLo}, // [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA + {0xAA80, 0xAAAF, prSA, gcLo}, // [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O + {0xAAB0, 0xAAB0, prSA, gcMn}, // TAI VIET MAI KANG + {0xAAB1, 0xAAB1, prSA, gcLo}, // TAI VIET VOWEL AA + {0xAAB2, 0xAAB4, prSA, gcMn}, // [3] TAI VIET VOWEL I..TAI VIET VOWEL U + {0xAAB5, 0xAAB6, prSA, gcLo}, // [2] TAI VIET VOWEL E..TAI VIET VOWEL O + {0xAAB7, 0xAAB8, prSA, gcMn}, // [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA + {0xAAB9, 0xAABD, prSA, gcLo}, // [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN + {0xAABE, 0xAABF, prSA, gcMn}, // [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK + {0xAAC0, 0xAAC0, prSA, gcLo}, // TAI VIET TONE MAI NUENG + {0xAAC1, 0xAAC1, prSA, gcMn}, // TAI VIET TONE MAI THO + {0xAAC2, 0xAAC2, prSA, gcLo}, // TAI VIET TONE MAI SONG + {0xAADB, 0xAADC, prSA, gcLo}, // [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG + {0xAADD, 0xAADD, prSA, gcLm}, // TAI VIET SYMBOL SAM + {0xAADE, 0xAADF, prSA, gcPo}, // [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI + {0xAAE0, 0xAAEA, prAL, gcLo}, // [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA + {0xAAEB, 0xAAEB, prCM, gcMc}, // MEETEI MAYEK VOWEL SIGN II + {0xAAEC, 0xAAED, prCM, gcMn}, // [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI + {0xAAEE, 0xAAEF, prCM, gcMc}, // [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU + {0xAAF0, 0xAAF1, prBA, gcPo}, // [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM + {0xAAF2, 0xAAF2, prAL, gcLo}, // MEETEI MAYEK ANJI + {0xAAF3, 0xAAF4, prAL, gcLm}, // [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK + {0xAAF5, 0xAAF5, prCM, gcMc}, // MEETEI MAYEK VOWEL SIGN VISARGA + {0xAAF6, 0xAAF6, prCM, gcMn}, // MEETEI MAYEK VIRAMA + {0xAB01, 0xAB06, prAL, gcLo}, // [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO + {0xAB09, 0xAB0E, prAL, gcLo}, // [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO + {0xAB11, 0xAB16, prAL, gcLo}, // [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO + {0xAB20, 0xAB26, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO + {0xAB28, 0xAB2E, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO + {0xAB30, 0xAB5A, prAL, gcLl}, // [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG + {0xAB5B, 0xAB5B, prAL, gcSk}, // MODIFIER BREVE WITH INVERTED BREVE + {0xAB5C, 0xAB5F, prAL, gcLm}, // [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK + {0xAB60, 0xAB68, prAL, gcLl}, // [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE + {0xAB69, 0xAB69, prAL, gcLm}, // MODIFIER LETTER SMALL TURNED W + {0xAB6A, 0xAB6B, prAL, gcSk}, // [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK + {0xAB70, 0xABBF, prAL, gcLl}, // [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA + {0xABC0, 0xABE2, prAL, gcLo}, // [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM + {0xABE3, 0xABE4, prCM, gcMc}, // [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP + {0xABE5, 0xABE5, prCM, gcMn}, // MEETEI MAYEK VOWEL SIGN ANAP + {0xABE6, 0xABE7, prCM, gcMc}, // [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP + {0xABE8, 0xABE8, prCM, gcMn}, // MEETEI MAYEK VOWEL SIGN UNAP + {0xABE9, 0xABEA, prCM, gcMc}, // [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG + {0xABEB, 0xABEB, prBA, gcPo}, // MEETEI MAYEK CHEIKHEI + {0xABEC, 0xABEC, prCM, gcMc}, // MEETEI MAYEK LUM IYEK + {0xABED, 0xABED, prCM, gcMn}, // MEETEI MAYEK APUN IYEK + {0xABF0, 0xABF9, prNU, gcNd}, // [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE + {0xAC00, 0xAC00, prH2, gcLo}, // HANGUL SYLLABLE GA + {0xAC01, 0xAC1B, prH3, gcLo}, // [27] HANGUL SYLLABLE GAG..HANGUL SYLLABLE GAH + {0xAC1C, 0xAC1C, prH2, gcLo}, // HANGUL SYLLABLE GAE + {0xAC1D, 0xAC37, prH3, gcLo}, // [27] HANGUL SYLLABLE GAEG..HANGUL SYLLABLE GAEH + {0xAC38, 0xAC38, prH2, gcLo}, // HANGUL SYLLABLE GYA + {0xAC39, 0xAC53, prH3, gcLo}, // [27] HANGUL SYLLABLE GYAG..HANGUL SYLLABLE GYAH + {0xAC54, 0xAC54, prH2, gcLo}, // HANGUL SYLLABLE GYAE + {0xAC55, 0xAC6F, prH3, gcLo}, // [27] HANGUL SYLLABLE GYAEG..HANGUL SYLLABLE GYAEH + {0xAC70, 0xAC70, prH2, gcLo}, // HANGUL SYLLABLE GEO + {0xAC71, 0xAC8B, prH3, gcLo}, // [27] HANGUL SYLLABLE GEOG..HANGUL SYLLABLE GEOH + {0xAC8C, 0xAC8C, prH2, gcLo}, // HANGUL SYLLABLE GE + {0xAC8D, 0xACA7, prH3, gcLo}, // [27] HANGUL SYLLABLE GEG..HANGUL SYLLABLE GEH + {0xACA8, 0xACA8, prH2, gcLo}, // HANGUL SYLLABLE GYEO + {0xACA9, 0xACC3, prH3, gcLo}, // [27] HANGUL SYLLABLE GYEOG..HANGUL SYLLABLE GYEOH + {0xACC4, 0xACC4, prH2, gcLo}, // HANGUL SYLLABLE GYE + {0xACC5, 0xACDF, prH3, gcLo}, // [27] HANGUL SYLLABLE GYEG..HANGUL SYLLABLE GYEH + {0xACE0, 0xACE0, prH2, gcLo}, // HANGUL SYLLABLE GO + {0xACE1, 0xACFB, prH3, gcLo}, // [27] HANGUL SYLLABLE GOG..HANGUL SYLLABLE GOH + {0xACFC, 0xACFC, prH2, gcLo}, // HANGUL SYLLABLE GWA + {0xACFD, 0xAD17, prH3, gcLo}, // [27] HANGUL SYLLABLE GWAG..HANGUL SYLLABLE GWAH + {0xAD18, 0xAD18, prH2, gcLo}, // HANGUL SYLLABLE GWAE + {0xAD19, 0xAD33, prH3, gcLo}, // [27] HANGUL SYLLABLE GWAEG..HANGUL SYLLABLE GWAEH + {0xAD34, 0xAD34, prH2, gcLo}, // HANGUL SYLLABLE GOE + {0xAD35, 0xAD4F, prH3, gcLo}, // [27] HANGUL SYLLABLE GOEG..HANGUL SYLLABLE GOEH + {0xAD50, 0xAD50, prH2, gcLo}, // HANGUL SYLLABLE GYO + {0xAD51, 0xAD6B, prH3, gcLo}, // [27] HANGUL SYLLABLE GYOG..HANGUL SYLLABLE GYOH + {0xAD6C, 0xAD6C, prH2, gcLo}, // HANGUL SYLLABLE GU + {0xAD6D, 0xAD87, prH3, gcLo}, // [27] HANGUL SYLLABLE GUG..HANGUL SYLLABLE GUH + {0xAD88, 0xAD88, prH2, gcLo}, // HANGUL SYLLABLE GWEO + {0xAD89, 0xADA3, prH3, gcLo}, // [27] HANGUL SYLLABLE GWEOG..HANGUL SYLLABLE GWEOH + {0xADA4, 0xADA4, prH2, gcLo}, // HANGUL SYLLABLE GWE + {0xADA5, 0xADBF, prH3, gcLo}, // [27] HANGUL SYLLABLE GWEG..HANGUL SYLLABLE GWEH + {0xADC0, 0xADC0, prH2, gcLo}, // HANGUL SYLLABLE GWI + {0xADC1, 0xADDB, prH3, gcLo}, // [27] HANGUL SYLLABLE GWIG..HANGUL SYLLABLE GWIH + {0xADDC, 0xADDC, prH2, gcLo}, // HANGUL SYLLABLE GYU + {0xADDD, 0xADF7, prH3, gcLo}, // [27] HANGUL SYLLABLE GYUG..HANGUL SYLLABLE GYUH + {0xADF8, 0xADF8, prH2, gcLo}, // HANGUL SYLLABLE GEU + {0xADF9, 0xAE13, prH3, gcLo}, // [27] HANGUL SYLLABLE GEUG..HANGUL SYLLABLE GEUH + {0xAE14, 0xAE14, prH2, gcLo}, // HANGUL SYLLABLE GYI + {0xAE15, 0xAE2F, prH3, gcLo}, // [27] HANGUL SYLLABLE GYIG..HANGUL SYLLABLE GYIH + {0xAE30, 0xAE30, prH2, gcLo}, // HANGUL SYLLABLE GI + {0xAE31, 0xAE4B, prH3, gcLo}, // [27] HANGUL SYLLABLE GIG..HANGUL SYLLABLE GIH + {0xAE4C, 0xAE4C, prH2, gcLo}, // HANGUL SYLLABLE GGA + {0xAE4D, 0xAE67, prH3, gcLo}, // [27] HANGUL SYLLABLE GGAG..HANGUL SYLLABLE GGAH + {0xAE68, 0xAE68, prH2, gcLo}, // HANGUL SYLLABLE GGAE + {0xAE69, 0xAE83, prH3, gcLo}, // [27] HANGUL SYLLABLE GGAEG..HANGUL SYLLABLE GGAEH + {0xAE84, 0xAE84, prH2, gcLo}, // HANGUL SYLLABLE GGYA + {0xAE85, 0xAE9F, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYAG..HANGUL SYLLABLE GGYAH + {0xAEA0, 0xAEA0, prH2, gcLo}, // HANGUL SYLLABLE GGYAE + {0xAEA1, 0xAEBB, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYAEG..HANGUL SYLLABLE GGYAEH + {0xAEBC, 0xAEBC, prH2, gcLo}, // HANGUL SYLLABLE GGEO + {0xAEBD, 0xAED7, prH3, gcLo}, // [27] HANGUL SYLLABLE GGEOG..HANGUL SYLLABLE GGEOH + {0xAED8, 0xAED8, prH2, gcLo}, // HANGUL SYLLABLE GGE + {0xAED9, 0xAEF3, prH3, gcLo}, // [27] HANGUL SYLLABLE GGEG..HANGUL SYLLABLE GGEH + {0xAEF4, 0xAEF4, prH2, gcLo}, // HANGUL SYLLABLE GGYEO + {0xAEF5, 0xAF0F, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYEOG..HANGUL SYLLABLE GGYEOH + {0xAF10, 0xAF10, prH2, gcLo}, // HANGUL SYLLABLE GGYE + {0xAF11, 0xAF2B, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYEG..HANGUL SYLLABLE GGYEH + {0xAF2C, 0xAF2C, prH2, gcLo}, // HANGUL SYLLABLE GGO + {0xAF2D, 0xAF47, prH3, gcLo}, // [27] HANGUL SYLLABLE GGOG..HANGUL SYLLABLE GGOH + {0xAF48, 0xAF48, prH2, gcLo}, // HANGUL SYLLABLE GGWA + {0xAF49, 0xAF63, prH3, gcLo}, // [27] HANGUL SYLLABLE GGWAG..HANGUL SYLLABLE GGWAH + {0xAF64, 0xAF64, prH2, gcLo}, // HANGUL SYLLABLE GGWAE + {0xAF65, 0xAF7F, prH3, gcLo}, // [27] HANGUL SYLLABLE GGWAEG..HANGUL SYLLABLE GGWAEH + {0xAF80, 0xAF80, prH2, gcLo}, // HANGUL SYLLABLE GGOE + {0xAF81, 0xAF9B, prH3, gcLo}, // [27] HANGUL SYLLABLE GGOEG..HANGUL SYLLABLE GGOEH + {0xAF9C, 0xAF9C, prH2, gcLo}, // HANGUL SYLLABLE GGYO + {0xAF9D, 0xAFB7, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYOG..HANGUL SYLLABLE GGYOH + {0xAFB8, 0xAFB8, prH2, gcLo}, // HANGUL SYLLABLE GGU + {0xAFB9, 0xAFD3, prH3, gcLo}, // [27] HANGUL SYLLABLE GGUG..HANGUL SYLLABLE GGUH + {0xAFD4, 0xAFD4, prH2, gcLo}, // HANGUL SYLLABLE GGWEO + {0xAFD5, 0xAFEF, prH3, gcLo}, // [27] HANGUL SYLLABLE GGWEOG..HANGUL SYLLABLE GGWEOH + {0xAFF0, 0xAFF0, prH2, gcLo}, // HANGUL SYLLABLE GGWE + {0xAFF1, 0xB00B, prH3, gcLo}, // [27] HANGUL SYLLABLE GGWEG..HANGUL SYLLABLE GGWEH + {0xB00C, 0xB00C, prH2, gcLo}, // HANGUL SYLLABLE GGWI + {0xB00D, 0xB027, prH3, gcLo}, // [27] HANGUL SYLLABLE GGWIG..HANGUL SYLLABLE GGWIH + {0xB028, 0xB028, prH2, gcLo}, // HANGUL SYLLABLE GGYU + {0xB029, 0xB043, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYUG..HANGUL SYLLABLE GGYUH + {0xB044, 0xB044, prH2, gcLo}, // HANGUL SYLLABLE GGEU + {0xB045, 0xB05F, prH3, gcLo}, // [27] HANGUL SYLLABLE GGEUG..HANGUL SYLLABLE GGEUH + {0xB060, 0xB060, prH2, gcLo}, // HANGUL SYLLABLE GGYI + {0xB061, 0xB07B, prH3, gcLo}, // [27] HANGUL SYLLABLE GGYIG..HANGUL SYLLABLE GGYIH + {0xB07C, 0xB07C, prH2, gcLo}, // HANGUL SYLLABLE GGI + {0xB07D, 0xB097, prH3, gcLo}, // [27] HANGUL SYLLABLE GGIG..HANGUL SYLLABLE GGIH + {0xB098, 0xB098, prH2, gcLo}, // HANGUL SYLLABLE NA + {0xB099, 0xB0B3, prH3, gcLo}, // [27] HANGUL SYLLABLE NAG..HANGUL SYLLABLE NAH + {0xB0B4, 0xB0B4, prH2, gcLo}, // HANGUL SYLLABLE NAE + {0xB0B5, 0xB0CF, prH3, gcLo}, // [27] HANGUL SYLLABLE NAEG..HANGUL SYLLABLE NAEH + {0xB0D0, 0xB0D0, prH2, gcLo}, // HANGUL SYLLABLE NYA + {0xB0D1, 0xB0EB, prH3, gcLo}, // [27] HANGUL SYLLABLE NYAG..HANGUL SYLLABLE NYAH + {0xB0EC, 0xB0EC, prH2, gcLo}, // HANGUL SYLLABLE NYAE + {0xB0ED, 0xB107, prH3, gcLo}, // [27] HANGUL SYLLABLE NYAEG..HANGUL SYLLABLE NYAEH + {0xB108, 0xB108, prH2, gcLo}, // HANGUL SYLLABLE NEO + {0xB109, 0xB123, prH3, gcLo}, // [27] HANGUL SYLLABLE NEOG..HANGUL SYLLABLE NEOH + {0xB124, 0xB124, prH2, gcLo}, // HANGUL SYLLABLE NE + {0xB125, 0xB13F, prH3, gcLo}, // [27] HANGUL SYLLABLE NEG..HANGUL SYLLABLE NEH + {0xB140, 0xB140, prH2, gcLo}, // HANGUL SYLLABLE NYEO + {0xB141, 0xB15B, prH3, gcLo}, // [27] HANGUL SYLLABLE NYEOG..HANGUL SYLLABLE NYEOH + {0xB15C, 0xB15C, prH2, gcLo}, // HANGUL SYLLABLE NYE + {0xB15D, 0xB177, prH3, gcLo}, // [27] HANGUL SYLLABLE NYEG..HANGUL SYLLABLE NYEH + {0xB178, 0xB178, prH2, gcLo}, // HANGUL SYLLABLE NO + {0xB179, 0xB193, prH3, gcLo}, // [27] HANGUL SYLLABLE NOG..HANGUL SYLLABLE NOH + {0xB194, 0xB194, prH2, gcLo}, // HANGUL SYLLABLE NWA + {0xB195, 0xB1AF, prH3, gcLo}, // [27] HANGUL SYLLABLE NWAG..HANGUL SYLLABLE NWAH + {0xB1B0, 0xB1B0, prH2, gcLo}, // HANGUL SYLLABLE NWAE + {0xB1B1, 0xB1CB, prH3, gcLo}, // [27] HANGUL SYLLABLE NWAEG..HANGUL SYLLABLE NWAEH + {0xB1CC, 0xB1CC, prH2, gcLo}, // HANGUL SYLLABLE NOE + {0xB1CD, 0xB1E7, prH3, gcLo}, // [27] HANGUL SYLLABLE NOEG..HANGUL SYLLABLE NOEH + {0xB1E8, 0xB1E8, prH2, gcLo}, // HANGUL SYLLABLE NYO + {0xB1E9, 0xB203, prH3, gcLo}, // [27] HANGUL SYLLABLE NYOG..HANGUL SYLLABLE NYOH + {0xB204, 0xB204, prH2, gcLo}, // HANGUL SYLLABLE NU + {0xB205, 0xB21F, prH3, gcLo}, // [27] HANGUL SYLLABLE NUG..HANGUL SYLLABLE NUH + {0xB220, 0xB220, prH2, gcLo}, // HANGUL SYLLABLE NWEO + {0xB221, 0xB23B, prH3, gcLo}, // [27] HANGUL SYLLABLE NWEOG..HANGUL SYLLABLE NWEOH + {0xB23C, 0xB23C, prH2, gcLo}, // HANGUL SYLLABLE NWE + {0xB23D, 0xB257, prH3, gcLo}, // [27] HANGUL SYLLABLE NWEG..HANGUL SYLLABLE NWEH + {0xB258, 0xB258, prH2, gcLo}, // HANGUL SYLLABLE NWI + {0xB259, 0xB273, prH3, gcLo}, // [27] HANGUL SYLLABLE NWIG..HANGUL SYLLABLE NWIH + {0xB274, 0xB274, prH2, gcLo}, // HANGUL SYLLABLE NYU + {0xB275, 0xB28F, prH3, gcLo}, // [27] HANGUL SYLLABLE NYUG..HANGUL SYLLABLE NYUH + {0xB290, 0xB290, prH2, gcLo}, // HANGUL SYLLABLE NEU + {0xB291, 0xB2AB, prH3, gcLo}, // [27] HANGUL SYLLABLE NEUG..HANGUL SYLLABLE NEUH + {0xB2AC, 0xB2AC, prH2, gcLo}, // HANGUL SYLLABLE NYI + {0xB2AD, 0xB2C7, prH3, gcLo}, // [27] HANGUL SYLLABLE NYIG..HANGUL SYLLABLE NYIH + {0xB2C8, 0xB2C8, prH2, gcLo}, // HANGUL SYLLABLE NI + {0xB2C9, 0xB2E3, prH3, gcLo}, // [27] HANGUL SYLLABLE NIG..HANGUL SYLLABLE NIH + {0xB2E4, 0xB2E4, prH2, gcLo}, // HANGUL SYLLABLE DA + {0xB2E5, 0xB2FF, prH3, gcLo}, // [27] HANGUL SYLLABLE DAG..HANGUL SYLLABLE DAH + {0xB300, 0xB300, prH2, gcLo}, // HANGUL SYLLABLE DAE + {0xB301, 0xB31B, prH3, gcLo}, // [27] HANGUL SYLLABLE DAEG..HANGUL SYLLABLE DAEH + {0xB31C, 0xB31C, prH2, gcLo}, // HANGUL SYLLABLE DYA + {0xB31D, 0xB337, prH3, gcLo}, // [27] HANGUL SYLLABLE DYAG..HANGUL SYLLABLE DYAH + {0xB338, 0xB338, prH2, gcLo}, // HANGUL SYLLABLE DYAE + {0xB339, 0xB353, prH3, gcLo}, // [27] HANGUL SYLLABLE DYAEG..HANGUL SYLLABLE DYAEH + {0xB354, 0xB354, prH2, gcLo}, // HANGUL SYLLABLE DEO + {0xB355, 0xB36F, prH3, gcLo}, // [27] HANGUL SYLLABLE DEOG..HANGUL SYLLABLE DEOH + {0xB370, 0xB370, prH2, gcLo}, // HANGUL SYLLABLE DE + {0xB371, 0xB38B, prH3, gcLo}, // [27] HANGUL SYLLABLE DEG..HANGUL SYLLABLE DEH + {0xB38C, 0xB38C, prH2, gcLo}, // HANGUL SYLLABLE DYEO + {0xB38D, 0xB3A7, prH3, gcLo}, // [27] HANGUL SYLLABLE DYEOG..HANGUL SYLLABLE DYEOH + {0xB3A8, 0xB3A8, prH2, gcLo}, // HANGUL SYLLABLE DYE + {0xB3A9, 0xB3C3, prH3, gcLo}, // [27] HANGUL SYLLABLE DYEG..HANGUL SYLLABLE DYEH + {0xB3C4, 0xB3C4, prH2, gcLo}, // HANGUL SYLLABLE DO + {0xB3C5, 0xB3DF, prH3, gcLo}, // [27] HANGUL SYLLABLE DOG..HANGUL SYLLABLE DOH + {0xB3E0, 0xB3E0, prH2, gcLo}, // HANGUL SYLLABLE DWA + {0xB3E1, 0xB3FB, prH3, gcLo}, // [27] HANGUL SYLLABLE DWAG..HANGUL SYLLABLE DWAH + {0xB3FC, 0xB3FC, prH2, gcLo}, // HANGUL SYLLABLE DWAE + {0xB3FD, 0xB417, prH3, gcLo}, // [27] HANGUL SYLLABLE DWAEG..HANGUL SYLLABLE DWAEH + {0xB418, 0xB418, prH2, gcLo}, // HANGUL SYLLABLE DOE + {0xB419, 0xB433, prH3, gcLo}, // [27] HANGUL SYLLABLE DOEG..HANGUL SYLLABLE DOEH + {0xB434, 0xB434, prH2, gcLo}, // HANGUL SYLLABLE DYO + {0xB435, 0xB44F, prH3, gcLo}, // [27] HANGUL SYLLABLE DYOG..HANGUL SYLLABLE DYOH + {0xB450, 0xB450, prH2, gcLo}, // HANGUL SYLLABLE DU + {0xB451, 0xB46B, prH3, gcLo}, // [27] HANGUL SYLLABLE DUG..HANGUL SYLLABLE DUH + {0xB46C, 0xB46C, prH2, gcLo}, // HANGUL SYLLABLE DWEO + {0xB46D, 0xB487, prH3, gcLo}, // [27] HANGUL SYLLABLE DWEOG..HANGUL SYLLABLE DWEOH + {0xB488, 0xB488, prH2, gcLo}, // HANGUL SYLLABLE DWE + {0xB489, 0xB4A3, prH3, gcLo}, // [27] HANGUL SYLLABLE DWEG..HANGUL SYLLABLE DWEH + {0xB4A4, 0xB4A4, prH2, gcLo}, // HANGUL SYLLABLE DWI + {0xB4A5, 0xB4BF, prH3, gcLo}, // [27] HANGUL SYLLABLE DWIG..HANGUL SYLLABLE DWIH + {0xB4C0, 0xB4C0, prH2, gcLo}, // HANGUL SYLLABLE DYU + {0xB4C1, 0xB4DB, prH3, gcLo}, // [27] HANGUL SYLLABLE DYUG..HANGUL SYLLABLE DYUH + {0xB4DC, 0xB4DC, prH2, gcLo}, // HANGUL SYLLABLE DEU + {0xB4DD, 0xB4F7, prH3, gcLo}, // [27] HANGUL SYLLABLE DEUG..HANGUL SYLLABLE DEUH + {0xB4F8, 0xB4F8, prH2, gcLo}, // HANGUL SYLLABLE DYI + {0xB4F9, 0xB513, prH3, gcLo}, // [27] HANGUL SYLLABLE DYIG..HANGUL SYLLABLE DYIH + {0xB514, 0xB514, prH2, gcLo}, // HANGUL SYLLABLE DI + {0xB515, 0xB52F, prH3, gcLo}, // [27] HANGUL SYLLABLE DIG..HANGUL SYLLABLE DIH + {0xB530, 0xB530, prH2, gcLo}, // HANGUL SYLLABLE DDA + {0xB531, 0xB54B, prH3, gcLo}, // [27] HANGUL SYLLABLE DDAG..HANGUL SYLLABLE DDAH + {0xB54C, 0xB54C, prH2, gcLo}, // HANGUL SYLLABLE DDAE + {0xB54D, 0xB567, prH3, gcLo}, // [27] HANGUL SYLLABLE DDAEG..HANGUL SYLLABLE DDAEH + {0xB568, 0xB568, prH2, gcLo}, // HANGUL SYLLABLE DDYA + {0xB569, 0xB583, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYAG..HANGUL SYLLABLE DDYAH + {0xB584, 0xB584, prH2, gcLo}, // HANGUL SYLLABLE DDYAE + {0xB585, 0xB59F, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYAEG..HANGUL SYLLABLE DDYAEH + {0xB5A0, 0xB5A0, prH2, gcLo}, // HANGUL SYLLABLE DDEO + {0xB5A1, 0xB5BB, prH3, gcLo}, // [27] HANGUL SYLLABLE DDEOG..HANGUL SYLLABLE DDEOH + {0xB5BC, 0xB5BC, prH2, gcLo}, // HANGUL SYLLABLE DDE + {0xB5BD, 0xB5D7, prH3, gcLo}, // [27] HANGUL SYLLABLE DDEG..HANGUL SYLLABLE DDEH + {0xB5D8, 0xB5D8, prH2, gcLo}, // HANGUL SYLLABLE DDYEO + {0xB5D9, 0xB5F3, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYEOG..HANGUL SYLLABLE DDYEOH + {0xB5F4, 0xB5F4, prH2, gcLo}, // HANGUL SYLLABLE DDYE + {0xB5F5, 0xB60F, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYEG..HANGUL SYLLABLE DDYEH + {0xB610, 0xB610, prH2, gcLo}, // HANGUL SYLLABLE DDO + {0xB611, 0xB62B, prH3, gcLo}, // [27] HANGUL SYLLABLE DDOG..HANGUL SYLLABLE DDOH + {0xB62C, 0xB62C, prH2, gcLo}, // HANGUL SYLLABLE DDWA + {0xB62D, 0xB647, prH3, gcLo}, // [27] HANGUL SYLLABLE DDWAG..HANGUL SYLLABLE DDWAH + {0xB648, 0xB648, prH2, gcLo}, // HANGUL SYLLABLE DDWAE + {0xB649, 0xB663, prH3, gcLo}, // [27] HANGUL SYLLABLE DDWAEG..HANGUL SYLLABLE DDWAEH + {0xB664, 0xB664, prH2, gcLo}, // HANGUL SYLLABLE DDOE + {0xB665, 0xB67F, prH3, gcLo}, // [27] HANGUL SYLLABLE DDOEG..HANGUL SYLLABLE DDOEH + {0xB680, 0xB680, prH2, gcLo}, // HANGUL SYLLABLE DDYO + {0xB681, 0xB69B, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYOG..HANGUL SYLLABLE DDYOH + {0xB69C, 0xB69C, prH2, gcLo}, // HANGUL SYLLABLE DDU + {0xB69D, 0xB6B7, prH3, gcLo}, // [27] HANGUL SYLLABLE DDUG..HANGUL SYLLABLE DDUH + {0xB6B8, 0xB6B8, prH2, gcLo}, // HANGUL SYLLABLE DDWEO + {0xB6B9, 0xB6D3, prH3, gcLo}, // [27] HANGUL SYLLABLE DDWEOG..HANGUL SYLLABLE DDWEOH + {0xB6D4, 0xB6D4, prH2, gcLo}, // HANGUL SYLLABLE DDWE + {0xB6D5, 0xB6EF, prH3, gcLo}, // [27] HANGUL SYLLABLE DDWEG..HANGUL SYLLABLE DDWEH + {0xB6F0, 0xB6F0, prH2, gcLo}, // HANGUL SYLLABLE DDWI + {0xB6F1, 0xB70B, prH3, gcLo}, // [27] HANGUL SYLLABLE DDWIG..HANGUL SYLLABLE DDWIH + {0xB70C, 0xB70C, prH2, gcLo}, // HANGUL SYLLABLE DDYU + {0xB70D, 0xB727, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYUG..HANGUL SYLLABLE DDYUH + {0xB728, 0xB728, prH2, gcLo}, // HANGUL SYLLABLE DDEU + {0xB729, 0xB743, prH3, gcLo}, // [27] HANGUL SYLLABLE DDEUG..HANGUL SYLLABLE DDEUH + {0xB744, 0xB744, prH2, gcLo}, // HANGUL SYLLABLE DDYI + {0xB745, 0xB75F, prH3, gcLo}, // [27] HANGUL SYLLABLE DDYIG..HANGUL SYLLABLE DDYIH + {0xB760, 0xB760, prH2, gcLo}, // HANGUL SYLLABLE DDI + {0xB761, 0xB77B, prH3, gcLo}, // [27] HANGUL SYLLABLE DDIG..HANGUL SYLLABLE DDIH + {0xB77C, 0xB77C, prH2, gcLo}, // HANGUL SYLLABLE RA + {0xB77D, 0xB797, prH3, gcLo}, // [27] HANGUL SYLLABLE RAG..HANGUL SYLLABLE RAH + {0xB798, 0xB798, prH2, gcLo}, // HANGUL SYLLABLE RAE + {0xB799, 0xB7B3, prH3, gcLo}, // [27] HANGUL SYLLABLE RAEG..HANGUL SYLLABLE RAEH + {0xB7B4, 0xB7B4, prH2, gcLo}, // HANGUL SYLLABLE RYA + {0xB7B5, 0xB7CF, prH3, gcLo}, // [27] HANGUL SYLLABLE RYAG..HANGUL SYLLABLE RYAH + {0xB7D0, 0xB7D0, prH2, gcLo}, // HANGUL SYLLABLE RYAE + {0xB7D1, 0xB7EB, prH3, gcLo}, // [27] HANGUL SYLLABLE RYAEG..HANGUL SYLLABLE RYAEH + {0xB7EC, 0xB7EC, prH2, gcLo}, // HANGUL SYLLABLE REO + {0xB7ED, 0xB807, prH3, gcLo}, // [27] HANGUL SYLLABLE REOG..HANGUL SYLLABLE REOH + {0xB808, 0xB808, prH2, gcLo}, // HANGUL SYLLABLE RE + {0xB809, 0xB823, prH3, gcLo}, // [27] HANGUL SYLLABLE REG..HANGUL SYLLABLE REH + {0xB824, 0xB824, prH2, gcLo}, // HANGUL SYLLABLE RYEO + {0xB825, 0xB83F, prH3, gcLo}, // [27] HANGUL SYLLABLE RYEOG..HANGUL SYLLABLE RYEOH + {0xB840, 0xB840, prH2, gcLo}, // HANGUL SYLLABLE RYE + {0xB841, 0xB85B, prH3, gcLo}, // [27] HANGUL SYLLABLE RYEG..HANGUL SYLLABLE RYEH + {0xB85C, 0xB85C, prH2, gcLo}, // HANGUL SYLLABLE RO + {0xB85D, 0xB877, prH3, gcLo}, // [27] HANGUL SYLLABLE ROG..HANGUL SYLLABLE ROH + {0xB878, 0xB878, prH2, gcLo}, // HANGUL SYLLABLE RWA + {0xB879, 0xB893, prH3, gcLo}, // [27] HANGUL SYLLABLE RWAG..HANGUL SYLLABLE RWAH + {0xB894, 0xB894, prH2, gcLo}, // HANGUL SYLLABLE RWAE + {0xB895, 0xB8AF, prH3, gcLo}, // [27] HANGUL SYLLABLE RWAEG..HANGUL SYLLABLE RWAEH + {0xB8B0, 0xB8B0, prH2, gcLo}, // HANGUL SYLLABLE ROE + {0xB8B1, 0xB8CB, prH3, gcLo}, // [27] HANGUL SYLLABLE ROEG..HANGUL SYLLABLE ROEH + {0xB8CC, 0xB8CC, prH2, gcLo}, // HANGUL SYLLABLE RYO + {0xB8CD, 0xB8E7, prH3, gcLo}, // [27] HANGUL SYLLABLE RYOG..HANGUL SYLLABLE RYOH + {0xB8E8, 0xB8E8, prH2, gcLo}, // HANGUL SYLLABLE RU + {0xB8E9, 0xB903, prH3, gcLo}, // [27] HANGUL SYLLABLE RUG..HANGUL SYLLABLE RUH + {0xB904, 0xB904, prH2, gcLo}, // HANGUL SYLLABLE RWEO + {0xB905, 0xB91F, prH3, gcLo}, // [27] HANGUL SYLLABLE RWEOG..HANGUL SYLLABLE RWEOH + {0xB920, 0xB920, prH2, gcLo}, // HANGUL SYLLABLE RWE + {0xB921, 0xB93B, prH3, gcLo}, // [27] HANGUL SYLLABLE RWEG..HANGUL SYLLABLE RWEH + {0xB93C, 0xB93C, prH2, gcLo}, // HANGUL SYLLABLE RWI + {0xB93D, 0xB957, prH3, gcLo}, // [27] HANGUL SYLLABLE RWIG..HANGUL SYLLABLE RWIH + {0xB958, 0xB958, prH2, gcLo}, // HANGUL SYLLABLE RYU + {0xB959, 0xB973, prH3, gcLo}, // [27] HANGUL SYLLABLE RYUG..HANGUL SYLLABLE RYUH + {0xB974, 0xB974, prH2, gcLo}, // HANGUL SYLLABLE REU + {0xB975, 0xB98F, prH3, gcLo}, // [27] HANGUL SYLLABLE REUG..HANGUL SYLLABLE REUH + {0xB990, 0xB990, prH2, gcLo}, // HANGUL SYLLABLE RYI + {0xB991, 0xB9AB, prH3, gcLo}, // [27] HANGUL SYLLABLE RYIG..HANGUL SYLLABLE RYIH + {0xB9AC, 0xB9AC, prH2, gcLo}, // HANGUL SYLLABLE RI + {0xB9AD, 0xB9C7, prH3, gcLo}, // [27] HANGUL SYLLABLE RIG..HANGUL SYLLABLE RIH + {0xB9C8, 0xB9C8, prH2, gcLo}, // HANGUL SYLLABLE MA + {0xB9C9, 0xB9E3, prH3, gcLo}, // [27] HANGUL SYLLABLE MAG..HANGUL SYLLABLE MAH + {0xB9E4, 0xB9E4, prH2, gcLo}, // HANGUL SYLLABLE MAE + {0xB9E5, 0xB9FF, prH3, gcLo}, // [27] HANGUL SYLLABLE MAEG..HANGUL SYLLABLE MAEH + {0xBA00, 0xBA00, prH2, gcLo}, // HANGUL SYLLABLE MYA + {0xBA01, 0xBA1B, prH3, gcLo}, // [27] HANGUL SYLLABLE MYAG..HANGUL SYLLABLE MYAH + {0xBA1C, 0xBA1C, prH2, gcLo}, // HANGUL SYLLABLE MYAE + {0xBA1D, 0xBA37, prH3, gcLo}, // [27] HANGUL SYLLABLE MYAEG..HANGUL SYLLABLE MYAEH + {0xBA38, 0xBA38, prH2, gcLo}, // HANGUL SYLLABLE MEO + {0xBA39, 0xBA53, prH3, gcLo}, // [27] HANGUL SYLLABLE MEOG..HANGUL SYLLABLE MEOH + {0xBA54, 0xBA54, prH2, gcLo}, // HANGUL SYLLABLE ME + {0xBA55, 0xBA6F, prH3, gcLo}, // [27] HANGUL SYLLABLE MEG..HANGUL SYLLABLE MEH + {0xBA70, 0xBA70, prH2, gcLo}, // HANGUL SYLLABLE MYEO + {0xBA71, 0xBA8B, prH3, gcLo}, // [27] HANGUL SYLLABLE MYEOG..HANGUL SYLLABLE MYEOH + {0xBA8C, 0xBA8C, prH2, gcLo}, // HANGUL SYLLABLE MYE + {0xBA8D, 0xBAA7, prH3, gcLo}, // [27] HANGUL SYLLABLE MYEG..HANGUL SYLLABLE MYEH + {0xBAA8, 0xBAA8, prH2, gcLo}, // HANGUL SYLLABLE MO + {0xBAA9, 0xBAC3, prH3, gcLo}, // [27] HANGUL SYLLABLE MOG..HANGUL SYLLABLE MOH + {0xBAC4, 0xBAC4, prH2, gcLo}, // HANGUL SYLLABLE MWA + {0xBAC5, 0xBADF, prH3, gcLo}, // [27] HANGUL SYLLABLE MWAG..HANGUL SYLLABLE MWAH + {0xBAE0, 0xBAE0, prH2, gcLo}, // HANGUL SYLLABLE MWAE + {0xBAE1, 0xBAFB, prH3, gcLo}, // [27] HANGUL SYLLABLE MWAEG..HANGUL SYLLABLE MWAEH + {0xBAFC, 0xBAFC, prH2, gcLo}, // HANGUL SYLLABLE MOE + {0xBAFD, 0xBB17, prH3, gcLo}, // [27] HANGUL SYLLABLE MOEG..HANGUL SYLLABLE MOEH + {0xBB18, 0xBB18, prH2, gcLo}, // HANGUL SYLLABLE MYO + {0xBB19, 0xBB33, prH3, gcLo}, // [27] HANGUL SYLLABLE MYOG..HANGUL SYLLABLE MYOH + {0xBB34, 0xBB34, prH2, gcLo}, // HANGUL SYLLABLE MU + {0xBB35, 0xBB4F, prH3, gcLo}, // [27] HANGUL SYLLABLE MUG..HANGUL SYLLABLE MUH + {0xBB50, 0xBB50, prH2, gcLo}, // HANGUL SYLLABLE MWEO + {0xBB51, 0xBB6B, prH3, gcLo}, // [27] HANGUL SYLLABLE MWEOG..HANGUL SYLLABLE MWEOH + {0xBB6C, 0xBB6C, prH2, gcLo}, // HANGUL SYLLABLE MWE + {0xBB6D, 0xBB87, prH3, gcLo}, // [27] HANGUL SYLLABLE MWEG..HANGUL SYLLABLE MWEH + {0xBB88, 0xBB88, prH2, gcLo}, // HANGUL SYLLABLE MWI + {0xBB89, 0xBBA3, prH3, gcLo}, // [27] HANGUL SYLLABLE MWIG..HANGUL SYLLABLE MWIH + {0xBBA4, 0xBBA4, prH2, gcLo}, // HANGUL SYLLABLE MYU + {0xBBA5, 0xBBBF, prH3, gcLo}, // [27] HANGUL SYLLABLE MYUG..HANGUL SYLLABLE MYUH + {0xBBC0, 0xBBC0, prH2, gcLo}, // HANGUL SYLLABLE MEU + {0xBBC1, 0xBBDB, prH3, gcLo}, // [27] HANGUL SYLLABLE MEUG..HANGUL SYLLABLE MEUH + {0xBBDC, 0xBBDC, prH2, gcLo}, // HANGUL SYLLABLE MYI + {0xBBDD, 0xBBF7, prH3, gcLo}, // [27] HANGUL SYLLABLE MYIG..HANGUL SYLLABLE MYIH + {0xBBF8, 0xBBF8, prH2, gcLo}, // HANGUL SYLLABLE MI + {0xBBF9, 0xBC13, prH3, gcLo}, // [27] HANGUL SYLLABLE MIG..HANGUL SYLLABLE MIH + {0xBC14, 0xBC14, prH2, gcLo}, // HANGUL SYLLABLE BA + {0xBC15, 0xBC2F, prH3, gcLo}, // [27] HANGUL SYLLABLE BAG..HANGUL SYLLABLE BAH + {0xBC30, 0xBC30, prH2, gcLo}, // HANGUL SYLLABLE BAE + {0xBC31, 0xBC4B, prH3, gcLo}, // [27] HANGUL SYLLABLE BAEG..HANGUL SYLLABLE BAEH + {0xBC4C, 0xBC4C, prH2, gcLo}, // HANGUL SYLLABLE BYA + {0xBC4D, 0xBC67, prH3, gcLo}, // [27] HANGUL SYLLABLE BYAG..HANGUL SYLLABLE BYAH + {0xBC68, 0xBC68, prH2, gcLo}, // HANGUL SYLLABLE BYAE + {0xBC69, 0xBC83, prH3, gcLo}, // [27] HANGUL SYLLABLE BYAEG..HANGUL SYLLABLE BYAEH + {0xBC84, 0xBC84, prH2, gcLo}, // HANGUL SYLLABLE BEO + {0xBC85, 0xBC9F, prH3, gcLo}, // [27] HANGUL SYLLABLE BEOG..HANGUL SYLLABLE BEOH + {0xBCA0, 0xBCA0, prH2, gcLo}, // HANGUL SYLLABLE BE + {0xBCA1, 0xBCBB, prH3, gcLo}, // [27] HANGUL SYLLABLE BEG..HANGUL SYLLABLE BEH + {0xBCBC, 0xBCBC, prH2, gcLo}, // HANGUL SYLLABLE BYEO + {0xBCBD, 0xBCD7, prH3, gcLo}, // [27] HANGUL SYLLABLE BYEOG..HANGUL SYLLABLE BYEOH + {0xBCD8, 0xBCD8, prH2, gcLo}, // HANGUL SYLLABLE BYE + {0xBCD9, 0xBCF3, prH3, gcLo}, // [27] HANGUL SYLLABLE BYEG..HANGUL SYLLABLE BYEH + {0xBCF4, 0xBCF4, prH2, gcLo}, // HANGUL SYLLABLE BO + {0xBCF5, 0xBD0F, prH3, gcLo}, // [27] HANGUL SYLLABLE BOG..HANGUL SYLLABLE BOH + {0xBD10, 0xBD10, prH2, gcLo}, // HANGUL SYLLABLE BWA + {0xBD11, 0xBD2B, prH3, gcLo}, // [27] HANGUL SYLLABLE BWAG..HANGUL SYLLABLE BWAH + {0xBD2C, 0xBD2C, prH2, gcLo}, // HANGUL SYLLABLE BWAE + {0xBD2D, 0xBD47, prH3, gcLo}, // [27] HANGUL SYLLABLE BWAEG..HANGUL SYLLABLE BWAEH + {0xBD48, 0xBD48, prH2, gcLo}, // HANGUL SYLLABLE BOE + {0xBD49, 0xBD63, prH3, gcLo}, // [27] HANGUL SYLLABLE BOEG..HANGUL SYLLABLE BOEH + {0xBD64, 0xBD64, prH2, gcLo}, // HANGUL SYLLABLE BYO + {0xBD65, 0xBD7F, prH3, gcLo}, // [27] HANGUL SYLLABLE BYOG..HANGUL SYLLABLE BYOH + {0xBD80, 0xBD80, prH2, gcLo}, // HANGUL SYLLABLE BU + {0xBD81, 0xBD9B, prH3, gcLo}, // [27] HANGUL SYLLABLE BUG..HANGUL SYLLABLE BUH + {0xBD9C, 0xBD9C, prH2, gcLo}, // HANGUL SYLLABLE BWEO + {0xBD9D, 0xBDB7, prH3, gcLo}, // [27] HANGUL SYLLABLE BWEOG..HANGUL SYLLABLE BWEOH + {0xBDB8, 0xBDB8, prH2, gcLo}, // HANGUL SYLLABLE BWE + {0xBDB9, 0xBDD3, prH3, gcLo}, // [27] HANGUL SYLLABLE BWEG..HANGUL SYLLABLE BWEH + {0xBDD4, 0xBDD4, prH2, gcLo}, // HANGUL SYLLABLE BWI + {0xBDD5, 0xBDEF, prH3, gcLo}, // [27] HANGUL SYLLABLE BWIG..HANGUL SYLLABLE BWIH + {0xBDF0, 0xBDF0, prH2, gcLo}, // HANGUL SYLLABLE BYU + {0xBDF1, 0xBE0B, prH3, gcLo}, // [27] HANGUL SYLLABLE BYUG..HANGUL SYLLABLE BYUH + {0xBE0C, 0xBE0C, prH2, gcLo}, // HANGUL SYLLABLE BEU + {0xBE0D, 0xBE27, prH3, gcLo}, // [27] HANGUL SYLLABLE BEUG..HANGUL SYLLABLE BEUH + {0xBE28, 0xBE28, prH2, gcLo}, // HANGUL SYLLABLE BYI + {0xBE29, 0xBE43, prH3, gcLo}, // [27] HANGUL SYLLABLE BYIG..HANGUL SYLLABLE BYIH + {0xBE44, 0xBE44, prH2, gcLo}, // HANGUL SYLLABLE BI + {0xBE45, 0xBE5F, prH3, gcLo}, // [27] HANGUL SYLLABLE BIG..HANGUL SYLLABLE BIH + {0xBE60, 0xBE60, prH2, gcLo}, // HANGUL SYLLABLE BBA + {0xBE61, 0xBE7B, prH3, gcLo}, // [27] HANGUL SYLLABLE BBAG..HANGUL SYLLABLE BBAH + {0xBE7C, 0xBE7C, prH2, gcLo}, // HANGUL SYLLABLE BBAE + {0xBE7D, 0xBE97, prH3, gcLo}, // [27] HANGUL SYLLABLE BBAEG..HANGUL SYLLABLE BBAEH + {0xBE98, 0xBE98, prH2, gcLo}, // HANGUL SYLLABLE BBYA + {0xBE99, 0xBEB3, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYAG..HANGUL SYLLABLE BBYAH + {0xBEB4, 0xBEB4, prH2, gcLo}, // HANGUL SYLLABLE BBYAE + {0xBEB5, 0xBECF, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYAEG..HANGUL SYLLABLE BBYAEH + {0xBED0, 0xBED0, prH2, gcLo}, // HANGUL SYLLABLE BBEO + {0xBED1, 0xBEEB, prH3, gcLo}, // [27] HANGUL SYLLABLE BBEOG..HANGUL SYLLABLE BBEOH + {0xBEEC, 0xBEEC, prH2, gcLo}, // HANGUL SYLLABLE BBE + {0xBEED, 0xBF07, prH3, gcLo}, // [27] HANGUL SYLLABLE BBEG..HANGUL SYLLABLE BBEH + {0xBF08, 0xBF08, prH2, gcLo}, // HANGUL SYLLABLE BBYEO + {0xBF09, 0xBF23, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYEOG..HANGUL SYLLABLE BBYEOH + {0xBF24, 0xBF24, prH2, gcLo}, // HANGUL SYLLABLE BBYE + {0xBF25, 0xBF3F, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYEG..HANGUL SYLLABLE BBYEH + {0xBF40, 0xBF40, prH2, gcLo}, // HANGUL SYLLABLE BBO + {0xBF41, 0xBF5B, prH3, gcLo}, // [27] HANGUL SYLLABLE BBOG..HANGUL SYLLABLE BBOH + {0xBF5C, 0xBF5C, prH2, gcLo}, // HANGUL SYLLABLE BBWA + {0xBF5D, 0xBF77, prH3, gcLo}, // [27] HANGUL SYLLABLE BBWAG..HANGUL SYLLABLE BBWAH + {0xBF78, 0xBF78, prH2, gcLo}, // HANGUL SYLLABLE BBWAE + {0xBF79, 0xBF93, prH3, gcLo}, // [27] HANGUL SYLLABLE BBWAEG..HANGUL SYLLABLE BBWAEH + {0xBF94, 0xBF94, prH2, gcLo}, // HANGUL SYLLABLE BBOE + {0xBF95, 0xBFAF, prH3, gcLo}, // [27] HANGUL SYLLABLE BBOEG..HANGUL SYLLABLE BBOEH + {0xBFB0, 0xBFB0, prH2, gcLo}, // HANGUL SYLLABLE BBYO + {0xBFB1, 0xBFCB, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYOG..HANGUL SYLLABLE BBYOH + {0xBFCC, 0xBFCC, prH2, gcLo}, // HANGUL SYLLABLE BBU + {0xBFCD, 0xBFE7, prH3, gcLo}, // [27] HANGUL SYLLABLE BBUG..HANGUL SYLLABLE BBUH + {0xBFE8, 0xBFE8, prH2, gcLo}, // HANGUL SYLLABLE BBWEO + {0xBFE9, 0xC003, prH3, gcLo}, // [27] HANGUL SYLLABLE BBWEOG..HANGUL SYLLABLE BBWEOH + {0xC004, 0xC004, prH2, gcLo}, // HANGUL SYLLABLE BBWE + {0xC005, 0xC01F, prH3, gcLo}, // [27] HANGUL SYLLABLE BBWEG..HANGUL SYLLABLE BBWEH + {0xC020, 0xC020, prH2, gcLo}, // HANGUL SYLLABLE BBWI + {0xC021, 0xC03B, prH3, gcLo}, // [27] HANGUL SYLLABLE BBWIG..HANGUL SYLLABLE BBWIH + {0xC03C, 0xC03C, prH2, gcLo}, // HANGUL SYLLABLE BBYU + {0xC03D, 0xC057, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYUG..HANGUL SYLLABLE BBYUH + {0xC058, 0xC058, prH2, gcLo}, // HANGUL SYLLABLE BBEU + {0xC059, 0xC073, prH3, gcLo}, // [27] HANGUL SYLLABLE BBEUG..HANGUL SYLLABLE BBEUH + {0xC074, 0xC074, prH2, gcLo}, // HANGUL SYLLABLE BBYI + {0xC075, 0xC08F, prH3, gcLo}, // [27] HANGUL SYLLABLE BBYIG..HANGUL SYLLABLE BBYIH + {0xC090, 0xC090, prH2, gcLo}, // HANGUL SYLLABLE BBI + {0xC091, 0xC0AB, prH3, gcLo}, // [27] HANGUL SYLLABLE BBIG..HANGUL SYLLABLE BBIH + {0xC0AC, 0xC0AC, prH2, gcLo}, // HANGUL SYLLABLE SA + {0xC0AD, 0xC0C7, prH3, gcLo}, // [27] HANGUL SYLLABLE SAG..HANGUL SYLLABLE SAH + {0xC0C8, 0xC0C8, prH2, gcLo}, // HANGUL SYLLABLE SAE + {0xC0C9, 0xC0E3, prH3, gcLo}, // [27] HANGUL SYLLABLE SAEG..HANGUL SYLLABLE SAEH + {0xC0E4, 0xC0E4, prH2, gcLo}, // HANGUL SYLLABLE SYA + {0xC0E5, 0xC0FF, prH3, gcLo}, // [27] HANGUL SYLLABLE SYAG..HANGUL SYLLABLE SYAH + {0xC100, 0xC100, prH2, gcLo}, // HANGUL SYLLABLE SYAE + {0xC101, 0xC11B, prH3, gcLo}, // [27] HANGUL SYLLABLE SYAEG..HANGUL SYLLABLE SYAEH + {0xC11C, 0xC11C, prH2, gcLo}, // HANGUL SYLLABLE SEO + {0xC11D, 0xC137, prH3, gcLo}, // [27] HANGUL SYLLABLE SEOG..HANGUL SYLLABLE SEOH + {0xC138, 0xC138, prH2, gcLo}, // HANGUL SYLLABLE SE + {0xC139, 0xC153, prH3, gcLo}, // [27] HANGUL SYLLABLE SEG..HANGUL SYLLABLE SEH + {0xC154, 0xC154, prH2, gcLo}, // HANGUL SYLLABLE SYEO + {0xC155, 0xC16F, prH3, gcLo}, // [27] HANGUL SYLLABLE SYEOG..HANGUL SYLLABLE SYEOH + {0xC170, 0xC170, prH2, gcLo}, // HANGUL SYLLABLE SYE + {0xC171, 0xC18B, prH3, gcLo}, // [27] HANGUL SYLLABLE SYEG..HANGUL SYLLABLE SYEH + {0xC18C, 0xC18C, prH2, gcLo}, // HANGUL SYLLABLE SO + {0xC18D, 0xC1A7, prH3, gcLo}, // [27] HANGUL SYLLABLE SOG..HANGUL SYLLABLE SOH + {0xC1A8, 0xC1A8, prH2, gcLo}, // HANGUL SYLLABLE SWA + {0xC1A9, 0xC1C3, prH3, gcLo}, // [27] HANGUL SYLLABLE SWAG..HANGUL SYLLABLE SWAH + {0xC1C4, 0xC1C4, prH2, gcLo}, // HANGUL SYLLABLE SWAE + {0xC1C5, 0xC1DF, prH3, gcLo}, // [27] HANGUL SYLLABLE SWAEG..HANGUL SYLLABLE SWAEH + {0xC1E0, 0xC1E0, prH2, gcLo}, // HANGUL SYLLABLE SOE + {0xC1E1, 0xC1FB, prH3, gcLo}, // [27] HANGUL SYLLABLE SOEG..HANGUL SYLLABLE SOEH + {0xC1FC, 0xC1FC, prH2, gcLo}, // HANGUL SYLLABLE SYO + {0xC1FD, 0xC217, prH3, gcLo}, // [27] HANGUL SYLLABLE SYOG..HANGUL SYLLABLE SYOH + {0xC218, 0xC218, prH2, gcLo}, // HANGUL SYLLABLE SU + {0xC219, 0xC233, prH3, gcLo}, // [27] HANGUL SYLLABLE SUG..HANGUL SYLLABLE SUH + {0xC234, 0xC234, prH2, gcLo}, // HANGUL SYLLABLE SWEO + {0xC235, 0xC24F, prH3, gcLo}, // [27] HANGUL SYLLABLE SWEOG..HANGUL SYLLABLE SWEOH + {0xC250, 0xC250, prH2, gcLo}, // HANGUL SYLLABLE SWE + {0xC251, 0xC26B, prH3, gcLo}, // [27] HANGUL SYLLABLE SWEG..HANGUL SYLLABLE SWEH + {0xC26C, 0xC26C, prH2, gcLo}, // HANGUL SYLLABLE SWI + {0xC26D, 0xC287, prH3, gcLo}, // [27] HANGUL SYLLABLE SWIG..HANGUL SYLLABLE SWIH + {0xC288, 0xC288, prH2, gcLo}, // HANGUL SYLLABLE SYU + {0xC289, 0xC2A3, prH3, gcLo}, // [27] HANGUL SYLLABLE SYUG..HANGUL SYLLABLE SYUH + {0xC2A4, 0xC2A4, prH2, gcLo}, // HANGUL SYLLABLE SEU + {0xC2A5, 0xC2BF, prH3, gcLo}, // [27] HANGUL SYLLABLE SEUG..HANGUL SYLLABLE SEUH + {0xC2C0, 0xC2C0, prH2, gcLo}, // HANGUL SYLLABLE SYI + {0xC2C1, 0xC2DB, prH3, gcLo}, // [27] HANGUL SYLLABLE SYIG..HANGUL SYLLABLE SYIH + {0xC2DC, 0xC2DC, prH2, gcLo}, // HANGUL SYLLABLE SI + {0xC2DD, 0xC2F7, prH3, gcLo}, // [27] HANGUL SYLLABLE SIG..HANGUL SYLLABLE SIH + {0xC2F8, 0xC2F8, prH2, gcLo}, // HANGUL SYLLABLE SSA + {0xC2F9, 0xC313, prH3, gcLo}, // [27] HANGUL SYLLABLE SSAG..HANGUL SYLLABLE SSAH + {0xC314, 0xC314, prH2, gcLo}, // HANGUL SYLLABLE SSAE + {0xC315, 0xC32F, prH3, gcLo}, // [27] HANGUL SYLLABLE SSAEG..HANGUL SYLLABLE SSAEH + {0xC330, 0xC330, prH2, gcLo}, // HANGUL SYLLABLE SSYA + {0xC331, 0xC34B, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYAG..HANGUL SYLLABLE SSYAH + {0xC34C, 0xC34C, prH2, gcLo}, // HANGUL SYLLABLE SSYAE + {0xC34D, 0xC367, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYAEG..HANGUL SYLLABLE SSYAEH + {0xC368, 0xC368, prH2, gcLo}, // HANGUL SYLLABLE SSEO + {0xC369, 0xC383, prH3, gcLo}, // [27] HANGUL SYLLABLE SSEOG..HANGUL SYLLABLE SSEOH + {0xC384, 0xC384, prH2, gcLo}, // HANGUL SYLLABLE SSE + {0xC385, 0xC39F, prH3, gcLo}, // [27] HANGUL SYLLABLE SSEG..HANGUL SYLLABLE SSEH + {0xC3A0, 0xC3A0, prH2, gcLo}, // HANGUL SYLLABLE SSYEO + {0xC3A1, 0xC3BB, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYEOG..HANGUL SYLLABLE SSYEOH + {0xC3BC, 0xC3BC, prH2, gcLo}, // HANGUL SYLLABLE SSYE + {0xC3BD, 0xC3D7, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYEG..HANGUL SYLLABLE SSYEH + {0xC3D8, 0xC3D8, prH2, gcLo}, // HANGUL SYLLABLE SSO + {0xC3D9, 0xC3F3, prH3, gcLo}, // [27] HANGUL SYLLABLE SSOG..HANGUL SYLLABLE SSOH + {0xC3F4, 0xC3F4, prH2, gcLo}, // HANGUL SYLLABLE SSWA + {0xC3F5, 0xC40F, prH3, gcLo}, // [27] HANGUL SYLLABLE SSWAG..HANGUL SYLLABLE SSWAH + {0xC410, 0xC410, prH2, gcLo}, // HANGUL SYLLABLE SSWAE + {0xC411, 0xC42B, prH3, gcLo}, // [27] HANGUL SYLLABLE SSWAEG..HANGUL SYLLABLE SSWAEH + {0xC42C, 0xC42C, prH2, gcLo}, // HANGUL SYLLABLE SSOE + {0xC42D, 0xC447, prH3, gcLo}, // [27] HANGUL SYLLABLE SSOEG..HANGUL SYLLABLE SSOEH + {0xC448, 0xC448, prH2, gcLo}, // HANGUL SYLLABLE SSYO + {0xC449, 0xC463, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYOG..HANGUL SYLLABLE SSYOH + {0xC464, 0xC464, prH2, gcLo}, // HANGUL SYLLABLE SSU + {0xC465, 0xC47F, prH3, gcLo}, // [27] HANGUL SYLLABLE SSUG..HANGUL SYLLABLE SSUH + {0xC480, 0xC480, prH2, gcLo}, // HANGUL SYLLABLE SSWEO + {0xC481, 0xC49B, prH3, gcLo}, // [27] HANGUL SYLLABLE SSWEOG..HANGUL SYLLABLE SSWEOH + {0xC49C, 0xC49C, prH2, gcLo}, // HANGUL SYLLABLE SSWE + {0xC49D, 0xC4B7, prH3, gcLo}, // [27] HANGUL SYLLABLE SSWEG..HANGUL SYLLABLE SSWEH + {0xC4B8, 0xC4B8, prH2, gcLo}, // HANGUL SYLLABLE SSWI + {0xC4B9, 0xC4D3, prH3, gcLo}, // [27] HANGUL SYLLABLE SSWIG..HANGUL SYLLABLE SSWIH + {0xC4D4, 0xC4D4, prH2, gcLo}, // HANGUL SYLLABLE SSYU + {0xC4D5, 0xC4EF, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYUG..HANGUL SYLLABLE SSYUH + {0xC4F0, 0xC4F0, prH2, gcLo}, // HANGUL SYLLABLE SSEU + {0xC4F1, 0xC50B, prH3, gcLo}, // [27] HANGUL SYLLABLE SSEUG..HANGUL SYLLABLE SSEUH + {0xC50C, 0xC50C, prH2, gcLo}, // HANGUL SYLLABLE SSYI + {0xC50D, 0xC527, prH3, gcLo}, // [27] HANGUL SYLLABLE SSYIG..HANGUL SYLLABLE SSYIH + {0xC528, 0xC528, prH2, gcLo}, // HANGUL SYLLABLE SSI + {0xC529, 0xC543, prH3, gcLo}, // [27] HANGUL SYLLABLE SSIG..HANGUL SYLLABLE SSIH + {0xC544, 0xC544, prH2, gcLo}, // HANGUL SYLLABLE A + {0xC545, 0xC55F, prH3, gcLo}, // [27] HANGUL SYLLABLE AG..HANGUL SYLLABLE AH + {0xC560, 0xC560, prH2, gcLo}, // HANGUL SYLLABLE AE + {0xC561, 0xC57B, prH3, gcLo}, // [27] HANGUL SYLLABLE AEG..HANGUL SYLLABLE AEH + {0xC57C, 0xC57C, prH2, gcLo}, // HANGUL SYLLABLE YA + {0xC57D, 0xC597, prH3, gcLo}, // [27] HANGUL SYLLABLE YAG..HANGUL SYLLABLE YAH + {0xC598, 0xC598, prH2, gcLo}, // HANGUL SYLLABLE YAE + {0xC599, 0xC5B3, prH3, gcLo}, // [27] HANGUL SYLLABLE YAEG..HANGUL SYLLABLE YAEH + {0xC5B4, 0xC5B4, prH2, gcLo}, // HANGUL SYLLABLE EO + {0xC5B5, 0xC5CF, prH3, gcLo}, // [27] HANGUL SYLLABLE EOG..HANGUL SYLLABLE EOH + {0xC5D0, 0xC5D0, prH2, gcLo}, // HANGUL SYLLABLE E + {0xC5D1, 0xC5EB, prH3, gcLo}, // [27] HANGUL SYLLABLE EG..HANGUL SYLLABLE EH + {0xC5EC, 0xC5EC, prH2, gcLo}, // HANGUL SYLLABLE YEO + {0xC5ED, 0xC607, prH3, gcLo}, // [27] HANGUL SYLLABLE YEOG..HANGUL SYLLABLE YEOH + {0xC608, 0xC608, prH2, gcLo}, // HANGUL SYLLABLE YE + {0xC609, 0xC623, prH3, gcLo}, // [27] HANGUL SYLLABLE YEG..HANGUL SYLLABLE YEH + {0xC624, 0xC624, prH2, gcLo}, // HANGUL SYLLABLE O + {0xC625, 0xC63F, prH3, gcLo}, // [27] HANGUL SYLLABLE OG..HANGUL SYLLABLE OH + {0xC640, 0xC640, prH2, gcLo}, // HANGUL SYLLABLE WA + {0xC641, 0xC65B, prH3, gcLo}, // [27] HANGUL SYLLABLE WAG..HANGUL SYLLABLE WAH + {0xC65C, 0xC65C, prH2, gcLo}, // HANGUL SYLLABLE WAE + {0xC65D, 0xC677, prH3, gcLo}, // [27] HANGUL SYLLABLE WAEG..HANGUL SYLLABLE WAEH + {0xC678, 0xC678, prH2, gcLo}, // HANGUL SYLLABLE OE + {0xC679, 0xC693, prH3, gcLo}, // [27] HANGUL SYLLABLE OEG..HANGUL SYLLABLE OEH + {0xC694, 0xC694, prH2, gcLo}, // HANGUL SYLLABLE YO + {0xC695, 0xC6AF, prH3, gcLo}, // [27] HANGUL SYLLABLE YOG..HANGUL SYLLABLE YOH + {0xC6B0, 0xC6B0, prH2, gcLo}, // HANGUL SYLLABLE U + {0xC6B1, 0xC6CB, prH3, gcLo}, // [27] HANGUL SYLLABLE UG..HANGUL SYLLABLE UH + {0xC6CC, 0xC6CC, prH2, gcLo}, // HANGUL SYLLABLE WEO + {0xC6CD, 0xC6E7, prH3, gcLo}, // [27] HANGUL SYLLABLE WEOG..HANGUL SYLLABLE WEOH + {0xC6E8, 0xC6E8, prH2, gcLo}, // HANGUL SYLLABLE WE + {0xC6E9, 0xC703, prH3, gcLo}, // [27] HANGUL SYLLABLE WEG..HANGUL SYLLABLE WEH + {0xC704, 0xC704, prH2, gcLo}, // HANGUL SYLLABLE WI + {0xC705, 0xC71F, prH3, gcLo}, // [27] HANGUL SYLLABLE WIG..HANGUL SYLLABLE WIH + {0xC720, 0xC720, prH2, gcLo}, // HANGUL SYLLABLE YU + {0xC721, 0xC73B, prH3, gcLo}, // [27] HANGUL SYLLABLE YUG..HANGUL SYLLABLE YUH + {0xC73C, 0xC73C, prH2, gcLo}, // HANGUL SYLLABLE EU + {0xC73D, 0xC757, prH3, gcLo}, // [27] HANGUL SYLLABLE EUG..HANGUL SYLLABLE EUH + {0xC758, 0xC758, prH2, gcLo}, // HANGUL SYLLABLE YI + {0xC759, 0xC773, prH3, gcLo}, // [27] HANGUL SYLLABLE YIG..HANGUL SYLLABLE YIH + {0xC774, 0xC774, prH2, gcLo}, // HANGUL SYLLABLE I + {0xC775, 0xC78F, prH3, gcLo}, // [27] HANGUL SYLLABLE IG..HANGUL SYLLABLE IH + {0xC790, 0xC790, prH2, gcLo}, // HANGUL SYLLABLE JA + {0xC791, 0xC7AB, prH3, gcLo}, // [27] HANGUL SYLLABLE JAG..HANGUL SYLLABLE JAH + {0xC7AC, 0xC7AC, prH2, gcLo}, // HANGUL SYLLABLE JAE + {0xC7AD, 0xC7C7, prH3, gcLo}, // [27] HANGUL SYLLABLE JAEG..HANGUL SYLLABLE JAEH + {0xC7C8, 0xC7C8, prH2, gcLo}, // HANGUL SYLLABLE JYA + {0xC7C9, 0xC7E3, prH3, gcLo}, // [27] HANGUL SYLLABLE JYAG..HANGUL SYLLABLE JYAH + {0xC7E4, 0xC7E4, prH2, gcLo}, // HANGUL SYLLABLE JYAE + {0xC7E5, 0xC7FF, prH3, gcLo}, // [27] HANGUL SYLLABLE JYAEG..HANGUL SYLLABLE JYAEH + {0xC800, 0xC800, prH2, gcLo}, // HANGUL SYLLABLE JEO + {0xC801, 0xC81B, prH3, gcLo}, // [27] HANGUL SYLLABLE JEOG..HANGUL SYLLABLE JEOH + {0xC81C, 0xC81C, prH2, gcLo}, // HANGUL SYLLABLE JE + {0xC81D, 0xC837, prH3, gcLo}, // [27] HANGUL SYLLABLE JEG..HANGUL SYLLABLE JEH + {0xC838, 0xC838, prH2, gcLo}, // HANGUL SYLLABLE JYEO + {0xC839, 0xC853, prH3, gcLo}, // [27] HANGUL SYLLABLE JYEOG..HANGUL SYLLABLE JYEOH + {0xC854, 0xC854, prH2, gcLo}, // HANGUL SYLLABLE JYE + {0xC855, 0xC86F, prH3, gcLo}, // [27] HANGUL SYLLABLE JYEG..HANGUL SYLLABLE JYEH + {0xC870, 0xC870, prH2, gcLo}, // HANGUL SYLLABLE JO + {0xC871, 0xC88B, prH3, gcLo}, // [27] HANGUL SYLLABLE JOG..HANGUL SYLLABLE JOH + {0xC88C, 0xC88C, prH2, gcLo}, // HANGUL SYLLABLE JWA + {0xC88D, 0xC8A7, prH3, gcLo}, // [27] HANGUL SYLLABLE JWAG..HANGUL SYLLABLE JWAH + {0xC8A8, 0xC8A8, prH2, gcLo}, // HANGUL SYLLABLE JWAE + {0xC8A9, 0xC8C3, prH3, gcLo}, // [27] HANGUL SYLLABLE JWAEG..HANGUL SYLLABLE JWAEH + {0xC8C4, 0xC8C4, prH2, gcLo}, // HANGUL SYLLABLE JOE + {0xC8C5, 0xC8DF, prH3, gcLo}, // [27] HANGUL SYLLABLE JOEG..HANGUL SYLLABLE JOEH + {0xC8E0, 0xC8E0, prH2, gcLo}, // HANGUL SYLLABLE JYO + {0xC8E1, 0xC8FB, prH3, gcLo}, // [27] HANGUL SYLLABLE JYOG..HANGUL SYLLABLE JYOH + {0xC8FC, 0xC8FC, prH2, gcLo}, // HANGUL SYLLABLE JU + {0xC8FD, 0xC917, prH3, gcLo}, // [27] HANGUL SYLLABLE JUG..HANGUL SYLLABLE JUH + {0xC918, 0xC918, prH2, gcLo}, // HANGUL SYLLABLE JWEO + {0xC919, 0xC933, prH3, gcLo}, // [27] HANGUL SYLLABLE JWEOG..HANGUL SYLLABLE JWEOH + {0xC934, 0xC934, prH2, gcLo}, // HANGUL SYLLABLE JWE + {0xC935, 0xC94F, prH3, gcLo}, // [27] HANGUL SYLLABLE JWEG..HANGUL SYLLABLE JWEH + {0xC950, 0xC950, prH2, gcLo}, // HANGUL SYLLABLE JWI + {0xC951, 0xC96B, prH3, gcLo}, // [27] HANGUL SYLLABLE JWIG..HANGUL SYLLABLE JWIH + {0xC96C, 0xC96C, prH2, gcLo}, // HANGUL SYLLABLE JYU + {0xC96D, 0xC987, prH3, gcLo}, // [27] HANGUL SYLLABLE JYUG..HANGUL SYLLABLE JYUH + {0xC988, 0xC988, prH2, gcLo}, // HANGUL SYLLABLE JEU + {0xC989, 0xC9A3, prH3, gcLo}, // [27] HANGUL SYLLABLE JEUG..HANGUL SYLLABLE JEUH + {0xC9A4, 0xC9A4, prH2, gcLo}, // HANGUL SYLLABLE JYI + {0xC9A5, 0xC9BF, prH3, gcLo}, // [27] HANGUL SYLLABLE JYIG..HANGUL SYLLABLE JYIH + {0xC9C0, 0xC9C0, prH2, gcLo}, // HANGUL SYLLABLE JI + {0xC9C1, 0xC9DB, prH3, gcLo}, // [27] HANGUL SYLLABLE JIG..HANGUL SYLLABLE JIH + {0xC9DC, 0xC9DC, prH2, gcLo}, // HANGUL SYLLABLE JJA + {0xC9DD, 0xC9F7, prH3, gcLo}, // [27] HANGUL SYLLABLE JJAG..HANGUL SYLLABLE JJAH + {0xC9F8, 0xC9F8, prH2, gcLo}, // HANGUL SYLLABLE JJAE + {0xC9F9, 0xCA13, prH3, gcLo}, // [27] HANGUL SYLLABLE JJAEG..HANGUL SYLLABLE JJAEH + {0xCA14, 0xCA14, prH2, gcLo}, // HANGUL SYLLABLE JJYA + {0xCA15, 0xCA2F, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYAG..HANGUL SYLLABLE JJYAH + {0xCA30, 0xCA30, prH2, gcLo}, // HANGUL SYLLABLE JJYAE + {0xCA31, 0xCA4B, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYAEG..HANGUL SYLLABLE JJYAEH + {0xCA4C, 0xCA4C, prH2, gcLo}, // HANGUL SYLLABLE JJEO + {0xCA4D, 0xCA67, prH3, gcLo}, // [27] HANGUL SYLLABLE JJEOG..HANGUL SYLLABLE JJEOH + {0xCA68, 0xCA68, prH2, gcLo}, // HANGUL SYLLABLE JJE + {0xCA69, 0xCA83, prH3, gcLo}, // [27] HANGUL SYLLABLE JJEG..HANGUL SYLLABLE JJEH + {0xCA84, 0xCA84, prH2, gcLo}, // HANGUL SYLLABLE JJYEO + {0xCA85, 0xCA9F, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYEOG..HANGUL SYLLABLE JJYEOH + {0xCAA0, 0xCAA0, prH2, gcLo}, // HANGUL SYLLABLE JJYE + {0xCAA1, 0xCABB, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYEG..HANGUL SYLLABLE JJYEH + {0xCABC, 0xCABC, prH2, gcLo}, // HANGUL SYLLABLE JJO + {0xCABD, 0xCAD7, prH3, gcLo}, // [27] HANGUL SYLLABLE JJOG..HANGUL SYLLABLE JJOH + {0xCAD8, 0xCAD8, prH2, gcLo}, // HANGUL SYLLABLE JJWA + {0xCAD9, 0xCAF3, prH3, gcLo}, // [27] HANGUL SYLLABLE JJWAG..HANGUL SYLLABLE JJWAH + {0xCAF4, 0xCAF4, prH2, gcLo}, // HANGUL SYLLABLE JJWAE + {0xCAF5, 0xCB0F, prH3, gcLo}, // [27] HANGUL SYLLABLE JJWAEG..HANGUL SYLLABLE JJWAEH + {0xCB10, 0xCB10, prH2, gcLo}, // HANGUL SYLLABLE JJOE + {0xCB11, 0xCB2B, prH3, gcLo}, // [27] HANGUL SYLLABLE JJOEG..HANGUL SYLLABLE JJOEH + {0xCB2C, 0xCB2C, prH2, gcLo}, // HANGUL SYLLABLE JJYO + {0xCB2D, 0xCB47, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYOG..HANGUL SYLLABLE JJYOH + {0xCB48, 0xCB48, prH2, gcLo}, // HANGUL SYLLABLE JJU + {0xCB49, 0xCB63, prH3, gcLo}, // [27] HANGUL SYLLABLE JJUG..HANGUL SYLLABLE JJUH + {0xCB64, 0xCB64, prH2, gcLo}, // HANGUL SYLLABLE JJWEO + {0xCB65, 0xCB7F, prH3, gcLo}, // [27] HANGUL SYLLABLE JJWEOG..HANGUL SYLLABLE JJWEOH + {0xCB80, 0xCB80, prH2, gcLo}, // HANGUL SYLLABLE JJWE + {0xCB81, 0xCB9B, prH3, gcLo}, // [27] HANGUL SYLLABLE JJWEG..HANGUL SYLLABLE JJWEH + {0xCB9C, 0xCB9C, prH2, gcLo}, // HANGUL SYLLABLE JJWI + {0xCB9D, 0xCBB7, prH3, gcLo}, // [27] HANGUL SYLLABLE JJWIG..HANGUL SYLLABLE JJWIH + {0xCBB8, 0xCBB8, prH2, gcLo}, // HANGUL SYLLABLE JJYU + {0xCBB9, 0xCBD3, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYUG..HANGUL SYLLABLE JJYUH + {0xCBD4, 0xCBD4, prH2, gcLo}, // HANGUL SYLLABLE JJEU + {0xCBD5, 0xCBEF, prH3, gcLo}, // [27] HANGUL SYLLABLE JJEUG..HANGUL SYLLABLE JJEUH + {0xCBF0, 0xCBF0, prH2, gcLo}, // HANGUL SYLLABLE JJYI + {0xCBF1, 0xCC0B, prH3, gcLo}, // [27] HANGUL SYLLABLE JJYIG..HANGUL SYLLABLE JJYIH + {0xCC0C, 0xCC0C, prH2, gcLo}, // HANGUL SYLLABLE JJI + {0xCC0D, 0xCC27, prH3, gcLo}, // [27] HANGUL SYLLABLE JJIG..HANGUL SYLLABLE JJIH + {0xCC28, 0xCC28, prH2, gcLo}, // HANGUL SYLLABLE CA + {0xCC29, 0xCC43, prH3, gcLo}, // [27] HANGUL SYLLABLE CAG..HANGUL SYLLABLE CAH + {0xCC44, 0xCC44, prH2, gcLo}, // HANGUL SYLLABLE CAE + {0xCC45, 0xCC5F, prH3, gcLo}, // [27] HANGUL SYLLABLE CAEG..HANGUL SYLLABLE CAEH + {0xCC60, 0xCC60, prH2, gcLo}, // HANGUL SYLLABLE CYA + {0xCC61, 0xCC7B, prH3, gcLo}, // [27] HANGUL SYLLABLE CYAG..HANGUL SYLLABLE CYAH + {0xCC7C, 0xCC7C, prH2, gcLo}, // HANGUL SYLLABLE CYAE + {0xCC7D, 0xCC97, prH3, gcLo}, // [27] HANGUL SYLLABLE CYAEG..HANGUL SYLLABLE CYAEH + {0xCC98, 0xCC98, prH2, gcLo}, // HANGUL SYLLABLE CEO + {0xCC99, 0xCCB3, prH3, gcLo}, // [27] HANGUL SYLLABLE CEOG..HANGUL SYLLABLE CEOH + {0xCCB4, 0xCCB4, prH2, gcLo}, // HANGUL SYLLABLE CE + {0xCCB5, 0xCCCF, prH3, gcLo}, // [27] HANGUL SYLLABLE CEG..HANGUL SYLLABLE CEH + {0xCCD0, 0xCCD0, prH2, gcLo}, // HANGUL SYLLABLE CYEO + {0xCCD1, 0xCCEB, prH3, gcLo}, // [27] HANGUL SYLLABLE CYEOG..HANGUL SYLLABLE CYEOH + {0xCCEC, 0xCCEC, prH2, gcLo}, // HANGUL SYLLABLE CYE + {0xCCED, 0xCD07, prH3, gcLo}, // [27] HANGUL SYLLABLE CYEG..HANGUL SYLLABLE CYEH + {0xCD08, 0xCD08, prH2, gcLo}, // HANGUL SYLLABLE CO + {0xCD09, 0xCD23, prH3, gcLo}, // [27] HANGUL SYLLABLE COG..HANGUL SYLLABLE COH + {0xCD24, 0xCD24, prH2, gcLo}, // HANGUL SYLLABLE CWA + {0xCD25, 0xCD3F, prH3, gcLo}, // [27] HANGUL SYLLABLE CWAG..HANGUL SYLLABLE CWAH + {0xCD40, 0xCD40, prH2, gcLo}, // HANGUL SYLLABLE CWAE + {0xCD41, 0xCD5B, prH3, gcLo}, // [27] HANGUL SYLLABLE CWAEG..HANGUL SYLLABLE CWAEH + {0xCD5C, 0xCD5C, prH2, gcLo}, // HANGUL SYLLABLE COE + {0xCD5D, 0xCD77, prH3, gcLo}, // [27] HANGUL SYLLABLE COEG..HANGUL SYLLABLE COEH + {0xCD78, 0xCD78, prH2, gcLo}, // HANGUL SYLLABLE CYO + {0xCD79, 0xCD93, prH3, gcLo}, // [27] HANGUL SYLLABLE CYOG..HANGUL SYLLABLE CYOH + {0xCD94, 0xCD94, prH2, gcLo}, // HANGUL SYLLABLE CU + {0xCD95, 0xCDAF, prH3, gcLo}, // [27] HANGUL SYLLABLE CUG..HANGUL SYLLABLE CUH + {0xCDB0, 0xCDB0, prH2, gcLo}, // HANGUL SYLLABLE CWEO + {0xCDB1, 0xCDCB, prH3, gcLo}, // [27] HANGUL SYLLABLE CWEOG..HANGUL SYLLABLE CWEOH + {0xCDCC, 0xCDCC, prH2, gcLo}, // HANGUL SYLLABLE CWE + {0xCDCD, 0xCDE7, prH3, gcLo}, // [27] HANGUL SYLLABLE CWEG..HANGUL SYLLABLE CWEH + {0xCDE8, 0xCDE8, prH2, gcLo}, // HANGUL SYLLABLE CWI + {0xCDE9, 0xCE03, prH3, gcLo}, // [27] HANGUL SYLLABLE CWIG..HANGUL SYLLABLE CWIH + {0xCE04, 0xCE04, prH2, gcLo}, // HANGUL SYLLABLE CYU + {0xCE05, 0xCE1F, prH3, gcLo}, // [27] HANGUL SYLLABLE CYUG..HANGUL SYLLABLE CYUH + {0xCE20, 0xCE20, prH2, gcLo}, // HANGUL SYLLABLE CEU + {0xCE21, 0xCE3B, prH3, gcLo}, // [27] HANGUL SYLLABLE CEUG..HANGUL SYLLABLE CEUH + {0xCE3C, 0xCE3C, prH2, gcLo}, // HANGUL SYLLABLE CYI + {0xCE3D, 0xCE57, prH3, gcLo}, // [27] HANGUL SYLLABLE CYIG..HANGUL SYLLABLE CYIH + {0xCE58, 0xCE58, prH2, gcLo}, // HANGUL SYLLABLE CI + {0xCE59, 0xCE73, prH3, gcLo}, // [27] HANGUL SYLLABLE CIG..HANGUL SYLLABLE CIH + {0xCE74, 0xCE74, prH2, gcLo}, // HANGUL SYLLABLE KA + {0xCE75, 0xCE8F, prH3, gcLo}, // [27] HANGUL SYLLABLE KAG..HANGUL SYLLABLE KAH + {0xCE90, 0xCE90, prH2, gcLo}, // HANGUL SYLLABLE KAE + {0xCE91, 0xCEAB, prH3, gcLo}, // [27] HANGUL SYLLABLE KAEG..HANGUL SYLLABLE KAEH + {0xCEAC, 0xCEAC, prH2, gcLo}, // HANGUL SYLLABLE KYA + {0xCEAD, 0xCEC7, prH3, gcLo}, // [27] HANGUL SYLLABLE KYAG..HANGUL SYLLABLE KYAH + {0xCEC8, 0xCEC8, prH2, gcLo}, // HANGUL SYLLABLE KYAE + {0xCEC9, 0xCEE3, prH3, gcLo}, // [27] HANGUL SYLLABLE KYAEG..HANGUL SYLLABLE KYAEH + {0xCEE4, 0xCEE4, prH2, gcLo}, // HANGUL SYLLABLE KEO + {0xCEE5, 0xCEFF, prH3, gcLo}, // [27] HANGUL SYLLABLE KEOG..HANGUL SYLLABLE KEOH + {0xCF00, 0xCF00, prH2, gcLo}, // HANGUL SYLLABLE KE + {0xCF01, 0xCF1B, prH3, gcLo}, // [27] HANGUL SYLLABLE KEG..HANGUL SYLLABLE KEH + {0xCF1C, 0xCF1C, prH2, gcLo}, // HANGUL SYLLABLE KYEO + {0xCF1D, 0xCF37, prH3, gcLo}, // [27] HANGUL SYLLABLE KYEOG..HANGUL SYLLABLE KYEOH + {0xCF38, 0xCF38, prH2, gcLo}, // HANGUL SYLLABLE KYE + {0xCF39, 0xCF53, prH3, gcLo}, // [27] HANGUL SYLLABLE KYEG..HANGUL SYLLABLE KYEH + {0xCF54, 0xCF54, prH2, gcLo}, // HANGUL SYLLABLE KO + {0xCF55, 0xCF6F, prH3, gcLo}, // [27] HANGUL SYLLABLE KOG..HANGUL SYLLABLE KOH + {0xCF70, 0xCF70, prH2, gcLo}, // HANGUL SYLLABLE KWA + {0xCF71, 0xCF8B, prH3, gcLo}, // [27] HANGUL SYLLABLE KWAG..HANGUL SYLLABLE KWAH + {0xCF8C, 0xCF8C, prH2, gcLo}, // HANGUL SYLLABLE KWAE + {0xCF8D, 0xCFA7, prH3, gcLo}, // [27] HANGUL SYLLABLE KWAEG..HANGUL SYLLABLE KWAEH + {0xCFA8, 0xCFA8, prH2, gcLo}, // HANGUL SYLLABLE KOE + {0xCFA9, 0xCFC3, prH3, gcLo}, // [27] HANGUL SYLLABLE KOEG..HANGUL SYLLABLE KOEH + {0xCFC4, 0xCFC4, prH2, gcLo}, // HANGUL SYLLABLE KYO + {0xCFC5, 0xCFDF, prH3, gcLo}, // [27] HANGUL SYLLABLE KYOG..HANGUL SYLLABLE KYOH + {0xCFE0, 0xCFE0, prH2, gcLo}, // HANGUL SYLLABLE KU + {0xCFE1, 0xCFFB, prH3, gcLo}, // [27] HANGUL SYLLABLE KUG..HANGUL SYLLABLE KUH + {0xCFFC, 0xCFFC, prH2, gcLo}, // HANGUL SYLLABLE KWEO + {0xCFFD, 0xD017, prH3, gcLo}, // [27] HANGUL SYLLABLE KWEOG..HANGUL SYLLABLE KWEOH + {0xD018, 0xD018, prH2, gcLo}, // HANGUL SYLLABLE KWE + {0xD019, 0xD033, prH3, gcLo}, // [27] HANGUL SYLLABLE KWEG..HANGUL SYLLABLE KWEH + {0xD034, 0xD034, prH2, gcLo}, // HANGUL SYLLABLE KWI + {0xD035, 0xD04F, prH3, gcLo}, // [27] HANGUL SYLLABLE KWIG..HANGUL SYLLABLE KWIH + {0xD050, 0xD050, prH2, gcLo}, // HANGUL SYLLABLE KYU + {0xD051, 0xD06B, prH3, gcLo}, // [27] HANGUL SYLLABLE KYUG..HANGUL SYLLABLE KYUH + {0xD06C, 0xD06C, prH2, gcLo}, // HANGUL SYLLABLE KEU + {0xD06D, 0xD087, prH3, gcLo}, // [27] HANGUL SYLLABLE KEUG..HANGUL SYLLABLE KEUH + {0xD088, 0xD088, prH2, gcLo}, // HANGUL SYLLABLE KYI + {0xD089, 0xD0A3, prH3, gcLo}, // [27] HANGUL SYLLABLE KYIG..HANGUL SYLLABLE KYIH + {0xD0A4, 0xD0A4, prH2, gcLo}, // HANGUL SYLLABLE KI + {0xD0A5, 0xD0BF, prH3, gcLo}, // [27] HANGUL SYLLABLE KIG..HANGUL SYLLABLE KIH + {0xD0C0, 0xD0C0, prH2, gcLo}, // HANGUL SYLLABLE TA + {0xD0C1, 0xD0DB, prH3, gcLo}, // [27] HANGUL SYLLABLE TAG..HANGUL SYLLABLE TAH + {0xD0DC, 0xD0DC, prH2, gcLo}, // HANGUL SYLLABLE TAE + {0xD0DD, 0xD0F7, prH3, gcLo}, // [27] HANGUL SYLLABLE TAEG..HANGUL SYLLABLE TAEH + {0xD0F8, 0xD0F8, prH2, gcLo}, // HANGUL SYLLABLE TYA + {0xD0F9, 0xD113, prH3, gcLo}, // [27] HANGUL SYLLABLE TYAG..HANGUL SYLLABLE TYAH + {0xD114, 0xD114, prH2, gcLo}, // HANGUL SYLLABLE TYAE + {0xD115, 0xD12F, prH3, gcLo}, // [27] HANGUL SYLLABLE TYAEG..HANGUL SYLLABLE TYAEH + {0xD130, 0xD130, prH2, gcLo}, // HANGUL SYLLABLE TEO + {0xD131, 0xD14B, prH3, gcLo}, // [27] HANGUL SYLLABLE TEOG..HANGUL SYLLABLE TEOH + {0xD14C, 0xD14C, prH2, gcLo}, // HANGUL SYLLABLE TE + {0xD14D, 0xD167, prH3, gcLo}, // [27] HANGUL SYLLABLE TEG..HANGUL SYLLABLE TEH + {0xD168, 0xD168, prH2, gcLo}, // HANGUL SYLLABLE TYEO + {0xD169, 0xD183, prH3, gcLo}, // [27] HANGUL SYLLABLE TYEOG..HANGUL SYLLABLE TYEOH + {0xD184, 0xD184, prH2, gcLo}, // HANGUL SYLLABLE TYE + {0xD185, 0xD19F, prH3, gcLo}, // [27] HANGUL SYLLABLE TYEG..HANGUL SYLLABLE TYEH + {0xD1A0, 0xD1A0, prH2, gcLo}, // HANGUL SYLLABLE TO + {0xD1A1, 0xD1BB, prH3, gcLo}, // [27] HANGUL SYLLABLE TOG..HANGUL SYLLABLE TOH + {0xD1BC, 0xD1BC, prH2, gcLo}, // HANGUL SYLLABLE TWA + {0xD1BD, 0xD1D7, prH3, gcLo}, // [27] HANGUL SYLLABLE TWAG..HANGUL SYLLABLE TWAH + {0xD1D8, 0xD1D8, prH2, gcLo}, // HANGUL SYLLABLE TWAE + {0xD1D9, 0xD1F3, prH3, gcLo}, // [27] HANGUL SYLLABLE TWAEG..HANGUL SYLLABLE TWAEH + {0xD1F4, 0xD1F4, prH2, gcLo}, // HANGUL SYLLABLE TOE + {0xD1F5, 0xD20F, prH3, gcLo}, // [27] HANGUL SYLLABLE TOEG..HANGUL SYLLABLE TOEH + {0xD210, 0xD210, prH2, gcLo}, // HANGUL SYLLABLE TYO + {0xD211, 0xD22B, prH3, gcLo}, // [27] HANGUL SYLLABLE TYOG..HANGUL SYLLABLE TYOH + {0xD22C, 0xD22C, prH2, gcLo}, // HANGUL SYLLABLE TU + {0xD22D, 0xD247, prH3, gcLo}, // [27] HANGUL SYLLABLE TUG..HANGUL SYLLABLE TUH + {0xD248, 0xD248, prH2, gcLo}, // HANGUL SYLLABLE TWEO + {0xD249, 0xD263, prH3, gcLo}, // [27] HANGUL SYLLABLE TWEOG..HANGUL SYLLABLE TWEOH + {0xD264, 0xD264, prH2, gcLo}, // HANGUL SYLLABLE TWE + {0xD265, 0xD27F, prH3, gcLo}, // [27] HANGUL SYLLABLE TWEG..HANGUL SYLLABLE TWEH + {0xD280, 0xD280, prH2, gcLo}, // HANGUL SYLLABLE TWI + {0xD281, 0xD29B, prH3, gcLo}, // [27] HANGUL SYLLABLE TWIG..HANGUL SYLLABLE TWIH + {0xD29C, 0xD29C, prH2, gcLo}, // HANGUL SYLLABLE TYU + {0xD29D, 0xD2B7, prH3, gcLo}, // [27] HANGUL SYLLABLE TYUG..HANGUL SYLLABLE TYUH + {0xD2B8, 0xD2B8, prH2, gcLo}, // HANGUL SYLLABLE TEU + {0xD2B9, 0xD2D3, prH3, gcLo}, // [27] HANGUL SYLLABLE TEUG..HANGUL SYLLABLE TEUH + {0xD2D4, 0xD2D4, prH2, gcLo}, // HANGUL SYLLABLE TYI + {0xD2D5, 0xD2EF, prH3, gcLo}, // [27] HANGUL SYLLABLE TYIG..HANGUL SYLLABLE TYIH + {0xD2F0, 0xD2F0, prH2, gcLo}, // HANGUL SYLLABLE TI + {0xD2F1, 0xD30B, prH3, gcLo}, // [27] HANGUL SYLLABLE TIG..HANGUL SYLLABLE TIH + {0xD30C, 0xD30C, prH2, gcLo}, // HANGUL SYLLABLE PA + {0xD30D, 0xD327, prH3, gcLo}, // [27] HANGUL SYLLABLE PAG..HANGUL SYLLABLE PAH + {0xD328, 0xD328, prH2, gcLo}, // HANGUL SYLLABLE PAE + {0xD329, 0xD343, prH3, gcLo}, // [27] HANGUL SYLLABLE PAEG..HANGUL SYLLABLE PAEH + {0xD344, 0xD344, prH2, gcLo}, // HANGUL SYLLABLE PYA + {0xD345, 0xD35F, prH3, gcLo}, // [27] HANGUL SYLLABLE PYAG..HANGUL SYLLABLE PYAH + {0xD360, 0xD360, prH2, gcLo}, // HANGUL SYLLABLE PYAE + {0xD361, 0xD37B, prH3, gcLo}, // [27] HANGUL SYLLABLE PYAEG..HANGUL SYLLABLE PYAEH + {0xD37C, 0xD37C, prH2, gcLo}, // HANGUL SYLLABLE PEO + {0xD37D, 0xD397, prH3, gcLo}, // [27] HANGUL SYLLABLE PEOG..HANGUL SYLLABLE PEOH + {0xD398, 0xD398, prH2, gcLo}, // HANGUL SYLLABLE PE + {0xD399, 0xD3B3, prH3, gcLo}, // [27] HANGUL SYLLABLE PEG..HANGUL SYLLABLE PEH + {0xD3B4, 0xD3B4, prH2, gcLo}, // HANGUL SYLLABLE PYEO + {0xD3B5, 0xD3CF, prH3, gcLo}, // [27] HANGUL SYLLABLE PYEOG..HANGUL SYLLABLE PYEOH + {0xD3D0, 0xD3D0, prH2, gcLo}, // HANGUL SYLLABLE PYE + {0xD3D1, 0xD3EB, prH3, gcLo}, // [27] HANGUL SYLLABLE PYEG..HANGUL SYLLABLE PYEH + {0xD3EC, 0xD3EC, prH2, gcLo}, // HANGUL SYLLABLE PO + {0xD3ED, 0xD407, prH3, gcLo}, // [27] HANGUL SYLLABLE POG..HANGUL SYLLABLE POH + {0xD408, 0xD408, prH2, gcLo}, // HANGUL SYLLABLE PWA + {0xD409, 0xD423, prH3, gcLo}, // [27] HANGUL SYLLABLE PWAG..HANGUL SYLLABLE PWAH + {0xD424, 0xD424, prH2, gcLo}, // HANGUL SYLLABLE PWAE + {0xD425, 0xD43F, prH3, gcLo}, // [27] HANGUL SYLLABLE PWAEG..HANGUL SYLLABLE PWAEH + {0xD440, 0xD440, prH2, gcLo}, // HANGUL SYLLABLE POE + {0xD441, 0xD45B, prH3, gcLo}, // [27] HANGUL SYLLABLE POEG..HANGUL SYLLABLE POEH + {0xD45C, 0xD45C, prH2, gcLo}, // HANGUL SYLLABLE PYO + {0xD45D, 0xD477, prH3, gcLo}, // [27] HANGUL SYLLABLE PYOG..HANGUL SYLLABLE PYOH + {0xD478, 0xD478, prH2, gcLo}, // HANGUL SYLLABLE PU + {0xD479, 0xD493, prH3, gcLo}, // [27] HANGUL SYLLABLE PUG..HANGUL SYLLABLE PUH + {0xD494, 0xD494, prH2, gcLo}, // HANGUL SYLLABLE PWEO + {0xD495, 0xD4AF, prH3, gcLo}, // [27] HANGUL SYLLABLE PWEOG..HANGUL SYLLABLE PWEOH + {0xD4B0, 0xD4B0, prH2, gcLo}, // HANGUL SYLLABLE PWE + {0xD4B1, 0xD4CB, prH3, gcLo}, // [27] HANGUL SYLLABLE PWEG..HANGUL SYLLABLE PWEH + {0xD4CC, 0xD4CC, prH2, gcLo}, // HANGUL SYLLABLE PWI + {0xD4CD, 0xD4E7, prH3, gcLo}, // [27] HANGUL SYLLABLE PWIG..HANGUL SYLLABLE PWIH + {0xD4E8, 0xD4E8, prH2, gcLo}, // HANGUL SYLLABLE PYU + {0xD4E9, 0xD503, prH3, gcLo}, // [27] HANGUL SYLLABLE PYUG..HANGUL SYLLABLE PYUH + {0xD504, 0xD504, prH2, gcLo}, // HANGUL SYLLABLE PEU + {0xD505, 0xD51F, prH3, gcLo}, // [27] HANGUL SYLLABLE PEUG..HANGUL SYLLABLE PEUH + {0xD520, 0xD520, prH2, gcLo}, // HANGUL SYLLABLE PYI + {0xD521, 0xD53B, prH3, gcLo}, // [27] HANGUL SYLLABLE PYIG..HANGUL SYLLABLE PYIH + {0xD53C, 0xD53C, prH2, gcLo}, // HANGUL SYLLABLE PI + {0xD53D, 0xD557, prH3, gcLo}, // [27] HANGUL SYLLABLE PIG..HANGUL SYLLABLE PIH + {0xD558, 0xD558, prH2, gcLo}, // HANGUL SYLLABLE HA + {0xD559, 0xD573, prH3, gcLo}, // [27] HANGUL SYLLABLE HAG..HANGUL SYLLABLE HAH + {0xD574, 0xD574, prH2, gcLo}, // HANGUL SYLLABLE HAE + {0xD575, 0xD58F, prH3, gcLo}, // [27] HANGUL SYLLABLE HAEG..HANGUL SYLLABLE HAEH + {0xD590, 0xD590, prH2, gcLo}, // HANGUL SYLLABLE HYA + {0xD591, 0xD5AB, prH3, gcLo}, // [27] HANGUL SYLLABLE HYAG..HANGUL SYLLABLE HYAH + {0xD5AC, 0xD5AC, prH2, gcLo}, // HANGUL SYLLABLE HYAE + {0xD5AD, 0xD5C7, prH3, gcLo}, // [27] HANGUL SYLLABLE HYAEG..HANGUL SYLLABLE HYAEH + {0xD5C8, 0xD5C8, prH2, gcLo}, // HANGUL SYLLABLE HEO + {0xD5C9, 0xD5E3, prH3, gcLo}, // [27] HANGUL SYLLABLE HEOG..HANGUL SYLLABLE HEOH + {0xD5E4, 0xD5E4, prH2, gcLo}, // HANGUL SYLLABLE HE + {0xD5E5, 0xD5FF, prH3, gcLo}, // [27] HANGUL SYLLABLE HEG..HANGUL SYLLABLE HEH + {0xD600, 0xD600, prH2, gcLo}, // HANGUL SYLLABLE HYEO + {0xD601, 0xD61B, prH3, gcLo}, // [27] HANGUL SYLLABLE HYEOG..HANGUL SYLLABLE HYEOH + {0xD61C, 0xD61C, prH2, gcLo}, // HANGUL SYLLABLE HYE + {0xD61D, 0xD637, prH3, gcLo}, // [27] HANGUL SYLLABLE HYEG..HANGUL SYLLABLE HYEH + {0xD638, 0xD638, prH2, gcLo}, // HANGUL SYLLABLE HO + {0xD639, 0xD653, prH3, gcLo}, // [27] HANGUL SYLLABLE HOG..HANGUL SYLLABLE HOH + {0xD654, 0xD654, prH2, gcLo}, // HANGUL SYLLABLE HWA + {0xD655, 0xD66F, prH3, gcLo}, // [27] HANGUL SYLLABLE HWAG..HANGUL SYLLABLE HWAH + {0xD670, 0xD670, prH2, gcLo}, // HANGUL SYLLABLE HWAE + {0xD671, 0xD68B, prH3, gcLo}, // [27] HANGUL SYLLABLE HWAEG..HANGUL SYLLABLE HWAEH + {0xD68C, 0xD68C, prH2, gcLo}, // HANGUL SYLLABLE HOE + {0xD68D, 0xD6A7, prH3, gcLo}, // [27] HANGUL SYLLABLE HOEG..HANGUL SYLLABLE HOEH + {0xD6A8, 0xD6A8, prH2, gcLo}, // HANGUL SYLLABLE HYO + {0xD6A9, 0xD6C3, prH3, gcLo}, // [27] HANGUL SYLLABLE HYOG..HANGUL SYLLABLE HYOH + {0xD6C4, 0xD6C4, prH2, gcLo}, // HANGUL SYLLABLE HU + {0xD6C5, 0xD6DF, prH3, gcLo}, // [27] HANGUL SYLLABLE HUG..HANGUL SYLLABLE HUH + {0xD6E0, 0xD6E0, prH2, gcLo}, // HANGUL SYLLABLE HWEO + {0xD6E1, 0xD6FB, prH3, gcLo}, // [27] HANGUL SYLLABLE HWEOG..HANGUL SYLLABLE HWEOH + {0xD6FC, 0xD6FC, prH2, gcLo}, // HANGUL SYLLABLE HWE + {0xD6FD, 0xD717, prH3, gcLo}, // [27] HANGUL SYLLABLE HWEG..HANGUL SYLLABLE HWEH + {0xD718, 0xD718, prH2, gcLo}, // HANGUL SYLLABLE HWI + {0xD719, 0xD733, prH3, gcLo}, // [27] HANGUL SYLLABLE HWIG..HANGUL SYLLABLE HWIH + {0xD734, 0xD734, prH2, gcLo}, // HANGUL SYLLABLE HYU + {0xD735, 0xD74F, prH3, gcLo}, // [27] HANGUL SYLLABLE HYUG..HANGUL SYLLABLE HYUH + {0xD750, 0xD750, prH2, gcLo}, // HANGUL SYLLABLE HEU + {0xD751, 0xD76B, prH3, gcLo}, // [27] HANGUL SYLLABLE HEUG..HANGUL SYLLABLE HEUH + {0xD76C, 0xD76C, prH2, gcLo}, // HANGUL SYLLABLE HYI + {0xD76D, 0xD787, prH3, gcLo}, // [27] HANGUL SYLLABLE HYIG..HANGUL SYLLABLE HYIH + {0xD788, 0xD788, prH2, gcLo}, // HANGUL SYLLABLE HI + {0xD789, 0xD7A3, prH3, gcLo}, // [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH + {0xD7B0, 0xD7C6, prJV, gcLo}, // [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E + {0xD7CB, 0xD7FB, prJT, gcLo}, // [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH + {0xD800, 0xDB7F, prSG, gcCs}, // [896] .. + {0xDB80, 0xDBFF, prSG, gcCs}, // [128] .. + {0xDC00, 0xDFFF, prSG, gcCs}, // [1024] .. + {0xE000, 0xF8FF, prXX, gcCo}, // [6400] .. + {0xF900, 0xFA6D, prID, gcLo}, // [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D + {0xFA6E, 0xFA6F, prID, gcCn}, // [2] .. + {0xFA70, 0xFAD9, prID, gcLo}, // [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 + {0xFADA, 0xFAFF, prID, gcCn}, // [38] .. + {0xFB00, 0xFB06, prAL, gcLl}, // [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST + {0xFB13, 0xFB17, prAL, gcLl}, // [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH + {0xFB1D, 0xFB1D, prHL, gcLo}, // HEBREW LETTER YOD WITH HIRIQ + {0xFB1E, 0xFB1E, prCM, gcMn}, // HEBREW POINT JUDEO-SPANISH VARIKA + {0xFB1F, 0xFB28, prHL, gcLo}, // [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV + {0xFB29, 0xFB29, prAL, gcSm}, // HEBREW LETTER ALTERNATIVE PLUS SIGN + {0xFB2A, 0xFB36, prHL, gcLo}, // [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH + {0xFB38, 0xFB3C, prHL, gcLo}, // [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH + {0xFB3E, 0xFB3E, prHL, gcLo}, // HEBREW LETTER MEM WITH DAGESH + {0xFB40, 0xFB41, prHL, gcLo}, // [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH + {0xFB43, 0xFB44, prHL, gcLo}, // [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH + {0xFB46, 0xFB4F, prHL, gcLo}, // [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED + {0xFB50, 0xFBB1, prAL, gcLo}, // [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM + {0xFBB2, 0xFBC2, prAL, gcSk}, // [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE + {0xFBD3, 0xFD3D, prAL, gcLo}, // [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM + {0xFD3E, 0xFD3E, prCL, gcPe}, // ORNATE LEFT PARENTHESIS + {0xFD3F, 0xFD3F, prOP, gcPs}, // ORNATE RIGHT PARENTHESIS + {0xFD40, 0xFD4F, prAL, gcSo}, // [16] ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH + {0xFD50, 0xFD8F, prAL, gcLo}, // [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM + {0xFD92, 0xFDC7, prAL, gcLo}, // [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM + {0xFDCF, 0xFDCF, prAL, gcSo}, // ARABIC LIGATURE SALAAMUHU ALAYNAA + {0xFDF0, 0xFDFB, prAL, gcLo}, // [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU + {0xFDFC, 0xFDFC, prPO, gcSc}, // RIAL SIGN + {0xFDFD, 0xFDFF, prAL, gcSo}, // [3] ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM..ARABIC LIGATURE AZZA WA JALL + {0xFE00, 0xFE0F, prCM, gcMn}, // [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 + {0xFE10, 0xFE10, prIS, gcPo}, // PRESENTATION FORM FOR VERTICAL COMMA + {0xFE11, 0xFE12, prCL, gcPo}, // [2] PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA..PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP + {0xFE13, 0xFE14, prIS, gcPo}, // [2] PRESENTATION FORM FOR VERTICAL COLON..PRESENTATION FORM FOR VERTICAL SEMICOLON + {0xFE15, 0xFE16, prEX, gcPo}, // [2] PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK..PRESENTATION FORM FOR VERTICAL QUESTION MARK + {0xFE17, 0xFE17, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET + {0xFE18, 0xFE18, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET + {0xFE19, 0xFE19, prIN, gcPo}, // PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS + {0xFE20, 0xFE2F, prCM, gcMn}, // [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + {0xFE30, 0xFE30, prID, gcPo}, // PRESENTATION FORM FOR VERTICAL TWO DOT LEADER + {0xFE31, 0xFE32, prID, gcPd}, // [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH + {0xFE33, 0xFE34, prID, gcPc}, // [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE + {0xFE35, 0xFE35, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS + {0xFE36, 0xFE36, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS + {0xFE37, 0xFE37, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET + {0xFE38, 0xFE38, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET + {0xFE39, 0xFE39, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET + {0xFE3A, 0xFE3A, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET + {0xFE3B, 0xFE3B, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET + {0xFE3C, 0xFE3C, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET + {0xFE3D, 0xFE3D, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET + {0xFE3E, 0xFE3E, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET + {0xFE3F, 0xFE3F, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET + {0xFE40, 0xFE40, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET + {0xFE41, 0xFE41, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET + {0xFE42, 0xFE42, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET + {0xFE43, 0xFE43, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET + {0xFE44, 0xFE44, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET + {0xFE45, 0xFE46, prID, gcPo}, // [2] SESAME DOT..WHITE SESAME DOT + {0xFE47, 0xFE47, prOP, gcPs}, // PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET + {0xFE48, 0xFE48, prCL, gcPe}, // PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET + {0xFE49, 0xFE4C, prID, gcPo}, // [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE + {0xFE4D, 0xFE4F, prID, gcPc}, // [3] DASHED LOW LINE..WAVY LOW LINE + {0xFE50, 0xFE50, prCL, gcPo}, // SMALL COMMA + {0xFE51, 0xFE51, prID, gcPo}, // SMALL IDEOGRAPHIC COMMA + {0xFE52, 0xFE52, prCL, gcPo}, // SMALL FULL STOP + {0xFE54, 0xFE55, prNS, gcPo}, // [2] SMALL SEMICOLON..SMALL COLON + {0xFE56, 0xFE57, prEX, gcPo}, // [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK + {0xFE58, 0xFE58, prID, gcPd}, // SMALL EM DASH + {0xFE59, 0xFE59, prOP, gcPs}, // SMALL LEFT PARENTHESIS + {0xFE5A, 0xFE5A, prCL, gcPe}, // SMALL RIGHT PARENTHESIS + {0xFE5B, 0xFE5B, prOP, gcPs}, // SMALL LEFT CURLY BRACKET + {0xFE5C, 0xFE5C, prCL, gcPe}, // SMALL RIGHT CURLY BRACKET + {0xFE5D, 0xFE5D, prOP, gcPs}, // SMALL LEFT TORTOISE SHELL BRACKET + {0xFE5E, 0xFE5E, prCL, gcPe}, // SMALL RIGHT TORTOISE SHELL BRACKET + {0xFE5F, 0xFE61, prID, gcPo}, // [3] SMALL NUMBER SIGN..SMALL ASTERISK + {0xFE62, 0xFE62, prID, gcSm}, // SMALL PLUS SIGN + {0xFE63, 0xFE63, prID, gcPd}, // SMALL HYPHEN-MINUS + {0xFE64, 0xFE66, prID, gcSm}, // [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN + {0xFE68, 0xFE68, prID, gcPo}, // SMALL REVERSE SOLIDUS + {0xFE69, 0xFE69, prPR, gcSc}, // SMALL DOLLAR SIGN + {0xFE6A, 0xFE6A, prPO, gcPo}, // SMALL PERCENT SIGN + {0xFE6B, 0xFE6B, prID, gcPo}, // SMALL COMMERCIAL AT + {0xFE70, 0xFE74, prAL, gcLo}, // [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM + {0xFE76, 0xFEFC, prAL, gcLo}, // [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM + {0xFEFF, 0xFEFF, prWJ, gcCf}, // ZERO WIDTH NO-BREAK SPACE + {0xFF01, 0xFF01, prEX, gcPo}, // FULLWIDTH EXCLAMATION MARK + {0xFF02, 0xFF03, prID, gcPo}, // [2] FULLWIDTH QUOTATION MARK..FULLWIDTH NUMBER SIGN + {0xFF04, 0xFF04, prPR, gcSc}, // FULLWIDTH DOLLAR SIGN + {0xFF05, 0xFF05, prPO, gcPo}, // FULLWIDTH PERCENT SIGN + {0xFF06, 0xFF07, prID, gcPo}, // [2] FULLWIDTH AMPERSAND..FULLWIDTH APOSTROPHE + {0xFF08, 0xFF08, prOP, gcPs}, // FULLWIDTH LEFT PARENTHESIS + {0xFF09, 0xFF09, prCL, gcPe}, // FULLWIDTH RIGHT PARENTHESIS + {0xFF0A, 0xFF0A, prID, gcPo}, // FULLWIDTH ASTERISK + {0xFF0B, 0xFF0B, prID, gcSm}, // FULLWIDTH PLUS SIGN + {0xFF0C, 0xFF0C, prCL, gcPo}, // FULLWIDTH COMMA + {0xFF0D, 0xFF0D, prID, gcPd}, // FULLWIDTH HYPHEN-MINUS + {0xFF0E, 0xFF0E, prCL, gcPo}, // FULLWIDTH FULL STOP + {0xFF0F, 0xFF0F, prID, gcPo}, // FULLWIDTH SOLIDUS + {0xFF10, 0xFF19, prID, gcNd}, // [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE + {0xFF1A, 0xFF1B, prNS, gcPo}, // [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON + {0xFF1C, 0xFF1E, prID, gcSm}, // [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN + {0xFF1F, 0xFF1F, prEX, gcPo}, // FULLWIDTH QUESTION MARK + {0xFF20, 0xFF20, prID, gcPo}, // FULLWIDTH COMMERCIAL AT + {0xFF21, 0xFF3A, prID, gcLu}, // [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z + {0xFF3B, 0xFF3B, prOP, gcPs}, // FULLWIDTH LEFT SQUARE BRACKET + {0xFF3C, 0xFF3C, prID, gcPo}, // FULLWIDTH REVERSE SOLIDUS + {0xFF3D, 0xFF3D, prCL, gcPe}, // FULLWIDTH RIGHT SQUARE BRACKET + {0xFF3E, 0xFF3E, prID, gcSk}, // FULLWIDTH CIRCUMFLEX ACCENT + {0xFF3F, 0xFF3F, prID, gcPc}, // FULLWIDTH LOW LINE + {0xFF40, 0xFF40, prID, gcSk}, // FULLWIDTH GRAVE ACCENT + {0xFF41, 0xFF5A, prID, gcLl}, // [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z + {0xFF5B, 0xFF5B, prOP, gcPs}, // FULLWIDTH LEFT CURLY BRACKET + {0xFF5C, 0xFF5C, prID, gcSm}, // FULLWIDTH VERTICAL LINE + {0xFF5D, 0xFF5D, prCL, gcPe}, // FULLWIDTH RIGHT CURLY BRACKET + {0xFF5E, 0xFF5E, prID, gcSm}, // FULLWIDTH TILDE + {0xFF5F, 0xFF5F, prOP, gcPs}, // FULLWIDTH LEFT WHITE PARENTHESIS + {0xFF60, 0xFF60, prCL, gcPe}, // FULLWIDTH RIGHT WHITE PARENTHESIS + {0xFF61, 0xFF61, prCL, gcPo}, // HALFWIDTH IDEOGRAPHIC FULL STOP + {0xFF62, 0xFF62, prOP, gcPs}, // HALFWIDTH LEFT CORNER BRACKET + {0xFF63, 0xFF63, prCL, gcPe}, // HALFWIDTH RIGHT CORNER BRACKET + {0xFF64, 0xFF64, prCL, gcPo}, // HALFWIDTH IDEOGRAPHIC COMMA + {0xFF65, 0xFF65, prNS, gcPo}, // HALFWIDTH KATAKANA MIDDLE DOT + {0xFF66, 0xFF66, prID, gcLo}, // HALFWIDTH KATAKANA LETTER WO + {0xFF67, 0xFF6F, prCJ, gcLo}, // [9] HALFWIDTH KATAKANA LETTER SMALL A..HALFWIDTH KATAKANA LETTER SMALL TU + {0xFF70, 0xFF70, prCJ, gcLm}, // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK + {0xFF71, 0xFF9D, prID, gcLo}, // [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N + {0xFF9E, 0xFF9F, prNS, gcLm}, // [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + {0xFFA0, 0xFFBE, prID, gcLo}, // [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH + {0xFFC2, 0xFFC7, prID, gcLo}, // [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E + {0xFFCA, 0xFFCF, prID, gcLo}, // [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE + {0xFFD2, 0xFFD7, prID, gcLo}, // [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU + {0xFFDA, 0xFFDC, prID, gcLo}, // [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I + {0xFFE0, 0xFFE0, prPO, gcSc}, // FULLWIDTH CENT SIGN + {0xFFE1, 0xFFE1, prPR, gcSc}, // FULLWIDTH POUND SIGN + {0xFFE2, 0xFFE2, prID, gcSm}, // FULLWIDTH NOT SIGN + {0xFFE3, 0xFFE3, prID, gcSk}, // FULLWIDTH MACRON + {0xFFE4, 0xFFE4, prID, gcSo}, // FULLWIDTH BROKEN BAR + {0xFFE5, 0xFFE6, prPR, gcSc}, // [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN + {0xFFE8, 0xFFE8, prAL, gcSo}, // HALFWIDTH FORMS LIGHT VERTICAL + {0xFFE9, 0xFFEC, prAL, gcSm}, // [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW + {0xFFED, 0xFFEE, prAL, gcSo}, // [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE + {0xFFF9, 0xFFFB, prCM, gcCf}, // [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR + {0xFFFC, 0xFFFC, prCB, gcSo}, // OBJECT REPLACEMENT CHARACTER + {0xFFFD, 0xFFFD, prAI, gcSo}, // REPLACEMENT CHARACTER + {0x10000, 0x1000B, prAL, gcLo}, // [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE + {0x1000D, 0x10026, prAL, gcLo}, // [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO + {0x10028, 0x1003A, prAL, gcLo}, // [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO + {0x1003C, 0x1003D, prAL, gcLo}, // [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE + {0x1003F, 0x1004D, prAL, gcLo}, // [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO + {0x10050, 0x1005D, prAL, gcLo}, // [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089 + {0x10080, 0x100FA, prAL, gcLo}, // [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305 + {0x10100, 0x10102, prBA, gcPo}, // [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK + {0x10107, 0x10133, prAL, gcNo}, // [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND + {0x10137, 0x1013F, prAL, gcSo}, // [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT + {0x10140, 0x10174, prAL, gcNl}, // [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS + {0x10175, 0x10178, prAL, gcNo}, // [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN + {0x10179, 0x10189, prAL, gcSo}, // [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN + {0x1018A, 0x1018B, prAL, gcNo}, // [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN + {0x1018C, 0x1018E, prAL, gcSo}, // [3] GREEK SINUSOID SIGN..NOMISMA SIGN + {0x10190, 0x1019C, prAL, gcSo}, // [13] ROMAN SEXTANS SIGN..ASCIA SYMBOL + {0x101A0, 0x101A0, prAL, gcSo}, // GREEK SYMBOL TAU RHO + {0x101D0, 0x101FC, prAL, gcSo}, // [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND + {0x101FD, 0x101FD, prCM, gcMn}, // PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE + {0x10280, 0x1029C, prAL, gcLo}, // [29] LYCIAN LETTER A..LYCIAN LETTER X + {0x102A0, 0x102D0, prAL, gcLo}, // [49] CARIAN LETTER A..CARIAN LETTER UUU3 + {0x102E0, 0x102E0, prCM, gcMn}, // COPTIC EPACT THOUSANDS MARK + {0x102E1, 0x102FB, prAL, gcNo}, // [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED + {0x10300, 0x1031F, prAL, gcLo}, // [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS + {0x10320, 0x10323, prAL, gcNo}, // [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY + {0x1032D, 0x1032F, prAL, gcLo}, // [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE + {0x10330, 0x10340, prAL, gcLo}, // [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA + {0x10341, 0x10341, prAL, gcNl}, // GOTHIC LETTER NINETY + {0x10342, 0x10349, prAL, gcLo}, // [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL + {0x1034A, 0x1034A, prAL, gcNl}, // GOTHIC LETTER NINE HUNDRED + {0x10350, 0x10375, prAL, gcLo}, // [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA + {0x10376, 0x1037A, prCM, gcMn}, // [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + {0x10380, 0x1039D, prAL, gcLo}, // [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU + {0x1039F, 0x1039F, prBA, gcPo}, // UGARITIC WORD DIVIDER + {0x103A0, 0x103C3, prAL, gcLo}, // [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA + {0x103C8, 0x103CF, prAL, gcLo}, // [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH + {0x103D0, 0x103D0, prBA, gcPo}, // OLD PERSIAN WORD DIVIDER + {0x103D1, 0x103D5, prAL, gcNl}, // [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED + {0x10400, 0x1044F, prAL, gcLC}, // [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW + {0x10450, 0x1047F, prAL, gcLo}, // [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW + {0x10480, 0x1049D, prAL, gcLo}, // [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO + {0x104A0, 0x104A9, prNU, gcNd}, // [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE + {0x104B0, 0x104D3, prAL, gcLu}, // [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA + {0x104D8, 0x104FB, prAL, gcLl}, // [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + {0x10500, 0x10527, prAL, gcLo}, // [40] ELBASAN LETTER A..ELBASAN LETTER KHE + {0x10530, 0x10563, prAL, gcLo}, // [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW + {0x1056F, 0x1056F, prAL, gcPo}, // CAUCASIAN ALBANIAN CITATION MARK + {0x10570, 0x1057A, prAL, gcLu}, // [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA + {0x1057C, 0x1058A, prAL, gcLu}, // [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE + {0x1058C, 0x10592, prAL, gcLu}, // [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE + {0x10594, 0x10595, prAL, gcLu}, // [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE + {0x10597, 0x105A1, prAL, gcLl}, // [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA + {0x105A3, 0x105B1, prAL, gcLl}, // [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE + {0x105B3, 0x105B9, prAL, gcLl}, // [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE + {0x105BB, 0x105BC, prAL, gcLl}, // [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE + {0x10600, 0x10736, prAL, gcLo}, // [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 + {0x10740, 0x10755, prAL, gcLo}, // [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE + {0x10760, 0x10767, prAL, gcLo}, // [8] LINEAR A SIGN A800..LINEAR A SIGN A807 + {0x10780, 0x10785, prAL, gcLm}, // [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK + {0x10787, 0x107B0, prAL, gcLm}, // [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK + {0x107B2, 0x107BA, prAL, gcLm}, // [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL + {0x10800, 0x10805, prAL, gcLo}, // [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA + {0x10808, 0x10808, prAL, gcLo}, // CYPRIOT SYLLABLE JO + {0x1080A, 0x10835, prAL, gcLo}, // [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO + {0x10837, 0x10838, prAL, gcLo}, // [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE + {0x1083C, 0x1083C, prAL, gcLo}, // CYPRIOT SYLLABLE ZA + {0x1083F, 0x1083F, prAL, gcLo}, // CYPRIOT SYLLABLE ZO + {0x10840, 0x10855, prAL, gcLo}, // [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW + {0x10857, 0x10857, prBA, gcPo}, // IMPERIAL ARAMAIC SECTION SIGN + {0x10858, 0x1085F, prAL, gcNo}, // [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND + {0x10860, 0x10876, prAL, gcLo}, // [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW + {0x10877, 0x10878, prAL, gcSo}, // [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON + {0x10879, 0x1087F, prAL, gcNo}, // [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY + {0x10880, 0x1089E, prAL, gcLo}, // [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW + {0x108A7, 0x108AF, prAL, gcNo}, // [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED + {0x108E0, 0x108F2, prAL, gcLo}, // [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH + {0x108F4, 0x108F5, prAL, gcLo}, // [2] HATRAN LETTER SHIN..HATRAN LETTER TAW + {0x108FB, 0x108FF, prAL, gcNo}, // [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED + {0x10900, 0x10915, prAL, gcLo}, // [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU + {0x10916, 0x1091B, prAL, gcNo}, // [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE + {0x1091F, 0x1091F, prBA, gcPo}, // PHOENICIAN WORD SEPARATOR + {0x10920, 0x10939, prAL, gcLo}, // [26] LYDIAN LETTER A..LYDIAN LETTER C + {0x1093F, 0x1093F, prAL, gcPo}, // LYDIAN TRIANGULAR MARK + {0x10980, 0x1099F, prAL, gcLo}, // [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2 + {0x109A0, 0x109B7, prAL, gcLo}, // [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA + {0x109BC, 0x109BD, prAL, gcNo}, // [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF + {0x109BE, 0x109BF, prAL, gcLo}, // [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN + {0x109C0, 0x109CF, prAL, gcNo}, // [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY + {0x109D2, 0x109FF, prAL, gcNo}, // [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS + {0x10A00, 0x10A00, prAL, gcLo}, // KHAROSHTHI LETTER A + {0x10A01, 0x10A03, prCM, gcMn}, // [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R + {0x10A05, 0x10A06, prCM, gcMn}, // [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O + {0x10A0C, 0x10A0F, prCM, gcMn}, // [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA + {0x10A10, 0x10A13, prAL, gcLo}, // [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA + {0x10A15, 0x10A17, prAL, gcLo}, // [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA + {0x10A19, 0x10A35, prAL, gcLo}, // [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA + {0x10A38, 0x10A3A, prCM, gcMn}, // [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW + {0x10A3F, 0x10A3F, prCM, gcMn}, // KHAROSHTHI VIRAMA + {0x10A40, 0x10A48, prAL, gcNo}, // [9] KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF + {0x10A50, 0x10A57, prBA, gcPo}, // [8] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION DOUBLE DANDA + {0x10A58, 0x10A58, prAL, gcPo}, // KHAROSHTHI PUNCTUATION LINES + {0x10A60, 0x10A7C, prAL, gcLo}, // [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH + {0x10A7D, 0x10A7E, prAL, gcNo}, // [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY + {0x10A7F, 0x10A7F, prAL, gcPo}, // OLD SOUTH ARABIAN NUMERIC INDICATOR + {0x10A80, 0x10A9C, prAL, gcLo}, // [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH + {0x10A9D, 0x10A9F, prAL, gcNo}, // [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY + {0x10AC0, 0x10AC7, prAL, gcLo}, // [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW + {0x10AC8, 0x10AC8, prAL, gcSo}, // MANICHAEAN SIGN UD + {0x10AC9, 0x10AE4, prAL, gcLo}, // [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW + {0x10AE5, 0x10AE6, prCM, gcMn}, // [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW + {0x10AEB, 0x10AEF, prAL, gcNo}, // [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED + {0x10AF0, 0x10AF5, prBA, gcPo}, // [6] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION TWO DOTS + {0x10AF6, 0x10AF6, prIN, gcPo}, // MANICHAEAN PUNCTUATION LINE FILLER + {0x10B00, 0x10B35, prAL, gcLo}, // [54] AVESTAN LETTER A..AVESTAN LETTER HE + {0x10B39, 0x10B3F, prBA, gcPo}, // [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION + {0x10B40, 0x10B55, prAL, gcLo}, // [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW + {0x10B58, 0x10B5F, prAL, gcNo}, // [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND + {0x10B60, 0x10B72, prAL, gcLo}, // [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW + {0x10B78, 0x10B7F, prAL, gcNo}, // [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND + {0x10B80, 0x10B91, prAL, gcLo}, // [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW + {0x10B99, 0x10B9C, prAL, gcPo}, // [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT + {0x10BA9, 0x10BAF, prAL, gcNo}, // [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED + {0x10C00, 0x10C48, prAL, gcLo}, // [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH + {0x10C80, 0x10CB2, prAL, gcLu}, // [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US + {0x10CC0, 0x10CF2, prAL, gcLl}, // [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US + {0x10CFA, 0x10CFF, prAL, gcNo}, // [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND + {0x10D00, 0x10D23, prAL, gcLo}, // [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA + {0x10D24, 0x10D27, prCM, gcMn}, // [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI + {0x10D30, 0x10D39, prNU, gcNd}, // [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE + {0x10E60, 0x10E7E, prAL, gcNo}, // [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS + {0x10E80, 0x10EA9, prAL, gcLo}, // [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET + {0x10EAB, 0x10EAC, prCM, gcMn}, // [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK + {0x10EAD, 0x10EAD, prBA, gcPd}, // YEZIDI HYPHENATION MARK + {0x10EB0, 0x10EB1, prAL, gcLo}, // [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prCM, gcMn}, // [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA + {0x10F00, 0x10F1C, prAL, gcLo}, // [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL + {0x10F1D, 0x10F26, prAL, gcNo}, // [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF + {0x10F27, 0x10F27, prAL, gcLo}, // OLD SOGDIAN LIGATURE AYIN-DALETH + {0x10F30, 0x10F45, prAL, gcLo}, // [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN + {0x10F46, 0x10F50, prCM, gcMn}, // [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW + {0x10F51, 0x10F54, prAL, gcNo}, // [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED + {0x10F55, 0x10F59, prAL, gcPo}, // [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT + {0x10F70, 0x10F81, prAL, gcLo}, // [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH + {0x10F82, 0x10F85, prCM, gcMn}, // [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW + {0x10F86, 0x10F89, prAL, gcPo}, // [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS + {0x10FB0, 0x10FC4, prAL, gcLo}, // [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW + {0x10FC5, 0x10FCB, prAL, gcNo}, // [7] CHORASMIAN NUMBER ONE..CHORASMIAN NUMBER ONE HUNDRED + {0x10FE0, 0x10FF6, prAL, gcLo}, // [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH + {0x11000, 0x11000, prCM, gcMc}, // BRAHMI SIGN CANDRABINDU + {0x11001, 0x11001, prCM, gcMn}, // BRAHMI SIGN ANUSVARA + {0x11002, 0x11002, prCM, gcMc}, // BRAHMI SIGN VISARGA + {0x11003, 0x11037, prAL, gcLo}, // [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA + {0x11038, 0x11046, prCM, gcMn}, // [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA + {0x11047, 0x11048, prBA, gcPo}, // [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA + {0x11049, 0x1104D, prAL, gcPo}, // [5] BRAHMI PUNCTUATION DOT..BRAHMI PUNCTUATION LOTUS + {0x11052, 0x11065, prAL, gcNo}, // [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND + {0x11066, 0x1106F, prNU, gcNd}, // [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE + {0x11070, 0x11070, prCM, gcMn}, // BRAHMI SIGN OLD TAMIL VIRAMA + {0x11071, 0x11072, prAL, gcLo}, // [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O + {0x11073, 0x11074, prCM, gcMn}, // [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O + {0x11075, 0x11075, prAL, gcLo}, // BRAHMI LETTER OLD TAMIL LLA + {0x1107F, 0x1107F, prCM, gcMn}, // BRAHMI NUMBER JOINER + {0x11080, 0x11081, prCM, gcMn}, // [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA + {0x11082, 0x11082, prCM, gcMc}, // KAITHI SIGN VISARGA + {0x11083, 0x110AF, prAL, gcLo}, // [45] KAITHI LETTER A..KAITHI LETTER HA + {0x110B0, 0x110B2, prCM, gcMc}, // [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II + {0x110B3, 0x110B6, prCM, gcMn}, // [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI + {0x110B7, 0x110B8, prCM, gcMc}, // [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU + {0x110B9, 0x110BA, prCM, gcMn}, // [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA + {0x110BB, 0x110BC, prAL, gcPo}, // [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN + {0x110BD, 0x110BD, prAL, gcCf}, // KAITHI NUMBER SIGN + {0x110BE, 0x110C1, prBA, gcPo}, // [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA + {0x110C2, 0x110C2, prCM, gcMn}, // KAITHI VOWEL SIGN VOCALIC R + {0x110CD, 0x110CD, prAL, gcCf}, // KAITHI NUMBER SIGN ABOVE + {0x110D0, 0x110E8, prAL, gcLo}, // [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE + {0x110F0, 0x110F9, prNU, gcNd}, // [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE + {0x11100, 0x11102, prCM, gcMn}, // [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA + {0x11103, 0x11126, prAL, gcLo}, // [36] CHAKMA LETTER AA..CHAKMA LETTER HAA + {0x11127, 0x1112B, prCM, gcMn}, // [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU + {0x1112C, 0x1112C, prCM, gcMc}, // CHAKMA VOWEL SIGN E + {0x1112D, 0x11134, prCM, gcMn}, // [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA + {0x11136, 0x1113F, prNU, gcNd}, // [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE + {0x11140, 0x11143, prBA, gcPo}, // [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK + {0x11144, 0x11144, prAL, gcLo}, // CHAKMA LETTER LHAA + {0x11145, 0x11146, prCM, gcMc}, // [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI + {0x11147, 0x11147, prAL, gcLo}, // CHAKMA LETTER VAA + {0x11150, 0x11172, prAL, gcLo}, // [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA + {0x11173, 0x11173, prCM, gcMn}, // MAHAJANI SIGN NUKTA + {0x11174, 0x11174, prAL, gcPo}, // MAHAJANI ABBREVIATION SIGN + {0x11175, 0x11175, prBB, gcPo}, // MAHAJANI SECTION MARK + {0x11176, 0x11176, prAL, gcLo}, // MAHAJANI LIGATURE SHRI + {0x11180, 0x11181, prCM, gcMn}, // [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA + {0x11182, 0x11182, prCM, gcMc}, // SHARADA SIGN VISARGA + {0x11183, 0x111B2, prAL, gcLo}, // [48] SHARADA LETTER A..SHARADA LETTER HA + {0x111B3, 0x111B5, prCM, gcMc}, // [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II + {0x111B6, 0x111BE, prCM, gcMn}, // [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O + {0x111BF, 0x111C0, prCM, gcMc}, // [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA + {0x111C1, 0x111C4, prAL, gcLo}, // [4] SHARADA SIGN AVAGRAHA..SHARADA OM + {0x111C5, 0x111C6, prBA, gcPo}, // [2] SHARADA DANDA..SHARADA DOUBLE DANDA + {0x111C7, 0x111C7, prAL, gcPo}, // SHARADA ABBREVIATION SIGN + {0x111C8, 0x111C8, prBA, gcPo}, // SHARADA SEPARATOR + {0x111C9, 0x111CC, prCM, gcMn}, // [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK + {0x111CD, 0x111CD, prAL, gcPo}, // SHARADA SUTRA MARK + {0x111CE, 0x111CE, prCM, gcMc}, // SHARADA VOWEL SIGN PRISHTHAMATRA E + {0x111CF, 0x111CF, prCM, gcMn}, // SHARADA SIGN INVERTED CANDRABINDU + {0x111D0, 0x111D9, prNU, gcNd}, // [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE + {0x111DA, 0x111DA, prAL, gcLo}, // SHARADA EKAM + {0x111DB, 0x111DB, prBB, gcPo}, // SHARADA SIGN SIDDHAM + {0x111DC, 0x111DC, prAL, gcLo}, // SHARADA HEADSTROKE + {0x111DD, 0x111DF, prBA, gcPo}, // [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2 + {0x111E1, 0x111F4, prAL, gcNo}, // [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND + {0x11200, 0x11211, prAL, gcLo}, // [18] KHOJKI LETTER A..KHOJKI LETTER JJA + {0x11213, 0x1122B, prAL, gcLo}, // [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA + {0x1122C, 0x1122E, prCM, gcMc}, // [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II + {0x1122F, 0x11231, prCM, gcMn}, // [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI + {0x11232, 0x11233, prCM, gcMc}, // [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU + {0x11234, 0x11234, prCM, gcMn}, // KHOJKI SIGN ANUSVARA + {0x11235, 0x11235, prCM, gcMc}, // KHOJKI SIGN VIRAMA + {0x11236, 0x11237, prCM, gcMn}, // [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA + {0x11238, 0x11239, prBA, gcPo}, // [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA + {0x1123A, 0x1123A, prAL, gcPo}, // KHOJKI WORD SEPARATOR + {0x1123B, 0x1123C, prBA, gcPo}, // [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK + {0x1123D, 0x1123D, prAL, gcPo}, // KHOJKI ABBREVIATION SIGN + {0x1123E, 0x1123E, prCM, gcMn}, // KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prAL, gcLo}, // [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prCM, gcMn}, // KHOJKI VOWEL SIGN VOCALIC R + {0x11280, 0x11286, prAL, gcLo}, // [7] MULTANI LETTER A..MULTANI LETTER GA + {0x11288, 0x11288, prAL, gcLo}, // MULTANI LETTER GHA + {0x1128A, 0x1128D, prAL, gcLo}, // [4] MULTANI LETTER CA..MULTANI LETTER JJA + {0x1128F, 0x1129D, prAL, gcLo}, // [15] MULTANI LETTER NYA..MULTANI LETTER BA + {0x1129F, 0x112A8, prAL, gcLo}, // [10] MULTANI LETTER BHA..MULTANI LETTER RHA + {0x112A9, 0x112A9, prBA, gcPo}, // MULTANI SECTION MARK + {0x112B0, 0x112DE, prAL, gcLo}, // [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA + {0x112DF, 0x112DF, prCM, gcMn}, // KHUDAWADI SIGN ANUSVARA + {0x112E0, 0x112E2, prCM, gcMc}, // [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II + {0x112E3, 0x112EA, prCM, gcMn}, // [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA + {0x112F0, 0x112F9, prNU, gcNd}, // [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE + {0x11300, 0x11301, prCM, gcMn}, // [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU + {0x11302, 0x11303, prCM, gcMc}, // [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA + {0x11305, 0x1130C, prAL, gcLo}, // [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L + {0x1130F, 0x11310, prAL, gcLo}, // [2] GRANTHA LETTER EE..GRANTHA LETTER AI + {0x11313, 0x11328, prAL, gcLo}, // [22] GRANTHA LETTER OO..GRANTHA LETTER NA + {0x1132A, 0x11330, prAL, gcLo}, // [7] GRANTHA LETTER PA..GRANTHA LETTER RA + {0x11332, 0x11333, prAL, gcLo}, // [2] GRANTHA LETTER LA..GRANTHA LETTER LLA + {0x11335, 0x11339, prAL, gcLo}, // [5] GRANTHA LETTER VA..GRANTHA LETTER HA + {0x1133B, 0x1133C, prCM, gcMn}, // [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA + {0x1133D, 0x1133D, prAL, gcLo}, // GRANTHA SIGN AVAGRAHA + {0x1133E, 0x1133F, prCM, gcMc}, // [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I + {0x11340, 0x11340, prCM, gcMn}, // GRANTHA VOWEL SIGN II + {0x11341, 0x11344, prCM, gcMc}, // [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR + {0x11347, 0x11348, prCM, gcMc}, // [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI + {0x1134B, 0x1134D, prCM, gcMc}, // [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA + {0x11350, 0x11350, prAL, gcLo}, // GRANTHA OM + {0x11357, 0x11357, prCM, gcMc}, // GRANTHA AU LENGTH MARK + {0x1135D, 0x11361, prAL, gcLo}, // [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL + {0x11362, 0x11363, prCM, gcMc}, // [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL + {0x11366, 0x1136C, prCM, gcMn}, // [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX + {0x11370, 0x11374, prCM, gcMn}, // [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + {0x11400, 0x11434, prAL, gcLo}, // [53] NEWA LETTER A..NEWA LETTER HA + {0x11435, 0x11437, prCM, gcMc}, // [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II + {0x11438, 0x1143F, prCM, gcMn}, // [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI + {0x11440, 0x11441, prCM, gcMc}, // [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU + {0x11442, 0x11444, prCM, gcMn}, // [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA + {0x11445, 0x11445, prCM, gcMc}, // NEWA SIGN VISARGA + {0x11446, 0x11446, prCM, gcMn}, // NEWA SIGN NUKTA + {0x11447, 0x1144A, prAL, gcLo}, // [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI + {0x1144B, 0x1144E, prBA, gcPo}, // [4] NEWA DANDA..NEWA GAP FILLER + {0x1144F, 0x1144F, prAL, gcPo}, // NEWA ABBREVIATION SIGN + {0x11450, 0x11459, prNU, gcNd}, // [10] NEWA DIGIT ZERO..NEWA DIGIT NINE + {0x1145A, 0x1145B, prBA, gcPo}, // [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK + {0x1145D, 0x1145D, prAL, gcPo}, // NEWA INSERTION SIGN + {0x1145E, 0x1145E, prCM, gcMn}, // NEWA SANDHI MARK + {0x1145F, 0x11461, prAL, gcLo}, // [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA + {0x11480, 0x114AF, prAL, gcLo}, // [48] TIRHUTA ANJI..TIRHUTA LETTER HA + {0x114B0, 0x114B2, prCM, gcMc}, // [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II + {0x114B3, 0x114B8, prCM, gcMn}, // [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL + {0x114B9, 0x114B9, prCM, gcMc}, // TIRHUTA VOWEL SIGN E + {0x114BA, 0x114BA, prCM, gcMn}, // TIRHUTA VOWEL SIGN SHORT E + {0x114BB, 0x114BE, prCM, gcMc}, // [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU + {0x114BF, 0x114C0, prCM, gcMn}, // [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA + {0x114C1, 0x114C1, prCM, gcMc}, // TIRHUTA SIGN VISARGA + {0x114C2, 0x114C3, prCM, gcMn}, // [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA + {0x114C4, 0x114C5, prAL, gcLo}, // [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG + {0x114C6, 0x114C6, prAL, gcPo}, // TIRHUTA ABBREVIATION SIGN + {0x114C7, 0x114C7, prAL, gcLo}, // TIRHUTA OM + {0x114D0, 0x114D9, prNU, gcNd}, // [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE + {0x11580, 0x115AE, prAL, gcLo}, // [47] SIDDHAM LETTER A..SIDDHAM LETTER HA + {0x115AF, 0x115B1, prCM, gcMc}, // [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II + {0x115B2, 0x115B5, prCM, gcMn}, // [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR + {0x115B8, 0x115BB, prCM, gcMc}, // [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU + {0x115BC, 0x115BD, prCM, gcMn}, // [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA + {0x115BE, 0x115BE, prCM, gcMc}, // SIDDHAM SIGN VISARGA + {0x115BF, 0x115C0, prCM, gcMn}, // [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA + {0x115C1, 0x115C1, prBB, gcPo}, // SIDDHAM SIGN SIDDHAM + {0x115C2, 0x115C3, prBA, gcPo}, // [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA + {0x115C4, 0x115C5, prEX, gcPo}, // [2] SIDDHAM SEPARATOR DOT..SIDDHAM SEPARATOR BAR + {0x115C6, 0x115C8, prAL, gcPo}, // [3] SIDDHAM REPETITION MARK-1..SIDDHAM REPETITION MARK-3 + {0x115C9, 0x115D7, prBA, gcPo}, // [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES + {0x115D8, 0x115DB, prAL, gcLo}, // [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U + {0x115DC, 0x115DD, prCM, gcMn}, // [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + {0x11600, 0x1162F, prAL, gcLo}, // [48] MODI LETTER A..MODI LETTER LLA + {0x11630, 0x11632, prCM, gcMc}, // [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II + {0x11633, 0x1163A, prCM, gcMn}, // [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI + {0x1163B, 0x1163C, prCM, gcMc}, // [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU + {0x1163D, 0x1163D, prCM, gcMn}, // MODI SIGN ANUSVARA + {0x1163E, 0x1163E, prCM, gcMc}, // MODI SIGN VISARGA + {0x1163F, 0x11640, prCM, gcMn}, // [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA + {0x11641, 0x11642, prBA, gcPo}, // [2] MODI DANDA..MODI DOUBLE DANDA + {0x11643, 0x11643, prAL, gcPo}, // MODI ABBREVIATION SIGN + {0x11644, 0x11644, prAL, gcLo}, // MODI SIGN HUVA + {0x11650, 0x11659, prNU, gcNd}, // [10] MODI DIGIT ZERO..MODI DIGIT NINE + {0x11660, 0x1166C, prBB, gcPo}, // [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT + {0x11680, 0x116AA, prAL, gcLo}, // [43] TAKRI LETTER A..TAKRI LETTER RRA + {0x116AB, 0x116AB, prCM, gcMn}, // TAKRI SIGN ANUSVARA + {0x116AC, 0x116AC, prCM, gcMc}, // TAKRI SIGN VISARGA + {0x116AD, 0x116AD, prCM, gcMn}, // TAKRI VOWEL SIGN AA + {0x116AE, 0x116AF, prCM, gcMc}, // [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II + {0x116B0, 0x116B5, prCM, gcMn}, // [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU + {0x116B6, 0x116B6, prCM, gcMc}, // TAKRI SIGN VIRAMA + {0x116B7, 0x116B7, prCM, gcMn}, // TAKRI SIGN NUKTA + {0x116B8, 0x116B8, prAL, gcLo}, // TAKRI LETTER ARCHAIC KHA + {0x116B9, 0x116B9, prAL, gcPo}, // TAKRI ABBREVIATION SIGN + {0x116C0, 0x116C9, prNU, gcNd}, // [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE + {0x11700, 0x1171A, prSA, gcLo}, // [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA + {0x1171D, 0x1171F, prSA, gcMn}, // [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA + {0x11720, 0x11721, prSA, gcMc}, // [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA + {0x11722, 0x11725, prSA, gcMn}, // [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU + {0x11726, 0x11726, prSA, gcMc}, // AHOM VOWEL SIGN E + {0x11727, 0x1172B, prSA, gcMn}, // [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER + {0x11730, 0x11739, prNU, gcNd}, // [10] AHOM DIGIT ZERO..AHOM DIGIT NINE + {0x1173A, 0x1173B, prSA, gcNo}, // [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY + {0x1173C, 0x1173E, prBA, gcPo}, // [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI + {0x1173F, 0x1173F, prSA, gcSo}, // AHOM SYMBOL VI + {0x11740, 0x11746, prSA, gcLo}, // [7] AHOM LETTER CA..AHOM LETTER LLA + {0x11800, 0x1182B, prAL, gcLo}, // [44] DOGRA LETTER A..DOGRA LETTER RRA + {0x1182C, 0x1182E, prCM, gcMc}, // [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II + {0x1182F, 0x11837, prCM, gcMn}, // [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA + {0x11838, 0x11838, prCM, gcMc}, // DOGRA SIGN VISARGA + {0x11839, 0x1183A, prCM, gcMn}, // [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA + {0x1183B, 0x1183B, prAL, gcPo}, // DOGRA ABBREVIATION SIGN + {0x118A0, 0x118DF, prAL, gcLC}, // [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO + {0x118E0, 0x118E9, prNU, gcNd}, // [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE + {0x118EA, 0x118F2, prAL, gcNo}, // [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY + {0x118FF, 0x118FF, prAL, gcLo}, // WARANG CITI OM + {0x11900, 0x11906, prAL, gcLo}, // [7] DIVES AKURU LETTER A..DIVES AKURU LETTER E + {0x11909, 0x11909, prAL, gcLo}, // DIVES AKURU LETTER O + {0x1190C, 0x11913, prAL, gcLo}, // [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA + {0x11915, 0x11916, prAL, gcLo}, // [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA + {0x11918, 0x1192F, prAL, gcLo}, // [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA + {0x11930, 0x11935, prCM, gcMc}, // [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E + {0x11937, 0x11938, prCM, gcMc}, // [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O + {0x1193B, 0x1193C, prCM, gcMn}, // [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU + {0x1193D, 0x1193D, prCM, gcMc}, // DIVES AKURU SIGN HALANTA + {0x1193E, 0x1193E, prCM, gcMn}, // DIVES AKURU VIRAMA + {0x1193F, 0x1193F, prAL, gcLo}, // DIVES AKURU PREFIXED NASAL SIGN + {0x11940, 0x11940, prCM, gcMc}, // DIVES AKURU MEDIAL YA + {0x11941, 0x11941, prAL, gcLo}, // DIVES AKURU INITIAL RA + {0x11942, 0x11942, prCM, gcMc}, // DIVES AKURU MEDIAL RA + {0x11943, 0x11943, prCM, gcMn}, // DIVES AKURU SIGN NUKTA + {0x11944, 0x11946, prBA, gcPo}, // [3] DIVES AKURU DOUBLE DANDA..DIVES AKURU END OF TEXT MARK + {0x11950, 0x11959, prNU, gcNd}, // [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE + {0x119A0, 0x119A7, prAL, gcLo}, // [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR + {0x119AA, 0x119D0, prAL, gcLo}, // [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA + {0x119D1, 0x119D3, prCM, gcMc}, // [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II + {0x119D4, 0x119D7, prCM, gcMn}, // [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR + {0x119DA, 0x119DB, prCM, gcMn}, // [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI + {0x119DC, 0x119DF, prCM, gcMc}, // [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA + {0x119E0, 0x119E0, prCM, gcMn}, // NANDINAGARI SIGN VIRAMA + {0x119E1, 0x119E1, prAL, gcLo}, // NANDINAGARI SIGN AVAGRAHA + {0x119E2, 0x119E2, prBB, gcPo}, // NANDINAGARI SIGN SIDDHAM + {0x119E3, 0x119E3, prAL, gcLo}, // NANDINAGARI HEADSTROKE + {0x119E4, 0x119E4, prCM, gcMc}, // NANDINAGARI VOWEL SIGN PRISHTHAMATRA E + {0x11A00, 0x11A00, prAL, gcLo}, // ZANABAZAR SQUARE LETTER A + {0x11A01, 0x11A0A, prCM, gcMn}, // [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK + {0x11A0B, 0x11A32, prAL, gcLo}, // [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA + {0x11A33, 0x11A38, prCM, gcMn}, // [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA + {0x11A39, 0x11A39, prCM, gcMc}, // ZANABAZAR SQUARE SIGN VISARGA + {0x11A3A, 0x11A3A, prAL, gcLo}, // ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA + {0x11A3B, 0x11A3E, prCM, gcMn}, // [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA + {0x11A3F, 0x11A3F, prBB, gcPo}, // ZANABAZAR SQUARE INITIAL HEAD MARK + {0x11A40, 0x11A40, prAL, gcPo}, // ZANABAZAR SQUARE CLOSING HEAD MARK + {0x11A41, 0x11A44, prBA, gcPo}, // [4] ZANABAZAR SQUARE MARK TSHEG..ZANABAZAR SQUARE MARK LONG TSHEG + {0x11A45, 0x11A45, prBB, gcPo}, // ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK + {0x11A46, 0x11A46, prAL, gcPo}, // ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK + {0x11A47, 0x11A47, prCM, gcMn}, // ZANABAZAR SQUARE SUBJOINER + {0x11A50, 0x11A50, prAL, gcLo}, // SOYOMBO LETTER A + {0x11A51, 0x11A56, prCM, gcMn}, // [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE + {0x11A57, 0x11A58, prCM, gcMc}, // [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU + {0x11A59, 0x11A5B, prCM, gcMn}, // [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK + {0x11A5C, 0x11A89, prAL, gcLo}, // [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA + {0x11A8A, 0x11A96, prCM, gcMn}, // [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA + {0x11A97, 0x11A97, prCM, gcMc}, // SOYOMBO SIGN VISARGA + {0x11A98, 0x11A99, prCM, gcMn}, // [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER + {0x11A9A, 0x11A9C, prBA, gcPo}, // [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD + {0x11A9D, 0x11A9D, prAL, gcLo}, // SOYOMBO MARK PLUTA + {0x11A9E, 0x11AA0, prBB, gcPo}, // [3] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO HEAD MARK WITH MOON AND SUN + {0x11AA1, 0x11AA2, prBA, gcPo}, // [2] SOYOMBO TERMINAL MARK-1..SOYOMBO TERMINAL MARK-2 + {0x11AB0, 0x11ABF, prAL, gcLo}, // [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA + {0x11AC0, 0x11AF8, prAL, gcLo}, // [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL + {0x11B00, 0x11B09, prBB, gcPo}, // [10] DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU + {0x11C00, 0x11C08, prAL, gcLo}, // [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L + {0x11C0A, 0x11C2E, prAL, gcLo}, // [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA + {0x11C2F, 0x11C2F, prCM, gcMc}, // BHAIKSUKI VOWEL SIGN AA + {0x11C30, 0x11C36, prCM, gcMn}, // [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L + {0x11C38, 0x11C3D, prCM, gcMn}, // [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA + {0x11C3E, 0x11C3E, prCM, gcMc}, // BHAIKSUKI SIGN VISARGA + {0x11C3F, 0x11C3F, prCM, gcMn}, // BHAIKSUKI SIGN VIRAMA + {0x11C40, 0x11C40, prAL, gcLo}, // BHAIKSUKI SIGN AVAGRAHA + {0x11C41, 0x11C45, prBA, gcPo}, // [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2 + {0x11C50, 0x11C59, prNU, gcNd}, // [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE + {0x11C5A, 0x11C6C, prAL, gcNo}, // [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK + {0x11C70, 0x11C70, prBB, gcPo}, // MARCHEN HEAD MARK + {0x11C71, 0x11C71, prEX, gcPo}, // MARCHEN MARK SHAD + {0x11C72, 0x11C8F, prAL, gcLo}, // [30] MARCHEN LETTER KA..MARCHEN LETTER A + {0x11C92, 0x11CA7, prCM, gcMn}, // [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA + {0x11CA9, 0x11CA9, prCM, gcMc}, // MARCHEN SUBJOINED LETTER YA + {0x11CAA, 0x11CB0, prCM, gcMn}, // [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA + {0x11CB1, 0x11CB1, prCM, gcMc}, // MARCHEN VOWEL SIGN I + {0x11CB2, 0x11CB3, prCM, gcMn}, // [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E + {0x11CB4, 0x11CB4, prCM, gcMc}, // MARCHEN VOWEL SIGN O + {0x11CB5, 0x11CB6, prCM, gcMn}, // [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + {0x11D00, 0x11D06, prAL, gcLo}, // [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E + {0x11D08, 0x11D09, prAL, gcLo}, // [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O + {0x11D0B, 0x11D30, prAL, gcLo}, // [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA + {0x11D31, 0x11D36, prCM, gcMn}, // [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R + {0x11D3A, 0x11D3A, prCM, gcMn}, // MASARAM GONDI VOWEL SIGN E + {0x11D3C, 0x11D3D, prCM, gcMn}, // [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O + {0x11D3F, 0x11D45, prCM, gcMn}, // [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA + {0x11D46, 0x11D46, prAL, gcLo}, // MASARAM GONDI REPHA + {0x11D47, 0x11D47, prCM, gcMn}, // MASARAM GONDI RA-KARA + {0x11D50, 0x11D59, prNU, gcNd}, // [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE + {0x11D60, 0x11D65, prAL, gcLo}, // [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU + {0x11D67, 0x11D68, prAL, gcLo}, // [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI + {0x11D6A, 0x11D89, prAL, gcLo}, // [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA + {0x11D8A, 0x11D8E, prCM, gcMc}, // [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU + {0x11D90, 0x11D91, prCM, gcMn}, // [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI + {0x11D93, 0x11D94, prCM, gcMc}, // [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU + {0x11D95, 0x11D95, prCM, gcMn}, // GUNJALA GONDI SIGN ANUSVARA + {0x11D96, 0x11D96, prCM, gcMc}, // GUNJALA GONDI SIGN VISARGA + {0x11D97, 0x11D97, prCM, gcMn}, // GUNJALA GONDI VIRAMA + {0x11D98, 0x11D98, prAL, gcLo}, // GUNJALA GONDI OM + {0x11DA0, 0x11DA9, prNU, gcNd}, // [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE + {0x11EE0, 0x11EF2, prAL, gcLo}, // [19] MAKASAR LETTER KA..MAKASAR ANGKA + {0x11EF3, 0x11EF4, prCM, gcMn}, // [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U + {0x11EF5, 0x11EF6, prCM, gcMc}, // [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x11EF7, 0x11EF8, prAL, gcPo}, // [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION + {0x11F00, 0x11F01, prCM, gcMn}, // [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prAL, gcLo}, // KAWI SIGN REPHA + {0x11F03, 0x11F03, prCM, gcMc}, // KAWI SIGN VISARGA + {0x11F04, 0x11F10, prAL, gcLo}, // [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prAL, gcLo}, // [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prCM, gcMc}, // [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prCM, gcMn}, // [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prCM, gcMc}, // [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prCM, gcMn}, // KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prCM, gcMc}, // KAWI SIGN KILLER + {0x11F42, 0x11F42, prCM, gcMn}, // KAWI CONJOINER + {0x11F43, 0x11F44, prBA, gcPo}, // [2] KAWI DANDA..KAWI DOUBLE DANDA + {0x11F45, 0x11F4F, prID, gcPo}, // [11] KAWI PUNCTUATION SECTION MARKER..KAWI PUNCTUATION CLOSING SPIRAL + {0x11F50, 0x11F59, prNU, gcNd}, // [10] KAWI DIGIT ZERO..KAWI DIGIT NINE + {0x11FB0, 0x11FB0, prAL, gcLo}, // LISU LETTER YHA + {0x11FC0, 0x11FD4, prAL, gcNo}, // [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH + {0x11FD5, 0x11FDC, prAL, gcSo}, // [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI + {0x11FDD, 0x11FE0, prPO, gcSc}, // [4] TAMIL SIGN KAACU..TAMIL SIGN VARAAKAN + {0x11FE1, 0x11FF1, prAL, gcSo}, // [17] TAMIL SIGN PAARAM..TAMIL SIGN VAKAIYARAA + {0x11FFF, 0x11FFF, prBA, gcPo}, // TAMIL PUNCTUATION END OF TEXT + {0x12000, 0x12399, prAL, gcLo}, // [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U + {0x12400, 0x1246E, prAL, gcNl}, // [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM + {0x12470, 0x12474, prBA, gcPo}, // [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON + {0x12480, 0x12543, prAL, gcLo}, // [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU + {0x12F90, 0x12FF0, prAL, gcLo}, // [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 + {0x12FF1, 0x12FF2, prAL, gcPo}, // [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302 + {0x13000, 0x13257, prAL, gcLo}, // [600] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH O006 + {0x13258, 0x1325A, prOP, gcLo}, // [3] EGYPTIAN HIEROGLYPH O006A..EGYPTIAN HIEROGLYPH O006C + {0x1325B, 0x1325D, prCL, gcLo}, // [3] EGYPTIAN HIEROGLYPH O006D..EGYPTIAN HIEROGLYPH O006F + {0x1325E, 0x13281, prAL, gcLo}, // [36] EGYPTIAN HIEROGLYPH O007..EGYPTIAN HIEROGLYPH O033 + {0x13282, 0x13282, prCL, gcLo}, // EGYPTIAN HIEROGLYPH O033A + {0x13283, 0x13285, prAL, gcLo}, // [3] EGYPTIAN HIEROGLYPH O034..EGYPTIAN HIEROGLYPH O036 + {0x13286, 0x13286, prOP, gcLo}, // EGYPTIAN HIEROGLYPH O036A + {0x13287, 0x13287, prCL, gcLo}, // EGYPTIAN HIEROGLYPH O036B + {0x13288, 0x13288, prOP, gcLo}, // EGYPTIAN HIEROGLYPH O036C + {0x13289, 0x13289, prCL, gcLo}, // EGYPTIAN HIEROGLYPH O036D + {0x1328A, 0x13378, prAL, gcLo}, // [239] EGYPTIAN HIEROGLYPH O037..EGYPTIAN HIEROGLYPH V011 + {0x13379, 0x13379, prOP, gcLo}, // EGYPTIAN HIEROGLYPH V011A + {0x1337A, 0x1337B, prCL, gcLo}, // [2] EGYPTIAN HIEROGLYPH V011B..EGYPTIAN HIEROGLYPH V011C + {0x1337C, 0x1342F, prAL, gcLo}, // [180] EGYPTIAN HIEROGLYPH V012..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x13436, prGL, gcCf}, // [7] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE + {0x13437, 0x13437, prOP, gcCf}, // EGYPTIAN HIEROGLYPH BEGIN SEGMENT + {0x13438, 0x13438, prCL, gcCf}, // EGYPTIAN HIEROGLYPH END SEGMENT + {0x13439, 0x1343B, prGL, gcCf}, // [3] EGYPTIAN HIEROGLYPH INSERT AT MIDDLE..EGYPTIAN HIEROGLYPH INSERT AT BOTTOM + {0x1343C, 0x1343C, prOP, gcCf}, // EGYPTIAN HIEROGLYPH BEGIN ENCLOSURE + {0x1343D, 0x1343D, prCL, gcCf}, // EGYPTIAN HIEROGLYPH END ENCLOSURE + {0x1343E, 0x1343E, prOP, gcCf}, // EGYPTIAN HIEROGLYPH BEGIN WALLED ENCLOSURE + {0x1343F, 0x1343F, prCL, gcCf}, // EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prCM, gcMn}, // EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prAL, gcLo}, // [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prCM, gcMn}, // [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED + {0x14400, 0x145CD, prAL, gcLo}, // [462] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A409 + {0x145CE, 0x145CE, prOP, gcLo}, // ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK + {0x145CF, 0x145CF, prCL, gcLo}, // ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK + {0x145D0, 0x14646, prAL, gcLo}, // [119] ANATOLIAN HIEROGLYPH A411..ANATOLIAN HIEROGLYPH A530 + {0x16800, 0x16A38, prAL, gcLo}, // [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ + {0x16A40, 0x16A5E, prAL, gcLo}, // [31] MRO LETTER TA..MRO LETTER TEK + {0x16A60, 0x16A69, prNU, gcNd}, // [10] MRO DIGIT ZERO..MRO DIGIT NINE + {0x16A6E, 0x16A6F, prBA, gcPo}, // [2] MRO DANDA..MRO DOUBLE DANDA + {0x16A70, 0x16ABE, prAL, gcLo}, // [79] TANGSA LETTER OZ..TANGSA LETTER ZA + {0x16AC0, 0x16AC9, prNU, gcNd}, // [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE + {0x16AD0, 0x16AED, prAL, gcLo}, // [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I + {0x16AF0, 0x16AF4, prCM, gcMn}, // [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE + {0x16AF5, 0x16AF5, prBA, gcPo}, // BASSA VAH FULL STOP + {0x16B00, 0x16B2F, prAL, gcLo}, // [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU + {0x16B30, 0x16B36, prCM, gcMn}, // [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM + {0x16B37, 0x16B39, prBA, gcPo}, // [3] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN CIM CHEEM + {0x16B3A, 0x16B3B, prAL, gcPo}, // [2] PAHAWH HMONG SIGN VOS THIAB..PAHAWH HMONG SIGN VOS FEEM + {0x16B3C, 0x16B3F, prAL, gcSo}, // [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB + {0x16B40, 0x16B43, prAL, gcLm}, // [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM + {0x16B44, 0x16B44, prBA, gcPo}, // PAHAWH HMONG SIGN XAUS + {0x16B45, 0x16B45, prAL, gcSo}, // PAHAWH HMONG SIGN CIM TSOV ROG + {0x16B50, 0x16B59, prNU, gcNd}, // [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE + {0x16B5B, 0x16B61, prAL, gcNo}, // [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS + {0x16B63, 0x16B77, prAL, gcLo}, // [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS + {0x16B7D, 0x16B8F, prAL, gcLo}, // [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ + {0x16E40, 0x16E7F, prAL, gcLC}, // [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y + {0x16E80, 0x16E96, prAL, gcNo}, // [23] MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN DIGIT THREE ALTERNATE FORM + {0x16E97, 0x16E98, prBA, gcPo}, // [2] MEDEFAIDRIN COMMA..MEDEFAIDRIN FULL STOP + {0x16E99, 0x16E9A, prAL, gcPo}, // [2] MEDEFAIDRIN SYMBOL AIVA..MEDEFAIDRIN EXCLAMATION OH + {0x16F00, 0x16F4A, prAL, gcLo}, // [75] MIAO LETTER PA..MIAO LETTER RTE + {0x16F4F, 0x16F4F, prCM, gcMn}, // MIAO SIGN CONSONANT MODIFIER BAR + {0x16F50, 0x16F50, prAL, gcLo}, // MIAO LETTER NASALIZATION + {0x16F51, 0x16F87, prCM, gcMc}, // [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI + {0x16F8F, 0x16F92, prCM, gcMn}, // [4] MIAO TONE RIGHT..MIAO TONE BELOW + {0x16F93, 0x16F9F, prAL, gcLm}, // [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 + {0x16FE0, 0x16FE1, prNS, gcLm}, // [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK + {0x16FE2, 0x16FE2, prNS, gcPo}, // OLD CHINESE HOOK MARK + {0x16FE3, 0x16FE3, prNS, gcLm}, // OLD CHINESE ITERATION MARK + {0x16FE4, 0x16FE4, prGL, gcMn}, // KHITAN SMALL SCRIPT FILLER + {0x16FF0, 0x16FF1, prCM, gcMc}, // [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY + {0x17000, 0x187F7, prID, gcLo}, // [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 + {0x18800, 0x18AFF, prID, gcLo}, // [768] TANGUT COMPONENT-001..TANGUT COMPONENT-768 + {0x18B00, 0x18CD5, prAL, gcLo}, // [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5 + {0x18D00, 0x18D08, prID, gcLo}, // [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 + {0x1AFF0, 0x1AFF3, prAL, gcLm}, // [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 + {0x1AFF5, 0x1AFFB, prAL, gcLm}, // [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 + {0x1AFFD, 0x1AFFE, prAL, gcLm}, // [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 + {0x1B000, 0x1B0FF, prID, gcLo}, // [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2 + {0x1B100, 0x1B122, prID, gcLo}, // [35] HENTAIGANA LETTER RE-3..KATAKANA LETTER ARCHAIC WU + {0x1B132, 0x1B132, prCJ, gcLo}, // HIRAGANA LETTER SMALL KO + {0x1B150, 0x1B152, prCJ, gcLo}, // [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO + {0x1B155, 0x1B155, prCJ, gcLo}, // KATAKANA LETTER SMALL KO + {0x1B164, 0x1B167, prCJ, gcLo}, // [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N + {0x1B170, 0x1B2FB, prID, gcLo}, // [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB + {0x1BC00, 0x1BC6A, prAL, gcLo}, // [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M + {0x1BC70, 0x1BC7C, prAL, gcLo}, // [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK + {0x1BC80, 0x1BC88, prAL, gcLo}, // [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL + {0x1BC90, 0x1BC99, prAL, gcLo}, // [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW + {0x1BC9C, 0x1BC9C, prAL, gcSo}, // DUPLOYAN SIGN O WITH CROSS + {0x1BC9D, 0x1BC9E, prCM, gcMn}, // [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK + {0x1BC9F, 0x1BC9F, prBA, gcPo}, // DUPLOYAN PUNCTUATION CHINOOK FULL STOP + {0x1BCA0, 0x1BCA3, prCM, gcCf}, // [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP + {0x1CF00, 0x1CF2D, prCM, gcMn}, // [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT + {0x1CF30, 0x1CF46, prCM, gcMn}, // [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG + {0x1CF50, 0x1CFC3, prAL, gcSo}, // [116] ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK + {0x1D000, 0x1D0F5, prAL, gcSo}, // [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO + {0x1D100, 0x1D126, prAL, gcSo}, // [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2 + {0x1D129, 0x1D164, prAL, gcSo}, // [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE + {0x1D165, 0x1D166, prCM, gcMc}, // [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM + {0x1D167, 0x1D169, prCM, gcMn}, // [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 + {0x1D16A, 0x1D16C, prAL, gcSo}, // [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3 + {0x1D16D, 0x1D172, prCM, gcMc}, // [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 + {0x1D173, 0x1D17A, prCM, gcCf}, // [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE + {0x1D17B, 0x1D182, prCM, gcMn}, // [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE + {0x1D183, 0x1D184, prAL, gcSo}, // [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN + {0x1D185, 0x1D18B, prCM, gcMn}, // [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE + {0x1D18C, 0x1D1A9, prAL, gcSo}, // [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH + {0x1D1AA, 0x1D1AD, prCM, gcMn}, // [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO + {0x1D1AE, 0x1D1EA, prAL, gcSo}, // [61] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KORON + {0x1D200, 0x1D241, prAL, gcSo}, // [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 + {0x1D242, 0x1D244, prCM, gcMn}, // [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME + {0x1D245, 0x1D245, prAL, gcSo}, // GREEK MUSICAL LEIMMA + {0x1D2C0, 0x1D2D3, prAL, gcNo}, // [20] KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN + {0x1D2E0, 0x1D2F3, prAL, gcNo}, // [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN + {0x1D300, 0x1D356, prAL, gcSo}, // [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING + {0x1D360, 0x1D378, prAL, gcNo}, // [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE + {0x1D400, 0x1D454, prAL, gcLC}, // [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G + {0x1D456, 0x1D49C, prAL, gcLC}, // [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A + {0x1D49E, 0x1D49F, prAL, gcLu}, // [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D + {0x1D4A2, 0x1D4A2, prAL, gcLu}, // MATHEMATICAL SCRIPT CAPITAL G + {0x1D4A5, 0x1D4A6, prAL, gcLu}, // [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K + {0x1D4A9, 0x1D4AC, prAL, gcLu}, // [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q + {0x1D4AE, 0x1D4B9, prAL, gcLC}, // [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D + {0x1D4BB, 0x1D4BB, prAL, gcLl}, // MATHEMATICAL SCRIPT SMALL F + {0x1D4BD, 0x1D4C3, prAL, gcLl}, // [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N + {0x1D4C5, 0x1D505, prAL, gcLC}, // [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B + {0x1D507, 0x1D50A, prAL, gcLu}, // [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G + {0x1D50D, 0x1D514, prAL, gcLu}, // [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q + {0x1D516, 0x1D51C, prAL, gcLu}, // [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y + {0x1D51E, 0x1D539, prAL, gcLC}, // [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B + {0x1D53B, 0x1D53E, prAL, gcLu}, // [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G + {0x1D540, 0x1D544, prAL, gcLu}, // [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M + {0x1D546, 0x1D546, prAL, gcLu}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL O + {0x1D54A, 0x1D550, prAL, gcLu}, // [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y + {0x1D552, 0x1D6A5, prAL, gcLC}, // [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J + {0x1D6A8, 0x1D6C0, prAL, gcLu}, // [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA + {0x1D6C1, 0x1D6C1, prAL, gcSm}, // MATHEMATICAL BOLD NABLA + {0x1D6C2, 0x1D6DA, prAL, gcLl}, // [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA + {0x1D6DB, 0x1D6DB, prAL, gcSm}, // MATHEMATICAL BOLD PARTIAL DIFFERENTIAL + {0x1D6DC, 0x1D6FA, prAL, gcLC}, // [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA + {0x1D6FB, 0x1D6FB, prAL, gcSm}, // MATHEMATICAL ITALIC NABLA + {0x1D6FC, 0x1D714, prAL, gcLl}, // [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA + {0x1D715, 0x1D715, prAL, gcSm}, // MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL + {0x1D716, 0x1D734, prAL, gcLC}, // [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA + {0x1D735, 0x1D735, prAL, gcSm}, // MATHEMATICAL BOLD ITALIC NABLA + {0x1D736, 0x1D74E, prAL, gcLl}, // [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA + {0x1D74F, 0x1D74F, prAL, gcSm}, // MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL + {0x1D750, 0x1D76E, prAL, gcLC}, // [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA + {0x1D76F, 0x1D76F, prAL, gcSm}, // MATHEMATICAL SANS-SERIF BOLD NABLA + {0x1D770, 0x1D788, prAL, gcLl}, // [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA + {0x1D789, 0x1D789, prAL, gcSm}, // MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL + {0x1D78A, 0x1D7A8, prAL, gcLC}, // [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA + {0x1D7A9, 0x1D7A9, prAL, gcSm}, // MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA + {0x1D7AA, 0x1D7C2, prAL, gcLl}, // [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA + {0x1D7C3, 0x1D7C3, prAL, gcSm}, // MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL + {0x1D7C4, 0x1D7CB, prAL, gcLC}, // [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA + {0x1D7CE, 0x1D7FF, prNU, gcNd}, // [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE + {0x1D800, 0x1D9FF, prAL, gcSo}, // [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD + {0x1DA00, 0x1DA36, prCM, gcMn}, // [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN + {0x1DA37, 0x1DA3A, prAL, gcSo}, // [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE + {0x1DA3B, 0x1DA6C, prCM, gcMn}, // [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT + {0x1DA6D, 0x1DA74, prAL, gcSo}, // [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING + {0x1DA75, 0x1DA75, prCM, gcMn}, // SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS + {0x1DA76, 0x1DA83, prAL, gcSo}, // [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH + {0x1DA84, 0x1DA84, prCM, gcMn}, // SIGNWRITING LOCATION HEAD NECK + {0x1DA85, 0x1DA86, prAL, gcSo}, // [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS + {0x1DA87, 0x1DA8A, prBA, gcPo}, // [4] SIGNWRITING COMMA..SIGNWRITING COLON + {0x1DA8B, 0x1DA8B, prAL, gcPo}, // SIGNWRITING PARENTHESIS + {0x1DA9B, 0x1DA9F, prCM, gcMn}, // [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 + {0x1DAA1, 0x1DAAF, prCM, gcMn}, // [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + {0x1DF00, 0x1DF09, prAL, gcLl}, // [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK + {0x1DF0A, 0x1DF0A, prAL, gcLo}, // LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK + {0x1DF0B, 0x1DF1E, prAL, gcLl}, // [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prAL, gcLl}, // [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK + {0x1E000, 0x1E006, prCM, gcMn}, // [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE + {0x1E008, 0x1E018, prCM, gcMn}, // [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU + {0x1E01B, 0x1E021, prCM, gcMn}, // [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI + {0x1E023, 0x1E024, prCM, gcMn}, // [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS + {0x1E026, 0x1E02A, prCM, gcMn}, // [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prAL, gcLm}, // [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prCM, gcMn}, // COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + {0x1E100, 0x1E12C, prAL, gcLo}, // [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W + {0x1E130, 0x1E136, prCM, gcMn}, // [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D + {0x1E137, 0x1E13D, prAL, gcLm}, // [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER + {0x1E140, 0x1E149, prNU, gcNd}, // [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE + {0x1E14E, 0x1E14E, prAL, gcLo}, // NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ + {0x1E14F, 0x1E14F, prAL, gcSo}, // NYIAKENG PUACHUE HMONG CIRCLED CA + {0x1E290, 0x1E2AD, prAL, gcLo}, // [30] TOTO LETTER PA..TOTO LETTER A + {0x1E2AE, 0x1E2AE, prCM, gcMn}, // TOTO SIGN RISING TONE + {0x1E2C0, 0x1E2EB, prAL, gcLo}, // [44] WANCHO LETTER AA..WANCHO LETTER YIH + {0x1E2EC, 0x1E2EF, prCM, gcMn}, // [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E2F0, 0x1E2F9, prNU, gcNd}, // [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE + {0x1E2FF, 0x1E2FF, prPR, gcSc}, // WANCHO NGUN SIGN + {0x1E4D0, 0x1E4EA, prAL, gcLo}, // [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prAL, gcLm}, // NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prCM, gcMn}, // [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prNU, gcNd}, // [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE + {0x1E7E0, 0x1E7E6, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO + {0x1E7E8, 0x1E7EB, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE + {0x1E7ED, 0x1E7EE, prAL, gcLo}, // [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE + {0x1E7F0, 0x1E7FE, prAL, gcLo}, // [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE + {0x1E800, 0x1E8C4, prAL, gcLo}, // [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON + {0x1E8C7, 0x1E8CF, prAL, gcNo}, // [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE + {0x1E8D0, 0x1E8D6, prCM, gcMn}, // [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + {0x1E900, 0x1E943, prAL, gcLC}, // [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA + {0x1E944, 0x1E94A, prCM, gcMn}, // [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA + {0x1E94B, 0x1E94B, prAL, gcLm}, // ADLAM NASALIZATION MARK + {0x1E950, 0x1E959, prNU, gcNd}, // [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE + {0x1E95E, 0x1E95F, prOP, gcPo}, // [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK + {0x1EC71, 0x1ECAB, prAL, gcNo}, // [59] INDIC SIYAQ NUMBER ONE..INDIC SIYAQ NUMBER PREFIXED NINE + {0x1ECAC, 0x1ECAC, prPO, gcSo}, // INDIC SIYAQ PLACEHOLDER + {0x1ECAD, 0x1ECAF, prAL, gcNo}, // [3] INDIC SIYAQ FRACTION ONE QUARTER..INDIC SIYAQ FRACTION THREE QUARTERS + {0x1ECB0, 0x1ECB0, prPO, gcSc}, // INDIC SIYAQ RUPEE MARK + {0x1ECB1, 0x1ECB4, prAL, gcNo}, // [4] INDIC SIYAQ NUMBER ALTERNATE ONE..INDIC SIYAQ ALTERNATE LAKH MARK + {0x1ED01, 0x1ED2D, prAL, gcNo}, // [45] OTTOMAN SIYAQ NUMBER ONE..OTTOMAN SIYAQ NUMBER NINETY THOUSAND + {0x1ED2E, 0x1ED2E, prAL, gcSo}, // OTTOMAN SIYAQ MARRATAN + {0x1ED2F, 0x1ED3D, prAL, gcNo}, // [15] OTTOMAN SIYAQ ALTERNATE NUMBER TWO..OTTOMAN SIYAQ FRACTION ONE SIXTH + {0x1EE00, 0x1EE03, prAL, gcLo}, // [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL + {0x1EE05, 0x1EE1F, prAL, gcLo}, // [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF + {0x1EE21, 0x1EE22, prAL, gcLo}, // [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM + {0x1EE24, 0x1EE24, prAL, gcLo}, // ARABIC MATHEMATICAL INITIAL HEH + {0x1EE27, 0x1EE27, prAL, gcLo}, // ARABIC MATHEMATICAL INITIAL HAH + {0x1EE29, 0x1EE32, prAL, gcLo}, // [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF + {0x1EE34, 0x1EE37, prAL, gcLo}, // [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH + {0x1EE39, 0x1EE39, prAL, gcLo}, // ARABIC MATHEMATICAL INITIAL DAD + {0x1EE3B, 0x1EE3B, prAL, gcLo}, // ARABIC MATHEMATICAL INITIAL GHAIN + {0x1EE42, 0x1EE42, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED JEEM + {0x1EE47, 0x1EE47, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED HAH + {0x1EE49, 0x1EE49, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED YEH + {0x1EE4B, 0x1EE4B, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED LAM + {0x1EE4D, 0x1EE4F, prAL, gcLo}, // [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN + {0x1EE51, 0x1EE52, prAL, gcLo}, // [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF + {0x1EE54, 0x1EE54, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED SHEEN + {0x1EE57, 0x1EE57, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED KHAH + {0x1EE59, 0x1EE59, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED DAD + {0x1EE5B, 0x1EE5B, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED GHAIN + {0x1EE5D, 0x1EE5D, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED DOTLESS NOON + {0x1EE5F, 0x1EE5F, prAL, gcLo}, // ARABIC MATHEMATICAL TAILED DOTLESS QAF + {0x1EE61, 0x1EE62, prAL, gcLo}, // [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM + {0x1EE64, 0x1EE64, prAL, gcLo}, // ARABIC MATHEMATICAL STRETCHED HEH + {0x1EE67, 0x1EE6A, prAL, gcLo}, // [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF + {0x1EE6C, 0x1EE72, prAL, gcLo}, // [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF + {0x1EE74, 0x1EE77, prAL, gcLo}, // [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH + {0x1EE79, 0x1EE7C, prAL, gcLo}, // [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH + {0x1EE7E, 0x1EE7E, prAL, gcLo}, // ARABIC MATHEMATICAL STRETCHED DOTLESS FEH + {0x1EE80, 0x1EE89, prAL, gcLo}, // [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH + {0x1EE8B, 0x1EE9B, prAL, gcLo}, // [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN + {0x1EEA1, 0x1EEA3, prAL, gcLo}, // [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL + {0x1EEA5, 0x1EEA9, prAL, gcLo}, // [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH + {0x1EEAB, 0x1EEBB, prAL, gcLo}, // [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN + {0x1EEF0, 0x1EEF1, prAL, gcSm}, // [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL + {0x1F000, 0x1F02B, prID, gcSo}, // [44] MAHJONG TILE EAST WIND..MAHJONG TILE BACK + {0x1F02C, 0x1F02F, prID, gcCn}, // [4] .. + {0x1F030, 0x1F093, prID, gcSo}, // [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06 + {0x1F094, 0x1F09F, prID, gcCn}, // [12] .. + {0x1F0A0, 0x1F0AE, prID, gcSo}, // [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES + {0x1F0AF, 0x1F0B0, prID, gcCn}, // [2] .. + {0x1F0B1, 0x1F0BF, prID, gcSo}, // [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER + {0x1F0C0, 0x1F0C0, prID, gcCn}, // + {0x1F0C1, 0x1F0CF, prID, gcSo}, // [15] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD BLACK JOKER + {0x1F0D0, 0x1F0D0, prID, gcCn}, // + {0x1F0D1, 0x1F0F5, prID, gcSo}, // [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21 + {0x1F0F6, 0x1F0FF, prID, gcCn}, // [10] .. + {0x1F100, 0x1F10C, prAI, gcNo}, // [13] DIGIT ZERO FULL STOP..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO + {0x1F10D, 0x1F10F, prID, gcSo}, // [3] CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH + {0x1F110, 0x1F12D, prAI, gcSo}, // [30] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED CD + {0x1F12E, 0x1F12F, prAL, gcSo}, // [2] CIRCLED WZ..COPYLEFT SYMBOL + {0x1F130, 0x1F169, prAI, gcSo}, // [58] SQUARED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z + {0x1F16A, 0x1F16C, prAL, gcSo}, // [3] RAISED MC SIGN..RAISED MR SIGN + {0x1F16D, 0x1F16F, prID, gcSo}, // [3] CIRCLED CC..CIRCLED HUMAN FIGURE + {0x1F170, 0x1F1AC, prAI, gcSo}, // [61] NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VOD + {0x1F1AD, 0x1F1AD, prID, gcSo}, // MASK WORK SYMBOL + {0x1F1AE, 0x1F1E5, prID, gcCn}, // [56] .. + {0x1F1E6, 0x1F1FF, prRI, gcSo}, // [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + {0x1F200, 0x1F202, prID, gcSo}, // [3] SQUARE HIRAGANA HOKA..SQUARED KATAKANA SA + {0x1F203, 0x1F20F, prID, gcCn}, // [13] .. + {0x1F210, 0x1F23B, prID, gcSo}, // [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D + {0x1F23C, 0x1F23F, prID, gcCn}, // [4] .. + {0x1F240, 0x1F248, prID, gcSo}, // [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 + {0x1F249, 0x1F24F, prID, gcCn}, // [7] .. + {0x1F250, 0x1F251, prID, gcSo}, // [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT + {0x1F252, 0x1F25F, prID, gcCn}, // [14] .. + {0x1F260, 0x1F265, prID, gcSo}, // [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI + {0x1F266, 0x1F2FF, prID, gcCn}, // [154] .. + {0x1F300, 0x1F384, prID, gcSo}, // [133] CYCLONE..CHRISTMAS TREE + {0x1F385, 0x1F385, prEB, gcSo}, // FATHER CHRISTMAS + {0x1F386, 0x1F39B, prID, gcSo}, // [22] FIREWORKS..CONTROL KNOBS + {0x1F39C, 0x1F39D, prAL, gcSo}, // [2] BEAMED ASCENDING MUSICAL NOTES..BEAMED DESCENDING MUSICAL NOTES + {0x1F39E, 0x1F3B4, prID, gcSo}, // [23] FILM FRAMES..FLOWER PLAYING CARDS + {0x1F3B5, 0x1F3B6, prAL, gcSo}, // [2] MUSICAL NOTE..MULTIPLE MUSICAL NOTES + {0x1F3B7, 0x1F3BB, prID, gcSo}, // [5] SAXOPHONE..VIOLIN + {0x1F3BC, 0x1F3BC, prAL, gcSo}, // MUSICAL SCORE + {0x1F3BD, 0x1F3C1, prID, gcSo}, // [5] RUNNING SHIRT WITH SASH..CHEQUERED FLAG + {0x1F3C2, 0x1F3C4, prEB, gcSo}, // [3] SNOWBOARDER..SURFER + {0x1F3C5, 0x1F3C6, prID, gcSo}, // [2] SPORTS MEDAL..TROPHY + {0x1F3C7, 0x1F3C7, prEB, gcSo}, // HORSE RACING + {0x1F3C8, 0x1F3C9, prID, gcSo}, // [2] AMERICAN FOOTBALL..RUGBY FOOTBALL + {0x1F3CA, 0x1F3CC, prEB, gcSo}, // [3] SWIMMER..GOLFER + {0x1F3CD, 0x1F3FA, prID, gcSo}, // [46] RACING MOTORCYCLE..AMPHORA + {0x1F3FB, 0x1F3FF, prEM, gcSk}, // [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 + {0x1F400, 0x1F441, prID, gcSo}, // [66] RAT..EYE + {0x1F442, 0x1F443, prEB, gcSo}, // [2] EAR..NOSE + {0x1F444, 0x1F445, prID, gcSo}, // [2] MOUTH..TONGUE + {0x1F446, 0x1F450, prEB, gcSo}, // [11] WHITE UP POINTING BACKHAND INDEX..OPEN HANDS SIGN + {0x1F451, 0x1F465, prID, gcSo}, // [21] CROWN..BUSTS IN SILHOUETTE + {0x1F466, 0x1F478, prEB, gcSo}, // [19] BOY..PRINCESS + {0x1F479, 0x1F47B, prID, gcSo}, // [3] JAPANESE OGRE..GHOST + {0x1F47C, 0x1F47C, prEB, gcSo}, // BABY ANGEL + {0x1F47D, 0x1F480, prID, gcSo}, // [4] EXTRATERRESTRIAL ALIEN..SKULL + {0x1F481, 0x1F483, prEB, gcSo}, // [3] INFORMATION DESK PERSON..DANCER + {0x1F484, 0x1F484, prID, gcSo}, // LIPSTICK + {0x1F485, 0x1F487, prEB, gcSo}, // [3] NAIL POLISH..HAIRCUT + {0x1F488, 0x1F48E, prID, gcSo}, // [7] BARBER POLE..GEM STONE + {0x1F48F, 0x1F48F, prEB, gcSo}, // KISS + {0x1F490, 0x1F490, prID, gcSo}, // BOUQUET + {0x1F491, 0x1F491, prEB, gcSo}, // COUPLE WITH HEART + {0x1F492, 0x1F49F, prID, gcSo}, // [14] WEDDING..HEART DECORATION + {0x1F4A0, 0x1F4A0, prAL, gcSo}, // DIAMOND SHAPE WITH A DOT INSIDE + {0x1F4A1, 0x1F4A1, prID, gcSo}, // ELECTRIC LIGHT BULB + {0x1F4A2, 0x1F4A2, prAL, gcSo}, // ANGER SYMBOL + {0x1F4A3, 0x1F4A3, prID, gcSo}, // BOMB + {0x1F4A4, 0x1F4A4, prAL, gcSo}, // SLEEPING SYMBOL + {0x1F4A5, 0x1F4A9, prID, gcSo}, // [5] COLLISION SYMBOL..PILE OF POO + {0x1F4AA, 0x1F4AA, prEB, gcSo}, // FLEXED BICEPS + {0x1F4AB, 0x1F4AE, prID, gcSo}, // [4] DIZZY SYMBOL..WHITE FLOWER + {0x1F4AF, 0x1F4AF, prAL, gcSo}, // HUNDRED POINTS SYMBOL + {0x1F4B0, 0x1F4B0, prID, gcSo}, // MONEY BAG + {0x1F4B1, 0x1F4B2, prAL, gcSo}, // [2] CURRENCY EXCHANGE..HEAVY DOLLAR SIGN + {0x1F4B3, 0x1F4FF, prID, gcSo}, // [77] CREDIT CARD..PRAYER BEADS + {0x1F500, 0x1F506, prAL, gcSo}, // [7] TWISTED RIGHTWARDS ARROWS..HIGH BRIGHTNESS SYMBOL + {0x1F507, 0x1F516, prID, gcSo}, // [16] SPEAKER WITH CANCELLATION STROKE..BOOKMARK + {0x1F517, 0x1F524, prAL, gcSo}, // [14] LINK SYMBOL..INPUT SYMBOL FOR LATIN LETTERS + {0x1F525, 0x1F531, prID, gcSo}, // [13] FIRE..TRIDENT EMBLEM + {0x1F532, 0x1F549, prAL, gcSo}, // [24] BLACK SQUARE BUTTON..OM SYMBOL + {0x1F54A, 0x1F573, prID, gcSo}, // [42] DOVE OF PEACE..HOLE + {0x1F574, 0x1F575, prEB, gcSo}, // [2] MAN IN BUSINESS SUIT LEVITATING..SLEUTH OR SPY + {0x1F576, 0x1F579, prID, gcSo}, // [4] DARK SUNGLASSES..JOYSTICK + {0x1F57A, 0x1F57A, prEB, gcSo}, // MAN DANCING + {0x1F57B, 0x1F58F, prID, gcSo}, // [21] LEFT HAND TELEPHONE RECEIVER..TURNED OK HAND SIGN + {0x1F590, 0x1F590, prEB, gcSo}, // RAISED HAND WITH FINGERS SPLAYED + {0x1F591, 0x1F594, prID, gcSo}, // [4] REVERSED RAISED HAND WITH FINGERS SPLAYED..REVERSED VICTORY HAND + {0x1F595, 0x1F596, prEB, gcSo}, // [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS + {0x1F597, 0x1F5D3, prID, gcSo}, // [61] WHITE DOWN POINTING LEFT HAND INDEX..SPIRAL CALENDAR PAD + {0x1F5D4, 0x1F5DB, prAL, gcSo}, // [8] DESKTOP WINDOW..DECREASE FONT SIZE SYMBOL + {0x1F5DC, 0x1F5F3, prID, gcSo}, // [24] COMPRESSION..BALLOT BOX WITH BALLOT + {0x1F5F4, 0x1F5F9, prAL, gcSo}, // [6] BALLOT SCRIPT X..BALLOT BOX WITH BOLD CHECK + {0x1F5FA, 0x1F5FF, prID, gcSo}, // [6] WORLD MAP..MOYAI + {0x1F600, 0x1F644, prID, gcSo}, // [69] GRINNING FACE..FACE WITH ROLLING EYES + {0x1F645, 0x1F647, prEB, gcSo}, // [3] FACE WITH NO GOOD GESTURE..PERSON BOWING DEEPLY + {0x1F648, 0x1F64A, prID, gcSo}, // [3] SEE-NO-EVIL MONKEY..SPEAK-NO-EVIL MONKEY + {0x1F64B, 0x1F64F, prEB, gcSo}, // [5] HAPPY PERSON RAISING ONE HAND..PERSON WITH FOLDED HANDS + {0x1F650, 0x1F675, prAL, gcSo}, // [38] NORTH WEST POINTING LEAF..SWASH AMPERSAND ORNAMENT + {0x1F676, 0x1F678, prQU, gcSo}, // [3] SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT..SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT + {0x1F679, 0x1F67B, prNS, gcSo}, // [3] HEAVY INTERROBANG ORNAMENT..HEAVY SANS-SERIF INTERROBANG ORNAMENT + {0x1F67C, 0x1F67F, prAL, gcSo}, // [4] VERY HEAVY SOLIDUS..REVERSE CHECKER BOARD + {0x1F680, 0x1F6A2, prID, gcSo}, // [35] ROCKET..SHIP + {0x1F6A3, 0x1F6A3, prEB, gcSo}, // ROWBOAT + {0x1F6A4, 0x1F6B3, prID, gcSo}, // [16] SPEEDBOAT..NO BICYCLES + {0x1F6B4, 0x1F6B6, prEB, gcSo}, // [3] BICYCLIST..PEDESTRIAN + {0x1F6B7, 0x1F6BF, prID, gcSo}, // [9] NO PEDESTRIANS..SHOWER + {0x1F6C0, 0x1F6C0, prEB, gcSo}, // BATH + {0x1F6C1, 0x1F6CB, prID, gcSo}, // [11] BATHTUB..COUCH AND LAMP + {0x1F6CC, 0x1F6CC, prEB, gcSo}, // SLEEPING ACCOMMODATION + {0x1F6CD, 0x1F6D7, prID, gcSo}, // [11] SHOPPING BAGS..ELEVATOR + {0x1F6D8, 0x1F6DB, prID, gcCn}, // [4] .. + {0x1F6DC, 0x1F6EC, prID, gcSo}, // [17] WIRELESS..AIRPLANE ARRIVING + {0x1F6ED, 0x1F6EF, prID, gcCn}, // [3] .. + {0x1F6F0, 0x1F6FC, prID, gcSo}, // [13] SATELLITE..ROLLER SKATE + {0x1F6FD, 0x1F6FF, prID, gcCn}, // [3] .. + {0x1F700, 0x1F773, prAL, gcSo}, // [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE + {0x1F774, 0x1F776, prID, gcSo}, // [3] LOT OF FORTUNE..LUNAR ECLIPSE + {0x1F777, 0x1F77A, prID, gcCn}, // [4] .. + {0x1F77B, 0x1F77F, prID, gcSo}, // [5] HAUMEA..ORCUS + {0x1F780, 0x1F7D4, prAL, gcSo}, // [85] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR + {0x1F7D5, 0x1F7D9, prID, gcSo}, // [5] CIRCLED TRIANGLE..NINE POINTED WHITE STAR + {0x1F7DA, 0x1F7DF, prID, gcCn}, // [6] .. + {0x1F7E0, 0x1F7EB, prID, gcSo}, // [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE + {0x1F7EC, 0x1F7EF, prID, gcCn}, // [4] .. + {0x1F7F0, 0x1F7F0, prID, gcSo}, // HEAVY EQUALS SIGN + {0x1F7F1, 0x1F7FF, prID, gcCn}, // [15] .. + {0x1F800, 0x1F80B, prAL, gcSo}, // [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD + {0x1F80C, 0x1F80F, prID, gcCn}, // [4] .. + {0x1F810, 0x1F847, prAL, gcSo}, // [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW + {0x1F848, 0x1F84F, prID, gcCn}, // [8] .. + {0x1F850, 0x1F859, prAL, gcSo}, // [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW + {0x1F85A, 0x1F85F, prID, gcCn}, // [6] .. + {0x1F860, 0x1F887, prAL, gcSo}, // [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW + {0x1F888, 0x1F88F, prID, gcCn}, // [8] .. + {0x1F890, 0x1F8AD, prAL, gcSo}, // [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS + {0x1F8AE, 0x1F8AF, prID, gcCn}, // [2] .. + {0x1F8B0, 0x1F8B1, prID, gcSo}, // [2] ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST + {0x1F8B2, 0x1F8FF, prID, gcCn}, // [78] .. + {0x1F900, 0x1F90B, prAL, gcSo}, // [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT + {0x1F90C, 0x1F90C, prEB, gcSo}, // PINCHED FINGERS + {0x1F90D, 0x1F90E, prID, gcSo}, // [2] WHITE HEART..BROWN HEART + {0x1F90F, 0x1F90F, prEB, gcSo}, // PINCHING HAND + {0x1F910, 0x1F917, prID, gcSo}, // [8] ZIPPER-MOUTH FACE..HUGGING FACE + {0x1F918, 0x1F91F, prEB, gcSo}, // [8] SIGN OF THE HORNS..I LOVE YOU HAND SIGN + {0x1F920, 0x1F925, prID, gcSo}, // [6] FACE WITH COWBOY HAT..LYING FACE + {0x1F926, 0x1F926, prEB, gcSo}, // FACE PALM + {0x1F927, 0x1F92F, prID, gcSo}, // [9] SNEEZING FACE..SHOCKED FACE WITH EXPLODING HEAD + {0x1F930, 0x1F939, prEB, gcSo}, // [10] PREGNANT WOMAN..JUGGLING + {0x1F93A, 0x1F93B, prID, gcSo}, // [2] FENCER..MODERN PENTATHLON + {0x1F93C, 0x1F93E, prEB, gcSo}, // [3] WRESTLERS..HANDBALL + {0x1F93F, 0x1F976, prID, gcSo}, // [56] DIVING MASK..FREEZING FACE + {0x1F977, 0x1F977, prEB, gcSo}, // NINJA + {0x1F978, 0x1F9B4, prID, gcSo}, // [61] DISGUISED FACE..BONE + {0x1F9B5, 0x1F9B6, prEB, gcSo}, // [2] LEG..FOOT + {0x1F9B7, 0x1F9B7, prID, gcSo}, // TOOTH + {0x1F9B8, 0x1F9B9, prEB, gcSo}, // [2] SUPERHERO..SUPERVILLAIN + {0x1F9BA, 0x1F9BA, prID, gcSo}, // SAFETY VEST + {0x1F9BB, 0x1F9BB, prEB, gcSo}, // EAR WITH HEARING AID + {0x1F9BC, 0x1F9CC, prID, gcSo}, // [17] MOTORIZED WHEELCHAIR..TROLL + {0x1F9CD, 0x1F9CF, prEB, gcSo}, // [3] STANDING PERSON..DEAF PERSON + {0x1F9D0, 0x1F9D0, prID, gcSo}, // FACE WITH MONOCLE + {0x1F9D1, 0x1F9DD, prEB, gcSo}, // [13] ADULT..ELF + {0x1F9DE, 0x1F9FF, prID, gcSo}, // [34] GENIE..NAZAR AMULET + {0x1FA00, 0x1FA53, prAL, gcSo}, // [84] NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP + {0x1FA54, 0x1FA5F, prID, gcCn}, // [12] .. + {0x1FA60, 0x1FA6D, prID, gcSo}, // [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER + {0x1FA6E, 0x1FA6F, prID, gcCn}, // [2] .. + {0x1FA70, 0x1FA7C, prID, gcSo}, // [13] BALLET SHOES..CRUTCH + {0x1FA7D, 0x1FA7F, prID, gcCn}, // [3] .. + {0x1FA80, 0x1FA88, prID, gcSo}, // [9] YO-YO..FLUTE + {0x1FA89, 0x1FA8F, prID, gcCn}, // [7] .. + {0x1FA90, 0x1FABD, prID, gcSo}, // [46] RINGED PLANET..WING + {0x1FABE, 0x1FABE, prID, gcCn}, // + {0x1FABF, 0x1FAC2, prID, gcSo}, // [4] GOOSE..PEOPLE HUGGING + {0x1FAC3, 0x1FAC5, prEB, gcSo}, // [3] PREGNANT MAN..PERSON WITH CROWN + {0x1FAC6, 0x1FACD, prID, gcCn}, // [8] .. + {0x1FACE, 0x1FADB, prID, gcSo}, // [14] MOOSE..PEA POD + {0x1FADC, 0x1FADF, prID, gcCn}, // [4] .. + {0x1FAE0, 0x1FAE8, prID, gcSo}, // [9] MELTING FACE..SHAKING FACE + {0x1FAE9, 0x1FAEF, prID, gcCn}, // [7] .. + {0x1FAF0, 0x1FAF8, prEB, gcSo}, // [9] HAND WITH INDEX FINGER AND THUMB CROSSED..RIGHTWARDS PUSHING HAND + {0x1FAF9, 0x1FAFF, prID, gcCn}, // [7] .. + {0x1FB00, 0x1FB92, prAL, gcSo}, // [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK + {0x1FB94, 0x1FBCA, prAL, gcSo}, // [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON + {0x1FBF0, 0x1FBF9, prNU, gcNd}, // [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE + {0x1FC00, 0x1FFFD, prID, gcCn}, // [1022] .. + {0x20000, 0x2A6DF, prID, gcLo}, // [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF + {0x2A6E0, 0x2A6FF, prID, gcCn}, // [32] .. + {0x2A700, 0x2B739, prID, gcLo}, // [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739 + {0x2B73A, 0x2B73F, prID, gcCn}, // [6] .. + {0x2B740, 0x2B81D, prID, gcLo}, // [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D + {0x2B81E, 0x2B81F, prID, gcCn}, // [2] .. + {0x2B820, 0x2CEA1, prID, gcLo}, // [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 + {0x2CEA2, 0x2CEAF, prID, gcCn}, // [14] .. + {0x2CEB0, 0x2EBE0, prID, gcLo}, // [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 + {0x2EBE1, 0x2F7FF, prID, gcCn}, // [3103] .. + {0x2F800, 0x2FA1D, prID, gcLo}, // [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D + {0x2FA1E, 0x2FA1F, prID, gcCn}, // [2] .. + {0x2FA20, 0x2FFFD, prID, gcCn}, // [1502] .. + {0x30000, 0x3134A, prID, gcLo}, // [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A + {0x3134B, 0x3134F, prID, gcCn}, // [5] .. + {0x31350, 0x323AF, prID, gcLo}, // [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF + {0x323B0, 0x3FFFD, prID, gcCn}, // [56398] .. + {0xE0001, 0xE0001, prCM, gcCf}, // LANGUAGE TAG + {0xE0020, 0xE007F, prCM, gcCf}, // [96] TAG SPACE..CANCEL TAG + {0xE0100, 0xE01EF, prCM, gcMn}, // [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + {0xF0000, 0xFFFFD, prXX, gcCo}, // [65534] .. + {0x100000, 0x10FFFD, prXX, gcCo}, // [65534] .. +} diff --git a/vendor/github.com/rivo/uniseg/linerules.go b/vendor/github.com/rivo/uniseg/linerules.go new file mode 100644 index 000000000..7708ae0fb --- /dev/null +++ b/vendor/github.com/rivo/uniseg/linerules.go @@ -0,0 +1,626 @@ +package uniseg + +import "unicode/utf8" + +// The states of the line break parser. +const ( + lbAny = iota + lbBK + lbCR + lbLF + lbNL + lbSP + lbZW + lbWJ + lbGL + lbBA + lbHY + lbCL + lbCP + lbEX + lbIS + lbSY + lbOP + lbQU + lbQUSP + lbNS + lbCLCPSP + lbB2 + lbB2SP + lbCB + lbBB + lbLB21a + lbHL + lbAL + lbNU + lbPR + lbEB + lbIDEM + lbNUNU + lbNUSY + lbNUIS + lbNUCL + lbNUCP + lbPO + lbJL + lbJV + lbJT + lbH2 + lbH3 + lbOddRI + lbEvenRI + lbExtPicCn + lbZWJBit = 64 + lbCPeaFWHBit = 128 +) + +// These constants define whether a given text may be broken into the next line. +// If the break is optional (LineCanBreak), you may choose to break or not based +// on your own criteria, for example, if the text has reached the available +// width. +const ( + LineDontBreak = iota // You may not break the line here. + LineCanBreak // You may or may not break the line here. + LineMustBreak // You must break the line here. +) + +// lbTransitions implements the line break parser's state transitions. It's +// anologous to [grTransitions], see comments there for details. +// +// Unicode version 15.0.0. +func lbTransitions(state, prop int) (newState, lineBreak, rule int) { + switch uint64(state) | uint64(prop)<<32 { + // LB4. + case lbBK | prAny<<32: + return lbAny, LineMustBreak, 40 + + // LB5. + case lbCR | prLF<<32: + return lbLF, LineDontBreak, 50 + case lbCR | prAny<<32: + return lbAny, LineMustBreak, 50 + case lbLF | prAny<<32: + return lbAny, LineMustBreak, 50 + case lbNL | prAny<<32: + return lbAny, LineMustBreak, 50 + + // LB6. + case lbAny | prBK<<32: + return lbBK, LineDontBreak, 60 + case lbAny | prCR<<32: + return lbCR, LineDontBreak, 60 + case lbAny | prLF<<32: + return lbLF, LineDontBreak, 60 + case lbAny | prNL<<32: + return lbNL, LineDontBreak, 60 + + // LB7. + case lbAny | prSP<<32: + return lbSP, LineDontBreak, 70 + case lbAny | prZW<<32: + return lbZW, LineDontBreak, 70 + + // LB8. + case lbZW | prSP<<32: + return lbZW, LineDontBreak, 70 + case lbZW | prAny<<32: + return lbAny, LineCanBreak, 80 + + // LB11. + case lbAny | prWJ<<32: + return lbWJ, LineDontBreak, 110 + case lbWJ | prAny<<32: + return lbAny, LineDontBreak, 110 + + // LB12. + case lbAny | prGL<<32: + return lbGL, LineCanBreak, 310 + case lbGL | prAny<<32: + return lbAny, LineDontBreak, 120 + + // LB13 (simple transitions). + case lbAny | prCL<<32: + return lbCL, LineCanBreak, 310 + case lbAny | prCP<<32: + return lbCP, LineCanBreak, 310 + case lbAny | prEX<<32: + return lbEX, LineDontBreak, 130 + case lbAny | prIS<<32: + return lbIS, LineCanBreak, 310 + case lbAny | prSY<<32: + return lbSY, LineCanBreak, 310 + + // LB14. + case lbAny | prOP<<32: + return lbOP, LineCanBreak, 310 + case lbOP | prSP<<32: + return lbOP, LineDontBreak, 70 + case lbOP | prAny<<32: + return lbAny, LineDontBreak, 140 + + // LB15. + case lbQU | prSP<<32: + return lbQUSP, LineDontBreak, 70 + case lbQU | prOP<<32: + return lbOP, LineDontBreak, 150 + case lbQUSP | prOP<<32: + return lbOP, LineDontBreak, 150 + + // LB16. + case lbCL | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbNUCL | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbCP | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbNUCP | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbCL | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbNUCL | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbCP | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbNUCP | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbCLCPSP | prNS<<32: + return lbNS, LineDontBreak, 160 + + // LB17. + case lbAny | prB2<<32: + return lbB2, LineCanBreak, 310 + case lbB2 | prSP<<32: + return lbB2SP, LineDontBreak, 70 + case lbB2 | prB2<<32: + return lbB2, LineDontBreak, 170 + case lbB2SP | prB2<<32: + return lbB2, LineDontBreak, 170 + + // LB18. + case lbSP | prAny<<32: + return lbAny, LineCanBreak, 180 + case lbQUSP | prAny<<32: + return lbAny, LineCanBreak, 180 + case lbCLCPSP | prAny<<32: + return lbAny, LineCanBreak, 180 + case lbB2SP | prAny<<32: + return lbAny, LineCanBreak, 180 + + // LB19. + case lbAny | prQU<<32: + return lbQU, LineDontBreak, 190 + case lbQU | prAny<<32: + return lbAny, LineDontBreak, 190 + + // LB20. + case lbAny | prCB<<32: + return lbCB, LineCanBreak, 200 + case lbCB | prAny<<32: + return lbAny, LineCanBreak, 200 + + // LB21. + case lbAny | prBA<<32: + return lbBA, LineDontBreak, 210 + case lbAny | prHY<<32: + return lbHY, LineDontBreak, 210 + case lbAny | prNS<<32: + return lbNS, LineDontBreak, 210 + case lbAny | prBB<<32: + return lbBB, LineCanBreak, 310 + case lbBB | prAny<<32: + return lbAny, LineDontBreak, 210 + + // LB21a. + case lbAny | prHL<<32: + return lbHL, LineCanBreak, 310 + case lbHL | prHY<<32: + return lbLB21a, LineDontBreak, 210 + case lbHL | prBA<<32: + return lbLB21a, LineDontBreak, 210 + case lbLB21a | prAny<<32: + return lbAny, LineDontBreak, 211 + + // LB21b. + case lbSY | prHL<<32: + return lbHL, LineDontBreak, 212 + case lbNUSY | prHL<<32: + return lbHL, LineDontBreak, 212 + + // LB22. + case lbAny | prIN<<32: + return lbAny, LineDontBreak, 220 + + // LB23. + case lbAny | prAL<<32: + return lbAL, LineCanBreak, 310 + case lbAny | prNU<<32: + return lbNU, LineCanBreak, 310 + case lbAL | prNU<<32: + return lbNU, LineDontBreak, 230 + case lbHL | prNU<<32: + return lbNU, LineDontBreak, 230 + case lbNU | prAL<<32: + return lbAL, LineDontBreak, 230 + case lbNU | prHL<<32: + return lbHL, LineDontBreak, 230 + case lbNUNU | prAL<<32: + return lbAL, LineDontBreak, 230 + case lbNUNU | prHL<<32: + return lbHL, LineDontBreak, 230 + + // LB23a. + case lbAny | prPR<<32: + return lbPR, LineCanBreak, 310 + case lbAny | prID<<32: + return lbIDEM, LineCanBreak, 310 + case lbAny | prEB<<32: + return lbEB, LineCanBreak, 310 + case lbAny | prEM<<32: + return lbIDEM, LineCanBreak, 310 + case lbPR | prID<<32: + return lbIDEM, LineDontBreak, 231 + case lbPR | prEB<<32: + return lbEB, LineDontBreak, 231 + case lbPR | prEM<<32: + return lbIDEM, LineDontBreak, 231 + case lbIDEM | prPO<<32: + return lbPO, LineDontBreak, 231 + case lbEB | prPO<<32: + return lbPO, LineDontBreak, 231 + + // LB24. + case lbAny | prPO<<32: + return lbPO, LineCanBreak, 310 + case lbPR | prAL<<32: + return lbAL, LineDontBreak, 240 + case lbPR | prHL<<32: + return lbHL, LineDontBreak, 240 + case lbPO | prAL<<32: + return lbAL, LineDontBreak, 240 + case lbPO | prHL<<32: + return lbHL, LineDontBreak, 240 + case lbAL | prPR<<32: + return lbPR, LineDontBreak, 240 + case lbAL | prPO<<32: + return lbPO, LineDontBreak, 240 + case lbHL | prPR<<32: + return lbPR, LineDontBreak, 240 + case lbHL | prPO<<32: + return lbPO, LineDontBreak, 240 + + // LB25 (simple transitions). + case lbPR | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbPO | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbOP | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbHY | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbNU | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNU | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNU | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNUNU | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNUNU | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNUNU | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNUSY | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNUSY | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNUSY | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNUIS | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNUIS | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNUIS | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNU | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNU | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNUNU | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNUNU | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNUSY | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNUSY | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNUIS | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNUIS | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNU | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUNU | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUSY | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUIS | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUCL | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUCP | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNU | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUNU | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUSY | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUIS | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUCL | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUCP | prPR<<32: + return lbPR, LineDontBreak, 250 + + // LB26. + case lbAny | prJL<<32: + return lbJL, LineCanBreak, 310 + case lbAny | prJV<<32: + return lbJV, LineCanBreak, 310 + case lbAny | prJT<<32: + return lbJT, LineCanBreak, 310 + case lbAny | prH2<<32: + return lbH2, LineCanBreak, 310 + case lbAny | prH3<<32: + return lbH3, LineCanBreak, 310 + case lbJL | prJL<<32: + return lbJL, LineDontBreak, 260 + case lbJL | prJV<<32: + return lbJV, LineDontBreak, 260 + case lbJL | prH2<<32: + return lbH2, LineDontBreak, 260 + case lbJL | prH3<<32: + return lbH3, LineDontBreak, 260 + case lbJV | prJV<<32: + return lbJV, LineDontBreak, 260 + case lbJV | prJT<<32: + return lbJT, LineDontBreak, 260 + case lbH2 | prJV<<32: + return lbJV, LineDontBreak, 260 + case lbH2 | prJT<<32: + return lbJT, LineDontBreak, 260 + case lbJT | prJT<<32: + return lbJT, LineDontBreak, 260 + case lbH3 | prJT<<32: + return lbJT, LineDontBreak, 260 + + // LB27. + case lbJL | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbJV | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbJT | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbH2 | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbH3 | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbPR | prJL<<32: + return lbJL, LineDontBreak, 270 + case lbPR | prJV<<32: + return lbJV, LineDontBreak, 270 + case lbPR | prJT<<32: + return lbJT, LineDontBreak, 270 + case lbPR | prH2<<32: + return lbH2, LineDontBreak, 270 + case lbPR | prH3<<32: + return lbH3, LineDontBreak, 270 + + // LB28. + case lbAL | prAL<<32: + return lbAL, LineDontBreak, 280 + case lbAL | prHL<<32: + return lbHL, LineDontBreak, 280 + case lbHL | prAL<<32: + return lbAL, LineDontBreak, 280 + case lbHL | prHL<<32: + return lbHL, LineDontBreak, 280 + + // LB29. + case lbIS | prAL<<32: + return lbAL, LineDontBreak, 290 + case lbIS | prHL<<32: + return lbHL, LineDontBreak, 290 + case lbNUIS | prAL<<32: + return lbAL, LineDontBreak, 290 + case lbNUIS | prHL<<32: + return lbHL, LineDontBreak, 290 + + default: + return -1, -1, -1 + } +} + +// transitionLineBreakState determines the new state of the line break parser +// given the current state and the next code point. It also returns the type of +// line break: LineDontBreak, LineCanBreak, or LineMustBreak. If more than one +// code point is needed to determine the new state, the byte slice or the string +// starting after rune "r" can be used (whichever is not nil or empty) for +// further lookups. +func transitionLineBreakState(state int, r rune, b []byte, str string) (newState int, lineBreak int) { + // Determine the property of the next character. + nextProperty, generalCategory := propertyLineBreak(r) + + // Prepare. + var forceNoBreak, isCPeaFWH bool + if state >= 0 && state&lbCPeaFWHBit != 0 { + isCPeaFWH = true // LB30: CP but ea is not F, W, or H. + state = state &^ lbCPeaFWHBit + } + if state >= 0 && state&lbZWJBit != 0 { + state = state &^ lbZWJBit // Extract zero-width joiner bit. + forceNoBreak = true // LB8a. + } + + defer func() { + // Transition into LB30. + if newState == lbCP || newState == lbNUCP { + ea := propertyEastAsianWidth(r) + if ea != prF && ea != prW && ea != prH { + newState |= lbCPeaFWHBit + } + } + + // Override break. + if forceNoBreak { + lineBreak = LineDontBreak + } + }() + + // LB1. + if nextProperty == prAI || nextProperty == prSG || nextProperty == prXX { + nextProperty = prAL + } else if nextProperty == prSA { + if generalCategory == gcMn || generalCategory == gcMc { + nextProperty = prCM + } else { + nextProperty = prAL + } + } else if nextProperty == prCJ { + nextProperty = prNS + } + + // Combining marks. + if nextProperty == prZWJ || nextProperty == prCM { + var bit int + if nextProperty == prZWJ { + bit = lbZWJBit + } + mustBreakState := state < 0 || state == lbBK || state == lbCR || state == lbLF || state == lbNL + if !mustBreakState && state != lbSP && state != lbZW && state != lbQUSP && state != lbCLCPSP && state != lbB2SP { + // LB9. + return state | bit, LineDontBreak + } else { + // LB10. + if mustBreakState { + return lbAL | bit, LineMustBreak + } + return lbAL | bit, LineCanBreak + } + } + + // Find the applicable transition in the table. + var rule int + newState, lineBreak, rule = lbTransitions(state, nextProperty) + if newState < 0 { + // No specific transition found. Try the less specific ones. + anyPropProp, anyPropLineBreak, anyPropRule := lbTransitions(state, prAny) + anyStateProp, anyStateLineBreak, anyStateRule := lbTransitions(lbAny, nextProperty) + if anyPropProp >= 0 && anyStateProp >= 0 { + // Both apply. We'll use a mix (see comments for grTransitions). + newState, lineBreak, rule = anyStateProp, anyStateLineBreak, anyStateRule + if anyPropRule < anyStateRule { + lineBreak, rule = anyPropLineBreak, anyPropRule + } + } else if anyPropProp >= 0 { + // We only have a specific state. + newState, lineBreak, rule = anyPropProp, anyPropLineBreak, anyPropRule + // This branch will probably never be reached because okAnyState will + // always be true given the current transition map. But we keep it here + // for future modifications to the transition map where this may not be + // true anymore. + } else if anyStateProp >= 0 { + // We only have a specific property. + newState, lineBreak, rule = anyStateProp, anyStateLineBreak, anyStateRule + } else { + // No known transition. LB31: ALL ÷ ALL. + newState, lineBreak, rule = lbAny, LineCanBreak, 310 + } + } + + // LB12a. + if rule > 121 && + nextProperty == prGL && + (state != lbSP && state != lbBA && state != lbHY && state != lbLB21a && state != lbQUSP && state != lbCLCPSP && state != lbB2SP) { + return lbGL, LineDontBreak + } + + // LB13. + if rule > 130 && state != lbNU && state != lbNUNU { + switch nextProperty { + case prCL: + return lbCL, LineDontBreak + case prCP: + return lbCP, LineDontBreak + case prIS: + return lbIS, LineDontBreak + case prSY: + return lbSY, LineDontBreak + } + } + + // LB25 (look ahead). + if rule > 250 && + (state == lbPR || state == lbPO) && + nextProperty == prOP || nextProperty == prHY { + var r rune + if b != nil { // Byte slice version. + r, _ = utf8.DecodeRune(b) + } else { // String version. + r, _ = utf8.DecodeRuneInString(str) + } + if r != utf8.RuneError { + pr, _ := propertyLineBreak(r) + if pr == prNU { + return lbNU, LineDontBreak + } + } + } + + // LB30 (part one). + if rule > 300 { + if (state == lbAL || state == lbHL || state == lbNU || state == lbNUNU) && nextProperty == prOP { + ea := propertyEastAsianWidth(r) + if ea != prF && ea != prW && ea != prH { + return lbOP, LineDontBreak + } + } else if isCPeaFWH { + switch nextProperty { + case prAL: + return lbAL, LineDontBreak + case prHL: + return lbHL, LineDontBreak + case prNU: + return lbNU, LineDontBreak + } + } + } + + // LB30a. + if newState == lbAny && nextProperty == prRI { + if state != lbOddRI && state != lbEvenRI { // Includes state == -1. + // Transition into the first RI. + return lbOddRI, lineBreak + } + if state == lbOddRI { + // Don't break pairs of Regional Indicators. + return lbEvenRI, LineDontBreak + } + return lbOddRI, lineBreak + } + + // LB30b. + if rule > 302 { + if nextProperty == prEM { + if state == lbEB || state == lbExtPicCn { + return prAny, LineDontBreak + } + } + graphemeProperty := propertyGraphemes(r) + if graphemeProperty == prExtendedPictographic && generalCategory == gcCn { + return lbExtPicCn, LineCanBreak + } + } + + return +} diff --git a/vendor/github.com/rivo/uniseg/properties.go b/vendor/github.com/rivo/uniseg/properties.go new file mode 100644 index 000000000..6290e6810 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/properties.go @@ -0,0 +1,208 @@ +package uniseg + +// The Unicode properties as used in the various parsers. Only the ones needed +// in the context of this package are included. +const ( + prXX = 0 // Same as prAny. + prAny = iota // prAny must be 0. + prPrepend // Grapheme properties must come first, to reduce the number of bits stored in the state vector. + prCR + prLF + prControl + prExtend + prRegionalIndicator + prSpacingMark + prL + prV + prT + prLV + prLVT + prZWJ + prExtendedPictographic + prNewline + prWSegSpace + prDoubleQuote + prSingleQuote + prMidNumLet + prNumeric + prMidLetter + prMidNum + prExtendNumLet + prALetter + prFormat + prHebrewLetter + prKatakana + prSp + prSTerm + prClose + prSContinue + prATerm + prUpper + prLower + prSep + prOLetter + prCM + prBA + prBK + prSP + prEX + prQU + prAL + prPR + prPO + prOP + prCP + prIS + prHY + prSY + prNU + prCL + prNL + prGL + prAI + prBB + prHL + prSA + prJL + prJV + prJT + prNS + prZW + prB2 + prIN + prWJ + prID + prEB + prCJ + prH2 + prH3 + prSG + prCB + prRI + prEM + prN + prNa + prA + prW + prH + prF + prEmojiPresentation +) + +// Unicode General Categories. Only the ones needed in the context of this +// package are included. +const ( + gcNone = iota // gcNone must be 0. + gcCc + gcZs + gcPo + gcSc + gcPs + gcPe + gcSm + gcPd + gcNd + gcLu + gcSk + gcPc + gcLl + gcSo + gcLo + gcPi + gcCf + gcNo + gcPf + gcLC + gcLm + gcMn + gcMe + gcMc + gcNl + gcZl + gcZp + gcCn + gcCs + gcCo +) + +// Special code points. +const ( + vs15 = 0xfe0e // Variation Selector-15 (text presentation) + vs16 = 0xfe0f // Variation Selector-16 (emoji presentation) +) + +// propertySearch performs a binary search on a property slice and returns the +// entry whose range (start = first array element, end = second array element) +// includes r, or an array of 0's if no such entry was found. +func propertySearch[E interface{ [3]int | [4]int }](dictionary []E, r rune) (result E) { + // Run a binary search. + from := 0 + to := len(dictionary) + for to > from { + middle := (from + to) / 2 + cpRange := dictionary[middle] + if int(r) < cpRange[0] { + to = middle + continue + } + if int(r) > cpRange[1] { + from = middle + 1 + continue + } + return cpRange + } + return +} + +// property returns the Unicode property value (see constants above) of the +// given code point. +func property(dictionary [][3]int, r rune) int { + return propertySearch(dictionary, r)[2] +} + +// propertyLineBreak returns the Unicode property value and General Category +// (see constants above) of the given code point, as listed in the line break +// code points table, while fast tracking ASCII digits and letters. +func propertyLineBreak(r rune) (property, generalCategory int) { + if r >= 'a' && r <= 'z' { + return prAL, gcLl + } + if r >= 'A' && r <= 'Z' { + return prAL, gcLu + } + if r >= '0' && r <= '9' { + return prNU, gcNd + } + entry := propertySearch(lineBreakCodePoints, r) + return entry[2], entry[3] +} + +// propertyGraphemes returns the Unicode grapheme cluster property value of the +// given code point while fast tracking ASCII characters. +func propertyGraphemes(r rune) int { + if r >= 0x20 && r <= 0x7e { + return prAny + } + if r == 0x0a { + return prLF + } + if r == 0x0d { + return prCR + } + if r >= 0 && r <= 0x1f || r == 0x7f { + return prControl + } + return property(graphemeCodePoints, r) +} + +// propertyEastAsianWidth returns the Unicode East Asian Width property value of +// the given code point while fast tracking ASCII characters. +func propertyEastAsianWidth(r rune) int { + if r >= 0x20 && r <= 0x7e { + return prNa + } + if r >= 0 && r <= 0x1f || r == 0x7f { + return prN + } + return property(eastAsianWidth, r) +} diff --git a/vendor/github.com/rivo/uniseg/sentence.go b/vendor/github.com/rivo/uniseg/sentence.go new file mode 100644 index 000000000..adc2a3577 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/sentence.go @@ -0,0 +1,90 @@ +package uniseg + +import "unicode/utf8" + +// FirstSentence returns the first sentence found in the given byte slice +// according to the rules of [Unicode Standard Annex #29, Sentence Boundaries]. +// This function can be called continuously to extract all sentences from a byte +// slice, as illustrated in the example below. +// +// If you don't know the current state, for example when calling the function +// for the first time, you must pass -1. For consecutive calls, pass the state +// and rest slice returned by the previous call. +// +// The "rest" slice is the sub-slice of the original byte slice "b" starting +// after the last byte of the identified sentence. If the length of the "rest" +// slice is 0, the entire byte slice "b" has been processed. The "sentence" byte +// slice is the sub-slice of the input slice containing the identified sentence. +// +// Given an empty byte slice "b", the function returns nil values. +// +// [Unicode Standard Annex #29, Sentence Boundaries]: http://unicode.org/reports/tr29/#Sentence_Boundaries +func FirstSentence(b []byte, state int) (sentence, rest []byte, newState int) { + // An empty byte slice returns nothing. + if len(b) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRune(b) + if len(b) <= length { // If we're already past the end, there is nothing else to parse. + return b, nil, sbAny + } + + // If we don't know the state, determine it now. + if state < 0 { + state, _ = transitionSentenceBreakState(state, r, b[length:], "") + } + + // Transition until we find a boundary. + var boundary bool + for { + r, l := utf8.DecodeRune(b[length:]) + state, boundary = transitionSentenceBreakState(state, r, b[length+l:], "") + + if boundary { + return b[:length], b[length:], state + } + + length += l + if len(b) <= length { + return b, nil, sbAny + } + } +} + +// FirstSentenceInString is like [FirstSentence] but its input and outputs are +// strings. +func FirstSentenceInString(str string, state int) (sentence, rest string, newState int) { + // An empty byte slice returns nothing. + if len(str) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRuneInString(str) + if len(str) <= length { // If we're already past the end, there is nothing else to parse. + return str, "", sbAny + } + + // If we don't know the state, determine it now. + if state < 0 { + state, _ = transitionSentenceBreakState(state, r, nil, str[length:]) + } + + // Transition until we find a boundary. + var boundary bool + for { + r, l := utf8.DecodeRuneInString(str[length:]) + state, boundary = transitionSentenceBreakState(state, r, nil, str[length+l:]) + + if boundary { + return str[:length], str[length:], state + } + + length += l + if len(str) <= length { + return str, "", sbAny + } + } +} diff --git a/vendor/github.com/rivo/uniseg/sentenceproperties.go b/vendor/github.com/rivo/uniseg/sentenceproperties.go new file mode 100644 index 000000000..67717ec1f --- /dev/null +++ b/vendor/github.com/rivo/uniseg/sentenceproperties.go @@ -0,0 +1,2845 @@ +// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// sentenceBreakCodePoints are taken from +// https://www.unicode.org/Public/15.0.0/ucd/auxiliary/SentenceBreakProperty.txt +// and +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt +// ("Extended_Pictographic" only) +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var sentenceBreakCodePoints = [][3]int{ + {0x0009, 0x0009, prSp}, // Cc + {0x000A, 0x000A, prLF}, // Cc + {0x000B, 0x000C, prSp}, // Cc [2] .. + {0x000D, 0x000D, prCR}, // Cc + {0x0020, 0x0020, prSp}, // Zs SPACE + {0x0021, 0x0021, prSTerm}, // Po EXCLAMATION MARK + {0x0022, 0x0022, prClose}, // Po QUOTATION MARK + {0x0027, 0x0027, prClose}, // Po APOSTROPHE + {0x0028, 0x0028, prClose}, // Ps LEFT PARENTHESIS + {0x0029, 0x0029, prClose}, // Pe RIGHT PARENTHESIS + {0x002C, 0x002C, prSContinue}, // Po COMMA + {0x002D, 0x002D, prSContinue}, // Pd HYPHEN-MINUS + {0x002E, 0x002E, prATerm}, // Po FULL STOP + {0x0030, 0x0039, prNumeric}, // Nd [10] DIGIT ZERO..DIGIT NINE + {0x003A, 0x003A, prSContinue}, // Po COLON + {0x003F, 0x003F, prSTerm}, // Po QUESTION MARK + {0x0041, 0x005A, prUpper}, // L& [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z + {0x005B, 0x005B, prClose}, // Ps LEFT SQUARE BRACKET + {0x005D, 0x005D, prClose}, // Pe RIGHT SQUARE BRACKET + {0x0061, 0x007A, prLower}, // L& [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z + {0x007B, 0x007B, prClose}, // Ps LEFT CURLY BRACKET + {0x007D, 0x007D, prClose}, // Pe RIGHT CURLY BRACKET + {0x0085, 0x0085, prSep}, // Cc + {0x00A0, 0x00A0, prSp}, // Zs NO-BREAK SPACE + {0x00AA, 0x00AA, prLower}, // Lo FEMININE ORDINAL INDICATOR + {0x00AB, 0x00AB, prClose}, // Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + {0x00AD, 0x00AD, prFormat}, // Cf SOFT HYPHEN + {0x00B5, 0x00B5, prLower}, // L& MICRO SIGN + {0x00BA, 0x00BA, prLower}, // Lo MASCULINE ORDINAL INDICATOR + {0x00BB, 0x00BB, prClose}, // Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + {0x00C0, 0x00D6, prUpper}, // L& [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS + {0x00D8, 0x00DE, prUpper}, // L& [7] LATIN CAPITAL LETTER O WITH STROKE..LATIN CAPITAL LETTER THORN + {0x00DF, 0x00F6, prLower}, // L& [24] LATIN SMALL LETTER SHARP S..LATIN SMALL LETTER O WITH DIAERESIS + {0x00F8, 0x00FF, prLower}, // L& [8] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER Y WITH DIAERESIS + {0x0100, 0x0100, prUpper}, // L& LATIN CAPITAL LETTER A WITH MACRON + {0x0101, 0x0101, prLower}, // L& LATIN SMALL LETTER A WITH MACRON + {0x0102, 0x0102, prUpper}, // L& LATIN CAPITAL LETTER A WITH BREVE + {0x0103, 0x0103, prLower}, // L& LATIN SMALL LETTER A WITH BREVE + {0x0104, 0x0104, prUpper}, // L& LATIN CAPITAL LETTER A WITH OGONEK + {0x0105, 0x0105, prLower}, // L& LATIN SMALL LETTER A WITH OGONEK + {0x0106, 0x0106, prUpper}, // L& LATIN CAPITAL LETTER C WITH ACUTE + {0x0107, 0x0107, prLower}, // L& LATIN SMALL LETTER C WITH ACUTE + {0x0108, 0x0108, prUpper}, // L& LATIN CAPITAL LETTER C WITH CIRCUMFLEX + {0x0109, 0x0109, prLower}, // L& LATIN SMALL LETTER C WITH CIRCUMFLEX + {0x010A, 0x010A, prUpper}, // L& LATIN CAPITAL LETTER C WITH DOT ABOVE + {0x010B, 0x010B, prLower}, // L& LATIN SMALL LETTER C WITH DOT ABOVE + {0x010C, 0x010C, prUpper}, // L& LATIN CAPITAL LETTER C WITH CARON + {0x010D, 0x010D, prLower}, // L& LATIN SMALL LETTER C WITH CARON + {0x010E, 0x010E, prUpper}, // L& LATIN CAPITAL LETTER D WITH CARON + {0x010F, 0x010F, prLower}, // L& LATIN SMALL LETTER D WITH CARON + {0x0110, 0x0110, prUpper}, // L& LATIN CAPITAL LETTER D WITH STROKE + {0x0111, 0x0111, prLower}, // L& LATIN SMALL LETTER D WITH STROKE + {0x0112, 0x0112, prUpper}, // L& LATIN CAPITAL LETTER E WITH MACRON + {0x0113, 0x0113, prLower}, // L& LATIN SMALL LETTER E WITH MACRON + {0x0114, 0x0114, prUpper}, // L& LATIN CAPITAL LETTER E WITH BREVE + {0x0115, 0x0115, prLower}, // L& LATIN SMALL LETTER E WITH BREVE + {0x0116, 0x0116, prUpper}, // L& LATIN CAPITAL LETTER E WITH DOT ABOVE + {0x0117, 0x0117, prLower}, // L& LATIN SMALL LETTER E WITH DOT ABOVE + {0x0118, 0x0118, prUpper}, // L& LATIN CAPITAL LETTER E WITH OGONEK + {0x0119, 0x0119, prLower}, // L& LATIN SMALL LETTER E WITH OGONEK + {0x011A, 0x011A, prUpper}, // L& LATIN CAPITAL LETTER E WITH CARON + {0x011B, 0x011B, prLower}, // L& LATIN SMALL LETTER E WITH CARON + {0x011C, 0x011C, prUpper}, // L& LATIN CAPITAL LETTER G WITH CIRCUMFLEX + {0x011D, 0x011D, prLower}, // L& LATIN SMALL LETTER G WITH CIRCUMFLEX + {0x011E, 0x011E, prUpper}, // L& LATIN CAPITAL LETTER G WITH BREVE + {0x011F, 0x011F, prLower}, // L& LATIN SMALL LETTER G WITH BREVE + {0x0120, 0x0120, prUpper}, // L& LATIN CAPITAL LETTER G WITH DOT ABOVE + {0x0121, 0x0121, prLower}, // L& LATIN SMALL LETTER G WITH DOT ABOVE + {0x0122, 0x0122, prUpper}, // L& LATIN CAPITAL LETTER G WITH CEDILLA + {0x0123, 0x0123, prLower}, // L& LATIN SMALL LETTER G WITH CEDILLA + {0x0124, 0x0124, prUpper}, // L& LATIN CAPITAL LETTER H WITH CIRCUMFLEX + {0x0125, 0x0125, prLower}, // L& LATIN SMALL LETTER H WITH CIRCUMFLEX + {0x0126, 0x0126, prUpper}, // L& LATIN CAPITAL LETTER H WITH STROKE + {0x0127, 0x0127, prLower}, // L& LATIN SMALL LETTER H WITH STROKE + {0x0128, 0x0128, prUpper}, // L& LATIN CAPITAL LETTER I WITH TILDE + {0x0129, 0x0129, prLower}, // L& LATIN SMALL LETTER I WITH TILDE + {0x012A, 0x012A, prUpper}, // L& LATIN CAPITAL LETTER I WITH MACRON + {0x012B, 0x012B, prLower}, // L& LATIN SMALL LETTER I WITH MACRON + {0x012C, 0x012C, prUpper}, // L& LATIN CAPITAL LETTER I WITH BREVE + {0x012D, 0x012D, prLower}, // L& LATIN SMALL LETTER I WITH BREVE + {0x012E, 0x012E, prUpper}, // L& LATIN CAPITAL LETTER I WITH OGONEK + {0x012F, 0x012F, prLower}, // L& LATIN SMALL LETTER I WITH OGONEK + {0x0130, 0x0130, prUpper}, // L& LATIN CAPITAL LETTER I WITH DOT ABOVE + {0x0131, 0x0131, prLower}, // L& LATIN SMALL LETTER DOTLESS I + {0x0132, 0x0132, prUpper}, // L& LATIN CAPITAL LIGATURE IJ + {0x0133, 0x0133, prLower}, // L& LATIN SMALL LIGATURE IJ + {0x0134, 0x0134, prUpper}, // L& LATIN CAPITAL LETTER J WITH CIRCUMFLEX + {0x0135, 0x0135, prLower}, // L& LATIN SMALL LETTER J WITH CIRCUMFLEX + {0x0136, 0x0136, prUpper}, // L& LATIN CAPITAL LETTER K WITH CEDILLA + {0x0137, 0x0138, prLower}, // L& [2] LATIN SMALL LETTER K WITH CEDILLA..LATIN SMALL LETTER KRA + {0x0139, 0x0139, prUpper}, // L& LATIN CAPITAL LETTER L WITH ACUTE + {0x013A, 0x013A, prLower}, // L& LATIN SMALL LETTER L WITH ACUTE + {0x013B, 0x013B, prUpper}, // L& LATIN CAPITAL LETTER L WITH CEDILLA + {0x013C, 0x013C, prLower}, // L& LATIN SMALL LETTER L WITH CEDILLA + {0x013D, 0x013D, prUpper}, // L& LATIN CAPITAL LETTER L WITH CARON + {0x013E, 0x013E, prLower}, // L& LATIN SMALL LETTER L WITH CARON + {0x013F, 0x013F, prUpper}, // L& LATIN CAPITAL LETTER L WITH MIDDLE DOT + {0x0140, 0x0140, prLower}, // L& LATIN SMALL LETTER L WITH MIDDLE DOT + {0x0141, 0x0141, prUpper}, // L& LATIN CAPITAL LETTER L WITH STROKE + {0x0142, 0x0142, prLower}, // L& LATIN SMALL LETTER L WITH STROKE + {0x0143, 0x0143, prUpper}, // L& LATIN CAPITAL LETTER N WITH ACUTE + {0x0144, 0x0144, prLower}, // L& LATIN SMALL LETTER N WITH ACUTE + {0x0145, 0x0145, prUpper}, // L& LATIN CAPITAL LETTER N WITH CEDILLA + {0x0146, 0x0146, prLower}, // L& LATIN SMALL LETTER N WITH CEDILLA + {0x0147, 0x0147, prUpper}, // L& LATIN CAPITAL LETTER N WITH CARON + {0x0148, 0x0149, prLower}, // L& [2] LATIN SMALL LETTER N WITH CARON..LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + {0x014A, 0x014A, prUpper}, // L& LATIN CAPITAL LETTER ENG + {0x014B, 0x014B, prLower}, // L& LATIN SMALL LETTER ENG + {0x014C, 0x014C, prUpper}, // L& LATIN CAPITAL LETTER O WITH MACRON + {0x014D, 0x014D, prLower}, // L& LATIN SMALL LETTER O WITH MACRON + {0x014E, 0x014E, prUpper}, // L& LATIN CAPITAL LETTER O WITH BREVE + {0x014F, 0x014F, prLower}, // L& LATIN SMALL LETTER O WITH BREVE + {0x0150, 0x0150, prUpper}, // L& LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + {0x0151, 0x0151, prLower}, // L& LATIN SMALL LETTER O WITH DOUBLE ACUTE + {0x0152, 0x0152, prUpper}, // L& LATIN CAPITAL LIGATURE OE + {0x0153, 0x0153, prLower}, // L& LATIN SMALL LIGATURE OE + {0x0154, 0x0154, prUpper}, // L& LATIN CAPITAL LETTER R WITH ACUTE + {0x0155, 0x0155, prLower}, // L& LATIN SMALL LETTER R WITH ACUTE + {0x0156, 0x0156, prUpper}, // L& LATIN CAPITAL LETTER R WITH CEDILLA + {0x0157, 0x0157, prLower}, // L& LATIN SMALL LETTER R WITH CEDILLA + {0x0158, 0x0158, prUpper}, // L& LATIN CAPITAL LETTER R WITH CARON + {0x0159, 0x0159, prLower}, // L& LATIN SMALL LETTER R WITH CARON + {0x015A, 0x015A, prUpper}, // L& LATIN CAPITAL LETTER S WITH ACUTE + {0x015B, 0x015B, prLower}, // L& LATIN SMALL LETTER S WITH ACUTE + {0x015C, 0x015C, prUpper}, // L& LATIN CAPITAL LETTER S WITH CIRCUMFLEX + {0x015D, 0x015D, prLower}, // L& LATIN SMALL LETTER S WITH CIRCUMFLEX + {0x015E, 0x015E, prUpper}, // L& LATIN CAPITAL LETTER S WITH CEDILLA + {0x015F, 0x015F, prLower}, // L& LATIN SMALL LETTER S WITH CEDILLA + {0x0160, 0x0160, prUpper}, // L& LATIN CAPITAL LETTER S WITH CARON + {0x0161, 0x0161, prLower}, // L& LATIN SMALL LETTER S WITH CARON + {0x0162, 0x0162, prUpper}, // L& LATIN CAPITAL LETTER T WITH CEDILLA + {0x0163, 0x0163, prLower}, // L& LATIN SMALL LETTER T WITH CEDILLA + {0x0164, 0x0164, prUpper}, // L& LATIN CAPITAL LETTER T WITH CARON + {0x0165, 0x0165, prLower}, // L& LATIN SMALL LETTER T WITH CARON + {0x0166, 0x0166, prUpper}, // L& LATIN CAPITAL LETTER T WITH STROKE + {0x0167, 0x0167, prLower}, // L& LATIN SMALL LETTER T WITH STROKE + {0x0168, 0x0168, prUpper}, // L& LATIN CAPITAL LETTER U WITH TILDE + {0x0169, 0x0169, prLower}, // L& LATIN SMALL LETTER U WITH TILDE + {0x016A, 0x016A, prUpper}, // L& LATIN CAPITAL LETTER U WITH MACRON + {0x016B, 0x016B, prLower}, // L& LATIN SMALL LETTER U WITH MACRON + {0x016C, 0x016C, prUpper}, // L& LATIN CAPITAL LETTER U WITH BREVE + {0x016D, 0x016D, prLower}, // L& LATIN SMALL LETTER U WITH BREVE + {0x016E, 0x016E, prUpper}, // L& LATIN CAPITAL LETTER U WITH RING ABOVE + {0x016F, 0x016F, prLower}, // L& LATIN SMALL LETTER U WITH RING ABOVE + {0x0170, 0x0170, prUpper}, // L& LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + {0x0171, 0x0171, prLower}, // L& LATIN SMALL LETTER U WITH DOUBLE ACUTE + {0x0172, 0x0172, prUpper}, // L& LATIN CAPITAL LETTER U WITH OGONEK + {0x0173, 0x0173, prLower}, // L& LATIN SMALL LETTER U WITH OGONEK + {0x0174, 0x0174, prUpper}, // L& LATIN CAPITAL LETTER W WITH CIRCUMFLEX + {0x0175, 0x0175, prLower}, // L& LATIN SMALL LETTER W WITH CIRCUMFLEX + {0x0176, 0x0176, prUpper}, // L& LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + {0x0177, 0x0177, prLower}, // L& LATIN SMALL LETTER Y WITH CIRCUMFLEX + {0x0178, 0x0179, prUpper}, // L& [2] LATIN CAPITAL LETTER Y WITH DIAERESIS..LATIN CAPITAL LETTER Z WITH ACUTE + {0x017A, 0x017A, prLower}, // L& LATIN SMALL LETTER Z WITH ACUTE + {0x017B, 0x017B, prUpper}, // L& LATIN CAPITAL LETTER Z WITH DOT ABOVE + {0x017C, 0x017C, prLower}, // L& LATIN SMALL LETTER Z WITH DOT ABOVE + {0x017D, 0x017D, prUpper}, // L& LATIN CAPITAL LETTER Z WITH CARON + {0x017E, 0x0180, prLower}, // L& [3] LATIN SMALL LETTER Z WITH CARON..LATIN SMALL LETTER B WITH STROKE + {0x0181, 0x0182, prUpper}, // L& [2] LATIN CAPITAL LETTER B WITH HOOK..LATIN CAPITAL LETTER B WITH TOPBAR + {0x0183, 0x0183, prLower}, // L& LATIN SMALL LETTER B WITH TOPBAR + {0x0184, 0x0184, prUpper}, // L& LATIN CAPITAL LETTER TONE SIX + {0x0185, 0x0185, prLower}, // L& LATIN SMALL LETTER TONE SIX + {0x0186, 0x0187, prUpper}, // L& [2] LATIN CAPITAL LETTER OPEN O..LATIN CAPITAL LETTER C WITH HOOK + {0x0188, 0x0188, prLower}, // L& LATIN SMALL LETTER C WITH HOOK + {0x0189, 0x018B, prUpper}, // L& [3] LATIN CAPITAL LETTER AFRICAN D..LATIN CAPITAL LETTER D WITH TOPBAR + {0x018C, 0x018D, prLower}, // L& [2] LATIN SMALL LETTER D WITH TOPBAR..LATIN SMALL LETTER TURNED DELTA + {0x018E, 0x0191, prUpper}, // L& [4] LATIN CAPITAL LETTER REVERSED E..LATIN CAPITAL LETTER F WITH HOOK + {0x0192, 0x0192, prLower}, // L& LATIN SMALL LETTER F WITH HOOK + {0x0193, 0x0194, prUpper}, // L& [2] LATIN CAPITAL LETTER G WITH HOOK..LATIN CAPITAL LETTER GAMMA + {0x0195, 0x0195, prLower}, // L& LATIN SMALL LETTER HV + {0x0196, 0x0198, prUpper}, // L& [3] LATIN CAPITAL LETTER IOTA..LATIN CAPITAL LETTER K WITH HOOK + {0x0199, 0x019B, prLower}, // L& [3] LATIN SMALL LETTER K WITH HOOK..LATIN SMALL LETTER LAMBDA WITH STROKE + {0x019C, 0x019D, prUpper}, // L& [2] LATIN CAPITAL LETTER TURNED M..LATIN CAPITAL LETTER N WITH LEFT HOOK + {0x019E, 0x019E, prLower}, // L& LATIN SMALL LETTER N WITH LONG RIGHT LEG + {0x019F, 0x01A0, prUpper}, // L& [2] LATIN CAPITAL LETTER O WITH MIDDLE TILDE..LATIN CAPITAL LETTER O WITH HORN + {0x01A1, 0x01A1, prLower}, // L& LATIN SMALL LETTER O WITH HORN + {0x01A2, 0x01A2, prUpper}, // L& LATIN CAPITAL LETTER OI + {0x01A3, 0x01A3, prLower}, // L& LATIN SMALL LETTER OI + {0x01A4, 0x01A4, prUpper}, // L& LATIN CAPITAL LETTER P WITH HOOK + {0x01A5, 0x01A5, prLower}, // L& LATIN SMALL LETTER P WITH HOOK + {0x01A6, 0x01A7, prUpper}, // L& [2] LATIN LETTER YR..LATIN CAPITAL LETTER TONE TWO + {0x01A8, 0x01A8, prLower}, // L& LATIN SMALL LETTER TONE TWO + {0x01A9, 0x01A9, prUpper}, // L& LATIN CAPITAL LETTER ESH + {0x01AA, 0x01AB, prLower}, // L& [2] LATIN LETTER REVERSED ESH LOOP..LATIN SMALL LETTER T WITH PALATAL HOOK + {0x01AC, 0x01AC, prUpper}, // L& LATIN CAPITAL LETTER T WITH HOOK + {0x01AD, 0x01AD, prLower}, // L& LATIN SMALL LETTER T WITH HOOK + {0x01AE, 0x01AF, prUpper}, // L& [2] LATIN CAPITAL LETTER T WITH RETROFLEX HOOK..LATIN CAPITAL LETTER U WITH HORN + {0x01B0, 0x01B0, prLower}, // L& LATIN SMALL LETTER U WITH HORN + {0x01B1, 0x01B3, prUpper}, // L& [3] LATIN CAPITAL LETTER UPSILON..LATIN CAPITAL LETTER Y WITH HOOK + {0x01B4, 0x01B4, prLower}, // L& LATIN SMALL LETTER Y WITH HOOK + {0x01B5, 0x01B5, prUpper}, // L& LATIN CAPITAL LETTER Z WITH STROKE + {0x01B6, 0x01B6, prLower}, // L& LATIN SMALL LETTER Z WITH STROKE + {0x01B7, 0x01B8, prUpper}, // L& [2] LATIN CAPITAL LETTER EZH..LATIN CAPITAL LETTER EZH REVERSED + {0x01B9, 0x01BA, prLower}, // L& [2] LATIN SMALL LETTER EZH REVERSED..LATIN SMALL LETTER EZH WITH TAIL + {0x01BB, 0x01BB, prOLetter}, // Lo LATIN LETTER TWO WITH STROKE + {0x01BC, 0x01BC, prUpper}, // L& LATIN CAPITAL LETTER TONE FIVE + {0x01BD, 0x01BF, prLower}, // L& [3] LATIN SMALL LETTER TONE FIVE..LATIN LETTER WYNN + {0x01C0, 0x01C3, prOLetter}, // Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK + {0x01C4, 0x01C5, prUpper}, // L& [2] LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON + {0x01C6, 0x01C6, prLower}, // L& LATIN SMALL LETTER DZ WITH CARON + {0x01C7, 0x01C8, prUpper}, // L& [2] LATIN CAPITAL LETTER LJ..LATIN CAPITAL LETTER L WITH SMALL LETTER J + {0x01C9, 0x01C9, prLower}, // L& LATIN SMALL LETTER LJ + {0x01CA, 0x01CB, prUpper}, // L& [2] LATIN CAPITAL LETTER NJ..LATIN CAPITAL LETTER N WITH SMALL LETTER J + {0x01CC, 0x01CC, prLower}, // L& LATIN SMALL LETTER NJ + {0x01CD, 0x01CD, prUpper}, // L& LATIN CAPITAL LETTER A WITH CARON + {0x01CE, 0x01CE, prLower}, // L& LATIN SMALL LETTER A WITH CARON + {0x01CF, 0x01CF, prUpper}, // L& LATIN CAPITAL LETTER I WITH CARON + {0x01D0, 0x01D0, prLower}, // L& LATIN SMALL LETTER I WITH CARON + {0x01D1, 0x01D1, prUpper}, // L& LATIN CAPITAL LETTER O WITH CARON + {0x01D2, 0x01D2, prLower}, // L& LATIN SMALL LETTER O WITH CARON + {0x01D3, 0x01D3, prUpper}, // L& LATIN CAPITAL LETTER U WITH CARON + {0x01D4, 0x01D4, prLower}, // L& LATIN SMALL LETTER U WITH CARON + {0x01D5, 0x01D5, prUpper}, // L& LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON + {0x01D6, 0x01D6, prLower}, // L& LATIN SMALL LETTER U WITH DIAERESIS AND MACRON + {0x01D7, 0x01D7, prUpper}, // L& LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE + {0x01D8, 0x01D8, prLower}, // L& LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE + {0x01D9, 0x01D9, prUpper}, // L& LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON + {0x01DA, 0x01DA, prLower}, // L& LATIN SMALL LETTER U WITH DIAERESIS AND CARON + {0x01DB, 0x01DB, prUpper}, // L& LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE + {0x01DC, 0x01DD, prLower}, // L& [2] LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE..LATIN SMALL LETTER TURNED E + {0x01DE, 0x01DE, prUpper}, // L& LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON + {0x01DF, 0x01DF, prLower}, // L& LATIN SMALL LETTER A WITH DIAERESIS AND MACRON + {0x01E0, 0x01E0, prUpper}, // L& LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON + {0x01E1, 0x01E1, prLower}, // L& LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON + {0x01E2, 0x01E2, prUpper}, // L& LATIN CAPITAL LETTER AE WITH MACRON + {0x01E3, 0x01E3, prLower}, // L& LATIN SMALL LETTER AE WITH MACRON + {0x01E4, 0x01E4, prUpper}, // L& LATIN CAPITAL LETTER G WITH STROKE + {0x01E5, 0x01E5, prLower}, // L& LATIN SMALL LETTER G WITH STROKE + {0x01E6, 0x01E6, prUpper}, // L& LATIN CAPITAL LETTER G WITH CARON + {0x01E7, 0x01E7, prLower}, // L& LATIN SMALL LETTER G WITH CARON + {0x01E8, 0x01E8, prUpper}, // L& LATIN CAPITAL LETTER K WITH CARON + {0x01E9, 0x01E9, prLower}, // L& LATIN SMALL LETTER K WITH CARON + {0x01EA, 0x01EA, prUpper}, // L& LATIN CAPITAL LETTER O WITH OGONEK + {0x01EB, 0x01EB, prLower}, // L& LATIN SMALL LETTER O WITH OGONEK + {0x01EC, 0x01EC, prUpper}, // L& LATIN CAPITAL LETTER O WITH OGONEK AND MACRON + {0x01ED, 0x01ED, prLower}, // L& LATIN SMALL LETTER O WITH OGONEK AND MACRON + {0x01EE, 0x01EE, prUpper}, // L& LATIN CAPITAL LETTER EZH WITH CARON + {0x01EF, 0x01F0, prLower}, // L& [2] LATIN SMALL LETTER EZH WITH CARON..LATIN SMALL LETTER J WITH CARON + {0x01F1, 0x01F2, prUpper}, // L& [2] LATIN CAPITAL LETTER DZ..LATIN CAPITAL LETTER D WITH SMALL LETTER Z + {0x01F3, 0x01F3, prLower}, // L& LATIN SMALL LETTER DZ + {0x01F4, 0x01F4, prUpper}, // L& LATIN CAPITAL LETTER G WITH ACUTE + {0x01F5, 0x01F5, prLower}, // L& LATIN SMALL LETTER G WITH ACUTE + {0x01F6, 0x01F8, prUpper}, // L& [3] LATIN CAPITAL LETTER HWAIR..LATIN CAPITAL LETTER N WITH GRAVE + {0x01F9, 0x01F9, prLower}, // L& LATIN SMALL LETTER N WITH GRAVE + {0x01FA, 0x01FA, prUpper}, // L& LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE + {0x01FB, 0x01FB, prLower}, // L& LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE + {0x01FC, 0x01FC, prUpper}, // L& LATIN CAPITAL LETTER AE WITH ACUTE + {0x01FD, 0x01FD, prLower}, // L& LATIN SMALL LETTER AE WITH ACUTE + {0x01FE, 0x01FE, prUpper}, // L& LATIN CAPITAL LETTER O WITH STROKE AND ACUTE + {0x01FF, 0x01FF, prLower}, // L& LATIN SMALL LETTER O WITH STROKE AND ACUTE + {0x0200, 0x0200, prUpper}, // L& LATIN CAPITAL LETTER A WITH DOUBLE GRAVE + {0x0201, 0x0201, prLower}, // L& LATIN SMALL LETTER A WITH DOUBLE GRAVE + {0x0202, 0x0202, prUpper}, // L& LATIN CAPITAL LETTER A WITH INVERTED BREVE + {0x0203, 0x0203, prLower}, // L& LATIN SMALL LETTER A WITH INVERTED BREVE + {0x0204, 0x0204, prUpper}, // L& LATIN CAPITAL LETTER E WITH DOUBLE GRAVE + {0x0205, 0x0205, prLower}, // L& LATIN SMALL LETTER E WITH DOUBLE GRAVE + {0x0206, 0x0206, prUpper}, // L& LATIN CAPITAL LETTER E WITH INVERTED BREVE + {0x0207, 0x0207, prLower}, // L& LATIN SMALL LETTER E WITH INVERTED BREVE + {0x0208, 0x0208, prUpper}, // L& LATIN CAPITAL LETTER I WITH DOUBLE GRAVE + {0x0209, 0x0209, prLower}, // L& LATIN SMALL LETTER I WITH DOUBLE GRAVE + {0x020A, 0x020A, prUpper}, // L& LATIN CAPITAL LETTER I WITH INVERTED BREVE + {0x020B, 0x020B, prLower}, // L& LATIN SMALL LETTER I WITH INVERTED BREVE + {0x020C, 0x020C, prUpper}, // L& LATIN CAPITAL LETTER O WITH DOUBLE GRAVE + {0x020D, 0x020D, prLower}, // L& LATIN SMALL LETTER O WITH DOUBLE GRAVE + {0x020E, 0x020E, prUpper}, // L& LATIN CAPITAL LETTER O WITH INVERTED BREVE + {0x020F, 0x020F, prLower}, // L& LATIN SMALL LETTER O WITH INVERTED BREVE + {0x0210, 0x0210, prUpper}, // L& LATIN CAPITAL LETTER R WITH DOUBLE GRAVE + {0x0211, 0x0211, prLower}, // L& LATIN SMALL LETTER R WITH DOUBLE GRAVE + {0x0212, 0x0212, prUpper}, // L& LATIN CAPITAL LETTER R WITH INVERTED BREVE + {0x0213, 0x0213, prLower}, // L& LATIN SMALL LETTER R WITH INVERTED BREVE + {0x0214, 0x0214, prUpper}, // L& LATIN CAPITAL LETTER U WITH DOUBLE GRAVE + {0x0215, 0x0215, prLower}, // L& LATIN SMALL LETTER U WITH DOUBLE GRAVE + {0x0216, 0x0216, prUpper}, // L& LATIN CAPITAL LETTER U WITH INVERTED BREVE + {0x0217, 0x0217, prLower}, // L& LATIN SMALL LETTER U WITH INVERTED BREVE + {0x0218, 0x0218, prUpper}, // L& LATIN CAPITAL LETTER S WITH COMMA BELOW + {0x0219, 0x0219, prLower}, // L& LATIN SMALL LETTER S WITH COMMA BELOW + {0x021A, 0x021A, prUpper}, // L& LATIN CAPITAL LETTER T WITH COMMA BELOW + {0x021B, 0x021B, prLower}, // L& LATIN SMALL LETTER T WITH COMMA BELOW + {0x021C, 0x021C, prUpper}, // L& LATIN CAPITAL LETTER YOGH + {0x021D, 0x021D, prLower}, // L& LATIN SMALL LETTER YOGH + {0x021E, 0x021E, prUpper}, // L& LATIN CAPITAL LETTER H WITH CARON + {0x021F, 0x021F, prLower}, // L& LATIN SMALL LETTER H WITH CARON + {0x0220, 0x0220, prUpper}, // L& LATIN CAPITAL LETTER N WITH LONG RIGHT LEG + {0x0221, 0x0221, prLower}, // L& LATIN SMALL LETTER D WITH CURL + {0x0222, 0x0222, prUpper}, // L& LATIN CAPITAL LETTER OU + {0x0223, 0x0223, prLower}, // L& LATIN SMALL LETTER OU + {0x0224, 0x0224, prUpper}, // L& LATIN CAPITAL LETTER Z WITH HOOK + {0x0225, 0x0225, prLower}, // L& LATIN SMALL LETTER Z WITH HOOK + {0x0226, 0x0226, prUpper}, // L& LATIN CAPITAL LETTER A WITH DOT ABOVE + {0x0227, 0x0227, prLower}, // L& LATIN SMALL LETTER A WITH DOT ABOVE + {0x0228, 0x0228, prUpper}, // L& LATIN CAPITAL LETTER E WITH CEDILLA + {0x0229, 0x0229, prLower}, // L& LATIN SMALL LETTER E WITH CEDILLA + {0x022A, 0x022A, prUpper}, // L& LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON + {0x022B, 0x022B, prLower}, // L& LATIN SMALL LETTER O WITH DIAERESIS AND MACRON + {0x022C, 0x022C, prUpper}, // L& LATIN CAPITAL LETTER O WITH TILDE AND MACRON + {0x022D, 0x022D, prLower}, // L& LATIN SMALL LETTER O WITH TILDE AND MACRON + {0x022E, 0x022E, prUpper}, // L& LATIN CAPITAL LETTER O WITH DOT ABOVE + {0x022F, 0x022F, prLower}, // L& LATIN SMALL LETTER O WITH DOT ABOVE + {0x0230, 0x0230, prUpper}, // L& LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON + {0x0231, 0x0231, prLower}, // L& LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON + {0x0232, 0x0232, prUpper}, // L& LATIN CAPITAL LETTER Y WITH MACRON + {0x0233, 0x0239, prLower}, // L& [7] LATIN SMALL LETTER Y WITH MACRON..LATIN SMALL LETTER QP DIGRAPH + {0x023A, 0x023B, prUpper}, // L& [2] LATIN CAPITAL LETTER A WITH STROKE..LATIN CAPITAL LETTER C WITH STROKE + {0x023C, 0x023C, prLower}, // L& LATIN SMALL LETTER C WITH STROKE + {0x023D, 0x023E, prUpper}, // L& [2] LATIN CAPITAL LETTER L WITH BAR..LATIN CAPITAL LETTER T WITH DIAGONAL STROKE + {0x023F, 0x0240, prLower}, // L& [2] LATIN SMALL LETTER S WITH SWASH TAIL..LATIN SMALL LETTER Z WITH SWASH TAIL + {0x0241, 0x0241, prUpper}, // L& LATIN CAPITAL LETTER GLOTTAL STOP + {0x0242, 0x0242, prLower}, // L& LATIN SMALL LETTER GLOTTAL STOP + {0x0243, 0x0246, prUpper}, // L& [4] LATIN CAPITAL LETTER B WITH STROKE..LATIN CAPITAL LETTER E WITH STROKE + {0x0247, 0x0247, prLower}, // L& LATIN SMALL LETTER E WITH STROKE + {0x0248, 0x0248, prUpper}, // L& LATIN CAPITAL LETTER J WITH STROKE + {0x0249, 0x0249, prLower}, // L& LATIN SMALL LETTER J WITH STROKE + {0x024A, 0x024A, prUpper}, // L& LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL + {0x024B, 0x024B, prLower}, // L& LATIN SMALL LETTER Q WITH HOOK TAIL + {0x024C, 0x024C, prUpper}, // L& LATIN CAPITAL LETTER R WITH STROKE + {0x024D, 0x024D, prLower}, // L& LATIN SMALL LETTER R WITH STROKE + {0x024E, 0x024E, prUpper}, // L& LATIN CAPITAL LETTER Y WITH STROKE + {0x024F, 0x0293, prLower}, // L& [69] LATIN SMALL LETTER Y WITH STROKE..LATIN SMALL LETTER EZH WITH CURL + {0x0294, 0x0294, prOLetter}, // Lo LATIN LETTER GLOTTAL STOP + {0x0295, 0x02AF, prLower}, // L& [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL + {0x02B0, 0x02B8, prLower}, // Lm [9] MODIFIER LETTER SMALL H..MODIFIER LETTER SMALL Y + {0x02B9, 0x02BF, prOLetter}, // Lm [7] MODIFIER LETTER PRIME..MODIFIER LETTER LEFT HALF RING + {0x02C0, 0x02C1, prLower}, // Lm [2] MODIFIER LETTER GLOTTAL STOP..MODIFIER LETTER REVERSED GLOTTAL STOP + {0x02C6, 0x02D1, prOLetter}, // Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON + {0x02E0, 0x02E4, prLower}, // Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP + {0x02EC, 0x02EC, prOLetter}, // Lm MODIFIER LETTER VOICING + {0x02EE, 0x02EE, prOLetter}, // Lm MODIFIER LETTER DOUBLE APOSTROPHE + {0x0300, 0x036F, prExtend}, // Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X + {0x0370, 0x0370, prUpper}, // L& GREEK CAPITAL LETTER HETA + {0x0371, 0x0371, prLower}, // L& GREEK SMALL LETTER HETA + {0x0372, 0x0372, prUpper}, // L& GREEK CAPITAL LETTER ARCHAIC SAMPI + {0x0373, 0x0373, prLower}, // L& GREEK SMALL LETTER ARCHAIC SAMPI + {0x0374, 0x0374, prOLetter}, // Lm GREEK NUMERAL SIGN + {0x0376, 0x0376, prUpper}, // L& GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA + {0x0377, 0x0377, prLower}, // L& GREEK SMALL LETTER PAMPHYLIAN DIGAMMA + {0x037A, 0x037A, prLower}, // Lm GREEK YPOGEGRAMMENI + {0x037B, 0x037D, prLower}, // L& [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL + {0x037F, 0x037F, prUpper}, // L& GREEK CAPITAL LETTER YOT + {0x0386, 0x0386, prUpper}, // L& GREEK CAPITAL LETTER ALPHA WITH TONOS + {0x0388, 0x038A, prUpper}, // L& [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS + {0x038C, 0x038C, prUpper}, // L& GREEK CAPITAL LETTER OMICRON WITH TONOS + {0x038E, 0x038F, prUpper}, // L& [2] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER OMEGA WITH TONOS + {0x0390, 0x0390, prLower}, // L& GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + {0x0391, 0x03A1, prUpper}, // L& [17] GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO + {0x03A3, 0x03AB, prUpper}, // L& [9] GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + {0x03AC, 0x03CE, prLower}, // L& [35] GREEK SMALL LETTER ALPHA WITH TONOS..GREEK SMALL LETTER OMEGA WITH TONOS + {0x03CF, 0x03CF, prUpper}, // L& GREEK CAPITAL KAI SYMBOL + {0x03D0, 0x03D1, prLower}, // L& [2] GREEK BETA SYMBOL..GREEK THETA SYMBOL + {0x03D2, 0x03D4, prUpper}, // L& [3] GREEK UPSILON WITH HOOK SYMBOL..GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL + {0x03D5, 0x03D7, prLower}, // L& [3] GREEK PHI SYMBOL..GREEK KAI SYMBOL + {0x03D8, 0x03D8, prUpper}, // L& GREEK LETTER ARCHAIC KOPPA + {0x03D9, 0x03D9, prLower}, // L& GREEK SMALL LETTER ARCHAIC KOPPA + {0x03DA, 0x03DA, prUpper}, // L& GREEK LETTER STIGMA + {0x03DB, 0x03DB, prLower}, // L& GREEK SMALL LETTER STIGMA + {0x03DC, 0x03DC, prUpper}, // L& GREEK LETTER DIGAMMA + {0x03DD, 0x03DD, prLower}, // L& GREEK SMALL LETTER DIGAMMA + {0x03DE, 0x03DE, prUpper}, // L& GREEK LETTER KOPPA + {0x03DF, 0x03DF, prLower}, // L& GREEK SMALL LETTER KOPPA + {0x03E0, 0x03E0, prUpper}, // L& GREEK LETTER SAMPI + {0x03E1, 0x03E1, prLower}, // L& GREEK SMALL LETTER SAMPI + {0x03E2, 0x03E2, prUpper}, // L& COPTIC CAPITAL LETTER SHEI + {0x03E3, 0x03E3, prLower}, // L& COPTIC SMALL LETTER SHEI + {0x03E4, 0x03E4, prUpper}, // L& COPTIC CAPITAL LETTER FEI + {0x03E5, 0x03E5, prLower}, // L& COPTIC SMALL LETTER FEI + {0x03E6, 0x03E6, prUpper}, // L& COPTIC CAPITAL LETTER KHEI + {0x03E7, 0x03E7, prLower}, // L& COPTIC SMALL LETTER KHEI + {0x03E8, 0x03E8, prUpper}, // L& COPTIC CAPITAL LETTER HORI + {0x03E9, 0x03E9, prLower}, // L& COPTIC SMALL LETTER HORI + {0x03EA, 0x03EA, prUpper}, // L& COPTIC CAPITAL LETTER GANGIA + {0x03EB, 0x03EB, prLower}, // L& COPTIC SMALL LETTER GANGIA + {0x03EC, 0x03EC, prUpper}, // L& COPTIC CAPITAL LETTER SHIMA + {0x03ED, 0x03ED, prLower}, // L& COPTIC SMALL LETTER SHIMA + {0x03EE, 0x03EE, prUpper}, // L& COPTIC CAPITAL LETTER DEI + {0x03EF, 0x03F3, prLower}, // L& [5] COPTIC SMALL LETTER DEI..GREEK LETTER YOT + {0x03F4, 0x03F4, prUpper}, // L& GREEK CAPITAL THETA SYMBOL + {0x03F5, 0x03F5, prLower}, // L& GREEK LUNATE EPSILON SYMBOL + {0x03F7, 0x03F7, prUpper}, // L& GREEK CAPITAL LETTER SHO + {0x03F8, 0x03F8, prLower}, // L& GREEK SMALL LETTER SHO + {0x03F9, 0x03FA, prUpper}, // L& [2] GREEK CAPITAL LUNATE SIGMA SYMBOL..GREEK CAPITAL LETTER SAN + {0x03FB, 0x03FC, prLower}, // L& [2] GREEK SMALL LETTER SAN..GREEK RHO WITH STROKE SYMBOL + {0x03FD, 0x042F, prUpper}, // L& [51] GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL..CYRILLIC CAPITAL LETTER YA + {0x0430, 0x045F, prLower}, // L& [48] CYRILLIC SMALL LETTER A..CYRILLIC SMALL LETTER DZHE + {0x0460, 0x0460, prUpper}, // L& CYRILLIC CAPITAL LETTER OMEGA + {0x0461, 0x0461, prLower}, // L& CYRILLIC SMALL LETTER OMEGA + {0x0462, 0x0462, prUpper}, // L& CYRILLIC CAPITAL LETTER YAT + {0x0463, 0x0463, prLower}, // L& CYRILLIC SMALL LETTER YAT + {0x0464, 0x0464, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTIFIED E + {0x0465, 0x0465, prLower}, // L& CYRILLIC SMALL LETTER IOTIFIED E + {0x0466, 0x0466, prUpper}, // L& CYRILLIC CAPITAL LETTER LITTLE YUS + {0x0467, 0x0467, prLower}, // L& CYRILLIC SMALL LETTER LITTLE YUS + {0x0468, 0x0468, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS + {0x0469, 0x0469, prLower}, // L& CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS + {0x046A, 0x046A, prUpper}, // L& CYRILLIC CAPITAL LETTER BIG YUS + {0x046B, 0x046B, prLower}, // L& CYRILLIC SMALL LETTER BIG YUS + {0x046C, 0x046C, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS + {0x046D, 0x046D, prLower}, // L& CYRILLIC SMALL LETTER IOTIFIED BIG YUS + {0x046E, 0x046E, prUpper}, // L& CYRILLIC CAPITAL LETTER KSI + {0x046F, 0x046F, prLower}, // L& CYRILLIC SMALL LETTER KSI + {0x0470, 0x0470, prUpper}, // L& CYRILLIC CAPITAL LETTER PSI + {0x0471, 0x0471, prLower}, // L& CYRILLIC SMALL LETTER PSI + {0x0472, 0x0472, prUpper}, // L& CYRILLIC CAPITAL LETTER FITA + {0x0473, 0x0473, prLower}, // L& CYRILLIC SMALL LETTER FITA + {0x0474, 0x0474, prUpper}, // L& CYRILLIC CAPITAL LETTER IZHITSA + {0x0475, 0x0475, prLower}, // L& CYRILLIC SMALL LETTER IZHITSA + {0x0476, 0x0476, prUpper}, // L& CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT + {0x0477, 0x0477, prLower}, // L& CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT + {0x0478, 0x0478, prUpper}, // L& CYRILLIC CAPITAL LETTER UK + {0x0479, 0x0479, prLower}, // L& CYRILLIC SMALL LETTER UK + {0x047A, 0x047A, prUpper}, // L& CYRILLIC CAPITAL LETTER ROUND OMEGA + {0x047B, 0x047B, prLower}, // L& CYRILLIC SMALL LETTER ROUND OMEGA + {0x047C, 0x047C, prUpper}, // L& CYRILLIC CAPITAL LETTER OMEGA WITH TITLO + {0x047D, 0x047D, prLower}, // L& CYRILLIC SMALL LETTER OMEGA WITH TITLO + {0x047E, 0x047E, prUpper}, // L& CYRILLIC CAPITAL LETTER OT + {0x047F, 0x047F, prLower}, // L& CYRILLIC SMALL LETTER OT + {0x0480, 0x0480, prUpper}, // L& CYRILLIC CAPITAL LETTER KOPPA + {0x0481, 0x0481, prLower}, // L& CYRILLIC SMALL LETTER KOPPA + {0x0483, 0x0487, prExtend}, // Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE + {0x0488, 0x0489, prExtend}, // Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN + {0x048A, 0x048A, prUpper}, // L& CYRILLIC CAPITAL LETTER SHORT I WITH TAIL + {0x048B, 0x048B, prLower}, // L& CYRILLIC SMALL LETTER SHORT I WITH TAIL + {0x048C, 0x048C, prUpper}, // L& CYRILLIC CAPITAL LETTER SEMISOFT SIGN + {0x048D, 0x048D, prLower}, // L& CYRILLIC SMALL LETTER SEMISOFT SIGN + {0x048E, 0x048E, prUpper}, // L& CYRILLIC CAPITAL LETTER ER WITH TICK + {0x048F, 0x048F, prLower}, // L& CYRILLIC SMALL LETTER ER WITH TICK + {0x0490, 0x0490, prUpper}, // L& CYRILLIC CAPITAL LETTER GHE WITH UPTURN + {0x0491, 0x0491, prLower}, // L& CYRILLIC SMALL LETTER GHE WITH UPTURN + {0x0492, 0x0492, prUpper}, // L& CYRILLIC CAPITAL LETTER GHE WITH STROKE + {0x0493, 0x0493, prLower}, // L& CYRILLIC SMALL LETTER GHE WITH STROKE + {0x0494, 0x0494, prUpper}, // L& CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK + {0x0495, 0x0495, prLower}, // L& CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK + {0x0496, 0x0496, prUpper}, // L& CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER + {0x0497, 0x0497, prLower}, // L& CYRILLIC SMALL LETTER ZHE WITH DESCENDER + {0x0498, 0x0498, prUpper}, // L& CYRILLIC CAPITAL LETTER ZE WITH DESCENDER + {0x0499, 0x0499, prLower}, // L& CYRILLIC SMALL LETTER ZE WITH DESCENDER + {0x049A, 0x049A, prUpper}, // L& CYRILLIC CAPITAL LETTER KA WITH DESCENDER + {0x049B, 0x049B, prLower}, // L& CYRILLIC SMALL LETTER KA WITH DESCENDER + {0x049C, 0x049C, prUpper}, // L& CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE + {0x049D, 0x049D, prLower}, // L& CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE + {0x049E, 0x049E, prUpper}, // L& CYRILLIC CAPITAL LETTER KA WITH STROKE + {0x049F, 0x049F, prLower}, // L& CYRILLIC SMALL LETTER KA WITH STROKE + {0x04A0, 0x04A0, prUpper}, // L& CYRILLIC CAPITAL LETTER BASHKIR KA + {0x04A1, 0x04A1, prLower}, // L& CYRILLIC SMALL LETTER BASHKIR KA + {0x04A2, 0x04A2, prUpper}, // L& CYRILLIC CAPITAL LETTER EN WITH DESCENDER + {0x04A3, 0x04A3, prLower}, // L& CYRILLIC SMALL LETTER EN WITH DESCENDER + {0x04A4, 0x04A4, prUpper}, // L& CYRILLIC CAPITAL LIGATURE EN GHE + {0x04A5, 0x04A5, prLower}, // L& CYRILLIC SMALL LIGATURE EN GHE + {0x04A6, 0x04A6, prUpper}, // L& CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK + {0x04A7, 0x04A7, prLower}, // L& CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK + {0x04A8, 0x04A8, prUpper}, // L& CYRILLIC CAPITAL LETTER ABKHASIAN HA + {0x04A9, 0x04A9, prLower}, // L& CYRILLIC SMALL LETTER ABKHASIAN HA + {0x04AA, 0x04AA, prUpper}, // L& CYRILLIC CAPITAL LETTER ES WITH DESCENDER + {0x04AB, 0x04AB, prLower}, // L& CYRILLIC SMALL LETTER ES WITH DESCENDER + {0x04AC, 0x04AC, prUpper}, // L& CYRILLIC CAPITAL LETTER TE WITH DESCENDER + {0x04AD, 0x04AD, prLower}, // L& CYRILLIC SMALL LETTER TE WITH DESCENDER + {0x04AE, 0x04AE, prUpper}, // L& CYRILLIC CAPITAL LETTER STRAIGHT U + {0x04AF, 0x04AF, prLower}, // L& CYRILLIC SMALL LETTER STRAIGHT U + {0x04B0, 0x04B0, prUpper}, // L& CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE + {0x04B1, 0x04B1, prLower}, // L& CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE + {0x04B2, 0x04B2, prUpper}, // L& CYRILLIC CAPITAL LETTER HA WITH DESCENDER + {0x04B3, 0x04B3, prLower}, // L& CYRILLIC SMALL LETTER HA WITH DESCENDER + {0x04B4, 0x04B4, prUpper}, // L& CYRILLIC CAPITAL LIGATURE TE TSE + {0x04B5, 0x04B5, prLower}, // L& CYRILLIC SMALL LIGATURE TE TSE + {0x04B6, 0x04B6, prUpper}, // L& CYRILLIC CAPITAL LETTER CHE WITH DESCENDER + {0x04B7, 0x04B7, prLower}, // L& CYRILLIC SMALL LETTER CHE WITH DESCENDER + {0x04B8, 0x04B8, prUpper}, // L& CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE + {0x04B9, 0x04B9, prLower}, // L& CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE + {0x04BA, 0x04BA, prUpper}, // L& CYRILLIC CAPITAL LETTER SHHA + {0x04BB, 0x04BB, prLower}, // L& CYRILLIC SMALL LETTER SHHA + {0x04BC, 0x04BC, prUpper}, // L& CYRILLIC CAPITAL LETTER ABKHASIAN CHE + {0x04BD, 0x04BD, prLower}, // L& CYRILLIC SMALL LETTER ABKHASIAN CHE + {0x04BE, 0x04BE, prUpper}, // L& CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER + {0x04BF, 0x04BF, prLower}, // L& CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER + {0x04C0, 0x04C1, prUpper}, // L& [2] CYRILLIC LETTER PALOCHKA..CYRILLIC CAPITAL LETTER ZHE WITH BREVE + {0x04C2, 0x04C2, prLower}, // L& CYRILLIC SMALL LETTER ZHE WITH BREVE + {0x04C3, 0x04C3, prUpper}, // L& CYRILLIC CAPITAL LETTER KA WITH HOOK + {0x04C4, 0x04C4, prLower}, // L& CYRILLIC SMALL LETTER KA WITH HOOK + {0x04C5, 0x04C5, prUpper}, // L& CYRILLIC CAPITAL LETTER EL WITH TAIL + {0x04C6, 0x04C6, prLower}, // L& CYRILLIC SMALL LETTER EL WITH TAIL + {0x04C7, 0x04C7, prUpper}, // L& CYRILLIC CAPITAL LETTER EN WITH HOOK + {0x04C8, 0x04C8, prLower}, // L& CYRILLIC SMALL LETTER EN WITH HOOK + {0x04C9, 0x04C9, prUpper}, // L& CYRILLIC CAPITAL LETTER EN WITH TAIL + {0x04CA, 0x04CA, prLower}, // L& CYRILLIC SMALL LETTER EN WITH TAIL + {0x04CB, 0x04CB, prUpper}, // L& CYRILLIC CAPITAL LETTER KHAKASSIAN CHE + {0x04CC, 0x04CC, prLower}, // L& CYRILLIC SMALL LETTER KHAKASSIAN CHE + {0x04CD, 0x04CD, prUpper}, // L& CYRILLIC CAPITAL LETTER EM WITH TAIL + {0x04CE, 0x04CF, prLower}, // L& [2] CYRILLIC SMALL LETTER EM WITH TAIL..CYRILLIC SMALL LETTER PALOCHKA + {0x04D0, 0x04D0, prUpper}, // L& CYRILLIC CAPITAL LETTER A WITH BREVE + {0x04D1, 0x04D1, prLower}, // L& CYRILLIC SMALL LETTER A WITH BREVE + {0x04D2, 0x04D2, prUpper}, // L& CYRILLIC CAPITAL LETTER A WITH DIAERESIS + {0x04D3, 0x04D3, prLower}, // L& CYRILLIC SMALL LETTER A WITH DIAERESIS + {0x04D4, 0x04D4, prUpper}, // L& CYRILLIC CAPITAL LIGATURE A IE + {0x04D5, 0x04D5, prLower}, // L& CYRILLIC SMALL LIGATURE A IE + {0x04D6, 0x04D6, prUpper}, // L& CYRILLIC CAPITAL LETTER IE WITH BREVE + {0x04D7, 0x04D7, prLower}, // L& CYRILLIC SMALL LETTER IE WITH BREVE + {0x04D8, 0x04D8, prUpper}, // L& CYRILLIC CAPITAL LETTER SCHWA + {0x04D9, 0x04D9, prLower}, // L& CYRILLIC SMALL LETTER SCHWA + {0x04DA, 0x04DA, prUpper}, // L& CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS + {0x04DB, 0x04DB, prLower}, // L& CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS + {0x04DC, 0x04DC, prUpper}, // L& CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS + {0x04DD, 0x04DD, prLower}, // L& CYRILLIC SMALL LETTER ZHE WITH DIAERESIS + {0x04DE, 0x04DE, prUpper}, // L& CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS + {0x04DF, 0x04DF, prLower}, // L& CYRILLIC SMALL LETTER ZE WITH DIAERESIS + {0x04E0, 0x04E0, prUpper}, // L& CYRILLIC CAPITAL LETTER ABKHASIAN DZE + {0x04E1, 0x04E1, prLower}, // L& CYRILLIC SMALL LETTER ABKHASIAN DZE + {0x04E2, 0x04E2, prUpper}, // L& CYRILLIC CAPITAL LETTER I WITH MACRON + {0x04E3, 0x04E3, prLower}, // L& CYRILLIC SMALL LETTER I WITH MACRON + {0x04E4, 0x04E4, prUpper}, // L& CYRILLIC CAPITAL LETTER I WITH DIAERESIS + {0x04E5, 0x04E5, prLower}, // L& CYRILLIC SMALL LETTER I WITH DIAERESIS + {0x04E6, 0x04E6, prUpper}, // L& CYRILLIC CAPITAL LETTER O WITH DIAERESIS + {0x04E7, 0x04E7, prLower}, // L& CYRILLIC SMALL LETTER O WITH DIAERESIS + {0x04E8, 0x04E8, prUpper}, // L& CYRILLIC CAPITAL LETTER BARRED O + {0x04E9, 0x04E9, prLower}, // L& CYRILLIC SMALL LETTER BARRED O + {0x04EA, 0x04EA, prUpper}, // L& CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS + {0x04EB, 0x04EB, prLower}, // L& CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS + {0x04EC, 0x04EC, prUpper}, // L& CYRILLIC CAPITAL LETTER E WITH DIAERESIS + {0x04ED, 0x04ED, prLower}, // L& CYRILLIC SMALL LETTER E WITH DIAERESIS + {0x04EE, 0x04EE, prUpper}, // L& CYRILLIC CAPITAL LETTER U WITH MACRON + {0x04EF, 0x04EF, prLower}, // L& CYRILLIC SMALL LETTER U WITH MACRON + {0x04F0, 0x04F0, prUpper}, // L& CYRILLIC CAPITAL LETTER U WITH DIAERESIS + {0x04F1, 0x04F1, prLower}, // L& CYRILLIC SMALL LETTER U WITH DIAERESIS + {0x04F2, 0x04F2, prUpper}, // L& CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE + {0x04F3, 0x04F3, prLower}, // L& CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE + {0x04F4, 0x04F4, prUpper}, // L& CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS + {0x04F5, 0x04F5, prLower}, // L& CYRILLIC SMALL LETTER CHE WITH DIAERESIS + {0x04F6, 0x04F6, prUpper}, // L& CYRILLIC CAPITAL LETTER GHE WITH DESCENDER + {0x04F7, 0x04F7, prLower}, // L& CYRILLIC SMALL LETTER GHE WITH DESCENDER + {0x04F8, 0x04F8, prUpper}, // L& CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS + {0x04F9, 0x04F9, prLower}, // L& CYRILLIC SMALL LETTER YERU WITH DIAERESIS + {0x04FA, 0x04FA, prUpper}, // L& CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK + {0x04FB, 0x04FB, prLower}, // L& CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK + {0x04FC, 0x04FC, prUpper}, // L& CYRILLIC CAPITAL LETTER HA WITH HOOK + {0x04FD, 0x04FD, prLower}, // L& CYRILLIC SMALL LETTER HA WITH HOOK + {0x04FE, 0x04FE, prUpper}, // L& CYRILLIC CAPITAL LETTER HA WITH STROKE + {0x04FF, 0x04FF, prLower}, // L& CYRILLIC SMALL LETTER HA WITH STROKE + {0x0500, 0x0500, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI DE + {0x0501, 0x0501, prLower}, // L& CYRILLIC SMALL LETTER KOMI DE + {0x0502, 0x0502, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI DJE + {0x0503, 0x0503, prLower}, // L& CYRILLIC SMALL LETTER KOMI DJE + {0x0504, 0x0504, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI ZJE + {0x0505, 0x0505, prLower}, // L& CYRILLIC SMALL LETTER KOMI ZJE + {0x0506, 0x0506, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI DZJE + {0x0507, 0x0507, prLower}, // L& CYRILLIC SMALL LETTER KOMI DZJE + {0x0508, 0x0508, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI LJE + {0x0509, 0x0509, prLower}, // L& CYRILLIC SMALL LETTER KOMI LJE + {0x050A, 0x050A, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI NJE + {0x050B, 0x050B, prLower}, // L& CYRILLIC SMALL LETTER KOMI NJE + {0x050C, 0x050C, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI SJE + {0x050D, 0x050D, prLower}, // L& CYRILLIC SMALL LETTER KOMI SJE + {0x050E, 0x050E, prUpper}, // L& CYRILLIC CAPITAL LETTER KOMI TJE + {0x050F, 0x050F, prLower}, // L& CYRILLIC SMALL LETTER KOMI TJE + {0x0510, 0x0510, prUpper}, // L& CYRILLIC CAPITAL LETTER REVERSED ZE + {0x0511, 0x0511, prLower}, // L& CYRILLIC SMALL LETTER REVERSED ZE + {0x0512, 0x0512, prUpper}, // L& CYRILLIC CAPITAL LETTER EL WITH HOOK + {0x0513, 0x0513, prLower}, // L& CYRILLIC SMALL LETTER EL WITH HOOK + {0x0514, 0x0514, prUpper}, // L& CYRILLIC CAPITAL LETTER LHA + {0x0515, 0x0515, prLower}, // L& CYRILLIC SMALL LETTER LHA + {0x0516, 0x0516, prUpper}, // L& CYRILLIC CAPITAL LETTER RHA + {0x0517, 0x0517, prLower}, // L& CYRILLIC SMALL LETTER RHA + {0x0518, 0x0518, prUpper}, // L& CYRILLIC CAPITAL LETTER YAE + {0x0519, 0x0519, prLower}, // L& CYRILLIC SMALL LETTER YAE + {0x051A, 0x051A, prUpper}, // L& CYRILLIC CAPITAL LETTER QA + {0x051B, 0x051B, prLower}, // L& CYRILLIC SMALL LETTER QA + {0x051C, 0x051C, prUpper}, // L& CYRILLIC CAPITAL LETTER WE + {0x051D, 0x051D, prLower}, // L& CYRILLIC SMALL LETTER WE + {0x051E, 0x051E, prUpper}, // L& CYRILLIC CAPITAL LETTER ALEUT KA + {0x051F, 0x051F, prLower}, // L& CYRILLIC SMALL LETTER ALEUT KA + {0x0520, 0x0520, prUpper}, // L& CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK + {0x0521, 0x0521, prLower}, // L& CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK + {0x0522, 0x0522, prUpper}, // L& CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK + {0x0523, 0x0523, prLower}, // L& CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK + {0x0524, 0x0524, prUpper}, // L& CYRILLIC CAPITAL LETTER PE WITH DESCENDER + {0x0525, 0x0525, prLower}, // L& CYRILLIC SMALL LETTER PE WITH DESCENDER + {0x0526, 0x0526, prUpper}, // L& CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER + {0x0527, 0x0527, prLower}, // L& CYRILLIC SMALL LETTER SHHA WITH DESCENDER + {0x0528, 0x0528, prUpper}, // L& CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK + {0x0529, 0x0529, prLower}, // L& CYRILLIC SMALL LETTER EN WITH LEFT HOOK + {0x052A, 0x052A, prUpper}, // L& CYRILLIC CAPITAL LETTER DZZHE + {0x052B, 0x052B, prLower}, // L& CYRILLIC SMALL LETTER DZZHE + {0x052C, 0x052C, prUpper}, // L& CYRILLIC CAPITAL LETTER DCHE + {0x052D, 0x052D, prLower}, // L& CYRILLIC SMALL LETTER DCHE + {0x052E, 0x052E, prUpper}, // L& CYRILLIC CAPITAL LETTER EL WITH DESCENDER + {0x052F, 0x052F, prLower}, // L& CYRILLIC SMALL LETTER EL WITH DESCENDER + {0x0531, 0x0556, prUpper}, // L& [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH + {0x0559, 0x0559, prOLetter}, // Lm ARMENIAN MODIFIER LETTER LEFT HALF RING + {0x055D, 0x055D, prSContinue}, // Po ARMENIAN COMMA + {0x0560, 0x0588, prLower}, // L& [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE + {0x0589, 0x0589, prSTerm}, // Po ARMENIAN FULL STOP + {0x0591, 0x05BD, prExtend}, // Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG + {0x05BF, 0x05BF, prExtend}, // Mn HEBREW POINT RAFE + {0x05C1, 0x05C2, prExtend}, // Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT + {0x05C4, 0x05C5, prExtend}, // Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT + {0x05C7, 0x05C7, prExtend}, // Mn HEBREW POINT QAMATS QATAN + {0x05D0, 0x05EA, prOLetter}, // Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV + {0x05EF, 0x05F2, prOLetter}, // Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD + {0x05F3, 0x05F3, prOLetter}, // Po HEBREW PUNCTUATION GERESH + {0x0600, 0x0605, prFormat}, // Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE + {0x060C, 0x060D, prSContinue}, // Po [2] ARABIC COMMA..ARABIC DATE SEPARATOR + {0x0610, 0x061A, prExtend}, // Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA + {0x061C, 0x061C, prFormat}, // Cf ARABIC LETTER MARK + {0x061D, 0x061F, prSTerm}, // Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK + {0x0620, 0x063F, prOLetter}, // Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE + {0x0640, 0x0640, prOLetter}, // Lm ARABIC TATWEEL + {0x0641, 0x064A, prOLetter}, // Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH + {0x064B, 0x065F, prExtend}, // Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW + {0x0660, 0x0669, prNumeric}, // Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE + {0x066B, 0x066C, prNumeric}, // Po [2] ARABIC DECIMAL SEPARATOR..ARABIC THOUSANDS SEPARATOR + {0x066E, 0x066F, prOLetter}, // Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF + {0x0670, 0x0670, prExtend}, // Mn ARABIC LETTER SUPERSCRIPT ALEF + {0x0671, 0x06D3, prOLetter}, // Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE + {0x06D4, 0x06D4, prSTerm}, // Po ARABIC FULL STOP + {0x06D5, 0x06D5, prOLetter}, // Lo ARABIC LETTER AE + {0x06D6, 0x06DC, prExtend}, // Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN + {0x06DD, 0x06DD, prFormat}, // Cf ARABIC END OF AYAH + {0x06DF, 0x06E4, prExtend}, // Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA + {0x06E5, 0x06E6, prOLetter}, // Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH + {0x06E7, 0x06E8, prExtend}, // Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON + {0x06EA, 0x06ED, prExtend}, // Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM + {0x06EE, 0x06EF, prOLetter}, // Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V + {0x06F0, 0x06F9, prNumeric}, // Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE + {0x06FA, 0x06FC, prOLetter}, // Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW + {0x06FF, 0x06FF, prOLetter}, // Lo ARABIC LETTER HEH WITH INVERTED V + {0x0700, 0x0702, prSTerm}, // Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP + {0x070F, 0x070F, prFormat}, // Cf SYRIAC ABBREVIATION MARK + {0x0710, 0x0710, prOLetter}, // Lo SYRIAC LETTER ALAPH + {0x0711, 0x0711, prExtend}, // Mn SYRIAC LETTER SUPERSCRIPT ALAPH + {0x0712, 0x072F, prOLetter}, // Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH + {0x0730, 0x074A, prExtend}, // Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH + {0x074D, 0x07A5, prOLetter}, // Lo [89] SYRIAC LETTER SOGDIAN ZHAIN..THAANA LETTER WAAVU + {0x07A6, 0x07B0, prExtend}, // Mn [11] THAANA ABAFILI..THAANA SUKUN + {0x07B1, 0x07B1, prOLetter}, // Lo THAANA LETTER NAA + {0x07C0, 0x07C9, prNumeric}, // Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE + {0x07CA, 0x07EA, prOLetter}, // Lo [33] NKO LETTER A..NKO LETTER JONA RA + {0x07EB, 0x07F3, prExtend}, // Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE + {0x07F4, 0x07F5, prOLetter}, // Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE + {0x07F8, 0x07F8, prSContinue}, // Po NKO COMMA + {0x07F9, 0x07F9, prSTerm}, // Po NKO EXCLAMATION MARK + {0x07FA, 0x07FA, prOLetter}, // Lm NKO LAJANYALAN + {0x07FD, 0x07FD, prExtend}, // Mn NKO DANTAYALAN + {0x0800, 0x0815, prOLetter}, // Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF + {0x0816, 0x0819, prExtend}, // Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH + {0x081A, 0x081A, prOLetter}, // Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT + {0x081B, 0x0823, prExtend}, // Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A + {0x0824, 0x0824, prOLetter}, // Lm SAMARITAN MODIFIER LETTER SHORT A + {0x0825, 0x0827, prExtend}, // Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U + {0x0828, 0x0828, prOLetter}, // Lm SAMARITAN MODIFIER LETTER I + {0x0829, 0x082D, prExtend}, // Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA + {0x0837, 0x0837, prSTerm}, // Po SAMARITAN PUNCTUATION MELODIC QITSA + {0x0839, 0x0839, prSTerm}, // Po SAMARITAN PUNCTUATION QITSA + {0x083D, 0x083E, prSTerm}, // Po [2] SAMARITAN PUNCTUATION SOF MASHFAAT..SAMARITAN PUNCTUATION ANNAAU + {0x0840, 0x0858, prOLetter}, // Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN + {0x0859, 0x085B, prExtend}, // Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK + {0x0860, 0x086A, prOLetter}, // Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA + {0x0870, 0x0887, prOLetter}, // Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT + {0x0889, 0x088E, prOLetter}, // Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL + {0x0890, 0x0891, prFormat}, // Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE + {0x0898, 0x089F, prExtend}, // Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA + {0x08A0, 0x08C8, prOLetter}, // Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF + {0x08C9, 0x08C9, prOLetter}, // Lm ARABIC SMALL FARSI YEH + {0x08CA, 0x08E1, prExtend}, // Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA + {0x08E2, 0x08E2, prFormat}, // Cf ARABIC DISPUTED END OF AYAH + {0x08E3, 0x0902, prExtend}, // Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA + {0x0903, 0x0903, prExtend}, // Mc DEVANAGARI SIGN VISARGA + {0x0904, 0x0939, prOLetter}, // Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA + {0x093A, 0x093A, prExtend}, // Mn DEVANAGARI VOWEL SIGN OE + {0x093B, 0x093B, prExtend}, // Mc DEVANAGARI VOWEL SIGN OOE + {0x093C, 0x093C, prExtend}, // Mn DEVANAGARI SIGN NUKTA + {0x093D, 0x093D, prOLetter}, // Lo DEVANAGARI SIGN AVAGRAHA + {0x093E, 0x0940, prExtend}, // Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II + {0x0941, 0x0948, prExtend}, // Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI + {0x0949, 0x094C, prExtend}, // Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU + {0x094D, 0x094D, prExtend}, // Mn DEVANAGARI SIGN VIRAMA + {0x094E, 0x094F, prExtend}, // Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW + {0x0950, 0x0950, prOLetter}, // Lo DEVANAGARI OM + {0x0951, 0x0957, prExtend}, // Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE + {0x0958, 0x0961, prOLetter}, // Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL + {0x0962, 0x0963, prExtend}, // Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL + {0x0964, 0x0965, prSTerm}, // Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA + {0x0966, 0x096F, prNumeric}, // Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE + {0x0971, 0x0971, prOLetter}, // Lm DEVANAGARI SIGN HIGH SPACING DOT + {0x0972, 0x0980, prOLetter}, // Lo [15] DEVANAGARI LETTER CANDRA A..BENGALI ANJI + {0x0981, 0x0981, prExtend}, // Mn BENGALI SIGN CANDRABINDU + {0x0982, 0x0983, prExtend}, // Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA + {0x0985, 0x098C, prOLetter}, // Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L + {0x098F, 0x0990, prOLetter}, // Lo [2] BENGALI LETTER E..BENGALI LETTER AI + {0x0993, 0x09A8, prOLetter}, // Lo [22] BENGALI LETTER O..BENGALI LETTER NA + {0x09AA, 0x09B0, prOLetter}, // Lo [7] BENGALI LETTER PA..BENGALI LETTER RA + {0x09B2, 0x09B2, prOLetter}, // Lo BENGALI LETTER LA + {0x09B6, 0x09B9, prOLetter}, // Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA + {0x09BC, 0x09BC, prExtend}, // Mn BENGALI SIGN NUKTA + {0x09BD, 0x09BD, prOLetter}, // Lo BENGALI SIGN AVAGRAHA + {0x09BE, 0x09C0, prExtend}, // Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II + {0x09C1, 0x09C4, prExtend}, // Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR + {0x09C7, 0x09C8, prExtend}, // Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI + {0x09CB, 0x09CC, prExtend}, // Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU + {0x09CD, 0x09CD, prExtend}, // Mn BENGALI SIGN VIRAMA + {0x09CE, 0x09CE, prOLetter}, // Lo BENGALI LETTER KHANDA TA + {0x09D7, 0x09D7, prExtend}, // Mc BENGALI AU LENGTH MARK + {0x09DC, 0x09DD, prOLetter}, // Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA + {0x09DF, 0x09E1, prOLetter}, // Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL + {0x09E2, 0x09E3, prExtend}, // Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL + {0x09E6, 0x09EF, prNumeric}, // Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE + {0x09F0, 0x09F1, prOLetter}, // Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL + {0x09FC, 0x09FC, prOLetter}, // Lo BENGALI LETTER VEDIC ANUSVARA + {0x09FE, 0x09FE, prExtend}, // Mn BENGALI SANDHI MARK + {0x0A01, 0x0A02, prExtend}, // Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI + {0x0A03, 0x0A03, prExtend}, // Mc GURMUKHI SIGN VISARGA + {0x0A05, 0x0A0A, prOLetter}, // Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU + {0x0A0F, 0x0A10, prOLetter}, // Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI + {0x0A13, 0x0A28, prOLetter}, // Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA + {0x0A2A, 0x0A30, prOLetter}, // Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA + {0x0A32, 0x0A33, prOLetter}, // Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA + {0x0A35, 0x0A36, prOLetter}, // Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA + {0x0A38, 0x0A39, prOLetter}, // Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA + {0x0A3C, 0x0A3C, prExtend}, // Mn GURMUKHI SIGN NUKTA + {0x0A3E, 0x0A40, prExtend}, // Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II + {0x0A41, 0x0A42, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU + {0x0A47, 0x0A48, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI + {0x0A4B, 0x0A4D, prExtend}, // Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA + {0x0A51, 0x0A51, prExtend}, // Mn GURMUKHI SIGN UDAAT + {0x0A59, 0x0A5C, prOLetter}, // Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA + {0x0A5E, 0x0A5E, prOLetter}, // Lo GURMUKHI LETTER FA + {0x0A66, 0x0A6F, prNumeric}, // Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE + {0x0A70, 0x0A71, prExtend}, // Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK + {0x0A72, 0x0A74, prOLetter}, // Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR + {0x0A75, 0x0A75, prExtend}, // Mn GURMUKHI SIGN YAKASH + {0x0A81, 0x0A82, prExtend}, // Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA + {0x0A83, 0x0A83, prExtend}, // Mc GUJARATI SIGN VISARGA + {0x0A85, 0x0A8D, prOLetter}, // Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E + {0x0A8F, 0x0A91, prOLetter}, // Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O + {0x0A93, 0x0AA8, prOLetter}, // Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA + {0x0AAA, 0x0AB0, prOLetter}, // Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA + {0x0AB2, 0x0AB3, prOLetter}, // Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA + {0x0AB5, 0x0AB9, prOLetter}, // Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA + {0x0ABC, 0x0ABC, prExtend}, // Mn GUJARATI SIGN NUKTA + {0x0ABD, 0x0ABD, prOLetter}, // Lo GUJARATI SIGN AVAGRAHA + {0x0ABE, 0x0AC0, prExtend}, // Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II + {0x0AC1, 0x0AC5, prExtend}, // Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E + {0x0AC7, 0x0AC8, prExtend}, // Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI + {0x0AC9, 0x0AC9, prExtend}, // Mc GUJARATI VOWEL SIGN CANDRA O + {0x0ACB, 0x0ACC, prExtend}, // Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU + {0x0ACD, 0x0ACD, prExtend}, // Mn GUJARATI SIGN VIRAMA + {0x0AD0, 0x0AD0, prOLetter}, // Lo GUJARATI OM + {0x0AE0, 0x0AE1, prOLetter}, // Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL + {0x0AE2, 0x0AE3, prExtend}, // Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL + {0x0AE6, 0x0AEF, prNumeric}, // Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE + {0x0AF9, 0x0AF9, prOLetter}, // Lo GUJARATI LETTER ZHA + {0x0AFA, 0x0AFF, prExtend}, // Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE + {0x0B01, 0x0B01, prExtend}, // Mn ORIYA SIGN CANDRABINDU + {0x0B02, 0x0B03, prExtend}, // Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA + {0x0B05, 0x0B0C, prOLetter}, // Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L + {0x0B0F, 0x0B10, prOLetter}, // Lo [2] ORIYA LETTER E..ORIYA LETTER AI + {0x0B13, 0x0B28, prOLetter}, // Lo [22] ORIYA LETTER O..ORIYA LETTER NA + {0x0B2A, 0x0B30, prOLetter}, // Lo [7] ORIYA LETTER PA..ORIYA LETTER RA + {0x0B32, 0x0B33, prOLetter}, // Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA + {0x0B35, 0x0B39, prOLetter}, // Lo [5] ORIYA LETTER VA..ORIYA LETTER HA + {0x0B3C, 0x0B3C, prExtend}, // Mn ORIYA SIGN NUKTA + {0x0B3D, 0x0B3D, prOLetter}, // Lo ORIYA SIGN AVAGRAHA + {0x0B3E, 0x0B3E, prExtend}, // Mc ORIYA VOWEL SIGN AA + {0x0B3F, 0x0B3F, prExtend}, // Mn ORIYA VOWEL SIGN I + {0x0B40, 0x0B40, prExtend}, // Mc ORIYA VOWEL SIGN II + {0x0B41, 0x0B44, prExtend}, // Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR + {0x0B47, 0x0B48, prExtend}, // Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI + {0x0B4B, 0x0B4C, prExtend}, // Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU + {0x0B4D, 0x0B4D, prExtend}, // Mn ORIYA SIGN VIRAMA + {0x0B55, 0x0B56, prExtend}, // Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK + {0x0B57, 0x0B57, prExtend}, // Mc ORIYA AU LENGTH MARK + {0x0B5C, 0x0B5D, prOLetter}, // Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA + {0x0B5F, 0x0B61, prOLetter}, // Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL + {0x0B62, 0x0B63, prExtend}, // Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL + {0x0B66, 0x0B6F, prNumeric}, // Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE + {0x0B71, 0x0B71, prOLetter}, // Lo ORIYA LETTER WA + {0x0B82, 0x0B82, prExtend}, // Mn TAMIL SIGN ANUSVARA + {0x0B83, 0x0B83, prOLetter}, // Lo TAMIL SIGN VISARGA + {0x0B85, 0x0B8A, prOLetter}, // Lo [6] TAMIL LETTER A..TAMIL LETTER UU + {0x0B8E, 0x0B90, prOLetter}, // Lo [3] TAMIL LETTER E..TAMIL LETTER AI + {0x0B92, 0x0B95, prOLetter}, // Lo [4] TAMIL LETTER O..TAMIL LETTER KA + {0x0B99, 0x0B9A, prOLetter}, // Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA + {0x0B9C, 0x0B9C, prOLetter}, // Lo TAMIL LETTER JA + {0x0B9E, 0x0B9F, prOLetter}, // Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA + {0x0BA3, 0x0BA4, prOLetter}, // Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA + {0x0BA8, 0x0BAA, prOLetter}, // Lo [3] TAMIL LETTER NA..TAMIL LETTER PA + {0x0BAE, 0x0BB9, prOLetter}, // Lo [12] TAMIL LETTER MA..TAMIL LETTER HA + {0x0BBE, 0x0BBF, prExtend}, // Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I + {0x0BC0, 0x0BC0, prExtend}, // Mn TAMIL VOWEL SIGN II + {0x0BC1, 0x0BC2, prExtend}, // Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU + {0x0BC6, 0x0BC8, prExtend}, // Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI + {0x0BCA, 0x0BCC, prExtend}, // Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU + {0x0BCD, 0x0BCD, prExtend}, // Mn TAMIL SIGN VIRAMA + {0x0BD0, 0x0BD0, prOLetter}, // Lo TAMIL OM + {0x0BD7, 0x0BD7, prExtend}, // Mc TAMIL AU LENGTH MARK + {0x0BE6, 0x0BEF, prNumeric}, // Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE + {0x0C00, 0x0C00, prExtend}, // Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE + {0x0C01, 0x0C03, prExtend}, // Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA + {0x0C04, 0x0C04, prExtend}, // Mn TELUGU SIGN COMBINING ANUSVARA ABOVE + {0x0C05, 0x0C0C, prOLetter}, // Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L + {0x0C0E, 0x0C10, prOLetter}, // Lo [3] TELUGU LETTER E..TELUGU LETTER AI + {0x0C12, 0x0C28, prOLetter}, // Lo [23] TELUGU LETTER O..TELUGU LETTER NA + {0x0C2A, 0x0C39, prOLetter}, // Lo [16] TELUGU LETTER PA..TELUGU LETTER HA + {0x0C3C, 0x0C3C, prExtend}, // Mn TELUGU SIGN NUKTA + {0x0C3D, 0x0C3D, prOLetter}, // Lo TELUGU SIGN AVAGRAHA + {0x0C3E, 0x0C40, prExtend}, // Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II + {0x0C41, 0x0C44, prExtend}, // Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR + {0x0C46, 0x0C48, prExtend}, // Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI + {0x0C4A, 0x0C4D, prExtend}, // Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA + {0x0C55, 0x0C56, prExtend}, // Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK + {0x0C58, 0x0C5A, prOLetter}, // Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA + {0x0C5D, 0x0C5D, prOLetter}, // Lo TELUGU LETTER NAKAARA POLLU + {0x0C60, 0x0C61, prOLetter}, // Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL + {0x0C62, 0x0C63, prExtend}, // Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL + {0x0C66, 0x0C6F, prNumeric}, // Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE + {0x0C80, 0x0C80, prOLetter}, // Lo KANNADA SIGN SPACING CANDRABINDU + {0x0C81, 0x0C81, prExtend}, // Mn KANNADA SIGN CANDRABINDU + {0x0C82, 0x0C83, prExtend}, // Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA + {0x0C85, 0x0C8C, prOLetter}, // Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L + {0x0C8E, 0x0C90, prOLetter}, // Lo [3] KANNADA LETTER E..KANNADA LETTER AI + {0x0C92, 0x0CA8, prOLetter}, // Lo [23] KANNADA LETTER O..KANNADA LETTER NA + {0x0CAA, 0x0CB3, prOLetter}, // Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA + {0x0CB5, 0x0CB9, prOLetter}, // Lo [5] KANNADA LETTER VA..KANNADA LETTER HA + {0x0CBC, 0x0CBC, prExtend}, // Mn KANNADA SIGN NUKTA + {0x0CBD, 0x0CBD, prOLetter}, // Lo KANNADA SIGN AVAGRAHA + {0x0CBE, 0x0CBE, prExtend}, // Mc KANNADA VOWEL SIGN AA + {0x0CBF, 0x0CBF, prExtend}, // Mn KANNADA VOWEL SIGN I + {0x0CC0, 0x0CC4, prExtend}, // Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR + {0x0CC6, 0x0CC6, prExtend}, // Mn KANNADA VOWEL SIGN E + {0x0CC7, 0x0CC8, prExtend}, // Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI + {0x0CCA, 0x0CCB, prExtend}, // Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO + {0x0CCC, 0x0CCD, prExtend}, // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA + {0x0CD5, 0x0CD6, prExtend}, // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK + {0x0CDD, 0x0CDE, prOLetter}, // Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA + {0x0CE0, 0x0CE1, prOLetter}, // Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL + {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0CE6, 0x0CEF, prNumeric}, // Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE + {0x0CF1, 0x0CF2, prOLetter}, // Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prExtend}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT + {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU + {0x0D02, 0x0D03, prExtend}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA + {0x0D04, 0x0D0C, prOLetter}, // Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L + {0x0D0E, 0x0D10, prOLetter}, // Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI + {0x0D12, 0x0D3A, prOLetter}, // Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA + {0x0D3B, 0x0D3C, prExtend}, // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA + {0x0D3D, 0x0D3D, prOLetter}, // Lo MALAYALAM SIGN AVAGRAHA + {0x0D3E, 0x0D40, prExtend}, // Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II + {0x0D41, 0x0D44, prExtend}, // Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR + {0x0D46, 0x0D48, prExtend}, // Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI + {0x0D4A, 0x0D4C, prExtend}, // Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU + {0x0D4D, 0x0D4D, prExtend}, // Mn MALAYALAM SIGN VIRAMA + {0x0D4E, 0x0D4E, prOLetter}, // Lo MALAYALAM LETTER DOT REPH + {0x0D54, 0x0D56, prOLetter}, // Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL + {0x0D57, 0x0D57, prExtend}, // Mc MALAYALAM AU LENGTH MARK + {0x0D5F, 0x0D61, prOLetter}, // Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL + {0x0D62, 0x0D63, prExtend}, // Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL + {0x0D66, 0x0D6F, prNumeric}, // Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE + {0x0D7A, 0x0D7F, prOLetter}, // Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K + {0x0D81, 0x0D81, prExtend}, // Mn SINHALA SIGN CANDRABINDU + {0x0D82, 0x0D83, prExtend}, // Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA + {0x0D85, 0x0D96, prOLetter}, // Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA + {0x0D9A, 0x0DB1, prOLetter}, // Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA + {0x0DB3, 0x0DBB, prOLetter}, // Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA + {0x0DBD, 0x0DBD, prOLetter}, // Lo SINHALA LETTER DANTAJA LAYANNA + {0x0DC0, 0x0DC6, prOLetter}, // Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA + {0x0DCA, 0x0DCA, prExtend}, // Mn SINHALA SIGN AL-LAKUNA + {0x0DCF, 0x0DD1, prExtend}, // Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA + {0x0DD2, 0x0DD4, prExtend}, // Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA + {0x0DD6, 0x0DD6, prExtend}, // Mn SINHALA VOWEL SIGN DIGA PAA-PILLA + {0x0DD8, 0x0DDF, prExtend}, // Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA + {0x0DE6, 0x0DEF, prNumeric}, // Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE + {0x0DF2, 0x0DF3, prExtend}, // Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA + {0x0E01, 0x0E30, prOLetter}, // Lo [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A + {0x0E31, 0x0E31, prExtend}, // Mn THAI CHARACTER MAI HAN-AKAT + {0x0E32, 0x0E33, prOLetter}, // Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM + {0x0E34, 0x0E3A, prExtend}, // Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU + {0x0E40, 0x0E45, prOLetter}, // Lo [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO + {0x0E46, 0x0E46, prOLetter}, // Lm THAI CHARACTER MAIYAMOK + {0x0E47, 0x0E4E, prExtend}, // Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN + {0x0E50, 0x0E59, prNumeric}, // Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE + {0x0E81, 0x0E82, prOLetter}, // Lo [2] LAO LETTER KO..LAO LETTER KHO SUNG + {0x0E84, 0x0E84, prOLetter}, // Lo LAO LETTER KHO TAM + {0x0E86, 0x0E8A, prOLetter}, // Lo [5] LAO LETTER PALI GHA..LAO LETTER SO TAM + {0x0E8C, 0x0EA3, prOLetter}, // Lo [24] LAO LETTER PALI JHA..LAO LETTER LO LING + {0x0EA5, 0x0EA5, prOLetter}, // Lo LAO LETTER LO LOOT + {0x0EA7, 0x0EB0, prOLetter}, // Lo [10] LAO LETTER WO..LAO VOWEL SIGN A + {0x0EB1, 0x0EB1, prExtend}, // Mn LAO VOWEL SIGN MAI KAN + {0x0EB2, 0x0EB3, prOLetter}, // Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM + {0x0EB4, 0x0EBC, prExtend}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO + {0x0EBD, 0x0EBD, prOLetter}, // Lo LAO SEMIVOWEL SIGN NYO + {0x0EC0, 0x0EC4, prOLetter}, // Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI + {0x0EC6, 0x0EC6, prOLetter}, // Lm LAO KO LA + {0x0EC8, 0x0ECE, prExtend}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN + {0x0ED0, 0x0ED9, prNumeric}, // Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE + {0x0EDC, 0x0EDF, prOLetter}, // Lo [4] LAO HO NO..LAO LETTER KHMU NYO + {0x0F00, 0x0F00, prOLetter}, // Lo TIBETAN SYLLABLE OM + {0x0F18, 0x0F19, prExtend}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS + {0x0F20, 0x0F29, prNumeric}, // Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE + {0x0F35, 0x0F35, prExtend}, // Mn TIBETAN MARK NGAS BZUNG NYI ZLA + {0x0F37, 0x0F37, prExtend}, // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS + {0x0F39, 0x0F39, prExtend}, // Mn TIBETAN MARK TSA -PHRU + {0x0F3A, 0x0F3A, prClose}, // Ps TIBETAN MARK GUG RTAGS GYON + {0x0F3B, 0x0F3B, prClose}, // Pe TIBETAN MARK GUG RTAGS GYAS + {0x0F3C, 0x0F3C, prClose}, // Ps TIBETAN MARK ANG KHANG GYON + {0x0F3D, 0x0F3D, prClose}, // Pe TIBETAN MARK ANG KHANG GYAS + {0x0F3E, 0x0F3F, prExtend}, // Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES + {0x0F40, 0x0F47, prOLetter}, // Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA + {0x0F49, 0x0F6C, prOLetter}, // Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA + {0x0F71, 0x0F7E, prExtend}, // Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO + {0x0F7F, 0x0F7F, prExtend}, // Mc TIBETAN SIGN RNAM BCAD + {0x0F80, 0x0F84, prExtend}, // Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA + {0x0F86, 0x0F87, prExtend}, // Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS + {0x0F88, 0x0F8C, prOLetter}, // Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN + {0x0F8D, 0x0F97, prExtend}, // Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA + {0x0F99, 0x0FBC, prExtend}, // Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA + {0x0FC6, 0x0FC6, prExtend}, // Mn TIBETAN SYMBOL PADMA GDAN + {0x1000, 0x102A, prOLetter}, // Lo [43] MYANMAR LETTER KA..MYANMAR LETTER AU + {0x102B, 0x102C, prExtend}, // Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA + {0x102D, 0x1030, prExtend}, // Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU + {0x1031, 0x1031, prExtend}, // Mc MYANMAR VOWEL SIGN E + {0x1032, 0x1037, prExtend}, // Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW + {0x1038, 0x1038, prExtend}, // Mc MYANMAR SIGN VISARGA + {0x1039, 0x103A, prExtend}, // Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT + {0x103B, 0x103C, prExtend}, // Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA + {0x103D, 0x103E, prExtend}, // Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA + {0x103F, 0x103F, prOLetter}, // Lo MYANMAR LETTER GREAT SA + {0x1040, 0x1049, prNumeric}, // Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE + {0x104A, 0x104B, prSTerm}, // Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION + {0x1050, 0x1055, prOLetter}, // Lo [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL + {0x1056, 0x1057, prExtend}, // Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR + {0x1058, 0x1059, prExtend}, // Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL + {0x105A, 0x105D, prOLetter}, // Lo [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE + {0x105E, 0x1060, prExtend}, // Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA + {0x1061, 0x1061, prOLetter}, // Lo MYANMAR LETTER SGAW KAREN SHA + {0x1062, 0x1064, prExtend}, // Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO + {0x1065, 0x1066, prOLetter}, // Lo [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA + {0x1067, 0x106D, prExtend}, // Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 + {0x106E, 0x1070, prOLetter}, // Lo [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA + {0x1071, 0x1074, prExtend}, // Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE + {0x1075, 0x1081, prOLetter}, // Lo [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA + {0x1082, 0x1082, prExtend}, // Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA + {0x1083, 0x1084, prExtend}, // Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E + {0x1085, 0x1086, prExtend}, // Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y + {0x1087, 0x108C, prExtend}, // Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 + {0x108D, 0x108D, prExtend}, // Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE + {0x108E, 0x108E, prOLetter}, // Lo MYANMAR LETTER RUMAI PALAUNG FA + {0x108F, 0x108F, prExtend}, // Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 + {0x1090, 0x1099, prNumeric}, // Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE + {0x109A, 0x109C, prExtend}, // Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A + {0x109D, 0x109D, prExtend}, // Mn MYANMAR VOWEL SIGN AITON AI + {0x10A0, 0x10C5, prUpper}, // L& [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE + {0x10C7, 0x10C7, prUpper}, // L& GEORGIAN CAPITAL LETTER YN + {0x10CD, 0x10CD, prUpper}, // L& GEORGIAN CAPITAL LETTER AEN + {0x10D0, 0x10FA, prOLetter}, // L& [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN + {0x10FC, 0x10FC, prLower}, // Lm MODIFIER LETTER GEORGIAN NAR + {0x10FD, 0x10FF, prOLetter}, // L& [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN + {0x1100, 0x1248, prOLetter}, // Lo [329] HANGUL CHOSEONG KIYEOK..ETHIOPIC SYLLABLE QWA + {0x124A, 0x124D, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE + {0x1250, 0x1256, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO + {0x1258, 0x1258, prOLetter}, // Lo ETHIOPIC SYLLABLE QHWA + {0x125A, 0x125D, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE + {0x1260, 0x1288, prOLetter}, // Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA + {0x128A, 0x128D, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE + {0x1290, 0x12B0, prOLetter}, // Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA + {0x12B2, 0x12B5, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE + {0x12B8, 0x12BE, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO + {0x12C0, 0x12C0, prOLetter}, // Lo ETHIOPIC SYLLABLE KXWA + {0x12C2, 0x12C5, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE + {0x12C8, 0x12D6, prOLetter}, // Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O + {0x12D8, 0x1310, prOLetter}, // Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA + {0x1312, 0x1315, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE + {0x1318, 0x135A, prOLetter}, // Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA + {0x135D, 0x135F, prExtend}, // Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK + {0x1362, 0x1362, prSTerm}, // Po ETHIOPIC FULL STOP + {0x1367, 0x1368, prSTerm}, // Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR + {0x1380, 0x138F, prOLetter}, // Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE + {0x13A0, 0x13F5, prUpper}, // L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV + {0x13F8, 0x13FD, prLower}, // L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV + {0x1401, 0x166C, prOLetter}, // Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA + {0x166E, 0x166E, prSTerm}, // Po CANADIAN SYLLABICS FULL STOP + {0x166F, 0x167F, prOLetter}, // Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W + {0x1680, 0x1680, prSp}, // Zs OGHAM SPACE MARK + {0x1681, 0x169A, prOLetter}, // Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH + {0x169B, 0x169B, prClose}, // Ps OGHAM FEATHER MARK + {0x169C, 0x169C, prClose}, // Pe OGHAM REVERSED FEATHER MARK + {0x16A0, 0x16EA, prOLetter}, // Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X + {0x16EE, 0x16F0, prOLetter}, // Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL + {0x16F1, 0x16F8, prOLetter}, // Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC + {0x1700, 0x1711, prOLetter}, // Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA + {0x1712, 0x1714, prExtend}, // Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + {0x1715, 0x1715, prExtend}, // Mc TAGALOG SIGN PAMUDPOD + {0x171F, 0x1731, prOLetter}, // Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA + {0x1732, 0x1733, prExtend}, // Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U + {0x1734, 0x1734, prExtend}, // Mc HANUNOO SIGN PAMUDPOD + {0x1735, 0x1736, prSTerm}, // Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION + {0x1740, 0x1751, prOLetter}, // Lo [18] BUHID LETTER A..BUHID LETTER HA + {0x1752, 0x1753, prExtend}, // Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + {0x1760, 0x176C, prOLetter}, // Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA + {0x176E, 0x1770, prOLetter}, // Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA + {0x1772, 0x1773, prExtend}, // Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + {0x1780, 0x17B3, prOLetter}, // Lo [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU + {0x17B4, 0x17B5, prExtend}, // Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA + {0x17B6, 0x17B6, prExtend}, // Mc KHMER VOWEL SIGN AA + {0x17B7, 0x17BD, prExtend}, // Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA + {0x17BE, 0x17C5, prExtend}, // Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU + {0x17C6, 0x17C6, prExtend}, // Mn KHMER SIGN NIKAHIT + {0x17C7, 0x17C8, prExtend}, // Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU + {0x17C9, 0x17D3, prExtend}, // Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT + {0x17D7, 0x17D7, prOLetter}, // Lm KHMER SIGN LEK TOO + {0x17DC, 0x17DC, prOLetter}, // Lo KHMER SIGN AVAKRAHASANYA + {0x17DD, 0x17DD, prExtend}, // Mn KHMER SIGN ATTHACAN + {0x17E0, 0x17E9, prNumeric}, // Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE + {0x1802, 0x1802, prSContinue}, // Po MONGOLIAN COMMA + {0x1803, 0x1803, prSTerm}, // Po MONGOLIAN FULL STOP + {0x1808, 0x1808, prSContinue}, // Po MONGOLIAN MANCHU COMMA + {0x1809, 0x1809, prSTerm}, // Po MONGOLIAN MANCHU FULL STOP + {0x180B, 0x180D, prExtend}, // Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE + {0x180E, 0x180E, prFormat}, // Cf MONGOLIAN VOWEL SEPARATOR + {0x180F, 0x180F, prExtend}, // Mn MONGOLIAN FREE VARIATION SELECTOR FOUR + {0x1810, 0x1819, prNumeric}, // Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE + {0x1820, 0x1842, prOLetter}, // Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI + {0x1843, 0x1843, prOLetter}, // Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN + {0x1844, 0x1878, prOLetter}, // Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS + {0x1880, 0x1884, prOLetter}, // Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA + {0x1885, 0x1886, prExtend}, // Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA + {0x1887, 0x18A8, prOLetter}, // Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA + {0x18A9, 0x18A9, prExtend}, // Mn MONGOLIAN LETTER ALI GALI DAGALGA + {0x18AA, 0x18AA, prOLetter}, // Lo MONGOLIAN LETTER MANCHU ALI GALI LHA + {0x18B0, 0x18F5, prOLetter}, // Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S + {0x1900, 0x191E, prOLetter}, // Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA + {0x1920, 0x1922, prExtend}, // Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U + {0x1923, 0x1926, prExtend}, // Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU + {0x1927, 0x1928, prExtend}, // Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O + {0x1929, 0x192B, prExtend}, // Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA + {0x1930, 0x1931, prExtend}, // Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA + {0x1932, 0x1932, prExtend}, // Mn LIMBU SMALL LETTER ANUSVARA + {0x1933, 0x1938, prExtend}, // Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA + {0x1939, 0x193B, prExtend}, // Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I + {0x1944, 0x1945, prSTerm}, // Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK + {0x1946, 0x194F, prNumeric}, // Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE + {0x1950, 0x196D, prOLetter}, // Lo [30] TAI LE LETTER KA..TAI LE LETTER AI + {0x1970, 0x1974, prOLetter}, // Lo [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6 + {0x1980, 0x19AB, prOLetter}, // Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA + {0x19B0, 0x19C9, prOLetter}, // Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2 + {0x19D0, 0x19D9, prNumeric}, // Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE + {0x1A00, 0x1A16, prOLetter}, // Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA + {0x1A17, 0x1A18, prExtend}, // Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U + {0x1A19, 0x1A1A, prExtend}, // Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O + {0x1A1B, 0x1A1B, prExtend}, // Mn BUGINESE VOWEL SIGN AE + {0x1A20, 0x1A54, prOLetter}, // Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA + {0x1A55, 0x1A55, prExtend}, // Mc TAI THAM CONSONANT SIGN MEDIAL RA + {0x1A56, 0x1A56, prExtend}, // Mn TAI THAM CONSONANT SIGN MEDIAL LA + {0x1A57, 0x1A57, prExtend}, // Mc TAI THAM CONSONANT SIGN LA TANG LAI + {0x1A58, 0x1A5E, prExtend}, // Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA + {0x1A60, 0x1A60, prExtend}, // Mn TAI THAM SIGN SAKOT + {0x1A61, 0x1A61, prExtend}, // Mc TAI THAM VOWEL SIGN A + {0x1A62, 0x1A62, prExtend}, // Mn TAI THAM VOWEL SIGN MAI SAT + {0x1A63, 0x1A64, prExtend}, // Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA + {0x1A65, 0x1A6C, prExtend}, // Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW + {0x1A6D, 0x1A72, prExtend}, // Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI + {0x1A73, 0x1A7C, prExtend}, // Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN + {0x1A7F, 0x1A7F, prExtend}, // Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT + {0x1A80, 0x1A89, prNumeric}, // Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE + {0x1A90, 0x1A99, prNumeric}, // Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE + {0x1AA7, 0x1AA7, prOLetter}, // Lm TAI THAM SIGN MAI YAMOK + {0x1AA8, 0x1AAB, prSTerm}, // Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU + {0x1AB0, 0x1ABD, prExtend}, // Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW + {0x1ABE, 0x1ABE, prExtend}, // Me COMBINING PARENTHESES OVERLAY + {0x1ABF, 0x1ACE, prExtend}, // Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T + {0x1B00, 0x1B03, prExtend}, // Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG + {0x1B04, 0x1B04, prExtend}, // Mc BALINESE SIGN BISAH + {0x1B05, 0x1B33, prOLetter}, // Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA + {0x1B34, 0x1B34, prExtend}, // Mn BALINESE SIGN REREKAN + {0x1B35, 0x1B35, prExtend}, // Mc BALINESE VOWEL SIGN TEDUNG + {0x1B36, 0x1B3A, prExtend}, // Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA + {0x1B3B, 0x1B3B, prExtend}, // Mc BALINESE VOWEL SIGN RA REPA TEDUNG + {0x1B3C, 0x1B3C, prExtend}, // Mn BALINESE VOWEL SIGN LA LENGA + {0x1B3D, 0x1B41, prExtend}, // Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG + {0x1B42, 0x1B42, prExtend}, // Mn BALINESE VOWEL SIGN PEPET + {0x1B43, 0x1B44, prExtend}, // Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG + {0x1B45, 0x1B4C, prOLetter}, // Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA + {0x1B50, 0x1B59, prNumeric}, // Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE + {0x1B5A, 0x1B5B, prSTerm}, // Po [2] BALINESE PANTI..BALINESE PAMADA + {0x1B5E, 0x1B5F, prSTerm}, // Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN + {0x1B6B, 0x1B73, prExtend}, // Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG + {0x1B7D, 0x1B7E, prSTerm}, // Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG + {0x1B80, 0x1B81, prExtend}, // Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR + {0x1B82, 0x1B82, prExtend}, // Mc SUNDANESE SIGN PANGWISAD + {0x1B83, 0x1BA0, prOLetter}, // Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA + {0x1BA1, 0x1BA1, prExtend}, // Mc SUNDANESE CONSONANT SIGN PAMINGKAL + {0x1BA2, 0x1BA5, prExtend}, // Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU + {0x1BA6, 0x1BA7, prExtend}, // Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG + {0x1BA8, 0x1BA9, prExtend}, // Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG + {0x1BAA, 0x1BAA, prExtend}, // Mc SUNDANESE SIGN PAMAAEH + {0x1BAB, 0x1BAD, prExtend}, // Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA + {0x1BAE, 0x1BAF, prOLetter}, // Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA + {0x1BB0, 0x1BB9, prNumeric}, // Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE + {0x1BBA, 0x1BE5, prOLetter}, // Lo [44] SUNDANESE AVAGRAHA..BATAK LETTER U + {0x1BE6, 0x1BE6, prExtend}, // Mn BATAK SIGN TOMPI + {0x1BE7, 0x1BE7, prExtend}, // Mc BATAK VOWEL SIGN E + {0x1BE8, 0x1BE9, prExtend}, // Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE + {0x1BEA, 0x1BEC, prExtend}, // Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O + {0x1BED, 0x1BED, prExtend}, // Mn BATAK VOWEL SIGN KARO O + {0x1BEE, 0x1BEE, prExtend}, // Mc BATAK VOWEL SIGN U + {0x1BEF, 0x1BF1, prExtend}, // Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H + {0x1BF2, 0x1BF3, prExtend}, // Mc [2] BATAK PANGOLAT..BATAK PANONGONAN + {0x1C00, 0x1C23, prOLetter}, // Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A + {0x1C24, 0x1C2B, prExtend}, // Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU + {0x1C2C, 0x1C33, prExtend}, // Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T + {0x1C34, 0x1C35, prExtend}, // Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG + {0x1C36, 0x1C37, prExtend}, // Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA + {0x1C3B, 0x1C3C, prSTerm}, // Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL + {0x1C40, 0x1C49, prNumeric}, // Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE + {0x1C4D, 0x1C4F, prOLetter}, // Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA + {0x1C50, 0x1C59, prNumeric}, // Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE + {0x1C5A, 0x1C77, prOLetter}, // Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH + {0x1C78, 0x1C7D, prOLetter}, // Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD + {0x1C7E, 0x1C7F, prSTerm}, // Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD + {0x1C80, 0x1C88, prLower}, // L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK + {0x1C90, 0x1CBA, prOLetter}, // L& [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN + {0x1CBD, 0x1CBF, prOLetter}, // L& [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN + {0x1CD0, 0x1CD2, prExtend}, // Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA + {0x1CD4, 0x1CE0, prExtend}, // Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA + {0x1CE1, 0x1CE1, prExtend}, // Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA + {0x1CE2, 0x1CE8, prExtend}, // Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL + {0x1CE9, 0x1CEC, prOLetter}, // Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL + {0x1CED, 0x1CED, prExtend}, // Mn VEDIC SIGN TIRYAK + {0x1CEE, 0x1CF3, prOLetter}, // Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA + {0x1CF4, 0x1CF4, prExtend}, // Mn VEDIC TONE CANDRA ABOVE + {0x1CF5, 0x1CF6, prOLetter}, // Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA + {0x1CF7, 0x1CF7, prExtend}, // Mc VEDIC SIGN ATIKRAMA + {0x1CF8, 0x1CF9, prExtend}, // Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE + {0x1CFA, 0x1CFA, prOLetter}, // Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA + {0x1D00, 0x1D2B, prLower}, // L& [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL + {0x1D2C, 0x1D6A, prLower}, // Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI + {0x1D6B, 0x1D77, prLower}, // L& [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G + {0x1D78, 0x1D78, prLower}, // Lm MODIFIER LETTER CYRILLIC EN + {0x1D79, 0x1D9A, prLower}, // L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK + {0x1D9B, 0x1DBF, prLower}, // Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA + {0x1DC0, 0x1DFF, prExtend}, // Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x1E00, 0x1E00, prUpper}, // L& LATIN CAPITAL LETTER A WITH RING BELOW + {0x1E01, 0x1E01, prLower}, // L& LATIN SMALL LETTER A WITH RING BELOW + {0x1E02, 0x1E02, prUpper}, // L& LATIN CAPITAL LETTER B WITH DOT ABOVE + {0x1E03, 0x1E03, prLower}, // L& LATIN SMALL LETTER B WITH DOT ABOVE + {0x1E04, 0x1E04, prUpper}, // L& LATIN CAPITAL LETTER B WITH DOT BELOW + {0x1E05, 0x1E05, prLower}, // L& LATIN SMALL LETTER B WITH DOT BELOW + {0x1E06, 0x1E06, prUpper}, // L& LATIN CAPITAL LETTER B WITH LINE BELOW + {0x1E07, 0x1E07, prLower}, // L& LATIN SMALL LETTER B WITH LINE BELOW + {0x1E08, 0x1E08, prUpper}, // L& LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE + {0x1E09, 0x1E09, prLower}, // L& LATIN SMALL LETTER C WITH CEDILLA AND ACUTE + {0x1E0A, 0x1E0A, prUpper}, // L& LATIN CAPITAL LETTER D WITH DOT ABOVE + {0x1E0B, 0x1E0B, prLower}, // L& LATIN SMALL LETTER D WITH DOT ABOVE + {0x1E0C, 0x1E0C, prUpper}, // L& LATIN CAPITAL LETTER D WITH DOT BELOW + {0x1E0D, 0x1E0D, prLower}, // L& LATIN SMALL LETTER D WITH DOT BELOW + {0x1E0E, 0x1E0E, prUpper}, // L& LATIN CAPITAL LETTER D WITH LINE BELOW + {0x1E0F, 0x1E0F, prLower}, // L& LATIN SMALL LETTER D WITH LINE BELOW + {0x1E10, 0x1E10, prUpper}, // L& LATIN CAPITAL LETTER D WITH CEDILLA + {0x1E11, 0x1E11, prLower}, // L& LATIN SMALL LETTER D WITH CEDILLA + {0x1E12, 0x1E12, prUpper}, // L& LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW + {0x1E13, 0x1E13, prLower}, // L& LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW + {0x1E14, 0x1E14, prUpper}, // L& LATIN CAPITAL LETTER E WITH MACRON AND GRAVE + {0x1E15, 0x1E15, prLower}, // L& LATIN SMALL LETTER E WITH MACRON AND GRAVE + {0x1E16, 0x1E16, prUpper}, // L& LATIN CAPITAL LETTER E WITH MACRON AND ACUTE + {0x1E17, 0x1E17, prLower}, // L& LATIN SMALL LETTER E WITH MACRON AND ACUTE + {0x1E18, 0x1E18, prUpper}, // L& LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW + {0x1E19, 0x1E19, prLower}, // L& LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW + {0x1E1A, 0x1E1A, prUpper}, // L& LATIN CAPITAL LETTER E WITH TILDE BELOW + {0x1E1B, 0x1E1B, prLower}, // L& LATIN SMALL LETTER E WITH TILDE BELOW + {0x1E1C, 0x1E1C, prUpper}, // L& LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE + {0x1E1D, 0x1E1D, prLower}, // L& LATIN SMALL LETTER E WITH CEDILLA AND BREVE + {0x1E1E, 0x1E1E, prUpper}, // L& LATIN CAPITAL LETTER F WITH DOT ABOVE + {0x1E1F, 0x1E1F, prLower}, // L& LATIN SMALL LETTER F WITH DOT ABOVE + {0x1E20, 0x1E20, prUpper}, // L& LATIN CAPITAL LETTER G WITH MACRON + {0x1E21, 0x1E21, prLower}, // L& LATIN SMALL LETTER G WITH MACRON + {0x1E22, 0x1E22, prUpper}, // L& LATIN CAPITAL LETTER H WITH DOT ABOVE + {0x1E23, 0x1E23, prLower}, // L& LATIN SMALL LETTER H WITH DOT ABOVE + {0x1E24, 0x1E24, prUpper}, // L& LATIN CAPITAL LETTER H WITH DOT BELOW + {0x1E25, 0x1E25, prLower}, // L& LATIN SMALL LETTER H WITH DOT BELOW + {0x1E26, 0x1E26, prUpper}, // L& LATIN CAPITAL LETTER H WITH DIAERESIS + {0x1E27, 0x1E27, prLower}, // L& LATIN SMALL LETTER H WITH DIAERESIS + {0x1E28, 0x1E28, prUpper}, // L& LATIN CAPITAL LETTER H WITH CEDILLA + {0x1E29, 0x1E29, prLower}, // L& LATIN SMALL LETTER H WITH CEDILLA + {0x1E2A, 0x1E2A, prUpper}, // L& LATIN CAPITAL LETTER H WITH BREVE BELOW + {0x1E2B, 0x1E2B, prLower}, // L& LATIN SMALL LETTER H WITH BREVE BELOW + {0x1E2C, 0x1E2C, prUpper}, // L& LATIN CAPITAL LETTER I WITH TILDE BELOW + {0x1E2D, 0x1E2D, prLower}, // L& LATIN SMALL LETTER I WITH TILDE BELOW + {0x1E2E, 0x1E2E, prUpper}, // L& LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE + {0x1E2F, 0x1E2F, prLower}, // L& LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE + {0x1E30, 0x1E30, prUpper}, // L& LATIN CAPITAL LETTER K WITH ACUTE + {0x1E31, 0x1E31, prLower}, // L& LATIN SMALL LETTER K WITH ACUTE + {0x1E32, 0x1E32, prUpper}, // L& LATIN CAPITAL LETTER K WITH DOT BELOW + {0x1E33, 0x1E33, prLower}, // L& LATIN SMALL LETTER K WITH DOT BELOW + {0x1E34, 0x1E34, prUpper}, // L& LATIN CAPITAL LETTER K WITH LINE BELOW + {0x1E35, 0x1E35, prLower}, // L& LATIN SMALL LETTER K WITH LINE BELOW + {0x1E36, 0x1E36, prUpper}, // L& LATIN CAPITAL LETTER L WITH DOT BELOW + {0x1E37, 0x1E37, prLower}, // L& LATIN SMALL LETTER L WITH DOT BELOW + {0x1E38, 0x1E38, prUpper}, // L& LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON + {0x1E39, 0x1E39, prLower}, // L& LATIN SMALL LETTER L WITH DOT BELOW AND MACRON + {0x1E3A, 0x1E3A, prUpper}, // L& LATIN CAPITAL LETTER L WITH LINE BELOW + {0x1E3B, 0x1E3B, prLower}, // L& LATIN SMALL LETTER L WITH LINE BELOW + {0x1E3C, 0x1E3C, prUpper}, // L& LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW + {0x1E3D, 0x1E3D, prLower}, // L& LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW + {0x1E3E, 0x1E3E, prUpper}, // L& LATIN CAPITAL LETTER M WITH ACUTE + {0x1E3F, 0x1E3F, prLower}, // L& LATIN SMALL LETTER M WITH ACUTE + {0x1E40, 0x1E40, prUpper}, // L& LATIN CAPITAL LETTER M WITH DOT ABOVE + {0x1E41, 0x1E41, prLower}, // L& LATIN SMALL LETTER M WITH DOT ABOVE + {0x1E42, 0x1E42, prUpper}, // L& LATIN CAPITAL LETTER M WITH DOT BELOW + {0x1E43, 0x1E43, prLower}, // L& LATIN SMALL LETTER M WITH DOT BELOW + {0x1E44, 0x1E44, prUpper}, // L& LATIN CAPITAL LETTER N WITH DOT ABOVE + {0x1E45, 0x1E45, prLower}, // L& LATIN SMALL LETTER N WITH DOT ABOVE + {0x1E46, 0x1E46, prUpper}, // L& LATIN CAPITAL LETTER N WITH DOT BELOW + {0x1E47, 0x1E47, prLower}, // L& LATIN SMALL LETTER N WITH DOT BELOW + {0x1E48, 0x1E48, prUpper}, // L& LATIN CAPITAL LETTER N WITH LINE BELOW + {0x1E49, 0x1E49, prLower}, // L& LATIN SMALL LETTER N WITH LINE BELOW + {0x1E4A, 0x1E4A, prUpper}, // L& LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW + {0x1E4B, 0x1E4B, prLower}, // L& LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW + {0x1E4C, 0x1E4C, prUpper}, // L& LATIN CAPITAL LETTER O WITH TILDE AND ACUTE + {0x1E4D, 0x1E4D, prLower}, // L& LATIN SMALL LETTER O WITH TILDE AND ACUTE + {0x1E4E, 0x1E4E, prUpper}, // L& LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS + {0x1E4F, 0x1E4F, prLower}, // L& LATIN SMALL LETTER O WITH TILDE AND DIAERESIS + {0x1E50, 0x1E50, prUpper}, // L& LATIN CAPITAL LETTER O WITH MACRON AND GRAVE + {0x1E51, 0x1E51, prLower}, // L& LATIN SMALL LETTER O WITH MACRON AND GRAVE + {0x1E52, 0x1E52, prUpper}, // L& LATIN CAPITAL LETTER O WITH MACRON AND ACUTE + {0x1E53, 0x1E53, prLower}, // L& LATIN SMALL LETTER O WITH MACRON AND ACUTE + {0x1E54, 0x1E54, prUpper}, // L& LATIN CAPITAL LETTER P WITH ACUTE + {0x1E55, 0x1E55, prLower}, // L& LATIN SMALL LETTER P WITH ACUTE + {0x1E56, 0x1E56, prUpper}, // L& LATIN CAPITAL LETTER P WITH DOT ABOVE + {0x1E57, 0x1E57, prLower}, // L& LATIN SMALL LETTER P WITH DOT ABOVE + {0x1E58, 0x1E58, prUpper}, // L& LATIN CAPITAL LETTER R WITH DOT ABOVE + {0x1E59, 0x1E59, prLower}, // L& LATIN SMALL LETTER R WITH DOT ABOVE + {0x1E5A, 0x1E5A, prUpper}, // L& LATIN CAPITAL LETTER R WITH DOT BELOW + {0x1E5B, 0x1E5B, prLower}, // L& LATIN SMALL LETTER R WITH DOT BELOW + {0x1E5C, 0x1E5C, prUpper}, // L& LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON + {0x1E5D, 0x1E5D, prLower}, // L& LATIN SMALL LETTER R WITH DOT BELOW AND MACRON + {0x1E5E, 0x1E5E, prUpper}, // L& LATIN CAPITAL LETTER R WITH LINE BELOW + {0x1E5F, 0x1E5F, prLower}, // L& LATIN SMALL LETTER R WITH LINE BELOW + {0x1E60, 0x1E60, prUpper}, // L& LATIN CAPITAL LETTER S WITH DOT ABOVE + {0x1E61, 0x1E61, prLower}, // L& LATIN SMALL LETTER S WITH DOT ABOVE + {0x1E62, 0x1E62, prUpper}, // L& LATIN CAPITAL LETTER S WITH DOT BELOW + {0x1E63, 0x1E63, prLower}, // L& LATIN SMALL LETTER S WITH DOT BELOW + {0x1E64, 0x1E64, prUpper}, // L& LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE + {0x1E65, 0x1E65, prLower}, // L& LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE + {0x1E66, 0x1E66, prUpper}, // L& LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE + {0x1E67, 0x1E67, prLower}, // L& LATIN SMALL LETTER S WITH CARON AND DOT ABOVE + {0x1E68, 0x1E68, prUpper}, // L& LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE + {0x1E69, 0x1E69, prLower}, // L& LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE + {0x1E6A, 0x1E6A, prUpper}, // L& LATIN CAPITAL LETTER T WITH DOT ABOVE + {0x1E6B, 0x1E6B, prLower}, // L& LATIN SMALL LETTER T WITH DOT ABOVE + {0x1E6C, 0x1E6C, prUpper}, // L& LATIN CAPITAL LETTER T WITH DOT BELOW + {0x1E6D, 0x1E6D, prLower}, // L& LATIN SMALL LETTER T WITH DOT BELOW + {0x1E6E, 0x1E6E, prUpper}, // L& LATIN CAPITAL LETTER T WITH LINE BELOW + {0x1E6F, 0x1E6F, prLower}, // L& LATIN SMALL LETTER T WITH LINE BELOW + {0x1E70, 0x1E70, prUpper}, // L& LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW + {0x1E71, 0x1E71, prLower}, // L& LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW + {0x1E72, 0x1E72, prUpper}, // L& LATIN CAPITAL LETTER U WITH DIAERESIS BELOW + {0x1E73, 0x1E73, prLower}, // L& LATIN SMALL LETTER U WITH DIAERESIS BELOW + {0x1E74, 0x1E74, prUpper}, // L& LATIN CAPITAL LETTER U WITH TILDE BELOW + {0x1E75, 0x1E75, prLower}, // L& LATIN SMALL LETTER U WITH TILDE BELOW + {0x1E76, 0x1E76, prUpper}, // L& LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW + {0x1E77, 0x1E77, prLower}, // L& LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW + {0x1E78, 0x1E78, prUpper}, // L& LATIN CAPITAL LETTER U WITH TILDE AND ACUTE + {0x1E79, 0x1E79, prLower}, // L& LATIN SMALL LETTER U WITH TILDE AND ACUTE + {0x1E7A, 0x1E7A, prUpper}, // L& LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS + {0x1E7B, 0x1E7B, prLower}, // L& LATIN SMALL LETTER U WITH MACRON AND DIAERESIS + {0x1E7C, 0x1E7C, prUpper}, // L& LATIN CAPITAL LETTER V WITH TILDE + {0x1E7D, 0x1E7D, prLower}, // L& LATIN SMALL LETTER V WITH TILDE + {0x1E7E, 0x1E7E, prUpper}, // L& LATIN CAPITAL LETTER V WITH DOT BELOW + {0x1E7F, 0x1E7F, prLower}, // L& LATIN SMALL LETTER V WITH DOT BELOW + {0x1E80, 0x1E80, prUpper}, // L& LATIN CAPITAL LETTER W WITH GRAVE + {0x1E81, 0x1E81, prLower}, // L& LATIN SMALL LETTER W WITH GRAVE + {0x1E82, 0x1E82, prUpper}, // L& LATIN CAPITAL LETTER W WITH ACUTE + {0x1E83, 0x1E83, prLower}, // L& LATIN SMALL LETTER W WITH ACUTE + {0x1E84, 0x1E84, prUpper}, // L& LATIN CAPITAL LETTER W WITH DIAERESIS + {0x1E85, 0x1E85, prLower}, // L& LATIN SMALL LETTER W WITH DIAERESIS + {0x1E86, 0x1E86, prUpper}, // L& LATIN CAPITAL LETTER W WITH DOT ABOVE + {0x1E87, 0x1E87, prLower}, // L& LATIN SMALL LETTER W WITH DOT ABOVE + {0x1E88, 0x1E88, prUpper}, // L& LATIN CAPITAL LETTER W WITH DOT BELOW + {0x1E89, 0x1E89, prLower}, // L& LATIN SMALL LETTER W WITH DOT BELOW + {0x1E8A, 0x1E8A, prUpper}, // L& LATIN CAPITAL LETTER X WITH DOT ABOVE + {0x1E8B, 0x1E8B, prLower}, // L& LATIN SMALL LETTER X WITH DOT ABOVE + {0x1E8C, 0x1E8C, prUpper}, // L& LATIN CAPITAL LETTER X WITH DIAERESIS + {0x1E8D, 0x1E8D, prLower}, // L& LATIN SMALL LETTER X WITH DIAERESIS + {0x1E8E, 0x1E8E, prUpper}, // L& LATIN CAPITAL LETTER Y WITH DOT ABOVE + {0x1E8F, 0x1E8F, prLower}, // L& LATIN SMALL LETTER Y WITH DOT ABOVE + {0x1E90, 0x1E90, prUpper}, // L& LATIN CAPITAL LETTER Z WITH CIRCUMFLEX + {0x1E91, 0x1E91, prLower}, // L& LATIN SMALL LETTER Z WITH CIRCUMFLEX + {0x1E92, 0x1E92, prUpper}, // L& LATIN CAPITAL LETTER Z WITH DOT BELOW + {0x1E93, 0x1E93, prLower}, // L& LATIN SMALL LETTER Z WITH DOT BELOW + {0x1E94, 0x1E94, prUpper}, // L& LATIN CAPITAL LETTER Z WITH LINE BELOW + {0x1E95, 0x1E9D, prLower}, // L& [9] LATIN SMALL LETTER Z WITH LINE BELOW..LATIN SMALL LETTER LONG S WITH HIGH STROKE + {0x1E9E, 0x1E9E, prUpper}, // L& LATIN CAPITAL LETTER SHARP S + {0x1E9F, 0x1E9F, prLower}, // L& LATIN SMALL LETTER DELTA + {0x1EA0, 0x1EA0, prUpper}, // L& LATIN CAPITAL LETTER A WITH DOT BELOW + {0x1EA1, 0x1EA1, prLower}, // L& LATIN SMALL LETTER A WITH DOT BELOW + {0x1EA2, 0x1EA2, prUpper}, // L& LATIN CAPITAL LETTER A WITH HOOK ABOVE + {0x1EA3, 0x1EA3, prLower}, // L& LATIN SMALL LETTER A WITH HOOK ABOVE + {0x1EA4, 0x1EA4, prUpper}, // L& LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE + {0x1EA5, 0x1EA5, prLower}, // L& LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE + {0x1EA6, 0x1EA6, prUpper}, // L& LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE + {0x1EA7, 0x1EA7, prLower}, // L& LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE + {0x1EA8, 0x1EA8, prUpper}, // L& LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE + {0x1EA9, 0x1EA9, prLower}, // L& LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE + {0x1EAA, 0x1EAA, prUpper}, // L& LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE + {0x1EAB, 0x1EAB, prLower}, // L& LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE + {0x1EAC, 0x1EAC, prUpper}, // L& LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW + {0x1EAD, 0x1EAD, prLower}, // L& LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW + {0x1EAE, 0x1EAE, prUpper}, // L& LATIN CAPITAL LETTER A WITH BREVE AND ACUTE + {0x1EAF, 0x1EAF, prLower}, // L& LATIN SMALL LETTER A WITH BREVE AND ACUTE + {0x1EB0, 0x1EB0, prUpper}, // L& LATIN CAPITAL LETTER A WITH BREVE AND GRAVE + {0x1EB1, 0x1EB1, prLower}, // L& LATIN SMALL LETTER A WITH BREVE AND GRAVE + {0x1EB2, 0x1EB2, prUpper}, // L& LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE + {0x1EB3, 0x1EB3, prLower}, // L& LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE + {0x1EB4, 0x1EB4, prUpper}, // L& LATIN CAPITAL LETTER A WITH BREVE AND TILDE + {0x1EB5, 0x1EB5, prLower}, // L& LATIN SMALL LETTER A WITH BREVE AND TILDE + {0x1EB6, 0x1EB6, prUpper}, // L& LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW + {0x1EB7, 0x1EB7, prLower}, // L& LATIN SMALL LETTER A WITH BREVE AND DOT BELOW + {0x1EB8, 0x1EB8, prUpper}, // L& LATIN CAPITAL LETTER E WITH DOT BELOW + {0x1EB9, 0x1EB9, prLower}, // L& LATIN SMALL LETTER E WITH DOT BELOW + {0x1EBA, 0x1EBA, prUpper}, // L& LATIN CAPITAL LETTER E WITH HOOK ABOVE + {0x1EBB, 0x1EBB, prLower}, // L& LATIN SMALL LETTER E WITH HOOK ABOVE + {0x1EBC, 0x1EBC, prUpper}, // L& LATIN CAPITAL LETTER E WITH TILDE + {0x1EBD, 0x1EBD, prLower}, // L& LATIN SMALL LETTER E WITH TILDE + {0x1EBE, 0x1EBE, prUpper}, // L& LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE + {0x1EBF, 0x1EBF, prLower}, // L& LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE + {0x1EC0, 0x1EC0, prUpper}, // L& LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE + {0x1EC1, 0x1EC1, prLower}, // L& LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE + {0x1EC2, 0x1EC2, prUpper}, // L& LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE + {0x1EC3, 0x1EC3, prLower}, // L& LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE + {0x1EC4, 0x1EC4, prUpper}, // L& LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE + {0x1EC5, 0x1EC5, prLower}, // L& LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE + {0x1EC6, 0x1EC6, prUpper}, // L& LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW + {0x1EC7, 0x1EC7, prLower}, // L& LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW + {0x1EC8, 0x1EC8, prUpper}, // L& LATIN CAPITAL LETTER I WITH HOOK ABOVE + {0x1EC9, 0x1EC9, prLower}, // L& LATIN SMALL LETTER I WITH HOOK ABOVE + {0x1ECA, 0x1ECA, prUpper}, // L& LATIN CAPITAL LETTER I WITH DOT BELOW + {0x1ECB, 0x1ECB, prLower}, // L& LATIN SMALL LETTER I WITH DOT BELOW + {0x1ECC, 0x1ECC, prUpper}, // L& LATIN CAPITAL LETTER O WITH DOT BELOW + {0x1ECD, 0x1ECD, prLower}, // L& LATIN SMALL LETTER O WITH DOT BELOW + {0x1ECE, 0x1ECE, prUpper}, // L& LATIN CAPITAL LETTER O WITH HOOK ABOVE + {0x1ECF, 0x1ECF, prLower}, // L& LATIN SMALL LETTER O WITH HOOK ABOVE + {0x1ED0, 0x1ED0, prUpper}, // L& LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE + {0x1ED1, 0x1ED1, prLower}, // L& LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE + {0x1ED2, 0x1ED2, prUpper}, // L& LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE + {0x1ED3, 0x1ED3, prLower}, // L& LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE + {0x1ED4, 0x1ED4, prUpper}, // L& LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE + {0x1ED5, 0x1ED5, prLower}, // L& LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE + {0x1ED6, 0x1ED6, prUpper}, // L& LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE + {0x1ED7, 0x1ED7, prLower}, // L& LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE + {0x1ED8, 0x1ED8, prUpper}, // L& LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW + {0x1ED9, 0x1ED9, prLower}, // L& LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW + {0x1EDA, 0x1EDA, prUpper}, // L& LATIN CAPITAL LETTER O WITH HORN AND ACUTE + {0x1EDB, 0x1EDB, prLower}, // L& LATIN SMALL LETTER O WITH HORN AND ACUTE + {0x1EDC, 0x1EDC, prUpper}, // L& LATIN CAPITAL LETTER O WITH HORN AND GRAVE + {0x1EDD, 0x1EDD, prLower}, // L& LATIN SMALL LETTER O WITH HORN AND GRAVE + {0x1EDE, 0x1EDE, prUpper}, // L& LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE + {0x1EDF, 0x1EDF, prLower}, // L& LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE + {0x1EE0, 0x1EE0, prUpper}, // L& LATIN CAPITAL LETTER O WITH HORN AND TILDE + {0x1EE1, 0x1EE1, prLower}, // L& LATIN SMALL LETTER O WITH HORN AND TILDE + {0x1EE2, 0x1EE2, prUpper}, // L& LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW + {0x1EE3, 0x1EE3, prLower}, // L& LATIN SMALL LETTER O WITH HORN AND DOT BELOW + {0x1EE4, 0x1EE4, prUpper}, // L& LATIN CAPITAL LETTER U WITH DOT BELOW + {0x1EE5, 0x1EE5, prLower}, // L& LATIN SMALL LETTER U WITH DOT BELOW + {0x1EE6, 0x1EE6, prUpper}, // L& LATIN CAPITAL LETTER U WITH HOOK ABOVE + {0x1EE7, 0x1EE7, prLower}, // L& LATIN SMALL LETTER U WITH HOOK ABOVE + {0x1EE8, 0x1EE8, prUpper}, // L& LATIN CAPITAL LETTER U WITH HORN AND ACUTE + {0x1EE9, 0x1EE9, prLower}, // L& LATIN SMALL LETTER U WITH HORN AND ACUTE + {0x1EEA, 0x1EEA, prUpper}, // L& LATIN CAPITAL LETTER U WITH HORN AND GRAVE + {0x1EEB, 0x1EEB, prLower}, // L& LATIN SMALL LETTER U WITH HORN AND GRAVE + {0x1EEC, 0x1EEC, prUpper}, // L& LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE + {0x1EED, 0x1EED, prLower}, // L& LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE + {0x1EEE, 0x1EEE, prUpper}, // L& LATIN CAPITAL LETTER U WITH HORN AND TILDE + {0x1EEF, 0x1EEF, prLower}, // L& LATIN SMALL LETTER U WITH HORN AND TILDE + {0x1EF0, 0x1EF0, prUpper}, // L& LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW + {0x1EF1, 0x1EF1, prLower}, // L& LATIN SMALL LETTER U WITH HORN AND DOT BELOW + {0x1EF2, 0x1EF2, prUpper}, // L& LATIN CAPITAL LETTER Y WITH GRAVE + {0x1EF3, 0x1EF3, prLower}, // L& LATIN SMALL LETTER Y WITH GRAVE + {0x1EF4, 0x1EF4, prUpper}, // L& LATIN CAPITAL LETTER Y WITH DOT BELOW + {0x1EF5, 0x1EF5, prLower}, // L& LATIN SMALL LETTER Y WITH DOT BELOW + {0x1EF6, 0x1EF6, prUpper}, // L& LATIN CAPITAL LETTER Y WITH HOOK ABOVE + {0x1EF7, 0x1EF7, prLower}, // L& LATIN SMALL LETTER Y WITH HOOK ABOVE + {0x1EF8, 0x1EF8, prUpper}, // L& LATIN CAPITAL LETTER Y WITH TILDE + {0x1EF9, 0x1EF9, prLower}, // L& LATIN SMALL LETTER Y WITH TILDE + {0x1EFA, 0x1EFA, prUpper}, // L& LATIN CAPITAL LETTER MIDDLE-WELSH LL + {0x1EFB, 0x1EFB, prLower}, // L& LATIN SMALL LETTER MIDDLE-WELSH LL + {0x1EFC, 0x1EFC, prUpper}, // L& LATIN CAPITAL LETTER MIDDLE-WELSH V + {0x1EFD, 0x1EFD, prLower}, // L& LATIN SMALL LETTER MIDDLE-WELSH V + {0x1EFE, 0x1EFE, prUpper}, // L& LATIN CAPITAL LETTER Y WITH LOOP + {0x1EFF, 0x1F07, prLower}, // L& [9] LATIN SMALL LETTER Y WITH LOOP..GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI + {0x1F08, 0x1F0F, prUpper}, // L& [8] GREEK CAPITAL LETTER ALPHA WITH PSILI..GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI + {0x1F10, 0x1F15, prLower}, // L& [6] GREEK SMALL LETTER EPSILON WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA + {0x1F18, 0x1F1D, prUpper}, // L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA + {0x1F20, 0x1F27, prLower}, // L& [8] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI + {0x1F28, 0x1F2F, prUpper}, // L& [8] GREEK CAPITAL LETTER ETA WITH PSILI..GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI + {0x1F30, 0x1F37, prLower}, // L& [8] GREEK SMALL LETTER IOTA WITH PSILI..GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI + {0x1F38, 0x1F3F, prUpper}, // L& [8] GREEK CAPITAL LETTER IOTA WITH PSILI..GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI + {0x1F40, 0x1F45, prLower}, // L& [6] GREEK SMALL LETTER OMICRON WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA + {0x1F48, 0x1F4D, prUpper}, // L& [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA + {0x1F50, 0x1F57, prLower}, // L& [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI + {0x1F59, 0x1F59, prUpper}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA + {0x1F5B, 0x1F5B, prUpper}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA + {0x1F5D, 0x1F5D, prUpper}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA + {0x1F5F, 0x1F5F, prUpper}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI + {0x1F60, 0x1F67, prLower}, // L& [8] GREEK SMALL LETTER OMEGA WITH PSILI..GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI + {0x1F68, 0x1F6F, prUpper}, // L& [8] GREEK CAPITAL LETTER OMEGA WITH PSILI..GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI + {0x1F70, 0x1F7D, prLower}, // L& [14] GREEK SMALL LETTER ALPHA WITH VARIA..GREEK SMALL LETTER OMEGA WITH OXIA + {0x1F80, 0x1F87, prLower}, // L& [8] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI + {0x1F88, 0x1F8F, prUpper}, // L& [8] GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI..GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + {0x1F90, 0x1F97, prLower}, // L& [8] GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI + {0x1F98, 0x1F9F, prUpper}, // L& [8] GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI..GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + {0x1FA0, 0x1FA7, prLower}, // L& [8] GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI + {0x1FA8, 0x1FAF, prUpper}, // L& [8] GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI..GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + {0x1FB0, 0x1FB4, prLower}, // L& [5] GREEK SMALL LETTER ALPHA WITH VRACHY..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI + {0x1FB6, 0x1FB7, prLower}, // L& [2] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI + {0x1FB8, 0x1FBC, prUpper}, // L& [5] GREEK CAPITAL LETTER ALPHA WITH VRACHY..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI + {0x1FBE, 0x1FBE, prLower}, // L& GREEK PROSGEGRAMMENI + {0x1FC2, 0x1FC4, prLower}, // L& [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI + {0x1FC6, 0x1FC7, prLower}, // L& [2] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI + {0x1FC8, 0x1FCC, prUpper}, // L& [5] GREEK CAPITAL LETTER EPSILON WITH VARIA..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI + {0x1FD0, 0x1FD3, prLower}, // L& [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA + {0x1FD6, 0x1FD7, prLower}, // L& [2] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI + {0x1FD8, 0x1FDB, prUpper}, // L& [4] GREEK CAPITAL LETTER IOTA WITH VRACHY..GREEK CAPITAL LETTER IOTA WITH OXIA + {0x1FE0, 0x1FE7, prLower}, // L& [8] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI + {0x1FE8, 0x1FEC, prUpper}, // L& [5] GREEK CAPITAL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA + {0x1FF2, 0x1FF4, prLower}, // L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + {0x1FF6, 0x1FF7, prLower}, // L& [2] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI + {0x1FF8, 0x1FFC, prUpper}, // L& [5] GREEK CAPITAL LETTER OMICRON WITH VARIA..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + {0x2000, 0x200A, prSp}, // Zs [11] EN QUAD..HAIR SPACE + {0x200B, 0x200B, prFormat}, // Cf ZERO WIDTH SPACE + {0x200C, 0x200D, prExtend}, // Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER + {0x200E, 0x200F, prFormat}, // Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK + {0x2013, 0x2014, prSContinue}, // Pd [2] EN DASH..EM DASH + {0x2018, 0x2018, prClose}, // Pi LEFT SINGLE QUOTATION MARK + {0x2019, 0x2019, prClose}, // Pf RIGHT SINGLE QUOTATION MARK + {0x201A, 0x201A, prClose}, // Ps SINGLE LOW-9 QUOTATION MARK + {0x201B, 0x201C, prClose}, // Pi [2] SINGLE HIGH-REVERSED-9 QUOTATION MARK..LEFT DOUBLE QUOTATION MARK + {0x201D, 0x201D, prClose}, // Pf RIGHT DOUBLE QUOTATION MARK + {0x201E, 0x201E, prClose}, // Ps DOUBLE LOW-9 QUOTATION MARK + {0x201F, 0x201F, prClose}, // Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK + {0x2024, 0x2024, prATerm}, // Po ONE DOT LEADER + {0x2028, 0x2028, prSep}, // Zl LINE SEPARATOR + {0x2029, 0x2029, prSep}, // Zp PARAGRAPH SEPARATOR + {0x202A, 0x202E, prFormat}, // Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE + {0x202F, 0x202F, prSp}, // Zs NARROW NO-BREAK SPACE + {0x2039, 0x2039, prClose}, // Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK + {0x203A, 0x203A, prClose}, // Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + {0x203C, 0x203D, prSTerm}, // Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG + {0x2045, 0x2045, prClose}, // Ps LEFT SQUARE BRACKET WITH QUILL + {0x2046, 0x2046, prClose}, // Pe RIGHT SQUARE BRACKET WITH QUILL + {0x2047, 0x2049, prSTerm}, // Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK + {0x205F, 0x205F, prSp}, // Zs MEDIUM MATHEMATICAL SPACE + {0x2060, 0x2064, prFormat}, // Cf [5] WORD JOINER..INVISIBLE PLUS + {0x2066, 0x206F, prFormat}, // Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES + {0x2071, 0x2071, prLower}, // Lm SUPERSCRIPT LATIN SMALL LETTER I + {0x207D, 0x207D, prClose}, // Ps SUPERSCRIPT LEFT PARENTHESIS + {0x207E, 0x207E, prClose}, // Pe SUPERSCRIPT RIGHT PARENTHESIS + {0x207F, 0x207F, prLower}, // Lm SUPERSCRIPT LATIN SMALL LETTER N + {0x208D, 0x208D, prClose}, // Ps SUBSCRIPT LEFT PARENTHESIS + {0x208E, 0x208E, prClose}, // Pe SUBSCRIPT RIGHT PARENTHESIS + {0x2090, 0x209C, prLower}, // Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T + {0x20D0, 0x20DC, prExtend}, // Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE + {0x20DD, 0x20E0, prExtend}, // Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH + {0x20E1, 0x20E1, prExtend}, // Mn COMBINING LEFT RIGHT ARROW ABOVE + {0x20E2, 0x20E4, prExtend}, // Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE + {0x20E5, 0x20F0, prExtend}, // Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE + {0x2102, 0x2102, prUpper}, // L& DOUBLE-STRUCK CAPITAL C + {0x2107, 0x2107, prUpper}, // L& EULER CONSTANT + {0x210A, 0x210A, prLower}, // L& SCRIPT SMALL G + {0x210B, 0x210D, prUpper}, // L& [3] SCRIPT CAPITAL H..DOUBLE-STRUCK CAPITAL H + {0x210E, 0x210F, prLower}, // L& [2] PLANCK CONSTANT..PLANCK CONSTANT OVER TWO PI + {0x2110, 0x2112, prUpper}, // L& [3] SCRIPT CAPITAL I..SCRIPT CAPITAL L + {0x2113, 0x2113, prLower}, // L& SCRIPT SMALL L + {0x2115, 0x2115, prUpper}, // L& DOUBLE-STRUCK CAPITAL N + {0x2119, 0x211D, prUpper}, // L& [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R + {0x2124, 0x2124, prUpper}, // L& DOUBLE-STRUCK CAPITAL Z + {0x2126, 0x2126, prUpper}, // L& OHM SIGN + {0x2128, 0x2128, prUpper}, // L& BLACK-LETTER CAPITAL Z + {0x212A, 0x212D, prUpper}, // L& [4] KELVIN SIGN..BLACK-LETTER CAPITAL C + {0x212F, 0x212F, prLower}, // L& SCRIPT SMALL E + {0x2130, 0x2133, prUpper}, // L& [4] SCRIPT CAPITAL E..SCRIPT CAPITAL M + {0x2134, 0x2134, prLower}, // L& SCRIPT SMALL O + {0x2135, 0x2138, prOLetter}, // Lo [4] ALEF SYMBOL..DALET SYMBOL + {0x2139, 0x2139, prLower}, // L& INFORMATION SOURCE + {0x213C, 0x213D, prLower}, // L& [2] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK SMALL GAMMA + {0x213E, 0x213F, prUpper}, // L& [2] DOUBLE-STRUCK CAPITAL GAMMA..DOUBLE-STRUCK CAPITAL PI + {0x2145, 0x2145, prUpper}, // L& DOUBLE-STRUCK ITALIC CAPITAL D + {0x2146, 0x2149, prLower}, // L& [4] DOUBLE-STRUCK ITALIC SMALL D..DOUBLE-STRUCK ITALIC SMALL J + {0x214E, 0x214E, prLower}, // L& TURNED SMALL F + {0x2160, 0x216F, prUpper}, // Nl [16] ROMAN NUMERAL ONE..ROMAN NUMERAL ONE THOUSAND + {0x2170, 0x217F, prLower}, // Nl [16] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND + {0x2180, 0x2182, prOLetter}, // Nl [3] ROMAN NUMERAL ONE THOUSAND C D..ROMAN NUMERAL TEN THOUSAND + {0x2183, 0x2183, prUpper}, // L& ROMAN NUMERAL REVERSED ONE HUNDRED + {0x2184, 0x2184, prLower}, // L& LATIN SMALL LETTER REVERSED C + {0x2185, 0x2188, prOLetter}, // Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND + {0x2308, 0x2308, prClose}, // Ps LEFT CEILING + {0x2309, 0x2309, prClose}, // Pe RIGHT CEILING + {0x230A, 0x230A, prClose}, // Ps LEFT FLOOR + {0x230B, 0x230B, prClose}, // Pe RIGHT FLOOR + {0x2329, 0x2329, prClose}, // Ps LEFT-POINTING ANGLE BRACKET + {0x232A, 0x232A, prClose}, // Pe RIGHT-POINTING ANGLE BRACKET + {0x24B6, 0x24CF, prUpper}, // So [26] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN CAPITAL LETTER Z + {0x24D0, 0x24E9, prLower}, // So [26] CIRCLED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z + {0x275B, 0x2760, prClose}, // So [6] HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT..HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT + {0x2768, 0x2768, prClose}, // Ps MEDIUM LEFT PARENTHESIS ORNAMENT + {0x2769, 0x2769, prClose}, // Pe MEDIUM RIGHT PARENTHESIS ORNAMENT + {0x276A, 0x276A, prClose}, // Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT + {0x276B, 0x276B, prClose}, // Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT + {0x276C, 0x276C, prClose}, // Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT + {0x276D, 0x276D, prClose}, // Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT + {0x276E, 0x276E, prClose}, // Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT + {0x276F, 0x276F, prClose}, // Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT + {0x2770, 0x2770, prClose}, // Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT + {0x2771, 0x2771, prClose}, // Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT + {0x2772, 0x2772, prClose}, // Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT + {0x2773, 0x2773, prClose}, // Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT + {0x2774, 0x2774, prClose}, // Ps MEDIUM LEFT CURLY BRACKET ORNAMENT + {0x2775, 0x2775, prClose}, // Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT + {0x27C5, 0x27C5, prClose}, // Ps LEFT S-SHAPED BAG DELIMITER + {0x27C6, 0x27C6, prClose}, // Pe RIGHT S-SHAPED BAG DELIMITER + {0x27E6, 0x27E6, prClose}, // Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET + {0x27E7, 0x27E7, prClose}, // Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET + {0x27E8, 0x27E8, prClose}, // Ps MATHEMATICAL LEFT ANGLE BRACKET + {0x27E9, 0x27E9, prClose}, // Pe MATHEMATICAL RIGHT ANGLE BRACKET + {0x27EA, 0x27EA, prClose}, // Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET + {0x27EB, 0x27EB, prClose}, // Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET + {0x27EC, 0x27EC, prClose}, // Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET + {0x27ED, 0x27ED, prClose}, // Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET + {0x27EE, 0x27EE, prClose}, // Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS + {0x27EF, 0x27EF, prClose}, // Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS + {0x2983, 0x2983, prClose}, // Ps LEFT WHITE CURLY BRACKET + {0x2984, 0x2984, prClose}, // Pe RIGHT WHITE CURLY BRACKET + {0x2985, 0x2985, prClose}, // Ps LEFT WHITE PARENTHESIS + {0x2986, 0x2986, prClose}, // Pe RIGHT WHITE PARENTHESIS + {0x2987, 0x2987, prClose}, // Ps Z NOTATION LEFT IMAGE BRACKET + {0x2988, 0x2988, prClose}, // Pe Z NOTATION RIGHT IMAGE BRACKET + {0x2989, 0x2989, prClose}, // Ps Z NOTATION LEFT BINDING BRACKET + {0x298A, 0x298A, prClose}, // Pe Z NOTATION RIGHT BINDING BRACKET + {0x298B, 0x298B, prClose}, // Ps LEFT SQUARE BRACKET WITH UNDERBAR + {0x298C, 0x298C, prClose}, // Pe RIGHT SQUARE BRACKET WITH UNDERBAR + {0x298D, 0x298D, prClose}, // Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER + {0x298E, 0x298E, prClose}, // Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {0x298F, 0x298F, prClose}, // Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {0x2990, 0x2990, prClose}, // Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER + {0x2991, 0x2991, prClose}, // Ps LEFT ANGLE BRACKET WITH DOT + {0x2992, 0x2992, prClose}, // Pe RIGHT ANGLE BRACKET WITH DOT + {0x2993, 0x2993, prClose}, // Ps LEFT ARC LESS-THAN BRACKET + {0x2994, 0x2994, prClose}, // Pe RIGHT ARC GREATER-THAN BRACKET + {0x2995, 0x2995, prClose}, // Ps DOUBLE LEFT ARC GREATER-THAN BRACKET + {0x2996, 0x2996, prClose}, // Pe DOUBLE RIGHT ARC LESS-THAN BRACKET + {0x2997, 0x2997, prClose}, // Ps LEFT BLACK TORTOISE SHELL BRACKET + {0x2998, 0x2998, prClose}, // Pe RIGHT BLACK TORTOISE SHELL BRACKET + {0x29D8, 0x29D8, prClose}, // Ps LEFT WIGGLY FENCE + {0x29D9, 0x29D9, prClose}, // Pe RIGHT WIGGLY FENCE + {0x29DA, 0x29DA, prClose}, // Ps LEFT DOUBLE WIGGLY FENCE + {0x29DB, 0x29DB, prClose}, // Pe RIGHT DOUBLE WIGGLY FENCE + {0x29FC, 0x29FC, prClose}, // Ps LEFT-POINTING CURVED ANGLE BRACKET + {0x29FD, 0x29FD, prClose}, // Pe RIGHT-POINTING CURVED ANGLE BRACKET + {0x2C00, 0x2C2F, prUpper}, // L& [48] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI + {0x2C30, 0x2C5F, prLower}, // L& [48] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI + {0x2C60, 0x2C60, prUpper}, // L& LATIN CAPITAL LETTER L WITH DOUBLE BAR + {0x2C61, 0x2C61, prLower}, // L& LATIN SMALL LETTER L WITH DOUBLE BAR + {0x2C62, 0x2C64, prUpper}, // L& [3] LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LATIN CAPITAL LETTER R WITH TAIL + {0x2C65, 0x2C66, prLower}, // L& [2] LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE + {0x2C67, 0x2C67, prUpper}, // L& LATIN CAPITAL LETTER H WITH DESCENDER + {0x2C68, 0x2C68, prLower}, // L& LATIN SMALL LETTER H WITH DESCENDER + {0x2C69, 0x2C69, prUpper}, // L& LATIN CAPITAL LETTER K WITH DESCENDER + {0x2C6A, 0x2C6A, prLower}, // L& LATIN SMALL LETTER K WITH DESCENDER + {0x2C6B, 0x2C6B, prUpper}, // L& LATIN CAPITAL LETTER Z WITH DESCENDER + {0x2C6C, 0x2C6C, prLower}, // L& LATIN SMALL LETTER Z WITH DESCENDER + {0x2C6D, 0x2C70, prUpper}, // L& [4] LATIN CAPITAL LETTER ALPHA..LATIN CAPITAL LETTER TURNED ALPHA + {0x2C71, 0x2C71, prLower}, // L& LATIN SMALL LETTER V WITH RIGHT HOOK + {0x2C72, 0x2C72, prUpper}, // L& LATIN CAPITAL LETTER W WITH HOOK + {0x2C73, 0x2C74, prLower}, // L& [2] LATIN SMALL LETTER W WITH HOOK..LATIN SMALL LETTER V WITH CURL + {0x2C75, 0x2C75, prUpper}, // L& LATIN CAPITAL LETTER HALF H + {0x2C76, 0x2C7B, prLower}, // L& [6] LATIN SMALL LETTER HALF H..LATIN LETTER SMALL CAPITAL TURNED E + {0x2C7C, 0x2C7D, prLower}, // Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V + {0x2C7E, 0x2C80, prUpper}, // L& [3] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC CAPITAL LETTER ALFA + {0x2C81, 0x2C81, prLower}, // L& COPTIC SMALL LETTER ALFA + {0x2C82, 0x2C82, prUpper}, // L& COPTIC CAPITAL LETTER VIDA + {0x2C83, 0x2C83, prLower}, // L& COPTIC SMALL LETTER VIDA + {0x2C84, 0x2C84, prUpper}, // L& COPTIC CAPITAL LETTER GAMMA + {0x2C85, 0x2C85, prLower}, // L& COPTIC SMALL LETTER GAMMA + {0x2C86, 0x2C86, prUpper}, // L& COPTIC CAPITAL LETTER DALDA + {0x2C87, 0x2C87, prLower}, // L& COPTIC SMALL LETTER DALDA + {0x2C88, 0x2C88, prUpper}, // L& COPTIC CAPITAL LETTER EIE + {0x2C89, 0x2C89, prLower}, // L& COPTIC SMALL LETTER EIE + {0x2C8A, 0x2C8A, prUpper}, // L& COPTIC CAPITAL LETTER SOU + {0x2C8B, 0x2C8B, prLower}, // L& COPTIC SMALL LETTER SOU + {0x2C8C, 0x2C8C, prUpper}, // L& COPTIC CAPITAL LETTER ZATA + {0x2C8D, 0x2C8D, prLower}, // L& COPTIC SMALL LETTER ZATA + {0x2C8E, 0x2C8E, prUpper}, // L& COPTIC CAPITAL LETTER HATE + {0x2C8F, 0x2C8F, prLower}, // L& COPTIC SMALL LETTER HATE + {0x2C90, 0x2C90, prUpper}, // L& COPTIC CAPITAL LETTER THETHE + {0x2C91, 0x2C91, prLower}, // L& COPTIC SMALL LETTER THETHE + {0x2C92, 0x2C92, prUpper}, // L& COPTIC CAPITAL LETTER IAUDA + {0x2C93, 0x2C93, prLower}, // L& COPTIC SMALL LETTER IAUDA + {0x2C94, 0x2C94, prUpper}, // L& COPTIC CAPITAL LETTER KAPA + {0x2C95, 0x2C95, prLower}, // L& COPTIC SMALL LETTER KAPA + {0x2C96, 0x2C96, prUpper}, // L& COPTIC CAPITAL LETTER LAULA + {0x2C97, 0x2C97, prLower}, // L& COPTIC SMALL LETTER LAULA + {0x2C98, 0x2C98, prUpper}, // L& COPTIC CAPITAL LETTER MI + {0x2C99, 0x2C99, prLower}, // L& COPTIC SMALL LETTER MI + {0x2C9A, 0x2C9A, prUpper}, // L& COPTIC CAPITAL LETTER NI + {0x2C9B, 0x2C9B, prLower}, // L& COPTIC SMALL LETTER NI + {0x2C9C, 0x2C9C, prUpper}, // L& COPTIC CAPITAL LETTER KSI + {0x2C9D, 0x2C9D, prLower}, // L& COPTIC SMALL LETTER KSI + {0x2C9E, 0x2C9E, prUpper}, // L& COPTIC CAPITAL LETTER O + {0x2C9F, 0x2C9F, prLower}, // L& COPTIC SMALL LETTER O + {0x2CA0, 0x2CA0, prUpper}, // L& COPTIC CAPITAL LETTER PI + {0x2CA1, 0x2CA1, prLower}, // L& COPTIC SMALL LETTER PI + {0x2CA2, 0x2CA2, prUpper}, // L& COPTIC CAPITAL LETTER RO + {0x2CA3, 0x2CA3, prLower}, // L& COPTIC SMALL LETTER RO + {0x2CA4, 0x2CA4, prUpper}, // L& COPTIC CAPITAL LETTER SIMA + {0x2CA5, 0x2CA5, prLower}, // L& COPTIC SMALL LETTER SIMA + {0x2CA6, 0x2CA6, prUpper}, // L& COPTIC CAPITAL LETTER TAU + {0x2CA7, 0x2CA7, prLower}, // L& COPTIC SMALL LETTER TAU + {0x2CA8, 0x2CA8, prUpper}, // L& COPTIC CAPITAL LETTER UA + {0x2CA9, 0x2CA9, prLower}, // L& COPTIC SMALL LETTER UA + {0x2CAA, 0x2CAA, prUpper}, // L& COPTIC CAPITAL LETTER FI + {0x2CAB, 0x2CAB, prLower}, // L& COPTIC SMALL LETTER FI + {0x2CAC, 0x2CAC, prUpper}, // L& COPTIC CAPITAL LETTER KHI + {0x2CAD, 0x2CAD, prLower}, // L& COPTIC SMALL LETTER KHI + {0x2CAE, 0x2CAE, prUpper}, // L& COPTIC CAPITAL LETTER PSI + {0x2CAF, 0x2CAF, prLower}, // L& COPTIC SMALL LETTER PSI + {0x2CB0, 0x2CB0, prUpper}, // L& COPTIC CAPITAL LETTER OOU + {0x2CB1, 0x2CB1, prLower}, // L& COPTIC SMALL LETTER OOU + {0x2CB2, 0x2CB2, prUpper}, // L& COPTIC CAPITAL LETTER DIALECT-P ALEF + {0x2CB3, 0x2CB3, prLower}, // L& COPTIC SMALL LETTER DIALECT-P ALEF + {0x2CB4, 0x2CB4, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC AIN + {0x2CB5, 0x2CB5, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC AIN + {0x2CB6, 0x2CB6, prUpper}, // L& COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE + {0x2CB7, 0x2CB7, prLower}, // L& COPTIC SMALL LETTER CRYPTOGRAMMIC EIE + {0x2CB8, 0x2CB8, prUpper}, // L& COPTIC CAPITAL LETTER DIALECT-P KAPA + {0x2CB9, 0x2CB9, prLower}, // L& COPTIC SMALL LETTER DIALECT-P KAPA + {0x2CBA, 0x2CBA, prUpper}, // L& COPTIC CAPITAL LETTER DIALECT-P NI + {0x2CBB, 0x2CBB, prLower}, // L& COPTIC SMALL LETTER DIALECT-P NI + {0x2CBC, 0x2CBC, prUpper}, // L& COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI + {0x2CBD, 0x2CBD, prLower}, // L& COPTIC SMALL LETTER CRYPTOGRAMMIC NI + {0x2CBE, 0x2CBE, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC OOU + {0x2CBF, 0x2CBF, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC OOU + {0x2CC0, 0x2CC0, prUpper}, // L& COPTIC CAPITAL LETTER SAMPI + {0x2CC1, 0x2CC1, prLower}, // L& COPTIC SMALL LETTER SAMPI + {0x2CC2, 0x2CC2, prUpper}, // L& COPTIC CAPITAL LETTER CROSSED SHEI + {0x2CC3, 0x2CC3, prLower}, // L& COPTIC SMALL LETTER CROSSED SHEI + {0x2CC4, 0x2CC4, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC SHEI + {0x2CC5, 0x2CC5, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC SHEI + {0x2CC6, 0x2CC6, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC ESH + {0x2CC7, 0x2CC7, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC ESH + {0x2CC8, 0x2CC8, prUpper}, // L& COPTIC CAPITAL LETTER AKHMIMIC KHEI + {0x2CC9, 0x2CC9, prLower}, // L& COPTIC SMALL LETTER AKHMIMIC KHEI + {0x2CCA, 0x2CCA, prUpper}, // L& COPTIC CAPITAL LETTER DIALECT-P HORI + {0x2CCB, 0x2CCB, prLower}, // L& COPTIC SMALL LETTER DIALECT-P HORI + {0x2CCC, 0x2CCC, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC HORI + {0x2CCD, 0x2CCD, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC HORI + {0x2CCE, 0x2CCE, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC HA + {0x2CCF, 0x2CCF, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC HA + {0x2CD0, 0x2CD0, prUpper}, // L& COPTIC CAPITAL LETTER L-SHAPED HA + {0x2CD1, 0x2CD1, prLower}, // L& COPTIC SMALL LETTER L-SHAPED HA + {0x2CD2, 0x2CD2, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC HEI + {0x2CD3, 0x2CD3, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC HEI + {0x2CD4, 0x2CD4, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC HAT + {0x2CD5, 0x2CD5, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC HAT + {0x2CD6, 0x2CD6, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC GANGIA + {0x2CD7, 0x2CD7, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC GANGIA + {0x2CD8, 0x2CD8, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC DJA + {0x2CD9, 0x2CD9, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC DJA + {0x2CDA, 0x2CDA, prUpper}, // L& COPTIC CAPITAL LETTER OLD COPTIC SHIMA + {0x2CDB, 0x2CDB, prLower}, // L& COPTIC SMALL LETTER OLD COPTIC SHIMA + {0x2CDC, 0x2CDC, prUpper}, // L& COPTIC CAPITAL LETTER OLD NUBIAN SHIMA + {0x2CDD, 0x2CDD, prLower}, // L& COPTIC SMALL LETTER OLD NUBIAN SHIMA + {0x2CDE, 0x2CDE, prUpper}, // L& COPTIC CAPITAL LETTER OLD NUBIAN NGI + {0x2CDF, 0x2CDF, prLower}, // L& COPTIC SMALL LETTER OLD NUBIAN NGI + {0x2CE0, 0x2CE0, prUpper}, // L& COPTIC CAPITAL LETTER OLD NUBIAN NYI + {0x2CE1, 0x2CE1, prLower}, // L& COPTIC SMALL LETTER OLD NUBIAN NYI + {0x2CE2, 0x2CE2, prUpper}, // L& COPTIC CAPITAL LETTER OLD NUBIAN WAU + {0x2CE3, 0x2CE4, prLower}, // L& [2] COPTIC SMALL LETTER OLD NUBIAN WAU..COPTIC SYMBOL KAI + {0x2CEB, 0x2CEB, prUpper}, // L& COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI + {0x2CEC, 0x2CEC, prLower}, // L& COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI + {0x2CED, 0x2CED, prUpper}, // L& COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA + {0x2CEE, 0x2CEE, prLower}, // L& COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA + {0x2CEF, 0x2CF1, prExtend}, // Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS + {0x2CF2, 0x2CF2, prUpper}, // L& COPTIC CAPITAL LETTER BOHAIRIC KHEI + {0x2CF3, 0x2CF3, prLower}, // L& COPTIC SMALL LETTER BOHAIRIC KHEI + {0x2D00, 0x2D25, prLower}, // L& [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE + {0x2D27, 0x2D27, prLower}, // L& GEORGIAN SMALL LETTER YN + {0x2D2D, 0x2D2D, prLower}, // L& GEORGIAN SMALL LETTER AEN + {0x2D30, 0x2D67, prOLetter}, // Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO + {0x2D6F, 0x2D6F, prOLetter}, // Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK + {0x2D7F, 0x2D7F, prExtend}, // Mn TIFINAGH CONSONANT JOINER + {0x2D80, 0x2D96, prOLetter}, // Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE + {0x2DA0, 0x2DA6, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO + {0x2DA8, 0x2DAE, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO + {0x2DB0, 0x2DB6, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO + {0x2DB8, 0x2DBE, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO + {0x2DC0, 0x2DC6, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO + {0x2DC8, 0x2DCE, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO + {0x2DD0, 0x2DD6, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO + {0x2DD8, 0x2DDE, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO + {0x2DE0, 0x2DFF, prExtend}, // Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS + {0x2E00, 0x2E01, prClose}, // Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER + {0x2E02, 0x2E02, prClose}, // Pi LEFT SUBSTITUTION BRACKET + {0x2E03, 0x2E03, prClose}, // Pf RIGHT SUBSTITUTION BRACKET + {0x2E04, 0x2E04, prClose}, // Pi LEFT DOTTED SUBSTITUTION BRACKET + {0x2E05, 0x2E05, prClose}, // Pf RIGHT DOTTED SUBSTITUTION BRACKET + {0x2E06, 0x2E08, prClose}, // Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER + {0x2E09, 0x2E09, prClose}, // Pi LEFT TRANSPOSITION BRACKET + {0x2E0A, 0x2E0A, prClose}, // Pf RIGHT TRANSPOSITION BRACKET + {0x2E0B, 0x2E0B, prClose}, // Po RAISED SQUARE + {0x2E0C, 0x2E0C, prClose}, // Pi LEFT RAISED OMISSION BRACKET + {0x2E0D, 0x2E0D, prClose}, // Pf RIGHT RAISED OMISSION BRACKET + {0x2E1C, 0x2E1C, prClose}, // Pi LEFT LOW PARAPHRASE BRACKET + {0x2E1D, 0x2E1D, prClose}, // Pf RIGHT LOW PARAPHRASE BRACKET + {0x2E20, 0x2E20, prClose}, // Pi LEFT VERTICAL BAR WITH QUILL + {0x2E21, 0x2E21, prClose}, // Pf RIGHT VERTICAL BAR WITH QUILL + {0x2E22, 0x2E22, prClose}, // Ps TOP LEFT HALF BRACKET + {0x2E23, 0x2E23, prClose}, // Pe TOP RIGHT HALF BRACKET + {0x2E24, 0x2E24, prClose}, // Ps BOTTOM LEFT HALF BRACKET + {0x2E25, 0x2E25, prClose}, // Pe BOTTOM RIGHT HALF BRACKET + {0x2E26, 0x2E26, prClose}, // Ps LEFT SIDEWAYS U BRACKET + {0x2E27, 0x2E27, prClose}, // Pe RIGHT SIDEWAYS U BRACKET + {0x2E28, 0x2E28, prClose}, // Ps LEFT DOUBLE PARENTHESIS + {0x2E29, 0x2E29, prClose}, // Pe RIGHT DOUBLE PARENTHESIS + {0x2E2E, 0x2E2E, prSTerm}, // Po REVERSED QUESTION MARK + {0x2E2F, 0x2E2F, prOLetter}, // Lm VERTICAL TILDE + {0x2E3C, 0x2E3C, prSTerm}, // Po STENOGRAPHIC FULL STOP + {0x2E42, 0x2E42, prClose}, // Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK + {0x2E53, 0x2E54, prSTerm}, // Po [2] MEDIEVAL EXCLAMATION MARK..MEDIEVAL QUESTION MARK + {0x2E55, 0x2E55, prClose}, // Ps LEFT SQUARE BRACKET WITH STROKE + {0x2E56, 0x2E56, prClose}, // Pe RIGHT SQUARE BRACKET WITH STROKE + {0x2E57, 0x2E57, prClose}, // Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE + {0x2E58, 0x2E58, prClose}, // Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE + {0x2E59, 0x2E59, prClose}, // Ps TOP HALF LEFT PARENTHESIS + {0x2E5A, 0x2E5A, prClose}, // Pe TOP HALF RIGHT PARENTHESIS + {0x2E5B, 0x2E5B, prClose}, // Ps BOTTOM HALF LEFT PARENTHESIS + {0x2E5C, 0x2E5C, prClose}, // Pe BOTTOM HALF RIGHT PARENTHESIS + {0x3000, 0x3000, prSp}, // Zs IDEOGRAPHIC SPACE + {0x3001, 0x3001, prSContinue}, // Po IDEOGRAPHIC COMMA + {0x3002, 0x3002, prSTerm}, // Po IDEOGRAPHIC FULL STOP + {0x3005, 0x3005, prOLetter}, // Lm IDEOGRAPHIC ITERATION MARK + {0x3006, 0x3006, prOLetter}, // Lo IDEOGRAPHIC CLOSING MARK + {0x3007, 0x3007, prOLetter}, // Nl IDEOGRAPHIC NUMBER ZERO + {0x3008, 0x3008, prClose}, // Ps LEFT ANGLE BRACKET + {0x3009, 0x3009, prClose}, // Pe RIGHT ANGLE BRACKET + {0x300A, 0x300A, prClose}, // Ps LEFT DOUBLE ANGLE BRACKET + {0x300B, 0x300B, prClose}, // Pe RIGHT DOUBLE ANGLE BRACKET + {0x300C, 0x300C, prClose}, // Ps LEFT CORNER BRACKET + {0x300D, 0x300D, prClose}, // Pe RIGHT CORNER BRACKET + {0x300E, 0x300E, prClose}, // Ps LEFT WHITE CORNER BRACKET + {0x300F, 0x300F, prClose}, // Pe RIGHT WHITE CORNER BRACKET + {0x3010, 0x3010, prClose}, // Ps LEFT BLACK LENTICULAR BRACKET + {0x3011, 0x3011, prClose}, // Pe RIGHT BLACK LENTICULAR BRACKET + {0x3014, 0x3014, prClose}, // Ps LEFT TORTOISE SHELL BRACKET + {0x3015, 0x3015, prClose}, // Pe RIGHT TORTOISE SHELL BRACKET + {0x3016, 0x3016, prClose}, // Ps LEFT WHITE LENTICULAR BRACKET + {0x3017, 0x3017, prClose}, // Pe RIGHT WHITE LENTICULAR BRACKET + {0x3018, 0x3018, prClose}, // Ps LEFT WHITE TORTOISE SHELL BRACKET + {0x3019, 0x3019, prClose}, // Pe RIGHT WHITE TORTOISE SHELL BRACKET + {0x301A, 0x301A, prClose}, // Ps LEFT WHITE SQUARE BRACKET + {0x301B, 0x301B, prClose}, // Pe RIGHT WHITE SQUARE BRACKET + {0x301D, 0x301D, prClose}, // Ps REVERSED DOUBLE PRIME QUOTATION MARK + {0x301E, 0x301F, prClose}, // Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK + {0x3021, 0x3029, prOLetter}, // Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE + {0x302A, 0x302D, prExtend}, // Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK + {0x302E, 0x302F, prExtend}, // Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK + {0x3031, 0x3035, prOLetter}, // Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF + {0x3038, 0x303A, prOLetter}, // Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY + {0x303B, 0x303B, prOLetter}, // Lm VERTICAL IDEOGRAPHIC ITERATION MARK + {0x303C, 0x303C, prOLetter}, // Lo MASU MARK + {0x3041, 0x3096, prOLetter}, // Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE + {0x3099, 0x309A, prExtend}, // Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x309D, 0x309E, prOLetter}, // Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK + {0x309F, 0x309F, prOLetter}, // Lo HIRAGANA DIGRAPH YORI + {0x30A1, 0x30FA, prOLetter}, // Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO + {0x30FC, 0x30FE, prOLetter}, // Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK + {0x30FF, 0x30FF, prOLetter}, // Lo KATAKANA DIGRAPH KOTO + {0x3105, 0x312F, prOLetter}, // Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN + {0x3131, 0x318E, prOLetter}, // Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE + {0x31A0, 0x31BF, prOLetter}, // Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH + {0x31F0, 0x31FF, prOLetter}, // Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO + {0x3400, 0x4DBF, prOLetter}, // Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF + {0x4E00, 0xA014, prOLetter}, // Lo [21013] CJK UNIFIED IDEOGRAPH-4E00..YI SYLLABLE E + {0xA015, 0xA015, prOLetter}, // Lm YI SYLLABLE WU + {0xA016, 0xA48C, prOLetter}, // Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR + {0xA4D0, 0xA4F7, prOLetter}, // Lo [40] LISU LETTER BA..LISU LETTER OE + {0xA4F8, 0xA4FD, prOLetter}, // Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU + {0xA4FF, 0xA4FF, prSTerm}, // Po LISU PUNCTUATION FULL STOP + {0xA500, 0xA60B, prOLetter}, // Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG + {0xA60C, 0xA60C, prOLetter}, // Lm VAI SYLLABLE LENGTHENER + {0xA60E, 0xA60F, prSTerm}, // Po [2] VAI FULL STOP..VAI QUESTION MARK + {0xA610, 0xA61F, prOLetter}, // Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG + {0xA620, 0xA629, prNumeric}, // Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE + {0xA62A, 0xA62B, prOLetter}, // Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO + {0xA640, 0xA640, prUpper}, // L& CYRILLIC CAPITAL LETTER ZEMLYA + {0xA641, 0xA641, prLower}, // L& CYRILLIC SMALL LETTER ZEMLYA + {0xA642, 0xA642, prUpper}, // L& CYRILLIC CAPITAL LETTER DZELO + {0xA643, 0xA643, prLower}, // L& CYRILLIC SMALL LETTER DZELO + {0xA644, 0xA644, prUpper}, // L& CYRILLIC CAPITAL LETTER REVERSED DZE + {0xA645, 0xA645, prLower}, // L& CYRILLIC SMALL LETTER REVERSED DZE + {0xA646, 0xA646, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTA + {0xA647, 0xA647, prLower}, // L& CYRILLIC SMALL LETTER IOTA + {0xA648, 0xA648, prUpper}, // L& CYRILLIC CAPITAL LETTER DJERV + {0xA649, 0xA649, prLower}, // L& CYRILLIC SMALL LETTER DJERV + {0xA64A, 0xA64A, prUpper}, // L& CYRILLIC CAPITAL LETTER MONOGRAPH UK + {0xA64B, 0xA64B, prLower}, // L& CYRILLIC SMALL LETTER MONOGRAPH UK + {0xA64C, 0xA64C, prUpper}, // L& CYRILLIC CAPITAL LETTER BROAD OMEGA + {0xA64D, 0xA64D, prLower}, // L& CYRILLIC SMALL LETTER BROAD OMEGA + {0xA64E, 0xA64E, prUpper}, // L& CYRILLIC CAPITAL LETTER NEUTRAL YER + {0xA64F, 0xA64F, prLower}, // L& CYRILLIC SMALL LETTER NEUTRAL YER + {0xA650, 0xA650, prUpper}, // L& CYRILLIC CAPITAL LETTER YERU WITH BACK YER + {0xA651, 0xA651, prLower}, // L& CYRILLIC SMALL LETTER YERU WITH BACK YER + {0xA652, 0xA652, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTIFIED YAT + {0xA653, 0xA653, prLower}, // L& CYRILLIC SMALL LETTER IOTIFIED YAT + {0xA654, 0xA654, prUpper}, // L& CYRILLIC CAPITAL LETTER REVERSED YU + {0xA655, 0xA655, prLower}, // L& CYRILLIC SMALL LETTER REVERSED YU + {0xA656, 0xA656, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTIFIED A + {0xA657, 0xA657, prLower}, // L& CYRILLIC SMALL LETTER IOTIFIED A + {0xA658, 0xA658, prUpper}, // L& CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS + {0xA659, 0xA659, prLower}, // L& CYRILLIC SMALL LETTER CLOSED LITTLE YUS + {0xA65A, 0xA65A, prUpper}, // L& CYRILLIC CAPITAL LETTER BLENDED YUS + {0xA65B, 0xA65B, prLower}, // L& CYRILLIC SMALL LETTER BLENDED YUS + {0xA65C, 0xA65C, prUpper}, // L& CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS + {0xA65D, 0xA65D, prLower}, // L& CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS + {0xA65E, 0xA65E, prUpper}, // L& CYRILLIC CAPITAL LETTER YN + {0xA65F, 0xA65F, prLower}, // L& CYRILLIC SMALL LETTER YN + {0xA660, 0xA660, prUpper}, // L& CYRILLIC CAPITAL LETTER REVERSED TSE + {0xA661, 0xA661, prLower}, // L& CYRILLIC SMALL LETTER REVERSED TSE + {0xA662, 0xA662, prUpper}, // L& CYRILLIC CAPITAL LETTER SOFT DE + {0xA663, 0xA663, prLower}, // L& CYRILLIC SMALL LETTER SOFT DE + {0xA664, 0xA664, prUpper}, // L& CYRILLIC CAPITAL LETTER SOFT EL + {0xA665, 0xA665, prLower}, // L& CYRILLIC SMALL LETTER SOFT EL + {0xA666, 0xA666, prUpper}, // L& CYRILLIC CAPITAL LETTER SOFT EM + {0xA667, 0xA667, prLower}, // L& CYRILLIC SMALL LETTER SOFT EM + {0xA668, 0xA668, prUpper}, // L& CYRILLIC CAPITAL LETTER MONOCULAR O + {0xA669, 0xA669, prLower}, // L& CYRILLIC SMALL LETTER MONOCULAR O + {0xA66A, 0xA66A, prUpper}, // L& CYRILLIC CAPITAL LETTER BINOCULAR O + {0xA66B, 0xA66B, prLower}, // L& CYRILLIC SMALL LETTER BINOCULAR O + {0xA66C, 0xA66C, prUpper}, // L& CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O + {0xA66D, 0xA66D, prLower}, // L& CYRILLIC SMALL LETTER DOUBLE MONOCULAR O + {0xA66E, 0xA66E, prOLetter}, // Lo CYRILLIC LETTER MULTIOCULAR O + {0xA66F, 0xA66F, prExtend}, // Mn COMBINING CYRILLIC VZMET + {0xA670, 0xA672, prExtend}, // Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN + {0xA674, 0xA67D, prExtend}, // Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK + {0xA67F, 0xA67F, prOLetter}, // Lm CYRILLIC PAYEROK + {0xA680, 0xA680, prUpper}, // L& CYRILLIC CAPITAL LETTER DWE + {0xA681, 0xA681, prLower}, // L& CYRILLIC SMALL LETTER DWE + {0xA682, 0xA682, prUpper}, // L& CYRILLIC CAPITAL LETTER DZWE + {0xA683, 0xA683, prLower}, // L& CYRILLIC SMALL LETTER DZWE + {0xA684, 0xA684, prUpper}, // L& CYRILLIC CAPITAL LETTER ZHWE + {0xA685, 0xA685, prLower}, // L& CYRILLIC SMALL LETTER ZHWE + {0xA686, 0xA686, prUpper}, // L& CYRILLIC CAPITAL LETTER CCHE + {0xA687, 0xA687, prLower}, // L& CYRILLIC SMALL LETTER CCHE + {0xA688, 0xA688, prUpper}, // L& CYRILLIC CAPITAL LETTER DZZE + {0xA689, 0xA689, prLower}, // L& CYRILLIC SMALL LETTER DZZE + {0xA68A, 0xA68A, prUpper}, // L& CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK + {0xA68B, 0xA68B, prLower}, // L& CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK + {0xA68C, 0xA68C, prUpper}, // L& CYRILLIC CAPITAL LETTER TWE + {0xA68D, 0xA68D, prLower}, // L& CYRILLIC SMALL LETTER TWE + {0xA68E, 0xA68E, prUpper}, // L& CYRILLIC CAPITAL LETTER TSWE + {0xA68F, 0xA68F, prLower}, // L& CYRILLIC SMALL LETTER TSWE + {0xA690, 0xA690, prUpper}, // L& CYRILLIC CAPITAL LETTER TSSE + {0xA691, 0xA691, prLower}, // L& CYRILLIC SMALL LETTER TSSE + {0xA692, 0xA692, prUpper}, // L& CYRILLIC CAPITAL LETTER TCHE + {0xA693, 0xA693, prLower}, // L& CYRILLIC SMALL LETTER TCHE + {0xA694, 0xA694, prUpper}, // L& CYRILLIC CAPITAL LETTER HWE + {0xA695, 0xA695, prLower}, // L& CYRILLIC SMALL LETTER HWE + {0xA696, 0xA696, prUpper}, // L& CYRILLIC CAPITAL LETTER SHWE + {0xA697, 0xA697, prLower}, // L& CYRILLIC SMALL LETTER SHWE + {0xA698, 0xA698, prUpper}, // L& CYRILLIC CAPITAL LETTER DOUBLE O + {0xA699, 0xA699, prLower}, // L& CYRILLIC SMALL LETTER DOUBLE O + {0xA69A, 0xA69A, prUpper}, // L& CYRILLIC CAPITAL LETTER CROSSED O + {0xA69B, 0xA69B, prLower}, // L& CYRILLIC SMALL LETTER CROSSED O + {0xA69C, 0xA69D, prLower}, // Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN + {0xA69E, 0xA69F, prExtend}, // Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E + {0xA6A0, 0xA6E5, prOLetter}, // Lo [70] BAMUM LETTER A..BAMUM LETTER KI + {0xA6E6, 0xA6EF, prOLetter}, // Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM + {0xA6F0, 0xA6F1, prExtend}, // Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS + {0xA6F3, 0xA6F3, prSTerm}, // Po BAMUM FULL STOP + {0xA6F7, 0xA6F7, prSTerm}, // Po BAMUM QUESTION MARK + {0xA717, 0xA71F, prOLetter}, // Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK + {0xA722, 0xA722, prUpper}, // L& LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF + {0xA723, 0xA723, prLower}, // L& LATIN SMALL LETTER EGYPTOLOGICAL ALEF + {0xA724, 0xA724, prUpper}, // L& LATIN CAPITAL LETTER EGYPTOLOGICAL AIN + {0xA725, 0xA725, prLower}, // L& LATIN SMALL LETTER EGYPTOLOGICAL AIN + {0xA726, 0xA726, prUpper}, // L& LATIN CAPITAL LETTER HENG + {0xA727, 0xA727, prLower}, // L& LATIN SMALL LETTER HENG + {0xA728, 0xA728, prUpper}, // L& LATIN CAPITAL LETTER TZ + {0xA729, 0xA729, prLower}, // L& LATIN SMALL LETTER TZ + {0xA72A, 0xA72A, prUpper}, // L& LATIN CAPITAL LETTER TRESILLO + {0xA72B, 0xA72B, prLower}, // L& LATIN SMALL LETTER TRESILLO + {0xA72C, 0xA72C, prUpper}, // L& LATIN CAPITAL LETTER CUATRILLO + {0xA72D, 0xA72D, prLower}, // L& LATIN SMALL LETTER CUATRILLO + {0xA72E, 0xA72E, prUpper}, // L& LATIN CAPITAL LETTER CUATRILLO WITH COMMA + {0xA72F, 0xA731, prLower}, // L& [3] LATIN SMALL LETTER CUATRILLO WITH COMMA..LATIN LETTER SMALL CAPITAL S + {0xA732, 0xA732, prUpper}, // L& LATIN CAPITAL LETTER AA + {0xA733, 0xA733, prLower}, // L& LATIN SMALL LETTER AA + {0xA734, 0xA734, prUpper}, // L& LATIN CAPITAL LETTER AO + {0xA735, 0xA735, prLower}, // L& LATIN SMALL LETTER AO + {0xA736, 0xA736, prUpper}, // L& LATIN CAPITAL LETTER AU + {0xA737, 0xA737, prLower}, // L& LATIN SMALL LETTER AU + {0xA738, 0xA738, prUpper}, // L& LATIN CAPITAL LETTER AV + {0xA739, 0xA739, prLower}, // L& LATIN SMALL LETTER AV + {0xA73A, 0xA73A, prUpper}, // L& LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR + {0xA73B, 0xA73B, prLower}, // L& LATIN SMALL LETTER AV WITH HORIZONTAL BAR + {0xA73C, 0xA73C, prUpper}, // L& LATIN CAPITAL LETTER AY + {0xA73D, 0xA73D, prLower}, // L& LATIN SMALL LETTER AY + {0xA73E, 0xA73E, prUpper}, // L& LATIN CAPITAL LETTER REVERSED C WITH DOT + {0xA73F, 0xA73F, prLower}, // L& LATIN SMALL LETTER REVERSED C WITH DOT + {0xA740, 0xA740, prUpper}, // L& LATIN CAPITAL LETTER K WITH STROKE + {0xA741, 0xA741, prLower}, // L& LATIN SMALL LETTER K WITH STROKE + {0xA742, 0xA742, prUpper}, // L& LATIN CAPITAL LETTER K WITH DIAGONAL STROKE + {0xA743, 0xA743, prLower}, // L& LATIN SMALL LETTER K WITH DIAGONAL STROKE + {0xA744, 0xA744, prUpper}, // L& LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE + {0xA745, 0xA745, prLower}, // L& LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE + {0xA746, 0xA746, prUpper}, // L& LATIN CAPITAL LETTER BROKEN L + {0xA747, 0xA747, prLower}, // L& LATIN SMALL LETTER BROKEN L + {0xA748, 0xA748, prUpper}, // L& LATIN CAPITAL LETTER L WITH HIGH STROKE + {0xA749, 0xA749, prLower}, // L& LATIN SMALL LETTER L WITH HIGH STROKE + {0xA74A, 0xA74A, prUpper}, // L& LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY + {0xA74B, 0xA74B, prLower}, // L& LATIN SMALL LETTER O WITH LONG STROKE OVERLAY + {0xA74C, 0xA74C, prUpper}, // L& LATIN CAPITAL LETTER O WITH LOOP + {0xA74D, 0xA74D, prLower}, // L& LATIN SMALL LETTER O WITH LOOP + {0xA74E, 0xA74E, prUpper}, // L& LATIN CAPITAL LETTER OO + {0xA74F, 0xA74F, prLower}, // L& LATIN SMALL LETTER OO + {0xA750, 0xA750, prUpper}, // L& LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER + {0xA751, 0xA751, prLower}, // L& LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER + {0xA752, 0xA752, prUpper}, // L& LATIN CAPITAL LETTER P WITH FLOURISH + {0xA753, 0xA753, prLower}, // L& LATIN SMALL LETTER P WITH FLOURISH + {0xA754, 0xA754, prUpper}, // L& LATIN CAPITAL LETTER P WITH SQUIRREL TAIL + {0xA755, 0xA755, prLower}, // L& LATIN SMALL LETTER P WITH SQUIRREL TAIL + {0xA756, 0xA756, prUpper}, // L& LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER + {0xA757, 0xA757, prLower}, // L& LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER + {0xA758, 0xA758, prUpper}, // L& LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE + {0xA759, 0xA759, prLower}, // L& LATIN SMALL LETTER Q WITH DIAGONAL STROKE + {0xA75A, 0xA75A, prUpper}, // L& LATIN CAPITAL LETTER R ROTUNDA + {0xA75B, 0xA75B, prLower}, // L& LATIN SMALL LETTER R ROTUNDA + {0xA75C, 0xA75C, prUpper}, // L& LATIN CAPITAL LETTER RUM ROTUNDA + {0xA75D, 0xA75D, prLower}, // L& LATIN SMALL LETTER RUM ROTUNDA + {0xA75E, 0xA75E, prUpper}, // L& LATIN CAPITAL LETTER V WITH DIAGONAL STROKE + {0xA75F, 0xA75F, prLower}, // L& LATIN SMALL LETTER V WITH DIAGONAL STROKE + {0xA760, 0xA760, prUpper}, // L& LATIN CAPITAL LETTER VY + {0xA761, 0xA761, prLower}, // L& LATIN SMALL LETTER VY + {0xA762, 0xA762, prUpper}, // L& LATIN CAPITAL LETTER VISIGOTHIC Z + {0xA763, 0xA763, prLower}, // L& LATIN SMALL LETTER VISIGOTHIC Z + {0xA764, 0xA764, prUpper}, // L& LATIN CAPITAL LETTER THORN WITH STROKE + {0xA765, 0xA765, prLower}, // L& LATIN SMALL LETTER THORN WITH STROKE + {0xA766, 0xA766, prUpper}, // L& LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER + {0xA767, 0xA767, prLower}, // L& LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER + {0xA768, 0xA768, prUpper}, // L& LATIN CAPITAL LETTER VEND + {0xA769, 0xA769, prLower}, // L& LATIN SMALL LETTER VEND + {0xA76A, 0xA76A, prUpper}, // L& LATIN CAPITAL LETTER ET + {0xA76B, 0xA76B, prLower}, // L& LATIN SMALL LETTER ET + {0xA76C, 0xA76C, prUpper}, // L& LATIN CAPITAL LETTER IS + {0xA76D, 0xA76D, prLower}, // L& LATIN SMALL LETTER IS + {0xA76E, 0xA76E, prUpper}, // L& LATIN CAPITAL LETTER CON + {0xA76F, 0xA76F, prLower}, // L& LATIN SMALL LETTER CON + {0xA770, 0xA770, prLower}, // Lm MODIFIER LETTER US + {0xA771, 0xA778, prLower}, // L& [8] LATIN SMALL LETTER DUM..LATIN SMALL LETTER UM + {0xA779, 0xA779, prUpper}, // L& LATIN CAPITAL LETTER INSULAR D + {0xA77A, 0xA77A, prLower}, // L& LATIN SMALL LETTER INSULAR D + {0xA77B, 0xA77B, prUpper}, // L& LATIN CAPITAL LETTER INSULAR F + {0xA77C, 0xA77C, prLower}, // L& LATIN SMALL LETTER INSULAR F + {0xA77D, 0xA77E, prUpper}, // L& [2] LATIN CAPITAL LETTER INSULAR G..LATIN CAPITAL LETTER TURNED INSULAR G + {0xA77F, 0xA77F, prLower}, // L& LATIN SMALL LETTER TURNED INSULAR G + {0xA780, 0xA780, prUpper}, // L& LATIN CAPITAL LETTER TURNED L + {0xA781, 0xA781, prLower}, // L& LATIN SMALL LETTER TURNED L + {0xA782, 0xA782, prUpper}, // L& LATIN CAPITAL LETTER INSULAR R + {0xA783, 0xA783, prLower}, // L& LATIN SMALL LETTER INSULAR R + {0xA784, 0xA784, prUpper}, // L& LATIN CAPITAL LETTER INSULAR S + {0xA785, 0xA785, prLower}, // L& LATIN SMALL LETTER INSULAR S + {0xA786, 0xA786, prUpper}, // L& LATIN CAPITAL LETTER INSULAR T + {0xA787, 0xA787, prLower}, // L& LATIN SMALL LETTER INSULAR T + {0xA788, 0xA788, prOLetter}, // Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT + {0xA78B, 0xA78B, prUpper}, // L& LATIN CAPITAL LETTER SALTILLO + {0xA78C, 0xA78C, prLower}, // L& LATIN SMALL LETTER SALTILLO + {0xA78D, 0xA78D, prUpper}, // L& LATIN CAPITAL LETTER TURNED H + {0xA78E, 0xA78E, prLower}, // L& LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT + {0xA78F, 0xA78F, prOLetter}, // Lo LATIN LETTER SINOLOGICAL DOT + {0xA790, 0xA790, prUpper}, // L& LATIN CAPITAL LETTER N WITH DESCENDER + {0xA791, 0xA791, prLower}, // L& LATIN SMALL LETTER N WITH DESCENDER + {0xA792, 0xA792, prUpper}, // L& LATIN CAPITAL LETTER C WITH BAR + {0xA793, 0xA795, prLower}, // L& [3] LATIN SMALL LETTER C WITH BAR..LATIN SMALL LETTER H WITH PALATAL HOOK + {0xA796, 0xA796, prUpper}, // L& LATIN CAPITAL LETTER B WITH FLOURISH + {0xA797, 0xA797, prLower}, // L& LATIN SMALL LETTER B WITH FLOURISH + {0xA798, 0xA798, prUpper}, // L& LATIN CAPITAL LETTER F WITH STROKE + {0xA799, 0xA799, prLower}, // L& LATIN SMALL LETTER F WITH STROKE + {0xA79A, 0xA79A, prUpper}, // L& LATIN CAPITAL LETTER VOLAPUK AE + {0xA79B, 0xA79B, prLower}, // L& LATIN SMALL LETTER VOLAPUK AE + {0xA79C, 0xA79C, prUpper}, // L& LATIN CAPITAL LETTER VOLAPUK OE + {0xA79D, 0xA79D, prLower}, // L& LATIN SMALL LETTER VOLAPUK OE + {0xA79E, 0xA79E, prUpper}, // L& LATIN CAPITAL LETTER VOLAPUK UE + {0xA79F, 0xA79F, prLower}, // L& LATIN SMALL LETTER VOLAPUK UE + {0xA7A0, 0xA7A0, prUpper}, // L& LATIN CAPITAL LETTER G WITH OBLIQUE STROKE + {0xA7A1, 0xA7A1, prLower}, // L& LATIN SMALL LETTER G WITH OBLIQUE STROKE + {0xA7A2, 0xA7A2, prUpper}, // L& LATIN CAPITAL LETTER K WITH OBLIQUE STROKE + {0xA7A3, 0xA7A3, prLower}, // L& LATIN SMALL LETTER K WITH OBLIQUE STROKE + {0xA7A4, 0xA7A4, prUpper}, // L& LATIN CAPITAL LETTER N WITH OBLIQUE STROKE + {0xA7A5, 0xA7A5, prLower}, // L& LATIN SMALL LETTER N WITH OBLIQUE STROKE + {0xA7A6, 0xA7A6, prUpper}, // L& LATIN CAPITAL LETTER R WITH OBLIQUE STROKE + {0xA7A7, 0xA7A7, prLower}, // L& LATIN SMALL LETTER R WITH OBLIQUE STROKE + {0xA7A8, 0xA7A8, prUpper}, // L& LATIN CAPITAL LETTER S WITH OBLIQUE STROKE + {0xA7A9, 0xA7A9, prLower}, // L& LATIN SMALL LETTER S WITH OBLIQUE STROKE + {0xA7AA, 0xA7AE, prUpper}, // L& [5] LATIN CAPITAL LETTER H WITH HOOK..LATIN CAPITAL LETTER SMALL CAPITAL I + {0xA7AF, 0xA7AF, prLower}, // L& LATIN LETTER SMALL CAPITAL Q + {0xA7B0, 0xA7B4, prUpper}, // L& [5] LATIN CAPITAL LETTER TURNED K..LATIN CAPITAL LETTER BETA + {0xA7B5, 0xA7B5, prLower}, // L& LATIN SMALL LETTER BETA + {0xA7B6, 0xA7B6, prUpper}, // L& LATIN CAPITAL LETTER OMEGA + {0xA7B7, 0xA7B7, prLower}, // L& LATIN SMALL LETTER OMEGA + {0xA7B8, 0xA7B8, prUpper}, // L& LATIN CAPITAL LETTER U WITH STROKE + {0xA7B9, 0xA7B9, prLower}, // L& LATIN SMALL LETTER U WITH STROKE + {0xA7BA, 0xA7BA, prUpper}, // L& LATIN CAPITAL LETTER GLOTTAL A + {0xA7BB, 0xA7BB, prLower}, // L& LATIN SMALL LETTER GLOTTAL A + {0xA7BC, 0xA7BC, prUpper}, // L& LATIN CAPITAL LETTER GLOTTAL I + {0xA7BD, 0xA7BD, prLower}, // L& LATIN SMALL LETTER GLOTTAL I + {0xA7BE, 0xA7BE, prUpper}, // L& LATIN CAPITAL LETTER GLOTTAL U + {0xA7BF, 0xA7BF, prLower}, // L& LATIN SMALL LETTER GLOTTAL U + {0xA7C0, 0xA7C0, prUpper}, // L& LATIN CAPITAL LETTER OLD POLISH O + {0xA7C1, 0xA7C1, prLower}, // L& LATIN SMALL LETTER OLD POLISH O + {0xA7C2, 0xA7C2, prUpper}, // L& LATIN CAPITAL LETTER ANGLICANA W + {0xA7C3, 0xA7C3, prLower}, // L& LATIN SMALL LETTER ANGLICANA W + {0xA7C4, 0xA7C7, prUpper}, // L& [4] LATIN CAPITAL LETTER C WITH PALATAL HOOK..LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY + {0xA7C8, 0xA7C8, prLower}, // L& LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY + {0xA7C9, 0xA7C9, prUpper}, // L& LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY + {0xA7CA, 0xA7CA, prLower}, // L& LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY + {0xA7D0, 0xA7D0, prUpper}, // L& LATIN CAPITAL LETTER CLOSED INSULAR G + {0xA7D1, 0xA7D1, prLower}, // L& LATIN SMALL LETTER CLOSED INSULAR G + {0xA7D3, 0xA7D3, prLower}, // L& LATIN SMALL LETTER DOUBLE THORN + {0xA7D5, 0xA7D5, prLower}, // L& LATIN SMALL LETTER DOUBLE WYNN + {0xA7D6, 0xA7D6, prUpper}, // L& LATIN CAPITAL LETTER MIDDLE SCOTS S + {0xA7D7, 0xA7D7, prLower}, // L& LATIN SMALL LETTER MIDDLE SCOTS S + {0xA7D8, 0xA7D8, prUpper}, // L& LATIN CAPITAL LETTER SIGMOID S + {0xA7D9, 0xA7D9, prLower}, // L& LATIN SMALL LETTER SIGMOID S + {0xA7F2, 0xA7F4, prLower}, // Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q + {0xA7F5, 0xA7F5, prUpper}, // L& LATIN CAPITAL LETTER REVERSED HALF H + {0xA7F6, 0xA7F6, prLower}, // L& LATIN SMALL LETTER REVERSED HALF H + {0xA7F7, 0xA7F7, prOLetter}, // Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I + {0xA7F8, 0xA7F9, prLower}, // Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE + {0xA7FA, 0xA7FA, prLower}, // L& LATIN LETTER SMALL CAPITAL TURNED M + {0xA7FB, 0xA801, prOLetter}, // Lo [7] LATIN EPIGRAPHIC LETTER REVERSED F..SYLOTI NAGRI LETTER I + {0xA802, 0xA802, prExtend}, // Mn SYLOTI NAGRI SIGN DVISVARA + {0xA803, 0xA805, prOLetter}, // Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O + {0xA806, 0xA806, prExtend}, // Mn SYLOTI NAGRI SIGN HASANTA + {0xA807, 0xA80A, prOLetter}, // Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO + {0xA80B, 0xA80B, prExtend}, // Mn SYLOTI NAGRI SIGN ANUSVARA + {0xA80C, 0xA822, prOLetter}, // Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO + {0xA823, 0xA824, prExtend}, // Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I + {0xA825, 0xA826, prExtend}, // Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E + {0xA827, 0xA827, prExtend}, // Mc SYLOTI NAGRI VOWEL SIGN OO + {0xA82C, 0xA82C, prExtend}, // Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA + {0xA840, 0xA873, prOLetter}, // Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU + {0xA876, 0xA877, prSTerm}, // Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD + {0xA880, 0xA881, prExtend}, // Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA + {0xA882, 0xA8B3, prOLetter}, // Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA + {0xA8B4, 0xA8C3, prExtend}, // Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU + {0xA8C4, 0xA8C5, prExtend}, // Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU + {0xA8CE, 0xA8CF, prSTerm}, // Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA + {0xA8D0, 0xA8D9, prNumeric}, // Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE + {0xA8E0, 0xA8F1, prExtend}, // Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA + {0xA8F2, 0xA8F7, prOLetter}, // Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA + {0xA8FB, 0xA8FB, prOLetter}, // Lo DEVANAGARI HEADSTROKE + {0xA8FD, 0xA8FE, prOLetter}, // Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY + {0xA8FF, 0xA8FF, prExtend}, // Mn DEVANAGARI VOWEL SIGN AY + {0xA900, 0xA909, prNumeric}, // Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE + {0xA90A, 0xA925, prOLetter}, // Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO + {0xA926, 0xA92D, prExtend}, // Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU + {0xA92F, 0xA92F, prSTerm}, // Po KAYAH LI SIGN SHYA + {0xA930, 0xA946, prOLetter}, // Lo [23] REJANG LETTER KA..REJANG LETTER A + {0xA947, 0xA951, prExtend}, // Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R + {0xA952, 0xA953, prExtend}, // Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA + {0xA960, 0xA97C, prOLetter}, // Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH + {0xA980, 0xA982, prExtend}, // Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR + {0xA983, 0xA983, prExtend}, // Mc JAVANESE SIGN WIGNYAN + {0xA984, 0xA9B2, prOLetter}, // Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA + {0xA9B3, 0xA9B3, prExtend}, // Mn JAVANESE SIGN CECAK TELU + {0xA9B4, 0xA9B5, prExtend}, // Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG + {0xA9B6, 0xA9B9, prExtend}, // Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT + {0xA9BA, 0xA9BB, prExtend}, // Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE + {0xA9BC, 0xA9BD, prExtend}, // Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET + {0xA9BE, 0xA9C0, prExtend}, // Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON + {0xA9C8, 0xA9C9, prSTerm}, // Po [2] JAVANESE PADA LINGSA..JAVANESE PADA LUNGSI + {0xA9CF, 0xA9CF, prOLetter}, // Lm JAVANESE PANGRANGKEP + {0xA9D0, 0xA9D9, prNumeric}, // Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE + {0xA9E0, 0xA9E4, prOLetter}, // Lo [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA + {0xA9E5, 0xA9E5, prExtend}, // Mn MYANMAR SIGN SHAN SAW + {0xA9E6, 0xA9E6, prOLetter}, // Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION + {0xA9E7, 0xA9EF, prOLetter}, // Lo [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA + {0xA9F0, 0xA9F9, prNumeric}, // Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE + {0xA9FA, 0xA9FE, prOLetter}, // Lo [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA + {0xAA00, 0xAA28, prOLetter}, // Lo [41] CHAM LETTER A..CHAM LETTER HA + {0xAA29, 0xAA2E, prExtend}, // Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE + {0xAA2F, 0xAA30, prExtend}, // Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI + {0xAA31, 0xAA32, prExtend}, // Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE + {0xAA33, 0xAA34, prExtend}, // Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA + {0xAA35, 0xAA36, prExtend}, // Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA + {0xAA40, 0xAA42, prOLetter}, // Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG + {0xAA43, 0xAA43, prExtend}, // Mn CHAM CONSONANT SIGN FINAL NG + {0xAA44, 0xAA4B, prOLetter}, // Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS + {0xAA4C, 0xAA4C, prExtend}, // Mn CHAM CONSONANT SIGN FINAL M + {0xAA4D, 0xAA4D, prExtend}, // Mc CHAM CONSONANT SIGN FINAL H + {0xAA50, 0xAA59, prNumeric}, // Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE + {0xAA5D, 0xAA5F, prSTerm}, // Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA + {0xAA60, 0xAA6F, prOLetter}, // Lo [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA + {0xAA70, 0xAA70, prOLetter}, // Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION + {0xAA71, 0xAA76, prOLetter}, // Lo [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM + {0xAA7A, 0xAA7A, prOLetter}, // Lo MYANMAR LETTER AITON RA + {0xAA7B, 0xAA7B, prExtend}, // Mc MYANMAR SIGN PAO KAREN TONE + {0xAA7C, 0xAA7C, prExtend}, // Mn MYANMAR SIGN TAI LAING TONE-2 + {0xAA7D, 0xAA7D, prExtend}, // Mc MYANMAR SIGN TAI LAING TONE-5 + {0xAA7E, 0xAAAF, prOLetter}, // Lo [50] MYANMAR LETTER SHWE PALAUNG CHA..TAI VIET LETTER HIGH O + {0xAAB0, 0xAAB0, prExtend}, // Mn TAI VIET MAI KANG + {0xAAB1, 0xAAB1, prOLetter}, // Lo TAI VIET VOWEL AA + {0xAAB2, 0xAAB4, prExtend}, // Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U + {0xAAB5, 0xAAB6, prOLetter}, // Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O + {0xAAB7, 0xAAB8, prExtend}, // Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA + {0xAAB9, 0xAABD, prOLetter}, // Lo [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN + {0xAABE, 0xAABF, prExtend}, // Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK + {0xAAC0, 0xAAC0, prOLetter}, // Lo TAI VIET TONE MAI NUENG + {0xAAC1, 0xAAC1, prExtend}, // Mn TAI VIET TONE MAI THO + {0xAAC2, 0xAAC2, prOLetter}, // Lo TAI VIET TONE MAI SONG + {0xAADB, 0xAADC, prOLetter}, // Lo [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG + {0xAADD, 0xAADD, prOLetter}, // Lm TAI VIET SYMBOL SAM + {0xAAE0, 0xAAEA, prOLetter}, // Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA + {0xAAEB, 0xAAEB, prExtend}, // Mc MEETEI MAYEK VOWEL SIGN II + {0xAAEC, 0xAAED, prExtend}, // Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI + {0xAAEE, 0xAAEF, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU + {0xAAF0, 0xAAF1, prSTerm}, // Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM + {0xAAF2, 0xAAF2, prOLetter}, // Lo MEETEI MAYEK ANJI + {0xAAF3, 0xAAF4, prOLetter}, // Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK + {0xAAF5, 0xAAF5, prExtend}, // Mc MEETEI MAYEK VOWEL SIGN VISARGA + {0xAAF6, 0xAAF6, prExtend}, // Mn MEETEI MAYEK VIRAMA + {0xAB01, 0xAB06, prOLetter}, // Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO + {0xAB09, 0xAB0E, prOLetter}, // Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO + {0xAB11, 0xAB16, prOLetter}, // Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO + {0xAB20, 0xAB26, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO + {0xAB28, 0xAB2E, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO + {0xAB30, 0xAB5A, prLower}, // L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG + {0xAB5C, 0xAB5F, prLower}, // Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK + {0xAB60, 0xAB68, prLower}, // L& [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE + {0xAB69, 0xAB69, prLower}, // Lm MODIFIER LETTER SMALL TURNED W + {0xAB70, 0xABBF, prLower}, // L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA + {0xABC0, 0xABE2, prOLetter}, // Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM + {0xABE3, 0xABE4, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP + {0xABE5, 0xABE5, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN ANAP + {0xABE6, 0xABE7, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP + {0xABE8, 0xABE8, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN UNAP + {0xABE9, 0xABEA, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG + {0xABEB, 0xABEB, prSTerm}, // Po MEETEI MAYEK CHEIKHEI + {0xABEC, 0xABEC, prExtend}, // Mc MEETEI MAYEK LUM IYEK + {0xABED, 0xABED, prExtend}, // Mn MEETEI MAYEK APUN IYEK + {0xABF0, 0xABF9, prNumeric}, // Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE + {0xAC00, 0xD7A3, prOLetter}, // Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH + {0xD7B0, 0xD7C6, prOLetter}, // Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E + {0xD7CB, 0xD7FB, prOLetter}, // Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH + {0xF900, 0xFA6D, prOLetter}, // Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D + {0xFA70, 0xFAD9, prOLetter}, // Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 + {0xFB00, 0xFB06, prLower}, // L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST + {0xFB13, 0xFB17, prLower}, // L& [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH + {0xFB1D, 0xFB1D, prOLetter}, // Lo HEBREW LETTER YOD WITH HIRIQ + {0xFB1E, 0xFB1E, prExtend}, // Mn HEBREW POINT JUDEO-SPANISH VARIKA + {0xFB1F, 0xFB28, prOLetter}, // Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV + {0xFB2A, 0xFB36, prOLetter}, // Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH + {0xFB38, 0xFB3C, prOLetter}, // Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH + {0xFB3E, 0xFB3E, prOLetter}, // Lo HEBREW LETTER MEM WITH DAGESH + {0xFB40, 0xFB41, prOLetter}, // Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH + {0xFB43, 0xFB44, prOLetter}, // Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH + {0xFB46, 0xFBB1, prOLetter}, // Lo [108] HEBREW LETTER TSADI WITH DAGESH..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM + {0xFBD3, 0xFD3D, prOLetter}, // Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM + {0xFD3E, 0xFD3E, prClose}, // Pe ORNATE LEFT PARENTHESIS + {0xFD3F, 0xFD3F, prClose}, // Ps ORNATE RIGHT PARENTHESIS + {0xFD50, 0xFD8F, prOLetter}, // Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM + {0xFD92, 0xFDC7, prOLetter}, // Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM + {0xFDF0, 0xFDFB, prOLetter}, // Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU + {0xFE00, 0xFE0F, prExtend}, // Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 + {0xFE10, 0xFE11, prSContinue}, // Po [2] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA + {0xFE13, 0xFE13, prSContinue}, // Po PRESENTATION FORM FOR VERTICAL COLON + {0xFE17, 0xFE17, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET + {0xFE18, 0xFE18, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET + {0xFE20, 0xFE2F, prExtend}, // Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + {0xFE31, 0xFE32, prSContinue}, // Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH + {0xFE35, 0xFE35, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS + {0xFE36, 0xFE36, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS + {0xFE37, 0xFE37, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET + {0xFE38, 0xFE38, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET + {0xFE39, 0xFE39, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET + {0xFE3A, 0xFE3A, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET + {0xFE3B, 0xFE3B, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET + {0xFE3C, 0xFE3C, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET + {0xFE3D, 0xFE3D, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET + {0xFE3E, 0xFE3E, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET + {0xFE3F, 0xFE3F, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET + {0xFE40, 0xFE40, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET + {0xFE41, 0xFE41, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET + {0xFE42, 0xFE42, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET + {0xFE43, 0xFE43, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET + {0xFE44, 0xFE44, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET + {0xFE47, 0xFE47, prClose}, // Ps PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET + {0xFE48, 0xFE48, prClose}, // Pe PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET + {0xFE50, 0xFE51, prSContinue}, // Po [2] SMALL COMMA..SMALL IDEOGRAPHIC COMMA + {0xFE52, 0xFE52, prATerm}, // Po SMALL FULL STOP + {0xFE55, 0xFE55, prSContinue}, // Po SMALL COLON + {0xFE56, 0xFE57, prSTerm}, // Po [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK + {0xFE58, 0xFE58, prSContinue}, // Pd SMALL EM DASH + {0xFE59, 0xFE59, prClose}, // Ps SMALL LEFT PARENTHESIS + {0xFE5A, 0xFE5A, prClose}, // Pe SMALL RIGHT PARENTHESIS + {0xFE5B, 0xFE5B, prClose}, // Ps SMALL LEFT CURLY BRACKET + {0xFE5C, 0xFE5C, prClose}, // Pe SMALL RIGHT CURLY BRACKET + {0xFE5D, 0xFE5D, prClose}, // Ps SMALL LEFT TORTOISE SHELL BRACKET + {0xFE5E, 0xFE5E, prClose}, // Pe SMALL RIGHT TORTOISE SHELL BRACKET + {0xFE63, 0xFE63, prSContinue}, // Pd SMALL HYPHEN-MINUS + {0xFE70, 0xFE74, prOLetter}, // Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM + {0xFE76, 0xFEFC, prOLetter}, // Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM + {0xFEFF, 0xFEFF, prFormat}, // Cf ZERO WIDTH NO-BREAK SPACE + {0xFF01, 0xFF01, prSTerm}, // Po FULLWIDTH EXCLAMATION MARK + {0xFF08, 0xFF08, prClose}, // Ps FULLWIDTH LEFT PARENTHESIS + {0xFF09, 0xFF09, prClose}, // Pe FULLWIDTH RIGHT PARENTHESIS + {0xFF0C, 0xFF0C, prSContinue}, // Po FULLWIDTH COMMA + {0xFF0D, 0xFF0D, prSContinue}, // Pd FULLWIDTH HYPHEN-MINUS + {0xFF0E, 0xFF0E, prATerm}, // Po FULLWIDTH FULL STOP + {0xFF10, 0xFF19, prNumeric}, // Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE + {0xFF1A, 0xFF1A, prSContinue}, // Po FULLWIDTH COLON + {0xFF1F, 0xFF1F, prSTerm}, // Po FULLWIDTH QUESTION MARK + {0xFF21, 0xFF3A, prUpper}, // L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z + {0xFF3B, 0xFF3B, prClose}, // Ps FULLWIDTH LEFT SQUARE BRACKET + {0xFF3D, 0xFF3D, prClose}, // Pe FULLWIDTH RIGHT SQUARE BRACKET + {0xFF41, 0xFF5A, prLower}, // L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z + {0xFF5B, 0xFF5B, prClose}, // Ps FULLWIDTH LEFT CURLY BRACKET + {0xFF5D, 0xFF5D, prClose}, // Pe FULLWIDTH RIGHT CURLY BRACKET + {0xFF5F, 0xFF5F, prClose}, // Ps FULLWIDTH LEFT WHITE PARENTHESIS + {0xFF60, 0xFF60, prClose}, // Pe FULLWIDTH RIGHT WHITE PARENTHESIS + {0xFF61, 0xFF61, prSTerm}, // Po HALFWIDTH IDEOGRAPHIC FULL STOP + {0xFF62, 0xFF62, prClose}, // Ps HALFWIDTH LEFT CORNER BRACKET + {0xFF63, 0xFF63, prClose}, // Pe HALFWIDTH RIGHT CORNER BRACKET + {0xFF64, 0xFF64, prSContinue}, // Po HALFWIDTH IDEOGRAPHIC COMMA + {0xFF66, 0xFF6F, prOLetter}, // Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU + {0xFF70, 0xFF70, prOLetter}, // Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK + {0xFF71, 0xFF9D, prOLetter}, // Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N + {0xFF9E, 0xFF9F, prExtend}, // Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + {0xFFA0, 0xFFBE, prOLetter}, // Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH + {0xFFC2, 0xFFC7, prOLetter}, // Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E + {0xFFCA, 0xFFCF, prOLetter}, // Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE + {0xFFD2, 0xFFD7, prOLetter}, // Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU + {0xFFDA, 0xFFDC, prOLetter}, // Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I + {0xFFF9, 0xFFFB, prFormat}, // Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR + {0x10000, 0x1000B, prOLetter}, // Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE + {0x1000D, 0x10026, prOLetter}, // Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO + {0x10028, 0x1003A, prOLetter}, // Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO + {0x1003C, 0x1003D, prOLetter}, // Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE + {0x1003F, 0x1004D, prOLetter}, // Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO + {0x10050, 0x1005D, prOLetter}, // Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089 + {0x10080, 0x100FA, prOLetter}, // Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305 + {0x10140, 0x10174, prOLetter}, // Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS + {0x101FD, 0x101FD, prExtend}, // Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE + {0x10280, 0x1029C, prOLetter}, // Lo [29] LYCIAN LETTER A..LYCIAN LETTER X + {0x102A0, 0x102D0, prOLetter}, // Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3 + {0x102E0, 0x102E0, prExtend}, // Mn COPTIC EPACT THOUSANDS MARK + {0x10300, 0x1031F, prOLetter}, // Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS + {0x1032D, 0x10340, prOLetter}, // Lo [20] OLD ITALIC LETTER YE..GOTHIC LETTER PAIRTHRA + {0x10341, 0x10341, prOLetter}, // Nl GOTHIC LETTER NINETY + {0x10342, 0x10349, prOLetter}, // Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL + {0x1034A, 0x1034A, prOLetter}, // Nl GOTHIC LETTER NINE HUNDRED + {0x10350, 0x10375, prOLetter}, // Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA + {0x10376, 0x1037A, prExtend}, // Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + {0x10380, 0x1039D, prOLetter}, // Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU + {0x103A0, 0x103C3, prOLetter}, // Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA + {0x103C8, 0x103CF, prOLetter}, // Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH + {0x103D1, 0x103D5, prOLetter}, // Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED + {0x10400, 0x10427, prUpper}, // L& [40] DESERET CAPITAL LETTER LONG I..DESERET CAPITAL LETTER EW + {0x10428, 0x1044F, prLower}, // L& [40] DESERET SMALL LETTER LONG I..DESERET SMALL LETTER EW + {0x10450, 0x1049D, prOLetter}, // Lo [78] SHAVIAN LETTER PEEP..OSMANYA LETTER OO + {0x104A0, 0x104A9, prNumeric}, // Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE + {0x104B0, 0x104D3, prUpper}, // L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA + {0x104D8, 0x104FB, prLower}, // L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + {0x10500, 0x10527, prOLetter}, // Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE + {0x10530, 0x10563, prOLetter}, // Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW + {0x10570, 0x1057A, prUpper}, // L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA + {0x1057C, 0x1058A, prUpper}, // L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE + {0x1058C, 0x10592, prUpper}, // L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE + {0x10594, 0x10595, prUpper}, // L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE + {0x10597, 0x105A1, prLower}, // L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA + {0x105A3, 0x105B1, prLower}, // L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE + {0x105B3, 0x105B9, prLower}, // L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE + {0x105BB, 0x105BC, prLower}, // L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE + {0x10600, 0x10736, prOLetter}, // Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 + {0x10740, 0x10755, prOLetter}, // Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE + {0x10760, 0x10767, prOLetter}, // Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 + {0x10780, 0x10780, prLower}, // Lm MODIFIER LETTER SMALL CAPITAL AA + {0x10781, 0x10782, prOLetter}, // Lm [2] MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON..MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON + {0x10783, 0x10785, prLower}, // Lm [3] MODIFIER LETTER SMALL AE..MODIFIER LETTER SMALL B WITH HOOK + {0x10787, 0x107B0, prLower}, // Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK + {0x107B2, 0x107BA, prLower}, // Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL + {0x10800, 0x10805, prOLetter}, // Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA + {0x10808, 0x10808, prOLetter}, // Lo CYPRIOT SYLLABLE JO + {0x1080A, 0x10835, prOLetter}, // Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO + {0x10837, 0x10838, prOLetter}, // Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE + {0x1083C, 0x1083C, prOLetter}, // Lo CYPRIOT SYLLABLE ZA + {0x1083F, 0x10855, prOLetter}, // Lo [23] CYPRIOT SYLLABLE ZO..IMPERIAL ARAMAIC LETTER TAW + {0x10860, 0x10876, prOLetter}, // Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW + {0x10880, 0x1089E, prOLetter}, // Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW + {0x108E0, 0x108F2, prOLetter}, // Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH + {0x108F4, 0x108F5, prOLetter}, // Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW + {0x10900, 0x10915, prOLetter}, // Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU + {0x10920, 0x10939, prOLetter}, // Lo [26] LYDIAN LETTER A..LYDIAN LETTER C + {0x10980, 0x109B7, prOLetter}, // Lo [56] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC CURSIVE LETTER DA + {0x109BE, 0x109BF, prOLetter}, // Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN + {0x10A00, 0x10A00, prOLetter}, // Lo KHAROSHTHI LETTER A + {0x10A01, 0x10A03, prExtend}, // Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R + {0x10A05, 0x10A06, prExtend}, // Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O + {0x10A0C, 0x10A0F, prExtend}, // Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA + {0x10A10, 0x10A13, prOLetter}, // Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA + {0x10A15, 0x10A17, prOLetter}, // Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA + {0x10A19, 0x10A35, prOLetter}, // Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA + {0x10A38, 0x10A3A, prExtend}, // Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW + {0x10A3F, 0x10A3F, prExtend}, // Mn KHAROSHTHI VIRAMA + {0x10A56, 0x10A57, prSTerm}, // Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA + {0x10A60, 0x10A7C, prOLetter}, // Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH + {0x10A80, 0x10A9C, prOLetter}, // Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH + {0x10AC0, 0x10AC7, prOLetter}, // Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW + {0x10AC9, 0x10AE4, prOLetter}, // Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW + {0x10AE5, 0x10AE6, prExtend}, // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW + {0x10B00, 0x10B35, prOLetter}, // Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE + {0x10B40, 0x10B55, prOLetter}, // Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW + {0x10B60, 0x10B72, prOLetter}, // Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW + {0x10B80, 0x10B91, prOLetter}, // Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW + {0x10C00, 0x10C48, prOLetter}, // Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH + {0x10C80, 0x10CB2, prUpper}, // L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US + {0x10CC0, 0x10CF2, prLower}, // L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US + {0x10D00, 0x10D23, prOLetter}, // Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA + {0x10D24, 0x10D27, prExtend}, // Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI + {0x10D30, 0x10D39, prNumeric}, // Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE + {0x10E80, 0x10EA9, prOLetter}, // Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET + {0x10EAB, 0x10EAC, prExtend}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK + {0x10EB0, 0x10EB1, prOLetter}, // Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prExtend}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA + {0x10F00, 0x10F1C, prOLetter}, // Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL + {0x10F27, 0x10F27, prOLetter}, // Lo OLD SOGDIAN LIGATURE AYIN-DALETH + {0x10F30, 0x10F45, prOLetter}, // Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN + {0x10F46, 0x10F50, prExtend}, // Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW + {0x10F55, 0x10F59, prSTerm}, // Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT + {0x10F70, 0x10F81, prOLetter}, // Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH + {0x10F82, 0x10F85, prExtend}, // Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW + {0x10F86, 0x10F89, prSTerm}, // Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS + {0x10FB0, 0x10FC4, prOLetter}, // Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW + {0x10FE0, 0x10FF6, prOLetter}, // Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH + {0x11000, 0x11000, prExtend}, // Mc BRAHMI SIGN CANDRABINDU + {0x11001, 0x11001, prExtend}, // Mn BRAHMI SIGN ANUSVARA + {0x11002, 0x11002, prExtend}, // Mc BRAHMI SIGN VISARGA + {0x11003, 0x11037, prOLetter}, // Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA + {0x11038, 0x11046, prExtend}, // Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA + {0x11047, 0x11048, prSTerm}, // Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA + {0x11066, 0x1106F, prNumeric}, // Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE + {0x11070, 0x11070, prExtend}, // Mn BRAHMI SIGN OLD TAMIL VIRAMA + {0x11071, 0x11072, prOLetter}, // Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O + {0x11073, 0x11074, prExtend}, // Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O + {0x11075, 0x11075, prOLetter}, // Lo BRAHMI LETTER OLD TAMIL LLA + {0x1107F, 0x11081, prExtend}, // Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA + {0x11082, 0x11082, prExtend}, // Mc KAITHI SIGN VISARGA + {0x11083, 0x110AF, prOLetter}, // Lo [45] KAITHI LETTER A..KAITHI LETTER HA + {0x110B0, 0x110B2, prExtend}, // Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II + {0x110B3, 0x110B6, prExtend}, // Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI + {0x110B7, 0x110B8, prExtend}, // Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU + {0x110B9, 0x110BA, prExtend}, // Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA + {0x110BD, 0x110BD, prFormat}, // Cf KAITHI NUMBER SIGN + {0x110BE, 0x110C1, prSTerm}, // Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA + {0x110C2, 0x110C2, prExtend}, // Mn KAITHI VOWEL SIGN VOCALIC R + {0x110CD, 0x110CD, prFormat}, // Cf KAITHI NUMBER SIGN ABOVE + {0x110D0, 0x110E8, prOLetter}, // Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE + {0x110F0, 0x110F9, prNumeric}, // Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE + {0x11100, 0x11102, prExtend}, // Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA + {0x11103, 0x11126, prOLetter}, // Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA + {0x11127, 0x1112B, prExtend}, // Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU + {0x1112C, 0x1112C, prExtend}, // Mc CHAKMA VOWEL SIGN E + {0x1112D, 0x11134, prExtend}, // Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA + {0x11136, 0x1113F, prNumeric}, // Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE + {0x11141, 0x11143, prSTerm}, // Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK + {0x11144, 0x11144, prOLetter}, // Lo CHAKMA LETTER LHAA + {0x11145, 0x11146, prExtend}, // Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI + {0x11147, 0x11147, prOLetter}, // Lo CHAKMA LETTER VAA + {0x11150, 0x11172, prOLetter}, // Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA + {0x11173, 0x11173, prExtend}, // Mn MAHAJANI SIGN NUKTA + {0x11176, 0x11176, prOLetter}, // Lo MAHAJANI LIGATURE SHRI + {0x11180, 0x11181, prExtend}, // Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA + {0x11182, 0x11182, prExtend}, // Mc SHARADA SIGN VISARGA + {0x11183, 0x111B2, prOLetter}, // Lo [48] SHARADA LETTER A..SHARADA LETTER HA + {0x111B3, 0x111B5, prExtend}, // Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II + {0x111B6, 0x111BE, prExtend}, // Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O + {0x111BF, 0x111C0, prExtend}, // Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA + {0x111C1, 0x111C4, prOLetter}, // Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM + {0x111C5, 0x111C6, prSTerm}, // Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA + {0x111C9, 0x111CC, prExtend}, // Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK + {0x111CD, 0x111CD, prSTerm}, // Po SHARADA SUTRA MARK + {0x111CE, 0x111CE, prExtend}, // Mc SHARADA VOWEL SIGN PRISHTHAMATRA E + {0x111CF, 0x111CF, prExtend}, // Mn SHARADA SIGN INVERTED CANDRABINDU + {0x111D0, 0x111D9, prNumeric}, // Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE + {0x111DA, 0x111DA, prOLetter}, // Lo SHARADA EKAM + {0x111DC, 0x111DC, prOLetter}, // Lo SHARADA HEADSTROKE + {0x111DE, 0x111DF, prSTerm}, // Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 + {0x11200, 0x11211, prOLetter}, // Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA + {0x11213, 0x1122B, prOLetter}, // Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA + {0x1122C, 0x1122E, prExtend}, // Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II + {0x1122F, 0x11231, prExtend}, // Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI + {0x11232, 0x11233, prExtend}, // Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU + {0x11234, 0x11234, prExtend}, // Mn KHOJKI SIGN ANUSVARA + {0x11235, 0x11235, prExtend}, // Mc KHOJKI SIGN VIRAMA + {0x11236, 0x11237, prExtend}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA + {0x11238, 0x11239, prSTerm}, // Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA + {0x1123B, 0x1123C, prSTerm}, // Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK + {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prOLetter}, // Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prExtend}, // Mn KHOJKI VOWEL SIGN VOCALIC R + {0x11280, 0x11286, prOLetter}, // Lo [7] MULTANI LETTER A..MULTANI LETTER GA + {0x11288, 0x11288, prOLetter}, // Lo MULTANI LETTER GHA + {0x1128A, 0x1128D, prOLetter}, // Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA + {0x1128F, 0x1129D, prOLetter}, // Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA + {0x1129F, 0x112A8, prOLetter}, // Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA + {0x112A9, 0x112A9, prSTerm}, // Po MULTANI SECTION MARK + {0x112B0, 0x112DE, prOLetter}, // Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA + {0x112DF, 0x112DF, prExtend}, // Mn KHUDAWADI SIGN ANUSVARA + {0x112E0, 0x112E2, prExtend}, // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II + {0x112E3, 0x112EA, prExtend}, // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA + {0x112F0, 0x112F9, prNumeric}, // Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE + {0x11300, 0x11301, prExtend}, // Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU + {0x11302, 0x11303, prExtend}, // Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA + {0x11305, 0x1130C, prOLetter}, // Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L + {0x1130F, 0x11310, prOLetter}, // Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI + {0x11313, 0x11328, prOLetter}, // Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA + {0x1132A, 0x11330, prOLetter}, // Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA + {0x11332, 0x11333, prOLetter}, // Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA + {0x11335, 0x11339, prOLetter}, // Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA + {0x1133B, 0x1133C, prExtend}, // Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA + {0x1133D, 0x1133D, prOLetter}, // Lo GRANTHA SIGN AVAGRAHA + {0x1133E, 0x1133F, prExtend}, // Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I + {0x11340, 0x11340, prExtend}, // Mn GRANTHA VOWEL SIGN II + {0x11341, 0x11344, prExtend}, // Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR + {0x11347, 0x11348, prExtend}, // Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI + {0x1134B, 0x1134D, prExtend}, // Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA + {0x11350, 0x11350, prOLetter}, // Lo GRANTHA OM + {0x11357, 0x11357, prExtend}, // Mc GRANTHA AU LENGTH MARK + {0x1135D, 0x11361, prOLetter}, // Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL + {0x11362, 0x11363, prExtend}, // Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL + {0x11366, 0x1136C, prExtend}, // Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX + {0x11370, 0x11374, prExtend}, // Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + {0x11400, 0x11434, prOLetter}, // Lo [53] NEWA LETTER A..NEWA LETTER HA + {0x11435, 0x11437, prExtend}, // Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II + {0x11438, 0x1143F, prExtend}, // Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI + {0x11440, 0x11441, prExtend}, // Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU + {0x11442, 0x11444, prExtend}, // Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA + {0x11445, 0x11445, prExtend}, // Mc NEWA SIGN VISARGA + {0x11446, 0x11446, prExtend}, // Mn NEWA SIGN NUKTA + {0x11447, 0x1144A, prOLetter}, // Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI + {0x1144B, 0x1144C, prSTerm}, // Po [2] NEWA DANDA..NEWA DOUBLE DANDA + {0x11450, 0x11459, prNumeric}, // Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE + {0x1145E, 0x1145E, prExtend}, // Mn NEWA SANDHI MARK + {0x1145F, 0x11461, prOLetter}, // Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA + {0x11480, 0x114AF, prOLetter}, // Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA + {0x114B0, 0x114B2, prExtend}, // Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II + {0x114B3, 0x114B8, prExtend}, // Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL + {0x114B9, 0x114B9, prExtend}, // Mc TIRHUTA VOWEL SIGN E + {0x114BA, 0x114BA, prExtend}, // Mn TIRHUTA VOWEL SIGN SHORT E + {0x114BB, 0x114BE, prExtend}, // Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU + {0x114BF, 0x114C0, prExtend}, // Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA + {0x114C1, 0x114C1, prExtend}, // Mc TIRHUTA SIGN VISARGA + {0x114C2, 0x114C3, prExtend}, // Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA + {0x114C4, 0x114C5, prOLetter}, // Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG + {0x114C7, 0x114C7, prOLetter}, // Lo TIRHUTA OM + {0x114D0, 0x114D9, prNumeric}, // Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE + {0x11580, 0x115AE, prOLetter}, // Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA + {0x115AF, 0x115B1, prExtend}, // Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II + {0x115B2, 0x115B5, prExtend}, // Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR + {0x115B8, 0x115BB, prExtend}, // Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU + {0x115BC, 0x115BD, prExtend}, // Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA + {0x115BE, 0x115BE, prExtend}, // Mc SIDDHAM SIGN VISARGA + {0x115BF, 0x115C0, prExtend}, // Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA + {0x115C2, 0x115C3, prSTerm}, // Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA + {0x115C9, 0x115D7, prSTerm}, // Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES + {0x115D8, 0x115DB, prOLetter}, // Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U + {0x115DC, 0x115DD, prExtend}, // Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + {0x11600, 0x1162F, prOLetter}, // Lo [48] MODI LETTER A..MODI LETTER LLA + {0x11630, 0x11632, prExtend}, // Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II + {0x11633, 0x1163A, prExtend}, // Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI + {0x1163B, 0x1163C, prExtend}, // Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU + {0x1163D, 0x1163D, prExtend}, // Mn MODI SIGN ANUSVARA + {0x1163E, 0x1163E, prExtend}, // Mc MODI SIGN VISARGA + {0x1163F, 0x11640, prExtend}, // Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA + {0x11641, 0x11642, prSTerm}, // Po [2] MODI DANDA..MODI DOUBLE DANDA + {0x11644, 0x11644, prOLetter}, // Lo MODI SIGN HUVA + {0x11650, 0x11659, prNumeric}, // Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE + {0x11680, 0x116AA, prOLetter}, // Lo [43] TAKRI LETTER A..TAKRI LETTER RRA + {0x116AB, 0x116AB, prExtend}, // Mn TAKRI SIGN ANUSVARA + {0x116AC, 0x116AC, prExtend}, // Mc TAKRI SIGN VISARGA + {0x116AD, 0x116AD, prExtend}, // Mn TAKRI VOWEL SIGN AA + {0x116AE, 0x116AF, prExtend}, // Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II + {0x116B0, 0x116B5, prExtend}, // Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU + {0x116B6, 0x116B6, prExtend}, // Mc TAKRI SIGN VIRAMA + {0x116B7, 0x116B7, prExtend}, // Mn TAKRI SIGN NUKTA + {0x116B8, 0x116B8, prOLetter}, // Lo TAKRI LETTER ARCHAIC KHA + {0x116C0, 0x116C9, prNumeric}, // Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE + {0x11700, 0x1171A, prOLetter}, // Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA + {0x1171D, 0x1171F, prExtend}, // Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA + {0x11720, 0x11721, prExtend}, // Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA + {0x11722, 0x11725, prExtend}, // Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU + {0x11726, 0x11726, prExtend}, // Mc AHOM VOWEL SIGN E + {0x11727, 0x1172B, prExtend}, // Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER + {0x11730, 0x11739, prNumeric}, // Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE + {0x1173C, 0x1173E, prSTerm}, // Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI + {0x11740, 0x11746, prOLetter}, // Lo [7] AHOM LETTER CA..AHOM LETTER LLA + {0x11800, 0x1182B, prOLetter}, // Lo [44] DOGRA LETTER A..DOGRA LETTER RRA + {0x1182C, 0x1182E, prExtend}, // Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II + {0x1182F, 0x11837, prExtend}, // Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA + {0x11838, 0x11838, prExtend}, // Mc DOGRA SIGN VISARGA + {0x11839, 0x1183A, prExtend}, // Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA + {0x118A0, 0x118BF, prUpper}, // L& [32] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI CAPITAL LETTER VIYO + {0x118C0, 0x118DF, prLower}, // L& [32] WARANG CITI SMALL LETTER NGAA..WARANG CITI SMALL LETTER VIYO + {0x118E0, 0x118E9, prNumeric}, // Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE + {0x118FF, 0x11906, prOLetter}, // Lo [8] WARANG CITI OM..DIVES AKURU LETTER E + {0x11909, 0x11909, prOLetter}, // Lo DIVES AKURU LETTER O + {0x1190C, 0x11913, prOLetter}, // Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA + {0x11915, 0x11916, prOLetter}, // Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA + {0x11918, 0x1192F, prOLetter}, // Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA + {0x11930, 0x11935, prExtend}, // Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E + {0x11937, 0x11938, prExtend}, // Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O + {0x1193B, 0x1193C, prExtend}, // Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU + {0x1193D, 0x1193D, prExtend}, // Mc DIVES AKURU SIGN HALANTA + {0x1193E, 0x1193E, prExtend}, // Mn DIVES AKURU VIRAMA + {0x1193F, 0x1193F, prOLetter}, // Lo DIVES AKURU PREFIXED NASAL SIGN + {0x11940, 0x11940, prExtend}, // Mc DIVES AKURU MEDIAL YA + {0x11941, 0x11941, prOLetter}, // Lo DIVES AKURU INITIAL RA + {0x11942, 0x11942, prExtend}, // Mc DIVES AKURU MEDIAL RA + {0x11943, 0x11943, prExtend}, // Mn DIVES AKURU SIGN NUKTA + {0x11944, 0x11944, prSTerm}, // Po DIVES AKURU DOUBLE DANDA + {0x11946, 0x11946, prSTerm}, // Po DIVES AKURU END OF TEXT MARK + {0x11950, 0x11959, prNumeric}, // Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE + {0x119A0, 0x119A7, prOLetter}, // Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR + {0x119AA, 0x119D0, prOLetter}, // Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA + {0x119D1, 0x119D3, prExtend}, // Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II + {0x119D4, 0x119D7, prExtend}, // Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR + {0x119DA, 0x119DB, prExtend}, // Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI + {0x119DC, 0x119DF, prExtend}, // Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA + {0x119E0, 0x119E0, prExtend}, // Mn NANDINAGARI SIGN VIRAMA + {0x119E1, 0x119E1, prOLetter}, // Lo NANDINAGARI SIGN AVAGRAHA + {0x119E3, 0x119E3, prOLetter}, // Lo NANDINAGARI HEADSTROKE + {0x119E4, 0x119E4, prExtend}, // Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E + {0x11A00, 0x11A00, prOLetter}, // Lo ZANABAZAR SQUARE LETTER A + {0x11A01, 0x11A0A, prExtend}, // Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK + {0x11A0B, 0x11A32, prOLetter}, // Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA + {0x11A33, 0x11A38, prExtend}, // Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA + {0x11A39, 0x11A39, prExtend}, // Mc ZANABAZAR SQUARE SIGN VISARGA + {0x11A3A, 0x11A3A, prOLetter}, // Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA + {0x11A3B, 0x11A3E, prExtend}, // Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA + {0x11A42, 0x11A43, prSTerm}, // Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD + {0x11A47, 0x11A47, prExtend}, // Mn ZANABAZAR SQUARE SUBJOINER + {0x11A50, 0x11A50, prOLetter}, // Lo SOYOMBO LETTER A + {0x11A51, 0x11A56, prExtend}, // Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE + {0x11A57, 0x11A58, prExtend}, // Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU + {0x11A59, 0x11A5B, prExtend}, // Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK + {0x11A5C, 0x11A89, prOLetter}, // Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA + {0x11A8A, 0x11A96, prExtend}, // Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA + {0x11A97, 0x11A97, prExtend}, // Mc SOYOMBO SIGN VISARGA + {0x11A98, 0x11A99, prExtend}, // Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER + {0x11A9B, 0x11A9C, prSTerm}, // Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD + {0x11A9D, 0x11A9D, prOLetter}, // Lo SOYOMBO MARK PLUTA + {0x11AB0, 0x11AF8, prOLetter}, // Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL + {0x11C00, 0x11C08, prOLetter}, // Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L + {0x11C0A, 0x11C2E, prOLetter}, // Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA + {0x11C2F, 0x11C2F, prExtend}, // Mc BHAIKSUKI VOWEL SIGN AA + {0x11C30, 0x11C36, prExtend}, // Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L + {0x11C38, 0x11C3D, prExtend}, // Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA + {0x11C3E, 0x11C3E, prExtend}, // Mc BHAIKSUKI SIGN VISARGA + {0x11C3F, 0x11C3F, prExtend}, // Mn BHAIKSUKI SIGN VIRAMA + {0x11C40, 0x11C40, prOLetter}, // Lo BHAIKSUKI SIGN AVAGRAHA + {0x11C41, 0x11C42, prSTerm}, // Po [2] BHAIKSUKI DANDA..BHAIKSUKI DOUBLE DANDA + {0x11C50, 0x11C59, prNumeric}, // Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE + {0x11C72, 0x11C8F, prOLetter}, // Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A + {0x11C92, 0x11CA7, prExtend}, // Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA + {0x11CA9, 0x11CA9, prExtend}, // Mc MARCHEN SUBJOINED LETTER YA + {0x11CAA, 0x11CB0, prExtend}, // Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA + {0x11CB1, 0x11CB1, prExtend}, // Mc MARCHEN VOWEL SIGN I + {0x11CB2, 0x11CB3, prExtend}, // Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E + {0x11CB4, 0x11CB4, prExtend}, // Mc MARCHEN VOWEL SIGN O + {0x11CB5, 0x11CB6, prExtend}, // Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + {0x11D00, 0x11D06, prOLetter}, // Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E + {0x11D08, 0x11D09, prOLetter}, // Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O + {0x11D0B, 0x11D30, prOLetter}, // Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA + {0x11D31, 0x11D36, prExtend}, // Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R + {0x11D3A, 0x11D3A, prExtend}, // Mn MASARAM GONDI VOWEL SIGN E + {0x11D3C, 0x11D3D, prExtend}, // Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O + {0x11D3F, 0x11D45, prExtend}, // Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA + {0x11D46, 0x11D46, prOLetter}, // Lo MASARAM GONDI REPHA + {0x11D47, 0x11D47, prExtend}, // Mn MASARAM GONDI RA-KARA + {0x11D50, 0x11D59, prNumeric}, // Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE + {0x11D60, 0x11D65, prOLetter}, // Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU + {0x11D67, 0x11D68, prOLetter}, // Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI + {0x11D6A, 0x11D89, prOLetter}, // Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA + {0x11D8A, 0x11D8E, prExtend}, // Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU + {0x11D90, 0x11D91, prExtend}, // Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI + {0x11D93, 0x11D94, prExtend}, // Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU + {0x11D95, 0x11D95, prExtend}, // Mn GUNJALA GONDI SIGN ANUSVARA + {0x11D96, 0x11D96, prExtend}, // Mc GUNJALA GONDI SIGN VISARGA + {0x11D97, 0x11D97, prExtend}, // Mn GUNJALA GONDI VIRAMA + {0x11D98, 0x11D98, prOLetter}, // Lo GUNJALA GONDI OM + {0x11DA0, 0x11DA9, prNumeric}, // Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE + {0x11EE0, 0x11EF2, prOLetter}, // Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA + {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U + {0x11EF5, 0x11EF6, prExtend}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x11EF7, 0x11EF8, prSTerm}, // Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION + {0x11F00, 0x11F01, prExtend}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prOLetter}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prExtend}, // Mc KAWI SIGN VISARGA + {0x11F04, 0x11F10, prOLetter}, // Lo [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prOLetter}, // Lo [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prExtend}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prExtend}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prExtend}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prExtend}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prExtend}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prExtend}, // Mn KAWI CONJOINER + {0x11F43, 0x11F44, prSTerm}, // Po [2] KAWI DANDA..KAWI DOUBLE DANDA + {0x11F50, 0x11F59, prNumeric}, // Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE + {0x11FB0, 0x11FB0, prOLetter}, // Lo LISU LETTER YHA + {0x12000, 0x12399, prOLetter}, // Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U + {0x12400, 0x1246E, prOLetter}, // Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM + {0x12480, 0x12543, prOLetter}, // Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU + {0x12F90, 0x12FF0, prOLetter}, // Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 + {0x13000, 0x1342F, prOLetter}, // Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x1343F, prFormat}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prExtend}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prOLetter}, // Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prExtend}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED + {0x14400, 0x14646, prOLetter}, // Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 + {0x16800, 0x16A38, prOLetter}, // Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ + {0x16A40, 0x16A5E, prOLetter}, // Lo [31] MRO LETTER TA..MRO LETTER TEK + {0x16A60, 0x16A69, prNumeric}, // Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE + {0x16A6E, 0x16A6F, prSTerm}, // Po [2] MRO DANDA..MRO DOUBLE DANDA + {0x16A70, 0x16ABE, prOLetter}, // Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA + {0x16AC0, 0x16AC9, prNumeric}, // Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE + {0x16AD0, 0x16AED, prOLetter}, // Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I + {0x16AF0, 0x16AF4, prExtend}, // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE + {0x16AF5, 0x16AF5, prSTerm}, // Po BASSA VAH FULL STOP + {0x16B00, 0x16B2F, prOLetter}, // Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU + {0x16B30, 0x16B36, prExtend}, // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM + {0x16B37, 0x16B38, prSTerm}, // Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB + {0x16B40, 0x16B43, prOLetter}, // Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM + {0x16B44, 0x16B44, prSTerm}, // Po PAHAWH HMONG SIGN XAUS + {0x16B50, 0x16B59, prNumeric}, // Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE + {0x16B63, 0x16B77, prOLetter}, // Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS + {0x16B7D, 0x16B8F, prOLetter}, // Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ + {0x16E40, 0x16E5F, prUpper}, // L& [32] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN CAPITAL LETTER Y + {0x16E60, 0x16E7F, prLower}, // L& [32] MEDEFAIDRIN SMALL LETTER M..MEDEFAIDRIN SMALL LETTER Y + {0x16E98, 0x16E98, prSTerm}, // Po MEDEFAIDRIN FULL STOP + {0x16F00, 0x16F4A, prOLetter}, // Lo [75] MIAO LETTER PA..MIAO LETTER RTE + {0x16F4F, 0x16F4F, prExtend}, // Mn MIAO SIGN CONSONANT MODIFIER BAR + {0x16F50, 0x16F50, prOLetter}, // Lo MIAO LETTER NASALIZATION + {0x16F51, 0x16F87, prExtend}, // Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI + {0x16F8F, 0x16F92, prExtend}, // Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW + {0x16F93, 0x16F9F, prOLetter}, // Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 + {0x16FE0, 0x16FE1, prOLetter}, // Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK + {0x16FE3, 0x16FE3, prOLetter}, // Lm OLD CHINESE ITERATION MARK + {0x16FE4, 0x16FE4, prExtend}, // Mn KHITAN SMALL SCRIPT FILLER + {0x16FF0, 0x16FF1, prExtend}, // Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY + {0x17000, 0x187F7, prOLetter}, // Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7 + {0x18800, 0x18CD5, prOLetter}, // Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5 + {0x18D00, 0x18D08, prOLetter}, // Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08 + {0x1AFF0, 0x1AFF3, prOLetter}, // Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 + {0x1AFF5, 0x1AFFB, prOLetter}, // Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 + {0x1AFFD, 0x1AFFE, prOLetter}, // Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 + {0x1B000, 0x1B122, prOLetter}, // Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU + {0x1B132, 0x1B132, prOLetter}, // Lo HIRAGANA LETTER SMALL KO + {0x1B150, 0x1B152, prOLetter}, // Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO + {0x1B155, 0x1B155, prOLetter}, // Lo KATAKANA LETTER SMALL KO + {0x1B164, 0x1B167, prOLetter}, // Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N + {0x1B170, 0x1B2FB, prOLetter}, // Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB + {0x1BC00, 0x1BC6A, prOLetter}, // Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M + {0x1BC70, 0x1BC7C, prOLetter}, // Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK + {0x1BC80, 0x1BC88, prOLetter}, // Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL + {0x1BC90, 0x1BC99, prOLetter}, // Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW + {0x1BC9D, 0x1BC9E, prExtend}, // Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK + {0x1BC9F, 0x1BC9F, prSTerm}, // Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP + {0x1BCA0, 0x1BCA3, prFormat}, // Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP + {0x1CF00, 0x1CF2D, prExtend}, // Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT + {0x1CF30, 0x1CF46, prExtend}, // Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG + {0x1D165, 0x1D166, prExtend}, // Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM + {0x1D167, 0x1D169, prExtend}, // Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 + {0x1D16D, 0x1D172, prExtend}, // Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 + {0x1D173, 0x1D17A, prFormat}, // Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE + {0x1D17B, 0x1D182, prExtend}, // Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE + {0x1D185, 0x1D18B, prExtend}, // Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE + {0x1D1AA, 0x1D1AD, prExtend}, // Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO + {0x1D242, 0x1D244, prExtend}, // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME + {0x1D400, 0x1D419, prUpper}, // L& [26] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL BOLD CAPITAL Z + {0x1D41A, 0x1D433, prLower}, // L& [26] MATHEMATICAL BOLD SMALL A..MATHEMATICAL BOLD SMALL Z + {0x1D434, 0x1D44D, prUpper}, // L& [26] MATHEMATICAL ITALIC CAPITAL A..MATHEMATICAL ITALIC CAPITAL Z + {0x1D44E, 0x1D454, prLower}, // L& [7] MATHEMATICAL ITALIC SMALL A..MATHEMATICAL ITALIC SMALL G + {0x1D456, 0x1D467, prLower}, // L& [18] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL ITALIC SMALL Z + {0x1D468, 0x1D481, prUpper}, // L& [26] MATHEMATICAL BOLD ITALIC CAPITAL A..MATHEMATICAL BOLD ITALIC CAPITAL Z + {0x1D482, 0x1D49B, prLower}, // L& [26] MATHEMATICAL BOLD ITALIC SMALL A..MATHEMATICAL BOLD ITALIC SMALL Z + {0x1D49C, 0x1D49C, prUpper}, // L& MATHEMATICAL SCRIPT CAPITAL A + {0x1D49E, 0x1D49F, prUpper}, // L& [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D + {0x1D4A2, 0x1D4A2, prUpper}, // L& MATHEMATICAL SCRIPT CAPITAL G + {0x1D4A5, 0x1D4A6, prUpper}, // L& [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K + {0x1D4A9, 0x1D4AC, prUpper}, // L& [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q + {0x1D4AE, 0x1D4B5, prUpper}, // L& [8] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT CAPITAL Z + {0x1D4B6, 0x1D4B9, prLower}, // L& [4] MATHEMATICAL SCRIPT SMALL A..MATHEMATICAL SCRIPT SMALL D + {0x1D4BB, 0x1D4BB, prLower}, // L& MATHEMATICAL SCRIPT SMALL F + {0x1D4BD, 0x1D4C3, prLower}, // L& [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N + {0x1D4C5, 0x1D4CF, prLower}, // L& [11] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL SCRIPT SMALL Z + {0x1D4D0, 0x1D4E9, prUpper}, // L& [26] MATHEMATICAL BOLD SCRIPT CAPITAL A..MATHEMATICAL BOLD SCRIPT CAPITAL Z + {0x1D4EA, 0x1D503, prLower}, // L& [26] MATHEMATICAL BOLD SCRIPT SMALL A..MATHEMATICAL BOLD SCRIPT SMALL Z + {0x1D504, 0x1D505, prUpper}, // L& [2] MATHEMATICAL FRAKTUR CAPITAL A..MATHEMATICAL FRAKTUR CAPITAL B + {0x1D507, 0x1D50A, prUpper}, // L& [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G + {0x1D50D, 0x1D514, prUpper}, // L& [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q + {0x1D516, 0x1D51C, prUpper}, // L& [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y + {0x1D51E, 0x1D537, prLower}, // L& [26] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL FRAKTUR SMALL Z + {0x1D538, 0x1D539, prUpper}, // L& [2] MATHEMATICAL DOUBLE-STRUCK CAPITAL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B + {0x1D53B, 0x1D53E, prUpper}, // L& [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G + {0x1D540, 0x1D544, prUpper}, // L& [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M + {0x1D546, 0x1D546, prUpper}, // L& MATHEMATICAL DOUBLE-STRUCK CAPITAL O + {0x1D54A, 0x1D550, prUpper}, // L& [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y + {0x1D552, 0x1D56B, prLower}, // L& [26] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL DOUBLE-STRUCK SMALL Z + {0x1D56C, 0x1D585, prUpper}, // L& [26] MATHEMATICAL BOLD FRAKTUR CAPITAL A..MATHEMATICAL BOLD FRAKTUR CAPITAL Z + {0x1D586, 0x1D59F, prLower}, // L& [26] MATHEMATICAL BOLD FRAKTUR SMALL A..MATHEMATICAL BOLD FRAKTUR SMALL Z + {0x1D5A0, 0x1D5B9, prUpper}, // L& [26] MATHEMATICAL SANS-SERIF CAPITAL A..MATHEMATICAL SANS-SERIF CAPITAL Z + {0x1D5BA, 0x1D5D3, prLower}, // L& [26] MATHEMATICAL SANS-SERIF SMALL A..MATHEMATICAL SANS-SERIF SMALL Z + {0x1D5D4, 0x1D5ED, prUpper}, // L& [26] MATHEMATICAL SANS-SERIF BOLD CAPITAL A..MATHEMATICAL SANS-SERIF BOLD CAPITAL Z + {0x1D5EE, 0x1D607, prLower}, // L& [26] MATHEMATICAL SANS-SERIF BOLD SMALL A..MATHEMATICAL SANS-SERIF BOLD SMALL Z + {0x1D608, 0x1D621, prUpper}, // L& [26] MATHEMATICAL SANS-SERIF ITALIC CAPITAL A..MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z + {0x1D622, 0x1D63B, prLower}, // L& [26] MATHEMATICAL SANS-SERIF ITALIC SMALL A..MATHEMATICAL SANS-SERIF ITALIC SMALL Z + {0x1D63C, 0x1D655, prUpper}, // L& [26] MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z + {0x1D656, 0x1D66F, prLower}, // L& [26] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z + {0x1D670, 0x1D689, prUpper}, // L& [26] MATHEMATICAL MONOSPACE CAPITAL A..MATHEMATICAL MONOSPACE CAPITAL Z + {0x1D68A, 0x1D6A5, prLower}, // L& [28] MATHEMATICAL MONOSPACE SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J + {0x1D6A8, 0x1D6C0, prUpper}, // L& [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA + {0x1D6C2, 0x1D6DA, prLower}, // L& [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA + {0x1D6DC, 0x1D6E1, prLower}, // L& [6] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL BOLD PI SYMBOL + {0x1D6E2, 0x1D6FA, prUpper}, // L& [25] MATHEMATICAL ITALIC CAPITAL ALPHA..MATHEMATICAL ITALIC CAPITAL OMEGA + {0x1D6FC, 0x1D714, prLower}, // L& [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA + {0x1D716, 0x1D71B, prLower}, // L& [6] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL ITALIC PI SYMBOL + {0x1D71C, 0x1D734, prUpper}, // L& [25] MATHEMATICAL BOLD ITALIC CAPITAL ALPHA..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA + {0x1D736, 0x1D74E, prLower}, // L& [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA + {0x1D750, 0x1D755, prLower}, // L& [6] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC PI SYMBOL + {0x1D756, 0x1D76E, prUpper}, // L& [25] MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA + {0x1D770, 0x1D788, prLower}, // L& [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA + {0x1D78A, 0x1D78F, prLower}, // L& [6] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD PI SYMBOL + {0x1D790, 0x1D7A8, prUpper}, // L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA + {0x1D7AA, 0x1D7C2, prLower}, // L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA + {0x1D7C4, 0x1D7C9, prLower}, // L& [6] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL + {0x1D7CA, 0x1D7CA, prUpper}, // L& MATHEMATICAL BOLD CAPITAL DIGAMMA + {0x1D7CB, 0x1D7CB, prLower}, // L& MATHEMATICAL BOLD SMALL DIGAMMA + {0x1D7CE, 0x1D7FF, prNumeric}, // Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE + {0x1DA00, 0x1DA36, prExtend}, // Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN + {0x1DA3B, 0x1DA6C, prExtend}, // Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT + {0x1DA75, 0x1DA75, prExtend}, // Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS + {0x1DA84, 0x1DA84, prExtend}, // Mn SIGNWRITING LOCATION HEAD NECK + {0x1DA88, 0x1DA88, prSTerm}, // Po SIGNWRITING FULL STOP + {0x1DA9B, 0x1DA9F, prExtend}, // Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 + {0x1DAA1, 0x1DAAF, prExtend}, // Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + {0x1DF00, 0x1DF09, prLower}, // L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK + {0x1DF0A, 0x1DF0A, prOLetter}, // Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK + {0x1DF0B, 0x1DF1E, prLower}, // L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prLower}, // L& [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK + {0x1E000, 0x1E006, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE + {0x1E008, 0x1E018, prExtend}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU + {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI + {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS + {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prLower}, // Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prExtend}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + {0x1E100, 0x1E12C, prOLetter}, // Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W + {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D + {0x1E137, 0x1E13D, prOLetter}, // Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER + {0x1E140, 0x1E149, prNumeric}, // Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE + {0x1E14E, 0x1E14E, prOLetter}, // Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ + {0x1E290, 0x1E2AD, prOLetter}, // Lo [30] TOTO LETTER PA..TOTO LETTER A + {0x1E2AE, 0x1E2AE, prExtend}, // Mn TOTO SIGN RISING TONE + {0x1E2C0, 0x1E2EB, prOLetter}, // Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH + {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E2F0, 0x1E2F9, prNumeric}, // Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE + {0x1E4D0, 0x1E4EA, prOLetter}, // Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prOLetter}, // Lm NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prExtend}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prNumeric}, // Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE + {0x1E7E0, 0x1E7E6, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO + {0x1E7E8, 0x1E7EB, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE + {0x1E7ED, 0x1E7EE, prOLetter}, // Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE + {0x1E7F0, 0x1E7FE, prOLetter}, // Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE + {0x1E800, 0x1E8C4, prOLetter}, // Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON + {0x1E8D0, 0x1E8D6, prExtend}, // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + {0x1E900, 0x1E921, prUpper}, // L& [34] ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA + {0x1E922, 0x1E943, prLower}, // L& [34] ADLAM SMALL LETTER ALIF..ADLAM SMALL LETTER SHA + {0x1E944, 0x1E94A, prExtend}, // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA + {0x1E94B, 0x1E94B, prOLetter}, // Lm ADLAM NASALIZATION MARK + {0x1E950, 0x1E959, prNumeric}, // Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE + {0x1EE00, 0x1EE03, prOLetter}, // Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL + {0x1EE05, 0x1EE1F, prOLetter}, // Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF + {0x1EE21, 0x1EE22, prOLetter}, // Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM + {0x1EE24, 0x1EE24, prOLetter}, // Lo ARABIC MATHEMATICAL INITIAL HEH + {0x1EE27, 0x1EE27, prOLetter}, // Lo ARABIC MATHEMATICAL INITIAL HAH + {0x1EE29, 0x1EE32, prOLetter}, // Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF + {0x1EE34, 0x1EE37, prOLetter}, // Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH + {0x1EE39, 0x1EE39, prOLetter}, // Lo ARABIC MATHEMATICAL INITIAL DAD + {0x1EE3B, 0x1EE3B, prOLetter}, // Lo ARABIC MATHEMATICAL INITIAL GHAIN + {0x1EE42, 0x1EE42, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED JEEM + {0x1EE47, 0x1EE47, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED HAH + {0x1EE49, 0x1EE49, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED YEH + {0x1EE4B, 0x1EE4B, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED LAM + {0x1EE4D, 0x1EE4F, prOLetter}, // Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN + {0x1EE51, 0x1EE52, prOLetter}, // Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF + {0x1EE54, 0x1EE54, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED SHEEN + {0x1EE57, 0x1EE57, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED KHAH + {0x1EE59, 0x1EE59, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED DAD + {0x1EE5B, 0x1EE5B, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED GHAIN + {0x1EE5D, 0x1EE5D, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON + {0x1EE5F, 0x1EE5F, prOLetter}, // Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF + {0x1EE61, 0x1EE62, prOLetter}, // Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM + {0x1EE64, 0x1EE64, prOLetter}, // Lo ARABIC MATHEMATICAL STRETCHED HEH + {0x1EE67, 0x1EE6A, prOLetter}, // Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF + {0x1EE6C, 0x1EE72, prOLetter}, // Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF + {0x1EE74, 0x1EE77, prOLetter}, // Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH + {0x1EE79, 0x1EE7C, prOLetter}, // Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH + {0x1EE7E, 0x1EE7E, prOLetter}, // Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH + {0x1EE80, 0x1EE89, prOLetter}, // Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH + {0x1EE8B, 0x1EE9B, prOLetter}, // Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN + {0x1EEA1, 0x1EEA3, prOLetter}, // Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL + {0x1EEA5, 0x1EEA9, prOLetter}, // Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH + {0x1EEAB, 0x1EEBB, prOLetter}, // Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN + {0x1F130, 0x1F149, prUpper}, // So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z + {0x1F150, 0x1F169, prUpper}, // So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z + {0x1F170, 0x1F189, prUpper}, // So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z + {0x1F676, 0x1F678, prClose}, // So [3] SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT..SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT + {0x1FBF0, 0x1FBF9, prNumeric}, // Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE + {0x20000, 0x2A6DF, prOLetter}, // Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF + {0x2A700, 0x2B739, prOLetter}, // Lo [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739 + {0x2B740, 0x2B81D, prOLetter}, // Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D + {0x2B820, 0x2CEA1, prOLetter}, // Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 + {0x2CEB0, 0x2EBE0, prOLetter}, // Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 + {0x2F800, 0x2FA1D, prOLetter}, // Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D + {0x30000, 0x3134A, prOLetter}, // Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A + {0x31350, 0x323AF, prOLetter}, // Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF + {0xE0001, 0xE0001, prFormat}, // Cf LANGUAGE TAG + {0xE0020, 0xE007F, prExtend}, // Cf [96] TAG SPACE..CANCEL TAG + {0xE0100, 0xE01EF, prExtend}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 +} diff --git a/vendor/github.com/rivo/uniseg/sentencerules.go b/vendor/github.com/rivo/uniseg/sentencerules.go new file mode 100644 index 000000000..0b29c7bdb --- /dev/null +++ b/vendor/github.com/rivo/uniseg/sentencerules.go @@ -0,0 +1,276 @@ +package uniseg + +import "unicode/utf8" + +// The states of the sentence break parser. +const ( + sbAny = iota + sbCR + sbParaSep + sbATerm + sbUpper + sbLower + sbSB7 + sbSB8Close + sbSB8Sp + sbSTerm + sbSB8aClose + sbSB8aSp +) + +// sbTransitions implements the sentence break parser's state transitions. It's +// anologous to [grTransitions], see comments there for details. +// +// Unicode version 15.0.0. +func sbTransitions(state, prop int) (newState int, sentenceBreak bool, rule int) { + switch uint64(state) | uint64(prop)<<32 { + // SB3. + case sbAny | prCR<<32: + return sbCR, false, 9990 + case sbCR | prLF<<32: + return sbParaSep, false, 30 + + // SB4. + case sbAny | prSep<<32: + return sbParaSep, false, 9990 + case sbAny | prLF<<32: + return sbParaSep, false, 9990 + case sbParaSep | prAny<<32: + return sbAny, true, 40 + case sbCR | prAny<<32: + return sbAny, true, 40 + + // SB6. + case sbAny | prATerm<<32: + return sbATerm, false, 9990 + case sbATerm | prNumeric<<32: + return sbAny, false, 60 + case sbSB7 | prNumeric<<32: + return sbAny, false, 60 // Because ATerm also appears in SB7. + + // SB7. + case sbAny | prUpper<<32: + return sbUpper, false, 9990 + case sbAny | prLower<<32: + return sbLower, false, 9990 + case sbUpper | prATerm<<32: + return sbSB7, false, 70 + case sbLower | prATerm<<32: + return sbSB7, false, 70 + case sbSB7 | prUpper<<32: + return sbUpper, false, 70 + + // SB8a. + case sbAny | prSTerm<<32: + return sbSTerm, false, 9990 + case sbATerm | prSContinue<<32: + return sbAny, false, 81 + case sbATerm | prATerm<<32: + return sbATerm, false, 81 + case sbATerm | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB7 | prSContinue<<32: + return sbAny, false, 81 + case sbSB7 | prATerm<<32: + return sbATerm, false, 81 + case sbSB7 | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8Close | prSContinue<<32: + return sbAny, false, 81 + case sbSB8Close | prATerm<<32: + return sbATerm, false, 81 + case sbSB8Close | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8Sp | prSContinue<<32: + return sbAny, false, 81 + case sbSB8Sp | prATerm<<32: + return sbATerm, false, 81 + case sbSB8Sp | prSTerm<<32: + return sbSTerm, false, 81 + case sbSTerm | prSContinue<<32: + return sbAny, false, 81 + case sbSTerm | prATerm<<32: + return sbATerm, false, 81 + case sbSTerm | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8aClose | prSContinue<<32: + return sbAny, false, 81 + case sbSB8aClose | prATerm<<32: + return sbATerm, false, 81 + case sbSB8aClose | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8aSp | prSContinue<<32: + return sbAny, false, 81 + case sbSB8aSp | prATerm<<32: + return sbATerm, false, 81 + case sbSB8aSp | prSTerm<<32: + return sbSTerm, false, 81 + + // SB9. + case sbATerm | prClose<<32: + return sbSB8Close, false, 90 + case sbSB7 | prClose<<32: + return sbSB8Close, false, 90 + case sbSB8Close | prClose<<32: + return sbSB8Close, false, 90 + case sbATerm | prSp<<32: + return sbSB8Sp, false, 90 + case sbSB7 | prSp<<32: + return sbSB8Sp, false, 90 + case sbSB8Close | prSp<<32: + return sbSB8Sp, false, 90 + case sbSTerm | prClose<<32: + return sbSB8aClose, false, 90 + case sbSB8aClose | prClose<<32: + return sbSB8aClose, false, 90 + case sbSTerm | prSp<<32: + return sbSB8aSp, false, 90 + case sbSB8aClose | prSp<<32: + return sbSB8aSp, false, 90 + case sbATerm | prSep<<32: + return sbParaSep, false, 90 + case sbATerm | prCR<<32: + return sbParaSep, false, 90 + case sbATerm | prLF<<32: + return sbParaSep, false, 90 + case sbSB7 | prSep<<32: + return sbParaSep, false, 90 + case sbSB7 | prCR<<32: + return sbParaSep, false, 90 + case sbSB7 | prLF<<32: + return sbParaSep, false, 90 + case sbSB8Close | prSep<<32: + return sbParaSep, false, 90 + case sbSB8Close | prCR<<32: + return sbParaSep, false, 90 + case sbSB8Close | prLF<<32: + return sbParaSep, false, 90 + case sbSTerm | prSep<<32: + return sbParaSep, false, 90 + case sbSTerm | prCR<<32: + return sbParaSep, false, 90 + case sbSTerm | prLF<<32: + return sbParaSep, false, 90 + case sbSB8aClose | prSep<<32: + return sbParaSep, false, 90 + case sbSB8aClose | prCR<<32: + return sbParaSep, false, 90 + case sbSB8aClose | prLF<<32: + return sbParaSep, false, 90 + + // SB10. + case sbSB8Sp | prSp<<32: + return sbSB8Sp, false, 100 + case sbSB8aSp | prSp<<32: + return sbSB8aSp, false, 100 + case sbSB8Sp | prSep<<32: + return sbParaSep, false, 100 + case sbSB8Sp | prCR<<32: + return sbParaSep, false, 100 + case sbSB8Sp | prLF<<32: + return sbParaSep, false, 100 + + // SB11. + case sbATerm | prAny<<32: + return sbAny, true, 110 + case sbSB7 | prAny<<32: + return sbAny, true, 110 + case sbSB8Close | prAny<<32: + return sbAny, true, 110 + case sbSB8Sp | prAny<<32: + return sbAny, true, 110 + case sbSTerm | prAny<<32: + return sbAny, true, 110 + case sbSB8aClose | prAny<<32: + return sbAny, true, 110 + case sbSB8aSp | prAny<<32: + return sbAny, true, 110 + // We'll always break after ParaSep due to SB4. + + default: + return -1, false, -1 + } +} + +// transitionSentenceBreakState determines the new state of the sentence break +// parser given the current state and the next code point. It also returns +// whether a sentence boundary was detected. If more than one code point is +// needed to determine the new state, the byte slice or the string starting +// after rune "r" can be used (whichever is not nil or empty) for further +// lookups. +func transitionSentenceBreakState(state int, r rune, b []byte, str string) (newState int, sentenceBreak bool) { + // Determine the property of the next character. + nextProperty := property(sentenceBreakCodePoints, r) + + // SB5 (Replacing Ignore Rules). + if nextProperty == prExtend || nextProperty == prFormat { + if state == sbParaSep || state == sbCR { + return sbAny, true // Make sure we don't apply SB5 to SB3 or SB4. + } + if state < 0 { + return sbAny, true // SB1. + } + return state, false + } + + // Find the applicable transition in the table. + var rule int + newState, sentenceBreak, rule = sbTransitions(state, nextProperty) + if newState < 0 { + // No specific transition found. Try the less specific ones. + anyPropState, anyPropProp, anyPropRule := sbTransitions(state, prAny) + anyStateState, anyStateProp, anyStateRule := sbTransitions(sbAny, nextProperty) + if anyPropState >= 0 && anyStateState >= 0 { + // Both apply. We'll use a mix (see comments for grTransitions). + newState, sentenceBreak, rule = anyStateState, anyStateProp, anyStateRule + if anyPropRule < anyStateRule { + sentenceBreak, rule = anyPropProp, anyPropRule + } + } else if anyPropState >= 0 { + // We only have a specific state. + newState, sentenceBreak, rule = anyPropState, anyPropProp, anyPropRule + // This branch will probably never be reached because okAnyState will + // always be true given the current transition map. But we keep it here + // for future modifications to the transition map where this may not be + // true anymore. + } else if anyStateState >= 0 { + // We only have a specific property. + newState, sentenceBreak, rule = anyStateState, anyStateProp, anyStateRule + } else { + // No known transition. SB999: Any × Any. + newState, sentenceBreak, rule = sbAny, false, 9990 + } + } + + // SB8. + if rule > 80 && (state == sbATerm || state == sbSB8Close || state == sbSB8Sp || state == sbSB7) { + // Check the right side of the rule. + var length int + for nextProperty != prOLetter && + nextProperty != prUpper && + nextProperty != prLower && + nextProperty != prSep && + nextProperty != prCR && + nextProperty != prLF && + nextProperty != prATerm && + nextProperty != prSTerm { + // Move on to the next rune. + if b != nil { // Byte slice version. + r, length = utf8.DecodeRune(b) + b = b[length:] + } else { // String version. + r, length = utf8.DecodeRuneInString(str) + str = str[length:] + } + if r == utf8.RuneError { + break + } + nextProperty = property(sentenceBreakCodePoints, r) + } + if nextProperty == prLower { + return sbLower, false + } + } + + return +} diff --git a/vendor/github.com/rivo/uniseg/step.go b/vendor/github.com/rivo/uniseg/step.go new file mode 100644 index 000000000..9b72c5e59 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/step.go @@ -0,0 +1,242 @@ +package uniseg + +import "unicode/utf8" + +// The bit masks used to extract boundary information returned by [Step]. +const ( + MaskLine = 3 + MaskWord = 4 + MaskSentence = 8 +) + +// The number of bits to shift the boundary information returned by [Step] to +// obtain the monospace width of the grapheme cluster. +const ShiftWidth = 4 + +// The bit positions by which boundary flags are shifted by the [Step] function. +// These must correspond to the Mask constants. +const ( + shiftWord = 2 + shiftSentence = 3 + // shiftwWidth is ShiftWidth above. No mask as these are always the remaining bits. +) + +// The bit positions by which states are shifted by the [Step] function. These +// values must ensure state values defined for each of the boundary algorithms +// don't overlap (and that they all still fit in a single int). These must +// correspond to the Mask constants. +const ( + shiftWordState = 4 + shiftSentenceState = 9 + shiftLineState = 13 + shiftPropState = 21 // No mask as these are always the remaining bits. +) + +// The bit mask used to extract the state returned by the [Step] function, after +// shifting. These values must correspond to the shift constants. +const ( + maskGraphemeState = 0xf + maskWordState = 0x1f + maskSentenceState = 0xf + maskLineState = 0xff +) + +// Step returns the first grapheme cluster (user-perceived character) found in +// the given byte slice. It also returns information about the boundary between +// that grapheme cluster and the one following it as well as the monospace width +// of the grapheme cluster. There are three types of boundary information: word +// boundaries, sentence boundaries, and line breaks. This function is therefore +// a combination of [FirstGraphemeCluster], [FirstWord], [FirstSentence], and +// [FirstLineSegment]. +// +// The "boundaries" return value can be evaluated as follows: +// +// - boundaries&MaskWord != 0: The boundary is a word boundary. +// - boundaries&MaskWord == 0: The boundary is not a word boundary. +// - boundaries&MaskSentence != 0: The boundary is a sentence boundary. +// - boundaries&MaskSentence == 0: The boundary is not a sentence boundary. +// - boundaries&MaskLine == LineDontBreak: You must not break the line at the +// boundary. +// - boundaries&MaskLine == LineMustBreak: You must break the line at the +// boundary. +// - boundaries&MaskLine == LineCanBreak: You may or may not break the line at +// the boundary. +// - boundaries >> ShiftWidth: The width of the grapheme cluster for most +// monospace fonts where a value of 1 represents one character cell. +// +// This function can be called continuously to extract all grapheme clusters +// from a byte slice, as illustrated in the examples below. +// +// If you don't know which state to pass, for example when calling the function +// for the first time, you must pass -1. For consecutive calls, pass the state +// and rest slice returned by the previous call. +// +// The "rest" slice is the sub-slice of the original byte slice "b" starting +// after the last byte of the identified grapheme cluster. If the length of the +// "rest" slice is 0, the entire byte slice "b" has been processed. The +// "cluster" byte slice is the sub-slice of the input slice containing the +// first identified grapheme cluster. +// +// Given an empty byte slice "b", the function returns nil values. +// +// While slightly less convenient than using the Graphemes class, this function +// has much better performance and makes no allocations. It lends itself well to +// large byte slices. +// +// Note that in accordance with [UAX #14 LB3], the final segment will end with +// a mandatory line break (boundaries&MaskLine == LineMustBreak). You can choose +// to ignore this by checking if the length of the "rest" slice is 0 and calling +// [HasTrailingLineBreak] or [HasTrailingLineBreakInString] on the last rune. +// +// [UAX #14 LB3]: https://www.unicode.org/reports/tr14/#Algorithm +func Step(b []byte, state int) (cluster, rest []byte, boundaries int, newState int) { + // An empty byte slice returns nothing. + if len(b) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRune(b) + if len(b) <= length { // If we're already past the end, there is nothing else to parse. + var prop int + if state < 0 { + prop = propertyGraphemes(r) + } else { + prop = state >> shiftPropState + } + return b, nil, LineMustBreak | (1 << shiftWord) | (1 << shiftSentence) | (runeWidth(r, prop) << ShiftWidth), grAny | (wbAny << shiftWordState) | (sbAny << shiftSentenceState) | (lbAny << shiftLineState) | (prop << shiftPropState) + } + + // If we don't know the state, determine it now. + var graphemeState, wordState, sentenceState, lineState, firstProp int + remainder := b[length:] + if state < 0 { + graphemeState, firstProp, _ = transitionGraphemeState(state, r) + wordState, _ = transitionWordBreakState(state, r, remainder, "") + sentenceState, _ = transitionSentenceBreakState(state, r, remainder, "") + lineState, _ = transitionLineBreakState(state, r, remainder, "") + } else { + graphemeState = state & maskGraphemeState + wordState = (state >> shiftWordState) & maskWordState + sentenceState = (state >> shiftSentenceState) & maskSentenceState + lineState = (state >> shiftLineState) & maskLineState + firstProp = state >> shiftPropState + } + + // Transition until we find a grapheme cluster boundary. + width := runeWidth(r, firstProp) + for { + var ( + graphemeBoundary, wordBoundary, sentenceBoundary bool + lineBreak, prop int + ) + + r, l := utf8.DecodeRune(remainder) + remainder = b[length+l:] + + graphemeState, prop, graphemeBoundary = transitionGraphemeState(graphemeState, r) + wordState, wordBoundary = transitionWordBreakState(wordState, r, remainder, "") + sentenceState, sentenceBoundary = transitionSentenceBreakState(sentenceState, r, remainder, "") + lineState, lineBreak = transitionLineBreakState(lineState, r, remainder, "") + + if graphemeBoundary { + boundary := lineBreak | (width << ShiftWidth) + if wordBoundary { + boundary |= 1 << shiftWord + } + if sentenceBoundary { + boundary |= 1 << shiftSentence + } + return b[:length], b[length:], boundary, graphemeState | (wordState << shiftWordState) | (sentenceState << shiftSentenceState) | (lineState << shiftLineState) | (prop << shiftPropState) + } + + if firstProp == prExtendedPictographic { + if r == vs15 { + width = 1 + } else if r == vs16 { + width = 2 + } + } else if firstProp != prRegionalIndicator && firstProp != prL { + width += runeWidth(r, prop) + } + + length += l + if len(b) <= length { + return b, nil, LineMustBreak | (1 << shiftWord) | (1 << shiftSentence) | (width << ShiftWidth), grAny | (wbAny << shiftWordState) | (sbAny << shiftSentenceState) | (lbAny << shiftLineState) | (prop << shiftPropState) + } + } +} + +// StepString is like [Step] but its input and outputs are strings. +func StepString(str string, state int) (cluster, rest string, boundaries int, newState int) { + // An empty byte slice returns nothing. + if len(str) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRuneInString(str) + if len(str) <= length { // If we're already past the end, there is nothing else to parse. + prop := propertyGraphemes(r) + return str, "", LineMustBreak | (1 << shiftWord) | (1 << shiftSentence) | (runeWidth(r, prop) << ShiftWidth), grAny | (wbAny << shiftWordState) | (sbAny << shiftSentenceState) | (lbAny << shiftLineState) + } + + // If we don't know the state, determine it now. + var graphemeState, wordState, sentenceState, lineState, firstProp int + remainder := str[length:] + if state < 0 { + graphemeState, firstProp, _ = transitionGraphemeState(state, r) + wordState, _ = transitionWordBreakState(state, r, nil, remainder) + sentenceState, _ = transitionSentenceBreakState(state, r, nil, remainder) + lineState, _ = transitionLineBreakState(state, r, nil, remainder) + } else { + graphemeState = state & maskGraphemeState + wordState = (state >> shiftWordState) & maskWordState + sentenceState = (state >> shiftSentenceState) & maskSentenceState + lineState = (state >> shiftLineState) & maskLineState + firstProp = state >> shiftPropState + } + + // Transition until we find a grapheme cluster boundary. + width := runeWidth(r, firstProp) + for { + var ( + graphemeBoundary, wordBoundary, sentenceBoundary bool + lineBreak, prop int + ) + + r, l := utf8.DecodeRuneInString(remainder) + remainder = str[length+l:] + + graphemeState, prop, graphemeBoundary = transitionGraphemeState(graphemeState, r) + wordState, wordBoundary = transitionWordBreakState(wordState, r, nil, remainder) + sentenceState, sentenceBoundary = transitionSentenceBreakState(sentenceState, r, nil, remainder) + lineState, lineBreak = transitionLineBreakState(lineState, r, nil, remainder) + + if graphemeBoundary { + boundary := lineBreak | (width << ShiftWidth) + if wordBoundary { + boundary |= 1 << shiftWord + } + if sentenceBoundary { + boundary |= 1 << shiftSentence + } + return str[:length], str[length:], boundary, graphemeState | (wordState << shiftWordState) | (sentenceState << shiftSentenceState) | (lineState << shiftLineState) | (prop << shiftPropState) + } + + if firstProp == prExtendedPictographic { + if r == vs15 { + width = 1 + } else if r == vs16 { + width = 2 + } + } else if firstProp != prRegionalIndicator && firstProp != prL { + width += runeWidth(r, prop) + } + + length += l + if len(str) <= length { + return str, "", LineMustBreak | (1 << shiftWord) | (1 << shiftSentence) | (width << ShiftWidth), grAny | (wbAny << shiftWordState) | (sbAny << shiftSentenceState) | (lbAny << shiftLineState) | (prop << shiftPropState) + } + } +} diff --git a/vendor/github.com/rivo/uniseg/width.go b/vendor/github.com/rivo/uniseg/width.go new file mode 100644 index 000000000..975a9f134 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/width.go @@ -0,0 +1,61 @@ +package uniseg + +// EastAsianAmbiguousWidth specifies the monospace width for East Asian +// characters classified as Ambiguous. The default is 1 but some rare fonts +// render them with a width of 2. +var EastAsianAmbiguousWidth = 1 + +// runeWidth returns the monospace width for the given rune. The provided +// grapheme property is a value mapped by the [graphemeCodePoints] table. +// +// Every rune has a width of 1, except for runes with the following properties +// (evaluated in this order): +// +// - Control, CR, LF, Extend, ZWJ: Width of 0 +// - \u2e3a, TWO-EM DASH: Width of 3 +// - \u2e3b, THREE-EM DASH: Width of 4 +// - East-Asian width Fullwidth and Wide: Width of 2 (Ambiguous and Neutral +// have a width of 1) +// - Regional Indicator: Width of 2 +// - Extended Pictographic: Width of 2, unless Emoji Presentation is "No". +func runeWidth(r rune, graphemeProperty int) int { + switch graphemeProperty { + case prControl, prCR, prLF, prExtend, prZWJ: + return 0 + case prRegionalIndicator: + return 2 + case prExtendedPictographic: + if property(emojiPresentation, r) == prEmojiPresentation { + return 2 + } + return 1 + } + + switch r { + case 0x2e3a: + return 3 + case 0x2e3b: + return 4 + } + + switch propertyEastAsianWidth(r) { + case prW, prF: + return 2 + case prA: + return EastAsianAmbiguousWidth + } + + return 1 +} + +// StringWidth returns the monospace width for the given string, that is, the +// number of same-size cells to be occupied by the string. +func StringWidth(s string) (width int) { + state := -1 + for len(s) > 0 { + var w int + _, s, w, state = FirstGraphemeClusterInString(s, state) + width += w + } + return +} diff --git a/vendor/github.com/rivo/uniseg/word.go b/vendor/github.com/rivo/uniseg/word.go new file mode 100644 index 000000000..34fba7f29 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/word.go @@ -0,0 +1,89 @@ +package uniseg + +import "unicode/utf8" + +// FirstWord returns the first word found in the given byte slice according to +// the rules of [Unicode Standard Annex #29, Word Boundaries]. This function can +// be called continuously to extract all words from a byte slice, as illustrated +// in the example below. +// +// If you don't know the current state, for example when calling the function +// for the first time, you must pass -1. For consecutive calls, pass the state +// and rest slice returned by the previous call. +// +// The "rest" slice is the sub-slice of the original byte slice "b" starting +// after the last byte of the identified word. If the length of the "rest" slice +// is 0, the entire byte slice "b" has been processed. The "word" byte slice is +// the sub-slice of the input slice containing the identified word. +// +// Given an empty byte slice "b", the function returns nil values. +// +// [Unicode Standard Annex #29, Word Boundaries]: http://unicode.org/reports/tr29/#Word_Boundaries +func FirstWord(b []byte, state int) (word, rest []byte, newState int) { + // An empty byte slice returns nothing. + if len(b) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRune(b) + if len(b) <= length { // If we're already past the end, there is nothing else to parse. + return b, nil, wbAny + } + + // If we don't know the state, determine it now. + if state < 0 { + state, _ = transitionWordBreakState(state, r, b[length:], "") + } + + // Transition until we find a boundary. + var boundary bool + for { + r, l := utf8.DecodeRune(b[length:]) + state, boundary = transitionWordBreakState(state, r, b[length+l:], "") + + if boundary { + return b[:length], b[length:], state + } + + length += l + if len(b) <= length { + return b, nil, wbAny + } + } +} + +// FirstWordInString is like [FirstWord] but its input and outputs are strings. +func FirstWordInString(str string, state int) (word, rest string, newState int) { + // An empty byte slice returns nothing. + if len(str) == 0 { + return + } + + // Extract the first rune. + r, length := utf8.DecodeRuneInString(str) + if len(str) <= length { // If we're already past the end, there is nothing else to parse. + return str, "", wbAny + } + + // If we don't know the state, determine it now. + if state < 0 { + state, _ = transitionWordBreakState(state, r, nil, str[length:]) + } + + // Transition until we find a boundary. + var boundary bool + for { + r, l := utf8.DecodeRuneInString(str[length:]) + state, boundary = transitionWordBreakState(state, r, nil, str[length+l:]) + + if boundary { + return str[:length], str[length:], state + } + + length += l + if len(str) <= length { + return str, "", wbAny + } + } +} diff --git a/vendor/github.com/rivo/uniseg/wordproperties.go b/vendor/github.com/rivo/uniseg/wordproperties.go new file mode 100644 index 000000000..277ca1006 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/wordproperties.go @@ -0,0 +1,1883 @@ +// Code generated via go generate from gen_properties.go. DO NOT EDIT. + +package uniseg + +// workBreakCodePoints are taken from +// https://www.unicode.org/Public/15.0.0/ucd/auxiliary/WordBreakProperty.txt +// and +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt +// ("Extended_Pictographic" only) +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode +// license agreement. +var workBreakCodePoints = [][3]int{ + {0x000A, 0x000A, prLF}, // Cc + {0x000B, 0x000C, prNewline}, // Cc [2] .. + {0x000D, 0x000D, prCR}, // Cc + {0x0020, 0x0020, prWSegSpace}, // Zs SPACE + {0x0022, 0x0022, prDoubleQuote}, // Po QUOTATION MARK + {0x0027, 0x0027, prSingleQuote}, // Po APOSTROPHE + {0x002C, 0x002C, prMidNum}, // Po COMMA + {0x002E, 0x002E, prMidNumLet}, // Po FULL STOP + {0x0030, 0x0039, prNumeric}, // Nd [10] DIGIT ZERO..DIGIT NINE + {0x003A, 0x003A, prMidLetter}, // Po COLON + {0x003B, 0x003B, prMidNum}, // Po SEMICOLON + {0x0041, 0x005A, prALetter}, // L& [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z + {0x005F, 0x005F, prExtendNumLet}, // Pc LOW LINE + {0x0061, 0x007A, prALetter}, // L& [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z + {0x0085, 0x0085, prNewline}, // Cc + {0x00A9, 0x00A9, prExtendedPictographic}, // E0.6 [1] (©️) copyright + {0x00AA, 0x00AA, prALetter}, // Lo FEMININE ORDINAL INDICATOR + {0x00AD, 0x00AD, prFormat}, // Cf SOFT HYPHEN + {0x00AE, 0x00AE, prExtendedPictographic}, // E0.6 [1] (®️) registered + {0x00B5, 0x00B5, prALetter}, // L& MICRO SIGN + {0x00B7, 0x00B7, prMidLetter}, // Po MIDDLE DOT + {0x00BA, 0x00BA, prALetter}, // Lo MASCULINE ORDINAL INDICATOR + {0x00C0, 0x00D6, prALetter}, // L& [23] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER O WITH DIAERESIS + {0x00D8, 0x00F6, prALetter}, // L& [31] LATIN CAPITAL LETTER O WITH STROKE..LATIN SMALL LETTER O WITH DIAERESIS + {0x00F8, 0x01BA, prALetter}, // L& [195] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL + {0x01BB, 0x01BB, prALetter}, // Lo LATIN LETTER TWO WITH STROKE + {0x01BC, 0x01BF, prALetter}, // L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN + {0x01C0, 0x01C3, prALetter}, // Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK + {0x01C4, 0x0293, prALetter}, // L& [208] LATIN CAPITAL LETTER DZ WITH CARON..LATIN SMALL LETTER EZH WITH CURL + {0x0294, 0x0294, prALetter}, // Lo LATIN LETTER GLOTTAL STOP + {0x0295, 0x02AF, prALetter}, // L& [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL + {0x02B0, 0x02C1, prALetter}, // Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP + {0x02C2, 0x02C5, prALetter}, // Sk [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD + {0x02C6, 0x02D1, prALetter}, // Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON + {0x02D2, 0x02D7, prALetter}, // Sk [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN + {0x02DE, 0x02DF, prALetter}, // Sk [2] MODIFIER LETTER RHOTIC HOOK..MODIFIER LETTER CROSS ACCENT + {0x02E0, 0x02E4, prALetter}, // Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP + {0x02E5, 0x02EB, prALetter}, // Sk [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK + {0x02EC, 0x02EC, prALetter}, // Lm MODIFIER LETTER VOICING + {0x02ED, 0x02ED, prALetter}, // Sk MODIFIER LETTER UNASPIRATED + {0x02EE, 0x02EE, prALetter}, // Lm MODIFIER LETTER DOUBLE APOSTROPHE + {0x02EF, 0x02FF, prALetter}, // Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW + {0x0300, 0x036F, prExtend}, // Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X + {0x0370, 0x0373, prALetter}, // L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI + {0x0374, 0x0374, prALetter}, // Lm GREEK NUMERAL SIGN + {0x0376, 0x0377, prALetter}, // L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA + {0x037A, 0x037A, prALetter}, // Lm GREEK YPOGEGRAMMENI + {0x037B, 0x037D, prALetter}, // L& [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL + {0x037E, 0x037E, prMidNum}, // Po GREEK QUESTION MARK + {0x037F, 0x037F, prALetter}, // L& GREEK CAPITAL LETTER YOT + {0x0386, 0x0386, prALetter}, // L& GREEK CAPITAL LETTER ALPHA WITH TONOS + {0x0387, 0x0387, prMidLetter}, // Po GREEK ANO TELEIA + {0x0388, 0x038A, prALetter}, // L& [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS + {0x038C, 0x038C, prALetter}, // L& GREEK CAPITAL LETTER OMICRON WITH TONOS + {0x038E, 0x03A1, prALetter}, // L& [20] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER RHO + {0x03A3, 0x03F5, prALetter}, // L& [83] GREEK CAPITAL LETTER SIGMA..GREEK LUNATE EPSILON SYMBOL + {0x03F7, 0x0481, prALetter}, // L& [139] GREEK CAPITAL LETTER SHO..CYRILLIC SMALL LETTER KOPPA + {0x0483, 0x0487, prExtend}, // Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE + {0x0488, 0x0489, prExtend}, // Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN + {0x048A, 0x052F, prALetter}, // L& [166] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER EL WITH DESCENDER + {0x0531, 0x0556, prALetter}, // L& [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH + {0x0559, 0x0559, prALetter}, // Lm ARMENIAN MODIFIER LETTER LEFT HALF RING + {0x055A, 0x055C, prALetter}, // Po [3] ARMENIAN APOSTROPHE..ARMENIAN EXCLAMATION MARK + {0x055E, 0x055E, prALetter}, // Po ARMENIAN QUESTION MARK + {0x055F, 0x055F, prMidLetter}, // Po ARMENIAN ABBREVIATION MARK + {0x0560, 0x0588, prALetter}, // L& [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE + {0x0589, 0x0589, prMidNum}, // Po ARMENIAN FULL STOP + {0x058A, 0x058A, prALetter}, // Pd ARMENIAN HYPHEN + {0x0591, 0x05BD, prExtend}, // Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG + {0x05BF, 0x05BF, prExtend}, // Mn HEBREW POINT RAFE + {0x05C1, 0x05C2, prExtend}, // Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT + {0x05C4, 0x05C5, prExtend}, // Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT + {0x05C7, 0x05C7, prExtend}, // Mn HEBREW POINT QAMATS QATAN + {0x05D0, 0x05EA, prHebrewLetter}, // Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV + {0x05EF, 0x05F2, prHebrewLetter}, // Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD + {0x05F3, 0x05F3, prALetter}, // Po HEBREW PUNCTUATION GERESH + {0x05F4, 0x05F4, prMidLetter}, // Po HEBREW PUNCTUATION GERSHAYIM + {0x0600, 0x0605, prFormat}, // Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE + {0x060C, 0x060D, prMidNum}, // Po [2] ARABIC COMMA..ARABIC DATE SEPARATOR + {0x0610, 0x061A, prExtend}, // Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA + {0x061C, 0x061C, prFormat}, // Cf ARABIC LETTER MARK + {0x0620, 0x063F, prALetter}, // Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE + {0x0640, 0x0640, prALetter}, // Lm ARABIC TATWEEL + {0x0641, 0x064A, prALetter}, // Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH + {0x064B, 0x065F, prExtend}, // Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW + {0x0660, 0x0669, prNumeric}, // Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE + {0x066B, 0x066B, prNumeric}, // Po ARABIC DECIMAL SEPARATOR + {0x066C, 0x066C, prMidNum}, // Po ARABIC THOUSANDS SEPARATOR + {0x066E, 0x066F, prALetter}, // Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF + {0x0670, 0x0670, prExtend}, // Mn ARABIC LETTER SUPERSCRIPT ALEF + {0x0671, 0x06D3, prALetter}, // Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE + {0x06D5, 0x06D5, prALetter}, // Lo ARABIC LETTER AE + {0x06D6, 0x06DC, prExtend}, // Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN + {0x06DD, 0x06DD, prFormat}, // Cf ARABIC END OF AYAH + {0x06DF, 0x06E4, prExtend}, // Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA + {0x06E5, 0x06E6, prALetter}, // Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH + {0x06E7, 0x06E8, prExtend}, // Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON + {0x06EA, 0x06ED, prExtend}, // Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM + {0x06EE, 0x06EF, prALetter}, // Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V + {0x06F0, 0x06F9, prNumeric}, // Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE + {0x06FA, 0x06FC, prALetter}, // Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW + {0x06FF, 0x06FF, prALetter}, // Lo ARABIC LETTER HEH WITH INVERTED V + {0x070F, 0x070F, prFormat}, // Cf SYRIAC ABBREVIATION MARK + {0x0710, 0x0710, prALetter}, // Lo SYRIAC LETTER ALAPH + {0x0711, 0x0711, prExtend}, // Mn SYRIAC LETTER SUPERSCRIPT ALAPH + {0x0712, 0x072F, prALetter}, // Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH + {0x0730, 0x074A, prExtend}, // Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH + {0x074D, 0x07A5, prALetter}, // Lo [89] SYRIAC LETTER SOGDIAN ZHAIN..THAANA LETTER WAAVU + {0x07A6, 0x07B0, prExtend}, // Mn [11] THAANA ABAFILI..THAANA SUKUN + {0x07B1, 0x07B1, prALetter}, // Lo THAANA LETTER NAA + {0x07C0, 0x07C9, prNumeric}, // Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE + {0x07CA, 0x07EA, prALetter}, // Lo [33] NKO LETTER A..NKO LETTER JONA RA + {0x07EB, 0x07F3, prExtend}, // Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE + {0x07F4, 0x07F5, prALetter}, // Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE + {0x07F8, 0x07F8, prMidNum}, // Po NKO COMMA + {0x07FA, 0x07FA, prALetter}, // Lm NKO LAJANYALAN + {0x07FD, 0x07FD, prExtend}, // Mn NKO DANTAYALAN + {0x0800, 0x0815, prALetter}, // Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF + {0x0816, 0x0819, prExtend}, // Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH + {0x081A, 0x081A, prALetter}, // Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT + {0x081B, 0x0823, prExtend}, // Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A + {0x0824, 0x0824, prALetter}, // Lm SAMARITAN MODIFIER LETTER SHORT A + {0x0825, 0x0827, prExtend}, // Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U + {0x0828, 0x0828, prALetter}, // Lm SAMARITAN MODIFIER LETTER I + {0x0829, 0x082D, prExtend}, // Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA + {0x0840, 0x0858, prALetter}, // Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN + {0x0859, 0x085B, prExtend}, // Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK + {0x0860, 0x086A, prALetter}, // Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA + {0x0870, 0x0887, prALetter}, // Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT + {0x0889, 0x088E, prALetter}, // Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL + {0x0890, 0x0891, prFormat}, // Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE + {0x0898, 0x089F, prExtend}, // Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA + {0x08A0, 0x08C8, prALetter}, // Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF + {0x08C9, 0x08C9, prALetter}, // Lm ARABIC SMALL FARSI YEH + {0x08CA, 0x08E1, prExtend}, // Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA + {0x08E2, 0x08E2, prFormat}, // Cf ARABIC DISPUTED END OF AYAH + {0x08E3, 0x0902, prExtend}, // Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA + {0x0903, 0x0903, prExtend}, // Mc DEVANAGARI SIGN VISARGA + {0x0904, 0x0939, prALetter}, // Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA + {0x093A, 0x093A, prExtend}, // Mn DEVANAGARI VOWEL SIGN OE + {0x093B, 0x093B, prExtend}, // Mc DEVANAGARI VOWEL SIGN OOE + {0x093C, 0x093C, prExtend}, // Mn DEVANAGARI SIGN NUKTA + {0x093D, 0x093D, prALetter}, // Lo DEVANAGARI SIGN AVAGRAHA + {0x093E, 0x0940, prExtend}, // Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II + {0x0941, 0x0948, prExtend}, // Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI + {0x0949, 0x094C, prExtend}, // Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU + {0x094D, 0x094D, prExtend}, // Mn DEVANAGARI SIGN VIRAMA + {0x094E, 0x094F, prExtend}, // Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW + {0x0950, 0x0950, prALetter}, // Lo DEVANAGARI OM + {0x0951, 0x0957, prExtend}, // Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE + {0x0958, 0x0961, prALetter}, // Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL + {0x0962, 0x0963, prExtend}, // Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL + {0x0966, 0x096F, prNumeric}, // Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE + {0x0971, 0x0971, prALetter}, // Lm DEVANAGARI SIGN HIGH SPACING DOT + {0x0972, 0x0980, prALetter}, // Lo [15] DEVANAGARI LETTER CANDRA A..BENGALI ANJI + {0x0981, 0x0981, prExtend}, // Mn BENGALI SIGN CANDRABINDU + {0x0982, 0x0983, prExtend}, // Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA + {0x0985, 0x098C, prALetter}, // Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L + {0x098F, 0x0990, prALetter}, // Lo [2] BENGALI LETTER E..BENGALI LETTER AI + {0x0993, 0x09A8, prALetter}, // Lo [22] BENGALI LETTER O..BENGALI LETTER NA + {0x09AA, 0x09B0, prALetter}, // Lo [7] BENGALI LETTER PA..BENGALI LETTER RA + {0x09B2, 0x09B2, prALetter}, // Lo BENGALI LETTER LA + {0x09B6, 0x09B9, prALetter}, // Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA + {0x09BC, 0x09BC, prExtend}, // Mn BENGALI SIGN NUKTA + {0x09BD, 0x09BD, prALetter}, // Lo BENGALI SIGN AVAGRAHA + {0x09BE, 0x09C0, prExtend}, // Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II + {0x09C1, 0x09C4, prExtend}, // Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR + {0x09C7, 0x09C8, prExtend}, // Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI + {0x09CB, 0x09CC, prExtend}, // Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU + {0x09CD, 0x09CD, prExtend}, // Mn BENGALI SIGN VIRAMA + {0x09CE, 0x09CE, prALetter}, // Lo BENGALI LETTER KHANDA TA + {0x09D7, 0x09D7, prExtend}, // Mc BENGALI AU LENGTH MARK + {0x09DC, 0x09DD, prALetter}, // Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA + {0x09DF, 0x09E1, prALetter}, // Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL + {0x09E2, 0x09E3, prExtend}, // Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL + {0x09E6, 0x09EF, prNumeric}, // Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE + {0x09F0, 0x09F1, prALetter}, // Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL + {0x09FC, 0x09FC, prALetter}, // Lo BENGALI LETTER VEDIC ANUSVARA + {0x09FE, 0x09FE, prExtend}, // Mn BENGALI SANDHI MARK + {0x0A01, 0x0A02, prExtend}, // Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI + {0x0A03, 0x0A03, prExtend}, // Mc GURMUKHI SIGN VISARGA + {0x0A05, 0x0A0A, prALetter}, // Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU + {0x0A0F, 0x0A10, prALetter}, // Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI + {0x0A13, 0x0A28, prALetter}, // Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA + {0x0A2A, 0x0A30, prALetter}, // Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA + {0x0A32, 0x0A33, prALetter}, // Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA + {0x0A35, 0x0A36, prALetter}, // Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA + {0x0A38, 0x0A39, prALetter}, // Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA + {0x0A3C, 0x0A3C, prExtend}, // Mn GURMUKHI SIGN NUKTA + {0x0A3E, 0x0A40, prExtend}, // Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II + {0x0A41, 0x0A42, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU + {0x0A47, 0x0A48, prExtend}, // Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI + {0x0A4B, 0x0A4D, prExtend}, // Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA + {0x0A51, 0x0A51, prExtend}, // Mn GURMUKHI SIGN UDAAT + {0x0A59, 0x0A5C, prALetter}, // Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA + {0x0A5E, 0x0A5E, prALetter}, // Lo GURMUKHI LETTER FA + {0x0A66, 0x0A6F, prNumeric}, // Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE + {0x0A70, 0x0A71, prExtend}, // Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK + {0x0A72, 0x0A74, prALetter}, // Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR + {0x0A75, 0x0A75, prExtend}, // Mn GURMUKHI SIGN YAKASH + {0x0A81, 0x0A82, prExtend}, // Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA + {0x0A83, 0x0A83, prExtend}, // Mc GUJARATI SIGN VISARGA + {0x0A85, 0x0A8D, prALetter}, // Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E + {0x0A8F, 0x0A91, prALetter}, // Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O + {0x0A93, 0x0AA8, prALetter}, // Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA + {0x0AAA, 0x0AB0, prALetter}, // Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA + {0x0AB2, 0x0AB3, prALetter}, // Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA + {0x0AB5, 0x0AB9, prALetter}, // Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA + {0x0ABC, 0x0ABC, prExtend}, // Mn GUJARATI SIGN NUKTA + {0x0ABD, 0x0ABD, prALetter}, // Lo GUJARATI SIGN AVAGRAHA + {0x0ABE, 0x0AC0, prExtend}, // Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II + {0x0AC1, 0x0AC5, prExtend}, // Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E + {0x0AC7, 0x0AC8, prExtend}, // Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI + {0x0AC9, 0x0AC9, prExtend}, // Mc GUJARATI VOWEL SIGN CANDRA O + {0x0ACB, 0x0ACC, prExtend}, // Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU + {0x0ACD, 0x0ACD, prExtend}, // Mn GUJARATI SIGN VIRAMA + {0x0AD0, 0x0AD0, prALetter}, // Lo GUJARATI OM + {0x0AE0, 0x0AE1, prALetter}, // Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL + {0x0AE2, 0x0AE3, prExtend}, // Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL + {0x0AE6, 0x0AEF, prNumeric}, // Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE + {0x0AF9, 0x0AF9, prALetter}, // Lo GUJARATI LETTER ZHA + {0x0AFA, 0x0AFF, prExtend}, // Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE + {0x0B01, 0x0B01, prExtend}, // Mn ORIYA SIGN CANDRABINDU + {0x0B02, 0x0B03, prExtend}, // Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA + {0x0B05, 0x0B0C, prALetter}, // Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L + {0x0B0F, 0x0B10, prALetter}, // Lo [2] ORIYA LETTER E..ORIYA LETTER AI + {0x0B13, 0x0B28, prALetter}, // Lo [22] ORIYA LETTER O..ORIYA LETTER NA + {0x0B2A, 0x0B30, prALetter}, // Lo [7] ORIYA LETTER PA..ORIYA LETTER RA + {0x0B32, 0x0B33, prALetter}, // Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA + {0x0B35, 0x0B39, prALetter}, // Lo [5] ORIYA LETTER VA..ORIYA LETTER HA + {0x0B3C, 0x0B3C, prExtend}, // Mn ORIYA SIGN NUKTA + {0x0B3D, 0x0B3D, prALetter}, // Lo ORIYA SIGN AVAGRAHA + {0x0B3E, 0x0B3E, prExtend}, // Mc ORIYA VOWEL SIGN AA + {0x0B3F, 0x0B3F, prExtend}, // Mn ORIYA VOWEL SIGN I + {0x0B40, 0x0B40, prExtend}, // Mc ORIYA VOWEL SIGN II + {0x0B41, 0x0B44, prExtend}, // Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR + {0x0B47, 0x0B48, prExtend}, // Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI + {0x0B4B, 0x0B4C, prExtend}, // Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU + {0x0B4D, 0x0B4D, prExtend}, // Mn ORIYA SIGN VIRAMA + {0x0B55, 0x0B56, prExtend}, // Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK + {0x0B57, 0x0B57, prExtend}, // Mc ORIYA AU LENGTH MARK + {0x0B5C, 0x0B5D, prALetter}, // Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA + {0x0B5F, 0x0B61, prALetter}, // Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL + {0x0B62, 0x0B63, prExtend}, // Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL + {0x0B66, 0x0B6F, prNumeric}, // Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE + {0x0B71, 0x0B71, prALetter}, // Lo ORIYA LETTER WA + {0x0B82, 0x0B82, prExtend}, // Mn TAMIL SIGN ANUSVARA + {0x0B83, 0x0B83, prALetter}, // Lo TAMIL SIGN VISARGA + {0x0B85, 0x0B8A, prALetter}, // Lo [6] TAMIL LETTER A..TAMIL LETTER UU + {0x0B8E, 0x0B90, prALetter}, // Lo [3] TAMIL LETTER E..TAMIL LETTER AI + {0x0B92, 0x0B95, prALetter}, // Lo [4] TAMIL LETTER O..TAMIL LETTER KA + {0x0B99, 0x0B9A, prALetter}, // Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA + {0x0B9C, 0x0B9C, prALetter}, // Lo TAMIL LETTER JA + {0x0B9E, 0x0B9F, prALetter}, // Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA + {0x0BA3, 0x0BA4, prALetter}, // Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA + {0x0BA8, 0x0BAA, prALetter}, // Lo [3] TAMIL LETTER NA..TAMIL LETTER PA + {0x0BAE, 0x0BB9, prALetter}, // Lo [12] TAMIL LETTER MA..TAMIL LETTER HA + {0x0BBE, 0x0BBF, prExtend}, // Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I + {0x0BC0, 0x0BC0, prExtend}, // Mn TAMIL VOWEL SIGN II + {0x0BC1, 0x0BC2, prExtend}, // Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU + {0x0BC6, 0x0BC8, prExtend}, // Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI + {0x0BCA, 0x0BCC, prExtend}, // Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU + {0x0BCD, 0x0BCD, prExtend}, // Mn TAMIL SIGN VIRAMA + {0x0BD0, 0x0BD0, prALetter}, // Lo TAMIL OM + {0x0BD7, 0x0BD7, prExtend}, // Mc TAMIL AU LENGTH MARK + {0x0BE6, 0x0BEF, prNumeric}, // Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE + {0x0C00, 0x0C00, prExtend}, // Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE + {0x0C01, 0x0C03, prExtend}, // Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA + {0x0C04, 0x0C04, prExtend}, // Mn TELUGU SIGN COMBINING ANUSVARA ABOVE + {0x0C05, 0x0C0C, prALetter}, // Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L + {0x0C0E, 0x0C10, prALetter}, // Lo [3] TELUGU LETTER E..TELUGU LETTER AI + {0x0C12, 0x0C28, prALetter}, // Lo [23] TELUGU LETTER O..TELUGU LETTER NA + {0x0C2A, 0x0C39, prALetter}, // Lo [16] TELUGU LETTER PA..TELUGU LETTER HA + {0x0C3C, 0x0C3C, prExtend}, // Mn TELUGU SIGN NUKTA + {0x0C3D, 0x0C3D, prALetter}, // Lo TELUGU SIGN AVAGRAHA + {0x0C3E, 0x0C40, prExtend}, // Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II + {0x0C41, 0x0C44, prExtend}, // Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR + {0x0C46, 0x0C48, prExtend}, // Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI + {0x0C4A, 0x0C4D, prExtend}, // Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA + {0x0C55, 0x0C56, prExtend}, // Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK + {0x0C58, 0x0C5A, prALetter}, // Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA + {0x0C5D, 0x0C5D, prALetter}, // Lo TELUGU LETTER NAKAARA POLLU + {0x0C60, 0x0C61, prALetter}, // Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL + {0x0C62, 0x0C63, prExtend}, // Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL + {0x0C66, 0x0C6F, prNumeric}, // Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE + {0x0C80, 0x0C80, prALetter}, // Lo KANNADA SIGN SPACING CANDRABINDU + {0x0C81, 0x0C81, prExtend}, // Mn KANNADA SIGN CANDRABINDU + {0x0C82, 0x0C83, prExtend}, // Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA + {0x0C85, 0x0C8C, prALetter}, // Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L + {0x0C8E, 0x0C90, prALetter}, // Lo [3] KANNADA LETTER E..KANNADA LETTER AI + {0x0C92, 0x0CA8, prALetter}, // Lo [23] KANNADA LETTER O..KANNADA LETTER NA + {0x0CAA, 0x0CB3, prALetter}, // Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA + {0x0CB5, 0x0CB9, prALetter}, // Lo [5] KANNADA LETTER VA..KANNADA LETTER HA + {0x0CBC, 0x0CBC, prExtend}, // Mn KANNADA SIGN NUKTA + {0x0CBD, 0x0CBD, prALetter}, // Lo KANNADA SIGN AVAGRAHA + {0x0CBE, 0x0CBE, prExtend}, // Mc KANNADA VOWEL SIGN AA + {0x0CBF, 0x0CBF, prExtend}, // Mn KANNADA VOWEL SIGN I + {0x0CC0, 0x0CC4, prExtend}, // Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR + {0x0CC6, 0x0CC6, prExtend}, // Mn KANNADA VOWEL SIGN E + {0x0CC7, 0x0CC8, prExtend}, // Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI + {0x0CCA, 0x0CCB, prExtend}, // Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO + {0x0CCC, 0x0CCD, prExtend}, // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA + {0x0CD5, 0x0CD6, prExtend}, // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK + {0x0CDD, 0x0CDE, prALetter}, // Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA + {0x0CE0, 0x0CE1, prALetter}, // Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL + {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0CE6, 0x0CEF, prNumeric}, // Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE + {0x0CF1, 0x0CF2, prALetter}, // Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prExtend}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT + {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU + {0x0D02, 0x0D03, prExtend}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA + {0x0D04, 0x0D0C, prALetter}, // Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L + {0x0D0E, 0x0D10, prALetter}, // Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI + {0x0D12, 0x0D3A, prALetter}, // Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA + {0x0D3B, 0x0D3C, prExtend}, // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA + {0x0D3D, 0x0D3D, prALetter}, // Lo MALAYALAM SIGN AVAGRAHA + {0x0D3E, 0x0D40, prExtend}, // Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II + {0x0D41, 0x0D44, prExtend}, // Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR + {0x0D46, 0x0D48, prExtend}, // Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI + {0x0D4A, 0x0D4C, prExtend}, // Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU + {0x0D4D, 0x0D4D, prExtend}, // Mn MALAYALAM SIGN VIRAMA + {0x0D4E, 0x0D4E, prALetter}, // Lo MALAYALAM LETTER DOT REPH + {0x0D54, 0x0D56, prALetter}, // Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL + {0x0D57, 0x0D57, prExtend}, // Mc MALAYALAM AU LENGTH MARK + {0x0D5F, 0x0D61, prALetter}, // Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL + {0x0D62, 0x0D63, prExtend}, // Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL + {0x0D66, 0x0D6F, prNumeric}, // Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE + {0x0D7A, 0x0D7F, prALetter}, // Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K + {0x0D81, 0x0D81, prExtend}, // Mn SINHALA SIGN CANDRABINDU + {0x0D82, 0x0D83, prExtend}, // Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA + {0x0D85, 0x0D96, prALetter}, // Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA + {0x0D9A, 0x0DB1, prALetter}, // Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA + {0x0DB3, 0x0DBB, prALetter}, // Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA + {0x0DBD, 0x0DBD, prALetter}, // Lo SINHALA LETTER DANTAJA LAYANNA + {0x0DC0, 0x0DC6, prALetter}, // Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA + {0x0DCA, 0x0DCA, prExtend}, // Mn SINHALA SIGN AL-LAKUNA + {0x0DCF, 0x0DD1, prExtend}, // Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA + {0x0DD2, 0x0DD4, prExtend}, // Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA + {0x0DD6, 0x0DD6, prExtend}, // Mn SINHALA VOWEL SIGN DIGA PAA-PILLA + {0x0DD8, 0x0DDF, prExtend}, // Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA + {0x0DE6, 0x0DEF, prNumeric}, // Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE + {0x0DF2, 0x0DF3, prExtend}, // Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA + {0x0E31, 0x0E31, prExtend}, // Mn THAI CHARACTER MAI HAN-AKAT + {0x0E34, 0x0E3A, prExtend}, // Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU + {0x0E47, 0x0E4E, prExtend}, // Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN + {0x0E50, 0x0E59, prNumeric}, // Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE + {0x0EB1, 0x0EB1, prExtend}, // Mn LAO VOWEL SIGN MAI KAN + {0x0EB4, 0x0EBC, prExtend}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO + {0x0EC8, 0x0ECE, prExtend}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN + {0x0ED0, 0x0ED9, prNumeric}, // Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE + {0x0F00, 0x0F00, prALetter}, // Lo TIBETAN SYLLABLE OM + {0x0F18, 0x0F19, prExtend}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS + {0x0F20, 0x0F29, prNumeric}, // Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE + {0x0F35, 0x0F35, prExtend}, // Mn TIBETAN MARK NGAS BZUNG NYI ZLA + {0x0F37, 0x0F37, prExtend}, // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS + {0x0F39, 0x0F39, prExtend}, // Mn TIBETAN MARK TSA -PHRU + {0x0F3E, 0x0F3F, prExtend}, // Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES + {0x0F40, 0x0F47, prALetter}, // Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA + {0x0F49, 0x0F6C, prALetter}, // Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA + {0x0F71, 0x0F7E, prExtend}, // Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO + {0x0F7F, 0x0F7F, prExtend}, // Mc TIBETAN SIGN RNAM BCAD + {0x0F80, 0x0F84, prExtend}, // Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA + {0x0F86, 0x0F87, prExtend}, // Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS + {0x0F88, 0x0F8C, prALetter}, // Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN + {0x0F8D, 0x0F97, prExtend}, // Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA + {0x0F99, 0x0FBC, prExtend}, // Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA + {0x0FC6, 0x0FC6, prExtend}, // Mn TIBETAN SYMBOL PADMA GDAN + {0x102B, 0x102C, prExtend}, // Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA + {0x102D, 0x1030, prExtend}, // Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU + {0x1031, 0x1031, prExtend}, // Mc MYANMAR VOWEL SIGN E + {0x1032, 0x1037, prExtend}, // Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW + {0x1038, 0x1038, prExtend}, // Mc MYANMAR SIGN VISARGA + {0x1039, 0x103A, prExtend}, // Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT + {0x103B, 0x103C, prExtend}, // Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA + {0x103D, 0x103E, prExtend}, // Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA + {0x1040, 0x1049, prNumeric}, // Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE + {0x1056, 0x1057, prExtend}, // Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR + {0x1058, 0x1059, prExtend}, // Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL + {0x105E, 0x1060, prExtend}, // Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA + {0x1062, 0x1064, prExtend}, // Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO + {0x1067, 0x106D, prExtend}, // Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 + {0x1071, 0x1074, prExtend}, // Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE + {0x1082, 0x1082, prExtend}, // Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA + {0x1083, 0x1084, prExtend}, // Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E + {0x1085, 0x1086, prExtend}, // Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y + {0x1087, 0x108C, prExtend}, // Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 + {0x108D, 0x108D, prExtend}, // Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE + {0x108F, 0x108F, prExtend}, // Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 + {0x1090, 0x1099, prNumeric}, // Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE + {0x109A, 0x109C, prExtend}, // Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A + {0x109D, 0x109D, prExtend}, // Mn MYANMAR VOWEL SIGN AITON AI + {0x10A0, 0x10C5, prALetter}, // L& [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE + {0x10C7, 0x10C7, prALetter}, // L& GEORGIAN CAPITAL LETTER YN + {0x10CD, 0x10CD, prALetter}, // L& GEORGIAN CAPITAL LETTER AEN + {0x10D0, 0x10FA, prALetter}, // L& [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN + {0x10FC, 0x10FC, prALetter}, // Lm MODIFIER LETTER GEORGIAN NAR + {0x10FD, 0x10FF, prALetter}, // L& [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN + {0x1100, 0x1248, prALetter}, // Lo [329] HANGUL CHOSEONG KIYEOK..ETHIOPIC SYLLABLE QWA + {0x124A, 0x124D, prALetter}, // Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE + {0x1250, 0x1256, prALetter}, // Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO + {0x1258, 0x1258, prALetter}, // Lo ETHIOPIC SYLLABLE QHWA + {0x125A, 0x125D, prALetter}, // Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE + {0x1260, 0x1288, prALetter}, // Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA + {0x128A, 0x128D, prALetter}, // Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE + {0x1290, 0x12B0, prALetter}, // Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA + {0x12B2, 0x12B5, prALetter}, // Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE + {0x12B8, 0x12BE, prALetter}, // Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO + {0x12C0, 0x12C0, prALetter}, // Lo ETHIOPIC SYLLABLE KXWA + {0x12C2, 0x12C5, prALetter}, // Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE + {0x12C8, 0x12D6, prALetter}, // Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O + {0x12D8, 0x1310, prALetter}, // Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA + {0x1312, 0x1315, prALetter}, // Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE + {0x1318, 0x135A, prALetter}, // Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA + {0x135D, 0x135F, prExtend}, // Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK + {0x1380, 0x138F, prALetter}, // Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE + {0x13A0, 0x13F5, prALetter}, // L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV + {0x13F8, 0x13FD, prALetter}, // L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV + {0x1401, 0x166C, prALetter}, // Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA + {0x166F, 0x167F, prALetter}, // Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W + {0x1680, 0x1680, prWSegSpace}, // Zs OGHAM SPACE MARK + {0x1681, 0x169A, prALetter}, // Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH + {0x16A0, 0x16EA, prALetter}, // Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X + {0x16EE, 0x16F0, prALetter}, // Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL + {0x16F1, 0x16F8, prALetter}, // Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC + {0x1700, 0x1711, prALetter}, // Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA + {0x1712, 0x1714, prExtend}, // Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA + {0x1715, 0x1715, prExtend}, // Mc TAGALOG SIGN PAMUDPOD + {0x171F, 0x1731, prALetter}, // Lo [19] TAGALOG LETTER ARCHAIC RA..HANUNOO LETTER HA + {0x1732, 0x1733, prExtend}, // Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U + {0x1734, 0x1734, prExtend}, // Mc HANUNOO SIGN PAMUDPOD + {0x1740, 0x1751, prALetter}, // Lo [18] BUHID LETTER A..BUHID LETTER HA + {0x1752, 0x1753, prExtend}, // Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U + {0x1760, 0x176C, prALetter}, // Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA + {0x176E, 0x1770, prALetter}, // Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA + {0x1772, 0x1773, prExtend}, // Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U + {0x17B4, 0x17B5, prExtend}, // Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA + {0x17B6, 0x17B6, prExtend}, // Mc KHMER VOWEL SIGN AA + {0x17B7, 0x17BD, prExtend}, // Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA + {0x17BE, 0x17C5, prExtend}, // Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU + {0x17C6, 0x17C6, prExtend}, // Mn KHMER SIGN NIKAHIT + {0x17C7, 0x17C8, prExtend}, // Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU + {0x17C9, 0x17D3, prExtend}, // Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT + {0x17DD, 0x17DD, prExtend}, // Mn KHMER SIGN ATTHACAN + {0x17E0, 0x17E9, prNumeric}, // Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE + {0x180B, 0x180D, prExtend}, // Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE + {0x180E, 0x180E, prFormat}, // Cf MONGOLIAN VOWEL SEPARATOR + {0x180F, 0x180F, prExtend}, // Mn MONGOLIAN FREE VARIATION SELECTOR FOUR + {0x1810, 0x1819, prNumeric}, // Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE + {0x1820, 0x1842, prALetter}, // Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI + {0x1843, 0x1843, prALetter}, // Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN + {0x1844, 0x1878, prALetter}, // Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS + {0x1880, 0x1884, prALetter}, // Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA + {0x1885, 0x1886, prExtend}, // Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA + {0x1887, 0x18A8, prALetter}, // Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA + {0x18A9, 0x18A9, prExtend}, // Mn MONGOLIAN LETTER ALI GALI DAGALGA + {0x18AA, 0x18AA, prALetter}, // Lo MONGOLIAN LETTER MANCHU ALI GALI LHA + {0x18B0, 0x18F5, prALetter}, // Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S + {0x1900, 0x191E, prALetter}, // Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA + {0x1920, 0x1922, prExtend}, // Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U + {0x1923, 0x1926, prExtend}, // Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU + {0x1927, 0x1928, prExtend}, // Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O + {0x1929, 0x192B, prExtend}, // Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA + {0x1930, 0x1931, prExtend}, // Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA + {0x1932, 0x1932, prExtend}, // Mn LIMBU SMALL LETTER ANUSVARA + {0x1933, 0x1938, prExtend}, // Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA + {0x1939, 0x193B, prExtend}, // Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I + {0x1946, 0x194F, prNumeric}, // Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE + {0x19D0, 0x19D9, prNumeric}, // Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE + {0x1A00, 0x1A16, prALetter}, // Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA + {0x1A17, 0x1A18, prExtend}, // Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U + {0x1A19, 0x1A1A, prExtend}, // Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O + {0x1A1B, 0x1A1B, prExtend}, // Mn BUGINESE VOWEL SIGN AE + {0x1A55, 0x1A55, prExtend}, // Mc TAI THAM CONSONANT SIGN MEDIAL RA + {0x1A56, 0x1A56, prExtend}, // Mn TAI THAM CONSONANT SIGN MEDIAL LA + {0x1A57, 0x1A57, prExtend}, // Mc TAI THAM CONSONANT SIGN LA TANG LAI + {0x1A58, 0x1A5E, prExtend}, // Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA + {0x1A60, 0x1A60, prExtend}, // Mn TAI THAM SIGN SAKOT + {0x1A61, 0x1A61, prExtend}, // Mc TAI THAM VOWEL SIGN A + {0x1A62, 0x1A62, prExtend}, // Mn TAI THAM VOWEL SIGN MAI SAT + {0x1A63, 0x1A64, prExtend}, // Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA + {0x1A65, 0x1A6C, prExtend}, // Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW + {0x1A6D, 0x1A72, prExtend}, // Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI + {0x1A73, 0x1A7C, prExtend}, // Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN + {0x1A7F, 0x1A7F, prExtend}, // Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT + {0x1A80, 0x1A89, prNumeric}, // Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE + {0x1A90, 0x1A99, prNumeric}, // Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE + {0x1AB0, 0x1ABD, prExtend}, // Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW + {0x1ABE, 0x1ABE, prExtend}, // Me COMBINING PARENTHESES OVERLAY + {0x1ABF, 0x1ACE, prExtend}, // Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T + {0x1B00, 0x1B03, prExtend}, // Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG + {0x1B04, 0x1B04, prExtend}, // Mc BALINESE SIGN BISAH + {0x1B05, 0x1B33, prALetter}, // Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA + {0x1B34, 0x1B34, prExtend}, // Mn BALINESE SIGN REREKAN + {0x1B35, 0x1B35, prExtend}, // Mc BALINESE VOWEL SIGN TEDUNG + {0x1B36, 0x1B3A, prExtend}, // Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA + {0x1B3B, 0x1B3B, prExtend}, // Mc BALINESE VOWEL SIGN RA REPA TEDUNG + {0x1B3C, 0x1B3C, prExtend}, // Mn BALINESE VOWEL SIGN LA LENGA + {0x1B3D, 0x1B41, prExtend}, // Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG + {0x1B42, 0x1B42, prExtend}, // Mn BALINESE VOWEL SIGN PEPET + {0x1B43, 0x1B44, prExtend}, // Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG + {0x1B45, 0x1B4C, prALetter}, // Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA + {0x1B50, 0x1B59, prNumeric}, // Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE + {0x1B6B, 0x1B73, prExtend}, // Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG + {0x1B80, 0x1B81, prExtend}, // Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR + {0x1B82, 0x1B82, prExtend}, // Mc SUNDANESE SIGN PANGWISAD + {0x1B83, 0x1BA0, prALetter}, // Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA + {0x1BA1, 0x1BA1, prExtend}, // Mc SUNDANESE CONSONANT SIGN PAMINGKAL + {0x1BA2, 0x1BA5, prExtend}, // Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU + {0x1BA6, 0x1BA7, prExtend}, // Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG + {0x1BA8, 0x1BA9, prExtend}, // Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG + {0x1BAA, 0x1BAA, prExtend}, // Mc SUNDANESE SIGN PAMAAEH + {0x1BAB, 0x1BAD, prExtend}, // Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA + {0x1BAE, 0x1BAF, prALetter}, // Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA + {0x1BB0, 0x1BB9, prNumeric}, // Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE + {0x1BBA, 0x1BE5, prALetter}, // Lo [44] SUNDANESE AVAGRAHA..BATAK LETTER U + {0x1BE6, 0x1BE6, prExtend}, // Mn BATAK SIGN TOMPI + {0x1BE7, 0x1BE7, prExtend}, // Mc BATAK VOWEL SIGN E + {0x1BE8, 0x1BE9, prExtend}, // Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE + {0x1BEA, 0x1BEC, prExtend}, // Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O + {0x1BED, 0x1BED, prExtend}, // Mn BATAK VOWEL SIGN KARO O + {0x1BEE, 0x1BEE, prExtend}, // Mc BATAK VOWEL SIGN U + {0x1BEF, 0x1BF1, prExtend}, // Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H + {0x1BF2, 0x1BF3, prExtend}, // Mc [2] BATAK PANGOLAT..BATAK PANONGONAN + {0x1C00, 0x1C23, prALetter}, // Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A + {0x1C24, 0x1C2B, prExtend}, // Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU + {0x1C2C, 0x1C33, prExtend}, // Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T + {0x1C34, 0x1C35, prExtend}, // Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG + {0x1C36, 0x1C37, prExtend}, // Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA + {0x1C40, 0x1C49, prNumeric}, // Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE + {0x1C4D, 0x1C4F, prALetter}, // Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA + {0x1C50, 0x1C59, prNumeric}, // Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE + {0x1C5A, 0x1C77, prALetter}, // Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH + {0x1C78, 0x1C7D, prALetter}, // Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD + {0x1C80, 0x1C88, prALetter}, // L& [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK + {0x1C90, 0x1CBA, prALetter}, // L& [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN + {0x1CBD, 0x1CBF, prALetter}, // L& [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN + {0x1CD0, 0x1CD2, prExtend}, // Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA + {0x1CD4, 0x1CE0, prExtend}, // Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA + {0x1CE1, 0x1CE1, prExtend}, // Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA + {0x1CE2, 0x1CE8, prExtend}, // Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL + {0x1CE9, 0x1CEC, prALetter}, // Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL + {0x1CED, 0x1CED, prExtend}, // Mn VEDIC SIGN TIRYAK + {0x1CEE, 0x1CF3, prALetter}, // Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA + {0x1CF4, 0x1CF4, prExtend}, // Mn VEDIC TONE CANDRA ABOVE + {0x1CF5, 0x1CF6, prALetter}, // Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA + {0x1CF7, 0x1CF7, prExtend}, // Mc VEDIC SIGN ATIKRAMA + {0x1CF8, 0x1CF9, prExtend}, // Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE + {0x1CFA, 0x1CFA, prALetter}, // Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA + {0x1D00, 0x1D2B, prALetter}, // L& [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL + {0x1D2C, 0x1D6A, prALetter}, // Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI + {0x1D6B, 0x1D77, prALetter}, // L& [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G + {0x1D78, 0x1D78, prALetter}, // Lm MODIFIER LETTER CYRILLIC EN + {0x1D79, 0x1D9A, prALetter}, // L& [34] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK + {0x1D9B, 0x1DBF, prALetter}, // Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA + {0x1DC0, 0x1DFF, prExtend}, // Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x1E00, 0x1F15, prALetter}, // L& [278] LATIN CAPITAL LETTER A WITH RING BELOW..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA + {0x1F18, 0x1F1D, prALetter}, // L& [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA + {0x1F20, 0x1F45, prALetter}, // L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA + {0x1F48, 0x1F4D, prALetter}, // L& [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA + {0x1F50, 0x1F57, prALetter}, // L& [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI + {0x1F59, 0x1F59, prALetter}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA + {0x1F5B, 0x1F5B, prALetter}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA + {0x1F5D, 0x1F5D, prALetter}, // L& GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA + {0x1F5F, 0x1F7D, prALetter}, // L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA + {0x1F80, 0x1FB4, prALetter}, // L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI + {0x1FB6, 0x1FBC, prALetter}, // L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI + {0x1FBE, 0x1FBE, prALetter}, // L& GREEK PROSGEGRAMMENI + {0x1FC2, 0x1FC4, prALetter}, // L& [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI + {0x1FC6, 0x1FCC, prALetter}, // L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI + {0x1FD0, 0x1FD3, prALetter}, // L& [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA + {0x1FD6, 0x1FDB, prALetter}, // L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA + {0x1FE0, 0x1FEC, prALetter}, // L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA + {0x1FF2, 0x1FF4, prALetter}, // L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + {0x1FF6, 0x1FFC, prALetter}, // L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + {0x2000, 0x2006, prWSegSpace}, // Zs [7] EN QUAD..SIX-PER-EM SPACE + {0x2008, 0x200A, prWSegSpace}, // Zs [3] PUNCTUATION SPACE..HAIR SPACE + {0x200C, 0x200C, prExtend}, // Cf ZERO WIDTH NON-JOINER + {0x200D, 0x200D, prZWJ}, // Cf ZERO WIDTH JOINER + {0x200E, 0x200F, prFormat}, // Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK + {0x2018, 0x2018, prMidNumLet}, // Pi LEFT SINGLE QUOTATION MARK + {0x2019, 0x2019, prMidNumLet}, // Pf RIGHT SINGLE QUOTATION MARK + {0x2024, 0x2024, prMidNumLet}, // Po ONE DOT LEADER + {0x2027, 0x2027, prMidLetter}, // Po HYPHENATION POINT + {0x2028, 0x2028, prNewline}, // Zl LINE SEPARATOR + {0x2029, 0x2029, prNewline}, // Zp PARAGRAPH SEPARATOR + {0x202A, 0x202E, prFormat}, // Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE + {0x202F, 0x202F, prExtendNumLet}, // Zs NARROW NO-BREAK SPACE + {0x203C, 0x203C, prExtendedPictographic}, // E0.6 [1] (‼️) double exclamation mark + {0x203F, 0x2040, prExtendNumLet}, // Pc [2] UNDERTIE..CHARACTER TIE + {0x2044, 0x2044, prMidNum}, // Sm FRACTION SLASH + {0x2049, 0x2049, prExtendedPictographic}, // E0.6 [1] (⁉️) exclamation question mark + {0x2054, 0x2054, prExtendNumLet}, // Pc INVERTED UNDERTIE + {0x205F, 0x205F, prWSegSpace}, // Zs MEDIUM MATHEMATICAL SPACE + {0x2060, 0x2064, prFormat}, // Cf [5] WORD JOINER..INVISIBLE PLUS + {0x2066, 0x206F, prFormat}, // Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES + {0x2071, 0x2071, prALetter}, // Lm SUPERSCRIPT LATIN SMALL LETTER I + {0x207F, 0x207F, prALetter}, // Lm SUPERSCRIPT LATIN SMALL LETTER N + {0x2090, 0x209C, prALetter}, // Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T + {0x20D0, 0x20DC, prExtend}, // Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE + {0x20DD, 0x20E0, prExtend}, // Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH + {0x20E1, 0x20E1, prExtend}, // Mn COMBINING LEFT RIGHT ARROW ABOVE + {0x20E2, 0x20E4, prExtend}, // Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE + {0x20E5, 0x20F0, prExtend}, // Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE + {0x2102, 0x2102, prALetter}, // L& DOUBLE-STRUCK CAPITAL C + {0x2107, 0x2107, prALetter}, // L& EULER CONSTANT + {0x210A, 0x2113, prALetter}, // L& [10] SCRIPT SMALL G..SCRIPT SMALL L + {0x2115, 0x2115, prALetter}, // L& DOUBLE-STRUCK CAPITAL N + {0x2119, 0x211D, prALetter}, // L& [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R + {0x2122, 0x2122, prExtendedPictographic}, // E0.6 [1] (™️) trade mark + {0x2124, 0x2124, prALetter}, // L& DOUBLE-STRUCK CAPITAL Z + {0x2126, 0x2126, prALetter}, // L& OHM SIGN + {0x2128, 0x2128, prALetter}, // L& BLACK-LETTER CAPITAL Z + {0x212A, 0x212D, prALetter}, // L& [4] KELVIN SIGN..BLACK-LETTER CAPITAL C + {0x212F, 0x2134, prALetter}, // L& [6] SCRIPT SMALL E..SCRIPT SMALL O + {0x2135, 0x2138, prALetter}, // Lo [4] ALEF SYMBOL..DALET SYMBOL + {0x2139, 0x2139, prExtendedPictographic}, // E0.6 [1] (ℹ️) information + {0x2139, 0x2139, prALetter}, // L& INFORMATION SOURCE + {0x213C, 0x213F, prALetter}, // L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI + {0x2145, 0x2149, prALetter}, // L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J + {0x214E, 0x214E, prALetter}, // L& TURNED SMALL F + {0x2160, 0x2182, prALetter}, // Nl [35] ROMAN NUMERAL ONE..ROMAN NUMERAL TEN THOUSAND + {0x2183, 0x2184, prALetter}, // L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C + {0x2185, 0x2188, prALetter}, // Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND + {0x2194, 0x2199, prExtendedPictographic}, // E0.6 [6] (↔️..↙️) left-right arrow..down-left arrow + {0x21A9, 0x21AA, prExtendedPictographic}, // E0.6 [2] (↩️..↪️) right arrow curving left..left arrow curving right + {0x231A, 0x231B, prExtendedPictographic}, // E0.6 [2] (⌚..⌛) watch..hourglass done + {0x2328, 0x2328, prExtendedPictographic}, // E1.0 [1] (⌨️) keyboard + {0x2388, 0x2388, prExtendedPictographic}, // E0.0 [1] (⎈) HELM SYMBOL + {0x23CF, 0x23CF, prExtendedPictographic}, // E1.0 [1] (⏏️) eject button + {0x23E9, 0x23EC, prExtendedPictographic}, // E0.6 [4] (⏩..⏬) fast-forward button..fast down button + {0x23ED, 0x23EE, prExtendedPictographic}, // E0.7 [2] (⏭️..⏮️) next track button..last track button + {0x23EF, 0x23EF, prExtendedPictographic}, // E1.0 [1] (⏯️) play or pause button + {0x23F0, 0x23F0, prExtendedPictographic}, // E0.6 [1] (⏰) alarm clock + {0x23F1, 0x23F2, prExtendedPictographic}, // E1.0 [2] (⏱️..⏲️) stopwatch..timer clock + {0x23F3, 0x23F3, prExtendedPictographic}, // E0.6 [1] (⏳) hourglass not done + {0x23F8, 0x23FA, prExtendedPictographic}, // E0.7 [3] (⏸️..⏺️) pause button..record button + {0x24B6, 0x24E9, prALetter}, // So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z + {0x24C2, 0x24C2, prExtendedPictographic}, // E0.6 [1] (Ⓜ️) circled M + {0x25AA, 0x25AB, prExtendedPictographic}, // E0.6 [2] (▪️..▫️) black small square..white small square + {0x25B6, 0x25B6, prExtendedPictographic}, // E0.6 [1] (▶️) play button + {0x25C0, 0x25C0, prExtendedPictographic}, // E0.6 [1] (◀️) reverse button + {0x25FB, 0x25FE, prExtendedPictographic}, // E0.6 [4] (◻️..◾) white medium square..black medium-small square + {0x2600, 0x2601, prExtendedPictographic}, // E0.6 [2] (☀️..☁️) sun..cloud + {0x2602, 0x2603, prExtendedPictographic}, // E0.7 [2] (☂️..☃️) umbrella..snowman + {0x2604, 0x2604, prExtendedPictographic}, // E1.0 [1] (☄️) comet + {0x2605, 0x2605, prExtendedPictographic}, // E0.0 [1] (★) BLACK STAR + {0x2607, 0x260D, prExtendedPictographic}, // E0.0 [7] (☇..☍) LIGHTNING..OPPOSITION + {0x260E, 0x260E, prExtendedPictographic}, // E0.6 [1] (☎️) telephone + {0x260F, 0x2610, prExtendedPictographic}, // E0.0 [2] (☏..☐) WHITE TELEPHONE..BALLOT BOX + {0x2611, 0x2611, prExtendedPictographic}, // E0.6 [1] (☑️) check box with check + {0x2612, 0x2612, prExtendedPictographic}, // E0.0 [1] (☒) BALLOT BOX WITH X + {0x2614, 0x2615, prExtendedPictographic}, // E0.6 [2] (☔..☕) umbrella with rain drops..hot beverage + {0x2616, 0x2617, prExtendedPictographic}, // E0.0 [2] (☖..☗) WHITE SHOGI PIECE..BLACK SHOGI PIECE + {0x2618, 0x2618, prExtendedPictographic}, // E1.0 [1] (☘️) shamrock + {0x2619, 0x261C, prExtendedPictographic}, // E0.0 [4] (☙..☜) REVERSED ROTATED FLORAL HEART BULLET..WHITE LEFT POINTING INDEX + {0x261D, 0x261D, prExtendedPictographic}, // E0.6 [1] (☝️) index pointing up + {0x261E, 0x261F, prExtendedPictographic}, // E0.0 [2] (☞..☟) WHITE RIGHT POINTING INDEX..WHITE DOWN POINTING INDEX + {0x2620, 0x2620, prExtendedPictographic}, // E1.0 [1] (☠️) skull and crossbones + {0x2621, 0x2621, prExtendedPictographic}, // E0.0 [1] (☡) CAUTION SIGN + {0x2622, 0x2623, prExtendedPictographic}, // E1.0 [2] (☢️..☣️) radioactive..biohazard + {0x2624, 0x2625, prExtendedPictographic}, // E0.0 [2] (☤..☥) CADUCEUS..ANKH + {0x2626, 0x2626, prExtendedPictographic}, // E1.0 [1] (☦️) orthodox cross + {0x2627, 0x2629, prExtendedPictographic}, // E0.0 [3] (☧..☩) CHI RHO..CROSS OF JERUSALEM + {0x262A, 0x262A, prExtendedPictographic}, // E0.7 [1] (☪️) star and crescent + {0x262B, 0x262D, prExtendedPictographic}, // E0.0 [3] (☫..☭) FARSI SYMBOL..HAMMER AND SICKLE + {0x262E, 0x262E, prExtendedPictographic}, // E1.0 [1] (☮️) peace symbol + {0x262F, 0x262F, prExtendedPictographic}, // E0.7 [1] (☯️) yin yang + {0x2630, 0x2637, prExtendedPictographic}, // E0.0 [8] (☰..☷) TRIGRAM FOR HEAVEN..TRIGRAM FOR EARTH + {0x2638, 0x2639, prExtendedPictographic}, // E0.7 [2] (☸️..☹️) wheel of dharma..frowning face + {0x263A, 0x263A, prExtendedPictographic}, // E0.6 [1] (☺️) smiling face + {0x263B, 0x263F, prExtendedPictographic}, // E0.0 [5] (☻..☿) BLACK SMILING FACE..MERCURY + {0x2640, 0x2640, prExtendedPictographic}, // E4.0 [1] (♀️) female sign + {0x2641, 0x2641, prExtendedPictographic}, // E0.0 [1] (♁) EARTH + {0x2642, 0x2642, prExtendedPictographic}, // E4.0 [1] (♂️) male sign + {0x2643, 0x2647, prExtendedPictographic}, // E0.0 [5] (♃..♇) JUPITER..PLUTO + {0x2648, 0x2653, prExtendedPictographic}, // E0.6 [12] (♈..♓) Aries..Pisces + {0x2654, 0x265E, prExtendedPictographic}, // E0.0 [11] (♔..♞) WHITE CHESS KING..BLACK CHESS KNIGHT + {0x265F, 0x265F, prExtendedPictographic}, // E11.0 [1] (♟️) chess pawn + {0x2660, 0x2660, prExtendedPictographic}, // E0.6 [1] (♠️) spade suit + {0x2661, 0x2662, prExtendedPictographic}, // E0.0 [2] (♡..♢) WHITE HEART SUIT..WHITE DIAMOND SUIT + {0x2663, 0x2663, prExtendedPictographic}, // E0.6 [1] (♣️) club suit + {0x2664, 0x2664, prExtendedPictographic}, // E0.0 [1] (♤) WHITE SPADE SUIT + {0x2665, 0x2666, prExtendedPictographic}, // E0.6 [2] (♥️..♦️) heart suit..diamond suit + {0x2667, 0x2667, prExtendedPictographic}, // E0.0 [1] (♧) WHITE CLUB SUIT + {0x2668, 0x2668, prExtendedPictographic}, // E0.6 [1] (♨️) hot springs + {0x2669, 0x267A, prExtendedPictographic}, // E0.0 [18] (♩..♺) QUARTER NOTE..RECYCLING SYMBOL FOR GENERIC MATERIALS + {0x267B, 0x267B, prExtendedPictographic}, // E0.6 [1] (♻️) recycling symbol + {0x267C, 0x267D, prExtendedPictographic}, // E0.0 [2] (♼..♽) RECYCLED PAPER SYMBOL..PARTIALLY-RECYCLED PAPER SYMBOL + {0x267E, 0x267E, prExtendedPictographic}, // E11.0 [1] (♾️) infinity + {0x267F, 0x267F, prExtendedPictographic}, // E0.6 [1] (♿) wheelchair symbol + {0x2680, 0x2685, prExtendedPictographic}, // E0.0 [6] (⚀..⚅) DIE FACE-1..DIE FACE-6 + {0x2690, 0x2691, prExtendedPictographic}, // E0.0 [2] (⚐..⚑) WHITE FLAG..BLACK FLAG + {0x2692, 0x2692, prExtendedPictographic}, // E1.0 [1] (⚒️) hammer and pick + {0x2693, 0x2693, prExtendedPictographic}, // E0.6 [1] (⚓) anchor + {0x2694, 0x2694, prExtendedPictographic}, // E1.0 [1] (⚔️) crossed swords + {0x2695, 0x2695, prExtendedPictographic}, // E4.0 [1] (⚕️) medical symbol + {0x2696, 0x2697, prExtendedPictographic}, // E1.0 [2] (⚖️..⚗️) balance scale..alembic + {0x2698, 0x2698, prExtendedPictographic}, // E0.0 [1] (⚘) FLOWER + {0x2699, 0x2699, prExtendedPictographic}, // E1.0 [1] (⚙️) gear + {0x269A, 0x269A, prExtendedPictographic}, // E0.0 [1] (⚚) STAFF OF HERMES + {0x269B, 0x269C, prExtendedPictographic}, // E1.0 [2] (⚛️..⚜️) atom symbol..fleur-de-lis + {0x269D, 0x269F, prExtendedPictographic}, // E0.0 [3] (⚝..⚟) OUTLINED WHITE STAR..THREE LINES CONVERGING LEFT + {0x26A0, 0x26A1, prExtendedPictographic}, // E0.6 [2] (⚠️..⚡) warning..high voltage + {0x26A2, 0x26A6, prExtendedPictographic}, // E0.0 [5] (⚢..⚦) DOUBLED FEMALE SIGN..MALE WITH STROKE SIGN + {0x26A7, 0x26A7, prExtendedPictographic}, // E13.0 [1] (⚧️) transgender symbol + {0x26A8, 0x26A9, prExtendedPictographic}, // E0.0 [2] (⚨..⚩) VERTICAL MALE WITH STROKE SIGN..HORIZONTAL MALE WITH STROKE SIGN + {0x26AA, 0x26AB, prExtendedPictographic}, // E0.6 [2] (⚪..⚫) white circle..black circle + {0x26AC, 0x26AF, prExtendedPictographic}, // E0.0 [4] (⚬..⚯) MEDIUM SMALL WHITE CIRCLE..UNMARRIED PARTNERSHIP SYMBOL + {0x26B0, 0x26B1, prExtendedPictographic}, // E1.0 [2] (⚰️..⚱️) coffin..funeral urn + {0x26B2, 0x26BC, prExtendedPictographic}, // E0.0 [11] (⚲..⚼) NEUTER..SESQUIQUADRATE + {0x26BD, 0x26BE, prExtendedPictographic}, // E0.6 [2] (⚽..⚾) soccer ball..baseball + {0x26BF, 0x26C3, prExtendedPictographic}, // E0.0 [5] (⚿..⛃) SQUARED KEY..BLACK DRAUGHTS KING + {0x26C4, 0x26C5, prExtendedPictographic}, // E0.6 [2] (⛄..⛅) snowman without snow..sun behind cloud + {0x26C6, 0x26C7, prExtendedPictographic}, // E0.0 [2] (⛆..⛇) RAIN..BLACK SNOWMAN + {0x26C8, 0x26C8, prExtendedPictographic}, // E0.7 [1] (⛈️) cloud with lightning and rain + {0x26C9, 0x26CD, prExtendedPictographic}, // E0.0 [5] (⛉..⛍) TURNED WHITE SHOGI PIECE..DISABLED CAR + {0x26CE, 0x26CE, prExtendedPictographic}, // E0.6 [1] (⛎) Ophiuchus + {0x26CF, 0x26CF, prExtendedPictographic}, // E0.7 [1] (⛏️) pick + {0x26D0, 0x26D0, prExtendedPictographic}, // E0.0 [1] (⛐) CAR SLIDING + {0x26D1, 0x26D1, prExtendedPictographic}, // E0.7 [1] (⛑️) rescue worker’s helmet + {0x26D2, 0x26D2, prExtendedPictographic}, // E0.0 [1] (⛒) CIRCLED CROSSING LANES + {0x26D3, 0x26D3, prExtendedPictographic}, // E0.7 [1] (⛓️) chains + {0x26D4, 0x26D4, prExtendedPictographic}, // E0.6 [1] (⛔) no entry + {0x26D5, 0x26E8, prExtendedPictographic}, // E0.0 [20] (⛕..⛨) ALTERNATE ONE-WAY LEFT WAY TRAFFIC..BLACK CROSS ON SHIELD + {0x26E9, 0x26E9, prExtendedPictographic}, // E0.7 [1] (⛩️) shinto shrine + {0x26EA, 0x26EA, prExtendedPictographic}, // E0.6 [1] (⛪) church + {0x26EB, 0x26EF, prExtendedPictographic}, // E0.0 [5] (⛫..⛯) CASTLE..MAP SYMBOL FOR LIGHTHOUSE + {0x26F0, 0x26F1, prExtendedPictographic}, // E0.7 [2] (⛰️..⛱️) mountain..umbrella on ground + {0x26F2, 0x26F3, prExtendedPictographic}, // E0.6 [2] (⛲..⛳) fountain..flag in hole + {0x26F4, 0x26F4, prExtendedPictographic}, // E0.7 [1] (⛴️) ferry + {0x26F5, 0x26F5, prExtendedPictographic}, // E0.6 [1] (⛵) sailboat + {0x26F6, 0x26F6, prExtendedPictographic}, // E0.0 [1] (⛶) SQUARE FOUR CORNERS + {0x26F7, 0x26F9, prExtendedPictographic}, // E0.7 [3] (⛷️..⛹️) skier..person bouncing ball + {0x26FA, 0x26FA, prExtendedPictographic}, // E0.6 [1] (⛺) tent + {0x26FB, 0x26FC, prExtendedPictographic}, // E0.0 [2] (⛻..⛼) JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL + {0x26FD, 0x26FD, prExtendedPictographic}, // E0.6 [1] (⛽) fuel pump + {0x26FE, 0x2701, prExtendedPictographic}, // E0.0 [4] (⛾..✁) CUP ON BLACK SQUARE..UPPER BLADE SCISSORS + {0x2702, 0x2702, prExtendedPictographic}, // E0.6 [1] (✂️) scissors + {0x2703, 0x2704, prExtendedPictographic}, // E0.0 [2] (✃..✄) LOWER BLADE SCISSORS..WHITE SCISSORS + {0x2705, 0x2705, prExtendedPictographic}, // E0.6 [1] (✅) check mark button + {0x2708, 0x270C, prExtendedPictographic}, // E0.6 [5] (✈️..✌️) airplane..victory hand + {0x270D, 0x270D, prExtendedPictographic}, // E0.7 [1] (✍️) writing hand + {0x270E, 0x270E, prExtendedPictographic}, // E0.0 [1] (✎) LOWER RIGHT PENCIL + {0x270F, 0x270F, prExtendedPictographic}, // E0.6 [1] (✏️) pencil + {0x2710, 0x2711, prExtendedPictographic}, // E0.0 [2] (✐..✑) UPPER RIGHT PENCIL..WHITE NIB + {0x2712, 0x2712, prExtendedPictographic}, // E0.6 [1] (✒️) black nib + {0x2714, 0x2714, prExtendedPictographic}, // E0.6 [1] (✔️) check mark + {0x2716, 0x2716, prExtendedPictographic}, // E0.6 [1] (✖️) multiply + {0x271D, 0x271D, prExtendedPictographic}, // E0.7 [1] (✝️) latin cross + {0x2721, 0x2721, prExtendedPictographic}, // E0.7 [1] (✡️) star of David + {0x2728, 0x2728, prExtendedPictographic}, // E0.6 [1] (✨) sparkles + {0x2733, 0x2734, prExtendedPictographic}, // E0.6 [2] (✳️..✴️) eight-spoked asterisk..eight-pointed star + {0x2744, 0x2744, prExtendedPictographic}, // E0.6 [1] (❄️) snowflake + {0x2747, 0x2747, prExtendedPictographic}, // E0.6 [1] (❇️) sparkle + {0x274C, 0x274C, prExtendedPictographic}, // E0.6 [1] (❌) cross mark + {0x274E, 0x274E, prExtendedPictographic}, // E0.6 [1] (❎) cross mark button + {0x2753, 0x2755, prExtendedPictographic}, // E0.6 [3] (❓..❕) red question mark..white exclamation mark + {0x2757, 0x2757, prExtendedPictographic}, // E0.6 [1] (❗) red exclamation mark + {0x2763, 0x2763, prExtendedPictographic}, // E1.0 [1] (❣️) heart exclamation + {0x2764, 0x2764, prExtendedPictographic}, // E0.6 [1] (❤️) red heart + {0x2765, 0x2767, prExtendedPictographic}, // E0.0 [3] (❥..❧) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET + {0x2795, 0x2797, prExtendedPictographic}, // E0.6 [3] (➕..➗) plus..divide + {0x27A1, 0x27A1, prExtendedPictographic}, // E0.6 [1] (➡️) right arrow + {0x27B0, 0x27B0, prExtendedPictographic}, // E0.6 [1] (➰) curly loop + {0x27BF, 0x27BF, prExtendedPictographic}, // E1.0 [1] (➿) double curly loop + {0x2934, 0x2935, prExtendedPictographic}, // E0.6 [2] (⤴️..⤵️) right arrow curving up..right arrow curving down + {0x2B05, 0x2B07, prExtendedPictographic}, // E0.6 [3] (⬅️..⬇️) left arrow..down arrow + {0x2B1B, 0x2B1C, prExtendedPictographic}, // E0.6 [2] (⬛..⬜) black large square..white large square + {0x2B50, 0x2B50, prExtendedPictographic}, // E0.6 [1] (⭐) star + {0x2B55, 0x2B55, prExtendedPictographic}, // E0.6 [1] (⭕) hollow red circle + {0x2C00, 0x2C7B, prALetter}, // L& [124] GLAGOLITIC CAPITAL LETTER AZU..LATIN LETTER SMALL CAPITAL TURNED E + {0x2C7C, 0x2C7D, prALetter}, // Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V + {0x2C7E, 0x2CE4, prALetter}, // L& [103] LATIN CAPITAL LETTER S WITH SWASH TAIL..COPTIC SYMBOL KAI + {0x2CEB, 0x2CEE, prALetter}, // L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA + {0x2CEF, 0x2CF1, prExtend}, // Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS + {0x2CF2, 0x2CF3, prALetter}, // L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI + {0x2D00, 0x2D25, prALetter}, // L& [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE + {0x2D27, 0x2D27, prALetter}, // L& GEORGIAN SMALL LETTER YN + {0x2D2D, 0x2D2D, prALetter}, // L& GEORGIAN SMALL LETTER AEN + {0x2D30, 0x2D67, prALetter}, // Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO + {0x2D6F, 0x2D6F, prALetter}, // Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK + {0x2D7F, 0x2D7F, prExtend}, // Mn TIFINAGH CONSONANT JOINER + {0x2D80, 0x2D96, prALetter}, // Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE + {0x2DA0, 0x2DA6, prALetter}, // Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO + {0x2DA8, 0x2DAE, prALetter}, // Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO + {0x2DB0, 0x2DB6, prALetter}, // Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO + {0x2DB8, 0x2DBE, prALetter}, // Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO + {0x2DC0, 0x2DC6, prALetter}, // Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO + {0x2DC8, 0x2DCE, prALetter}, // Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO + {0x2DD0, 0x2DD6, prALetter}, // Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO + {0x2DD8, 0x2DDE, prALetter}, // Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO + {0x2DE0, 0x2DFF, prExtend}, // Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS + {0x2E2F, 0x2E2F, prALetter}, // Lm VERTICAL TILDE + {0x3000, 0x3000, prWSegSpace}, // Zs IDEOGRAPHIC SPACE + {0x3005, 0x3005, prALetter}, // Lm IDEOGRAPHIC ITERATION MARK + {0x302A, 0x302D, prExtend}, // Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK + {0x302E, 0x302F, prExtend}, // Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK + {0x3030, 0x3030, prExtendedPictographic}, // E0.6 [1] (〰️) wavy dash + {0x3031, 0x3035, prKatakana}, // Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF + {0x303B, 0x303B, prALetter}, // Lm VERTICAL IDEOGRAPHIC ITERATION MARK + {0x303C, 0x303C, prALetter}, // Lo MASU MARK + {0x303D, 0x303D, prExtendedPictographic}, // E0.6 [1] (〽️) part alternation mark + {0x3099, 0x309A, prExtend}, // Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x309B, 0x309C, prKatakana}, // Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + {0x30A0, 0x30A0, prKatakana}, // Pd KATAKANA-HIRAGANA DOUBLE HYPHEN + {0x30A1, 0x30FA, prKatakana}, // Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO + {0x30FC, 0x30FE, prKatakana}, // Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK + {0x30FF, 0x30FF, prKatakana}, // Lo KATAKANA DIGRAPH KOTO + {0x3105, 0x312F, prALetter}, // Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN + {0x3131, 0x318E, prALetter}, // Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE + {0x31A0, 0x31BF, prALetter}, // Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH + {0x31F0, 0x31FF, prKatakana}, // Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO + {0x3297, 0x3297, prExtendedPictographic}, // E0.6 [1] (㊗️) Japanese “congratulations” button + {0x3299, 0x3299, prExtendedPictographic}, // E0.6 [1] (㊙️) Japanese “secret” button + {0x32D0, 0x32FE, prKatakana}, // So [47] CIRCLED KATAKANA A..CIRCLED KATAKANA WO + {0x3300, 0x3357, prKatakana}, // So [88] SQUARE APAATO..SQUARE WATTO + {0xA000, 0xA014, prALetter}, // Lo [21] YI SYLLABLE IT..YI SYLLABLE E + {0xA015, 0xA015, prALetter}, // Lm YI SYLLABLE WU + {0xA016, 0xA48C, prALetter}, // Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR + {0xA4D0, 0xA4F7, prALetter}, // Lo [40] LISU LETTER BA..LISU LETTER OE + {0xA4F8, 0xA4FD, prALetter}, // Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU + {0xA500, 0xA60B, prALetter}, // Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG + {0xA60C, 0xA60C, prALetter}, // Lm VAI SYLLABLE LENGTHENER + {0xA610, 0xA61F, prALetter}, // Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG + {0xA620, 0xA629, prNumeric}, // Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE + {0xA62A, 0xA62B, prALetter}, // Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO + {0xA640, 0xA66D, prALetter}, // L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O + {0xA66E, 0xA66E, prALetter}, // Lo CYRILLIC LETTER MULTIOCULAR O + {0xA66F, 0xA66F, prExtend}, // Mn COMBINING CYRILLIC VZMET + {0xA670, 0xA672, prExtend}, // Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN + {0xA674, 0xA67D, prExtend}, // Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK + {0xA67F, 0xA67F, prALetter}, // Lm CYRILLIC PAYEROK + {0xA680, 0xA69B, prALetter}, // L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O + {0xA69C, 0xA69D, prALetter}, // Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN + {0xA69E, 0xA69F, prExtend}, // Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E + {0xA6A0, 0xA6E5, prALetter}, // Lo [70] BAMUM LETTER A..BAMUM LETTER KI + {0xA6E6, 0xA6EF, prALetter}, // Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM + {0xA6F0, 0xA6F1, prExtend}, // Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS + {0xA708, 0xA716, prALetter}, // Sk [15] MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR + {0xA717, 0xA71F, prALetter}, // Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK + {0xA720, 0xA721, prALetter}, // Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE + {0xA722, 0xA76F, prALetter}, // L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON + {0xA770, 0xA770, prALetter}, // Lm MODIFIER LETTER US + {0xA771, 0xA787, prALetter}, // L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T + {0xA788, 0xA788, prALetter}, // Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT + {0xA789, 0xA78A, prALetter}, // Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN + {0xA78B, 0xA78E, prALetter}, // L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT + {0xA78F, 0xA78F, prALetter}, // Lo LATIN LETTER SINOLOGICAL DOT + {0xA790, 0xA7CA, prALetter}, // L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY + {0xA7D0, 0xA7D1, prALetter}, // L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G + {0xA7D3, 0xA7D3, prALetter}, // L& LATIN SMALL LETTER DOUBLE THORN + {0xA7D5, 0xA7D9, prALetter}, // L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S + {0xA7F2, 0xA7F4, prALetter}, // Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q + {0xA7F5, 0xA7F6, prALetter}, // L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H + {0xA7F7, 0xA7F7, prALetter}, // Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I + {0xA7F8, 0xA7F9, prALetter}, // Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE + {0xA7FA, 0xA7FA, prALetter}, // L& LATIN LETTER SMALL CAPITAL TURNED M + {0xA7FB, 0xA801, prALetter}, // Lo [7] LATIN EPIGRAPHIC LETTER REVERSED F..SYLOTI NAGRI LETTER I + {0xA802, 0xA802, prExtend}, // Mn SYLOTI NAGRI SIGN DVISVARA + {0xA803, 0xA805, prALetter}, // Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O + {0xA806, 0xA806, prExtend}, // Mn SYLOTI NAGRI SIGN HASANTA + {0xA807, 0xA80A, prALetter}, // Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO + {0xA80B, 0xA80B, prExtend}, // Mn SYLOTI NAGRI SIGN ANUSVARA + {0xA80C, 0xA822, prALetter}, // Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO + {0xA823, 0xA824, prExtend}, // Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I + {0xA825, 0xA826, prExtend}, // Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E + {0xA827, 0xA827, prExtend}, // Mc SYLOTI NAGRI VOWEL SIGN OO + {0xA82C, 0xA82C, prExtend}, // Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA + {0xA840, 0xA873, prALetter}, // Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU + {0xA880, 0xA881, prExtend}, // Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA + {0xA882, 0xA8B3, prALetter}, // Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA + {0xA8B4, 0xA8C3, prExtend}, // Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU + {0xA8C4, 0xA8C5, prExtend}, // Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU + {0xA8D0, 0xA8D9, prNumeric}, // Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE + {0xA8E0, 0xA8F1, prExtend}, // Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA + {0xA8F2, 0xA8F7, prALetter}, // Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA + {0xA8FB, 0xA8FB, prALetter}, // Lo DEVANAGARI HEADSTROKE + {0xA8FD, 0xA8FE, prALetter}, // Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY + {0xA8FF, 0xA8FF, prExtend}, // Mn DEVANAGARI VOWEL SIGN AY + {0xA900, 0xA909, prNumeric}, // Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE + {0xA90A, 0xA925, prALetter}, // Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO + {0xA926, 0xA92D, prExtend}, // Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU + {0xA930, 0xA946, prALetter}, // Lo [23] REJANG LETTER KA..REJANG LETTER A + {0xA947, 0xA951, prExtend}, // Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R + {0xA952, 0xA953, prExtend}, // Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA + {0xA960, 0xA97C, prALetter}, // Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH + {0xA980, 0xA982, prExtend}, // Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR + {0xA983, 0xA983, prExtend}, // Mc JAVANESE SIGN WIGNYAN + {0xA984, 0xA9B2, prALetter}, // Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA + {0xA9B3, 0xA9B3, prExtend}, // Mn JAVANESE SIGN CECAK TELU + {0xA9B4, 0xA9B5, prExtend}, // Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG + {0xA9B6, 0xA9B9, prExtend}, // Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT + {0xA9BA, 0xA9BB, prExtend}, // Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE + {0xA9BC, 0xA9BD, prExtend}, // Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET + {0xA9BE, 0xA9C0, prExtend}, // Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON + {0xA9CF, 0xA9CF, prALetter}, // Lm JAVANESE PANGRANGKEP + {0xA9D0, 0xA9D9, prNumeric}, // Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE + {0xA9E5, 0xA9E5, prExtend}, // Mn MYANMAR SIGN SHAN SAW + {0xA9F0, 0xA9F9, prNumeric}, // Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE + {0xAA00, 0xAA28, prALetter}, // Lo [41] CHAM LETTER A..CHAM LETTER HA + {0xAA29, 0xAA2E, prExtend}, // Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE + {0xAA2F, 0xAA30, prExtend}, // Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI + {0xAA31, 0xAA32, prExtend}, // Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE + {0xAA33, 0xAA34, prExtend}, // Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA + {0xAA35, 0xAA36, prExtend}, // Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA + {0xAA40, 0xAA42, prALetter}, // Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG + {0xAA43, 0xAA43, prExtend}, // Mn CHAM CONSONANT SIGN FINAL NG + {0xAA44, 0xAA4B, prALetter}, // Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS + {0xAA4C, 0xAA4C, prExtend}, // Mn CHAM CONSONANT SIGN FINAL M + {0xAA4D, 0xAA4D, prExtend}, // Mc CHAM CONSONANT SIGN FINAL H + {0xAA50, 0xAA59, prNumeric}, // Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE + {0xAA7B, 0xAA7B, prExtend}, // Mc MYANMAR SIGN PAO KAREN TONE + {0xAA7C, 0xAA7C, prExtend}, // Mn MYANMAR SIGN TAI LAING TONE-2 + {0xAA7D, 0xAA7D, prExtend}, // Mc MYANMAR SIGN TAI LAING TONE-5 + {0xAAB0, 0xAAB0, prExtend}, // Mn TAI VIET MAI KANG + {0xAAB2, 0xAAB4, prExtend}, // Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U + {0xAAB7, 0xAAB8, prExtend}, // Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA + {0xAABE, 0xAABF, prExtend}, // Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK + {0xAAC1, 0xAAC1, prExtend}, // Mn TAI VIET TONE MAI THO + {0xAAE0, 0xAAEA, prALetter}, // Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA + {0xAAEB, 0xAAEB, prExtend}, // Mc MEETEI MAYEK VOWEL SIGN II + {0xAAEC, 0xAAED, prExtend}, // Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI + {0xAAEE, 0xAAEF, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU + {0xAAF2, 0xAAF2, prALetter}, // Lo MEETEI MAYEK ANJI + {0xAAF3, 0xAAF4, prALetter}, // Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK + {0xAAF5, 0xAAF5, prExtend}, // Mc MEETEI MAYEK VOWEL SIGN VISARGA + {0xAAF6, 0xAAF6, prExtend}, // Mn MEETEI MAYEK VIRAMA + {0xAB01, 0xAB06, prALetter}, // Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO + {0xAB09, 0xAB0E, prALetter}, // Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO + {0xAB11, 0xAB16, prALetter}, // Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO + {0xAB20, 0xAB26, prALetter}, // Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO + {0xAB28, 0xAB2E, prALetter}, // Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO + {0xAB30, 0xAB5A, prALetter}, // L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG + {0xAB5B, 0xAB5B, prALetter}, // Sk MODIFIER BREVE WITH INVERTED BREVE + {0xAB5C, 0xAB5F, prALetter}, // Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK + {0xAB60, 0xAB68, prALetter}, // L& [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE + {0xAB69, 0xAB69, prALetter}, // Lm MODIFIER LETTER SMALL TURNED W + {0xAB70, 0xABBF, prALetter}, // L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA + {0xABC0, 0xABE2, prALetter}, // Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM + {0xABE3, 0xABE4, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP + {0xABE5, 0xABE5, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN ANAP + {0xABE6, 0xABE7, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP + {0xABE8, 0xABE8, prExtend}, // Mn MEETEI MAYEK VOWEL SIGN UNAP + {0xABE9, 0xABEA, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG + {0xABEC, 0xABEC, prExtend}, // Mc MEETEI MAYEK LUM IYEK + {0xABED, 0xABED, prExtend}, // Mn MEETEI MAYEK APUN IYEK + {0xABF0, 0xABF9, prNumeric}, // Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE + {0xAC00, 0xD7A3, prALetter}, // Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH + {0xD7B0, 0xD7C6, prALetter}, // Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E + {0xD7CB, 0xD7FB, prALetter}, // Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH + {0xFB00, 0xFB06, prALetter}, // L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST + {0xFB13, 0xFB17, prALetter}, // L& [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH + {0xFB1D, 0xFB1D, prHebrewLetter}, // Lo HEBREW LETTER YOD WITH HIRIQ + {0xFB1E, 0xFB1E, prExtend}, // Mn HEBREW POINT JUDEO-SPANISH VARIKA + {0xFB1F, 0xFB28, prHebrewLetter}, // Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV + {0xFB2A, 0xFB36, prHebrewLetter}, // Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH + {0xFB38, 0xFB3C, prHebrewLetter}, // Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH + {0xFB3E, 0xFB3E, prHebrewLetter}, // Lo HEBREW LETTER MEM WITH DAGESH + {0xFB40, 0xFB41, prHebrewLetter}, // Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH + {0xFB43, 0xFB44, prHebrewLetter}, // Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH + {0xFB46, 0xFB4F, prHebrewLetter}, // Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED + {0xFB50, 0xFBB1, prALetter}, // Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM + {0xFBD3, 0xFD3D, prALetter}, // Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM + {0xFD50, 0xFD8F, prALetter}, // Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM + {0xFD92, 0xFDC7, prALetter}, // Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM + {0xFDF0, 0xFDFB, prALetter}, // Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU + {0xFE00, 0xFE0F, prExtend}, // Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 + {0xFE10, 0xFE10, prMidNum}, // Po PRESENTATION FORM FOR VERTICAL COMMA + {0xFE13, 0xFE13, prMidLetter}, // Po PRESENTATION FORM FOR VERTICAL COLON + {0xFE14, 0xFE14, prMidNum}, // Po PRESENTATION FORM FOR VERTICAL SEMICOLON + {0xFE20, 0xFE2F, prExtend}, // Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF + {0xFE33, 0xFE34, prExtendNumLet}, // Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE + {0xFE4D, 0xFE4F, prExtendNumLet}, // Pc [3] DASHED LOW LINE..WAVY LOW LINE + {0xFE50, 0xFE50, prMidNum}, // Po SMALL COMMA + {0xFE52, 0xFE52, prMidNumLet}, // Po SMALL FULL STOP + {0xFE54, 0xFE54, prMidNum}, // Po SMALL SEMICOLON + {0xFE55, 0xFE55, prMidLetter}, // Po SMALL COLON + {0xFE70, 0xFE74, prALetter}, // Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM + {0xFE76, 0xFEFC, prALetter}, // Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM + {0xFEFF, 0xFEFF, prFormat}, // Cf ZERO WIDTH NO-BREAK SPACE + {0xFF07, 0xFF07, prMidNumLet}, // Po FULLWIDTH APOSTROPHE + {0xFF0C, 0xFF0C, prMidNum}, // Po FULLWIDTH COMMA + {0xFF0E, 0xFF0E, prMidNumLet}, // Po FULLWIDTH FULL STOP + {0xFF10, 0xFF19, prNumeric}, // Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE + {0xFF1A, 0xFF1A, prMidLetter}, // Po FULLWIDTH COLON + {0xFF1B, 0xFF1B, prMidNum}, // Po FULLWIDTH SEMICOLON + {0xFF21, 0xFF3A, prALetter}, // L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z + {0xFF3F, 0xFF3F, prExtendNumLet}, // Pc FULLWIDTH LOW LINE + {0xFF41, 0xFF5A, prALetter}, // L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z + {0xFF66, 0xFF6F, prKatakana}, // Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU + {0xFF70, 0xFF70, prKatakana}, // Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK + {0xFF71, 0xFF9D, prKatakana}, // Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N + {0xFF9E, 0xFF9F, prExtend}, // Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK + {0xFFA0, 0xFFBE, prALetter}, // Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH + {0xFFC2, 0xFFC7, prALetter}, // Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E + {0xFFCA, 0xFFCF, prALetter}, // Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE + {0xFFD2, 0xFFD7, prALetter}, // Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU + {0xFFDA, 0xFFDC, prALetter}, // Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I + {0xFFF9, 0xFFFB, prFormat}, // Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR + {0x10000, 0x1000B, prALetter}, // Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE + {0x1000D, 0x10026, prALetter}, // Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO + {0x10028, 0x1003A, prALetter}, // Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO + {0x1003C, 0x1003D, prALetter}, // Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE + {0x1003F, 0x1004D, prALetter}, // Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO + {0x10050, 0x1005D, prALetter}, // Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089 + {0x10080, 0x100FA, prALetter}, // Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305 + {0x10140, 0x10174, prALetter}, // Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS + {0x101FD, 0x101FD, prExtend}, // Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE + {0x10280, 0x1029C, prALetter}, // Lo [29] LYCIAN LETTER A..LYCIAN LETTER X + {0x102A0, 0x102D0, prALetter}, // Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3 + {0x102E0, 0x102E0, prExtend}, // Mn COPTIC EPACT THOUSANDS MARK + {0x10300, 0x1031F, prALetter}, // Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS + {0x1032D, 0x10340, prALetter}, // Lo [20] OLD ITALIC LETTER YE..GOTHIC LETTER PAIRTHRA + {0x10341, 0x10341, prALetter}, // Nl GOTHIC LETTER NINETY + {0x10342, 0x10349, prALetter}, // Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL + {0x1034A, 0x1034A, prALetter}, // Nl GOTHIC LETTER NINE HUNDRED + {0x10350, 0x10375, prALetter}, // Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA + {0x10376, 0x1037A, prExtend}, // Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII + {0x10380, 0x1039D, prALetter}, // Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU + {0x103A0, 0x103C3, prALetter}, // Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA + {0x103C8, 0x103CF, prALetter}, // Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH + {0x103D1, 0x103D5, prALetter}, // Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED + {0x10400, 0x1044F, prALetter}, // L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW + {0x10450, 0x1049D, prALetter}, // Lo [78] SHAVIAN LETTER PEEP..OSMANYA LETTER OO + {0x104A0, 0x104A9, prNumeric}, // Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE + {0x104B0, 0x104D3, prALetter}, // L& [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA + {0x104D8, 0x104FB, prALetter}, // L& [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA + {0x10500, 0x10527, prALetter}, // Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE + {0x10530, 0x10563, prALetter}, // Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW + {0x10570, 0x1057A, prALetter}, // L& [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA + {0x1057C, 0x1058A, prALetter}, // L& [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE + {0x1058C, 0x10592, prALetter}, // L& [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE + {0x10594, 0x10595, prALetter}, // L& [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE + {0x10597, 0x105A1, prALetter}, // L& [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA + {0x105A3, 0x105B1, prALetter}, // L& [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE + {0x105B3, 0x105B9, prALetter}, // L& [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE + {0x105BB, 0x105BC, prALetter}, // L& [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE + {0x10600, 0x10736, prALetter}, // Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664 + {0x10740, 0x10755, prALetter}, // Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE + {0x10760, 0x10767, prALetter}, // Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807 + {0x10780, 0x10785, prALetter}, // Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK + {0x10787, 0x107B0, prALetter}, // Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK + {0x107B2, 0x107BA, prALetter}, // Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL + {0x10800, 0x10805, prALetter}, // Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA + {0x10808, 0x10808, prALetter}, // Lo CYPRIOT SYLLABLE JO + {0x1080A, 0x10835, prALetter}, // Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO + {0x10837, 0x10838, prALetter}, // Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE + {0x1083C, 0x1083C, prALetter}, // Lo CYPRIOT SYLLABLE ZA + {0x1083F, 0x10855, prALetter}, // Lo [23] CYPRIOT SYLLABLE ZO..IMPERIAL ARAMAIC LETTER TAW + {0x10860, 0x10876, prALetter}, // Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW + {0x10880, 0x1089E, prALetter}, // Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW + {0x108E0, 0x108F2, prALetter}, // Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH + {0x108F4, 0x108F5, prALetter}, // Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW + {0x10900, 0x10915, prALetter}, // Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU + {0x10920, 0x10939, prALetter}, // Lo [26] LYDIAN LETTER A..LYDIAN LETTER C + {0x10980, 0x109B7, prALetter}, // Lo [56] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC CURSIVE LETTER DA + {0x109BE, 0x109BF, prALetter}, // Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN + {0x10A00, 0x10A00, prALetter}, // Lo KHAROSHTHI LETTER A + {0x10A01, 0x10A03, prExtend}, // Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R + {0x10A05, 0x10A06, prExtend}, // Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O + {0x10A0C, 0x10A0F, prExtend}, // Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA + {0x10A10, 0x10A13, prALetter}, // Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA + {0x10A15, 0x10A17, prALetter}, // Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA + {0x10A19, 0x10A35, prALetter}, // Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA + {0x10A38, 0x10A3A, prExtend}, // Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW + {0x10A3F, 0x10A3F, prExtend}, // Mn KHAROSHTHI VIRAMA + {0x10A60, 0x10A7C, prALetter}, // Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH + {0x10A80, 0x10A9C, prALetter}, // Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH + {0x10AC0, 0x10AC7, prALetter}, // Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW + {0x10AC9, 0x10AE4, prALetter}, // Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW + {0x10AE5, 0x10AE6, prExtend}, // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW + {0x10B00, 0x10B35, prALetter}, // Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE + {0x10B40, 0x10B55, prALetter}, // Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW + {0x10B60, 0x10B72, prALetter}, // Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW + {0x10B80, 0x10B91, prALetter}, // Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW + {0x10C00, 0x10C48, prALetter}, // Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH + {0x10C80, 0x10CB2, prALetter}, // L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US + {0x10CC0, 0x10CF2, prALetter}, // L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US + {0x10D00, 0x10D23, prALetter}, // Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA + {0x10D24, 0x10D27, prExtend}, // Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI + {0x10D30, 0x10D39, prNumeric}, // Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE + {0x10E80, 0x10EA9, prALetter}, // Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET + {0x10EAB, 0x10EAC, prExtend}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK + {0x10EB0, 0x10EB1, prALetter}, // Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prExtend}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA + {0x10F00, 0x10F1C, prALetter}, // Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL + {0x10F27, 0x10F27, prALetter}, // Lo OLD SOGDIAN LIGATURE AYIN-DALETH + {0x10F30, 0x10F45, prALetter}, // Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN + {0x10F46, 0x10F50, prExtend}, // Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW + {0x10F70, 0x10F81, prALetter}, // Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH + {0x10F82, 0x10F85, prExtend}, // Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW + {0x10FB0, 0x10FC4, prALetter}, // Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW + {0x10FE0, 0x10FF6, prALetter}, // Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH + {0x11000, 0x11000, prExtend}, // Mc BRAHMI SIGN CANDRABINDU + {0x11001, 0x11001, prExtend}, // Mn BRAHMI SIGN ANUSVARA + {0x11002, 0x11002, prExtend}, // Mc BRAHMI SIGN VISARGA + {0x11003, 0x11037, prALetter}, // Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA + {0x11038, 0x11046, prExtend}, // Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA + {0x11066, 0x1106F, prNumeric}, // Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE + {0x11070, 0x11070, prExtend}, // Mn BRAHMI SIGN OLD TAMIL VIRAMA + {0x11071, 0x11072, prALetter}, // Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O + {0x11073, 0x11074, prExtend}, // Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O + {0x11075, 0x11075, prALetter}, // Lo BRAHMI LETTER OLD TAMIL LLA + {0x1107F, 0x11081, prExtend}, // Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA + {0x11082, 0x11082, prExtend}, // Mc KAITHI SIGN VISARGA + {0x11083, 0x110AF, prALetter}, // Lo [45] KAITHI LETTER A..KAITHI LETTER HA + {0x110B0, 0x110B2, prExtend}, // Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II + {0x110B3, 0x110B6, prExtend}, // Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI + {0x110B7, 0x110B8, prExtend}, // Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU + {0x110B9, 0x110BA, prExtend}, // Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA + {0x110BD, 0x110BD, prFormat}, // Cf KAITHI NUMBER SIGN + {0x110C2, 0x110C2, prExtend}, // Mn KAITHI VOWEL SIGN VOCALIC R + {0x110CD, 0x110CD, prFormat}, // Cf KAITHI NUMBER SIGN ABOVE + {0x110D0, 0x110E8, prALetter}, // Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE + {0x110F0, 0x110F9, prNumeric}, // Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE + {0x11100, 0x11102, prExtend}, // Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA + {0x11103, 0x11126, prALetter}, // Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA + {0x11127, 0x1112B, prExtend}, // Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU + {0x1112C, 0x1112C, prExtend}, // Mc CHAKMA VOWEL SIGN E + {0x1112D, 0x11134, prExtend}, // Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA + {0x11136, 0x1113F, prNumeric}, // Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE + {0x11144, 0x11144, prALetter}, // Lo CHAKMA LETTER LHAA + {0x11145, 0x11146, prExtend}, // Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI + {0x11147, 0x11147, prALetter}, // Lo CHAKMA LETTER VAA + {0x11150, 0x11172, prALetter}, // Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA + {0x11173, 0x11173, prExtend}, // Mn MAHAJANI SIGN NUKTA + {0x11176, 0x11176, prALetter}, // Lo MAHAJANI LIGATURE SHRI + {0x11180, 0x11181, prExtend}, // Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA + {0x11182, 0x11182, prExtend}, // Mc SHARADA SIGN VISARGA + {0x11183, 0x111B2, prALetter}, // Lo [48] SHARADA LETTER A..SHARADA LETTER HA + {0x111B3, 0x111B5, prExtend}, // Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II + {0x111B6, 0x111BE, prExtend}, // Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O + {0x111BF, 0x111C0, prExtend}, // Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA + {0x111C1, 0x111C4, prALetter}, // Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM + {0x111C9, 0x111CC, prExtend}, // Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK + {0x111CE, 0x111CE, prExtend}, // Mc SHARADA VOWEL SIGN PRISHTHAMATRA E + {0x111CF, 0x111CF, prExtend}, // Mn SHARADA SIGN INVERTED CANDRABINDU + {0x111D0, 0x111D9, prNumeric}, // Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE + {0x111DA, 0x111DA, prALetter}, // Lo SHARADA EKAM + {0x111DC, 0x111DC, prALetter}, // Lo SHARADA HEADSTROKE + {0x11200, 0x11211, prALetter}, // Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA + {0x11213, 0x1122B, prALetter}, // Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA + {0x1122C, 0x1122E, prExtend}, // Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II + {0x1122F, 0x11231, prExtend}, // Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI + {0x11232, 0x11233, prExtend}, // Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU + {0x11234, 0x11234, prExtend}, // Mn KHOJKI SIGN ANUSVARA + {0x11235, 0x11235, prExtend}, // Mc KHOJKI SIGN VIRAMA + {0x11236, 0x11237, prExtend}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA + {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prALetter}, // Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prExtend}, // Mn KHOJKI VOWEL SIGN VOCALIC R + {0x11280, 0x11286, prALetter}, // Lo [7] MULTANI LETTER A..MULTANI LETTER GA + {0x11288, 0x11288, prALetter}, // Lo MULTANI LETTER GHA + {0x1128A, 0x1128D, prALetter}, // Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA + {0x1128F, 0x1129D, prALetter}, // Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA + {0x1129F, 0x112A8, prALetter}, // Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA + {0x112B0, 0x112DE, prALetter}, // Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA + {0x112DF, 0x112DF, prExtend}, // Mn KHUDAWADI SIGN ANUSVARA + {0x112E0, 0x112E2, prExtend}, // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II + {0x112E3, 0x112EA, prExtend}, // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA + {0x112F0, 0x112F9, prNumeric}, // Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE + {0x11300, 0x11301, prExtend}, // Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU + {0x11302, 0x11303, prExtend}, // Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA + {0x11305, 0x1130C, prALetter}, // Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L + {0x1130F, 0x11310, prALetter}, // Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI + {0x11313, 0x11328, prALetter}, // Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA + {0x1132A, 0x11330, prALetter}, // Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA + {0x11332, 0x11333, prALetter}, // Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA + {0x11335, 0x11339, prALetter}, // Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA + {0x1133B, 0x1133C, prExtend}, // Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA + {0x1133D, 0x1133D, prALetter}, // Lo GRANTHA SIGN AVAGRAHA + {0x1133E, 0x1133F, prExtend}, // Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I + {0x11340, 0x11340, prExtend}, // Mn GRANTHA VOWEL SIGN II + {0x11341, 0x11344, prExtend}, // Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR + {0x11347, 0x11348, prExtend}, // Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI + {0x1134B, 0x1134D, prExtend}, // Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA + {0x11350, 0x11350, prALetter}, // Lo GRANTHA OM + {0x11357, 0x11357, prExtend}, // Mc GRANTHA AU LENGTH MARK + {0x1135D, 0x11361, prALetter}, // Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL + {0x11362, 0x11363, prExtend}, // Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL + {0x11366, 0x1136C, prExtend}, // Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX + {0x11370, 0x11374, prExtend}, // Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA + {0x11400, 0x11434, prALetter}, // Lo [53] NEWA LETTER A..NEWA LETTER HA + {0x11435, 0x11437, prExtend}, // Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II + {0x11438, 0x1143F, prExtend}, // Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI + {0x11440, 0x11441, prExtend}, // Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU + {0x11442, 0x11444, prExtend}, // Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA + {0x11445, 0x11445, prExtend}, // Mc NEWA SIGN VISARGA + {0x11446, 0x11446, prExtend}, // Mn NEWA SIGN NUKTA + {0x11447, 0x1144A, prALetter}, // Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI + {0x11450, 0x11459, prNumeric}, // Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE + {0x1145E, 0x1145E, prExtend}, // Mn NEWA SANDHI MARK + {0x1145F, 0x11461, prALetter}, // Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA + {0x11480, 0x114AF, prALetter}, // Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA + {0x114B0, 0x114B2, prExtend}, // Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II + {0x114B3, 0x114B8, prExtend}, // Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL + {0x114B9, 0x114B9, prExtend}, // Mc TIRHUTA VOWEL SIGN E + {0x114BA, 0x114BA, prExtend}, // Mn TIRHUTA VOWEL SIGN SHORT E + {0x114BB, 0x114BE, prExtend}, // Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU + {0x114BF, 0x114C0, prExtend}, // Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA + {0x114C1, 0x114C1, prExtend}, // Mc TIRHUTA SIGN VISARGA + {0x114C2, 0x114C3, prExtend}, // Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA + {0x114C4, 0x114C5, prALetter}, // Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG + {0x114C7, 0x114C7, prALetter}, // Lo TIRHUTA OM + {0x114D0, 0x114D9, prNumeric}, // Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE + {0x11580, 0x115AE, prALetter}, // Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA + {0x115AF, 0x115B1, prExtend}, // Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II + {0x115B2, 0x115B5, prExtend}, // Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR + {0x115B8, 0x115BB, prExtend}, // Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU + {0x115BC, 0x115BD, prExtend}, // Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA + {0x115BE, 0x115BE, prExtend}, // Mc SIDDHAM SIGN VISARGA + {0x115BF, 0x115C0, prExtend}, // Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA + {0x115D8, 0x115DB, prALetter}, // Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U + {0x115DC, 0x115DD, prExtend}, // Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU + {0x11600, 0x1162F, prALetter}, // Lo [48] MODI LETTER A..MODI LETTER LLA + {0x11630, 0x11632, prExtend}, // Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II + {0x11633, 0x1163A, prExtend}, // Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI + {0x1163B, 0x1163C, prExtend}, // Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU + {0x1163D, 0x1163D, prExtend}, // Mn MODI SIGN ANUSVARA + {0x1163E, 0x1163E, prExtend}, // Mc MODI SIGN VISARGA + {0x1163F, 0x11640, prExtend}, // Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA + {0x11644, 0x11644, prALetter}, // Lo MODI SIGN HUVA + {0x11650, 0x11659, prNumeric}, // Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE + {0x11680, 0x116AA, prALetter}, // Lo [43] TAKRI LETTER A..TAKRI LETTER RRA + {0x116AB, 0x116AB, prExtend}, // Mn TAKRI SIGN ANUSVARA + {0x116AC, 0x116AC, prExtend}, // Mc TAKRI SIGN VISARGA + {0x116AD, 0x116AD, prExtend}, // Mn TAKRI VOWEL SIGN AA + {0x116AE, 0x116AF, prExtend}, // Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II + {0x116B0, 0x116B5, prExtend}, // Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU + {0x116B6, 0x116B6, prExtend}, // Mc TAKRI SIGN VIRAMA + {0x116B7, 0x116B7, prExtend}, // Mn TAKRI SIGN NUKTA + {0x116B8, 0x116B8, prALetter}, // Lo TAKRI LETTER ARCHAIC KHA + {0x116C0, 0x116C9, prNumeric}, // Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE + {0x1171D, 0x1171F, prExtend}, // Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA + {0x11720, 0x11721, prExtend}, // Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA + {0x11722, 0x11725, prExtend}, // Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU + {0x11726, 0x11726, prExtend}, // Mc AHOM VOWEL SIGN E + {0x11727, 0x1172B, prExtend}, // Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER + {0x11730, 0x11739, prNumeric}, // Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE + {0x11800, 0x1182B, prALetter}, // Lo [44] DOGRA LETTER A..DOGRA LETTER RRA + {0x1182C, 0x1182E, prExtend}, // Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II + {0x1182F, 0x11837, prExtend}, // Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA + {0x11838, 0x11838, prExtend}, // Mc DOGRA SIGN VISARGA + {0x11839, 0x1183A, prExtend}, // Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA + {0x118A0, 0x118DF, prALetter}, // L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO + {0x118E0, 0x118E9, prNumeric}, // Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE + {0x118FF, 0x11906, prALetter}, // Lo [8] WARANG CITI OM..DIVES AKURU LETTER E + {0x11909, 0x11909, prALetter}, // Lo DIVES AKURU LETTER O + {0x1190C, 0x11913, prALetter}, // Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA + {0x11915, 0x11916, prALetter}, // Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA + {0x11918, 0x1192F, prALetter}, // Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA + {0x11930, 0x11935, prExtend}, // Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E + {0x11937, 0x11938, prExtend}, // Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O + {0x1193B, 0x1193C, prExtend}, // Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU + {0x1193D, 0x1193D, prExtend}, // Mc DIVES AKURU SIGN HALANTA + {0x1193E, 0x1193E, prExtend}, // Mn DIVES AKURU VIRAMA + {0x1193F, 0x1193F, prALetter}, // Lo DIVES AKURU PREFIXED NASAL SIGN + {0x11940, 0x11940, prExtend}, // Mc DIVES AKURU MEDIAL YA + {0x11941, 0x11941, prALetter}, // Lo DIVES AKURU INITIAL RA + {0x11942, 0x11942, prExtend}, // Mc DIVES AKURU MEDIAL RA + {0x11943, 0x11943, prExtend}, // Mn DIVES AKURU SIGN NUKTA + {0x11950, 0x11959, prNumeric}, // Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE + {0x119A0, 0x119A7, prALetter}, // Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR + {0x119AA, 0x119D0, prALetter}, // Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA + {0x119D1, 0x119D3, prExtend}, // Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II + {0x119D4, 0x119D7, prExtend}, // Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR + {0x119DA, 0x119DB, prExtend}, // Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI + {0x119DC, 0x119DF, prExtend}, // Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA + {0x119E0, 0x119E0, prExtend}, // Mn NANDINAGARI SIGN VIRAMA + {0x119E1, 0x119E1, prALetter}, // Lo NANDINAGARI SIGN AVAGRAHA + {0x119E3, 0x119E3, prALetter}, // Lo NANDINAGARI HEADSTROKE + {0x119E4, 0x119E4, prExtend}, // Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E + {0x11A00, 0x11A00, prALetter}, // Lo ZANABAZAR SQUARE LETTER A + {0x11A01, 0x11A0A, prExtend}, // Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK + {0x11A0B, 0x11A32, prALetter}, // Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA + {0x11A33, 0x11A38, prExtend}, // Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA + {0x11A39, 0x11A39, prExtend}, // Mc ZANABAZAR SQUARE SIGN VISARGA + {0x11A3A, 0x11A3A, prALetter}, // Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA + {0x11A3B, 0x11A3E, prExtend}, // Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA + {0x11A47, 0x11A47, prExtend}, // Mn ZANABAZAR SQUARE SUBJOINER + {0x11A50, 0x11A50, prALetter}, // Lo SOYOMBO LETTER A + {0x11A51, 0x11A56, prExtend}, // Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE + {0x11A57, 0x11A58, prExtend}, // Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU + {0x11A59, 0x11A5B, prExtend}, // Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK + {0x11A5C, 0x11A89, prALetter}, // Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA + {0x11A8A, 0x11A96, prExtend}, // Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA + {0x11A97, 0x11A97, prExtend}, // Mc SOYOMBO SIGN VISARGA + {0x11A98, 0x11A99, prExtend}, // Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER + {0x11A9D, 0x11A9D, prALetter}, // Lo SOYOMBO MARK PLUTA + {0x11AB0, 0x11AF8, prALetter}, // Lo [73] CANADIAN SYLLABICS NATTILIK HI..PAU CIN HAU GLOTTAL STOP FINAL + {0x11C00, 0x11C08, prALetter}, // Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L + {0x11C0A, 0x11C2E, prALetter}, // Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA + {0x11C2F, 0x11C2F, prExtend}, // Mc BHAIKSUKI VOWEL SIGN AA + {0x11C30, 0x11C36, prExtend}, // Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L + {0x11C38, 0x11C3D, prExtend}, // Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA + {0x11C3E, 0x11C3E, prExtend}, // Mc BHAIKSUKI SIGN VISARGA + {0x11C3F, 0x11C3F, prExtend}, // Mn BHAIKSUKI SIGN VIRAMA + {0x11C40, 0x11C40, prALetter}, // Lo BHAIKSUKI SIGN AVAGRAHA + {0x11C50, 0x11C59, prNumeric}, // Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE + {0x11C72, 0x11C8F, prALetter}, // Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A + {0x11C92, 0x11CA7, prExtend}, // Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA + {0x11CA9, 0x11CA9, prExtend}, // Mc MARCHEN SUBJOINED LETTER YA + {0x11CAA, 0x11CB0, prExtend}, // Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA + {0x11CB1, 0x11CB1, prExtend}, // Mc MARCHEN VOWEL SIGN I + {0x11CB2, 0x11CB3, prExtend}, // Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E + {0x11CB4, 0x11CB4, prExtend}, // Mc MARCHEN VOWEL SIGN O + {0x11CB5, 0x11CB6, prExtend}, // Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU + {0x11D00, 0x11D06, prALetter}, // Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E + {0x11D08, 0x11D09, prALetter}, // Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O + {0x11D0B, 0x11D30, prALetter}, // Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA + {0x11D31, 0x11D36, prExtend}, // Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R + {0x11D3A, 0x11D3A, prExtend}, // Mn MASARAM GONDI VOWEL SIGN E + {0x11D3C, 0x11D3D, prExtend}, // Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O + {0x11D3F, 0x11D45, prExtend}, // Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA + {0x11D46, 0x11D46, prALetter}, // Lo MASARAM GONDI REPHA + {0x11D47, 0x11D47, prExtend}, // Mn MASARAM GONDI RA-KARA + {0x11D50, 0x11D59, prNumeric}, // Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE + {0x11D60, 0x11D65, prALetter}, // Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU + {0x11D67, 0x11D68, prALetter}, // Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI + {0x11D6A, 0x11D89, prALetter}, // Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA + {0x11D8A, 0x11D8E, prExtend}, // Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU + {0x11D90, 0x11D91, prExtend}, // Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI + {0x11D93, 0x11D94, prExtend}, // Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU + {0x11D95, 0x11D95, prExtend}, // Mn GUNJALA GONDI SIGN ANUSVARA + {0x11D96, 0x11D96, prExtend}, // Mc GUNJALA GONDI SIGN VISARGA + {0x11D97, 0x11D97, prExtend}, // Mn GUNJALA GONDI VIRAMA + {0x11D98, 0x11D98, prALetter}, // Lo GUNJALA GONDI OM + {0x11DA0, 0x11DA9, prNumeric}, // Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE + {0x11EE0, 0x11EF2, prALetter}, // Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA + {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U + {0x11EF5, 0x11EF6, prExtend}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x11F00, 0x11F01, prExtend}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prALetter}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prExtend}, // Mc KAWI SIGN VISARGA + {0x11F04, 0x11F10, prALetter}, // Lo [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prALetter}, // Lo [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prExtend}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prExtend}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prExtend}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prExtend}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prExtend}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prExtend}, // Mn KAWI CONJOINER + {0x11F50, 0x11F59, prNumeric}, // Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE + {0x11FB0, 0x11FB0, prALetter}, // Lo LISU LETTER YHA + {0x12000, 0x12399, prALetter}, // Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U + {0x12400, 0x1246E, prALetter}, // Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM + {0x12480, 0x12543, prALetter}, // Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU + {0x12F90, 0x12FF0, prALetter}, // Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 + {0x13000, 0x1342F, prALetter}, // Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x1343F, prFormat}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prExtend}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prALetter}, // Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prExtend}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED + {0x14400, 0x14646, prALetter}, // Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 + {0x16800, 0x16A38, prALetter}, // Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ + {0x16A40, 0x16A5E, prALetter}, // Lo [31] MRO LETTER TA..MRO LETTER TEK + {0x16A60, 0x16A69, prNumeric}, // Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE + {0x16A70, 0x16ABE, prALetter}, // Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA + {0x16AC0, 0x16AC9, prNumeric}, // Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE + {0x16AD0, 0x16AED, prALetter}, // Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I + {0x16AF0, 0x16AF4, prExtend}, // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE + {0x16B00, 0x16B2F, prALetter}, // Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU + {0x16B30, 0x16B36, prExtend}, // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM + {0x16B40, 0x16B43, prALetter}, // Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM + {0x16B50, 0x16B59, prNumeric}, // Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE + {0x16B63, 0x16B77, prALetter}, // Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS + {0x16B7D, 0x16B8F, prALetter}, // Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ + {0x16E40, 0x16E7F, prALetter}, // L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y + {0x16F00, 0x16F4A, prALetter}, // Lo [75] MIAO LETTER PA..MIAO LETTER RTE + {0x16F4F, 0x16F4F, prExtend}, // Mn MIAO SIGN CONSONANT MODIFIER BAR + {0x16F50, 0x16F50, prALetter}, // Lo MIAO LETTER NASALIZATION + {0x16F51, 0x16F87, prExtend}, // Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI + {0x16F8F, 0x16F92, prExtend}, // Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW + {0x16F93, 0x16F9F, prALetter}, // Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 + {0x16FE0, 0x16FE1, prALetter}, // Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK + {0x16FE3, 0x16FE3, prALetter}, // Lm OLD CHINESE ITERATION MARK + {0x16FE4, 0x16FE4, prExtend}, // Mn KHITAN SMALL SCRIPT FILLER + {0x16FF0, 0x16FF1, prExtend}, // Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY + {0x1AFF0, 0x1AFF3, prKatakana}, // Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 + {0x1AFF5, 0x1AFFB, prKatakana}, // Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 + {0x1AFFD, 0x1AFFE, prKatakana}, // Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 + {0x1B000, 0x1B000, prKatakana}, // Lo KATAKANA LETTER ARCHAIC E + {0x1B120, 0x1B122, prKatakana}, // Lo [3] KATAKANA LETTER ARCHAIC YI..KATAKANA LETTER ARCHAIC WU + {0x1B155, 0x1B155, prKatakana}, // Lo KATAKANA LETTER SMALL KO + {0x1B164, 0x1B167, prKatakana}, // Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N + {0x1BC00, 0x1BC6A, prALetter}, // Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M + {0x1BC70, 0x1BC7C, prALetter}, // Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK + {0x1BC80, 0x1BC88, prALetter}, // Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL + {0x1BC90, 0x1BC99, prALetter}, // Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW + {0x1BC9D, 0x1BC9E, prExtend}, // Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK + {0x1BCA0, 0x1BCA3, prFormat}, // Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP + {0x1CF00, 0x1CF2D, prExtend}, // Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT + {0x1CF30, 0x1CF46, prExtend}, // Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG + {0x1D165, 0x1D166, prExtend}, // Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM + {0x1D167, 0x1D169, prExtend}, // Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 + {0x1D16D, 0x1D172, prExtend}, // Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 + {0x1D173, 0x1D17A, prFormat}, // Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE + {0x1D17B, 0x1D182, prExtend}, // Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE + {0x1D185, 0x1D18B, prExtend}, // Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE + {0x1D1AA, 0x1D1AD, prExtend}, // Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO + {0x1D242, 0x1D244, prExtend}, // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME + {0x1D400, 0x1D454, prALetter}, // L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G + {0x1D456, 0x1D49C, prALetter}, // L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A + {0x1D49E, 0x1D49F, prALetter}, // L& [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D + {0x1D4A2, 0x1D4A2, prALetter}, // L& MATHEMATICAL SCRIPT CAPITAL G + {0x1D4A5, 0x1D4A6, prALetter}, // L& [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K + {0x1D4A9, 0x1D4AC, prALetter}, // L& [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q + {0x1D4AE, 0x1D4B9, prALetter}, // L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D + {0x1D4BB, 0x1D4BB, prALetter}, // L& MATHEMATICAL SCRIPT SMALL F + {0x1D4BD, 0x1D4C3, prALetter}, // L& [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N + {0x1D4C5, 0x1D505, prALetter}, // L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B + {0x1D507, 0x1D50A, prALetter}, // L& [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G + {0x1D50D, 0x1D514, prALetter}, // L& [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q + {0x1D516, 0x1D51C, prALetter}, // L& [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y + {0x1D51E, 0x1D539, prALetter}, // L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B + {0x1D53B, 0x1D53E, prALetter}, // L& [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G + {0x1D540, 0x1D544, prALetter}, // L& [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M + {0x1D546, 0x1D546, prALetter}, // L& MATHEMATICAL DOUBLE-STRUCK CAPITAL O + {0x1D54A, 0x1D550, prALetter}, // L& [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y + {0x1D552, 0x1D6A5, prALetter}, // L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J + {0x1D6A8, 0x1D6C0, prALetter}, // L& [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA + {0x1D6C2, 0x1D6DA, prALetter}, // L& [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA + {0x1D6DC, 0x1D6FA, prALetter}, // L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA + {0x1D6FC, 0x1D714, prALetter}, // L& [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA + {0x1D716, 0x1D734, prALetter}, // L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA + {0x1D736, 0x1D74E, prALetter}, // L& [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA + {0x1D750, 0x1D76E, prALetter}, // L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA + {0x1D770, 0x1D788, prALetter}, // L& [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA + {0x1D78A, 0x1D7A8, prALetter}, // L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA + {0x1D7AA, 0x1D7C2, prALetter}, // L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA + {0x1D7C4, 0x1D7CB, prALetter}, // L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA + {0x1D7CE, 0x1D7FF, prNumeric}, // Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE + {0x1DA00, 0x1DA36, prExtend}, // Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN + {0x1DA3B, 0x1DA6C, prExtend}, // Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT + {0x1DA75, 0x1DA75, prExtend}, // Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS + {0x1DA84, 0x1DA84, prExtend}, // Mn SIGNWRITING LOCATION HEAD NECK + {0x1DA9B, 0x1DA9F, prExtend}, // Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6 + {0x1DAA1, 0x1DAAF, prExtend}, // Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16 + {0x1DF00, 0x1DF09, prALetter}, // L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK + {0x1DF0A, 0x1DF0A, prALetter}, // Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK + {0x1DF0B, 0x1DF1E, prALetter}, // L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prALetter}, // L& [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK + {0x1E000, 0x1E006, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE + {0x1E008, 0x1E018, prExtend}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU + {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI + {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS + {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prALetter}, // Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prExtend}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + {0x1E100, 0x1E12C, prALetter}, // Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W + {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D + {0x1E137, 0x1E13D, prALetter}, // Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER + {0x1E140, 0x1E149, prNumeric}, // Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE + {0x1E14E, 0x1E14E, prALetter}, // Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ + {0x1E290, 0x1E2AD, prALetter}, // Lo [30] TOTO LETTER PA..TOTO LETTER A + {0x1E2AE, 0x1E2AE, prExtend}, // Mn TOTO SIGN RISING TONE + {0x1E2C0, 0x1E2EB, prALetter}, // Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH + {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E2F0, 0x1E2F9, prNumeric}, // Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE + {0x1E4D0, 0x1E4EA, prALetter}, // Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prALetter}, // Lm NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prExtend}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prNumeric}, // Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE + {0x1E7E0, 0x1E7E6, prALetter}, // Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO + {0x1E7E8, 0x1E7EB, prALetter}, // Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE + {0x1E7ED, 0x1E7EE, prALetter}, // Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE + {0x1E7F0, 0x1E7FE, prALetter}, // Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE + {0x1E800, 0x1E8C4, prALetter}, // Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON + {0x1E8D0, 0x1E8D6, prExtend}, // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS + {0x1E900, 0x1E943, prALetter}, // L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA + {0x1E944, 0x1E94A, prExtend}, // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA + {0x1E94B, 0x1E94B, prALetter}, // Lm ADLAM NASALIZATION MARK + {0x1E950, 0x1E959, prNumeric}, // Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE + {0x1EE00, 0x1EE03, prALetter}, // Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL + {0x1EE05, 0x1EE1F, prALetter}, // Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF + {0x1EE21, 0x1EE22, prALetter}, // Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM + {0x1EE24, 0x1EE24, prALetter}, // Lo ARABIC MATHEMATICAL INITIAL HEH + {0x1EE27, 0x1EE27, prALetter}, // Lo ARABIC MATHEMATICAL INITIAL HAH + {0x1EE29, 0x1EE32, prALetter}, // Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF + {0x1EE34, 0x1EE37, prALetter}, // Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH + {0x1EE39, 0x1EE39, prALetter}, // Lo ARABIC MATHEMATICAL INITIAL DAD + {0x1EE3B, 0x1EE3B, prALetter}, // Lo ARABIC MATHEMATICAL INITIAL GHAIN + {0x1EE42, 0x1EE42, prALetter}, // Lo ARABIC MATHEMATICAL TAILED JEEM + {0x1EE47, 0x1EE47, prALetter}, // Lo ARABIC MATHEMATICAL TAILED HAH + {0x1EE49, 0x1EE49, prALetter}, // Lo ARABIC MATHEMATICAL TAILED YEH + {0x1EE4B, 0x1EE4B, prALetter}, // Lo ARABIC MATHEMATICAL TAILED LAM + {0x1EE4D, 0x1EE4F, prALetter}, // Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN + {0x1EE51, 0x1EE52, prALetter}, // Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF + {0x1EE54, 0x1EE54, prALetter}, // Lo ARABIC MATHEMATICAL TAILED SHEEN + {0x1EE57, 0x1EE57, prALetter}, // Lo ARABIC MATHEMATICAL TAILED KHAH + {0x1EE59, 0x1EE59, prALetter}, // Lo ARABIC MATHEMATICAL TAILED DAD + {0x1EE5B, 0x1EE5B, prALetter}, // Lo ARABIC MATHEMATICAL TAILED GHAIN + {0x1EE5D, 0x1EE5D, prALetter}, // Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON + {0x1EE5F, 0x1EE5F, prALetter}, // Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF + {0x1EE61, 0x1EE62, prALetter}, // Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM + {0x1EE64, 0x1EE64, prALetter}, // Lo ARABIC MATHEMATICAL STRETCHED HEH + {0x1EE67, 0x1EE6A, prALetter}, // Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF + {0x1EE6C, 0x1EE72, prALetter}, // Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF + {0x1EE74, 0x1EE77, prALetter}, // Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH + {0x1EE79, 0x1EE7C, prALetter}, // Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH + {0x1EE7E, 0x1EE7E, prALetter}, // Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH + {0x1EE80, 0x1EE89, prALetter}, // Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH + {0x1EE8B, 0x1EE9B, prALetter}, // Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN + {0x1EEA1, 0x1EEA3, prALetter}, // Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL + {0x1EEA5, 0x1EEA9, prALetter}, // Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH + {0x1EEAB, 0x1EEBB, prALetter}, // Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN + {0x1F000, 0x1F003, prExtendedPictographic}, // E0.0 [4] (🀀..🀃) MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND + {0x1F004, 0x1F004, prExtendedPictographic}, // E0.6 [1] (🀄) mahjong red dragon + {0x1F005, 0x1F0CE, prExtendedPictographic}, // E0.0 [202] (🀅..🃎) MAHJONG TILE GREEN DRAGON..PLAYING CARD KING OF DIAMONDS + {0x1F0CF, 0x1F0CF, prExtendedPictographic}, // E0.6 [1] (🃏) joker + {0x1F0D0, 0x1F0FF, prExtendedPictographic}, // E0.0 [48] (🃐..🃿) .. + {0x1F10D, 0x1F10F, prExtendedPictographic}, // E0.0 [3] (🄍..🄏) CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH + {0x1F12F, 0x1F12F, prExtendedPictographic}, // E0.0 [1] (🄯) COPYLEFT SYMBOL + {0x1F130, 0x1F149, prALetter}, // So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z + {0x1F150, 0x1F169, prALetter}, // So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z + {0x1F16C, 0x1F16F, prExtendedPictographic}, // E0.0 [4] (🅬..🅯) RAISED MR SIGN..CIRCLED HUMAN FIGURE + {0x1F170, 0x1F189, prALetter}, // So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z + {0x1F170, 0x1F171, prExtendedPictographic}, // E0.6 [2] (🅰️..🅱️) A button (blood type)..B button (blood type) + {0x1F17E, 0x1F17F, prExtendedPictographic}, // E0.6 [2] (🅾️..🅿️) O button (blood type)..P button + {0x1F18E, 0x1F18E, prExtendedPictographic}, // E0.6 [1] (🆎) AB button (blood type) + {0x1F191, 0x1F19A, prExtendedPictographic}, // E0.6 [10] (🆑..🆚) CL button..VS button + {0x1F1AD, 0x1F1E5, prExtendedPictographic}, // E0.0 [57] (🆭..🇥) MASK WORK SYMBOL.. + {0x1F1E6, 0x1F1FF, prRegionalIndicator}, // So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + {0x1F201, 0x1F202, prExtendedPictographic}, // E0.6 [2] (🈁..🈂️) Japanese “here” button..Japanese “service charge” button + {0x1F203, 0x1F20F, prExtendedPictographic}, // E0.0 [13] (🈃..🈏) .. + {0x1F21A, 0x1F21A, prExtendedPictographic}, // E0.6 [1] (🈚) Japanese “free of charge” button + {0x1F22F, 0x1F22F, prExtendedPictographic}, // E0.6 [1] (🈯) Japanese “reserved” button + {0x1F232, 0x1F23A, prExtendedPictographic}, // E0.6 [9] (🈲..🈺) Japanese “prohibited” button..Japanese “open for business” button + {0x1F23C, 0x1F23F, prExtendedPictographic}, // E0.0 [4] (🈼..🈿) .. + {0x1F249, 0x1F24F, prExtendedPictographic}, // E0.0 [7] (🉉..🉏) .. + {0x1F250, 0x1F251, prExtendedPictographic}, // E0.6 [2] (🉐..🉑) Japanese “bargain” button..Japanese “acceptable” button + {0x1F252, 0x1F2FF, prExtendedPictographic}, // E0.0 [174] (🉒..🋿) .. + {0x1F300, 0x1F30C, prExtendedPictographic}, // E0.6 [13] (🌀..🌌) cyclone..milky way + {0x1F30D, 0x1F30E, prExtendedPictographic}, // E0.7 [2] (🌍..🌎) globe showing Europe-Africa..globe showing Americas + {0x1F30F, 0x1F30F, prExtendedPictographic}, // E0.6 [1] (🌏) globe showing Asia-Australia + {0x1F310, 0x1F310, prExtendedPictographic}, // E1.0 [1] (🌐) globe with meridians + {0x1F311, 0x1F311, prExtendedPictographic}, // E0.6 [1] (🌑) new moon + {0x1F312, 0x1F312, prExtendedPictographic}, // E1.0 [1] (🌒) waxing crescent moon + {0x1F313, 0x1F315, prExtendedPictographic}, // E0.6 [3] (🌓..🌕) first quarter moon..full moon + {0x1F316, 0x1F318, prExtendedPictographic}, // E1.0 [3] (🌖..🌘) waning gibbous moon..waning crescent moon + {0x1F319, 0x1F319, prExtendedPictographic}, // E0.6 [1] (🌙) crescent moon + {0x1F31A, 0x1F31A, prExtendedPictographic}, // E1.0 [1] (🌚) new moon face + {0x1F31B, 0x1F31B, prExtendedPictographic}, // E0.6 [1] (🌛) first quarter moon face + {0x1F31C, 0x1F31C, prExtendedPictographic}, // E0.7 [1] (🌜) last quarter moon face + {0x1F31D, 0x1F31E, prExtendedPictographic}, // E1.0 [2] (🌝..🌞) full moon face..sun with face + {0x1F31F, 0x1F320, prExtendedPictographic}, // E0.6 [2] (🌟..🌠) glowing star..shooting star + {0x1F321, 0x1F321, prExtendedPictographic}, // E0.7 [1] (🌡️) thermometer + {0x1F322, 0x1F323, prExtendedPictographic}, // E0.0 [2] (🌢..🌣) BLACK DROPLET..WHITE SUN + {0x1F324, 0x1F32C, prExtendedPictographic}, // E0.7 [9] (🌤️..🌬️) sun behind small cloud..wind face + {0x1F32D, 0x1F32F, prExtendedPictographic}, // E1.0 [3] (🌭..🌯) hot dog..burrito + {0x1F330, 0x1F331, prExtendedPictographic}, // E0.6 [2] (🌰..🌱) chestnut..seedling + {0x1F332, 0x1F333, prExtendedPictographic}, // E1.0 [2] (🌲..🌳) evergreen tree..deciduous tree + {0x1F334, 0x1F335, prExtendedPictographic}, // E0.6 [2] (🌴..🌵) palm tree..cactus + {0x1F336, 0x1F336, prExtendedPictographic}, // E0.7 [1] (🌶️) hot pepper + {0x1F337, 0x1F34A, prExtendedPictographic}, // E0.6 [20] (🌷..🍊) tulip..tangerine + {0x1F34B, 0x1F34B, prExtendedPictographic}, // E1.0 [1] (🍋) lemon + {0x1F34C, 0x1F34F, prExtendedPictographic}, // E0.6 [4] (🍌..🍏) banana..green apple + {0x1F350, 0x1F350, prExtendedPictographic}, // E1.0 [1] (🍐) pear + {0x1F351, 0x1F37B, prExtendedPictographic}, // E0.6 [43] (🍑..🍻) peach..clinking beer mugs + {0x1F37C, 0x1F37C, prExtendedPictographic}, // E1.0 [1] (🍼) baby bottle + {0x1F37D, 0x1F37D, prExtendedPictographic}, // E0.7 [1] (🍽️) fork and knife with plate + {0x1F37E, 0x1F37F, prExtendedPictographic}, // E1.0 [2] (🍾..🍿) bottle with popping cork..popcorn + {0x1F380, 0x1F393, prExtendedPictographic}, // E0.6 [20] (🎀..🎓) ribbon..graduation cap + {0x1F394, 0x1F395, prExtendedPictographic}, // E0.0 [2] (🎔..🎕) HEART WITH TIP ON THE LEFT..BOUQUET OF FLOWERS + {0x1F396, 0x1F397, prExtendedPictographic}, // E0.7 [2] (🎖️..🎗️) military medal..reminder ribbon + {0x1F398, 0x1F398, prExtendedPictographic}, // E0.0 [1] (🎘) MUSICAL KEYBOARD WITH JACKS + {0x1F399, 0x1F39B, prExtendedPictographic}, // E0.7 [3] (🎙️..🎛️) studio microphone..control knobs + {0x1F39C, 0x1F39D, prExtendedPictographic}, // E0.0 [2] (🎜..🎝) BEAMED ASCENDING MUSICAL NOTES..BEAMED DESCENDING MUSICAL NOTES + {0x1F39E, 0x1F39F, prExtendedPictographic}, // E0.7 [2] (🎞️..🎟️) film frames..admission tickets + {0x1F3A0, 0x1F3C4, prExtendedPictographic}, // E0.6 [37] (🎠..🏄) carousel horse..person surfing + {0x1F3C5, 0x1F3C5, prExtendedPictographic}, // E1.0 [1] (🏅) sports medal + {0x1F3C6, 0x1F3C6, prExtendedPictographic}, // E0.6 [1] (🏆) trophy + {0x1F3C7, 0x1F3C7, prExtendedPictographic}, // E1.0 [1] (🏇) horse racing + {0x1F3C8, 0x1F3C8, prExtendedPictographic}, // E0.6 [1] (🏈) american football + {0x1F3C9, 0x1F3C9, prExtendedPictographic}, // E1.0 [1] (🏉) rugby football + {0x1F3CA, 0x1F3CA, prExtendedPictographic}, // E0.6 [1] (🏊) person swimming + {0x1F3CB, 0x1F3CE, prExtendedPictographic}, // E0.7 [4] (🏋️..🏎️) person lifting weights..racing car + {0x1F3CF, 0x1F3D3, prExtendedPictographic}, // E1.0 [5] (🏏..🏓) cricket game..ping pong + {0x1F3D4, 0x1F3DF, prExtendedPictographic}, // E0.7 [12] (🏔️..🏟️) snow-capped mountain..stadium + {0x1F3E0, 0x1F3E3, prExtendedPictographic}, // E0.6 [4] (🏠..🏣) house..Japanese post office + {0x1F3E4, 0x1F3E4, prExtendedPictographic}, // E1.0 [1] (🏤) post office + {0x1F3E5, 0x1F3F0, prExtendedPictographic}, // E0.6 [12] (🏥..🏰) hospital..castle + {0x1F3F1, 0x1F3F2, prExtendedPictographic}, // E0.0 [2] (🏱..🏲) WHITE PENNANT..BLACK PENNANT + {0x1F3F3, 0x1F3F3, prExtendedPictographic}, // E0.7 [1] (🏳️) white flag + {0x1F3F4, 0x1F3F4, prExtendedPictographic}, // E1.0 [1] (🏴) black flag + {0x1F3F5, 0x1F3F5, prExtendedPictographic}, // E0.7 [1] (🏵️) rosette + {0x1F3F6, 0x1F3F6, prExtendedPictographic}, // E0.0 [1] (🏶) BLACK ROSETTE + {0x1F3F7, 0x1F3F7, prExtendedPictographic}, // E0.7 [1] (🏷️) label + {0x1F3F8, 0x1F3FA, prExtendedPictographic}, // E1.0 [3] (🏸..🏺) badminton..amphora + {0x1F3FB, 0x1F3FF, prExtend}, // Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6 + {0x1F400, 0x1F407, prExtendedPictographic}, // E1.0 [8] (🐀..🐇) rat..rabbit + {0x1F408, 0x1F408, prExtendedPictographic}, // E0.7 [1] (🐈) cat + {0x1F409, 0x1F40B, prExtendedPictographic}, // E1.0 [3] (🐉..🐋) dragon..whale + {0x1F40C, 0x1F40E, prExtendedPictographic}, // E0.6 [3] (🐌..🐎) snail..horse + {0x1F40F, 0x1F410, prExtendedPictographic}, // E1.0 [2] (🐏..🐐) ram..goat + {0x1F411, 0x1F412, prExtendedPictographic}, // E0.6 [2] (🐑..🐒) ewe..monkey + {0x1F413, 0x1F413, prExtendedPictographic}, // E1.0 [1] (🐓) rooster + {0x1F414, 0x1F414, prExtendedPictographic}, // E0.6 [1] (🐔) chicken + {0x1F415, 0x1F415, prExtendedPictographic}, // E0.7 [1] (🐕) dog + {0x1F416, 0x1F416, prExtendedPictographic}, // E1.0 [1] (🐖) pig + {0x1F417, 0x1F429, prExtendedPictographic}, // E0.6 [19] (🐗..🐩) boar..poodle + {0x1F42A, 0x1F42A, prExtendedPictographic}, // E1.0 [1] (🐪) camel + {0x1F42B, 0x1F43E, prExtendedPictographic}, // E0.6 [20] (🐫..🐾) two-hump camel..paw prints + {0x1F43F, 0x1F43F, prExtendedPictographic}, // E0.7 [1] (🐿️) chipmunk + {0x1F440, 0x1F440, prExtendedPictographic}, // E0.6 [1] (👀) eyes + {0x1F441, 0x1F441, prExtendedPictographic}, // E0.7 [1] (👁️) eye + {0x1F442, 0x1F464, prExtendedPictographic}, // E0.6 [35] (👂..👤) ear..bust in silhouette + {0x1F465, 0x1F465, prExtendedPictographic}, // E1.0 [1] (👥) busts in silhouette + {0x1F466, 0x1F46B, prExtendedPictographic}, // E0.6 [6] (👦..👫) boy..woman and man holding hands + {0x1F46C, 0x1F46D, prExtendedPictographic}, // E1.0 [2] (👬..👭) men holding hands..women holding hands + {0x1F46E, 0x1F4AC, prExtendedPictographic}, // E0.6 [63] (👮..💬) police officer..speech balloon + {0x1F4AD, 0x1F4AD, prExtendedPictographic}, // E1.0 [1] (💭) thought balloon + {0x1F4AE, 0x1F4B5, prExtendedPictographic}, // E0.6 [8] (💮..💵) white flower..dollar banknote + {0x1F4B6, 0x1F4B7, prExtendedPictographic}, // E1.0 [2] (💶..💷) euro banknote..pound banknote + {0x1F4B8, 0x1F4EB, prExtendedPictographic}, // E0.6 [52] (💸..📫) money with wings..closed mailbox with raised flag + {0x1F4EC, 0x1F4ED, prExtendedPictographic}, // E0.7 [2] (📬..📭) open mailbox with raised flag..open mailbox with lowered flag + {0x1F4EE, 0x1F4EE, prExtendedPictographic}, // E0.6 [1] (📮) postbox + {0x1F4EF, 0x1F4EF, prExtendedPictographic}, // E1.0 [1] (📯) postal horn + {0x1F4F0, 0x1F4F4, prExtendedPictographic}, // E0.6 [5] (📰..📴) newspaper..mobile phone off + {0x1F4F5, 0x1F4F5, prExtendedPictographic}, // E1.0 [1] (📵) no mobile phones + {0x1F4F6, 0x1F4F7, prExtendedPictographic}, // E0.6 [2] (📶..📷) antenna bars..camera + {0x1F4F8, 0x1F4F8, prExtendedPictographic}, // E1.0 [1] (📸) camera with flash + {0x1F4F9, 0x1F4FC, prExtendedPictographic}, // E0.6 [4] (📹..📼) video camera..videocassette + {0x1F4FD, 0x1F4FD, prExtendedPictographic}, // E0.7 [1] (📽️) film projector + {0x1F4FE, 0x1F4FE, prExtendedPictographic}, // E0.0 [1] (📾) PORTABLE STEREO + {0x1F4FF, 0x1F502, prExtendedPictographic}, // E1.0 [4] (📿..🔂) prayer beads..repeat single button + {0x1F503, 0x1F503, prExtendedPictographic}, // E0.6 [1] (🔃) clockwise vertical arrows + {0x1F504, 0x1F507, prExtendedPictographic}, // E1.0 [4] (🔄..🔇) counterclockwise arrows button..muted speaker + {0x1F508, 0x1F508, prExtendedPictographic}, // E0.7 [1] (🔈) speaker low volume + {0x1F509, 0x1F509, prExtendedPictographic}, // E1.0 [1] (🔉) speaker medium volume + {0x1F50A, 0x1F514, prExtendedPictographic}, // E0.6 [11] (🔊..🔔) speaker high volume..bell + {0x1F515, 0x1F515, prExtendedPictographic}, // E1.0 [1] (🔕) bell with slash + {0x1F516, 0x1F52B, prExtendedPictographic}, // E0.6 [22] (🔖..🔫) bookmark..water pistol + {0x1F52C, 0x1F52D, prExtendedPictographic}, // E1.0 [2] (🔬..🔭) microscope..telescope + {0x1F52E, 0x1F53D, prExtendedPictographic}, // E0.6 [16] (🔮..🔽) crystal ball..downwards button + {0x1F546, 0x1F548, prExtendedPictographic}, // E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS + {0x1F549, 0x1F54A, prExtendedPictographic}, // E0.7 [2] (🕉️..🕊️) om..dove + {0x1F54B, 0x1F54E, prExtendedPictographic}, // E1.0 [4] (🕋..🕎) kaaba..menorah + {0x1F54F, 0x1F54F, prExtendedPictographic}, // E0.0 [1] (🕏) BOWL OF HYGIEIA + {0x1F550, 0x1F55B, prExtendedPictographic}, // E0.6 [12] (🕐..🕛) one o’clock..twelve o’clock + {0x1F55C, 0x1F567, prExtendedPictographic}, // E0.7 [12] (🕜..🕧) one-thirty..twelve-thirty + {0x1F568, 0x1F56E, prExtendedPictographic}, // E0.0 [7] (🕨..🕮) RIGHT SPEAKER..BOOK + {0x1F56F, 0x1F570, prExtendedPictographic}, // E0.7 [2] (🕯️..🕰️) candle..mantelpiece clock + {0x1F571, 0x1F572, prExtendedPictographic}, // E0.0 [2] (🕱..🕲) BLACK SKULL AND CROSSBONES..NO PIRACY + {0x1F573, 0x1F579, prExtendedPictographic}, // E0.7 [7] (🕳️..🕹️) hole..joystick + {0x1F57A, 0x1F57A, prExtendedPictographic}, // E3.0 [1] (🕺) man dancing + {0x1F57B, 0x1F586, prExtendedPictographic}, // E0.0 [12] (🕻..🖆) LEFT HAND TELEPHONE RECEIVER..PEN OVER STAMPED ENVELOPE + {0x1F587, 0x1F587, prExtendedPictographic}, // E0.7 [1] (🖇️) linked paperclips + {0x1F588, 0x1F589, prExtendedPictographic}, // E0.0 [2] (🖈..🖉) BLACK PUSHPIN..LOWER LEFT PENCIL + {0x1F58A, 0x1F58D, prExtendedPictographic}, // E0.7 [4] (🖊️..🖍️) pen..crayon + {0x1F58E, 0x1F58F, prExtendedPictographic}, // E0.0 [2] (🖎..🖏) LEFT WRITING HAND..TURNED OK HAND SIGN + {0x1F590, 0x1F590, prExtendedPictographic}, // E0.7 [1] (🖐️) hand with fingers splayed + {0x1F591, 0x1F594, prExtendedPictographic}, // E0.0 [4] (🖑..🖔) REVERSED RAISED HAND WITH FINGERS SPLAYED..REVERSED VICTORY HAND + {0x1F595, 0x1F596, prExtendedPictographic}, // E1.0 [2] (🖕..🖖) middle finger..vulcan salute + {0x1F597, 0x1F5A3, prExtendedPictographic}, // E0.0 [13] (🖗..🖣) WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX + {0x1F5A4, 0x1F5A4, prExtendedPictographic}, // E3.0 [1] (🖤) black heart + {0x1F5A5, 0x1F5A5, prExtendedPictographic}, // E0.7 [1] (🖥️) desktop computer + {0x1F5A6, 0x1F5A7, prExtendedPictographic}, // E0.0 [2] (🖦..🖧) KEYBOARD AND MOUSE..THREE NETWORKED COMPUTERS + {0x1F5A8, 0x1F5A8, prExtendedPictographic}, // E0.7 [1] (🖨️) printer + {0x1F5A9, 0x1F5B0, prExtendedPictographic}, // E0.0 [8] (🖩..🖰) POCKET CALCULATOR..TWO BUTTON MOUSE + {0x1F5B1, 0x1F5B2, prExtendedPictographic}, // E0.7 [2] (🖱️..🖲️) computer mouse..trackball + {0x1F5B3, 0x1F5BB, prExtendedPictographic}, // E0.0 [9] (🖳..🖻) OLD PERSONAL COMPUTER..DOCUMENT WITH PICTURE + {0x1F5BC, 0x1F5BC, prExtendedPictographic}, // E0.7 [1] (🖼️) framed picture + {0x1F5BD, 0x1F5C1, prExtendedPictographic}, // E0.0 [5] (🖽..🗁) FRAME WITH TILES..OPEN FOLDER + {0x1F5C2, 0x1F5C4, prExtendedPictographic}, // E0.7 [3] (🗂️..🗄️) card index dividers..file cabinet + {0x1F5C5, 0x1F5D0, prExtendedPictographic}, // E0.0 [12] (🗅..🗐) EMPTY NOTE..PAGES + {0x1F5D1, 0x1F5D3, prExtendedPictographic}, // E0.7 [3] (🗑️..🗓️) wastebasket..spiral calendar + {0x1F5D4, 0x1F5DB, prExtendedPictographic}, // E0.0 [8] (🗔..🗛) DESKTOP WINDOW..DECREASE FONT SIZE SYMBOL + {0x1F5DC, 0x1F5DE, prExtendedPictographic}, // E0.7 [3] (🗜️..🗞️) clamp..rolled-up newspaper + {0x1F5DF, 0x1F5E0, prExtendedPictographic}, // E0.0 [2] (🗟..🗠) PAGE WITH CIRCLED TEXT..STOCK CHART + {0x1F5E1, 0x1F5E1, prExtendedPictographic}, // E0.7 [1] (🗡️) dagger + {0x1F5E2, 0x1F5E2, prExtendedPictographic}, // E0.0 [1] (🗢) LIPS + {0x1F5E3, 0x1F5E3, prExtendedPictographic}, // E0.7 [1] (🗣️) speaking head + {0x1F5E4, 0x1F5E7, prExtendedPictographic}, // E0.0 [4] (🗤..🗧) THREE RAYS ABOVE..THREE RAYS RIGHT + {0x1F5E8, 0x1F5E8, prExtendedPictographic}, // E2.0 [1] (🗨️) left speech bubble + {0x1F5E9, 0x1F5EE, prExtendedPictographic}, // E0.0 [6] (🗩..🗮) RIGHT SPEECH BUBBLE..LEFT ANGER BUBBLE + {0x1F5EF, 0x1F5EF, prExtendedPictographic}, // E0.7 [1] (🗯️) right anger bubble + {0x1F5F0, 0x1F5F2, prExtendedPictographic}, // E0.0 [3] (🗰..🗲) MOOD BUBBLE..LIGHTNING MOOD + {0x1F5F3, 0x1F5F3, prExtendedPictographic}, // E0.7 [1] (🗳️) ballot box with ballot + {0x1F5F4, 0x1F5F9, prExtendedPictographic}, // E0.0 [6] (🗴..🗹) BALLOT SCRIPT X..BALLOT BOX WITH BOLD CHECK + {0x1F5FA, 0x1F5FA, prExtendedPictographic}, // E0.7 [1] (🗺️) world map + {0x1F5FB, 0x1F5FF, prExtendedPictographic}, // E0.6 [5] (🗻..🗿) mount fuji..moai + {0x1F600, 0x1F600, prExtendedPictographic}, // E1.0 [1] (😀) grinning face + {0x1F601, 0x1F606, prExtendedPictographic}, // E0.6 [6] (😁..😆) beaming face with smiling eyes..grinning squinting face + {0x1F607, 0x1F608, prExtendedPictographic}, // E1.0 [2] (😇..😈) smiling face with halo..smiling face with horns + {0x1F609, 0x1F60D, prExtendedPictographic}, // E0.6 [5] (😉..😍) winking face..smiling face with heart-eyes + {0x1F60E, 0x1F60E, prExtendedPictographic}, // E1.0 [1] (😎) smiling face with sunglasses + {0x1F60F, 0x1F60F, prExtendedPictographic}, // E0.6 [1] (😏) smirking face + {0x1F610, 0x1F610, prExtendedPictographic}, // E0.7 [1] (😐) neutral face + {0x1F611, 0x1F611, prExtendedPictographic}, // E1.0 [1] (😑) expressionless face + {0x1F612, 0x1F614, prExtendedPictographic}, // E0.6 [3] (😒..😔) unamused face..pensive face + {0x1F615, 0x1F615, prExtendedPictographic}, // E1.0 [1] (😕) confused face + {0x1F616, 0x1F616, prExtendedPictographic}, // E0.6 [1] (😖) confounded face + {0x1F617, 0x1F617, prExtendedPictographic}, // E1.0 [1] (😗) kissing face + {0x1F618, 0x1F618, prExtendedPictographic}, // E0.6 [1] (😘) face blowing a kiss + {0x1F619, 0x1F619, prExtendedPictographic}, // E1.0 [1] (😙) kissing face with smiling eyes + {0x1F61A, 0x1F61A, prExtendedPictographic}, // E0.6 [1] (😚) kissing face with closed eyes + {0x1F61B, 0x1F61B, prExtendedPictographic}, // E1.0 [1] (😛) face with tongue + {0x1F61C, 0x1F61E, prExtendedPictographic}, // E0.6 [3] (😜..😞) winking face with tongue..disappointed face + {0x1F61F, 0x1F61F, prExtendedPictographic}, // E1.0 [1] (😟) worried face + {0x1F620, 0x1F625, prExtendedPictographic}, // E0.6 [6] (😠..😥) angry face..sad but relieved face + {0x1F626, 0x1F627, prExtendedPictographic}, // E1.0 [2] (😦..😧) frowning face with open mouth..anguished face + {0x1F628, 0x1F62B, prExtendedPictographic}, // E0.6 [4] (😨..😫) fearful face..tired face + {0x1F62C, 0x1F62C, prExtendedPictographic}, // E1.0 [1] (😬) grimacing face + {0x1F62D, 0x1F62D, prExtendedPictographic}, // E0.6 [1] (😭) loudly crying face + {0x1F62E, 0x1F62F, prExtendedPictographic}, // E1.0 [2] (😮..😯) face with open mouth..hushed face + {0x1F630, 0x1F633, prExtendedPictographic}, // E0.6 [4] (😰..😳) anxious face with sweat..flushed face + {0x1F634, 0x1F634, prExtendedPictographic}, // E1.0 [1] (😴) sleeping face + {0x1F635, 0x1F635, prExtendedPictographic}, // E0.6 [1] (😵) face with crossed-out eyes + {0x1F636, 0x1F636, prExtendedPictographic}, // E1.0 [1] (😶) face without mouth + {0x1F637, 0x1F640, prExtendedPictographic}, // E0.6 [10] (😷..🙀) face with medical mask..weary cat + {0x1F641, 0x1F644, prExtendedPictographic}, // E1.0 [4] (🙁..🙄) slightly frowning face..face with rolling eyes + {0x1F645, 0x1F64F, prExtendedPictographic}, // E0.6 [11] (🙅..🙏) person gesturing NO..folded hands + {0x1F680, 0x1F680, prExtendedPictographic}, // E0.6 [1] (🚀) rocket + {0x1F681, 0x1F682, prExtendedPictographic}, // E1.0 [2] (🚁..🚂) helicopter..locomotive + {0x1F683, 0x1F685, prExtendedPictographic}, // E0.6 [3] (🚃..🚅) railway car..bullet train + {0x1F686, 0x1F686, prExtendedPictographic}, // E1.0 [1] (🚆) train + {0x1F687, 0x1F687, prExtendedPictographic}, // E0.6 [1] (🚇) metro + {0x1F688, 0x1F688, prExtendedPictographic}, // E1.0 [1] (🚈) light rail + {0x1F689, 0x1F689, prExtendedPictographic}, // E0.6 [1] (🚉) station + {0x1F68A, 0x1F68B, prExtendedPictographic}, // E1.0 [2] (🚊..🚋) tram..tram car + {0x1F68C, 0x1F68C, prExtendedPictographic}, // E0.6 [1] (🚌) bus + {0x1F68D, 0x1F68D, prExtendedPictographic}, // E0.7 [1] (🚍) oncoming bus + {0x1F68E, 0x1F68E, prExtendedPictographic}, // E1.0 [1] (🚎) trolleybus + {0x1F68F, 0x1F68F, prExtendedPictographic}, // E0.6 [1] (🚏) bus stop + {0x1F690, 0x1F690, prExtendedPictographic}, // E1.0 [1] (🚐) minibus + {0x1F691, 0x1F693, prExtendedPictographic}, // E0.6 [3] (🚑..🚓) ambulance..police car + {0x1F694, 0x1F694, prExtendedPictographic}, // E0.7 [1] (🚔) oncoming police car + {0x1F695, 0x1F695, prExtendedPictographic}, // E0.6 [1] (🚕) taxi + {0x1F696, 0x1F696, prExtendedPictographic}, // E1.0 [1] (🚖) oncoming taxi + {0x1F697, 0x1F697, prExtendedPictographic}, // E0.6 [1] (🚗) automobile + {0x1F698, 0x1F698, prExtendedPictographic}, // E0.7 [1] (🚘) oncoming automobile + {0x1F699, 0x1F69A, prExtendedPictographic}, // E0.6 [2] (🚙..🚚) sport utility vehicle..delivery truck + {0x1F69B, 0x1F6A1, prExtendedPictographic}, // E1.0 [7] (🚛..🚡) articulated lorry..aerial tramway + {0x1F6A2, 0x1F6A2, prExtendedPictographic}, // E0.6 [1] (🚢) ship + {0x1F6A3, 0x1F6A3, prExtendedPictographic}, // E1.0 [1] (🚣) person rowing boat + {0x1F6A4, 0x1F6A5, prExtendedPictographic}, // E0.6 [2] (🚤..🚥) speedboat..horizontal traffic light + {0x1F6A6, 0x1F6A6, prExtendedPictographic}, // E1.0 [1] (🚦) vertical traffic light + {0x1F6A7, 0x1F6AD, prExtendedPictographic}, // E0.6 [7] (🚧..🚭) construction..no smoking + {0x1F6AE, 0x1F6B1, prExtendedPictographic}, // E1.0 [4] (🚮..🚱) litter in bin sign..non-potable water + {0x1F6B2, 0x1F6B2, prExtendedPictographic}, // E0.6 [1] (🚲) bicycle + {0x1F6B3, 0x1F6B5, prExtendedPictographic}, // E1.0 [3] (🚳..🚵) no bicycles..person mountain biking + {0x1F6B6, 0x1F6B6, prExtendedPictographic}, // E0.6 [1] (🚶) person walking + {0x1F6B7, 0x1F6B8, prExtendedPictographic}, // E1.0 [2] (🚷..🚸) no pedestrians..children crossing + {0x1F6B9, 0x1F6BE, prExtendedPictographic}, // E0.6 [6] (🚹..🚾) men’s room..water closet + {0x1F6BF, 0x1F6BF, prExtendedPictographic}, // E1.0 [1] (🚿) shower + {0x1F6C0, 0x1F6C0, prExtendedPictographic}, // E0.6 [1] (🛀) person taking bath + {0x1F6C1, 0x1F6C5, prExtendedPictographic}, // E1.0 [5] (🛁..🛅) bathtub..left luggage + {0x1F6C6, 0x1F6CA, prExtendedPictographic}, // E0.0 [5] (🛆..🛊) TRIANGLE WITH ROUNDED CORNERS..GIRLS SYMBOL + {0x1F6CB, 0x1F6CB, prExtendedPictographic}, // E0.7 [1] (🛋️) couch and lamp + {0x1F6CC, 0x1F6CC, prExtendedPictographic}, // E1.0 [1] (🛌) person in bed + {0x1F6CD, 0x1F6CF, prExtendedPictographic}, // E0.7 [3] (🛍️..🛏️) shopping bags..bed + {0x1F6D0, 0x1F6D0, prExtendedPictographic}, // E1.0 [1] (🛐) place of worship + {0x1F6D1, 0x1F6D2, prExtendedPictographic}, // E3.0 [2] (🛑..🛒) stop sign..shopping cart + {0x1F6D3, 0x1F6D4, prExtendedPictographic}, // E0.0 [2] (🛓..🛔) STUPA..PAGODA + {0x1F6D5, 0x1F6D5, prExtendedPictographic}, // E12.0 [1] (🛕) hindu temple + {0x1F6D6, 0x1F6D7, prExtendedPictographic}, // E13.0 [2] (🛖..🛗) hut..elevator + {0x1F6D8, 0x1F6DB, prExtendedPictographic}, // E0.0 [4] (🛘..🛛) .. + {0x1F6DC, 0x1F6DC, prExtendedPictographic}, // E15.0 [1] (🛜) wireless + {0x1F6DD, 0x1F6DF, prExtendedPictographic}, // E14.0 [3] (🛝..🛟) playground slide..ring buoy + {0x1F6E0, 0x1F6E5, prExtendedPictographic}, // E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat + {0x1F6E6, 0x1F6E8, prExtendedPictographic}, // E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE + {0x1F6E9, 0x1F6E9, prExtendedPictographic}, // E0.7 [1] (🛩️) small airplane + {0x1F6EA, 0x1F6EA, prExtendedPictographic}, // E0.0 [1] (🛪) NORTHEAST-POINTING AIRPLANE + {0x1F6EB, 0x1F6EC, prExtendedPictographic}, // E1.0 [2] (🛫..🛬) airplane departure..airplane arrival + {0x1F6ED, 0x1F6EF, prExtendedPictographic}, // E0.0 [3] (🛭..🛯) .. + {0x1F6F0, 0x1F6F0, prExtendedPictographic}, // E0.7 [1] (🛰️) satellite + {0x1F6F1, 0x1F6F2, prExtendedPictographic}, // E0.0 [2] (🛱..🛲) ONCOMING FIRE ENGINE..DIESEL LOCOMOTIVE + {0x1F6F3, 0x1F6F3, prExtendedPictographic}, // E0.7 [1] (🛳️) passenger ship + {0x1F6F4, 0x1F6F6, prExtendedPictographic}, // E3.0 [3] (🛴..🛶) kick scooter..canoe + {0x1F6F7, 0x1F6F8, prExtendedPictographic}, // E5.0 [2] (🛷..🛸) sled..flying saucer + {0x1F6F9, 0x1F6F9, prExtendedPictographic}, // E11.0 [1] (🛹) skateboard + {0x1F6FA, 0x1F6FA, prExtendedPictographic}, // E12.0 [1] (🛺) auto rickshaw + {0x1F6FB, 0x1F6FC, prExtendedPictographic}, // E13.0 [2] (🛻..🛼) pickup truck..roller skate + {0x1F6FD, 0x1F6FF, prExtendedPictographic}, // E0.0 [3] (🛽..🛿) .. + {0x1F774, 0x1F77F, prExtendedPictographic}, // E0.0 [12] (🝴..🝿) LOT OF FORTUNE..ORCUS + {0x1F7D5, 0x1F7DF, prExtendedPictographic}, // E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE.. + {0x1F7E0, 0x1F7EB, prExtendedPictographic}, // E12.0 [12] (🟠..🟫) orange circle..brown square + {0x1F7EC, 0x1F7EF, prExtendedPictographic}, // E0.0 [4] (🟬..🟯) .. + {0x1F7F0, 0x1F7F0, prExtendedPictographic}, // E14.0 [1] (🟰) heavy equals sign + {0x1F7F1, 0x1F7FF, prExtendedPictographic}, // E0.0 [15] (🟱..🟿) .. + {0x1F80C, 0x1F80F, prExtendedPictographic}, // E0.0 [4] (🠌..🠏) .. + {0x1F848, 0x1F84F, prExtendedPictographic}, // E0.0 [8] (🡈..🡏) .. + {0x1F85A, 0x1F85F, prExtendedPictographic}, // E0.0 [6] (🡚..🡟) .. + {0x1F888, 0x1F88F, prExtendedPictographic}, // E0.0 [8] (🢈..🢏) .. + {0x1F8AE, 0x1F8FF, prExtendedPictographic}, // E0.0 [82] (🢮..🣿) .. + {0x1F90C, 0x1F90C, prExtendedPictographic}, // E13.0 [1] (🤌) pinched fingers + {0x1F90D, 0x1F90F, prExtendedPictographic}, // E12.0 [3] (🤍..🤏) white heart..pinching hand + {0x1F910, 0x1F918, prExtendedPictographic}, // E1.0 [9] (🤐..🤘) zipper-mouth face..sign of the horns + {0x1F919, 0x1F91E, prExtendedPictographic}, // E3.0 [6] (🤙..🤞) call me hand..crossed fingers + {0x1F91F, 0x1F91F, prExtendedPictographic}, // E5.0 [1] (🤟) love-you gesture + {0x1F920, 0x1F927, prExtendedPictographic}, // E3.0 [8] (🤠..🤧) cowboy hat face..sneezing face + {0x1F928, 0x1F92F, prExtendedPictographic}, // E5.0 [8] (🤨..🤯) face with raised eyebrow..exploding head + {0x1F930, 0x1F930, prExtendedPictographic}, // E3.0 [1] (🤰) pregnant woman + {0x1F931, 0x1F932, prExtendedPictographic}, // E5.0 [2] (🤱..🤲) breast-feeding..palms up together + {0x1F933, 0x1F93A, prExtendedPictographic}, // E3.0 [8] (🤳..🤺) selfie..person fencing + {0x1F93C, 0x1F93E, prExtendedPictographic}, // E3.0 [3] (🤼..🤾) people wrestling..person playing handball + {0x1F93F, 0x1F93F, prExtendedPictographic}, // E12.0 [1] (🤿) diving mask + {0x1F940, 0x1F945, prExtendedPictographic}, // E3.0 [6] (🥀..🥅) wilted flower..goal net + {0x1F947, 0x1F94B, prExtendedPictographic}, // E3.0 [5] (🥇..🥋) 1st place medal..martial arts uniform + {0x1F94C, 0x1F94C, prExtendedPictographic}, // E5.0 [1] (🥌) curling stone + {0x1F94D, 0x1F94F, prExtendedPictographic}, // E11.0 [3] (🥍..🥏) lacrosse..flying disc + {0x1F950, 0x1F95E, prExtendedPictographic}, // E3.0 [15] (🥐..🥞) croissant..pancakes + {0x1F95F, 0x1F96B, prExtendedPictographic}, // E5.0 [13] (🥟..🥫) dumpling..canned food + {0x1F96C, 0x1F970, prExtendedPictographic}, // E11.0 [5] (🥬..🥰) leafy green..smiling face with hearts + {0x1F971, 0x1F971, prExtendedPictographic}, // E12.0 [1] (🥱) yawning face + {0x1F972, 0x1F972, prExtendedPictographic}, // E13.0 [1] (🥲) smiling face with tear + {0x1F973, 0x1F976, prExtendedPictographic}, // E11.0 [4] (🥳..🥶) partying face..cold face + {0x1F977, 0x1F978, prExtendedPictographic}, // E13.0 [2] (🥷..🥸) ninja..disguised face + {0x1F979, 0x1F979, prExtendedPictographic}, // E14.0 [1] (🥹) face holding back tears + {0x1F97A, 0x1F97A, prExtendedPictographic}, // E11.0 [1] (🥺) pleading face + {0x1F97B, 0x1F97B, prExtendedPictographic}, // E12.0 [1] (🥻) sari + {0x1F97C, 0x1F97F, prExtendedPictographic}, // E11.0 [4] (🥼..🥿) lab coat..flat shoe + {0x1F980, 0x1F984, prExtendedPictographic}, // E1.0 [5] (🦀..🦄) crab..unicorn + {0x1F985, 0x1F991, prExtendedPictographic}, // E3.0 [13] (🦅..🦑) eagle..squid + {0x1F992, 0x1F997, prExtendedPictographic}, // E5.0 [6] (🦒..🦗) giraffe..cricket + {0x1F998, 0x1F9A2, prExtendedPictographic}, // E11.0 [11] (🦘..🦢) kangaroo..swan + {0x1F9A3, 0x1F9A4, prExtendedPictographic}, // E13.0 [2] (🦣..🦤) mammoth..dodo + {0x1F9A5, 0x1F9AA, prExtendedPictographic}, // E12.0 [6] (🦥..🦪) sloth..oyster + {0x1F9AB, 0x1F9AD, prExtendedPictographic}, // E13.0 [3] (🦫..🦭) beaver..seal + {0x1F9AE, 0x1F9AF, prExtendedPictographic}, // E12.0 [2] (🦮..🦯) guide dog..white cane + {0x1F9B0, 0x1F9B9, prExtendedPictographic}, // E11.0 [10] (🦰..🦹) red hair..supervillain + {0x1F9BA, 0x1F9BF, prExtendedPictographic}, // E12.0 [6] (🦺..🦿) safety vest..mechanical leg + {0x1F9C0, 0x1F9C0, prExtendedPictographic}, // E1.0 [1] (🧀) cheese wedge + {0x1F9C1, 0x1F9C2, prExtendedPictographic}, // E11.0 [2] (🧁..🧂) cupcake..salt + {0x1F9C3, 0x1F9CA, prExtendedPictographic}, // E12.0 [8] (🧃..🧊) beverage box..ice + {0x1F9CB, 0x1F9CB, prExtendedPictographic}, // E13.0 [1] (🧋) bubble tea + {0x1F9CC, 0x1F9CC, prExtendedPictographic}, // E14.0 [1] (🧌) troll + {0x1F9CD, 0x1F9CF, prExtendedPictographic}, // E12.0 [3] (🧍..🧏) person standing..deaf person + {0x1F9D0, 0x1F9E6, prExtendedPictographic}, // E5.0 [23] (🧐..🧦) face with monocle..socks + {0x1F9E7, 0x1F9FF, prExtendedPictographic}, // E11.0 [25] (🧧..🧿) red envelope..nazar amulet + {0x1FA00, 0x1FA6F, prExtendedPictographic}, // E0.0 [112] (🨀..🩯) NEUTRAL CHESS KING.. + {0x1FA70, 0x1FA73, prExtendedPictographic}, // E12.0 [4] (🩰..🩳) ballet shoes..shorts + {0x1FA74, 0x1FA74, prExtendedPictographic}, // E13.0 [1] (🩴) thong sandal + {0x1FA75, 0x1FA77, prExtendedPictographic}, // E15.0 [3] (🩵..🩷) light blue heart..pink heart + {0x1FA78, 0x1FA7A, prExtendedPictographic}, // E12.0 [3] (🩸..🩺) drop of blood..stethoscope + {0x1FA7B, 0x1FA7C, prExtendedPictographic}, // E14.0 [2] (🩻..🩼) x-ray..crutch + {0x1FA7D, 0x1FA7F, prExtendedPictographic}, // E0.0 [3] (🩽..🩿) .. + {0x1FA80, 0x1FA82, prExtendedPictographic}, // E12.0 [3] (🪀..🪂) yo-yo..parachute + {0x1FA83, 0x1FA86, prExtendedPictographic}, // E13.0 [4] (🪃..🪆) boomerang..nesting dolls + {0x1FA87, 0x1FA88, prExtendedPictographic}, // E15.0 [2] (🪇..🪈) maracas..flute + {0x1FA89, 0x1FA8F, prExtendedPictographic}, // E0.0 [7] (🪉..🪏) .. + {0x1FA90, 0x1FA95, prExtendedPictographic}, // E12.0 [6] (🪐..🪕) ringed planet..banjo + {0x1FA96, 0x1FAA8, prExtendedPictographic}, // E13.0 [19] (🪖..🪨) military helmet..rock + {0x1FAA9, 0x1FAAC, prExtendedPictographic}, // E14.0 [4] (🪩..🪬) mirror ball..hamsa + {0x1FAAD, 0x1FAAF, prExtendedPictographic}, // E15.0 [3] (🪭..🪯) folding hand fan..khanda + {0x1FAB0, 0x1FAB6, prExtendedPictographic}, // E13.0 [7] (🪰..🪶) fly..feather + {0x1FAB7, 0x1FABA, prExtendedPictographic}, // E14.0 [4] (🪷..🪺) lotus..nest with eggs + {0x1FABB, 0x1FABD, prExtendedPictographic}, // E15.0 [3] (🪻..🪽) hyacinth..wing + {0x1FABE, 0x1FABE, prExtendedPictographic}, // E0.0 [1] (🪾) + {0x1FABF, 0x1FABF, prExtendedPictographic}, // E15.0 [1] (🪿) goose + {0x1FAC0, 0x1FAC2, prExtendedPictographic}, // E13.0 [3] (🫀..🫂) anatomical heart..people hugging + {0x1FAC3, 0x1FAC5, prExtendedPictographic}, // E14.0 [3] (🫃..🫅) pregnant man..person with crown + {0x1FAC6, 0x1FACD, prExtendedPictographic}, // E0.0 [8] (🫆..🫍) .. + {0x1FACE, 0x1FACF, prExtendedPictographic}, // E15.0 [2] (🫎..🫏) moose..donkey + {0x1FAD0, 0x1FAD6, prExtendedPictographic}, // E13.0 [7] (🫐..🫖) blueberries..teapot + {0x1FAD7, 0x1FAD9, prExtendedPictographic}, // E14.0 [3] (🫗..🫙) pouring liquid..jar + {0x1FADA, 0x1FADB, prExtendedPictographic}, // E15.0 [2] (🫚..🫛) ginger root..pea pod + {0x1FADC, 0x1FADF, prExtendedPictographic}, // E0.0 [4] (🫜..🫟) .. + {0x1FAE0, 0x1FAE7, prExtendedPictographic}, // E14.0 [8] (🫠..🫧) melting face..bubbles + {0x1FAE8, 0x1FAE8, prExtendedPictographic}, // E15.0 [1] (🫨) shaking face + {0x1FAE9, 0x1FAEF, prExtendedPictographic}, // E0.0 [7] (🫩..🫯) .. + {0x1FAF0, 0x1FAF6, prExtendedPictographic}, // E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands + {0x1FAF7, 0x1FAF8, prExtendedPictographic}, // E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + {0x1FAF9, 0x1FAFF, prExtendedPictographic}, // E0.0 [7] (🫹..🫿) .. + {0x1FBF0, 0x1FBF9, prNumeric}, // Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE + {0x1FC00, 0x1FFFD, prExtendedPictographic}, // E0.0[1022] (🰀..🿽) .. + {0xE0001, 0xE0001, prFormat}, // Cf LANGUAGE TAG + {0xE0020, 0xE007F, prExtend}, // Cf [96] TAG SPACE..CANCEL TAG + {0xE0100, 0xE01EF, prExtend}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 +} diff --git a/vendor/github.com/rivo/uniseg/wordrules.go b/vendor/github.com/rivo/uniseg/wordrules.go new file mode 100644 index 000000000..57a8c6831 --- /dev/null +++ b/vendor/github.com/rivo/uniseg/wordrules.go @@ -0,0 +1,282 @@ +package uniseg + +import "unicode/utf8" + +// The states of the word break parser. +const ( + wbAny = iota + wbCR + wbLF + wbNewline + wbWSegSpace + wbHebrewLetter + wbALetter + wbWB7 + wbWB7c + wbNumeric + wbWB11 + wbKatakana + wbExtendNumLet + wbOddRI + wbEvenRI + wbZWJBit = 16 // This bit is set for any states followed by at least one zero-width joiner (see WB4 and WB3c). +) + +// wbTransitions implements the word break parser's state transitions. It's +// anologous to [grTransitions], see comments there for details. +// +// Unicode version 15.0.0. +func wbTransitions(state, prop int) (newState int, wordBreak bool, rule int) { + switch uint64(state) | uint64(prop)<<32 { + // WB3b. + case wbAny | prNewline<<32: + return wbNewline, true, 32 + case wbAny | prCR<<32: + return wbCR, true, 32 + case wbAny | prLF<<32: + return wbLF, true, 32 + + // WB3a. + case wbNewline | prAny<<32: + return wbAny, true, 31 + case wbCR | prAny<<32: + return wbAny, true, 31 + case wbLF | prAny<<32: + return wbAny, true, 31 + + // WB3. + case wbCR | prLF<<32: + return wbLF, false, 30 + + // WB3d. + case wbAny | prWSegSpace<<32: + return wbWSegSpace, true, 9990 + case wbWSegSpace | prWSegSpace<<32: + return wbWSegSpace, false, 34 + + // WB5. + case wbAny | prALetter<<32: + return wbALetter, true, 9990 + case wbAny | prHebrewLetter<<32: + return wbHebrewLetter, true, 9990 + case wbALetter | prALetter<<32: + return wbALetter, false, 50 + case wbALetter | prHebrewLetter<<32: + return wbHebrewLetter, false, 50 + case wbHebrewLetter | prALetter<<32: + return wbALetter, false, 50 + case wbHebrewLetter | prHebrewLetter<<32: + return wbHebrewLetter, false, 50 + + // WB7. Transitions to wbWB7 handled by transitionWordBreakState(). + case wbWB7 | prALetter<<32: + return wbALetter, false, 70 + case wbWB7 | prHebrewLetter<<32: + return wbHebrewLetter, false, 70 + + // WB7a. + case wbHebrewLetter | prSingleQuote<<32: + return wbAny, false, 71 + + // WB7c. Transitions to wbWB7c handled by transitionWordBreakState(). + case wbWB7c | prHebrewLetter<<32: + return wbHebrewLetter, false, 73 + + // WB8. + case wbAny | prNumeric<<32: + return wbNumeric, true, 9990 + case wbNumeric | prNumeric<<32: + return wbNumeric, false, 80 + + // WB9. + case wbALetter | prNumeric<<32: + return wbNumeric, false, 90 + case wbHebrewLetter | prNumeric<<32: + return wbNumeric, false, 90 + + // WB10. + case wbNumeric | prALetter<<32: + return wbALetter, false, 100 + case wbNumeric | prHebrewLetter<<32: + return wbHebrewLetter, false, 100 + + // WB11. Transitions to wbWB11 handled by transitionWordBreakState(). + case wbWB11 | prNumeric<<32: + return wbNumeric, false, 110 + + // WB13. + case wbAny | prKatakana<<32: + return wbKatakana, true, 9990 + case wbKatakana | prKatakana<<32: + return wbKatakana, false, 130 + + // WB13a. + case wbAny | prExtendNumLet<<32: + return wbExtendNumLet, true, 9990 + case wbALetter | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbHebrewLetter | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbNumeric | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbKatakana | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbExtendNumLet | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + + // WB13b. + case wbExtendNumLet | prALetter<<32: + return wbALetter, false, 132 + case wbExtendNumLet | prHebrewLetter<<32: + return wbHebrewLetter, false, 132 + case wbExtendNumLet | prNumeric<<32: + return wbNumeric, false, 132 + case wbExtendNumLet | prKatakana<<32: + return wbKatakana, false, 132 + + default: + return -1, false, -1 + } +} + +// transitionWordBreakState determines the new state of the word break parser +// given the current state and the next code point. It also returns whether a +// word boundary was detected. If more than one code point is needed to +// determine the new state, the byte slice or the string starting after rune "r" +// can be used (whichever is not nil or empty) for further lookups. +func transitionWordBreakState(state int, r rune, b []byte, str string) (newState int, wordBreak bool) { + // Determine the property of the next character. + nextProperty := property(workBreakCodePoints, r) + + // "Replacing Ignore Rules". + if nextProperty == prZWJ { + // WB4 (for zero-width joiners). + if state == wbNewline || state == wbCR || state == wbLF { + return wbAny | wbZWJBit, true // Make sure we don't apply WB4 to WB3a. + } + if state < 0 { + return wbAny | wbZWJBit, false + } + return state | wbZWJBit, false + } else if nextProperty == prExtend || nextProperty == prFormat { + // WB4 (for Extend and Format). + if state == wbNewline || state == wbCR || state == wbLF { + return wbAny, true // Make sure we don't apply WB4 to WB3a. + } + if state == wbWSegSpace || state == wbAny|wbZWJBit { + return wbAny, false // We don't break but this is also not WB3d or WB3c. + } + if state < 0 { + return wbAny, false + } + return state, false + } else if nextProperty == prExtendedPictographic && state >= 0 && state&wbZWJBit != 0 { + // WB3c. + return wbAny, false + } + if state >= 0 { + state = state &^ wbZWJBit + } + + // Find the applicable transition in the table. + var rule int + newState, wordBreak, rule = wbTransitions(state, nextProperty) + if newState < 0 { + // No specific transition found. Try the less specific ones. + anyPropState, anyPropWordBreak, anyPropRule := wbTransitions(state, prAny) + anyStateState, anyStateWordBreak, anyStateRule := wbTransitions(wbAny, nextProperty) + if anyPropState >= 0 && anyStateState >= 0 { + // Both apply. We'll use a mix (see comments for grTransitions). + newState, wordBreak, rule = anyStateState, anyStateWordBreak, anyStateRule + if anyPropRule < anyStateRule { + wordBreak, rule = anyPropWordBreak, anyPropRule + } + } else if anyPropState >= 0 { + // We only have a specific state. + newState, wordBreak, rule = anyPropState, anyPropWordBreak, anyPropRule + // This branch will probably never be reached because okAnyState will + // always be true given the current transition map. But we keep it here + // for future modifications to the transition map where this may not be + // true anymore. + } else if anyStateState >= 0 { + // We only have a specific property. + newState, wordBreak, rule = anyStateState, anyStateWordBreak, anyStateRule + } else { + // No known transition. WB999: Any ÷ Any. + newState, wordBreak, rule = wbAny, true, 9990 + } + } + + // For those rules that need to look up runes further in the string, we + // determine the property after nextProperty, skipping over Format, Extend, + // and ZWJ (according to WB4). It's -1 if not needed, if such a rune cannot + // be determined (because the text ends or the rune is faulty). + farProperty := -1 + if rule > 60 && + (state == wbALetter || state == wbHebrewLetter || state == wbNumeric) && + (nextProperty == prMidLetter || nextProperty == prMidNumLet || nextProperty == prSingleQuote || // WB6. + nextProperty == prDoubleQuote || // WB7b. + nextProperty == prMidNum) { // WB12. + for { + var ( + r rune + length int + ) + if b != nil { // Byte slice version. + r, length = utf8.DecodeRune(b) + b = b[length:] + } else { // String version. + r, length = utf8.DecodeRuneInString(str) + str = str[length:] + } + if r == utf8.RuneError { + break + } + prop := property(workBreakCodePoints, r) + if prop == prExtend || prop == prFormat || prop == prZWJ { + continue + } + farProperty = prop + break + } + } + + // WB6. + if rule > 60 && + (state == wbALetter || state == wbHebrewLetter) && + (nextProperty == prMidLetter || nextProperty == prMidNumLet || nextProperty == prSingleQuote) && + (farProperty == prALetter || farProperty == prHebrewLetter) { + return wbWB7, false + } + + // WB7b. + if rule > 72 && + state == wbHebrewLetter && + nextProperty == prDoubleQuote && + farProperty == prHebrewLetter { + return wbWB7c, false + } + + // WB12. + if rule > 120 && + state == wbNumeric && + (nextProperty == prMidNum || nextProperty == prMidNumLet || nextProperty == prSingleQuote) && + farProperty == prNumeric { + return wbWB11, false + } + + // WB15 and WB16. + if newState == wbAny && nextProperty == prRegionalIndicator { + if state != wbOddRI && state != wbEvenRI { // Includes state == -1. + // Transition into the first RI. + return wbOddRI, true + } + if state == wbOddRI { + // Don't break pairs of Regional Indicators. + return wbEvenRI, false + } + return wbOddRI, true // We can break after a pair. + } + + return +} diff --git a/vendor/github.com/robertkrimen/otto/.clog.toml b/vendor/github.com/robertkrimen/otto/.clog.toml new file mode 100644 index 000000000..74e370292 --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/.clog.toml @@ -0,0 +1,13 @@ +[clog] +repository = "https://github.com/robertkrimen/otto" +subtitle = "Release Notes" + +[sections] +"Refactors" = ["refactor"] +"Chores" = ["chore"] +"Continuous Integration" = ["ci"] +"Improvements" = ["imp", "improvement"] +"Features" = ["feat", "feature"] +"Legacy" = ["legacy"] +"QA" = ["qa", "test", "tests"] +"Documentation" = ["doc", "docs"] diff --git a/vendor/github.com/robertkrimen/otto/.gitignore b/vendor/github.com/robertkrimen/otto/.gitignore index 8c2a16949..ea050b8b9 100644 --- a/vendor/github.com/robertkrimen/otto/.gitignore +++ b/vendor/github.com/robertkrimen/otto/.gitignore @@ -1,5 +1,10 @@ -/.test -/otto/otto -/otto/otto-* -/test/test-*.js -/test/tester +.test +otto/otto +otto/otto-* +tools/tester/testdata/ +tools/tester/tester +tools/gen-jscore/gen-jscore +tools/gen-tokens/gen-tokens +.idea +dist/ +.vscode/ diff --git a/vendor/github.com/robertkrimen/otto/.golangci.yml b/vendor/github.com/robertkrimen/otto/.golangci.yml new file mode 100644 index 000000000..16a53009b --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/.golangci.yml @@ -0,0 +1,73 @@ +run: + timeout: 6m + +linters-settings: + govet: + settings: + shadow: + strict: true + enable-all: true + goconst: + min-len: 2 + min-occurrences: 4 + revive: + enable-all-rules: false + rules: + - name: var-naming + disabled: true + gosec: + excludes: + - G115 # Too many false positives. + +linters: + enable-all: true + disable: + - dupl + - lll + - gochecknoglobals + - gochecknoinits + - funlen + - godox + - err113 + - wsl + - nlreturn + - gomnd + - mnd + - paralleltest + - wrapcheck + - testpackage + - gocognit + - nestif + - exhaustive + - forcetypeassert + - gocyclo + - cyclop + - varnamelen + - maintidx + - ireturn + - exhaustruct + - dupword + # Just causes noise + - depguard + # Deprecated + - execinquery + # Not needed in go 1.22+ + - exportloopref + +issues: + exclude-use-default: false + max-same-issues: 0 + exclude: + - Deferring unsafe method "Close" on type "io\.ReadCloser" + exclude-dirs: + - terst + exclude-files: + - dbg/dbg.go + - token/token_const.go + exclude-rules: + # Field alignment in tests isn't a performance issue. + - text: fieldalignment + path: _test\.go + - text: Error return value of `fmt\.Fprint.*` is not checked + path: tools/tester/main.go + diff --git a/vendor/github.com/robertkrimen/otto/.goreleaser.yaml b/vendor/github.com/robertkrimen/otto/.goreleaser.yaml new file mode 100644 index 000000000..56f72d9db --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/.goreleaser.yaml @@ -0,0 +1,70 @@ +# When adding options check the documentation at https://goreleaser.com +before: + hooks: + - go mod tidy +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + main: ./otto + id: otto + binary: otto +universal_binaries: + - replace: true + id: otto +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}-next" +archives: + - id: otto + name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" +release: + header: | + + ### {{.Tag}} Release Notes ({{.Date}}) + footer: | + [Full Changelog](https://{{ .ModulePath }}/compare/{{ .PreviousTag }}...{{ .Tag }}) +changelog: + use: github + sort: asc + filters: + exclude: + - Merge pull request + - Merge remote-tracking branch + - Merge branch + + # Group commits messages by given regex and title. + # Order value defines the order of the groups. + # Proving no regex means all commits will be grouped under the default group. + # Groups are disabled when using github-native, as it already groups things by itself. + # Matches are performed against strings of the form: " ". + # Regex use RE2 syntax as defined here: https://github.com/google/re2/wiki/Syntax. + # + # Default is no groups. + groups: + - title: Features + regexp: '^.*?(feat|feature)(\([[:word:]]+\))??!?:.+$' + order: 0 + - title: 'Bug fixes' + regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$' + order: 1 + - title: 'Chores' + regexp: '^.*?chore(\([[:word:]]+\))??!?:.+$' + order: 2 + - title: 'Quality' + regexp: '^.*?(qa|test|tests)(\([[:word:]]+\))??!?:.+$' + order: 3 + - title: 'Documentation' + regexp: '^.*?(doc|docs)(\([[:word:]]+\))??!?:.+$' + order: 4 + - title: 'Continuous Integration' + regexp: '^.*?ci(\([[:word:]]+\))??!?:.+$' + order: 5 + - title: Other + order: 999 diff --git a/vendor/github.com/robertkrimen/otto/Makefile b/vendor/github.com/robertkrimen/otto/Makefile deleted file mode 100644 index 9868db3ca..000000000 --- a/vendor/github.com/robertkrimen/otto/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -.PHONY: test test-race test-release release release-check test-262 -.PHONY: parser -.PHONY: otto assets underscore - -TESTS := \ - ~ - -TEST := -v --run -TEST := -v -TEST := -v --run Test\($(subst $(eval) ,\|,$(TESTS))\) -TEST := . - -test: parser inline.go - go test -i - go test $(TEST) - @echo PASS - -parser: - $(MAKE) -C parser - -inline.go: inline.pl - ./$< > $@ - -################# -# release, test # -################# - -release: test-race test-release - for package in . parser token ast file underscore registry; do (cd $$package && godocdown --signature > README.markdown); done - @echo \*\*\* make release-check - @echo PASS - -release-check: .test - $(MAKE) -C test build test - $(MAKE) -C .test/test262 build test - @echo PASS - -test-262: .test - $(MAKE) -C .test/test262 build test - @echo PASS - -test-release: - go test -i - go test - -test-race: - go test -race -i - go test -race - -################################# -# otto, assets, underscore, ... # -################################# - -otto: - $(MAKE) -C otto - -assets: - mkdir -p .assets - for file in underscore/test/*.js; do tr "\`" "_" < $$file > .assets/`basename $$file`; done - -underscore: - $(MAKE) -C $@ - diff --git a/vendor/github.com/robertkrimen/otto/README.markdown b/vendor/github.com/robertkrimen/otto/README.md similarity index 77% rename from vendor/github.com/robertkrimen/otto/README.markdown rename to vendor/github.com/robertkrimen/otto/README.md index 40584d32b..fa21eb9a7 100644 --- a/vendor/github.com/robertkrimen/otto/README.markdown +++ b/vendor/github.com/robertkrimen/otto/README.md @@ -1,12 +1,12 @@ # otto --- -```go -import "github.com/robertkrimen/otto" -``` + +[![GoDoc Reference](https://pkg.go.dev/badge/github.com/robertkrimen/otto.svg)](https://pkg.go.dev/github.com/robertkrimen/otto) + +## Basic Usage Package otto is a JavaScript parser and interpreter written natively in Go. -http://godoc.org/github.com/robertkrimen/otto +To use import it with the following: ```go import ( @@ -29,7 +29,7 @@ Get a value out of the VM ```go if value, err := vm.Get("abc"); err == nil { if value_int, err := value.ToInteger(); err == nil { - fmt.Printf("", value_int, err) + fmt.Printf("", value_int, err) } } ``` @@ -104,12 +104,12 @@ result, _ = vm.Run(` `) ``` -### Parser +## Parser A separate parser is available in the parser package if you're just interested in building an AST. -http://godoc.org/github.com/robertkrimen/otto/parser +[![GoDoc Reference](https://pkg.go.dev/badge/github.com/robertkrimen/otto/parser.svg)](https://pkg.go.dev/github.com/robertkrimen/otto/parser) Parse and return an AST @@ -133,18 +133,22 @@ src := ` program, err := parser.ParseFile(nil, filename, src, 0) ``` -### otto +## Setup -You can run (Go) JavaScript from the commandline with: -http://github.com/robertkrimen/otto/tree/master/otto +You can run (Go) JavaScript from the command line with +[otto](http://github.com/robertkrimen/otto/tree/master/otto). - $ go get -v github.com/robertkrimen/otto/otto +```shell +go install github.com/robertkrimen/otto/otto@latest +``` Run JavaScript by entering some source on stdin or by giving otto a filename: - $ otto example.js +```shell +otto example.js +``` -### underscore +## Underscore Optionally include the JavaScript utility-belt library, underscore, with this import: @@ -158,41 +162,39 @@ import ( // Now every otto runtime will come loaded with underscore ``` -For more information: http://github.com/robertkrimen/otto/tree/master/underscore - +For more information: [underscore](http://github.com/robertkrimen/otto/tree/master/underscore) -### Caveat Emptor +## Caveat Emptor The following are some limitations with otto: - * "use strict" will parse, but does nothing. - * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. - * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. - +* `use strict` will parse, but does nothing. +* The regular expression engine ([re2/regexp](https://pkg.go.dev/regexp)) is not fully compatible with the ECMA5 specification. +* Otto targets ES5. Some ES6 features e.g. Typed Arrays are not supported, PR's to add functionality are always welcome. ### Regular Expression Incompatibility Go translates JavaScript-style regular expressions into something that is "regexp" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires -backtracking for some patterns, and backtracking is not supported by the -standard Go engine: https://code.google.com/p/re2/wiki/Syntax +backtracking for some patterns, and backtracking is not supported by Go +[re2](https://github.com/google/re2/wiki/syntax). Therefore, the following syntax is incompatible: - (?=) // Lookahead (positive), currently a parsing error - (?!) // Lookahead (backhead), currently a parsing error - \1 // Backreference (\1, \2, \3, ...), currently a parsing error +```plaintext +(?=) // Lookahead (positive), currently a parsing error +(?!) // Lookahead (backhead), currently a parsing error +\1 // Backreference (\1, \2, \3, ...), currently a parsing error +``` -A brief discussion of these limitations: "Regexp (?!re)" -https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E +A brief discussion of these limitations: [Regexp (?!re)](https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E) -More information about re2: https://code.google.com/p/re2/ +More information [about re2](https://github.com/google/re2) -In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r -]. The JavaScript definition, on the other hand, also includes \v, Unicode +In addition to the above, re2 (Go) has a different definition for `\s`: `[\t\n\f\r +]`. The JavaScript definition, on the other hand, also includes `\v`, Unicode "Separator, Space", etc. - ### Halting Problem If you want to stop long running executions (like third-party code), you can use @@ -236,36 +238,38 @@ func runUnsafe(unsafe string) { vm := otto.New() vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking + watchdogCleanup := make(chan struct{}) + defer close(watchdogCleanup) go func() { - time.Sleep(2 * time.Second) // Stop after two seconds - vm.Interrupt <- func() { - panic(halt) + select { + case <-time.After(2 * time.Second): // Stop after two seconds + vm.Interrupt <- func() { + panic(halt) + } + case <-watchdogCleanup: } + close(vm.Interrupt) }() vm.Run(unsafe) // Here be dragons (risky code) } ``` -Where is setTimeout/setInterval? +Where is `setTimeout` / `setInterval`? -These timing functions are not actually part of the ECMA-262 specification. +These timing functions are not actually part of the [ECMA-262 specification](https://ecma-international.org/publications-and-standards/standards/ecma-262/). Typically, they belong to the `window` object (in the browser). It would not be difficult to provide something like these via Go, but you probably want to wrap otto in an event loop in that case. -For an example of how this could be done in Go with otto, see natto: - -http://github.com/robertkrimen/natto +For an example of how this could be done in Go with otto, see [natto](http://github.com/robertkrimen/natto). Here is some more discussion of the issue: -* http://book.mixu.net/node/ch2.html - -* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 - -* http://aaroncrane.co.uk/2009/02/perl_safe_signals/ +* [What is Node.js?](http://book.mixu.net/node/ch2.html) +* [Reentrancy (computing)](http://en.wikipedia.org/wiki/Reentrancy_%28computing%29) +* [Perl Safe Signals](https://metacpan.org/pod/Perl::Unsafe::Signals) ## Usage @@ -273,93 +277,103 @@ Here is some more discussion of the issue: var ErrVersion = errors.New("version mismatch") ``` -#### type Error +### type Error ```go -type Error struct { -} +type Error struct {} ``` -An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. +An Error represents a runtime error, e.g. a `TypeError`, a `ReferenceError`, etc. -#### func (Error) Error +### func (Error) Error ```go func (err Error) Error() string ``` + Error returns a description of the error +```plaintext TypeError: 'def' is not a function +``` -#### func (Error) String +### func (Error) String ```go func (err Error) String() string ``` + String returns a description of the error and a trace of where the error occurred. +```plaintext TypeError: 'def' is not a function at xyz (:3:9) at :7:1/ +``` -#### type FunctionCall +### type FunctionCall ```go type FunctionCall struct { - This Value - ArgumentList []Value - Otto *Otto + This Value + ArgumentList []Value + Otto *Otto } ``` FunctionCall is an encapsulation of a JavaScript function call. -#### func (FunctionCall) Argument +### func (FunctionCall) Argument ```go func (self FunctionCall) Argument(index int) Value ``` + Argument will return the value of the argument at the given index. If no such argument exists, undefined is returned. -#### type Object +### type Object ```go -type Object struct { -} +type Object struct {} ``` Object is the representation of a JavaScript object. -#### func (Object) Call +### func (Object) Call ```go func (self Object) Call(name string, argumentList ...interface{}) (Value, error) ``` + Call a method on the object. It is essentially equivalent to: - var method, _ := object.Get(name) - method.Call(object, argumentList...) +```go +var method, _ := object.Get(name) +method.Call(object, argumentList...) +``` An undefined value and an error will result if: - 1. There is an error during conversion of the argument list - 2. The property is not actually a function - 3. An (uncaught) exception is thrown +1. There is an error during conversion of the argument list +2. The property is not actually a function +3. An (uncaught) exception is thrown -#### func (Object) Class +### func (Object) Class ```go func (self Object) Class() string ``` + Class will return the class string of the object. The return value will (generally) be one of: +```plaintext Object Function Array @@ -368,65 +382,72 @@ The return value will (generally) be one of: Boolean Date RegExp +``` -#### func (Object) Get +### func (Object) Get ```go func (self Object) Get(name string) (Value, error) ``` + Get the value of the property with the given name. -#### func (Object) Keys +### func (Object) Keys ```go func (self Object) Keys() []string ``` + Get the keys for the object Equivalent to calling Object.keys on the object -#### func (Object) Set +### func (Object) Set ```go func (self Object) Set(name string, value interface{}) error ``` + Set the property of the given name to the given value. An error will result if the setting the property triggers an exception (i.e. read-only), or there is an error during conversion of the given value. -#### func (Object) Value +### func (Object) Value ```go func (self Object) Value() Value ``` + Value will return self as a value. -#### type Otto +### type Otto ```go type Otto struct { - // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. - // See "Halting Problem" for more information. - Interrupt chan func() + // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. + // See "Halting Problem" for more information. + Interrupt chan func() } ``` Otto is the representation of the JavaScript runtime. Each instance of Otto has a self-contained namespace. -#### func New +### func New ```go func New() *Otto ``` + New will allocate a new JavaScript runtime -#### func Run +### func Run ```go func Run(src interface{}) (*Otto, Value, error) ``` + Run will allocate a new JavaScript runtime, run the given source on the allocated runtime, and return the runtime, resulting value, and error (if any). @@ -438,11 +459,12 @@ src may also be a Script. src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. -#### func (Otto) Call +### func (Otto) Call ```go func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) ``` + Call the given JavaScript with a given this and arguments. If this is nil, then some special handling takes place to determine the proper @@ -465,11 +487,12 @@ value, _ := vm.Call("new Object", nil, "Hello, World.") value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") ``` -#### func (*Otto) Compile +### func (*Otto) Compile ```go func (self *Otto) Compile(filename string, src interface{}) (*Script, error) ``` + Compile will parse the given source and return a Script value or nil and an error if there was a problem during compilation. @@ -478,11 +501,12 @@ script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) vm.Run(script) ``` -#### func (*Otto) Copy +### func (*Otto) Copy ```go func (in *Otto) Copy() *Otto ``` + Copy will create a copy/clone of the runtime. Copy is useful for saving some time when creating many similar runtimes. @@ -492,21 +516,23 @@ scope, stash, etc. into a new runtime. Be on the lookout for memory leaks or inadvertent sharing of resources. -#### func (Otto) Get +### func (Otto) Get ```go func (self Otto) Get(name string) (Value, error) ``` + Get the value of the top-level binding of the given name. If there is an error (like the binding does not exist), then the value will be undefined. -#### func (Otto) Object +### func (Otto) Object ```go func (self Otto) Object(source string) (*Object, error) ``` + Object will run the given source and return the result as an object. For example, accessing an existing object: @@ -531,11 +557,12 @@ object.Set("volume", 11) If there is an error (like the source does not result in an object), then nil and an error is returned. -#### func (Otto) Run +### func (Otto) Run ```go func (self Otto) Run(src interface{}) (Value, error) ``` + Run will run the given source (parsing it first if necessary), returning the resulting value and error (if any) @@ -550,11 +577,12 @@ src may also be a Script. src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. -#### func (Otto) Set +### func (Otto) Set ```go func (self Otto) Set(name string, value interface{}) error ``` + Set the top-level binding of the given name to the given value. Set will automatically apply ToValue to the given value in order to convert it @@ -565,44 +593,44 @@ fails), then an error is returned. If the top-level binding does not exist, it will be created. -#### func (Otto) ToValue +### func (Otto) ToValue ```go func (self Otto) ToValue(value interface{}) (Value, error) ``` + ToValue will convert an interface{} value to a value digestible by otto/JavaScript. -#### type Script +### type Script ```go -type Script struct { -} +type Script struct {} ``` Script is a handle for some (reusable) JavaScript. Passing a Script value to a run method will evaluate the JavaScript. -#### func (*Script) String +### func (*Script) String ```go func (self *Script) String() string ``` -#### type Value +### type Value ```go -type Value struct { -} +type Value struct {} ``` Value is the representation of a JavaScript value. -#### func FalseValue +### func FalseValue ```go func FalseValue() Value ``` + FalseValue will return a value representing false. It is equivalent to: @@ -611,11 +639,12 @@ It is equivalent to: ToValue(false) ``` -#### func NaNValue +### func NaNValue ```go func NaNValue() Value ``` + NaNValue will return a value representing NaN. It is equivalent to: @@ -624,29 +653,32 @@ It is equivalent to: ToValue(math.NaN()) ``` -#### func NullValue +### func NullValue ```go func NullValue() Value ``` + NullValue will return a Value representing null. -#### func ToValue +### func ToValue ```go func ToValue(value interface{}) (Value, error) ``` + ToValue will convert an interface{} value to a value digestible by otto/JavaScript This function will not work for advanced types (struct, map, slice/array, etc.) and you should use Otto.ToValue instead. -#### func TrueValue +### func TrueValue ```go func TrueValue() Value ``` + TrueValue will return a value representing true. It is equivalent to: @@ -655,39 +687,45 @@ It is equivalent to: ToValue(true) ``` -#### func UndefinedValue +### func UndefinedValue ```go func UndefinedValue() Value ``` + UndefinedValue will return a Value representing undefined. -#### func (Value) Call +### func (Value) Call ```go func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) ``` + Call the value as a function with the given this value and argument list and return the result of invocation. It is essentially equivalent to: +```js value.apply(thisValue, argumentList) +``` An undefined value and an error will result if: - 1. There is an error during conversion of the argument list - 2. The value is not actually a function - 3. An (uncaught) exception is thrown +1. There is an error during conversion of the argument list +2. The value is not actually a function +3. An (uncaught) exception is thrown -#### func (Value) Class +### func (Value) Class ```go func (value Value) Class() string ``` + Class will return the class string of the value or the empty string if value is not an object. The return value will (generally) be one of: +```plaintext Object Function Array @@ -696,12 +734,14 @@ The return value will (generally) be one of: Boolean Date RegExp +``` -#### func (Value) Export +### func (Value) Export ```go func (self Value) Export() (interface{}, error) ``` + Export will attempt to convert the value to a Go representation and return it via an interface{} kind. @@ -710,6 +750,7 @@ compatibility. If a reasonable conversion is not possible, then the original value is returned. +```plaintext undefined -> nil (FIXME?: Should be Value{}) null -> nil boolean -> bool @@ -717,155 +758,177 @@ If a reasonable conversion is not possible, then the original value is returned. string -> string Array -> []interface{} Object -> map[string]interface{} +``` -#### func (Value) IsBoolean +### func (Value) IsBoolean ```go func (value Value) IsBoolean() bool ``` + IsBoolean will return true if value is a boolean (primitive). -#### func (Value) IsDefined +### func (Value) IsDefined ```go func (value Value) IsDefined() bool ``` + IsDefined will return false if the value is undefined, and true otherwise. -#### func (Value) IsFunction +### func (Value) IsFunction ```go func (value Value) IsFunction() bool ``` + IsFunction will return true if value is a function. -#### func (Value) IsNaN +### func (Value) IsNaN ```go func (value Value) IsNaN() bool ``` + IsNaN will return true if value is NaN (or would convert to NaN). -#### func (Value) IsNull +### func (Value) IsNull ```go func (value Value) IsNull() bool ``` + IsNull will return true if the value is null, and false otherwise. -#### func (Value) IsNumber +### func (Value) IsNumber ```go func (value Value) IsNumber() bool ``` + IsNumber will return true if value is a number (primitive). -#### func (Value) IsObject +### func (Value) IsObject ```go func (value Value) IsObject() bool ``` + IsObject will return true if value is an object. -#### func (Value) IsPrimitive +### func (Value) IsPrimitive ```go func (value Value) IsPrimitive() bool ``` + IsPrimitive will return true if value is a primitive (any kind of primitive). -#### func (Value) IsString +### func (Value) IsString ```go func (value Value) IsString() bool ``` + IsString will return true if value is a string (primitive). -#### func (Value) IsUndefined +### func (Value) IsUndefined ```go func (value Value) IsUndefined() bool ``` + IsUndefined will return true if the value is undefined, and false otherwise. -#### func (Value) Object +### func (Value) Object ```go func (value Value) Object() *Object ``` + Object will return the object of the value, or nil if value is not an object. This method will not do any implicit conversion. For example, calling this method on a string primitive value will not return a String object. -#### func (Value) String +### func (Value) String ```go func (value Value) String() string ``` + String will return the value as a string. This method will make return the empty string if there is an error. -#### func (Value) ToBoolean +### func (Value) ToBoolean ```go func (value Value) ToBoolean() (bool, error) ``` + ToBoolean will convert the value to a boolean (bool). +```plaintext ToValue(0).ToBoolean() => false ToValue("").ToBoolean() => false ToValue(true).ToBoolean() => true ToValue(1).ToBoolean() => true ToValue("Nothing happens").ToBoolean() => true +``` If there is an error during the conversion process (like an uncaught exception), then the result will be false and an error. -#### func (Value) ToFloat +### func (Value) ToFloat ```go func (value Value) ToFloat() (float64, error) ``` + ToFloat will convert the value to a number (float64). +```plaintext ToValue(0).ToFloat() => 0. ToValue(1.1).ToFloat() => 1.1 ToValue("11").ToFloat() => 11. +``` If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -#### func (Value) ToInteger +### func (Value) ToInteger ```go func (value Value) ToInteger() (int64, error) ``` + ToInteger will convert the value to a number (int64). +```plaintext ToValue(0).ToInteger() => 0 ToValue(1.1).ToInteger() => 1 ToValue("11").ToInteger() => 11 +``` If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -#### func (Value) ToString +### func (Value) ToString ```go func (value Value) ToString() (string, error) ``` + ToString will convert the value to a string (string). +```plaintext ToValue(0).ToString() => "0" ToValue(false).ToString() => "false" ToValue(1.1).ToString() => "1.1" ToValue("11").ToString() => "11" ToValue('Nothing happens.').ToString() => "Nothing happens." +``` If there is an error during the conversion process (like an uncaught exception), then the result will be the empty string ("") and an error. - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/ast/README.markdown b/vendor/github.com/robertkrimen/otto/ast/README.markdown deleted file mode 100644 index a785da911..000000000 --- a/vendor/github.com/robertkrimen/otto/ast/README.markdown +++ /dev/null @@ -1,1068 +0,0 @@ -# ast --- - import "github.com/robertkrimen/otto/ast" - -Package ast declares types representing a JavaScript AST. - - -### Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -## Usage - -#### type ArrayLiteral - -```go -type ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression -} -``` - - -#### func (*ArrayLiteral) Idx0 - -```go -func (self *ArrayLiteral) Idx0() file.Idx -``` - -#### func (*ArrayLiteral) Idx1 - -```go -func (self *ArrayLiteral) Idx1() file.Idx -``` - -#### type AssignExpression - -```go -type AssignExpression struct { - Operator token.Token - Left Expression - Right Expression -} -``` - - -#### func (*AssignExpression) Idx0 - -```go -func (self *AssignExpression) Idx0() file.Idx -``` - -#### func (*AssignExpression) Idx1 - -```go -func (self *AssignExpression) Idx1() file.Idx -``` - -#### type BadExpression - -```go -type BadExpression struct { - From file.Idx - To file.Idx -} -``` - - -#### func (*BadExpression) Idx0 - -```go -func (self *BadExpression) Idx0() file.Idx -``` - -#### func (*BadExpression) Idx1 - -```go -func (self *BadExpression) Idx1() file.Idx -``` - -#### type BadStatement - -```go -type BadStatement struct { - From file.Idx - To file.Idx -} -``` - - -#### func (*BadStatement) Idx0 - -```go -func (self *BadStatement) Idx0() file.Idx -``` - -#### func (*BadStatement) Idx1 - -```go -func (self *BadStatement) Idx1() file.Idx -``` - -#### type BinaryExpression - -```go -type BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool -} -``` - - -#### func (*BinaryExpression) Idx0 - -```go -func (self *BinaryExpression) Idx0() file.Idx -``` - -#### func (*BinaryExpression) Idx1 - -```go -func (self *BinaryExpression) Idx1() file.Idx -``` - -#### type BlockStatement - -```go -type BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx -} -``` - - -#### func (*BlockStatement) Idx0 - -```go -func (self *BlockStatement) Idx0() file.Idx -``` - -#### func (*BlockStatement) Idx1 - -```go -func (self *BlockStatement) Idx1() file.Idx -``` - -#### type BooleanLiteral - -```go -type BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool -} -``` - - -#### func (*BooleanLiteral) Idx0 - -```go -func (self *BooleanLiteral) Idx0() file.Idx -``` - -#### func (*BooleanLiteral) Idx1 - -```go -func (self *BooleanLiteral) Idx1() file.Idx -``` - -#### type BracketExpression - -```go -type BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx -} -``` - - -#### func (*BracketExpression) Idx0 - -```go -func (self *BracketExpression) Idx0() file.Idx -``` - -#### func (*BracketExpression) Idx1 - -```go -func (self *BracketExpression) Idx1() file.Idx -``` - -#### type BranchStatement - -```go -type BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier -} -``` - - -#### func (*BranchStatement) Idx0 - -```go -func (self *BranchStatement) Idx0() file.Idx -``` - -#### func (*BranchStatement) Idx1 - -```go -func (self *BranchStatement) Idx1() file.Idx -``` - -#### type CallExpression - -```go -type CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx -} -``` - - -#### func (*CallExpression) Idx0 - -```go -func (self *CallExpression) Idx0() file.Idx -``` - -#### func (*CallExpression) Idx1 - -```go -func (self *CallExpression) Idx1() file.Idx -``` - -#### type CaseStatement - -```go -type CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement -} -``` - - -#### func (*CaseStatement) Idx0 - -```go -func (self *CaseStatement) Idx0() file.Idx -``` - -#### func (*CaseStatement) Idx1 - -```go -func (self *CaseStatement) Idx1() file.Idx -``` - -#### type CatchStatement - -```go -type CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement -} -``` - - -#### func (*CatchStatement) Idx0 - -```go -func (self *CatchStatement) Idx0() file.Idx -``` - -#### func (*CatchStatement) Idx1 - -```go -func (self *CatchStatement) Idx1() file.Idx -``` - -#### type ConditionalExpression - -```go -type ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression -} -``` - - -#### func (*ConditionalExpression) Idx0 - -```go -func (self *ConditionalExpression) Idx0() file.Idx -``` - -#### func (*ConditionalExpression) Idx1 - -```go -func (self *ConditionalExpression) Idx1() file.Idx -``` - -#### type DebuggerStatement - -```go -type DebuggerStatement struct { - Debugger file.Idx -} -``` - - -#### func (*DebuggerStatement) Idx0 - -```go -func (self *DebuggerStatement) Idx0() file.Idx -``` - -#### func (*DebuggerStatement) Idx1 - -```go -func (self *DebuggerStatement) Idx1() file.Idx -``` - -#### type Declaration - -```go -type Declaration interface { - // contains filtered or unexported methods -} -``` - -All declaration nodes implement the Declaration interface. - -#### type DoWhileStatement - -```go -type DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement -} -``` - - -#### func (*DoWhileStatement) Idx0 - -```go -func (self *DoWhileStatement) Idx0() file.Idx -``` - -#### func (*DoWhileStatement) Idx1 - -```go -func (self *DoWhileStatement) Idx1() file.Idx -``` - -#### type DotExpression - -```go -type DotExpression struct { - Left Expression - Identifier Identifier -} -``` - - -#### func (*DotExpression) Idx0 - -```go -func (self *DotExpression) Idx0() file.Idx -``` - -#### func (*DotExpression) Idx1 - -```go -func (self *DotExpression) Idx1() file.Idx -``` - -#### type EmptyStatement - -```go -type EmptyStatement struct { - Semicolon file.Idx -} -``` - - -#### func (*EmptyStatement) Idx0 - -```go -func (self *EmptyStatement) Idx0() file.Idx -``` - -#### func (*EmptyStatement) Idx1 - -```go -func (self *EmptyStatement) Idx1() file.Idx -``` - -#### type Expression - -```go -type Expression interface { - Node - // contains filtered or unexported methods -} -``` - -All expression nodes implement the Expression interface. - -#### type ExpressionStatement - -```go -type ExpressionStatement struct { - Expression Expression -} -``` - - -#### func (*ExpressionStatement) Idx0 - -```go -func (self *ExpressionStatement) Idx0() file.Idx -``` - -#### func (*ExpressionStatement) Idx1 - -```go -func (self *ExpressionStatement) Idx1() file.Idx -``` - -#### type ForInStatement - -```go -type ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement -} -``` - - -#### func (*ForInStatement) Idx0 - -```go -func (self *ForInStatement) Idx0() file.Idx -``` - -#### func (*ForInStatement) Idx1 - -```go -func (self *ForInStatement) Idx1() file.Idx -``` - -#### type ForStatement - -```go -type ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement -} -``` - - -#### func (*ForStatement) Idx0 - -```go -func (self *ForStatement) Idx0() file.Idx -``` - -#### func (*ForStatement) Idx1 - -```go -func (self *ForStatement) Idx1() file.Idx -``` - -#### type FunctionDeclaration - -```go -type FunctionDeclaration struct { - Function *FunctionLiteral -} -``` - - -#### type FunctionLiteral - -```go -type FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string - - DeclarationList []Declaration -} -``` - - -#### func (*FunctionLiteral) Idx0 - -```go -func (self *FunctionLiteral) Idx0() file.Idx -``` - -#### func (*FunctionLiteral) Idx1 - -```go -func (self *FunctionLiteral) Idx1() file.Idx -``` - -#### type Identifier - -```go -type Identifier struct { - Name string - Idx file.Idx -} -``` - - -#### func (*Identifier) Idx0 - -```go -func (self *Identifier) Idx0() file.Idx -``` - -#### func (*Identifier) Idx1 - -```go -func (self *Identifier) Idx1() file.Idx -``` - -#### type IfStatement - -```go -type IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement -} -``` - - -#### func (*IfStatement) Idx0 - -```go -func (self *IfStatement) Idx0() file.Idx -``` - -#### func (*IfStatement) Idx1 - -```go -func (self *IfStatement) Idx1() file.Idx -``` - -#### type LabelledStatement - -```go -type LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement -} -``` - - -#### func (*LabelledStatement) Idx0 - -```go -func (self *LabelledStatement) Idx0() file.Idx -``` - -#### func (*LabelledStatement) Idx1 - -```go -func (self *LabelledStatement) Idx1() file.Idx -``` - -#### type NewExpression - -```go -type NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx -} -``` - - -#### func (*NewExpression) Idx0 - -```go -func (self *NewExpression) Idx0() file.Idx -``` - -#### func (*NewExpression) Idx1 - -```go -func (self *NewExpression) Idx1() file.Idx -``` - -#### type Node - -```go -type Node interface { - Idx0() file.Idx // The index of the first character belonging to the node - Idx1() file.Idx // The index of the first character immediately after the node -} -``` - -All nodes implement the Node interface. - -#### type NullLiteral - -```go -type NullLiteral struct { - Idx file.Idx - Literal string -} -``` - - -#### func (*NullLiteral) Idx0 - -```go -func (self *NullLiteral) Idx0() file.Idx -``` - -#### func (*NullLiteral) Idx1 - -```go -func (self *NullLiteral) Idx1() file.Idx -``` - -#### type NumberLiteral - -```go -type NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} -} -``` - - -#### func (*NumberLiteral) Idx0 - -```go -func (self *NumberLiteral) Idx0() file.Idx -``` - -#### func (*NumberLiteral) Idx1 - -```go -func (self *NumberLiteral) Idx1() file.Idx -``` - -#### type ObjectLiteral - -```go -type ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property -} -``` - - -#### func (*ObjectLiteral) Idx0 - -```go -func (self *ObjectLiteral) Idx0() file.Idx -``` - -#### func (*ObjectLiteral) Idx1 - -```go -func (self *ObjectLiteral) Idx1() file.Idx -``` - -#### type ParameterList - -```go -type ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx -} -``` - - -#### type Program - -```go -type Program struct { - Body []Statement - - DeclarationList []Declaration - - File *file.File -} -``` - - -#### func (*Program) Idx0 - -```go -func (self *Program) Idx0() file.Idx -``` - -#### func (*Program) Idx1 - -```go -func (self *Program) Idx1() file.Idx -``` - -#### type Property - -```go -type Property struct { - Key string - Kind string - Value Expression -} -``` - - -#### type RegExpLiteral - -```go -type RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string -} -``` - - -#### func (*RegExpLiteral) Idx0 - -```go -func (self *RegExpLiteral) Idx0() file.Idx -``` - -#### func (*RegExpLiteral) Idx1 - -```go -func (self *RegExpLiteral) Idx1() file.Idx -``` - -#### type ReturnStatement - -```go -type ReturnStatement struct { - Return file.Idx - Argument Expression -} -``` - - -#### func (*ReturnStatement) Idx0 - -```go -func (self *ReturnStatement) Idx0() file.Idx -``` - -#### func (*ReturnStatement) Idx1 - -```go -func (self *ReturnStatement) Idx1() file.Idx -``` - -#### type SequenceExpression - -```go -type SequenceExpression struct { - Sequence []Expression -} -``` - - -#### func (*SequenceExpression) Idx0 - -```go -func (self *SequenceExpression) Idx0() file.Idx -``` - -#### func (*SequenceExpression) Idx1 - -```go -func (self *SequenceExpression) Idx1() file.Idx -``` - -#### type Statement - -```go -type Statement interface { - Node - // contains filtered or unexported methods -} -``` - -All statement nodes implement the Statement interface. - -#### type StringLiteral - -```go -type StringLiteral struct { - Idx file.Idx - Literal string - Value string -} -``` - - -#### func (*StringLiteral) Idx0 - -```go -func (self *StringLiteral) Idx0() file.Idx -``` - -#### func (*StringLiteral) Idx1 - -```go -func (self *StringLiteral) Idx1() file.Idx -``` - -#### type SwitchStatement - -```go -type SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement -} -``` - - -#### func (*SwitchStatement) Idx0 - -```go -func (self *SwitchStatement) Idx0() file.Idx -``` - -#### func (*SwitchStatement) Idx1 - -```go -func (self *SwitchStatement) Idx1() file.Idx -``` - -#### type ThisExpression - -```go -type ThisExpression struct { - Idx file.Idx -} -``` - - -#### func (*ThisExpression) Idx0 - -```go -func (self *ThisExpression) Idx0() file.Idx -``` - -#### func (*ThisExpression) Idx1 - -```go -func (self *ThisExpression) Idx1() file.Idx -``` - -#### type ThrowStatement - -```go -type ThrowStatement struct { - Throw file.Idx - Argument Expression -} -``` - - -#### func (*ThrowStatement) Idx0 - -```go -func (self *ThrowStatement) Idx0() file.Idx -``` - -#### func (*ThrowStatement) Idx1 - -```go -func (self *ThrowStatement) Idx1() file.Idx -``` - -#### type TryStatement - -```go -type TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement -} -``` - - -#### func (*TryStatement) Idx0 - -```go -func (self *TryStatement) Idx0() file.Idx -``` - -#### func (*TryStatement) Idx1 - -```go -func (self *TryStatement) Idx1() file.Idx -``` - -#### type UnaryExpression - -```go -type UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool -} -``` - - -#### func (*UnaryExpression) Idx0 - -```go -func (self *UnaryExpression) Idx0() file.Idx -``` - -#### func (*UnaryExpression) Idx1 - -```go -func (self *UnaryExpression) Idx1() file.Idx -``` - -#### type VariableDeclaration - -```go -type VariableDeclaration struct { - Var file.Idx - List []*VariableExpression -} -``` - - -#### type VariableExpression - -```go -type VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression -} -``` - - -#### func (*VariableExpression) Idx0 - -```go -func (self *VariableExpression) Idx0() file.Idx -``` - -#### func (*VariableExpression) Idx1 - -```go -func (self *VariableExpression) Idx1() file.Idx -``` - -#### type VariableStatement - -```go -type VariableStatement struct { - Var file.Idx - List []Expression -} -``` - - -#### func (*VariableStatement) Idx0 - -```go -func (self *VariableStatement) Idx0() file.Idx -``` - -#### func (*VariableStatement) Idx1 - -```go -func (self *VariableStatement) Idx1() file.Idx -``` - -#### type WhileStatement - -```go -type WhileStatement struct { - While file.Idx - Test Expression - Body Statement -} -``` - - -#### func (*WhileStatement) Idx0 - -```go -func (self *WhileStatement) Idx0() file.Idx -``` - -#### func (*WhileStatement) Idx1 - -```go -func (self *WhileStatement) Idx1() file.Idx -``` - -#### type WithStatement - -```go -type WithStatement struct { - With file.Idx - Object Expression - Body Statement -} -``` - - -#### func (*WithStatement) Idx0 - -```go -func (self *WithStatement) Idx0() file.Idx -``` - -#### func (*WithStatement) Idx1 - -```go -func (self *WithStatement) Idx1() file.Idx -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/ast/comments.go b/vendor/github.com/robertkrimen/otto/ast/comments.go index ef2cc3d89..81dc594eb 100644 --- a/vendor/github.com/robertkrimen/otto/ast/comments.go +++ b/vendor/github.com/robertkrimen/otto/ast/comments.go @@ -2,35 +2,48 @@ package ast import ( "fmt" + "github.com/robertkrimen/otto/file" ) -// CommentPosition determines where the comment is in a given context +// CommentPosition determines where the comment is in a given context. type CommentPosition int +// Available comment positions. const ( - _ CommentPosition = iota - LEADING // Before the pertinent expression - TRAILING // After the pertinent expression - KEY // Before a key in an object - COLON // After a colon in a field declaration - FINAL // Final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal - IF // After an if keyword - WHILE // After a while keyword - DO // After do keyword - FOR // After a for keyword - WITH // After a with keyword + _ CommentPosition = iota + // LEADING is before the pertinent expression. + LEADING + // TRAILING is after the pertinent expression. + TRAILING + // KEY is before a key in an object. + KEY + // COLON is after a colon in a field declaration. + COLON + // FINAL is the final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal. + FINAL + // IF is after an if keyword. + IF + // WHILE is after a while keyword. + WHILE + // DO is after do keyword. + DO + // FOR is after a for keyword. + FOR + // WITH is after a with keyword. + WITH + // TBD is unknown. TBD ) -// Comment contains the data of the comment +// Comment contains the data of the comment. type Comment struct { - Begin file.Idx Text string + Begin file.Idx Position CommentPosition } -// NewComment creates a new comment +// NewComment creates a new comment. func NewComment(text string, idx file.Idx) *Comment { comment := &Comment{ Begin: idx, @@ -41,7 +54,7 @@ func NewComment(text string, idx file.Idx) *Comment { return comment } -// String returns a stringified version of the position +// String returns a stringified version of the position. func (cp CommentPosition) String() string { switch cp { case LEADING: @@ -69,23 +82,23 @@ func (cp CommentPosition) String() string { } } -// String returns a stringified version of the comment +// String returns a stringified version of the comment. func (c Comment) String() string { return fmt.Sprintf("Comment: %v", c.Text) } -// Comments defines the current view of comments from the parser +// Comments defines the current view of comments from the parser. type Comments struct { // CommentMap is a reference to the parser comment map CommentMap CommentMap // Comments lists the comments scanned, not linked to a node yet Comments []*Comment - // future lists the comments after a line break during a sequence of comments - future []*Comment // Current is node for which comments are linked to Current Expression - // wasLineBreak determines if a line break occured while scanning for comments + // future lists the comments after a line break during a sequence of comments + future []*Comment + // wasLineBreak determines if a line break occurred while scanning for comments wasLineBreak bool // primary determines whether or not processing a primary expression primary bool @@ -93,6 +106,7 @@ type Comments struct { afterBlock bool } +// NewComments returns a new Comments. func NewComments() *Comments { comments := &Comments{ CommentMap: CommentMap{}, @@ -106,7 +120,7 @@ func (c *Comments) String() string { } // FetchAll returns all the currently scanned comments, -// including those from the next line +// including those from the next line. func (c *Comments) FetchAll() []*Comment { defer func() { c.Comments = nil @@ -116,7 +130,7 @@ func (c *Comments) FetchAll() []*Comment { return append(c.Comments, c.future...) } -// Fetch returns all the currently scanned comments +// Fetch returns all the currently scanned comments. func (c *Comments) Fetch() []*Comment { defer func() { c.Comments = nil @@ -125,12 +139,12 @@ func (c *Comments) Fetch() []*Comment { return c.Comments } -// ResetLineBreak marks the beginning of a new statement +// ResetLineBreak marks the beginning of a new statement. func (c *Comments) ResetLineBreak() { c.wasLineBreak = false } -// MarkPrimary will mark the context as processing a primary expression +// MarkPrimary will mark the context as processing a primary expression. func (c *Comments) MarkPrimary() { c.primary = true c.wasLineBreak = false @@ -204,7 +218,7 @@ func (c *Comments) SetExpression(node Expression) { c.applyComments(node, previous, TRAILING) } -// PostProcessNode applies all found comments to the given node +// PostProcessNode applies all found comments to the given node. func (c *Comments) PostProcessNode(node Node) { c.applyComments(node, nil, TRAILING) } @@ -227,15 +241,15 @@ func (c *Comments) applyComments(node, previous Node, position CommentPosition) } } -// AtLineBreak will mark a line break +// AtLineBreak will mark a line break. func (c *Comments) AtLineBreak() { c.wasLineBreak = true } -// CommentMap is the data structure where all found comments are stored +// CommentMap is the data structure where all found comments are stored. type CommentMap map[Node][]*Comment -// AddComment adds a single comment to the map +// AddComment adds a single comment to the map. func (cm CommentMap) AddComment(node Node, comment *Comment) { list := cm[node] list = append(list, comment) @@ -243,7 +257,7 @@ func (cm CommentMap) AddComment(node Node, comment *Comment) { cm[node] = list } -// AddComments adds a slice of comments, given a node and an updated position +// AddComments adds a slice of comments, given a node and an updated position. func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) { for _, comment := range comments { if comment.Position == TBD { @@ -253,7 +267,7 @@ func (cm CommentMap) AddComments(node Node, comments []*Comment, position Commen } } -// Size returns the size of the map +// Size returns the size of the map. func (cm CommentMap) Size() int { size := 0 for _, comments := range cm { @@ -263,7 +277,7 @@ func (cm CommentMap) Size() int { return size } -// MoveComments moves comments with a given position from a node to another +// MoveComments moves comments with a given position from a node to another. func (cm CommentMap) MoveComments(from, to Node, position CommentPosition) { for i, c := range cm[from] { if c.Position == position { diff --git a/vendor/github.com/robertkrimen/otto/ast/node.go b/vendor/github.com/robertkrimen/otto/ast/node.go index 7e45abe97..ae9e63b87 100644 --- a/vendor/github.com/robertkrimen/otto/ast/node.go +++ b/vendor/github.com/robertkrimen/otto/ast/node.go @@ -1,12 +1,8 @@ -/* -Package ast declares types representing a JavaScript AST. - -Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -*/ +// Package ast declares types representing a JavaScript AST. +// +// # Warning +// The parser and AST interfaces are still works-in-progress (particularly where +// node types are concerned) and may change in the future. package ast import ( @@ -14,502 +10,955 @@ import ( "github.com/robertkrimen/otto/token" ) -// All nodes implement the Node interface. +// Node is implemented by types that represent a node. type Node interface { Idx0() file.Idx // The index of the first character belonging to the node Idx1() file.Idx // The index of the first character immediately after the node } -// ========== // -// Expression // -// ========== // +// Expression is implemented by types that represent an Expression. +type Expression interface { + Node + expression() +} -type ( - // All expression nodes implement the Expression interface. - Expression interface { - Node - _expressionNode() - } +// ArrayLiteral represents an array literal. +type ArrayLiteral struct { + Value []Expression + LeftBracket file.Idx + RightBracket file.Idx +} - ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression - } +// Idx0 implements Node. +func (al *ArrayLiteral) Idx0() file.Idx { + return al.LeftBracket +} - AssignExpression struct { - Operator token.Token - Left Expression - Right Expression - } +// Idx1 implements Node. +func (al *ArrayLiteral) Idx1() file.Idx { + return al.RightBracket + 1 +} - BadExpression struct { - From file.Idx - To file.Idx - } +// expression implements Expression. +func (*ArrayLiteral) expression() {} - BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool - } +// AssignExpression represents an assignment expression. +type AssignExpression struct { + Left Expression + Right Expression + Operator token.Token +} - BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool - } +// Idx0 implements Node. +func (ae *AssignExpression) Idx0() file.Idx { + return ae.Left.Idx0() +} - BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx - } +// Idx1 implements Node. +func (ae *AssignExpression) Idx1() file.Idx { + return ae.Right.Idx1() +} - CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } +// expression implements Expression. +func (*AssignExpression) expression() {} - ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression - } +// BadExpression represents a bad expression. +type BadExpression struct { + From file.Idx + To file.Idx +} - DotExpression struct { - Left Expression - Identifier *Identifier - } +// Idx0 implements Node. +func (be *BadExpression) Idx0() file.Idx { + return be.From +} - EmptyExpression struct { - Begin file.Idx - End file.Idx - } +// Idx1 implements Node. +func (be *BadExpression) Idx1() file.Idx { + return be.To +} - FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string +// expression implements Expression. +func (*BadExpression) expression() {} - DeclarationList []Declaration - } +// BinaryExpression represents a binary expression. +type BinaryExpression struct { + Left Expression + Right Expression + Operator token.Token + Comparison bool +} - Identifier struct { - Name string - Idx file.Idx - } +// Idx0 implements Node. +func (be *BinaryExpression) Idx0() file.Idx { + return be.Left.Idx0() +} - NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } +// Idx1 implements Node. +func (be *BinaryExpression) Idx1() file.Idx { + return be.Right.Idx1() +} - NullLiteral struct { - Idx file.Idx - Literal string - } +// expression implements Expression. +func (*BinaryExpression) expression() {} - NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} - } +// BooleanLiteral represents a boolean expression. +type BooleanLiteral struct { + Literal string + Idx file.Idx + Value bool +} - ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property - } +// Idx0 implements Node. +func (bl *BooleanLiteral) Idx0() file.Idx { + return bl.Idx +} - ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx - } +// Idx1 implements Node. +func (bl *BooleanLiteral) Idx1() file.Idx { + return file.Idx(int(bl.Idx) + len(bl.Literal)) +} - Property struct { - Key string - Kind string - Value Expression - } +// expression implements Expression. +func (*BooleanLiteral) expression() {} - RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string - } +// BracketExpression represents a bracketed expression. +type BracketExpression struct { + Left Expression + Member Expression + LeftBracket file.Idx + RightBracket file.Idx +} - SequenceExpression struct { - Sequence []Expression - } +// Idx0 implements Node. +func (be *BracketExpression) Idx0() file.Idx { + return be.Left.Idx0() +} - StringLiteral struct { - Idx file.Idx - Literal string - Value string - } +// Idx1 implements Node. +func (be *BracketExpression) Idx1() file.Idx { + return be.RightBracket + 1 +} - ThisExpression struct { - Idx file.Idx - } +// expression implements Expression. +func (*BracketExpression) expression() {} - UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool - } +// CallExpression represents a call expression. +type CallExpression struct { + Callee Expression + ArgumentList []Expression + LeftParenthesis file.Idx + RightParenthesis file.Idx +} - VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression - } -) +// Idx0 implements Node. +func (ce *CallExpression) Idx0() file.Idx { + return ce.Callee.Idx0() +} -// _expressionNode - -func (*ArrayLiteral) _expressionNode() {} -func (*AssignExpression) _expressionNode() {} -func (*BadExpression) _expressionNode() {} -func (*BinaryExpression) _expressionNode() {} -func (*BooleanLiteral) _expressionNode() {} -func (*BracketExpression) _expressionNode() {} -func (*CallExpression) _expressionNode() {} -func (*ConditionalExpression) _expressionNode() {} -func (*DotExpression) _expressionNode() {} -func (*EmptyExpression) _expressionNode() {} -func (*FunctionLiteral) _expressionNode() {} -func (*Identifier) _expressionNode() {} -func (*NewExpression) _expressionNode() {} -func (*NullLiteral) _expressionNode() {} -func (*NumberLiteral) _expressionNode() {} -func (*ObjectLiteral) _expressionNode() {} -func (*RegExpLiteral) _expressionNode() {} -func (*SequenceExpression) _expressionNode() {} -func (*StringLiteral) _expressionNode() {} -func (*ThisExpression) _expressionNode() {} -func (*UnaryExpression) _expressionNode() {} -func (*VariableExpression) _expressionNode() {} - -// ========= // -// Statement // -// ========= // - -type ( - // All statement nodes implement the Statement interface. - Statement interface { - Node - _statementNode() - } +// Idx1 implements Node. +func (ce *CallExpression) Idx1() file.Idx { + return ce.RightParenthesis + 1 +} - BadStatement struct { - From file.Idx - To file.Idx - } +// expression implements Expression. +func (*CallExpression) expression() {} - BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx - } +// ConditionalExpression represents a conditional expression. +type ConditionalExpression struct { + Test Expression + Consequent Expression + Alternate Expression +} - BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier - } +// Idx0 implements Node. +func (ce *ConditionalExpression) Idx0() file.Idx { + return ce.Test.Idx0() +} - CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement - } +// Idx1 implements Node. +func (ce *ConditionalExpression) Idx1() file.Idx { + return ce.Alternate.Idx1() +} - CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement - } +// expression implements Expression. +func (*ConditionalExpression) expression() {} - DebuggerStatement struct { - Debugger file.Idx - } +// DotExpression represents a dot expression. +type DotExpression struct { + Left Expression + Identifier *Identifier +} - DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement - } +// Idx0 implements Node. +func (de *DotExpression) Idx0() file.Idx { + return de.Left.Idx0() +} - EmptyStatement struct { - Semicolon file.Idx - } +// Idx1 implements Node. +func (de *DotExpression) Idx1() file.Idx { + return de.Identifier.Idx1() +} - ExpressionStatement struct { - Expression Expression - } +// expression implements Expression. +func (*DotExpression) expression() {} - ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement - } +// EmptyExpression represents an empty expression. +type EmptyExpression struct { + Begin file.Idx + End file.Idx +} - ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement - } +// Idx0 implements Node. +func (ee *EmptyExpression) Idx0() file.Idx { + return ee.Begin +} - FunctionStatement struct { - Function *FunctionLiteral - } +// Idx1 implements Node. +func (ee *EmptyExpression) Idx1() file.Idx { + return ee.End +} - IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement - } +// expression implements Expression. +func (*EmptyExpression) expression() {} - LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement - } +// FunctionLiteral represents a function literal. +type FunctionLiteral struct { + Body Statement + Name *Identifier + ParameterList *ParameterList + Source string + DeclarationList []Declaration + Function file.Idx +} - ReturnStatement struct { - Return file.Idx - Argument Expression - } +// Idx0 implements Node. +func (fl *FunctionLiteral) Idx0() file.Idx { + return fl.Function +} - SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement - } +// Idx1 implements Node. +func (fl *FunctionLiteral) Idx1() file.Idx { + return fl.Body.Idx1() +} + +// expression implements Expression. +func (*FunctionLiteral) expression() {} + +// Identifier represents an identifier. +type Identifier struct { + Name string + Idx file.Idx +} + +// Idx0 implements Node. +func (i *Identifier) Idx0() file.Idx { + return i.Idx +} + +// Idx1 implements Node. +func (i *Identifier) Idx1() file.Idx { + return file.Idx(int(i.Idx) + len(i.Name)) +} + +// expression implements Expression. +func (*Identifier) expression() {} + +// NewExpression represents a new expression. +type NewExpression struct { + Callee Expression + ArgumentList []Expression + New file.Idx + LeftParenthesis file.Idx + RightParenthesis file.Idx +} + +// Idx0 implements Node. +func (ne *NewExpression) Idx0() file.Idx { + return ne.New +} - ThrowStatement struct { - Throw file.Idx - Argument Expression +// Idx1 implements Node. +func (ne *NewExpression) Idx1() file.Idx { + if ne.RightParenthesis > 0 { + return ne.RightParenthesis + 1 } + return ne.Callee.Idx1() +} + +// expression implements Expression. +func (*NewExpression) expression() {} + +// NullLiteral represents a null literal. +type NullLiteral struct { + Literal string + Idx file.Idx +} + +// Idx0 implements Node. +func (nl *NullLiteral) Idx0() file.Idx { + return nl.Idx +} + +// Idx1 implements Node. +func (nl *NullLiteral) Idx1() file.Idx { + return file.Idx(int(nl.Idx) + 4) +} + +// expression implements Expression. +func (*NullLiteral) expression() {} + +// NumberLiteral represents a number literal. +type NumberLiteral struct { + Value interface{} + Literal string + Idx file.Idx +} + +// Idx0 implements Node. +func (nl *NumberLiteral) Idx0() file.Idx { + return nl.Idx +} + +// Idx1 implements Node. +func (nl *NumberLiteral) Idx1() file.Idx { + return file.Idx(int(nl.Idx) + len(nl.Literal)) +} + +// expression implements Expression. +func (*NumberLiteral) expression() {} + +// ObjectLiteral represents an object literal. +type ObjectLiteral struct { + Value []Property + LeftBrace file.Idx + RightBrace file.Idx +} + +// Idx0 implements Node. +func (ol *ObjectLiteral) Idx0() file.Idx { + return ol.LeftBrace +} + +// Idx1 implements Node. +func (ol *ObjectLiteral) Idx1() file.Idx { + return ol.RightBrace + 1 +} + +// expression implements Expression. +func (*ObjectLiteral) expression() {} + +// ParameterList represents a parameter list. +type ParameterList struct { + List []*Identifier + Opening file.Idx + Closing file.Idx +} + +// Property represents a property. +type Property struct { + Value Expression + Key string + Kind string +} - TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement +// RegExpLiteral represents a regular expression literal. +type RegExpLiteral struct { + Literal string + Pattern string + Flags string + Value string + Idx file.Idx +} + +// Idx0 implements Node. +func (rl *RegExpLiteral) Idx0() file.Idx { + return rl.Idx +} + +// Idx1 implements Node. +func (rl *RegExpLiteral) Idx1() file.Idx { + return file.Idx(int(rl.Idx) + len(rl.Literal)) +} + +// expression implements Expression. +func (*RegExpLiteral) expression() {} + +// SequenceExpression represents a sequence literal. +type SequenceExpression struct { + Sequence []Expression +} + +// Idx0 implements Node. +func (se *SequenceExpression) Idx0() file.Idx { + return se.Sequence[0].Idx0() +} + +// Idx1 implements Node. +func (se *SequenceExpression) Idx1() file.Idx { + return se.Sequence[len(se.Sequence)-1].Idx1() +} + +// expression implements Expression. +func (*SequenceExpression) expression() {} + +// StringLiteral represents a string literal. +type StringLiteral struct { + Literal string + Value string + Idx file.Idx +} + +// Idx0 implements Node. +func (sl *StringLiteral) Idx0() file.Idx { + return sl.Idx +} + +// Idx1 implements Node. +func (sl *StringLiteral) Idx1() file.Idx { + return file.Idx(int(sl.Idx) + len(sl.Literal)) +} + +// expression implements Expression. +func (*StringLiteral) expression() {} + +// ThisExpression represents a this expression. +type ThisExpression struct { + Idx file.Idx +} + +// Idx0 implements Node. +func (te *ThisExpression) Idx0() file.Idx { + return te.Idx +} + +// Idx1 implements Node. +func (te *ThisExpression) Idx1() file.Idx { + return te.Idx + 4 +} + +// expression implements Expression. +func (*ThisExpression) expression() {} + +// UnaryExpression represents a unary expression. +type UnaryExpression struct { + Operand Expression + Operator token.Token + Idx file.Idx + Postfix bool +} + +// Idx0 implements Node. +func (ue *UnaryExpression) Idx0() file.Idx { + if ue.Postfix { + return ue.Operand.Idx0() } + return ue.Idx +} - VariableStatement struct { - Var file.Idx - List []Expression +// Idx1 implements Node. +func (ue *UnaryExpression) Idx1() file.Idx { + if ue.Postfix { + return ue.Operand.Idx1() + 2 // ++ -- } + return ue.Operand.Idx1() +} + +// expression implements Expression. +func (*UnaryExpression) expression() {} + +// VariableExpression represents a variable expression. +type VariableExpression struct { + Initializer Expression + Name string + Idx file.Idx +} - WhileStatement struct { - While file.Idx - Test Expression - Body Statement +// Idx0 implements Node. +func (ve *VariableExpression) Idx0() file.Idx { + return ve.Idx +} + +// Idx1 implements Node. +func (ve *VariableExpression) Idx1() file.Idx { + if ve.Initializer == nil { + return file.Idx(int(ve.Idx) + len(ve.Name)) } + return ve.Initializer.Idx1() +} + +// expression implements Expression. +func (*VariableExpression) expression() {} - WithStatement struct { - With file.Idx - Object Expression - Body Statement +// Statement is implemented by types which represent a statement. +type Statement interface { + Node + statement() +} + +// BadStatement represents a bad statement. +type BadStatement struct { + From file.Idx + To file.Idx +} + +// Idx0 implements Node. +func (bs *BadStatement) Idx0() file.Idx { + return bs.From +} + +// Idx1 implements Node. +func (bs *BadStatement) Idx1() file.Idx { + return bs.To +} + +// expression implements Statement. +func (*BadStatement) statement() {} + +// BlockStatement represents a block statement. +type BlockStatement struct { + List []Statement + LeftBrace file.Idx + RightBrace file.Idx +} + +// Idx0 implements Node. +func (bs *BlockStatement) Idx0() file.Idx { + return bs.LeftBrace +} + +// Idx1 implements Node. +func (bs *BlockStatement) Idx1() file.Idx { + return bs.RightBrace + 1 +} + +// expression implements Statement. +func (*BlockStatement) statement() {} + +// BranchStatement represents a branch statement. +type BranchStatement struct { + Label *Identifier + Idx file.Idx + Token token.Token +} + +// Idx0 implements Node. +func (bs *BranchStatement) Idx0() file.Idx { + return bs.Idx +} + +// Idx1 implements Node. +func (bs *BranchStatement) Idx1() file.Idx { + if bs.Label == nil { + return file.Idx(int(bs.Idx) + len(bs.Token.String())) } -) + return bs.Label.Idx1() +} + +// expression implements Statement. +func (*BranchStatement) statement() {} + +// CaseStatement represents a case statement. +type CaseStatement struct { + Test Expression + Consequent []Statement + Case file.Idx +} + +// Idx0 implements Node. +func (cs *CaseStatement) Idx0() file.Idx { + return cs.Case +} + +// Idx1 implements Node. +func (cs *CaseStatement) Idx1() file.Idx { + return cs.Consequent[len(cs.Consequent)-1].Idx1() +} + +// expression implements Statement. +func (*CaseStatement) statement() {} + +// CatchStatement represents a catch statement. +type CatchStatement struct { + Body Statement + Parameter *Identifier + Catch file.Idx +} + +// Idx0 implements Node. +func (cs *CatchStatement) Idx0() file.Idx { + return cs.Catch +} + +// Idx1 implements Node. +func (cs *CatchStatement) Idx1() file.Idx { + return cs.Body.Idx1() +} + +// expression implements Statement. +func (*CatchStatement) statement() {} + +// DebuggerStatement represents a debugger statement. +type DebuggerStatement struct { + Debugger file.Idx +} + +// Idx0 implements Node. +func (ds *DebuggerStatement) Idx0() file.Idx { + return ds.Debugger +} + +// Idx1 implements Node. +func (ds *DebuggerStatement) Idx1() file.Idx { + return ds.Debugger + 8 +} + +// expression implements Statement. +func (*DebuggerStatement) statement() {} + +// DoWhileStatement represents a do while statement. +type DoWhileStatement struct { + Test Expression + Body Statement + Do file.Idx + RightParenthesis file.Idx +} + +// Idx0 implements Node. +func (dws *DoWhileStatement) Idx0() file.Idx { + return dws.Do +} + +// Idx1 implements Node. +func (dws *DoWhileStatement) Idx1() file.Idx { + return dws.RightParenthesis + 1 +} + +// expression implements Statement. +func (*DoWhileStatement) statement() {} + +// EmptyStatement represents a empty statement. +type EmptyStatement struct { + Semicolon file.Idx +} + +// Idx0 implements Node. +func (es *EmptyStatement) Idx0() file.Idx { + return es.Semicolon +} + +// Idx1 implements Node. +func (es *EmptyStatement) Idx1() file.Idx { + return es.Semicolon + 1 +} + +// expression implements Statement. +func (*EmptyStatement) statement() {} + +// ExpressionStatement represents a expression statement. +type ExpressionStatement struct { + Expression Expression +} -// _statementNode - -func (*BadStatement) _statementNode() {} -func (*BlockStatement) _statementNode() {} -func (*BranchStatement) _statementNode() {} -func (*CaseStatement) _statementNode() {} -func (*CatchStatement) _statementNode() {} -func (*DebuggerStatement) _statementNode() {} -func (*DoWhileStatement) _statementNode() {} -func (*EmptyStatement) _statementNode() {} -func (*ExpressionStatement) _statementNode() {} -func (*ForInStatement) _statementNode() {} -func (*ForStatement) _statementNode() {} -func (*FunctionStatement) _statementNode() {} -func (*IfStatement) _statementNode() {} -func (*LabelledStatement) _statementNode() {} -func (*ReturnStatement) _statementNode() {} -func (*SwitchStatement) _statementNode() {} -func (*ThrowStatement) _statementNode() {} -func (*TryStatement) _statementNode() {} -func (*VariableStatement) _statementNode() {} -func (*WhileStatement) _statementNode() {} -func (*WithStatement) _statementNode() {} - -// =========== // -// Declaration // -// =========== // - -type ( - // All declaration nodes implement the Declaration interface. - Declaration interface { - _declarationNode() +// Idx0 implements Node. +func (es *ExpressionStatement) Idx0() file.Idx { + return es.Expression.Idx0() +} + +// Idx1 implements Node. +func (es *ExpressionStatement) Idx1() file.Idx { + return es.Expression.Idx1() +} + +// expression implements Statement. +func (*ExpressionStatement) statement() {} + +// ForInStatement represents a for in statement. +type ForInStatement struct { + Into Expression + Source Expression + Body Statement + For file.Idx +} + +// Idx0 implements Node. +func (fis *ForInStatement) Idx0() file.Idx { + return fis.For +} + +// Idx1 implements Node. +func (fis *ForInStatement) Idx1() file.Idx { + return fis.Body.Idx1() +} + +// expression implements Statement. +func (*ForInStatement) statement() {} + +// ForStatement represents a for statement. +type ForStatement struct { + Initializer Expression + Update Expression + Test Expression + Body Statement + For file.Idx +} + +// Idx0 implements Node. +func (fs *ForStatement) Idx0() file.Idx { + return fs.For +} + +// Idx1 implements Node. +func (fs *ForStatement) Idx1() file.Idx { + return fs.Body.Idx1() +} + +// expression implements Statement. +func (*ForStatement) statement() {} + +// FunctionStatement represents a function statement. +type FunctionStatement struct { + Function *FunctionLiteral +} + +// Idx0 implements Node. +func (fs *FunctionStatement) Idx0() file.Idx { + return fs.Function.Idx0() +} + +// Idx1 implements Node. +func (fs *FunctionStatement) Idx1() file.Idx { + return fs.Function.Idx1() +} + +// expression implements Statement. +func (*FunctionStatement) statement() {} + +// IfStatement represents a if statement. +type IfStatement struct { + Test Expression + Consequent Statement + Alternate Statement + If file.Idx +} + +// Idx0 implements Node. +func (is *IfStatement) Idx0() file.Idx { + return is.If +} + +// Idx1 implements Node. +func (is *IfStatement) Idx1() file.Idx { + if is.Alternate != nil { + return is.Alternate.Idx1() } + return is.Consequent.Idx1() +} + +// expression implements Statement. +func (*IfStatement) statement() {} + +// LabelledStatement represents a labelled statement. +type LabelledStatement struct { + Statement Statement + Label *Identifier + Colon file.Idx +} + +// Idx0 implements Node. +func (ls *LabelledStatement) Idx0() file.Idx { + return ls.Label.Idx0() +} + +// Idx1 implements Node. +func (ls *LabelledStatement) Idx1() file.Idx { + return ls.Statement.Idx1() +} + +// expression implements Statement. +func (*LabelledStatement) statement() {} + +// ReturnStatement represents a return statement. +type ReturnStatement struct { + Argument Expression + Return file.Idx +} + +// Idx0 implements Node. +func (rs *ReturnStatement) Idx0() file.Idx { + return rs.Return +} - FunctionDeclaration struct { - Function *FunctionLiteral +// Idx1 implements Node. +func (rs *ReturnStatement) Idx1() file.Idx { + if rs.Argument != nil { + return rs.Argument.Idx1() } + return rs.Return + 6 +} + +// expression implements Statement. +func (*ReturnStatement) statement() {} + +// SwitchStatement represents a switch statement. +type SwitchStatement struct { + Discriminant Expression + Body []*CaseStatement + Switch file.Idx + Default int + RightBrace file.Idx +} + +// Idx0 implements Node. +func (ss *SwitchStatement) Idx0() file.Idx { + return ss.Switch +} + +// Idx1 implements Node. +func (ss *SwitchStatement) Idx1() file.Idx { + return ss.RightBrace + 1 +} + +// expression implements Statement. +func (*SwitchStatement) statement() {} + +// ThrowStatement represents a throw statement. +type ThrowStatement struct { + Argument Expression + Throw file.Idx +} + +// Idx0 implements Node. +func (ts *ThrowStatement) Idx0() file.Idx { + return ts.Throw +} + +// Idx1 implements Node. +func (ts *ThrowStatement) Idx1() file.Idx { + return ts.Argument.Idx1() +} - VariableDeclaration struct { - Var file.Idx - List []*VariableExpression +// expression implements Statement. +func (*ThrowStatement) statement() {} + +// TryStatement represents a try statement. +type TryStatement struct { + Body Statement + Finally Statement + Catch *CatchStatement + Try file.Idx +} + +// Idx0 implements Node. +func (ts *TryStatement) Idx0() file.Idx { + return ts.Try +} + +// Idx1 implements Node. +func (ts *TryStatement) Idx1() file.Idx { + if ts.Finally != nil { + return ts.Finally.Idx1() } -) + return ts.Catch.Idx1() +} -// _declarationNode +// expression implements Statement. +func (*TryStatement) statement() {} -func (*FunctionDeclaration) _declarationNode() {} -func (*VariableDeclaration) _declarationNode() {} +// VariableStatement represents a variable statement. +type VariableStatement struct { + List []Expression + Var file.Idx +} -// ==== // -// Node // -// ==== // +// Idx0 implements Node. +func (vs *VariableStatement) Idx0() file.Idx { + return vs.Var +} -type Program struct { - Body []Statement +// Idx1 implements Node. +func (vs *VariableStatement) Idx1() file.Idx { + return vs.List[len(vs.List)-1].Idx1() +} + +// expression implements Statement. +func (*VariableStatement) statement() {} +// WhileStatement represents a while statement. +type WhileStatement struct { + Test Expression + Body Statement + While file.Idx +} + +// Idx0 implements Node. +func (ws *WhileStatement) Idx0() file.Idx { + return ws.While +} + +// Idx1 implements Node. +func (ws *WhileStatement) Idx1() file.Idx { + return ws.Body.Idx1() +} + +// expression implements Statement. +func (*WhileStatement) statement() {} + +// WithStatement represents a with statement. +type WithStatement struct { + Object Expression + Body Statement + With file.Idx +} + +// Idx0 implements Node. +func (ws *WithStatement) Idx0() file.Idx { + return ws.With +} + +// Idx1 implements Node. +func (ws *WithStatement) Idx1() file.Idx { + return ws.Body.Idx1() +} + +// expression implements Statement. +func (*WithStatement) statement() {} + +// Declaration is implemented by type which represent declarations. +type Declaration interface { + declaration() +} + +// FunctionDeclaration represents a function declaration. +type FunctionDeclaration struct { + Function *FunctionLiteral +} + +func (*FunctionDeclaration) declaration() {} + +// VariableDeclaration represents a variable declaration. +type VariableDeclaration struct { + List []*VariableExpression + Var file.Idx +} + +// declaration implements Declaration. +func (*VariableDeclaration) declaration() {} + +// Program represents a full program. +type Program struct { + File *file.File + Comments CommentMap + Body []Statement DeclarationList []Declaration +} - File *file.File - - Comments CommentMap -} - -// ==== // -// Idx0 // -// ==== // - -func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket } -func (self *AssignExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *BadExpression) Idx0() file.Idx { return self.From } -func (self *BinaryExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *BooleanLiteral) Idx0() file.Idx { return self.Idx } -func (self *BracketExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() } -func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() } -func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *EmptyExpression) Idx0() file.Idx { return self.Begin } -func (self *FunctionLiteral) Idx0() file.Idx { return self.Function } -func (self *Identifier) Idx0() file.Idx { return self.Idx } -func (self *NewExpression) Idx0() file.Idx { return self.New } -func (self *NullLiteral) Idx0() file.Idx { return self.Idx } -func (self *NumberLiteral) Idx0() file.Idx { return self.Idx } -func (self *ObjectLiteral) Idx0() file.Idx { return self.LeftBrace } -func (self *RegExpLiteral) Idx0() file.Idx { return self.Idx } -func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx0() } -func (self *StringLiteral) Idx0() file.Idx { return self.Idx } -func (self *ThisExpression) Idx0() file.Idx { return self.Idx } -func (self *UnaryExpression) Idx0() file.Idx { return self.Idx } -func (self *VariableExpression) Idx0() file.Idx { return self.Idx } - -func (self *BadStatement) Idx0() file.Idx { return self.From } -func (self *BlockStatement) Idx0() file.Idx { return self.LeftBrace } -func (self *BranchStatement) Idx0() file.Idx { return self.Idx } -func (self *CaseStatement) Idx0() file.Idx { return self.Case } -func (self *CatchStatement) Idx0() file.Idx { return self.Catch } -func (self *DebuggerStatement) Idx0() file.Idx { return self.Debugger } -func (self *DoWhileStatement) Idx0() file.Idx { return self.Do } -func (self *EmptyStatement) Idx0() file.Idx { return self.Semicolon } -func (self *ExpressionStatement) Idx0() file.Idx { return self.Expression.Idx0() } -func (self *ForInStatement) Idx0() file.Idx { return self.For } -func (self *ForStatement) Idx0() file.Idx { return self.For } -func (self *FunctionStatement) Idx0() file.Idx { return self.Function.Idx0() } -func (self *IfStatement) Idx0() file.Idx { return self.If } -func (self *LabelledStatement) Idx0() file.Idx { return self.Label.Idx0() } -func (self *Program) Idx0() file.Idx { return self.Body[0].Idx0() } -func (self *ReturnStatement) Idx0() file.Idx { return self.Return } -func (self *SwitchStatement) Idx0() file.Idx { return self.Switch } -func (self *ThrowStatement) Idx0() file.Idx { return self.Throw } -func (self *TryStatement) Idx0() file.Idx { return self.Try } -func (self *VariableStatement) Idx0() file.Idx { return self.Var } -func (self *WhileStatement) Idx0() file.Idx { return self.While } -func (self *WithStatement) Idx0() file.Idx { return self.With } - -// ==== // -// Idx1 // -// ==== // - -func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket } -func (self *AssignExpression) Idx1() file.Idx { return self.Right.Idx1() } -func (self *BadExpression) Idx1() file.Idx { return self.To } -func (self *BinaryExpression) Idx1() file.Idx { return self.Right.Idx1() } -func (self *BooleanLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket + 1 } -func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() } -func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() } -func (self *EmptyExpression) Idx1() file.Idx { return self.End } -func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() } -func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) } -func (self *NewExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null" -func (self *NumberLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace } -func (self *RegExpLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *SequenceExpression) Idx1() file.Idx { return self.Sequence[0].Idx1() } -func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *ThisExpression) Idx1() file.Idx { return self.Idx + 4 } -func (self *UnaryExpression) Idx1() file.Idx { - if self.Postfix { - return self.Operand.Idx1() + 2 // ++ -- - } - return self.Operand.Idx1() +// Idx0 implements Node. +func (p *Program) Idx0() file.Idx { + return p.Body[0].Idx0() +} + +// Idx1 implements Node. +func (p *Program) Idx1() file.Idx { + return p.Body[len(p.Body)-1].Idx1() } -func (self *VariableExpression) Idx1() file.Idx { - if self.Initializer == nil { - return file.Idx(int(self.Idx) + len(self.Name) + 1) - } - return self.Initializer.Idx1() -} - -func (self *BadStatement) Idx1() file.Idx { return self.To } -func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 } -func (self *BranchStatement) Idx1() file.Idx { return self.Idx } -func (self *CaseStatement) Idx1() file.Idx { return self.Consequent[len(self.Consequent)-1].Idx1() } -func (self *CatchStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *DebuggerStatement) Idx1() file.Idx { return self.Debugger + 8 } -func (self *DoWhileStatement) Idx1() file.Idx { return self.Test.Idx1() } -func (self *EmptyStatement) Idx1() file.Idx { return self.Semicolon + 1 } -func (self *ExpressionStatement) Idx1() file.Idx { return self.Expression.Idx1() } -func (self *ForInStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *ForStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *FunctionStatement) Idx1() file.Idx { return self.Function.Idx1() } -func (self *IfStatement) Idx1() file.Idx { - if self.Alternate != nil { - return self.Alternate.Idx1() - } - return self.Consequent.Idx1() -} -func (self *LabelledStatement) Idx1() file.Idx { return self.Colon + 1 } -func (self *Program) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ReturnStatement) Idx1() file.Idx { return self.Return } -func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ThrowStatement) Idx1() file.Idx { return self.Throw } -func (self *TryStatement) Idx1() file.Idx { return self.Try } -func (self *VariableStatement) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() } -func (self *WhileStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *WithStatement) Idx1() file.Idx { return self.Body.Idx1() } diff --git a/vendor/github.com/robertkrimen/otto/ast/walk.go b/vendor/github.com/robertkrimen/otto/ast/walk.go index 7580a82b5..442293027 100644 --- a/vendor/github.com/robertkrimen/otto/ast/walk.go +++ b/vendor/github.com/robertkrimen/otto/ast/walk.go @@ -38,6 +38,7 @@ func Walk(v Visitor, n Node) { Walk(v, n.Right) } case *BadExpression: + case *BadStatement: case *BinaryExpression: if n != nil { Walk(v, n.Left) @@ -93,6 +94,7 @@ func Walk(v Visitor, n Node) { case *DotExpression: if n != nil { Walk(v, n.Left) + Walk(v, n.Identifier) } case *EmptyExpression: case *EmptyStatement: @@ -134,6 +136,7 @@ func Walk(v Visitor, n Node) { } case *LabelledStatement: if n != nil { + Walk(v, n.Label) Walk(v, n.Statement) } case *NewExpression: diff --git a/vendor/github.com/robertkrimen/otto/builtin.go b/vendor/github.com/robertkrimen/otto/builtin.go index 256ee3c55..bfb15621a 100644 --- a/vendor/github.com/robertkrimen/otto/builtin.go +++ b/vendor/github.com/robertkrimen/otto/builtin.go @@ -2,6 +2,7 @@ package otto import ( "encoding/hex" + "errors" "math" "net/url" "regexp" @@ -11,52 +12,36 @@ import ( "unicode/utf8" ) -// Global -func builtinGlobal_eval(call FunctionCall) Value { +// Global. +func builtinGlobalEval(call FunctionCall) Value { src := call.Argument(0) if !src.IsString() { return src } - runtime := call.runtime - program := runtime.cmpl_parseOrThrow(src.string(), nil) + rt := call.runtime + program := rt.cmplParseOrThrow(src.string(), nil) if !call.eval { // Not a direct call to eval, so we enter the global ExecutionContext - runtime.enterGlobalScope() - defer runtime.leaveScope() + rt.enterGlobalScope() + defer rt.leaveScope() } - returnValue := runtime.cmpl_evaluate_nodeProgram(program, true) + returnValue := rt.cmplEvaluateNodeProgram(program, true) if returnValue.isEmpty() { return Value{} } return returnValue } -func builtinGlobal_isNaN(call FunctionCall) Value { +func builtinGlobalIsNaN(call FunctionCall) Value { value := call.Argument(0).float64() - return toValue_bool(math.IsNaN(value)) + return boolValue(math.IsNaN(value)) } -func builtinGlobal_isFinite(call FunctionCall) Value { +func builtinGlobalIsFinite(call FunctionCall) Value { value := call.Argument(0).float64() - return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0)) + return boolValue(!math.IsNaN(value) && !math.IsInf(value, 0)) } -// radix 3 => 2 (ASCII 50) +47 -// radix 11 => A/a (ASCII 65/97) +54/+86 -var parseInt_alphabetTable = func() []string { - table := []string{"", "", "01"} - for radix := 3; radix <= 36; radix += 1 { - alphabet := table[radix-1] - if radix <= 10 { - alphabet += string(radix + 47) - } else { - alphabet += string(radix+54) + string(radix+86) - } - table = append(table, alphabet) - } - return table -}() - func digitValue(chr rune) int { switch { case '0' <= chr && chr <= '9': @@ -69,8 +54,8 @@ func digitValue(chr rune) int { return 36 // Larger than any legal digit value } -func builtinGlobal_parseInt(call FunctionCall) Value { - input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace) +func builtinGlobalParseInt(call FunctionCall) Value { + input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace) if len(input) == 0 { return NaNValue() } @@ -122,50 +107,51 @@ func builtinGlobal_parseInt(call FunctionCall) Value { value, err := strconv.ParseInt(input, radix, 64) if err != nil { - if err.(*strconv.NumError).Err == strconv.ErrRange { + if errors.Is(err, strconv.ErrRange) { base := float64(base) // Could just be a very large number (e.g. 0x8000000000000000) var value float64 for _, chr := range input { digit := float64(digitValue(chr)) if digit >= base { - goto error + return NaNValue() } value = value*base + digit } if negative { value *= -1 } - return toValue_float64(value) + return float64Value(value) } - error: return NaNValue() } if negative { value *= -1 } - return toValue_int64(value) + return int64Value(value) } -var parseFloat_matchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`) -var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) +var ( + parseFloatMatchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`) + parseFloatMatchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) +) -func builtinGlobal_parseFloat(call FunctionCall) Value { +func builtinGlobalParseFloat(call FunctionCall) Value { // Caveat emptor: This implementation does NOT match the specification - input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace) + input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace) - if parseFloat_matchBadSpecial.MatchString(input) { + if parseFloatMatchBadSpecial.MatchString(input) { return NaNValue() } value, err := strconv.ParseFloat(input, 64) if err != nil { for end := len(input); end > 0; end-- { - input := input[0:end] - if !parseFloat_matchValid.MatchString(input) { + val := input[0:end] + if !parseFloatMatchValid.MatchString(val) { return NaNValue() } - value, err = strconv.ParseFloat(input, 64) + value, err = strconv.ParseFloat(val, 64) if err == nil { break } @@ -174,12 +160,12 @@ func builtinGlobal_parseFloat(call FunctionCall) Value { return NaNValue() } } - return toValue_float64(value) + return float64Value(value) } // encodeURI/decodeURI -func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { +func encodeDecodeURI(call FunctionCall, escape *regexp.Regexp) Value { value := call.Argument(0) var input []uint16 switch vl := value.value.(type) { @@ -189,7 +175,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { input = utf16.Encode([]rune(value.string())) } if len(input) == 0 { - return toValue_string("") + return stringValue("") } output := []byte{} length := len(input) @@ -201,7 +187,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { panic(call.runtime.panicURIError("URI malformed")) } if value >= 0xD800 && value <= 0xDBFF { - index += 1 + index++ if index >= length { panic(call.runtime.panicURIError("URI malformed")) } @@ -212,43 +198,41 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { } decode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000} } - index += 1 + index++ size := utf8.EncodeRune(encode, decode[0]) - encode := encode[0:size] - output = append(output, encode...) - } - { - value := escape.ReplaceAllFunc(output, func(target []byte) []byte { - // Probably a better way of doing this - if target[0] == ' ' { - return []byte("%20") - } - return []byte(url.QueryEscape(string(target))) - }) - return toValue_string(string(value)) + output = append(output, encode[0:size]...) } + + bytes := escape.ReplaceAllFunc(output, func(target []byte) []byte { + // Probably a better way of doing this + if target[0] == ' ' { + return []byte("%20") + } + return []byte(url.QueryEscape(string(target))) + }) + return stringValue(string(bytes)) } -var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) +var encodeURIRegexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) -func builtinGlobal_encodeURI(call FunctionCall) Value { - return _builtinGlobal_encodeURI(call, encodeURI_Regexp) +func builtinGlobalEncodeURI(call FunctionCall) Value { + return encodeDecodeURI(call, encodeURIRegexp) } -var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`) +var encodeURIComponentRegexp = regexp.MustCompile(`([^~!*()'])`) -func builtinGlobal_encodeURIComponent(call FunctionCall) Value { - return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp) +func builtinGlobalEncodeURIComponent(call FunctionCall) Value { + return encodeDecodeURI(call, encodeURIComponentRegexp) } -// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23 -var decodeURI_guard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) +// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23. +var decodeURIGuard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) -func _decodeURI(input string, reserve bool) (string, bool) { +func decodeURI(input string, reserve bool) (string, bool) { if reserve { - input = decodeURI_guard.ReplaceAllString(input, "%25$1") + input = decodeURIGuard.ReplaceAllString(input, "%25$1") } - input = strings.Replace(input, "+", "%2B", -1) // Ugly hack to make QueryUnescape work with our use case + input = strings.ReplaceAll(input, "+", "%2B") // Ugly hack to make QueryUnescape work with our use case output, err := url.QueryUnescape(input) if err != nil || !utf8.ValidString(output) { return "", true @@ -256,25 +240,25 @@ func _decodeURI(input string, reserve bool) (string, bool) { return output, false } -func builtinGlobal_decodeURI(call FunctionCall) Value { - output, err := _decodeURI(call.Argument(0).string(), true) +func builtinGlobalDecodeURI(call FunctionCall) Value { + output, err := decodeURI(call.Argument(0).string(), true) if err { panic(call.runtime.panicURIError("URI malformed")) } - return toValue_string(output) + return stringValue(output) } -func builtinGlobal_decodeURIComponent(call FunctionCall) Value { - output, err := _decodeURI(call.Argument(0).string(), false) +func builtinGlobalDecodeURIComponent(call FunctionCall) Value { + output, err := decodeURI(call.Argument(0).string(), false) if err { panic(call.runtime.panicURIError("URI malformed")) } - return toValue_string(output) + return stringValue(output) } // escape/unescape -func builtin_shouldEscape(chr byte) bool { +func builtinShouldEscape(chr byte) bool { if 'A' <= chr && chr <= 'Z' || 'a' <= chr && chr <= 'z' || '0' <= chr && chr <= '9' { return false } @@ -283,11 +267,11 @@ func builtin_shouldEscape(chr byte) bool { const escapeBase16 = "0123456789ABCDEF" -func builtin_escape(input string) string { +func builtinEscape(input string) string { output := make([]byte, 0, len(input)) length := len(input) for index := 0; index < length; { - if builtin_shouldEscape(input[index]) { + if builtinShouldEscape(input[index]) { chr, width := utf8.DecodeRuneInString(input[index:]) chr16 := utf16.Encode([]rune{chr})[0] if 256 > chr16 { @@ -304,16 +288,15 @@ func builtin_escape(input string) string { ) } index += width - } else { output = append(output, input[index]) - index += 1 + index++ } } return string(output) } -func builtin_unescape(input string) string { +func builtinUnescape(input string) string { output := make([]rune, 0, len(input)) length := len(input) for index := 0; index < length; { @@ -340,15 +323,15 @@ func builtin_unescape(input string) string { } } output = append(output, rune(input[index])) - index += 1 + index++ } return string(output) } -func builtinGlobal_escape(call FunctionCall) Value { - return toValue_string(builtin_escape(call.Argument(0).string())) +func builtinGlobalEscape(call FunctionCall) Value { + return stringValue(builtinEscape(call.Argument(0).string())) } -func builtinGlobal_unescape(call FunctionCall) Value { - return toValue_string(builtin_unescape(call.Argument(0).string())) +func builtinGlobalUnescape(call FunctionCall) Value { + return stringValue(builtinUnescape(call.Argument(0).string())) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_array.go b/vendor/github.com/robertkrimen/otto/builtin_array.go index 56dd95ab6..c4c30e1b7 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_array.go +++ b/vendor/github.com/robertkrimen/otto/builtin_array.go @@ -8,92 +8,93 @@ import ( // Array func builtinArray(call FunctionCall) Value { - return toValue_object(builtinNewArrayNative(call.runtime, call.ArgumentList)) + return objectValue(builtinNewArrayNative(call.runtime, call.ArgumentList)) } -func builtinNewArray(self *_object, argumentList []Value) Value { - return toValue_object(builtinNewArrayNative(self.runtime, argumentList)) +func builtinNewArray(obj *object, argumentList []Value) Value { + return objectValue(builtinNewArrayNative(obj.runtime, argumentList)) } -func builtinNewArrayNative(runtime *_runtime, argumentList []Value) *_object { +func builtinNewArrayNative(rt *runtime, argumentList []Value) *object { if len(argumentList) == 1 { firstArgument := argumentList[0] if firstArgument.IsNumber() { - return runtime.newArray(arrayUint32(runtime, firstArgument)) + return rt.newArray(arrayUint32(rt, firstArgument)) } } - return runtime.newArrayOf(argumentList) + return rt.newArrayOf(argumentList) } -func builtinArray_toString(call FunctionCall) Value { +func builtinArrayToString(call FunctionCall) Value { thisObject := call.thisObject() join := thisObject.get("join") if join.isCallable() { - join := join._object() + join := join.object() return join.call(call.This, call.ArgumentList, false, nativeFrame) } - return builtinObject_toString(call) + return builtinObjectToString(call) } -func builtinArray_toLocaleString(call FunctionCall) Value { +func builtinArrayToLocaleString(call FunctionCall) Value { separator := "," thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) if length == 0 { - return toValue_string("") + return stringValue("") } stringList := make([]string, 0, length) - for index := int64(0); index < length; index += 1 { + for index := range length { value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value.kind { case valueEmpty, valueUndefined, valueNull: default: - object := call.runtime.toObject(value) - toLocaleString := object.get("toLocaleString") + obj := call.runtime.toObject(value) + toLocaleString := obj.get("toLocaleString") if !toLocaleString.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.toLocaleString index[%d] %q is not callable", index, toLocaleString)) } - stringValue = toLocaleString.call(call.runtime, toValue_object(object)).string() + stringValue = toLocaleString.call(call.runtime, objectValue(obj)).string() } stringList = append(stringList, stringValue) } - return toValue_string(strings.Join(stringList, separator)) + return stringValue(strings.Join(stringList, separator)) } -func builtinArray_concat(call FunctionCall) Value { +func builtinArrayConcat(call FunctionCall) Value { thisObject := call.thisObject() valueArray := []Value{} - source := append([]Value{toValue_object(thisObject)}, call.ArgumentList...) + source := append([]Value{objectValue(thisObject)}, call.ArgumentList...) for _, item := range source { switch item.kind { case valueObject: - object := item._object() - if isArray(object) { - length := object.get("length").number().int64 - for index := int64(0); index < length; index += 1 { + obj := item.object() + if isArray(obj) { + length := obj.get(propertyLength).number().int64 + for index := range length { name := strconv.FormatInt(index, 10) - if object.hasProperty(name) { - valueArray = append(valueArray, object.get(name)) + if obj.hasProperty(name) { + valueArray = append(valueArray, obj.get(name)) } else { valueArray = append(valueArray, Value{}) } } continue } + fallthrough default: valueArray = append(valueArray, item) } } - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } -func builtinArray_shift(call FunctionCall) Value { +func builtinArrayShift(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) - if 0 == length { - thisObject.put("length", toValue_int64(0), true) + length := int64(toUint32(thisObject.get(propertyLength))) + if length == 0 { + thisObject.put(propertyLength, int64Value(0), true) return Value{} } first := thisObject.get("0") @@ -107,52 +108,50 @@ func builtinArray_shift(call FunctionCall) Value { } } thisObject.delete(arrayIndexToString(length-1), true) - thisObject.put("length", toValue_int64(length-1), true) + thisObject.put(propertyLength, int64Value(length-1), true) return first } -func builtinArray_push(call FunctionCall) Value { +func builtinArrayPush(call FunctionCall) Value { thisObject := call.thisObject() itemList := call.ArgumentList - index := int64(toUint32(thisObject.get("length"))) + index := int64(toUint32(thisObject.get(propertyLength))) for len(itemList) > 0 { thisObject.put(arrayIndexToString(index), itemList[0], true) itemList = itemList[1:] - index += 1 + index++ } - length := toValue_int64(index) - thisObject.put("length", length, true) + length := int64Value(index) + thisObject.put(propertyLength, length, true) return length } -func builtinArray_pop(call FunctionCall) Value { +func builtinArrayPop(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) - if 0 == length { - thisObject.put("length", toValue_uint32(0), true) + length := int64(toUint32(thisObject.get(propertyLength))) + if length == 0 { + thisObject.put(propertyLength, uint32Value(0), true) return Value{} } last := thisObject.get(arrayIndexToString(length - 1)) thisObject.delete(arrayIndexToString(length-1), true) - thisObject.put("length", toValue_int64(length-1), true) + thisObject.put(propertyLength, int64Value(length-1), true) return last } -func builtinArray_join(call FunctionCall) Value { +func builtinArrayJoin(call FunctionCall) Value { separator := "," - { - argument := call.Argument(0) - if argument.IsDefined() { - separator = argument.string() - } + argument := call.Argument(0) + if argument.IsDefined() { + separator = argument.string() } thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) if length == 0 { - return toValue_string("") + return stringValue("") } stringList := make([]string, 0, length) - for index := int64(0); index < length; index += 1 { + for index := range length { value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value.kind { @@ -162,12 +161,12 @@ func builtinArray_join(call FunctionCall) Value { } stringList = append(stringList, stringValue) } - return toValue_string(strings.Join(stringList, separator)) + return stringValue(strings.Join(stringList, separator)) } -func builtinArray_splice(call FunctionCall) Value { +func builtinArraySplice(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) start := valueToRangeIndex(call.Argument(0), length, false) deleteCount := length - start @@ -176,8 +175,8 @@ func builtinArray_splice(call FunctionCall) Value { } valueArray := make([]Value, deleteCount) - for index := int64(0); index < deleteCount; index++ { - indexString := arrayIndexToString(int64(start + index)) + for index := range deleteCount { + indexString := arrayIndexToString(start + index) if thisObject.hasProperty(indexString) { valueArray[index] = thisObject.get(indexString) } @@ -197,7 +196,7 @@ func builtinArray_splice(call FunctionCall) Value { } if itemCount < deleteCount { // The Object/Array is shrinking - stop := int64(length) - deleteCount + stop := length - deleteCount // The new length of the Object/Array before // appending the itemList remainder // Stopping at the lower bound of the insertion: @@ -215,7 +214,7 @@ func builtinArray_splice(call FunctionCall) Value { // Delete off the end // We don't bother to delete below (if any) since those // will be overwritten anyway - for index := int64(length); index > (stop + itemCount); index-- { + for index := length; index > (stop + itemCount); index-- { thisObject.delete(arrayIndexToString(index-1), true) } } else if itemCount > deleteCount { @@ -226,7 +225,7 @@ func builtinArray_splice(call FunctionCall) Value { // Starting from the upper bound of the deletion: // Move an item from the after the deleted portion // to a position after the inserted portion - for index := int64(length) - deleteCount; index > start; index-- { + for index := length - deleteCount; index > start; index-- { from := arrayIndexToString(index + deleteCount - 1) to := arrayIndexToString(index + itemCount - 1) if thisObject.hasProperty(from) { @@ -237,40 +236,40 @@ func builtinArray_splice(call FunctionCall) Value { } } - for index := int64(0); index < itemCount; index++ { + for index := range itemCount { thisObject.put(arrayIndexToString(index+start), itemList[index], true) } - thisObject.put("length", toValue_int64(int64(length)+itemCount-deleteCount), true) + thisObject.put(propertyLength, int64Value(length+itemCount-deleteCount), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } -func builtinArray_slice(call FunctionCall) Value { +func builtinArraySlice(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) start, end := rangeStartEnd(call.ArgumentList, length, false) if start >= end { // Always an empty array - return toValue_object(call.runtime.newArray(0)) + return objectValue(call.runtime.newArray(0)) } sliceLength := end - start sliceValueArray := make([]Value, sliceLength) - for index := int64(0); index < sliceLength; index++ { + for index := range sliceLength { from := arrayIndexToString(index + start) if thisObject.hasProperty(from) { sliceValueArray[index] = thisObject.get(from) } } - return toValue_object(call.runtime.newArrayOf(sliceValueArray)) + return objectValue(call.runtime.newArrayOf(sliceValueArray)) } -func builtinArray_unshift(call FunctionCall) Value { +func builtinArrayUnshift(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) itemList := call.ArgumentList itemCount := int64(len(itemList)) @@ -284,18 +283,18 @@ func builtinArray_unshift(call FunctionCall) Value { } } - for index := int64(0); index < itemCount; index++ { + for index := range itemCount { thisObject.put(arrayIndexToString(index), itemList[index], true) } - newLength := toValue_int64(length + itemCount) - thisObject.put("length", newLength, true) + newLength := int64Value(length + itemCount) + thisObject.put(propertyLength, newLength, true) return newLength } -func builtinArray_reverse(call FunctionCall) Value { +func builtinArrayReverse(call FunctionCall) Value { thisObject := call.thisObject() - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) lower := struct { name string @@ -315,35 +314,34 @@ func builtinArray_reverse(call FunctionCall) Value { lower.exists = thisObject.hasProperty(lower.name) upper.exists = thisObject.hasProperty(upper.name) - if lower.exists && upper.exists { + switch { + case lower.exists && upper.exists: lowerValue := thisObject.get(lower.name) upperValue := thisObject.get(upper.name) thisObject.put(lower.name, upperValue, true) thisObject.put(upper.name, lowerValue, true) - } else if !lower.exists && upper.exists { + case !lower.exists && upper.exists: value := thisObject.get(upper.name) thisObject.delete(upper.name, true) thisObject.put(lower.name, value, true) - } else if lower.exists && !upper.exists { + case lower.exists && !upper.exists: value := thisObject.get(lower.name) thisObject.delete(lower.name, true) thisObject.put(upper.name, value, true) - } else { - // Nothing happens. } - lower.index += 1 + lower.index++ } return call.This } -func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int { +func sortCompare(thisObject *object, index0, index1 uint, compare *object) int { j := struct { name string + value string exists bool defined bool - value string }{} k := j j.name = arrayIndexToString(int64(index0)) @@ -351,11 +349,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int k.name = arrayIndexToString(int64(index1)) k.exists = thisObject.hasProperty(k.name) - if !j.exists && !k.exists { + switch { + case !j.exists && !k.exists: return 0 - } else if !j.exists { + case !j.exists: return 1 - } else if !k.exists { + case !k.exists: return -1 } @@ -364,11 +363,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int j.defined = x.IsDefined() k.defined = y.IsDefined() - if !j.defined && !k.defined { + switch { + case !j.defined && !k.defined: return 0 - } else if !j.defined { + case !j.defined: return 1 - } else if !k.defined { + case !k.defined: return -1 } @@ -385,11 +385,10 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int return 1 } - return int(toInt32(compare.call(Value{}, []Value{x, y}, false, nativeFrame))) + return toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame)) } -func arraySortSwap(thisObject *_object, index0, index1 uint) { - +func arraySortSwap(thisObject *object, index0, index1 uint) { j := struct { name string exists bool @@ -401,25 +400,24 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) { k.name = arrayIndexToString(int64(index1)) k.exists = thisObject.hasProperty(k.name) - if j.exists && k.exists { - jValue := thisObject.get(j.name) - kValue := thisObject.get(k.name) - thisObject.put(j.name, kValue, true) - thisObject.put(k.name, jValue, true) - } else if !j.exists && k.exists { + switch { + case j.exists && k.exists: + jv := thisObject.get(j.name) + kv := thisObject.get(k.name) + thisObject.put(j.name, kv, true) + thisObject.put(k.name, jv, true) + case !j.exists && k.exists: value := thisObject.get(k.name) thisObject.delete(k.name, true) thisObject.put(j.name, value, true) - } else if j.exists && !k.exists { + case j.exists && !k.exists: value := thisObject.get(j.name) thisObject.delete(j.name, true) thisObject.put(k.name, value, true) - } else { - // Nothing happens. } } -func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compare *_object) (uint, uint) { +func arraySortQuickPartition(thisObject *object, left, right, pivot uint, compare *object) (uint, uint) { arraySortSwap(thisObject, pivot, right) // Right is now the pivot value cursor := left cursor2 := left @@ -430,18 +428,18 @@ func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compa if cursor < cursor2 { arraySortSwap(thisObject, index, cursor2) } - cursor += 1 - cursor2 += 1 + cursor++ + cursor2++ } else if comparison == 0 { arraySortSwap(thisObject, index, cursor2) - cursor2 += 1 + cursor2++ } } arraySortSwap(thisObject, cursor2, right) return cursor, cursor2 } -func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) { +func arraySortQuickSort(thisObject *object, left, right uint, compare *object) { if left < right { middle := left + (right-left)/2 pivot, pivot2 := arraySortQuickPartition(thisObject, left, right, middle, compare) @@ -452,14 +450,14 @@ func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) } } -func builtinArray_sort(call FunctionCall) Value { +func builtinArraySort(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUint32(thisObject.get("length"))) + length := uint(toUint32(thisObject.get(propertyLength))) compareValue := call.Argument(0) - compare := compareValue._object() + compare := compareValue.object() if compareValue.IsUndefined() { } else if !compareValue.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.sort value %q is not callable", compareValue)) } if length > 1 { arraySortQuickSort(thisObject, 0, length-1, compare) @@ -467,13 +465,13 @@ func builtinArray_sort(call FunctionCall) Value { return call.This } -func builtinArray_isArray(call FunctionCall) Value { - return toValue_bool(isArray(call.Argument(0)._object())) +func builtinArrayIsArray(call FunctionCall) Value { + return boolValue(isArray(call.Argument(0).object())) } -func builtinArray_indexOf(call FunctionCall) Value { +func builtinArrayIndexOf(call FunctionCall) Value { thisObject, matchValue := call.thisObject(), call.Argument(0) - if length := int64(toUint32(thisObject.get("length"))); length > 0 { + if length := int64(toUint32(thisObject.get(propertyLength))); length > 0 { index := int64(0) if len(call.ArgumentList) > 1 { index = call.Argument(1).number().int64 @@ -486,22 +484,22 @@ func builtinArray_indexOf(call FunctionCall) Value { index = -1 } for ; index >= 0 && index < length; index++ { - name := arrayIndexToString(int64(index)) + name := arrayIndexToString(index) if !thisObject.hasProperty(name) { continue } value := thisObject.get(name) if strictEqualityComparison(matchValue, value) { - return toValue_uint32(uint32(index)) + return uint32Value(uint32(index)) } } } - return toValue_int(-1) + return intValue(-1) } -func builtinArray_lastIndexOf(call FunctionCall) Value { +func builtinArrayLastIndexOf(call FunctionCall) Value { thisObject, matchValue := call.thisObject(), call.Argument(0) - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) index := length - 1 if len(call.ArgumentList) > 1 { index = call.Argument(1).number().int64 @@ -512,30 +510,30 @@ func builtinArray_lastIndexOf(call FunctionCall) Value { if index > length { index = length - 1 } else if 0 > index { - return toValue_int(-1) + return intValue(-1) } for ; index >= 0; index-- { - name := arrayIndexToString(int64(index)) + name := arrayIndexToString(index) if !thisObject.hasProperty(name) { continue } value := thisObject.get(name) if strictEqualityComparison(matchValue, value) { - return toValue_uint32(uint32(index)) + return uint32Value(uint32(index)) } } - return toValue_int(-1) + return intValue(-1) } -func builtinArray_every(call FunctionCall) Value { +func builtinArrayEvery(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() { continue } return falseValue @@ -543,70 +541,70 @@ func builtinArray_every(call FunctionCall) Value { } return trueValue } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.every argument %q is not callable", call.Argument(0))) } -func builtinArray_some(call FunctionCall) Value { +func builtinArraySome(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() { return trueValue } } } return falseValue } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.some %q if not callable", call.Argument(0))) } -func builtinArray_forEach(call FunctionCall) Value { +func builtinArrayForEach(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - iterator.call(call.runtime, callThis, thisObject.get(key), toValue_int64(index), this) + iterator.call(call.runtime, callThis, thisObject.get(key), int64Value(index), this) } } return Value{} } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.foreach %q if not callable", call.Argument(0))) } -func builtinArray_map(call FunctionCall) Value { +func builtinArrayMap(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) values := make([]Value, length) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { values[index] = iterator.call(call.runtime, callThis, thisObject.get(key), index, this) } else { values[index] = Value{} } } - return toValue_object(call.runtime.newArrayOf(values)) + return objectValue(call.runtime.newArrayOf(values)) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.foreach %q if not callable", call.Argument(0))) } -func builtinArray_filter(call FunctionCall) Value { +func builtinArrayFilter(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) values := make([]Value, 0) - for index := int64(0); index < length; index++ { + for index := range length { if key := arrayIndexToString(index); thisObject.hasProperty(key) { value := thisObject.get(key) if iterator.call(call.runtime, callThis, value, index, this).bool() { @@ -614,18 +612,18 @@ func builtinArray_filter(call FunctionCall) Value { } } } - return toValue_object(call.runtime.newArrayOf(values)) + return objectValue(call.runtime.newArrayOf(values)) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.filter %q if not callable", call.Argument(0))) } -func builtinArray_reduce(call FunctionCall) Value { +func builtinArrayReduce(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { initial := len(call.ArgumentList) > 1 start := call.Argument(1) - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) index := int64(0) if length > 0 || initial { var accumulator Value @@ -634,6 +632,7 @@ func builtinArray_reduce(call FunctionCall) Value { if key := arrayIndexToString(index); thisObject.hasProperty(key) { accumulator = thisObject.get(key) index++ + break } } @@ -642,22 +641,22 @@ func builtinArray_reduce(call FunctionCall) Value { } for ; index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - accumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), key, this) + accumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), index, this) } } return accumulator } } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.reduce %q if not callable", call.Argument(0))) } -func builtinArray_reduceRight(call FunctionCall) Value { +func builtinArrayReduceRight(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { initial := len(call.ArgumentList) > 1 start := call.Argument(1) - length := int64(toUint32(thisObject.get("length"))) + length := int64(toUint32(thisObject.get(propertyLength))) if length > 0 || initial { index := length - 1 var accumulator Value @@ -680,5 +679,5 @@ func builtinArray_reduceRight(call FunctionCall) Value { return accumulator } } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Array.reduceRight %q if not callable", call.Argument(0))) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_boolean.go b/vendor/github.com/robertkrimen/otto/builtin_boolean.go index 59b8e789b..54f02028f 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_boolean.go +++ b/vendor/github.com/robertkrimen/otto/builtin_boolean.go @@ -3,26 +3,26 @@ package otto // Boolean func builtinBoolean(call FunctionCall) Value { - return toValue_bool(call.Argument(0).bool()) + return boolValue(call.Argument(0).bool()) } -func builtinNewBoolean(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) +func builtinNewBoolean(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) } -func builtinBoolean_toString(call FunctionCall) Value { +func builtinBooleanToString(call FunctionCall) Value { value := call.This if !value.IsBoolean() { // Will throw a TypeError if ThisObject is not a Boolean - value = call.thisClassObject("Boolean").primitiveValue() + value = call.thisClassObject(classBooleanName).primitiveValue() } - return toValue_string(value.string()) + return stringValue(value.string()) } -func builtinBoolean_valueOf(call FunctionCall) Value { +func builtinBooleanValueOf(call FunctionCall) Value { value := call.This if !value.IsBoolean() { - value = call.thisClassObject("Boolean").primitiveValue() + value = call.thisClassObject(classBooleanName).primitiveValue() } return value } diff --git a/vendor/github.com/robertkrimen/otto/builtin_date.go b/vendor/github.com/robertkrimen/otto/builtin_date.go index f20bf8e3f..01822edaf 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_date.go +++ b/vendor/github.com/robertkrimen/otto/builtin_date.go @@ -2,114 +2,118 @@ package otto import ( "math" - Time "time" + "time" ) // Date const ( // TODO Be like V8? - // builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)" - builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" - builtinDate_goDateLayout = "Mon, 02 Jan 2006" - builtinDate_goTimeLayout = "15:04:05 MST" + // builtinDateDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)". + builtinDateDateTimeLayout = time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" + builtinDateDateLayout = "Mon, 02 Jan 2006" + builtinDateTimeLayout = "15:04:05 MST" ) +// utcTimeZone is the time zone used for UTC calculations. +// It is GMT not UTC as that's what Javascript does because toUTCString is +// actually an alias to toGMTString. +var utcTimeZone = time.FixedZone("GMT", 0) + func builtinDate(call FunctionCall) Value { - date := &_dateObject{} - date.Set(newDateTime([]Value{}, Time.Local)) - return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) + date := &dateObject{} + date.Set(newDateTime([]Value{}, time.Local)) //nolint:gosmopolitan + return stringValue(date.Time().Format(builtinDateDateTimeLayout)) } -func builtinNewDate(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local))) +func builtinNewDate(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newDate(newDateTime(argumentList, time.Local))) //nolint:gosmopolitan } -func builtinDate_toString(call FunctionCall) Value { +func builtinDateToString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().Local().Format(builtinDateDateTimeLayout)) //nolint:gosmopolitan } -func builtinDate_toDateString(call FunctionCall) Value { +func builtinDateToDateString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goDateLayout)) + return stringValue(date.Time().Local().Format(builtinDateDateLayout)) //nolint:gosmopolitan } -func builtinDate_toTimeString(call FunctionCall) Value { +func builtinDateToTimeString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goTimeLayout)) + return stringValue(date.Time().Local().Format(builtinDateTimeLayout)) //nolint:gosmopolitan } -func builtinDate_toUTCString(call FunctionCall) Value { +func builtinDateToUTCString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().In(utcTimeZone).Format(builtinDateDateTimeLayout)) } -func builtinDate_toISOString(call FunctionCall) Value { +func builtinDateToISOString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format("2006-01-02T15:04:05.000Z")) + return stringValue(date.Time().Format("2006-01-02T15:04:05.000Z")) } -func builtinDate_toJSON(call FunctionCall) Value { - object := call.thisObject() - value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue - { // FIXME value.isFinite - value := value.float64() - if math.IsNaN(value) || math.IsInf(value, 0) { - return nullValue - } +func builtinDateToJSON(call FunctionCall) Value { + obj := call.thisObject() + value := obj.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue + // FIXME fv.isFinite + if fv := value.float64(); math.IsNaN(fv) || math.IsInf(fv, 0) { + return nullValue } - toISOString := object.get("toISOString") + + toISOString := obj.get("toISOString") if !toISOString.isCallable() { // FIXME - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Date.toJSON toISOString %q is not callable", toISOString)) } - return toISOString.call(call.runtime, toValue_object(object), []Value{}) + return toISOString.call(call.runtime, objectValue(obj), []Value{}) } -func builtinDate_toGMTString(call FunctionCall) Value { +func builtinDateToGMTString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) + return stringValue(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) } -func builtinDate_getTime(call FunctionCall) Value { +func builtinDateGetTime(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } // We do this (convert away from a float) so the user // does not get something back in exponential notation - return toValue_int64(int64(date.Epoch())) + return int64Value(date.Epoch()) } -func builtinDate_setTime(call FunctionCall) Value { - object := call.thisObject() +func builtinDateSetTime(call FunctionCall) Value { + obj := call.thisObject() date := dateObjectOf(call.runtime, call.thisObject()) date.Set(call.Argument(0).float64()) - object.value = date + obj.value = date return date.Value() } -func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) { - object := call.thisObject() +func builtinDateBeforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*object, *dateObject, *ecmaTime, []int) { + obj := call.thisObject() date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return nil, nil, nil, nil @@ -120,72 +124,72 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool } if argumentLimit == 0 { - object.value = invalidDateObject + obj.value = invalidDateObject return nil, nil, nil, nil } valueList := make([]int, argumentLimit) - for index := 0; index < argumentLimit; index++ { + for index := range argumentLimit { value := call.ArgumentList[index] nm := value.number() switch nm.kind { case numberInteger, numberFloat: default: - object.value = invalidDateObject + obj.value = invalidDateObject return nil, nil, nil, nil } valueList[index] = int(nm.int64) } baseTime := date.Time() if timeLocal { - baseTime = baseTime.Local() + baseTime = baseTime.Local() //nolint:gosmopolitan } - ecmaTime := ecmaTime(baseTime) - return object, &date, &ecmaTime, valueList + ecmaTime := newEcmaTime(baseTime) + return obj, &date, &ecmaTime, valueList } -func builtinDate_parse(call FunctionCall) Value { +func builtinDateParse(call FunctionCall) Value { date := call.Argument(0).string() - return toValue_float64(dateParse(date)) + return float64Value(dateParse(date)) } -func builtinDate_UTC(call FunctionCall) Value { - return toValue_float64(newDateTime(call.ArgumentList, Time.UTC)) +func builtinDateUTC(call FunctionCall) Value { + return float64Value(newDateTime(call.ArgumentList, time.UTC)) } -func builtinDate_now(call FunctionCall) Value { +func builtinDateNow(call FunctionCall) Value { call.ArgumentList = []Value(nil) - return builtinDate_UTC(call) + return builtinDateUTC(call) } -// This is a placeholder -func builtinDate_toLocaleString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("2006-01-02 15:04:05")) + return stringValue(date.Time().Local().Format("2006-01-02 15:04:05")) //nolint:gosmopolitan } -// This is a placeholder -func builtinDate_toLocaleDateString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleDateString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("2006-01-02")) + return stringValue(date.Time().Local().Format("2006-01-02")) //nolint:gosmopolitan } -// This is a placeholder -func builtinDate_toLocaleTimeString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleTimeString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("15:04:05")) + return stringValue(date.Time().Local().Format("15:04:05")) //nolint:gosmopolitan } -func builtinDate_valueOf(call FunctionCall) Value { +func builtinDateValueOf(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() @@ -193,155 +197,155 @@ func builtinDate_valueOf(call FunctionCall) Value { return date.Value() } -func builtinDate_getYear(call FunctionCall) Value { +func builtinDateGetYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Year() - 1900) + return intValue(date.Time().Local().Year() - 1900) //nolint:gosmopolitan } -func builtinDate_getFullYear(call FunctionCall) Value { +func builtinDateGetFullYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Year()) + return intValue(date.Time().Local().Year()) //nolint:gosmopolitan } -func builtinDate_getUTCFullYear(call FunctionCall) Value { +func builtinDateGetUTCFullYear(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Year()) + return intValue(date.Time().Year()) } -func builtinDate_getMonth(call FunctionCall) Value { +func builtinDateGetMonth(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoMonth(date.Time().Local().Month())) + return intValue(dateFromGoMonth(date.Time().Local().Month())) //nolint:gosmopolitan } -func builtinDate_getUTCMonth(call FunctionCall) Value { +func builtinDateGetUTCMonth(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoMonth(date.Time().Month())) + return intValue(dateFromGoMonth(date.Time().Month())) } -func builtinDate_getDate(call FunctionCall) Value { +func builtinDateGetDate(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Day()) + return intValue(date.Time().Local().Day()) //nolint:gosmopolitan } -func builtinDate_getUTCDate(call FunctionCall) Value { +func builtinDateGetUTCDate(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Day()) + return intValue(date.Time().Day()) } -func builtinDate_getDay(call FunctionCall) Value { +func builtinDateGetDay(call FunctionCall) Value { // Actually day of the week date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoDay(date.Time().Local().Weekday())) + return intValue(dateFromGoDay(date.Time().Local().Weekday())) //nolint:gosmopolitan } -func builtinDate_getUTCDay(call FunctionCall) Value { +func builtinDateGetUTCDay(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoDay(date.Time().Weekday())) + return intValue(dateFromGoDay(date.Time().Weekday())) } -func builtinDate_getHours(call FunctionCall) Value { +func builtinDateGetHours(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Hour()) + return intValue(date.Time().Local().Hour()) //nolint:gosmopolitan } -func builtinDate_getUTCHours(call FunctionCall) Value { +func builtinDateGetUTCHours(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Hour()) + return intValue(date.Time().Hour()) } -func builtinDate_getMinutes(call FunctionCall) Value { +func builtinDateGetMinutes(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Minute()) + return intValue(date.Time().Local().Minute()) //nolint:gosmopolitan } -func builtinDate_getUTCMinutes(call FunctionCall) Value { +func builtinDateGetUTCMinutes(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Minute()) + return intValue(date.Time().Minute()) } -func builtinDate_getSeconds(call FunctionCall) Value { +func builtinDateGetSeconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Second()) + return intValue(date.Time().Local().Second()) //nolint:gosmopolitan } -func builtinDate_getUTCSeconds(call FunctionCall) Value { +func builtinDateGetUTCSeconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Second()) + return intValue(date.Time().Second()) } -func builtinDate_getMilliseconds(call FunctionCall) Value { +func builtinDateGetMilliseconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Nanosecond() / (100 * 100 * 100)) + return intValue(date.Time().Local().Nanosecond() / (100 * 100 * 100)) //nolint:gosmopolitan } -func builtinDate_getUTCMilliseconds(call FunctionCall) Value { +func builtinDateGetUTCMilliseconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Nanosecond() / (100 * 100 * 100)) + return intValue(date.Time().Nanosecond() / (100 * 100 * 100)) } -func builtinDate_getTimezoneOffset(call FunctionCall) Value { +func builtinDateGetTimezoneOffset(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - timeLocal := date.Time().Local() + timeLocal := date.Time().Local() //nolint:gosmopolitan // Is this kosher? - timeLocalAsUTC := Time.Date( + timeLocalAsUTC := time.Date( timeLocal.Year(), timeLocal.Month(), timeLocal.Day(), @@ -349,13 +353,13 @@ func builtinDate_getTimezoneOffset(call FunctionCall) Value { timeLocal.Minute(), timeLocal.Second(), timeLocal.Nanosecond(), - Time.UTC, + time.UTC, ) - return toValue_float64(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) + return float64Value(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) } -func builtinDate_setMilliseconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetMilliseconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -363,12 +367,12 @@ func builtinDate_setMilliseconds(call FunctionCall) Value { ecmaTime.millisecond = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMilliseconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) +func builtinDateSetUTCMilliseconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false) if ecmaTime == nil { return NaNValue() } @@ -376,12 +380,12 @@ func builtinDate_setUTCMilliseconds(call FunctionCall) Value { ecmaTime.millisecond = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setSeconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) +func builtinDateSetSeconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true) if ecmaTime == nil { return NaNValue() } @@ -392,12 +396,12 @@ func builtinDate_setSeconds(call FunctionCall) Value { ecmaTime.second = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCSeconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) +func builtinDateSetUTCSeconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false) if ecmaTime == nil { return NaNValue() } @@ -408,12 +412,12 @@ func builtinDate_setUTCSeconds(call FunctionCall) Value { ecmaTime.second = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setMinutes(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) +func builtinDateSetMinutes(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true) if ecmaTime == nil { return NaNValue() } @@ -427,12 +431,12 @@ func builtinDate_setMinutes(call FunctionCall) Value { ecmaTime.minute = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMinutes(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) +func builtinDateSetUTCMinutes(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false) if ecmaTime == nil { return NaNValue() } @@ -446,58 +450,58 @@ func builtinDate_setUTCMinutes(call FunctionCall) Value { ecmaTime.minute = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setHours(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true) +func builtinDateSetHours(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, true) if ecmaTime == nil { return NaNValue() } - if len(value) > 3 { + switch { + case len(value) > 3: ecmaTime.millisecond = value[3] + fallthrough + case len(value) > 2: ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 2 { - ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 1 { + fallthrough + case len(value) > 1: ecmaTime.minute = value[1] } ecmaTime.hour = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCHours(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false) +func builtinDateSetUTCHours(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, false) if ecmaTime == nil { return NaNValue() } - if len(value) > 3 { + switch { + case len(value) > 3: ecmaTime.millisecond = value[3] + fallthrough + case len(value) > 2: ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 2 { - ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 1 { + fallthrough + case len(value) > 1: ecmaTime.minute = value[1] } ecmaTime.hour = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setDate(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetDate(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -505,12 +509,12 @@ func builtinDate_setDate(call FunctionCall) Value { ecmaTime.day = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCDate(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) +func builtinDateSetUTCDate(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false) if ecmaTime == nil { return NaNValue() } @@ -518,12 +522,12 @@ func builtinDate_setUTCDate(call FunctionCall) Value { ecmaTime.day = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setMonth(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) +func builtinDateSetMonth(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true) if ecmaTime == nil { return NaNValue() } @@ -534,12 +538,12 @@ func builtinDate_setMonth(call FunctionCall) Value { ecmaTime.month = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMonth(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) +func builtinDateSetUTCMonth(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false) if ecmaTime == nil { return NaNValue() } @@ -550,12 +554,12 @@ func builtinDate_setUTCMonth(call FunctionCall) Value { ecmaTime.month = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -567,12 +571,12 @@ func builtinDate_setYear(call FunctionCall) Value { ecmaTime.year = year date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setFullYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) +func builtinDateSetFullYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true) if ecmaTime == nil { return NaNValue() } @@ -586,12 +590,12 @@ func builtinDate_setFullYear(call FunctionCall) Value { ecmaTime.year = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCFullYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) +func builtinDateSetUTCFullYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false) if ecmaTime == nil { return NaNValue() } @@ -605,7 +609,7 @@ func builtinDate_setUTCFullYear(call FunctionCall) Value { ecmaTime.year = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } diff --git a/vendor/github.com/robertkrimen/otto/builtin_error.go b/vendor/github.com/robertkrimen/otto/builtin_error.go index 41da84ef2..9d524f548 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_error.go +++ b/vendor/github.com/robertkrimen/otto/builtin_error.go @@ -5,20 +5,20 @@ import ( ) func builtinError(call FunctionCall) Value { - return toValue_object(call.runtime.newError("Error", call.Argument(0), 1)) + return objectValue(call.runtime.newError(classErrorName, call.Argument(0), 1)) } -func builtinNewError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newError("Error", valueOfArrayIndex(argumentList, 0), 0)) +func builtinNewError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newError(classErrorName, valueOfArrayIndex(argumentList, 0), 0)) } -func builtinError_toString(call FunctionCall) Value { +func builtinErrorToString(call FunctionCall) Value { thisObject := call.thisObject() if thisObject == nil { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Error.toString is nil")) } - name := "Error" + name := classErrorName nameValue := thisObject.get("name") if nameValue.IsDefined() { name = nameValue.string() @@ -31,96 +31,96 @@ func builtinError_toString(call FunctionCall) Value { } if len(name) == 0 { - return toValue_string(message) + return stringValue(message) } if len(message) == 0 { - return toValue_string(name) + return stringValue(name) } - return toValue_string(fmt.Sprintf("%s: %s", name, message)) + return stringValue(fmt.Sprintf("%s: %s", name, message)) } -func (runtime *_runtime) newEvalError(message Value) *_object { - self := runtime.newErrorObject("EvalError", message, 0) - self.prototype = runtime.global.EvalErrorPrototype - return self +func (rt *runtime) newEvalError(message Value) *object { + o := rt.newErrorObject("EvalError", message, 0) + o.prototype = rt.global.EvalErrorPrototype + return o } func builtinEvalError(call FunctionCall) Value { - return toValue_object(call.runtime.newEvalError(call.Argument(0))) + return objectValue(call.runtime.newEvalError(call.Argument(0))) } -func builtinNewEvalError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) +func builtinNewEvalError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newTypeError(message Value) *_object { - self := runtime.newErrorObject("TypeError", message, 0) - self.prototype = runtime.global.TypeErrorPrototype - return self +func (rt *runtime) newTypeError(message Value) *object { + o := rt.newErrorObject("TypeError", message, 0) + o.prototype = rt.global.TypeErrorPrototype + return o } func builtinTypeError(call FunctionCall) Value { - return toValue_object(call.runtime.newTypeError(call.Argument(0))) + return objectValue(call.runtime.newTypeError(call.Argument(0))) } -func builtinNewTypeError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) +func builtinNewTypeError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newRangeError(message Value) *_object { - self := runtime.newErrorObject("RangeError", message, 0) - self.prototype = runtime.global.RangeErrorPrototype - return self +func (rt *runtime) newRangeError(message Value) *object { + o := rt.newErrorObject("RangeError", message, 0) + o.prototype = rt.global.RangeErrorPrototype + return o } func builtinRangeError(call FunctionCall) Value { - return toValue_object(call.runtime.newRangeError(call.Argument(0))) + return objectValue(call.runtime.newRangeError(call.Argument(0))) } -func builtinNewRangeError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) +func builtinNewRangeError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newURIError(message Value) *_object { - self := runtime.newErrorObject("URIError", message, 0) - self.prototype = runtime.global.URIErrorPrototype - return self +func (rt *runtime) newURIError(message Value) *object { + o := rt.newErrorObject("URIError", message, 0) + o.prototype = rt.global.URIErrorPrototype + return o } -func (runtime *_runtime) newReferenceError(message Value) *_object { - self := runtime.newErrorObject("ReferenceError", message, 0) - self.prototype = runtime.global.ReferenceErrorPrototype - return self +func (rt *runtime) newReferenceError(message Value) *object { + o := rt.newErrorObject("ReferenceError", message, 0) + o.prototype = rt.global.ReferenceErrorPrototype + return o } func builtinReferenceError(call FunctionCall) Value { - return toValue_object(call.runtime.newReferenceError(call.Argument(0))) + return objectValue(call.runtime.newReferenceError(call.Argument(0))) } -func builtinNewReferenceError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) +func builtinNewReferenceError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newSyntaxError(message Value) *_object { - self := runtime.newErrorObject("SyntaxError", message, 0) - self.prototype = runtime.global.SyntaxErrorPrototype - return self +func (rt *runtime) newSyntaxError(message Value) *object { + o := rt.newErrorObject("SyntaxError", message, 0) + o.prototype = rt.global.SyntaxErrorPrototype + return o } func builtinSyntaxError(call FunctionCall) Value { - return toValue_object(call.runtime.newSyntaxError(call.Argument(0))) + return objectValue(call.runtime.newSyntaxError(call.Argument(0))) } -func builtinNewSyntaxError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) +func builtinNewSyntaxError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) } func builtinURIError(call FunctionCall) Value { - return toValue_object(call.runtime.newURIError(call.Argument(0))) + return objectValue(call.runtime.newURIError(call.Argument(0))) } -func builtinNewURIError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) +func builtinNewURIError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_function.go b/vendor/github.com/robertkrimen/otto/builtin_function.go index 3d07566c6..4149ce4f2 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_function.go +++ b/vendor/github.com/robertkrimen/otto/builtin_function.go @@ -2,7 +2,6 @@ package otto import ( "fmt" - "regexp" "strings" "unicode" @@ -12,11 +11,11 @@ import ( // Function func builtinFunction(call FunctionCall) Value { - return toValue_object(builtinNewFunctionNative(call.runtime, call.ArgumentList)) + return objectValue(builtinNewFunctionNative(call.runtime, call.ArgumentList)) } -func builtinNewFunction(self *_object, argumentList []Value) Value { - return toValue_object(builtinNewFunctionNative(self.runtime, argumentList)) +func builtinNewFunction(obj *object, argumentList []Value) Value { + return objectValue(builtinNewFunctionNative(obj.runtime, argumentList)) } func argumentList2parameterList(argumentList []Value) []string { @@ -30,12 +29,9 @@ func argumentList2parameterList(argumentList []Value) []string { return parameterList } -var matchIdentifier = regexp.MustCompile(`^[$_\p{L}][$_\p{L}\d}]*$`) - -func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object { +func builtinNewFunctionNative(rt *runtime, argumentList []Value) *object { var parameterList, body string - count := len(argumentList) - if count > 0 { + if count := len(argumentList); count > 0 { tmp := make([]string, 0, count-1) for _, value := range argumentList[0 : count-1] { tmp = append(tmp, value.string()) @@ -46,35 +42,35 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object // FIXME function, err := parser.ParseFunction(parameterList, body) - runtime.parseThrow(err) // Will panic/throw appropriately - cmpl := _compiler{} - cmpl_function := cmpl.parseExpression(function) + rt.parseThrow(err) // Will panic/throw appropriately + cmpl := compiler{} + cmplFunction := cmpl.parseExpression(function) - return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.globalStash) + return rt.newNodeFunction(cmplFunction.(*nodeFunctionLiteral), rt.globalStash) } -func builtinFunction_toString(call FunctionCall) Value { - object := call.thisClassObject("Function") // Should throw a TypeError unless Function - switch fn := object.value.(type) { - case _nativeFunctionObject: - return toValue_string(fmt.Sprintf("function %s() { [native code] }", fn.name)) - case _nodeFunctionObject: - return toValue_string(fn.node.source) - case _bindFunctionObject: - return toValue_string("function () { [native code] }") +func builtinFunctionToString(call FunctionCall) Value { + obj := call.thisClassObject(classFunctionName) // Should throw a TypeError unless Function + switch fn := obj.value.(type) { + case nativeFunctionObject: + return stringValue(fmt.Sprintf("function %s() { [native code] }", fn.name)) + case nodeFunctionObject: + return stringValue(fn.node.source) + case bindFunctionObject: + return stringValue("function () { [native code] }") + default: + panic(call.runtime.panicTypeError("Function.toString unknown type %T", obj.value)) } - - panic(call.runtime.panicTypeError("Function.toString()")) } -func builtinFunction_apply(call FunctionCall) Value { +func builtinFunctionApply(call FunctionCall) Value { if !call.This.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.apply %q is not callable", call.This)) } this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } argumentList := call.Argument(1) switch argumentList.kind { @@ -82,28 +78,28 @@ func builtinFunction_apply(call FunctionCall) Value { return call.thisObject().call(this, nil, false, nativeFrame) case valueObject: default: - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.apply unknown type %T for second argument")) } - arrayObject := argumentList._object() + arrayObject := argumentList.object() thisObject := call.thisObject() - length := int64(toUint32(arrayObject.get("length"))) + length := int64(toUint32(arrayObject.get(propertyLength))) valueArray := make([]Value, length) - for index := int64(0); index < length; index++ { + for index := range length { valueArray[index] = arrayObject.get(arrayIndexToString(index)) } return thisObject.call(this, valueArray, false, nativeFrame) } -func builtinFunction_call(call FunctionCall) Value { +func builtinFunctionCall(call FunctionCall) Value { if !call.This.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.call %q is not callable", call.This)) } thisObject := call.thisObject() this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } if len(call.ArgumentList) >= 1 { return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame) @@ -111,19 +107,19 @@ func builtinFunction_call(call FunctionCall) Value { return thisObject.call(this, nil, false, nativeFrame) } -func builtinFunction_bind(call FunctionCall) Value { +func builtinFunctionBind(call FunctionCall) Value { target := call.This if !target.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Function.bind %q is not callable", call.This)) } - targetObject := target._object() + targetObject := target.object() this := call.Argument(0) argumentList := call.slice(1) if this.IsUndefined() { // FIXME Do this elsewhere? - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } - return toValue_object(call.runtime.newBoundFunction(targetObject, this, argumentList)) + return objectValue(call.runtime.newBoundFunction(targetObject, this, argumentList)) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_json.go b/vendor/github.com/robertkrimen/otto/builtin_json.go index aed54bf12..f66315d85 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_json.go +++ b/vendor/github.com/robertkrimen/otto/builtin_json.go @@ -7,13 +7,13 @@ import ( "strings" ) -type _builtinJSON_parseContext struct { - call FunctionCall +type builtinJSONParseContext struct { reviver Value + call FunctionCall } -func builtinJSON_parse(call FunctionCall) Value { - ctx := _builtinJSON_parseContext{ +func builtinJSONParse(call FunctionCall) Value { + ctx := builtinJSONParseContext{ call: call, } revive := false @@ -27,109 +27,107 @@ func builtinJSON_parse(call FunctionCall) Value { if err != nil { panic(call.runtime.panicSyntaxError(err.Error())) } - value, exists := builtinJSON_parseWalk(ctx, root) + value, exists := builtinJSONParseWalk(ctx, root) if !exists { value = Value{} } if revive { root := ctx.call.runtime.newObject() root.put("", value, false) - return builtinJSON_reviveWalk(ctx, root, "") + return builtinJSONReviveWalk(ctx, root, "") } return value } -func builtinJSON_reviveWalk(ctx _builtinJSON_parseContext, holder *_object, name string) Value { +func builtinJSONReviveWalk(ctx builtinJSONParseContext, holder *object, name string) Value { value := holder.get(name) - if object := value._object(); object != nil { - if isArray(object) { - length := int64(objectLength(object)) - for index := int64(0); index < length; index += 1 { - name := arrayIndexToString(index) - value := builtinJSON_reviveWalk(ctx, object, name) - if value.IsUndefined() { - object.delete(name, false) + if obj := value.object(); obj != nil { + if isArray(obj) { + length := int64(objectLength(obj)) + for index := range length { + idxName := arrayIndexToString(index) + idxValue := builtinJSONReviveWalk(ctx, obj, idxName) + if idxValue.IsUndefined() { + obj.delete(idxName, false) } else { - object.defineProperty(name, value, 0111, false) + obj.defineProperty(idxName, idxValue, 0o111, false) } } } else { - object.enumerate(false, func(name string) bool { - value := builtinJSON_reviveWalk(ctx, object, name) - if value.IsUndefined() { - object.delete(name, false) + obj.enumerate(false, func(name string) bool { + enumVal := builtinJSONReviveWalk(ctx, obj, name) + if enumVal.IsUndefined() { + obj.delete(name, false) } else { - object.defineProperty(name, value, 0111, false) + obj.defineProperty(name, enumVal, 0o111, false) } return true }) } } - return ctx.reviver.call(ctx.call.runtime, toValue_object(holder), name, value) + return ctx.reviver.call(ctx.call.runtime, objectValue(holder), name, value) } -func builtinJSON_parseWalk(ctx _builtinJSON_parseContext, rawValue interface{}) (Value, bool) { +func builtinJSONParseWalk(ctx builtinJSONParseContext, rawValue interface{}) (Value, bool) { switch value := rawValue.(type) { case nil: return nullValue, true case bool: - return toValue_bool(value), true + return boolValue(value), true case string: - return toValue_string(value), true + return stringValue(value), true case float64: - return toValue_float64(value), true + return float64Value(value), true case []interface{}: arrayValue := make([]Value, len(value)) for index, rawValue := range value { - if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists { + if value, exists := builtinJSONParseWalk(ctx, rawValue); exists { arrayValue[index] = value } } - return toValue_object(ctx.call.runtime.newArrayOf(arrayValue)), true + return objectValue(ctx.call.runtime.newArrayOf(arrayValue)), true case map[string]interface{}: - object := ctx.call.runtime.newObject() + obj := ctx.call.runtime.newObject() for name, rawValue := range value { - if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists { - object.put(name, value, false) + if value, exists := builtinJSONParseWalk(ctx, rawValue); exists { + obj.put(name, value, false) } } - return toValue_object(object), true + return objectValue(obj), true } return Value{}, false } -type _builtinJSON_stringifyContext struct { - call FunctionCall - stack []*_object - propertyList []string +type builtinJSONStringifyContext struct { replacerFunction *Value gap string + stack []*object + propertyList []string + call FunctionCall } -func builtinJSON_stringify(call FunctionCall) Value { - ctx := _builtinJSON_stringifyContext{ +func builtinJSONStringify(call FunctionCall) Value { + ctx := builtinJSONStringifyContext{ call: call, - stack: []*_object{nil}, + stack: []*object{nil}, } - replacer := call.Argument(1)._object() + replacer := call.Argument(1).object() if replacer != nil { if isArray(replacer) { length := objectLength(replacer) seen := map[string]bool{} propertyList := make([]string, length) length = 0 - for index, _ := range propertyList { + for index := range propertyList { value := replacer.get(arrayIndexToString(int64(index))) switch value.kind { case valueObject: - switch value.value.(*_object).class { - case "String": - case "Number": + switch value.value.(*object).class { + case classStringName, classNumberName: default: continue } - case valueString: - case valueNumber: + case valueString, valueNumber: default: continue } @@ -138,21 +136,21 @@ func builtinJSON_stringify(call FunctionCall) Value { continue } seen[name] = true - length += 1 + length++ propertyList[index] = name } ctx.propertyList = propertyList[0:length] - } else if replacer.class == "Function" { - value := toValue_object(replacer) + } else if replacer.class == classFunctionName { + value := objectValue(replacer) ctx.replacerFunction = &value } } if spaceValue, exists := call.getArgument(2); exists { if spaceValue.kind == valueObject { - switch spaceValue.value.(*_object).class { - case "String": - spaceValue = toValue_string(spaceValue.string()) - case "Number": + switch spaceValue.value.(*object).class { + case classStringName: + spaceValue = stringValue(spaceValue.string()) + case classNumberName: spaceValue = spaceValue.numberValue() } } @@ -176,51 +174,51 @@ func builtinJSON_stringify(call FunctionCall) Value { } holder := call.runtime.newObject() holder.put("", call.Argument(0), false) - value, exists := builtinJSON_stringifyWalk(ctx, "", holder) + value, exists := builtinJSONStringifyWalk(ctx, "", holder) if !exists { return Value{} } valueJSON, err := json.Marshal(value) if err != nil { - panic(call.runtime.panicTypeError(err.Error())) + panic(call.runtime.panicTypeError("JSON.stringify marshal: %s", err)) } if ctx.gap != "" { valueJSON1 := bytes.Buffer{} - json.Indent(&valueJSON1, valueJSON, "", ctx.gap) + if err = json.Indent(&valueJSON1, valueJSON, "", ctx.gap); err != nil { + panic(call.runtime.panicTypeError("JSON.stringify indent: %s", err)) + } valueJSON = valueJSON1.Bytes() } - return toValue_string(string(valueJSON)) + return stringValue(string(valueJSON)) } -func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, holder *_object) (interface{}, bool) { +func builtinJSONStringifyWalk(ctx builtinJSONStringifyContext, key string, holder *object) (interface{}, bool) { value := holder.get(key) if value.IsObject() { - object := value._object() - if toJSON := object.get("toJSON"); toJSON.IsFunction() { + obj := value.object() + if toJSON := obj.get("toJSON"); toJSON.IsFunction() { value = toJSON.call(ctx.call.runtime, value, key) - } else { + } else if obj.objectClass.marshalJSON != nil { // If the object is a GoStruct or something that implements json.Marshaler - if object.objectClass.marshalJSON != nil { - marshaler := object.objectClass.marshalJSON(object) - if marshaler != nil { - return marshaler, true - } + marshaler := obj.objectClass.marshalJSON(obj) + if marshaler != nil { + return marshaler, true } } } if ctx.replacerFunction != nil { - value = (*ctx.replacerFunction).call(ctx.call.runtime, toValue_object(holder), key, value) + value = ctx.replacerFunction.call(ctx.call.runtime, objectValue(holder), key, value) } if value.kind == valueObject { - switch value.value.(*_object).class { - case "Boolean": - value = value._object().value.(Value) - case "String": - value = toValue_string(value.string()) - case "Number": + switch value.value.(*object).class { + case classBooleanName: + value = value.object().value.(Value) + case classStringName: + value = stringValue(value.string()) + case classNumberName: value = value.numberValue() } } @@ -243,19 +241,19 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho case valueNull: return nil, true case valueObject: - holder := value._object() - if value := value._object(); nil != value { - for _, object := range ctx.stack { - if holder == object { + objHolder := value.object() + if value := value.object(); nil != value { + for _, obj := range ctx.stack { + if objHolder == obj { panic(ctx.call.runtime.panicTypeError("Converting circular structure to JSON")) } } ctx.stack = append(ctx.stack, value) defer func() { ctx.stack = ctx.stack[:len(ctx.stack)-1] }() } - if isArray(holder) { + if isArray(objHolder) { var length uint32 - switch value := holder.get("length").value.(type) { + switch value := objHolder.get(propertyLength).value.(type) { case uint32: length = value case int: @@ -266,33 +264,33 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho panic(ctx.call.runtime.panicTypeError(fmt.Sprintf("JSON.stringify: invalid length: %v (%[1]T)", value))) } array := make([]interface{}, length) - for index, _ := range array { + for index := range array { name := arrayIndexToString(int64(index)) - value, _ := builtinJSON_stringifyWalk(ctx, name, holder) + value, _ := builtinJSONStringifyWalk(ctx, name, objHolder) array[index] = value } return array, true - } else if holder.class != "Function" { - object := map[string]interface{}{} + } else if objHolder.class != classFunctionName { + obj := map[string]interface{}{} if ctx.propertyList != nil { for _, name := range ctx.propertyList { - value, exists := builtinJSON_stringifyWalk(ctx, name, holder) + value, exists := builtinJSONStringifyWalk(ctx, name, objHolder) if exists { - object[name] = value + obj[name] = value } } } else { // Go maps are without order, so this doesn't conform to the ECMA ordering // standard, but oh well... - holder.enumerate(false, func(name string) bool { - value, exists := builtinJSON_stringifyWalk(ctx, name, holder) + objHolder.enumerate(false, func(name string) bool { + value, exists := builtinJSONStringifyWalk(ctx, name, objHolder) if exists { - object[name] = value + obj[name] = value } return true }) } - return object, true + return obj, true } } return nil, false diff --git a/vendor/github.com/robertkrimen/otto/builtin_math.go b/vendor/github.com/robertkrimen/otto/builtin_math.go index 7ce90c339..6429aa5a5 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_math.go +++ b/vendor/github.com/robertkrimen/otto/builtin_math.go @@ -7,27 +7,37 @@ import ( // Math -func builtinMath_abs(call FunctionCall) Value { +func builtinMathAbs(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Abs(number)) + return float64Value(math.Abs(number)) } -func builtinMath_acos(call FunctionCall) Value { +func builtinMathAcos(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Acos(number)) + return float64Value(math.Acos(number)) } -func builtinMath_asin(call FunctionCall) Value { +func builtinMathAcosh(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Asin(number)) + return float64Value(math.Acosh(number)) } -func builtinMath_atan(call FunctionCall) Value { +func builtinMathAsin(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Atan(number)) + return float64Value(math.Asin(number)) } -func builtinMath_atan2(call FunctionCall) Value { +func builtinMathAsinh(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Asinh(number)) +} + +func builtinMathAtan(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Atan(number)) +} + +func builtinMathAtan2(call FunctionCall) Value { y := call.Argument(0).float64() if math.IsNaN(y) { return NaNValue() @@ -36,40 +46,75 @@ func builtinMath_atan2(call FunctionCall) Value { if math.IsNaN(x) { return NaNValue() } - return toValue_float64(math.Atan2(y, x)) + return float64Value(math.Atan2(y, x)) +} + +func builtinMathAtanh(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Atanh(number)) +} + +func builtinMathCbrt(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Cbrt(number)) +} + +func builtinMathCos(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Cos(number)) +} + +func builtinMathCeil(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Ceil(number)) } -func builtinMath_cos(call FunctionCall) Value { +func builtinMathCosh(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Cos(number)) + return float64Value(math.Cosh(number)) } -func builtinMath_ceil(call FunctionCall) Value { +func builtinMathExp(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Ceil(number)) + return float64Value(math.Exp(number)) } -func builtinMath_exp(call FunctionCall) Value { +func builtinMathExpm1(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Exp(number)) + return float64Value(math.Expm1(number)) } -func builtinMath_floor(call FunctionCall) Value { +func builtinMathFloor(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Floor(number)) + return float64Value(math.Floor(number)) } -func builtinMath_log(call FunctionCall) Value { +func builtinMathLog(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Log(number)) + return float64Value(math.Log(number)) } -func builtinMath_max(call FunctionCall) Value { +func builtinMathLog10(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Log10(number)) +} + +func builtinMathLog1p(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Log1p(number)) +} + +func builtinMathLog2(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Log2(number)) +} + +func builtinMathMax(call FunctionCall) Value { switch len(call.ArgumentList) { case 0: return negativeInfinityValue() case 1: - return toValue_float64(call.ArgumentList[0].float64()) + return float64Value(call.ArgumentList[0].float64()) } result := call.ArgumentList[0].float64() if math.IsNaN(result) { @@ -82,15 +127,15 @@ func builtinMath_max(call FunctionCall) Value { } result = math.Max(result, value) } - return toValue_float64(result) + return float64Value(result) } -func builtinMath_min(call FunctionCall) Value { +func builtinMathMin(call FunctionCall) Value { switch len(call.ArgumentList) { case 0: return positiveInfinityValue() case 1: - return toValue_float64(call.ArgumentList[0].float64()) + return float64Value(call.ArgumentList[0].float64()) } result := call.ArgumentList[0].float64() if math.IsNaN(result) { @@ -103,49 +148,64 @@ func builtinMath_min(call FunctionCall) Value { } result = math.Min(result, value) } - return toValue_float64(result) + return float64Value(result) } -func builtinMath_pow(call FunctionCall) Value { +func builtinMathPow(call FunctionCall) Value { // TODO Make sure this works according to the specification (15.8.2.13) x := call.Argument(0).float64() y := call.Argument(1).float64() if math.Abs(x) == 1 && math.IsInf(y, 0) { return NaNValue() } - return toValue_float64(math.Pow(x, y)) + return float64Value(math.Pow(x, y)) } -func builtinMath_random(call FunctionCall) Value { +func builtinMathRandom(call FunctionCall) Value { var v float64 if call.runtime.random != nil { v = call.runtime.random() } else { - v = rand.Float64() + v = rand.Float64() //nolint:gosec } - return toValue_float64(v) + return float64Value(v) } -func builtinMath_round(call FunctionCall) Value { +func builtinMathRound(call FunctionCall) Value { number := call.Argument(0).float64() value := math.Floor(number + 0.5) if value == 0 { value = math.Copysign(0, number) } - return toValue_float64(value) + return float64Value(value) +} + +func builtinMathSin(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Sin(number)) +} + +func builtinMathSinh(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Sinh(number)) +} + +func builtinMathSqrt(call FunctionCall) Value { + number := call.Argument(0).float64() + return float64Value(math.Sqrt(number)) } -func builtinMath_sin(call FunctionCall) Value { +func builtinMathTan(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Sin(number)) + return float64Value(math.Tan(number)) } -func builtinMath_sqrt(call FunctionCall) Value { +func builtinMathTanh(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Sqrt(number)) + return float64Value(math.Tanh(number)) } -func builtinMath_tan(call FunctionCall) Value { +func builtinMathTrunc(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Tan(number)) + return float64Value(math.Trunc(number)) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_number.go b/vendor/github.com/robertkrimen/otto/builtin_number.go index f99a42a2f..acdeb501b 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_number.go +++ b/vendor/github.com/robertkrimen/otto/builtin_number.go @@ -3,6 +3,10 @@ package otto import ( "math" "strconv" + + "golang.org/x/text/language" + "golang.org/x/text/message" + "golang.org/x/text/number" ) // Number @@ -11,20 +15,20 @@ func numberValueFromNumberArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { return argumentList[0].numberValue() } - return toValue_int(0) + return intValue(0) } func builtinNumber(call FunctionCall) Value { return numberValueFromNumberArgumentList(call.ArgumentList) } -func builtinNewNumber(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) +func builtinNewNumber(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) } -func builtinNumber_toString(call FunctionCall) Value { +func builtinNumberToString(call FunctionCall) Value { // Will throw a TypeError if ThisObject is not a Number - value := call.thisClassObject("Number").primitiveValue() + value := call.thisClassObject(classNumberName).primitiveValue() radix := 10 radixArgument := call.Argument(0) if radixArgument.IsDefined() { @@ -35,33 +39,32 @@ func builtinNumber_toString(call FunctionCall) Value { radix = int(integer) } if radix == 10 { - return toValue_string(value.string()) + return stringValue(value.string()) } - return toValue_string(numberToStringRadix(value, radix)) + return stringValue(numberToStringRadix(value, radix)) } -func builtinNumber_valueOf(call FunctionCall) Value { - return call.thisClassObject("Number").primitiveValue() +func builtinNumberValueOf(call FunctionCall) Value { + return call.thisClassObject(classNumberName).primitiveValue() } -func builtinNumber_toFixed(call FunctionCall) Value { +func builtinNumberToFixed(call FunctionCall) Value { precision := toIntegerFloat(call.Argument(0)) if 20 < precision || 0 > precision { panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20")) } if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } - value := call.This.float64() - if math.Abs(value) >= 1e21 { - return toValue_string(floatToString(value, 64)) + if value := call.This.float64(); math.Abs(value) >= 1e21 { + return stringValue(floatToString(value, 64)) } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) } -func builtinNumber_toExponential(call FunctionCall) Value { +func builtinNumberToExponential(call FunctionCall) Value { if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } precision := float64(-1) if value := call.Argument(0); value.IsDefined() { @@ -70,24 +73,39 @@ func builtinNumber_toExponential(call FunctionCall) Value { panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36")) } } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) } -func builtinNumber_toPrecision(call FunctionCall) Value { +func builtinNumberToPrecision(call FunctionCall) Value { if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } value := call.Argument(0) if value.IsUndefined() { - return toValue_string(call.This.string()) + return stringValue(call.This.string()) } precision := toIntegerFloat(value) if 1 > precision { panic(call.runtime.panicRangeError("toPrecision() precision must be greater than 1")) } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) +} + +func builtinNumberIsNaN(call FunctionCall) Value { + if len(call.ArgumentList) < 1 { + return boolValue(false) + } + return boolValue(call.Argument(0).IsNaN()) } -func builtinNumber_toLocaleString(call FunctionCall) Value { - return builtinNumber_toString(call) +func builtinNumberToLocaleString(call FunctionCall) Value { + value := call.thisClassObject(classNumberName).primitiveValue() + locale := call.Argument(0) + lang := defaultLanguage + if locale.IsDefined() { + lang = language.MustParse(locale.string()) + } + + p := message.NewPrinter(lang) + return stringValue(p.Sprintf("%v", number.Decimal(value.value))) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_object.go b/vendor/github.com/robertkrimen/otto/builtin_object.go index c2433f7be..82da2cf9b 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_object.go +++ b/vendor/github.com/robertkrimen/otto/builtin_object.go @@ -10,36 +10,36 @@ func builtinObject(call FunctionCall) Value { value := call.Argument(0) switch value.kind { case valueUndefined, valueNull: - return toValue_object(call.runtime.newObject()) + return objectValue(call.runtime.newObject()) } - return toValue_object(call.runtime.toObject(value)) + return objectValue(call.runtime.toObject(value)) } -func builtinNewObject(self *_object, argumentList []Value) Value { +func builtinNewObject(obj *object, argumentList []Value) Value { value := valueOfArrayIndex(argumentList, 0) switch value.kind { case valueNull, valueUndefined: case valueNumber, valueString, valueBoolean: - return toValue_object(self.runtime.toObject(value)) + return objectValue(obj.runtime.toObject(value)) case valueObject: return value default: } - return toValue_object(self.runtime.newObject()) + return objectValue(obj.runtime.newObject()) } -func builtinObject_valueOf(call FunctionCall) Value { - return toValue_object(call.thisObject()) +func builtinObjectValueOf(call FunctionCall) Value { + return objectValue(call.thisObject()) } -func builtinObject_hasOwnProperty(call FunctionCall) Value { +func builtinObjectHasOwnProperty(call FunctionCall) Value { propertyName := call.Argument(0).string() thisObject := call.thisObject() - return toValue_bool(thisObject.hasOwnProperty(propertyName)) + return boolValue(thisObject.hasOwnProperty(propertyName)) } -func builtinObject_isPrototypeOf(call FunctionCall) Value { +func builtinObjectIsPrototypeOf(call FunctionCall) Value { value := call.Argument(0) if !value.IsObject() { return falseValue @@ -55,235 +55,246 @@ func builtinObject_isPrototypeOf(call FunctionCall) Value { return falseValue } -func builtinObject_propertyIsEnumerable(call FunctionCall) Value { +func builtinObjectPropertyIsEnumerable(call FunctionCall) Value { propertyName := call.Argument(0).string() thisObject := call.thisObject() - property := thisObject.getOwnProperty(propertyName) - if property != nil && property.enumerable() { + prop := thisObject.getOwnProperty(propertyName) + if prop != nil && prop.enumerable() { return trueValue } return falseValue } -func builtinObject_toString(call FunctionCall) Value { - result := "" - if call.This.IsUndefined() { +func builtinObjectToString(call FunctionCall) Value { + var result string + switch { + case call.This.IsUndefined(): result = "[object Undefined]" - } else if call.This.IsNull() { + case call.This.IsNull(): result = "[object Null]" - } else { + default: result = fmt.Sprintf("[object %s]", call.thisObject().class) } - return toValue_string(result) + return stringValue(result) } -func builtinObject_toLocaleString(call FunctionCall) Value { +func builtinObjectToLocaleString(call FunctionCall) Value { toString := call.thisObject().get("toString") if !toString.isCallable() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.toLocaleString %q is not callable", toString)) } return toString.call(call.runtime, call.This) } -func builtinObject_getPrototypeOf(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectGetPrototypeOf(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.GetPrototypeOf is nil")) } - if object.prototype == nil { + if obj.prototype == nil { return nullValue } - return toValue_object(object.prototype) + return objectValue(obj.prototype) } -func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.GetOwnPropertyDescriptor is nil")) } name := call.Argument(1).string() - descriptor := object.getOwnProperty(name) + descriptor := obj.getOwnProperty(name) if descriptor == nil { return Value{} } - return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor)) + return objectValue(call.runtime.fromPropertyDescriptor(*descriptor)) } -func builtinObject_defineProperty(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectDefineProperty(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.DefineProperty is nil")) } name := call.Argument(1).string() descriptor := toPropertyDescriptor(call.runtime, call.Argument(2)) - object.defineOwnProperty(name, descriptor, true) - return objectValue + obj.defineOwnProperty(name, descriptor, true) + return val } -func builtinObject_defineProperties(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { - panic(call.runtime.panicTypeError()) +func builtinObjectDefineProperties(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { + panic(call.runtime.panicTypeError("Object.DefineProperties is nil")) } properties := call.runtime.toObject(call.Argument(1)) properties.enumerate(false, func(name string) bool { descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) - object.defineOwnProperty(name, descriptor, true) + obj.defineOwnProperty(name, descriptor, true) return true }) - return objectValue + return val } -func builtinObject_create(call FunctionCall) Value { +func builtinObjectCreate(call FunctionCall) Value { prototypeValue := call.Argument(0) if !prototypeValue.IsNull() && !prototypeValue.IsObject() { - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.Create is nil")) } - object := call.runtime.newObject() - object.prototype = prototypeValue._object() + obj := call.runtime.newObject() + obj.prototype = prototypeValue.object() propertiesValue := call.Argument(1) if propertiesValue.IsDefined() { properties := call.runtime.toObject(propertiesValue) properties.enumerate(false, func(name string) bool { descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) - object.defineOwnProperty(name, descriptor, true) + obj.defineOwnProperty(name, descriptor, true) return true }) } - return toValue_object(object) + return objectValue(obj) } -func builtinObject_isExtensible(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - return toValue_bool(object.extensible) +func builtinObjectIsExtensible(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + return boolValue(obj.extensible) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.IsExtensible is nil")) } -func builtinObject_preventExtensions(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.extensible = false - } else { - panic(call.runtime.panicTypeError()) +func builtinObjectPreventExtensions(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.extensible = false + return val } - return object + panic(call.runtime.panicTypeError("Object.PreventExtensions is nil")) } -func builtinObject_isSealed(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - if object.extensible { - return toValue_bool(false) +func builtinObjectIsSealed(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + if obj.extensible { + return boolValue(false) } result := true - object.enumerate(true, func(name string) bool { - property := object.getProperty(name) - if property.configurable() { + obj.enumerate(true, func(name string) bool { + prop := obj.getProperty(name) + if prop.configurable() { result = false } return true }) - return toValue_bool(result) + return boolValue(result) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.IsSealed is nil")) } -func builtinObject_seal(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.enumerate(true, func(name string) bool { - if property := object.getOwnProperty(name); nil != property && property.configurable() { - property.configureOff() - object.defineOwnProperty(name, *property, true) +func builtinObjectSeal(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.enumerate(true, func(name string) bool { + if prop := obj.getOwnProperty(name); nil != prop && prop.configurable() { + prop.configureOff() + obj.defineOwnProperty(name, *prop, true) } return true }) - object.extensible = false - } else { - panic(call.runtime.panicTypeError()) + obj.extensible = false + return val } - return object + panic(call.runtime.panicTypeError("Object.Seal is nil")) } -func builtinObject_isFrozen(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - if object.extensible { - return toValue_bool(false) +func builtinObjectIsFrozen(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + if obj.extensible { + return boolValue(false) } result := true - object.enumerate(true, func(name string) bool { - property := object.getProperty(name) - if property.configurable() || property.writable() { + obj.enumerate(true, func(name string) bool { + prop := obj.getProperty(name) + if prop.configurable() || prop.writable() { result = false } return true }) - return toValue_bool(result) + return boolValue(result) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.IsFrozen is nil")) } -func builtinObject_freeze(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.enumerate(true, func(name string) bool { - if property, update := object.getOwnProperty(name), false; nil != property { - if property.isDataDescriptor() && property.writable() { - property.writeOff() +func builtinObjectFreeze(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.enumerate(true, func(name string) bool { + if prop, update := obj.getOwnProperty(name), false; nil != prop { + if prop.isDataDescriptor() && prop.writable() { + prop.writeOff() update = true } - if property.configurable() { - property.configureOff() + if prop.configurable() { + prop.configureOff() update = true } if update { - object.defineOwnProperty(name, *property, true) + obj.defineOwnProperty(name, *prop, true) } } return true }) - object.extensible = false - } else { - panic(call.runtime.panicTypeError()) + obj.extensible = false + return val } - return object + panic(call.runtime.panicTypeError("Object.Freeze is nil")) } -func builtinObject_keys(call FunctionCall) Value { - if object, keys := call.Argument(0)._object(), []Value(nil); nil != object { - object.enumerate(false, func(name string) bool { - keys = append(keys, toValue_string(name)) +func builtinObjectKeys(call FunctionCall) Value { + if obj, keys := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(false, func(name string) bool { + keys = append(keys, stringValue(name)) return true }) - return toValue_object(call.runtime.newArrayOf(keys)) + return objectValue(call.runtime.newArrayOf(keys)) } - panic(call.runtime.panicTypeError()) + panic(call.runtime.panicTypeError("Object.Keys is nil")) } -func builtinObject_getOwnPropertyNames(call FunctionCall) Value { - if object, propertyNames := call.Argument(0)._object(), []Value(nil); nil != object { - object.enumerate(true, func(name string) bool { - if object.hasOwnProperty(name) { - propertyNames = append(propertyNames, toValue_string(name)) +func builtinObjectValues(call FunctionCall) Value { + if obj, values := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(false, func(name string) bool { + values = append(values, obj.get(name)) + return true + }) + return objectValue(call.runtime.newArrayOf(values)) + } + panic(call.runtime.panicTypeError("Object.Values is nil")) +} + +func builtinObjectGetOwnPropertyNames(call FunctionCall) Value { + if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(true, func(name string) bool { + if obj.hasOwnProperty(name) { + propertyNames = append(propertyNames, stringValue(name)) } return true }) - return toValue_object(call.runtime.newArrayOf(propertyNames)) + return objectValue(call.runtime.newArrayOf(propertyNames)) } - panic(call.runtime.panicTypeError()) + + // Default to empty array for non object types. + return objectValue(call.runtime.newArray(0)) } diff --git a/vendor/github.com/robertkrimen/otto/builtin_regexp.go b/vendor/github.com/robertkrimen/otto/builtin_regexp.go index 99422510d..043034472 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_regexp.go +++ b/vendor/github.com/robertkrimen/otto/builtin_regexp.go @@ -9,22 +9,22 @@ import ( func builtinRegExp(call FunctionCall) Value { pattern := call.Argument(0) flags := call.Argument(1) - if object := pattern._object(); object != nil { - if object.class == "RegExp" && flags.IsUndefined() { + if obj := pattern.object(); obj != nil { + if obj.class == classRegExpName && flags.IsUndefined() { return pattern } } - return toValue_object(call.runtime.newRegExp(pattern, flags)) + return objectValue(call.runtime.newRegExp(pattern, flags)) } -func builtinNewRegExp(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newRegExp( +func builtinNewRegExp(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newRegExp( valueOfArrayIndex(argumentList, 0), valueOfArrayIndex(argumentList, 1), )) } -func builtinRegExp_toString(call FunctionCall) Value { +func builtinRegExpToString(call FunctionCall) Value { thisObject := call.thisObject() source := thisObject.get("source").string() flags := []byte{} @@ -37,27 +37,65 @@ func builtinRegExp_toString(call FunctionCall) Value { if thisObject.get("multiline").bool() { flags = append(flags, 'm') } - return toValue_string(fmt.Sprintf("/%s/%s", source, flags)) + return stringValue(fmt.Sprintf("/%s/%s", source, flags)) } -func builtinRegExp_exec(call FunctionCall) Value { +func builtinRegExpExec(call FunctionCall) Value { thisObject := call.thisObject() target := call.Argument(0).string() match, result := execRegExp(thisObject, target) if !match { return nullValue } - return toValue_object(execResultToArray(call.runtime, target, result)) + return objectValue(execResultToArray(call.runtime, target, result)) } -func builtinRegExp_test(call FunctionCall) Value { +func builtinRegExpTest(call FunctionCall) Value { thisObject := call.thisObject() target := call.Argument(0).string() - match, _ := execRegExp(thisObject, target) - return toValue_bool(match) + match, result := execRegExp(thisObject, target) + + if !match { + return boolValue(match) + } + + // Match extract and assign input, $_ and $1 -> $9 on global RegExp. + input := stringValue(target) + call.runtime.global.RegExp.defineProperty("$_", input, 0o100, false) + call.runtime.global.RegExp.defineProperty("input", input, 0o100, false) + + var start int + n := 1 + re := call.runtime.global.RegExp + empty := stringValue("") + for i, v := range result[2:] { + if i%2 == 0 { + start = v + } else { + if v == -1 { + // No match for this part. + re.defineProperty(fmt.Sprintf("$%d", n), empty, 0o100, false) + } else { + re.defineProperty(fmt.Sprintf("$%d", n), stringValue(target[start:v]), 0o100, false) + } + n++ + if n == 10 { + break + } + } + } + + if n <= 9 { + // Erase remaining. + for i := n; i <= 9; i++ { + re.defineProperty(fmt.Sprintf("$%d", i), empty, 0o100, false) + } + } + + return boolValue(match) } -func builtinRegExp_compile(call FunctionCall) Value { +func builtinRegExpCompile(call FunctionCall) Value { // This (useless) function is deprecated, but is here to provide some // semblance of compatibility. // Caveat emptor: it may not be around for long. diff --git a/vendor/github.com/robertkrimen/otto/builtin_string.go b/vendor/github.com/robertkrimen/otto/builtin_string.go index 6a1718458..48ef20387 100644 --- a/vendor/github.com/robertkrimen/otto/builtin_string.go +++ b/vendor/github.com/robertkrimen/otto/builtin_string.go @@ -5,6 +5,7 @@ import ( "regexp" "strconv" "strings" + "unicode/utf16" "unicode/utf8" ) @@ -12,102 +13,121 @@ import ( func stringValueFromStringArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { - return toValue_string(argumentList[0].string()) + return stringValue(argumentList[0].string()) } - return toValue_string("") + return stringValue("") } func builtinString(call FunctionCall) Value { return stringValueFromStringArgumentList(call.ArgumentList) } -func builtinNewString(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList))) +func builtinNewString(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newString(stringValueFromStringArgumentList(argumentList))) } -func builtinString_toString(call FunctionCall) Value { - return call.thisClassObject("String").primitiveValue() +func builtinStringToString(call FunctionCall) Value { + return call.thisClassObject(classStringName).primitiveValue() } -func builtinString_valueOf(call FunctionCall) Value { - return call.thisClassObject("String").primitiveValue() + +func builtinStringValueOf(call FunctionCall) Value { + return call.thisClassObject(classStringName).primitiveValue() } -func builtinString_fromCharCode(call FunctionCall) Value { +func builtinStringFromCharCode(call FunctionCall) Value { chrList := make([]uint16, len(call.ArgumentList)) for index, value := range call.ArgumentList { chrList[index] = toUint16(value) } - return toValue_string16(chrList) + return string16Value(chrList) } -func builtinString_charAt(call FunctionCall) Value { +func builtinStringCharAt(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) idx := int(call.Argument(0).number().int64) - chr := stringAt(call.This._object().stringValue(), idx) + chr := stringAt(call.This.object().stringValue(), idx) if chr == utf8.RuneError { - return toValue_string("") + return stringValue("") } - return toValue_string(string(chr)) + return stringValue(string(chr)) } -func builtinString_charCodeAt(call FunctionCall) Value { +func builtinStringCharCodeAt(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) idx := int(call.Argument(0).number().int64) - chr := stringAt(call.This._object().stringValue(), idx) + chr := stringAt(call.This.object().stringValue(), idx) if chr == utf8.RuneError { return NaNValue() } - return toValue_uint16(uint16(chr)) + return uint16Value(uint16(chr)) } -func builtinString_concat(call FunctionCall) Value { +func builtinStringConcat(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) var value bytes.Buffer value.WriteString(call.This.string()) for _, item := range call.ArgumentList { value.WriteString(item.string()) } - return toValue_string(value.String()) + return stringValue(value.String()) +} + +func lastIndexRune(s, substr string) int { + if i := strings.LastIndex(s, substr); i >= 0 { + return utf16Length(s[:i]) + } + return -1 +} + +func indexRune(s, substr string) int { + if i := strings.Index(s, substr); i >= 0 { + return utf16Length(s[:i]) + } + return -1 } -func builtinString_indexOf(call FunctionCall) Value { +func utf16Length(s string) int { + return len(utf16.Encode([]rune(s))) +} + +func builtinStringIndexOf(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) value := call.This.string() target := call.Argument(0).string() if 2 > len(call.ArgumentList) { - return toValue_int(strings.Index(value, target)) + return intValue(indexRune(value, target)) } start := toIntegerFloat(call.Argument(1)) if 0 > start { start = 0 } else if start >= float64(len(value)) { if target == "" { - return toValue_int(len(value)) + return intValue(len(value)) } - return toValue_int(-1) + return intValue(-1) } - index := strings.Index(value[int(start):], target) + index := indexRune(value[int(start):], target) if index >= 0 { index += int(start) } - return toValue_int(index) + return intValue(index) } -func builtinString_lastIndexOf(call FunctionCall) Value { +func builtinStringLastIndexOf(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) value := call.This.string() target := call.Argument(0).string() if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() { - return toValue_int(strings.LastIndex(value, target)) + return intValue(lastIndexRune(value, target)) } length := len(value) if length == 0 { - return toValue_int(strings.LastIndex(value, target)) + return intValue(lastIndexRune(value, target)) } start := call.ArgumentList[1].number() if start.kind == numberInfinity { // FIXME // startNumber is infinity, so start is the end of string (start = length) - return toValue_int(strings.LastIndex(value, target)) + return intValue(lastIndexRune(value, target)) } if 0 > start.int64 { start.int64 = 0 @@ -116,15 +136,15 @@ func builtinString_lastIndexOf(call FunctionCall) Value { if end > length { end = length } - return toValue_int(strings.LastIndex(value[:end], target)) + return intValue(lastIndexRune(value[:end], target)) } -func builtinString_match(call FunctionCall) Value { +func builtinStringMatch(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() matcherValue := call.Argument(0) - matcher := matcherValue._object() - if !matcherValue.IsObject() || matcher.class != "RegExp" { + matcher := matcherValue.object() + if !matcherValue.IsObject() || matcher.class != classRegExpName { matcher = call.runtime.newRegExp(matcherValue, Value{}) } global := matcher.get("global").bool() @@ -133,35 +153,32 @@ func builtinString_match(call FunctionCall) Value { if !match { return nullValue } - return toValue_object(execResultToArray(call.runtime, target, result)) + return objectValue(execResultToArray(call.runtime, target, result)) } - { - result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) - matchCount := len(result) - if result == nil { - matcher.put("lastIndex", toValue_int(0), true) - return Value{} // !match - } - matchCount = len(result) - valueArray := make([]Value, matchCount) - for index := 0; index < matchCount; index++ { - valueArray[index] = toValue_string(target[result[index][0]:result[index][1]]) - } - matcher.put("lastIndex", toValue_int(result[matchCount-1][1]), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) + result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) + if result == nil { + matcher.put("lastIndex", intValue(0), true) + return Value{} // !match + } + matchCount := len(result) + valueArray := make([]Value, matchCount) + for index := range matchCount { + valueArray[index] = stringValue(target[result[index][0]:result[index][1]]) } + matcher.put("lastIndex", intValue(result[matchCount-1][1]), true) + return objectValue(call.runtime.newArrayOf(valueArray)) } -var builtinString_replace_Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") +var builtinStringReplaceRegexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") -func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) { +func builtinStringFindAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) []byte { matchCount := len(match) / 2 - output = input + output := input if match[0] != lastIndex { output = append(output, target[lastIndex:match[0]]...) } - replacement := builtinString_replace_Regexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { + replacement := builtinStringReplaceRegexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { // TODO Check if match[0] or match[1] can be -1 in this scenario switch part[1] { case '$': @@ -171,38 +188,42 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int case '`': return target[:match[0]] case '\'': - return target[match[1]:len(target)] + return target[match[1]:] + } + matchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64) + if err != nil { + return nil } - matchNumberParse, error := strconv.ParseInt(string(part[1:]), 10, 64) matchNumber := int(matchNumberParse) - if error != nil || matchNumber >= matchCount { - return []byte{} + if matchNumber >= matchCount { + return nil } offset := 2 * matchNumber if match[offset] != -1 { return target[match[offset]:match[offset+1]] } - return []byte{} // The empty string + return nil // The empty string }) - output = append(output, replacement...) - return output + + return append(output, replacement...) } -func builtinString_replace(call FunctionCall) Value { +func builtinStringReplace(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := []byte(call.This.string()) searchValue := call.Argument(0) - searchObject := searchValue._object() + searchObject := searchValue.object() // TODO If a capture is -1? var search *regexp.Regexp global := false find := 1 - if searchValue.IsObject() && searchObject.class == "RegExp" { + if searchValue.IsObject() && searchObject.class == classRegExpName { regExp := searchObject.regExpValue() search = regExp.regularExpression if regExp.global { find = -1 + global = true } } else { search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string())) @@ -210,85 +231,72 @@ func builtinString_replace(call FunctionCall) Value { found := search.FindAllSubmatchIndex(target, find) if found == nil { - return toValue_string(string(target)) // !match - } - - { - lastIndex := 0 - result := []byte{} - - replaceValue := call.Argument(1) - if replaceValue.isCallable() { - target := string(target) - replace := replaceValue._object() - for _, match := range found { - if match[0] != lastIndex { - result = append(result, target[lastIndex:match[0]]...) - } - matchCount := len(match) / 2 - argumentList := make([]Value, matchCount+2) - for index := 0; index < matchCount; index++ { - offset := 2 * index - if match[offset] != -1 { - argumentList[index] = toValue_string(target[match[offset]:match[offset+1]]) - } else { - argumentList[index] = Value{} - } - } - argumentList[matchCount+0] = toValue_int(match[0]) - argumentList[matchCount+1] = toValue_string(target) - replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() - result = append(result, []byte(replacement)...) - lastIndex = match[1] + return stringValue(string(target)) // !match + } + + lastIndex := 0 + result := []byte{} + replaceValue := call.Argument(1) + if replaceValue.isCallable() { + target := string(target) + replace := replaceValue.object() + for _, match := range found { + if match[0] != lastIndex { + result = append(result, target[lastIndex:match[0]]...) } - - } else { - replace := []byte(replaceValue.string()) - for _, match := range found { - result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace) - lastIndex = match[1] + matchCount := len(match) / 2 + argumentList := make([]Value, matchCount+2) + for index := range matchCount { + offset := 2 * index + if match[offset] != -1 { + argumentList[index] = stringValue(target[match[offset]:match[offset+1]]) + } else { + argumentList[index] = Value{} + } } + // Replace expects rune offsets not byte offsets. + startIndex := utf8.RuneCountInString(target[0:match[0]]) + argumentList[matchCount+0] = intValue(startIndex) + argumentList[matchCount+1] = stringValue(target) + replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() + result = append(result, []byte(replacement)...) + lastIndex = match[1] } - - if lastIndex != len(target) { - result = append(result, target[lastIndex:]...) + } else { + replace := []byte(replaceValue.string()) + for _, match := range found { + result = builtinStringFindAndReplaceString(result, lastIndex, match, target, replace) + lastIndex = match[1] } + } - if global && searchObject != nil { - searchObject.put("lastIndex", toValue_int(lastIndex), true) - } + if lastIndex != len(target) { + result = append(result, target[lastIndex:]...) + } - return toValue_string(string(result)) + if global && searchObject != nil { + searchObject.put("lastIndex", intValue(lastIndex), true) } + + return stringValue(string(result)) } -func builtinString_search(call FunctionCall) Value { +func builtinStringSearch(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() searchValue := call.Argument(0) - search := searchValue._object() - if !searchValue.IsObject() || search.class != "RegExp" { + search := searchValue.object() + if !searchValue.IsObject() || search.class != classRegExpName { search = call.runtime.newRegExp(searchValue, Value{}) } result := search.regExpValue().regularExpression.FindStringIndex(target) if result == nil { - return toValue_int(-1) + return intValue(-1) } - return toValue_int(result[0]) + return intValue(result[0]) } -func stringSplitMatch(target string, targetLength int64, index uint, search string, searchLength int64) (bool, uint) { - if int64(index)+searchLength > searchLength { - return false, 0 - } - found := strings.Index(target[index:], search) - if 0 > found { - return false, 0 - } - return true, uint(found) -} - -func builtinString_split(call FunctionCall) Value { +func builtinStringSplit(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() @@ -300,16 +308,16 @@ func builtinString_split(call FunctionCall) Value { } if limit == 0 { - return toValue_object(call.runtime.newArray(0)) + return objectValue(call.runtime.newArray(0)) } if separatorValue.IsUndefined() { - return toValue_object(call.runtime.newArrayOf([]Value{toValue_string(target)})) + return objectValue(call.runtime.newArrayOf([]Value{stringValue(target)})) } if separatorValue.isRegExp() { targetLength := len(target) - search := separatorValue._object().regExpValue().regularExpression + search := separatorValue.object().regExpValue().regularExpression valueArray := []Value{} result := search.FindAllStringSubmatchIndex(target, -1) lastIndex := 0 @@ -324,11 +332,11 @@ func builtinString_split(call FunctionCall) Value { } if lastIndex != match[0] { - valueArray = append(valueArray, toValue_string(target[lastIndex:match[0]])) + valueArray = append(valueArray, stringValue(target[lastIndex:match[0]])) found++ } else if lastIndex == match[0] { if lastIndex != -1 { - valueArray = append(valueArray, toValue_string("")) + valueArray = append(valueArray, stringValue("")) found++ } } @@ -343,7 +351,7 @@ func builtinString_split(call FunctionCall) Value { offset := index * 2 value := Value{} if match[offset] != -1 { - value = toValue_string(target[match[offset]:match[offset+1]]) + value = stringValue(target[match[offset]:match[offset+1]]) } valueArray = append(valueArray, value) found++ @@ -355,15 +363,14 @@ func builtinString_split(call FunctionCall) Value { if found != limit { if lastIndex != targetLength { - valueArray = append(valueArray, toValue_string(target[lastIndex:targetLength])) + valueArray = append(valueArray, stringValue(target[lastIndex:targetLength])) } else { - valueArray = append(valueArray, toValue_string("")) + valueArray = append(valueArray, stringValue("")) } } RETURN: - return toValue_object(call.runtime.newArrayOf(valueArray)) - + return objectValue(call.runtime.newArrayOf(valueArray)) } else { separator := separatorValue.string() @@ -382,49 +389,51 @@ func builtinString_split(call FunctionCall) Value { valueArray := make([]Value, len(split)) for index, value := range split { - valueArray[index] = toValue_string(value) + valueArray[index] = stringValue(value) } - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } } -func builtinString_slice(call FunctionCall) Value { +// builtinStringSlice returns the string sliced by the given values +// which are rune not byte offsets, as per String.prototype.slice. +func builtinStringSlice(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - target := call.This.string() + target := []rune(call.This.string()) length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, false) if end-start <= 0 { - return toValue_string("") + return stringValue("") } - return toValue_string(target[start:end]) + return stringValue(string(target[start:end])) } -func builtinString_substring(call FunctionCall) Value { +func builtinStringSubstring(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - target := call.This.string() + target := []rune(call.This.string()) length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, true) if start > end { start, end = end, start } - return toValue_string(target[start:end]) + return stringValue(string(target[start:end])) } -func builtinString_substr(call FunctionCall) Value { - target := call.This.string() +func builtinStringSubstr(call FunctionCall) Value { + target := []rune(call.This.string()) size := int64(len(target)) start, length := rangeStartLength(call.ArgumentList, size) if start >= size { - return toValue_string("") + return stringValue("") } if length <= 0 { - return toValue_string("") + return stringValue("") } if start+length >= size { @@ -435,66 +444,77 @@ func builtinString_substr(call FunctionCall) Value { length = size - start } - return toValue_string(target[start : start+length]) + return stringValue(string(target[start : start+length])) +} + +func builtinStringStartsWith(call FunctionCall) Value { + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() + search := call.Argument(0).string() + length := len(search) + if length > len(target) { + return boolValue(false) + } + return boolValue(target[:length] == search) } -func builtinString_toLowerCase(call FunctionCall) Value { +func builtinStringToLowerCase(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - return toValue_string(strings.ToLower(call.This.string())) + return stringValue(strings.ToLower(call.This.string())) } -func builtinString_toUpperCase(call FunctionCall) Value { +func builtinStringToUpperCase(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - return toValue_string(strings.ToUpper(call.This.string())) + return stringValue(strings.ToUpper(call.This.string())) } -// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters -const builtinString_trim_whitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF" +// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters. +const builtinStringTrimWhitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF" -func builtinString_trim(call FunctionCall) Value { +func builtinStringTrim(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.Trim(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -// Mozilla extension, not ECMAScript 5 -func builtinString_trimLeft(call FunctionCall) Value { +func builtinStringTrimStart(call FunctionCall) Value { + return builtinStringTrimLeft(call) +} + +func builtinStringTrimEnd(call FunctionCall) Value { + return builtinStringTrimRight(call) +} + +// Mozilla extension, not ECMAScript 5. +func builtinStringTrimLeft(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.TrimLeft(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -// Mozilla extension, not ECMAScript 5 -func builtinString_trimRight(call FunctionCall) Value { +// Mozilla extension, not ECMAScript 5. +func builtinStringTrimRight(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.TrimRight(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -func builtinString_localeCompare(call FunctionCall) Value { +func builtinStringLocaleCompare(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - this := call.This.string() + this := call.This.string() //nolint:ifshort that := call.Argument(0).string() if this < that { - return toValue_int(-1) + return intValue(-1) } else if this == that { - return toValue_int(0) + return intValue(0) } - return toValue_int(1) -} - -/* -An alternate version of String.trim -func builtinString_trim(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.TrimFunc(call.string(.This), isWhiteSpaceOrLineTerminator)) + return intValue(1) } -*/ -func builtinString_toLocaleLowerCase(call FunctionCall) Value { - return builtinString_toLowerCase(call) +func builtinStringToLocaleLowerCase(call FunctionCall) Value { + return builtinStringToLowerCase(call) } -func builtinString_toLocaleUpperCase(call FunctionCall) Value { - return builtinString_toUpperCase(call) +func builtinStringToLocaleUpperCase(call FunctionCall) Value { + return builtinStringToUpperCase(call) } diff --git a/vendor/github.com/robertkrimen/otto/clone.go b/vendor/github.com/robertkrimen/otto/clone.go index 23b59f8ac..edc284594 100644 --- a/vendor/github.com/robertkrimen/otto/clone.go +++ b/vendor/github.com/robertkrimen/otto/clone.go @@ -4,159 +4,157 @@ import ( "fmt" ) -type _clone struct { - runtime *_runtime - _object map[*_object]*_object - _objectStash map[*_objectStash]*_objectStash - _dclStash map[*_dclStash]*_dclStash - _fnStash map[*_fnStash]*_fnStash +type cloner struct { + runtime *runtime + obj map[*object]*object + objectstash map[*objectStash]*objectStash + dclstash map[*dclStash]*dclStash + fnstash map[*fnStash]*fnStash } -func (in *_runtime) clone() *_runtime { +func (rt *runtime) clone() *runtime { + rt.lck.Lock() + defer rt.lck.Unlock() - in.lck.Lock() - defer in.lck.Unlock() - - out := &_runtime{ - debugger: in.debugger, - random: in.random, - stackLimit: in.stackLimit, - traceLimit: in.traceLimit, + out := &runtime{ + debugger: rt.debugger, + random: rt.random, + stackLimit: rt.stackLimit, + traceLimit: rt.traceLimit, } - clone := _clone{ - runtime: out, - _object: make(map[*_object]*_object), - _objectStash: make(map[*_objectStash]*_objectStash), - _dclStash: make(map[*_dclStash]*_dclStash), - _fnStash: make(map[*_fnStash]*_fnStash), + c := cloner{ + runtime: out, + obj: make(map[*object]*object), + objectstash: make(map[*objectStash]*objectStash), + dclstash: make(map[*dclStash]*dclStash), + fnstash: make(map[*fnStash]*fnStash), } - globalObject := clone.object(in.globalObject) + globalObject := c.object(rt.globalObject) out.globalStash = out.newObjectStash(globalObject, nil) out.globalObject = globalObject - out.global = _global{ - clone.object(in.global.Object), - clone.object(in.global.Function), - clone.object(in.global.Array), - clone.object(in.global.String), - clone.object(in.global.Boolean), - clone.object(in.global.Number), - clone.object(in.global.Math), - clone.object(in.global.Date), - clone.object(in.global.RegExp), - clone.object(in.global.Error), - clone.object(in.global.EvalError), - clone.object(in.global.TypeError), - clone.object(in.global.RangeError), - clone.object(in.global.ReferenceError), - clone.object(in.global.SyntaxError), - clone.object(in.global.URIError), - clone.object(in.global.JSON), - - clone.object(in.global.ObjectPrototype), - clone.object(in.global.FunctionPrototype), - clone.object(in.global.ArrayPrototype), - clone.object(in.global.StringPrototype), - clone.object(in.global.BooleanPrototype), - clone.object(in.global.NumberPrototype), - clone.object(in.global.DatePrototype), - clone.object(in.global.RegExpPrototype), - clone.object(in.global.ErrorPrototype), - clone.object(in.global.EvalErrorPrototype), - clone.object(in.global.TypeErrorPrototype), - clone.object(in.global.RangeErrorPrototype), - clone.object(in.global.ReferenceErrorPrototype), - clone.object(in.global.SyntaxErrorPrototype), - clone.object(in.global.URIErrorPrototype), + out.global = global{ + c.object(rt.global.Object), + c.object(rt.global.Function), + c.object(rt.global.Array), + c.object(rt.global.String), + c.object(rt.global.Boolean), + c.object(rt.global.Number), + c.object(rt.global.Math), + c.object(rt.global.Date), + c.object(rt.global.RegExp), + c.object(rt.global.Error), + c.object(rt.global.EvalError), + c.object(rt.global.TypeError), + c.object(rt.global.RangeError), + c.object(rt.global.ReferenceError), + c.object(rt.global.SyntaxError), + c.object(rt.global.URIError), + c.object(rt.global.JSON), + + c.object(rt.global.ObjectPrototype), + c.object(rt.global.FunctionPrototype), + c.object(rt.global.ArrayPrototype), + c.object(rt.global.StringPrototype), + c.object(rt.global.BooleanPrototype), + c.object(rt.global.NumberPrototype), + c.object(rt.global.DatePrototype), + c.object(rt.global.RegExpPrototype), + c.object(rt.global.ErrorPrototype), + c.object(rt.global.EvalErrorPrototype), + c.object(rt.global.TypeErrorPrototype), + c.object(rt.global.RangeErrorPrototype), + c.object(rt.global.ReferenceErrorPrototype), + c.object(rt.global.SyntaxErrorPrototype), + c.object(rt.global.URIErrorPrototype), } - out.eval = out.globalObject.property["eval"].value.(Value).value.(*_object) + out.eval = out.globalObject.property["eval"].value.(Value).value.(*object) out.globalObject.prototype = out.global.ObjectPrototype // Not sure if this is necessary, but give some help to the GC - clone.runtime = nil - clone._object = nil - clone._objectStash = nil - clone._dclStash = nil - clone._fnStash = nil + c.runtime = nil + c.obj = nil + c.objectstash = nil + c.dclstash = nil + c.fnstash = nil return out } -func (clone *_clone) object(in *_object) *_object { - if out, exists := clone._object[in]; exists { +func (c *cloner) object(in *object) *object { + if out, exists := c.obj[in]; exists { return out } - out := &_object{} - clone._object[in] = out - return in.objectClass.clone(in, out, clone) + out := &object{} + c.obj[in] = out + return in.objectClass.clone(in, out, c) } -func (clone *_clone) dclStash(in *_dclStash) (*_dclStash, bool) { - if out, exists := clone._dclStash[in]; exists { +func (c *cloner) dclStash(in *dclStash) (*dclStash, bool) { + if out, exists := c.dclstash[in]; exists { return out, true } - out := &_dclStash{} - clone._dclStash[in] = out + out := &dclStash{} + c.dclstash[in] = out return out, false } -func (clone *_clone) objectStash(in *_objectStash) (*_objectStash, bool) { - if out, exists := clone._objectStash[in]; exists { +func (c *cloner) objectStash(in *objectStash) (*objectStash, bool) { + if out, exists := c.objectstash[in]; exists { return out, true } - out := &_objectStash{} - clone._objectStash[in] = out + out := &objectStash{} + c.objectstash[in] = out return out, false } -func (clone *_clone) fnStash(in *_fnStash) (*_fnStash, bool) { - if out, exists := clone._fnStash[in]; exists { +func (c *cloner) fnStash(in *fnStash) (*fnStash, bool) { + if out, exists := c.fnstash[in]; exists { return out, true } - out := &_fnStash{} - clone._fnStash[in] = out + out := &fnStash{} + c.fnstash[in] = out return out, false } -func (clone *_clone) value(in Value) Value { +func (c *cloner) value(in Value) Value { out := in - switch value := in.value.(type) { - case *_object: - out.value = clone.object(value) + if value, ok := in.value.(*object); ok { + out.value = c.object(value) } return out } -func (clone *_clone) valueArray(in []Value) []Value { +func (c *cloner) valueArray(in []Value) []Value { out := make([]Value, len(in)) for index, value := range in { - out[index] = clone.value(value) + out[index] = c.value(value) } return out } -func (clone *_clone) stash(in _stash) _stash { +func (c *cloner) stash(in stasher) stasher { if in == nil { return nil } - return in.clone(clone) + return in.clone(c) } -func (clone *_clone) property(in _property) _property { +func (c *cloner) property(in property) property { out := in switch value := in.value.(type) { case Value: - out.value = clone.value(value) - case _propertyGetSet: - p := _propertyGetSet{} + out.value = c.value(value) + case propertyGetSet: + p := propertyGetSet{} if value[0] != nil { - p[0] = clone.object(value[0]) + p[0] = c.object(value[0]) } if value[1] != nil { - p[1] = clone.object(value[1]) + p[1] = c.object(value[1]) } out.value = p default: @@ -166,8 +164,8 @@ func (clone *_clone) property(in _property) _property { return out } -func (clone *_clone) dclProperty(in _dclProperty) _dclProperty { +func (c *cloner) dclProperty(in dclProperty) dclProperty { out := in - out.value = clone.value(in.value) + out.value = c.value(in.value) return out } diff --git a/vendor/github.com/robertkrimen/otto/cmpl.go b/vendor/github.com/robertkrimen/otto/cmpl.go index c191b4527..e81cd50b4 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl.go +++ b/vendor/github.com/robertkrimen/otto/cmpl.go @@ -5,20 +5,7 @@ import ( "github.com/robertkrimen/otto/file" ) -type _file struct { - name string - src string - base int // This will always be 1 or greater -} - -type _compiler struct { +type compiler struct { file *file.File program *ast.Program } - -func (cmpl *_compiler) parse() *_nodeProgram { - if cmpl.program != nil { - cmpl.file = cmpl.program.File - } - return cmpl._parse(cmpl.program) -} diff --git a/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go b/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go index 6741bf394..a29b7d880 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_evaluate.go @@ -4,21 +4,18 @@ import ( "strconv" ) -func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram, eval bool) Value { +func (rt *runtime) cmplEvaluateNodeProgram(node *nodeProgram, eval bool) Value { if !eval { - self.enterGlobalScope() - defer func() { - self.leaveScope() - }() + rt.enterGlobalScope() + defer rt.leaveScope() } - self.cmpl_functionDeclaration(node.functionList) - self.cmpl_variableDeclaration(node.varList) - self.scope.frame.file = node.file - return self.cmpl_evaluate_nodeStatementList(node.body) + rt.cmplFunctionDeclaration(node.functionList) + rt.cmplVariableDeclaration(node.varList) + rt.scope.frame.file = node.file + return rt.cmplEvaluateNodeStatementList(node.body) } -func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, node *_nodeFunctionLiteral, this Value, argumentList []Value) Value { - +func (rt *runtime) cmplCallNodeFunction(function *object, stash *fnStash, node *nodeFunctionLiteral, argumentList []Value) Value { indexOfParameterName := make([]string, len(argumentList)) // function(abc, def, ghi) // indexOfParameterName[0] = "abc" @@ -37,28 +34,28 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, indexOfParameterName[index] = name } // strict = false - self.scope.lexical.setValue(name, value, false) + rt.scope.lexical.setValue(name, value, false) } if !argumentsFound { - arguments := self.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) - arguments.defineProperty("callee", toValue_object(function), 0101, false) + arguments := rt.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) + arguments.defineProperty("callee", objectValue(function), 0o101, false) stash.arguments = arguments // strict = false - self.scope.lexical.setValue("arguments", toValue_object(arguments), false) - for index, _ := range argumentList { + rt.scope.lexical.setValue("arguments", objectValue(arguments), false) + for index := range argumentList { if index < len(node.parameterList) { continue } indexAsString := strconv.FormatInt(int64(index), 10) - arguments.defineProperty(indexAsString, argumentList[index], 0111, false) + arguments.defineProperty(indexAsString, argumentList[index], 0o111, false) } } - self.cmpl_functionDeclaration(node.functionList) - self.cmpl_variableDeclaration(node.varList) + rt.cmplFunctionDeclaration(node.functionList) + rt.cmplVariableDeclaration(node.varList) - result := self.cmpl_evaluate_nodeStatement(node.body) + result := rt.cmplEvaluateNodeStatement(node.body) if result.kind == valueResult { return result } @@ -66,16 +63,16 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, return Value{} } -func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { - executionContext := self.scope +func (rt *runtime) cmplFunctionDeclaration(list []*nodeFunctionLiteral) { + executionContext := rt.scope eval := executionContext.eval stash := executionContext.variable for _, function := range list { name := function.name - value := self.cmpl_evaluate_nodeExpression(function) + value := rt.cmplEvaluateNodeExpression(function) if !stash.hasBinding(name) { - stash.createBinding(name, eval == true, value) + stash.createBinding(name, eval, value) } else { // TODO 10.5.5.e stash.setBinding(name, value, false) // TODO strict @@ -83,14 +80,14 @@ func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { } } -func (self *_runtime) cmpl_variableDeclaration(list []string) { - executionContext := self.scope +func (rt *runtime) cmplVariableDeclaration(list []string) { + executionContext := rt.scope eval := executionContext.eval stash := executionContext.variable for _, name := range list { if !stash.hasBinding(name) { - stash.createBinding(name, eval == true, Value{}) // TODO strict? + stash.createBinding(name, eval, Value{}) // TODO strict? } } } diff --git a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go index 8586a484f..69c673a8a 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_expression.go @@ -3,140 +3,135 @@ package otto import ( "fmt" "math" - "runtime" + goruntime "runtime" "github.com/robertkrimen/otto/token" ) -func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { +func (rt *runtime) cmplEvaluateNodeExpression(node nodeExpression) Value { // Allow interpreter interruption // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.otto.Interrupt != nil { - runtime.Gosched() + if rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } switch node := node.(type) { + case *nodeArrayLiteral: + return rt.cmplEvaluateNodeArrayLiteral(node) - case *_nodeArrayLiteral: - return self.cmpl_evaluate_nodeArrayLiteral(node) + case *nodeAssignExpression: + return rt.cmplEvaluateNodeAssignExpression(node) - case *_nodeAssignExpression: - return self.cmpl_evaluate_nodeAssignExpression(node) - - case *_nodeBinaryExpression: + case *nodeBinaryExpression: if node.comparison { - return self.cmpl_evaluate_nodeBinaryExpression_comparison(node) - } else { - return self.cmpl_evaluate_nodeBinaryExpression(node) + return rt.cmplEvaluateNodeBinaryExpressionComparison(node) } + return rt.cmplEvaluateNodeBinaryExpression(node) - case *_nodeBracketExpression: - return self.cmpl_evaluate_nodeBracketExpression(node) + case *nodeBracketExpression: + return rt.cmplEvaluateNodeBracketExpression(node) - case *_nodeCallExpression: - return self.cmpl_evaluate_nodeCallExpression(node, nil) + case *nodeCallExpression: + return rt.cmplEvaluateNodeCallExpression(node, nil) - case *_nodeConditionalExpression: - return self.cmpl_evaluate_nodeConditionalExpression(node) + case *nodeConditionalExpression: + return rt.cmplEvaluateNodeConditionalExpression(node) - case *_nodeDotExpression: - return self.cmpl_evaluate_nodeDotExpression(node) + case *nodeDotExpression: + return rt.cmplEvaluateNodeDotExpression(node) - case *_nodeFunctionLiteral: - var local = self.scope.lexical + case *nodeFunctionLiteral: + local := rt.scope.lexical if node.name != "" { - local = self.newDeclarationStash(local) + local = rt.newDeclarationStash(local) } - value := toValue_object(self.newNodeFunction(node, local)) + value := objectValue(rt.newNodeFunction(node, local)) if node.name != "" { local.createBinding(node.name, false, value) } return value - case *_nodeIdentifier: + case *nodeIdentifier: name := node.name // TODO Should be true or false (strictness) depending on context // getIdentifierReference should not return nil, but we check anyway and panic // so as not to propagate the nil into something else - reference := getIdentifierReference(self, self.scope.lexical, name, false, _at(node.idx)) + reference := getIdentifierReference(rt, rt.scope.lexical, name, false, at(node.idx)) if reference == nil { // Should never get here! panic(hereBeDragons("referenceError == nil: " + name)) } return toValue(reference) - case *_nodeLiteral: + case *nodeLiteral: return node.value - case *_nodeNewExpression: - return self.cmpl_evaluate_nodeNewExpression(node) + case *nodeNewExpression: + return rt.cmplEvaluateNodeNewExpression(node) - case *_nodeObjectLiteral: - return self.cmpl_evaluate_nodeObjectLiteral(node) + case *nodeObjectLiteral: + return rt.cmplEvaluateNodeObjectLiteral(node) - case *_nodeRegExpLiteral: - return toValue_object(self._newRegExp(node.pattern, node.flags)) + case *nodeRegExpLiteral: + return objectValue(rt.newRegExpDirect(node.pattern, node.flags)) - case *_nodeSequenceExpression: - return self.cmpl_evaluate_nodeSequenceExpression(node) + case *nodeSequenceExpression: + return rt.cmplEvaluateNodeSequenceExpression(node) - case *_nodeThisExpression: - return toValue_object(self.scope.this) + case *nodeThisExpression: + return objectValue(rt.scope.this) - case *_nodeUnaryExpression: - return self.cmpl_evaluate_nodeUnaryExpression(node) + case *nodeUnaryExpression: + return rt.cmplEvaluateNodeUnaryExpression(node) - case *_nodeVariableExpression: - return self.cmpl_evaluate_nodeVariableExpression(node) + case *nodeVariableExpression: + return rt.cmplEvaluateNodeVariableExpression(node) + default: + panic(fmt.Sprintf("unknown node type: %T", node)) } - - panic(fmt.Errorf("Here be dragons: evaluate_nodeExpression(%T)", node)) } -func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Value { - +func (rt *runtime) cmplEvaluateNodeArrayLiteral(node *nodeArrayLiteral) Value { valueArray := []Value{} for _, node := range node.value { if node == nil { valueArray = append(valueArray, emptyValue) } else { - valueArray = append(valueArray, self.cmpl_evaluate_nodeExpression(node).resolve()) + valueArray = append(valueArray, rt.cmplEvaluateNodeExpression(node).resolve()) } } - result := self.newArrayOf(valueArray) + result := rt.newArrayOf(valueArray) - return toValue_object(result) + return objectValue(result) } -func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpression) Value { - - left := self.cmpl_evaluate_nodeExpression(node.left) - right := self.cmpl_evaluate_nodeExpression(node.right) +func (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left) + right := rt.cmplEvaluateNodeExpression(node.right) rightValue := right.resolve() result := rightValue if node.operator != token.ASSIGN { - result = self.calculateBinaryExpression(node.operator, left, rightValue) + result = rt.calculateBinaryExpression(node.operator, left, rightValue) } - self.putValue(left.reference(), result) + rt.putValue(left.reference(), result) return result } -func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value { - - left := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left) leftValue := left.resolve() switch node.operator { @@ -145,217 +140,206 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres if !leftValue.bool() { return leftValue } - right := self.cmpl_evaluate_nodeExpression(node.right) + right := rt.cmplEvaluateNodeExpression(node.right) return right.resolve() case token.LOGICAL_OR: if leftValue.bool() { return leftValue } - right := self.cmpl_evaluate_nodeExpression(node.right) + right := rt.cmplEvaluateNodeExpression(node.right) return right.resolve() } - return self.calculateBinaryExpression(node.operator, leftValue, self.cmpl_evaluate_nodeExpression(node.right)) + return rt.calculateBinaryExpression(node.operator, leftValue, rt.cmplEvaluateNodeExpression(node.right)) } -func (self *_runtime) cmpl_evaluate_nodeBinaryExpression_comparison(node *_nodeBinaryExpression) Value { +func (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left).resolve() + right := rt.cmplEvaluateNodeExpression(node.right).resolve() - left := self.cmpl_evaluate_nodeExpression(node.left).resolve() - right := self.cmpl_evaluate_nodeExpression(node.right).resolve() - - return toValue_bool(self.calculateComparison(node.operator, left, right)) + return boolValue(rt.calculateComparison(node.operator, left, right)) } -func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.left) targetValue := target.resolve() - member := self.cmpl_evaluate_nodeExpression(node.member) + member := rt.cmplEvaluateNodeExpression(node.member) memberValue := member.resolve() // TODO Pass in base value as-is, and defer toObject till later? - object, err := self.objectCoerce(targetValue) + obj, err := rt.objectCoerce(targetValue) if err != nil { - panic(self.panicTypeError("Cannot access member '%s' of %s", memberValue.string(), err.Error(), _at(node.idx))) + panic(rt.panicTypeError("Cannot access member %q of %s", memberValue.string(), err, at(node.idx))) } - return toValue(newPropertyReference(self, object, memberValue.string(), false, _at(node.idx))) + return toValue(newPropertyReference(rt, obj, memberValue.string(), false, at(node.idx))) } -func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value { - rt := self +func (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value { this := Value{} - callee := self.cmpl_evaluate_nodeExpression(node.callee) + callee := rt.cmplEvaluateNodeExpression(node.callee) argumentList := []Value{} if withArgumentList != nil { - argumentList = self.toValueArray(withArgumentList...) + argumentList = rt.toValueArray(withArgumentList...) } else { for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) + argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve()) } } - rf := callee.reference() - vl := callee.resolve() - eval := false // Whether this call is a (candidate for) direct call to eval name := "" - if rf != nil { + if rf := callee.reference(); rf != nil { switch rf := rf.(type) { - case *_propertyReference: + case *propertyReference: name = rf.name - object := rf.base - this = toValue_object(object) + this = objectValue(rf.base) eval = rf.name == "eval" // Possible direct eval - case *_stashReference: + case *stashReference: // TODO ImplicitThisValue name = rf.name eval = rf.name == "eval" // Possible direct eval default: // FIXME? - panic(rt.panicTypeError("Here be dragons")) + panic(rt.panicTypeError("unexpected callee type %T to node call expression", rf)) } } - at := _at(-1) + atv := at(-1) switch callee := node.callee.(type) { - case *_nodeIdentifier: - at = _at(callee.idx) - case *_nodeDotExpression: - at = _at(callee.idx) - case *_nodeBracketExpression: - at = _at(callee.idx) + case *nodeIdentifier: + atv = at(callee.idx) + case *nodeDotExpression: + atv = at(callee.idx) + case *nodeBracketExpression: + atv = at(callee.idx) } - frame := _frame{ + frm := frame{ callee: name, - file: self.scope.frame.file, + file: rt.scope.frame.file, } + vl := callee.resolve() if !vl.IsFunction() { if name == "" { // FIXME Maybe typeof? - panic(rt.panicTypeError("%v is not a function", vl, at)) + panic(rt.panicTypeError("%v is not a function", vl, atv)) } - panic(rt.panicTypeError("'%s' is not a function", name, at)) + panic(rt.panicTypeError("%q is not a function", name, atv)) } - self.scope.frame.offset = int(at) + rt.scope.frame.offset = int(atv) - return vl._object().call(this, argumentList, eval, frame) + return vl.object().call(this, argumentList, eval, frm) } -func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value { - test := self.cmpl_evaluate_nodeExpression(node.test) +func (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value { + test := rt.cmplEvaluateNodeExpression(node.test) testValue := test.resolve() if testValue.bool() { - return self.cmpl_evaluate_nodeExpression(node.consequent) + return rt.cmplEvaluateNodeExpression(node.consequent) } - return self.cmpl_evaluate_nodeExpression(node.alternate) + return rt.cmplEvaluateNodeExpression(node.alternate) } -func (self *_runtime) cmpl_evaluate_nodeDotExpression(node *_nodeDotExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.left) targetValue := target.resolve() // TODO Pass in base value as-is, and defer toObject till later? - object, err := self.objectCoerce(targetValue) + obj, err := rt.objectCoerce(targetValue) if err != nil { - panic(self.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error(), _at(node.idx))) + panic(rt.panicTypeError("Cannot access member %q of %s", node.identifier, err, at(node.idx))) } - return toValue(newPropertyReference(self, object, node.identifier, false, _at(node.idx))) + return toValue(newPropertyReference(rt, obj, node.identifier, false, at(node.idx))) } -func (self *_runtime) cmpl_evaluate_nodeNewExpression(node *_nodeNewExpression) Value { - rt := self - callee := self.cmpl_evaluate_nodeExpression(node.callee) +func (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value { + callee := rt.cmplEvaluateNodeExpression(node.callee) argumentList := []Value{} for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) + argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve()) } - rf := callee.reference() - vl := callee.resolve() - - name := "" - if rf != nil { + var name string + if rf := callee.reference(); rf != nil { switch rf := rf.(type) { - case *_propertyReference: + case *propertyReference: name = rf.name - case *_stashReference: + case *stashReference: name = rf.name default: - panic(rt.panicTypeError("Here be dragons")) + panic(rt.panicTypeError("node new expression unexpected callee type %T", rf)) } } - at := _at(-1) + atv := at(-1) switch callee := node.callee.(type) { - case *_nodeIdentifier: - at = _at(callee.idx) - case *_nodeDotExpression: - at = _at(callee.idx) - case *_nodeBracketExpression: - at = _at(callee.idx) + case *nodeIdentifier: + atv = at(callee.idx) + case *nodeDotExpression: + atv = at(callee.idx) + case *nodeBracketExpression: + atv = at(callee.idx) } + vl := callee.resolve() if !vl.IsFunction() { if name == "" { // FIXME Maybe typeof? - panic(rt.panicTypeError("%v is not a function", vl, at)) + panic(rt.panicTypeError("%v is not a function", vl, atv)) } - panic(rt.panicTypeError("'%s' is not a function", name, at)) + panic(rt.panicTypeError("'%s' is not a function", name, atv)) } - self.scope.frame.offset = int(at) + rt.scope.frame.offset = int(atv) - return vl._object().construct(argumentList) + return vl.object().construct(argumentList) } -func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) Value { - - result := self.newObject() - - for _, property := range node.value { - switch property.kind { +func (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value { + result := rt.newObject() + for _, prop := range node.value { + switch prop.kind { case "value": - result.defineProperty(property.key, self.cmpl_evaluate_nodeExpression(property.value).resolve(), 0111, false) + result.defineProperty(prop.key, rt.cmplEvaluateNodeExpression(prop.value).resolve(), 0o111, false) case "get": - getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) - descriptor := _property{} - descriptor.mode = 0211 - descriptor.value = _propertyGetSet{getter, nil} - result.defineOwnProperty(property.key, descriptor, false) + getter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical) + descriptor := property{} + descriptor.mode = 0o211 + descriptor.value = propertyGetSet{getter, nil} + result.defineOwnProperty(prop.key, descriptor, false) case "set": - setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) - descriptor := _property{} - descriptor.mode = 0211 - descriptor.value = _propertyGetSet{nil, setter} - result.defineOwnProperty(property.key, descriptor, false) + setter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical) + descriptor := property{} + descriptor.mode = 0o211 + descriptor.value = propertyGetSet{nil, setter} + result.defineOwnProperty(prop.key, descriptor, false) default: - panic(fmt.Errorf("Here be dragons: evaluate_nodeObjectLiteral: invalid property.Kind: %v", property.kind)) + panic(fmt.Sprintf("unknown node object literal property kind %T", prop.kind)) } } - return toValue_object(result) + return objectValue(result) } -func (self *_runtime) cmpl_evaluate_nodeSequenceExpression(node *_nodeSequenceExpression) Value { +func (rt *runtime) cmplEvaluateNodeSequenceExpression(node *nodeSequenceExpression) Value { var result Value for _, node := range node.sequence { - result = self.cmpl_evaluate_nodeExpression(node) + result = rt.cmplEvaluateNodeExpression(node) result = result.resolve() } return result } -func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpression) Value { - - target := self.cmpl_evaluate_nodeExpression(node.operand) +func (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.operand) switch node.operator { case token.TYPEOF, token.DELETE: if target.kind == valueReference && target.reference().invalid() { if node.operator == token.TYPEOF { - return toValue_string("undefined") + return stringValue("undefined") } return trueValue } @@ -371,10 +355,10 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi case token.BITWISE_NOT: targetValue := target.resolve() integerValue := toInt32(targetValue) - return toValue_int32(^integerValue) + return int32Value(^integerValue) case token.PLUS: targetValue := target.resolve() - return toValue_float64(targetValue.float64()) + return float64Value(targetValue.float64()) case token.MINUS: targetValue := target.resolve() value := targetValue.float64() @@ -383,35 +367,35 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi if math.Signbit(value) { sign = 1 } - return toValue_float64(math.Copysign(value, sign)) + return float64Value(math.Copysign(value, sign)) case token.INCREMENT: targetValue := target.resolve() if node.postfix { // Postfix++ oldValue := targetValue.float64() - newValue := toValue_float64(+1 + oldValue) - self.putValue(target.reference(), newValue) - return toValue_float64(oldValue) - } else { - // ++Prefix - newValue := toValue_float64(+1 + targetValue.float64()) - self.putValue(target.reference(), newValue) - return newValue + newValue := float64Value(+1 + oldValue) + rt.putValue(target.reference(), newValue) + return float64Value(oldValue) } + + // ++Prefix + newValue := float64Value(+1 + targetValue.float64()) + rt.putValue(target.reference(), newValue) + return newValue case token.DECREMENT: targetValue := target.resolve() if node.postfix { // Postfix-- oldValue := targetValue.float64() - newValue := toValue_float64(-1 + oldValue) - self.putValue(target.reference(), newValue) - return toValue_float64(oldValue) - } else { - // --Prefix - newValue := toValue_float64(-1 + targetValue.float64()) - self.putValue(target.reference(), newValue) - return newValue + newValue := float64Value(-1 + oldValue) + rt.putValue(target.reference(), newValue) + return float64Value(oldValue) } + + // --Prefix + newValue := float64Value(-1 + targetValue.float64()) + rt.putValue(target.reference(), newValue) + return newValue case token.VOID: target.resolve() // FIXME Side effect? return Value{} @@ -420,25 +404,25 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi if reference == nil { return trueValue } - return toValue_bool(target.reference().delete()) + return boolValue(target.reference().delete()) case token.TYPEOF: targetValue := target.resolve() switch targetValue.kind { case valueUndefined: - return toValue_string("undefined") + return stringValue("undefined") case valueNull: - return toValue_string("object") + return stringValue("object") case valueBoolean: - return toValue_string("boolean") + return stringValue("boolean") case valueNumber: - return toValue_string("number") + return stringValue("number") case valueString: - return toValue_string("string") + return stringValue("string") case valueObject: - if targetValue._object().isCall() { - return toValue_string("function") + if targetValue.object().isCall() { + return stringValue("function") } - return toValue_string("object") + return stringValue("object") default: // FIXME ? } @@ -447,14 +431,14 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi panic(hereBeDragons()) } -func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value { +func (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value { if node.initializer != nil { // FIXME If reference is nil - left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx)) - right := self.cmpl_evaluate_nodeExpression(node.initializer) + left := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx)) + right := rt.cmplEvaluateNodeExpression(node.initializer) rightValue := right.resolve() - self.putValue(left, rightValue) + rt.putValue(left, rightValue) } - return toValue_string(node.name) + return stringValue(node.name) } diff --git a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go index e16c6ac6c..724120ac3 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go @@ -2,123 +2,121 @@ package otto import ( "fmt" - "runtime" + goruntime "runtime" "github.com/robertkrimen/otto/token" ) -func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { +func (rt *runtime) cmplEvaluateNodeStatement(node nodeStatement) Value { // Allow interpreter interruption // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.otto.Interrupt != nil { - runtime.Gosched() + if rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } switch node := node.(type) { + case *nodeBlockStatement: + labels := rt.labels + rt.labels = nil - case *_nodeBlockStatement: - labels := self.labels - self.labels = nil - - value := self.cmpl_evaluate_nodeStatementList(node.list) - switch value.kind { - case valueResult: - switch value.evaluateBreak(labels) { - case resultBreak: + value := rt.cmplEvaluateNodeStatementList(node.list) + if value.kind == valueResult { + if value.evaluateBreak(labels) == resultBreak { return emptyValue } } return value - case *_nodeBranchStatement: + case *nodeBranchStatement: target := node.label switch node.branch { // FIXME Maybe node.kind? node.operator? case token.BREAK: return toValue(newBreakResult(target)) case token.CONTINUE: return toValue(newContinueResult(target)) + default: + panic(fmt.Errorf("unknown node branch token %T", node)) } - case *_nodeDebuggerStatement: - if self.debugger != nil { - self.debugger(self.otto) + case *nodeDebuggerStatement: + if rt.debugger != nil { + rt.debugger(rt.otto) } return emptyValue // Nothing happens. - case *_nodeDoWhileStatement: - return self.cmpl_evaluate_nodeDoWhileStatement(node) + case *nodeDoWhileStatement: + return rt.cmplEvaluateNodeDoWhileStatement(node) - case *_nodeEmptyStatement: + case *nodeEmptyStatement: return emptyValue - case *_nodeExpressionStatement: - return self.cmpl_evaluate_nodeExpression(node.expression) + case *nodeExpressionStatement: + return rt.cmplEvaluateNodeExpression(node.expression) - case *_nodeForInStatement: - return self.cmpl_evaluate_nodeForInStatement(node) + case *nodeForInStatement: + return rt.cmplEvaluateNodeForInStatement(node) - case *_nodeForStatement: - return self.cmpl_evaluate_nodeForStatement(node) + case *nodeForStatement: + return rt.cmplEvaluateNodeForStatement(node) - case *_nodeIfStatement: - return self.cmpl_evaluate_nodeIfStatement(node) + case *nodeIfStatement: + return rt.cmplEvaluateNodeIfStatement(node) - case *_nodeLabelledStatement: - self.labels = append(self.labels, node.label) + case *nodeLabelledStatement: + rt.labels = append(rt.labels, node.label) defer func() { - if len(self.labels) > 0 { - self.labels = self.labels[:len(self.labels)-1] // Pop the label + if len(rt.labels) > 0 { + rt.labels = rt.labels[:len(rt.labels)-1] // Pop the label } else { - self.labels = nil + rt.labels = nil } }() - return self.cmpl_evaluate_nodeStatement(node.statement) + return rt.cmplEvaluateNodeStatement(node.statement) - case *_nodeReturnStatement: + case *nodeReturnStatement: if node.argument != nil { - return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve())) + return toValue(newReturnResult(rt.cmplEvaluateNodeExpression(node.argument).resolve())) } return toValue(newReturnResult(Value{})) - case *_nodeSwitchStatement: - return self.cmpl_evaluate_nodeSwitchStatement(node) + case *nodeSwitchStatement: + return rt.cmplEvaluateNodeSwitchStatement(node) - case *_nodeThrowStatement: - value := self.cmpl_evaluate_nodeExpression(node.argument).resolve() + case *nodeThrowStatement: + value := rt.cmplEvaluateNodeExpression(node.argument).resolve() panic(newException(value)) - case *_nodeTryStatement: - return self.cmpl_evaluate_nodeTryStatement(node) + case *nodeTryStatement: + return rt.cmplEvaluateNodeTryStatement(node) - case *_nodeVariableStatement: + case *nodeVariableStatement: // Variables are already defined, this is initialization only for _, variable := range node.list { - self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression)) + rt.cmplEvaluateNodeVariableExpression(variable.(*nodeVariableExpression)) } return emptyValue - case *_nodeWhileStatement: - return self.cmpl_evaluate_nodeWhileStatement(node) - - case *_nodeWithStatement: - return self.cmpl_evaluate_nodeWithStatement(node) + case *nodeWhileStatement: + return rt.cmplEvaluateModeWhileStatement(node) + case *nodeWithStatement: + return rt.cmplEvaluateNodeWithStatement(node) + default: + panic(fmt.Errorf("unknown node statement type %T", node)) } - - panic(fmt.Errorf("Here be dragons: evaluate_nodeStatement(%T)", node)) } -func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Value { +func (rt *runtime) cmplEvaluateNodeStatementList(list []nodeStatement) Value { var result Value for _, node := range list { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: return value @@ -135,10 +133,9 @@ func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Val return result } -func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileStatement) Value { - - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeDoWhileStatement(node *nodeDoWhileStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil test := node.test @@ -146,7 +143,7 @@ func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileState resultBreak: for { for _, node := range node.body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -163,7 +160,7 @@ resultBreak: } } resultContinue: - if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { + if !rt.cmplEvaluateNodeExpression(test).resolve().bool() { // Stahp: do ... while (false) break } @@ -171,12 +168,11 @@ resultBreak: return result } -func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement) Value { - - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeForInStatement(node *nodeForInStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil - source := self.cmpl_evaluate_nodeExpression(node.source) + source := rt.cmplEvaluateNodeExpression(node.source) sourceValue := source.resolve() switch sourceValue.kind { @@ -184,26 +180,26 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement return emptyValue } - sourceObject := self.toObject(sourceValue) + sourceObject := rt.toObject(sourceValue) into := node.into body := node.body result := emptyValue - object := sourceObject - for object != nil { + obj := sourceObject + for obj != nil { enumerateValue := emptyValue - object.enumerate(false, func(name string) bool { - into := self.cmpl_evaluate_nodeExpression(into) + obj.enumerate(false, func(name string) bool { + into := rt.cmplEvaluateNodeExpression(into) // In the case of: for (var abc in def) ... if into.reference() == nil { identifier := into.string() // TODO Should be true or false (strictness) depending on context - into = toValue(getIdentifierReference(self, self.scope.lexical, identifier, false, -1)) + into = toValue(getIdentifierReference(rt, rt.scope.lexical, identifier, false, -1)) } - self.putValue(into.reference(), toValue_string(name)) + rt.putValue(into.reference(), stringValue(name)) for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -211,7 +207,7 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement enumerateValue = value return false case resultBreak: - object = nil + obj = nil return false case resultContinue: return true @@ -223,10 +219,10 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement } return true }) - if object == nil { + if obj == nil { break } - object = object.prototype + obj = obj.prototype if !enumerateValue.isEmpty() { result = enumerateValue } @@ -234,10 +230,9 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement return result } -func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Value { - - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeForStatement(node *nodeForStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil initializer := node.initializer test := node.test @@ -245,7 +240,7 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va body := node.body if initializer != nil { - initialResult := self.cmpl_evaluate_nodeExpression(initializer) + initialResult := rt.cmplEvaluateNodeExpression(initializer) initialResult.resolve() // Side-effect trigger } @@ -253,14 +248,25 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va resultBreak: for { if test != nil { - testResult := self.cmpl_evaluate_nodeExpression(test) + testResult := rt.cmplEvaluateNodeExpression(test) testResultValue := testResult.resolve() - if testResultValue.bool() == false { + if !testResultValue.bool() { break } } + + // this is to prevent for cycles with no body from running forever + if len(body) == 0 && rt.otto.Interrupt != nil { + goruntime.Gosched() + select { + case value := <-rt.otto.Interrupt: + value() + default: + } + } + for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -278,37 +284,36 @@ resultBreak: } resultContinue: if update != nil { - updateResult := self.cmpl_evaluate_nodeExpression(update) + updateResult := rt.cmplEvaluateNodeExpression(update) updateResult.resolve() // Side-effect trigger } } return result } -func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value { - test := self.cmpl_evaluate_nodeExpression(node.test) +func (rt *runtime) cmplEvaluateNodeIfStatement(node *nodeIfStatement) Value { + test := rt.cmplEvaluateNodeExpression(node.test) testValue := test.resolve() if testValue.bool() { - return self.cmpl_evaluate_nodeStatement(node.consequent) + return rt.cmplEvaluateNodeStatement(node.consequent) } else if node.alternate != nil { - return self.cmpl_evaluate_nodeStatement(node.alternate) + return rt.cmplEvaluateNodeStatement(node.alternate) } return emptyValue } -func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value { +func (rt *runtime) cmplEvaluateNodeSwitchStatement(node *nodeSwitchStatement) Value { + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil - labels := append(self.labels, "") - self.labels = nil - - discriminantResult := self.cmpl_evaluate_nodeExpression(node.discriminant) - target := node.default_ + discriminantResult := rt.cmplEvaluateNodeExpression(node.discriminant) + target := node.defaultIdx for index, clause := range node.body { test := clause.test if test != nil { - if self.calculateComparison(token.STRICT_EQUAL, discriminantResult, self.cmpl_evaluate_nodeExpression(test)) { + if rt.calculateComparison(token.STRICT_EQUAL, discriminantResult, rt.cmplEvaluateNodeExpression(test)) { target = index break } @@ -319,7 +324,7 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme if target != -1 { for _, clause := range node.body[target:] { for _, statement := range clause.consequent { - value := self.cmpl_evaluate_nodeStatement(statement) + value := rt.cmplEvaluateNodeStatement(statement) switch value.kind { case valueResult: switch value.evaluateBreak(labels) { @@ -339,59 +344,58 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme return result } -func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Value { - tryCatchValue, exception := self.tryCatchEvaluate(func() Value { - return self.cmpl_evaluate_nodeStatement(node.body) +func (rt *runtime) cmplEvaluateNodeTryStatement(node *nodeTryStatement) Value { + tryCatchValue, exep := rt.tryCatchEvaluate(func() Value { + return rt.cmplEvaluateNodeStatement(node.body) }) - if exception && node.catch != nil { - outer := self.scope.lexical - self.scope.lexical = self.newDeclarationStash(outer) + if exep && node.catch != nil { + outer := rt.scope.lexical + rt.scope.lexical = rt.newDeclarationStash(outer) defer func() { - self.scope.lexical = outer + rt.scope.lexical = outer }() // TODO If necessary, convert TypeError => TypeError // That, is, such errors can be thrown despite not being JavaScript "native" // strict = false - self.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) + rt.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) // FIXME node.CatchParameter // FIXME node.Catch - tryCatchValue, exception = self.tryCatchEvaluate(func() Value { - return self.cmpl_evaluate_nodeStatement(node.catch.body) + tryCatchValue, exep = rt.tryCatchEvaluate(func() Value { + return rt.cmplEvaluateNodeStatement(node.catch.body) }) } if node.finally != nil { - finallyValue := self.cmpl_evaluate_nodeStatement(node.finally) + finallyValue := rt.cmplEvaluateNodeStatement(node.finally) if finallyValue.kind == valueResult { return finallyValue } } - if exception { + if exep { panic(newException(tryCatchValue)) } return tryCatchValue } -func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement) Value { - +func (rt *runtime) cmplEvaluateModeWhileStatement(node *nodeWhileStatement) Value { test := node.test body := node.body - labels := append(self.labels, "") - self.labels = nil + labels := append(rt.labels, "") //nolint:gocritic + rt.labels = nil result := emptyValue resultBreakContinue: for { - if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { + if !rt.cmplEvaluateNodeExpression(test).resolve().bool() { // Stahp: while (false) ... break } for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -411,14 +415,14 @@ resultBreakContinue: return result } -func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value { - object := self.cmpl_evaluate_nodeExpression(node.object) - outer := self.scope.lexical - lexical := self.newObjectStash(self.toObject(object.resolve()), outer) - self.scope.lexical = lexical +func (rt *runtime) cmplEvaluateNodeWithStatement(node *nodeWithStatement) Value { + obj := rt.cmplEvaluateNodeExpression(node.object) + outer := rt.scope.lexical + lexical := rt.newObjectStash(rt.toObject(obj.resolve()), outer) + rt.scope.lexical = lexical defer func() { - self.scope.lexical = outer + rt.scope.lexical = outer }() - return self.cmpl_evaluate_nodeStatement(node.body) + return rt.cmplEvaluateNodeStatement(node.body) } diff --git a/vendor/github.com/robertkrimen/otto/cmpl_parse.go b/vendor/github.com/robertkrimen/otto/cmpl_parse.go index dc5baa12a..d3fe8da55 100644 --- a/vendor/github.com/robertkrimen/otto/cmpl_parse.go +++ b/vendor/github.com/robertkrimen/otto/cmpl_parse.go @@ -2,84 +2,84 @@ package otto import ( "fmt" - "regexp" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/token" ) -var trueLiteral = &_nodeLiteral{value: toValue_bool(true)} -var falseLiteral = &_nodeLiteral{value: toValue_bool(false)} -var nullLiteral = &_nodeLiteral{value: nullValue} -var emptyStatement = &_nodeEmptyStatement{} +var ( + trueLiteral = &nodeLiteral{value: boolValue(true)} + falseLiteral = &nodeLiteral{value: boolValue(false)} + nullLiteral = &nodeLiteral{value: nullValue} + emptyStatement = &nodeEmptyStatement{} +) -func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { - if in == nil { +func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression { + if expr == nil { return nil } - switch in := in.(type) { - + switch expr := expr.(type) { case *ast.ArrayLiteral: - out := &_nodeArrayLiteral{ - value: make([]_nodeExpression, len(in.Value)), + out := &nodeArrayLiteral{ + value: make([]nodeExpression, len(expr.Value)), } - for i, value := range in.Value { + for i, value := range expr.Value { out.value[i] = cmpl.parseExpression(value) } return out case *ast.AssignExpression: - return &_nodeAssignExpression{ - operator: in.Operator, - left: cmpl.parseExpression(in.Left), - right: cmpl.parseExpression(in.Right), + return &nodeAssignExpression{ + operator: expr.Operator, + left: cmpl.parseExpression(expr.Left), + right: cmpl.parseExpression(expr.Right), } case *ast.BinaryExpression: - return &_nodeBinaryExpression{ - operator: in.Operator, - left: cmpl.parseExpression(in.Left), - right: cmpl.parseExpression(in.Right), - comparison: in.Comparison, + return &nodeBinaryExpression{ + operator: expr.Operator, + left: cmpl.parseExpression(expr.Left), + right: cmpl.parseExpression(expr.Right), + comparison: expr.Comparison, } case *ast.BooleanLiteral: - if in.Value { + if expr.Value { return trueLiteral } return falseLiteral case *ast.BracketExpression: - return &_nodeBracketExpression{ - idx: in.Left.Idx0(), - left: cmpl.parseExpression(in.Left), - member: cmpl.parseExpression(in.Member), + return &nodeBracketExpression{ + idx: expr.Left.Idx0(), + left: cmpl.parseExpression(expr.Left), + member: cmpl.parseExpression(expr.Member), } case *ast.CallExpression: - out := &_nodeCallExpression{ - callee: cmpl.parseExpression(in.Callee), - argumentList: make([]_nodeExpression, len(in.ArgumentList)), + out := &nodeCallExpression{ + callee: cmpl.parseExpression(expr.Callee), + argumentList: make([]nodeExpression, len(expr.ArgumentList)), } - for i, value := range in.ArgumentList { + for i, value := range expr.ArgumentList { out.argumentList[i] = cmpl.parseExpression(value) } return out case *ast.ConditionalExpression: - return &_nodeConditionalExpression{ - test: cmpl.parseExpression(in.Test), - consequent: cmpl.parseExpression(in.Consequent), - alternate: cmpl.parseExpression(in.Alternate), + return &nodeConditionalExpression{ + test: cmpl.parseExpression(expr.Test), + consequent: cmpl.parseExpression(expr.Consequent), + alternate: cmpl.parseExpression(expr.Alternate), } case *ast.DotExpression: - return &_nodeDotExpression{ - idx: in.Left.Idx0(), - left: cmpl.parseExpression(in.Left), - identifier: in.Identifier.Name, + return &nodeDotExpression{ + idx: expr.Left.Idx0(), + left: cmpl.parseExpression(expr.Left), + identifier: expr.Identifier.Name, } case *ast.EmptyExpression: @@ -87,48 +87,48 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { case *ast.FunctionLiteral: name := "" - if in.Name != nil { - name = in.Name.Name + if expr.Name != nil { + name = expr.Name.Name } - out := &_nodeFunctionLiteral{ + out := &nodeFunctionLiteral{ name: name, - body: cmpl.parseStatement(in.Body), - source: in.Source, + body: cmpl.parseStatement(expr.Body), + source: expr.Source, file: cmpl.file, } - if in.ParameterList != nil { - list := in.ParameterList.List + if expr.ParameterList != nil { + list := expr.ParameterList.List out.parameterList = make([]string, len(list)) for i, value := range list { out.parameterList[i] = value.Name } } - for _, value := range in.DeclarationList { + for _, value := range expr.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value)) + panic(fmt.Sprintf("parse expression unknown function declaration type %T", value)) } } return out case *ast.Identifier: - return &_nodeIdentifier{ - idx: in.Idx, - name: in.Name, + return &nodeIdentifier{ + idx: expr.Idx, + name: expr.Name, } case *ast.NewExpression: - out := &_nodeNewExpression{ - callee: cmpl.parseExpression(in.Callee), - argumentList: make([]_nodeExpression, len(in.ArgumentList)), + out := &nodeNewExpression{ + callee: cmpl.parseExpression(expr.Callee), + argumentList: make([]nodeExpression, len(expr.ArgumentList)), } - for i, value := range in.ArgumentList { + for i, value := range expr.ArgumentList { out.argumentList[i] = cmpl.parseExpression(value) } return out @@ -137,16 +137,16 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { return nullLiteral case *ast.NumberLiteral: - return &_nodeLiteral{ - value: toValue(in.Value), + return &nodeLiteral{ + value: toValue(expr.Value), } case *ast.ObjectLiteral: - out := &_nodeObjectLiteral{ - value: make([]_nodeProperty, len(in.Value)), + out := &nodeObjectLiteral{ + value: make([]nodeProperty, len(expr.Value)), } - for i, value := range in.Value { - out.value[i] = _nodeProperty{ + for i, value := range expr.Value { + out.value[i] = nodeProperty{ key: value.Key, kind: value.Kind, value: cmpl.parseExpression(value.Value), @@ -155,81 +155,79 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { return out case *ast.RegExpLiteral: - return &_nodeRegExpLiteral{ - flags: in.Flags, - pattern: in.Pattern, + return &nodeRegExpLiteral{ + flags: expr.Flags, + pattern: expr.Pattern, } case *ast.SequenceExpression: - out := &_nodeSequenceExpression{ - sequence: make([]_nodeExpression, len(in.Sequence)), + out := &nodeSequenceExpression{ + sequence: make([]nodeExpression, len(expr.Sequence)), } - for i, value := range in.Sequence { + for i, value := range expr.Sequence { out.sequence[i] = cmpl.parseExpression(value) } return out case *ast.StringLiteral: - return &_nodeLiteral{ - value: toValue_string(in.Value), + return &nodeLiteral{ + value: stringValue(expr.Value), } case *ast.ThisExpression: - return &_nodeThisExpression{} + return &nodeThisExpression{} case *ast.UnaryExpression: - return &_nodeUnaryExpression{ - operator: in.Operator, - operand: cmpl.parseExpression(in.Operand), - postfix: in.Postfix, + return &nodeUnaryExpression{ + operator: expr.Operator, + operand: cmpl.parseExpression(expr.Operand), + postfix: expr.Postfix, } case *ast.VariableExpression: - return &_nodeVariableExpression{ - idx: in.Idx0(), - name: in.Name, - initializer: cmpl.parseExpression(in.Initializer), + return &nodeVariableExpression{ + idx: expr.Idx0(), + name: expr.Name, + initializer: cmpl.parseExpression(expr.Initializer), } - + default: + panic(fmt.Errorf("parse expression unknown node type %T", expr)) } - - panic(fmt.Errorf("Here be dragons: cmpl.parseExpression(%T)", in)) } -func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { - if in == nil { +func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement { + if stmt == nil { return nil } - switch in := in.(type) { - + switch stmt := stmt.(type) { case *ast.BlockStatement: - out := &_nodeBlockStatement{ - list: make([]_nodeStatement, len(in.List)), + out := &nodeBlockStatement{ + list: make([]nodeStatement, len(stmt.List)), } - for i, value := range in.List { + for i, value := range stmt.List { out.list[i] = cmpl.parseStatement(value) } return out case *ast.BranchStatement: - out := &_nodeBranchStatement{ - branch: in.Token, + out := &nodeBranchStatement{ + branch: stmt.Token, } - if in.Label != nil { - out.label = in.Label.Name + if stmt.Label != nil { + out.label = stmt.Label.Name } return out case *ast.DebuggerStatement: - return &_nodeDebuggerStatement{} + return &nodeDebuggerStatement{} case *ast.DoWhileStatement: - out := &_nodeDoWhileStatement{ - test: cmpl.parseExpression(in.Test), + out := &nodeDoWhileStatement{ + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -240,17 +238,17 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return emptyStatement case *ast.ExpressionStatement: - return &_nodeExpressionStatement{ - expression: cmpl.parseExpression(in.Expression), + return &nodeExpressionStatement{ + expression: cmpl.parseExpression(stmt.Expression), } case *ast.ForInStatement: - out := &_nodeForInStatement{ - into: cmpl.parseExpression(in.Into), - source: cmpl.parseExpression(in.Source), + out := &nodeForInStatement{ + into: cmpl.parseExpression(stmt.Into), + source: cmpl.parseExpression(stmt.Source), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -258,13 +256,13 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.ForStatement: - out := &_nodeForStatement{ - initializer: cmpl.parseExpression(in.Initializer), - update: cmpl.parseExpression(in.Update), - test: cmpl.parseExpression(in.Test), + out := &nodeForStatement{ + initializer: cmpl.parseExpression(stmt.Initializer), + update: cmpl.parseExpression(stmt.Update), + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -275,33 +273,33 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return emptyStatement case *ast.IfStatement: - return &_nodeIfStatement{ - test: cmpl.parseExpression(in.Test), - consequent: cmpl.parseStatement(in.Consequent), - alternate: cmpl.parseStatement(in.Alternate), + return &nodeIfStatement{ + test: cmpl.parseExpression(stmt.Test), + consequent: cmpl.parseStatement(stmt.Consequent), + alternate: cmpl.parseStatement(stmt.Alternate), } case *ast.LabelledStatement: - return &_nodeLabelledStatement{ - label: in.Label.Name, - statement: cmpl.parseStatement(in.Statement), + return &nodeLabelledStatement{ + label: stmt.Label.Name, + statement: cmpl.parseStatement(stmt.Statement), } case *ast.ReturnStatement: - return &_nodeReturnStatement{ - argument: cmpl.parseExpression(in.Argument), + return &nodeReturnStatement{ + argument: cmpl.parseExpression(stmt.Argument), } case *ast.SwitchStatement: - out := &_nodeSwitchStatement{ - discriminant: cmpl.parseExpression(in.Discriminant), - default_: in.Default, - body: make([]*_nodeCaseStatement, len(in.Body)), + out := &nodeSwitchStatement{ + discriminant: cmpl.parseExpression(stmt.Discriminant), + defaultIdx: stmt.Default, + body: make([]*nodeCaseStatement, len(stmt.Body)), } - for i, clause := range in.Body { - out.body[i] = &_nodeCaseStatement{ + for i, clause := range stmt.Body { + out.body[i] = &nodeCaseStatement{ test: cmpl.parseExpression(clause.Test), - consequent: make([]_nodeStatement, len(clause.Consequent)), + consequent: make([]nodeStatement, len(clause.Consequent)), } for j, value := range clause.Consequent { out.body[i].consequent[j] = cmpl.parseStatement(value) @@ -310,38 +308,38 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.ThrowStatement: - return &_nodeThrowStatement{ - argument: cmpl.parseExpression(in.Argument), + return &nodeThrowStatement{ + argument: cmpl.parseExpression(stmt.Argument), } case *ast.TryStatement: - out := &_nodeTryStatement{ - body: cmpl.parseStatement(in.Body), - finally: cmpl.parseStatement(in.Finally), - } - if in.Catch != nil { - out.catch = &_nodeCatchStatement{ - parameter: in.Catch.Parameter.Name, - body: cmpl.parseStatement(in.Catch.Body), + out := &nodeTryStatement{ + body: cmpl.parseStatement(stmt.Body), + finally: cmpl.parseStatement(stmt.Finally), + } + if stmt.Catch != nil { + out.catch = &nodeCatchStatement{ + parameter: stmt.Catch.Parameter.Name, + body: cmpl.parseStatement(stmt.Catch.Body), } } return out case *ast.VariableStatement: - out := &_nodeVariableStatement{ - list: make([]_nodeExpression, len(in.List)), + out := &nodeVariableStatement{ + list: make([]nodeExpression, len(stmt.List)), } - for i, value := range in.List { + for i, value := range stmt.List { out.list[i] = cmpl.parseExpression(value) } return out case *ast.WhileStatement: - out := &_nodeWhileStatement{ - test: cmpl.parseExpression(in.Test), + out := &nodeWhileStatement{ + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -349,308 +347,296 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.WithStatement: - return &_nodeWithStatement{ - object: cmpl.parseExpression(in.Object), - body: cmpl.parseStatement(in.Body), + return &nodeWithStatement{ + object: cmpl.parseExpression(stmt.Object), + body: cmpl.parseStatement(stmt.Body), } - + default: + panic(fmt.Sprintf("parse statement: unknown type %T", stmt)) } - - panic(fmt.Errorf("Here be dragons: cmpl.parseStatement(%T)", in)) } -func cmpl_parse(in *ast.Program) *_nodeProgram { - cmpl := _compiler{ +func cmplParse(in *ast.Program) *nodeProgram { + cmpl := compiler{ program: in, } + if cmpl.program != nil { + cmpl.file = cmpl.program.File + } + return cmpl.parse() } -func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram { - out := &_nodeProgram{ - body: make([]_nodeStatement, len(in.Body)), - file: in.File, +func (cmpl *compiler) parse() *nodeProgram { + out := &nodeProgram{ + body: make([]nodeStatement, len(cmpl.program.Body)), + file: cmpl.program.File, } - for i, value := range in.Body { + for i, value := range cmpl.program.Body { out.body[i] = cmpl.parseStatement(value) } - for _, value := range in.DeclarationList { + for _, value := range cmpl.program.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) + panic(fmt.Sprintf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) } } return out } -type _nodeProgram struct { - body []_nodeStatement - +type nodeProgram struct { + file *file.File + body []nodeStatement varList []string - functionList []*_nodeFunctionLiteral - - variableList []_nodeDeclaration - - file *file.File -} - -type _nodeDeclaration struct { - name string - definition _node + functionList []*nodeFunctionLiteral } -type _node interface { -} +type node interface{} type ( - _nodeExpression interface { - _node - _expressionNode() + nodeExpression interface { + node + expressionNode() } - _nodeArrayLiteral struct { - value []_nodeExpression + nodeArrayLiteral struct { + value []nodeExpression } - _nodeAssignExpression struct { + nodeAssignExpression struct { + left nodeExpression + right nodeExpression operator token.Token - left _nodeExpression - right _nodeExpression } - _nodeBinaryExpression struct { + nodeBinaryExpression struct { + left nodeExpression + right nodeExpression operator token.Token - left _nodeExpression - right _nodeExpression comparison bool } - _nodeBracketExpression struct { + nodeBracketExpression struct { + left nodeExpression + member nodeExpression idx file.Idx - left _nodeExpression - member _nodeExpression } - _nodeCallExpression struct { - callee _nodeExpression - argumentList []_nodeExpression + nodeCallExpression struct { + callee nodeExpression + argumentList []nodeExpression } - _nodeConditionalExpression struct { - test _nodeExpression - consequent _nodeExpression - alternate _nodeExpression + nodeConditionalExpression struct { + test nodeExpression + consequent nodeExpression + alternate nodeExpression } - _nodeDotExpression struct { - idx file.Idx - left _nodeExpression + nodeDotExpression struct { + left nodeExpression identifier string + idx file.Idx } - _nodeFunctionLiteral struct { + nodeFunctionLiteral struct { + body nodeStatement + file *file.File name string - body _nodeStatement source string parameterList []string varList []string - functionList []*_nodeFunctionLiteral - file *file.File + functionList []*nodeFunctionLiteral } - _nodeIdentifier struct { - idx file.Idx + nodeIdentifier struct { name string + idx file.Idx } - _nodeLiteral struct { + nodeLiteral struct { value Value } - _nodeNewExpression struct { - callee _nodeExpression - argumentList []_nodeExpression + nodeNewExpression struct { + callee nodeExpression + argumentList []nodeExpression } - _nodeObjectLiteral struct { - value []_nodeProperty + nodeObjectLiteral struct { + value []nodeProperty } - _nodeProperty struct { + nodeProperty struct { + value nodeExpression key string kind string - value _nodeExpression } - _nodeRegExpLiteral struct { + nodeRegExpLiteral struct { flags string pattern string // Value? - regexp *regexp.Regexp } - _nodeSequenceExpression struct { - sequence []_nodeExpression + nodeSequenceExpression struct { + sequence []nodeExpression } - _nodeThisExpression struct { - } + nodeThisExpression struct{} - _nodeUnaryExpression struct { + nodeUnaryExpression struct { + operand nodeExpression operator token.Token - operand _nodeExpression postfix bool } - _nodeVariableExpression struct { - idx file.Idx + nodeVariableExpression struct { + initializer nodeExpression name string - initializer _nodeExpression + idx file.Idx } ) type ( - _nodeStatement interface { - _node - _statementNode() + nodeStatement interface { + node + statementNode() } - _nodeBlockStatement struct { - list []_nodeStatement + nodeBlockStatement struct { + list []nodeStatement } - _nodeBranchStatement struct { - branch token.Token + nodeBranchStatement struct { label string + branch token.Token } - _nodeCaseStatement struct { - test _nodeExpression - consequent []_nodeStatement + nodeCaseStatement struct { + test nodeExpression + consequent []nodeStatement } - _nodeCatchStatement struct { + nodeCatchStatement struct { + body nodeStatement parameter string - body _nodeStatement } - _nodeDebuggerStatement struct { - } + nodeDebuggerStatement struct{} - _nodeDoWhileStatement struct { - test _nodeExpression - body []_nodeStatement + nodeDoWhileStatement struct { + test nodeExpression + body []nodeStatement } - _nodeEmptyStatement struct { - } + nodeEmptyStatement struct{} - _nodeExpressionStatement struct { - expression _nodeExpression + nodeExpressionStatement struct { + expression nodeExpression } - _nodeForInStatement struct { - into _nodeExpression - source _nodeExpression - body []_nodeStatement + nodeForInStatement struct { + into nodeExpression + source nodeExpression + body []nodeStatement } - _nodeForStatement struct { - initializer _nodeExpression - update _nodeExpression - test _nodeExpression - body []_nodeStatement + nodeForStatement struct { + initializer nodeExpression + update nodeExpression + test nodeExpression + body []nodeStatement } - _nodeIfStatement struct { - test _nodeExpression - consequent _nodeStatement - alternate _nodeStatement + nodeIfStatement struct { + test nodeExpression + consequent nodeStatement + alternate nodeStatement } - _nodeLabelledStatement struct { + nodeLabelledStatement struct { + statement nodeStatement label string - statement _nodeStatement } - _nodeReturnStatement struct { - argument _nodeExpression + nodeReturnStatement struct { + argument nodeExpression } - _nodeSwitchStatement struct { - discriminant _nodeExpression - default_ int - body []*_nodeCaseStatement + nodeSwitchStatement struct { + discriminant nodeExpression + body []*nodeCaseStatement + defaultIdx int } - _nodeThrowStatement struct { - argument _nodeExpression + nodeThrowStatement struct { + argument nodeExpression } - _nodeTryStatement struct { - body _nodeStatement - catch *_nodeCatchStatement - finally _nodeStatement + nodeTryStatement struct { + body nodeStatement + catch *nodeCatchStatement + finally nodeStatement } - _nodeVariableStatement struct { - list []_nodeExpression + nodeVariableStatement struct { + list []nodeExpression } - _nodeWhileStatement struct { - test _nodeExpression - body []_nodeStatement + nodeWhileStatement struct { + test nodeExpression + body []nodeStatement } - _nodeWithStatement struct { - object _nodeExpression - body _nodeStatement + nodeWithStatement struct { + object nodeExpression + body nodeStatement } ) -// _expressionNode - -func (*_nodeArrayLiteral) _expressionNode() {} -func (*_nodeAssignExpression) _expressionNode() {} -func (*_nodeBinaryExpression) _expressionNode() {} -func (*_nodeBracketExpression) _expressionNode() {} -func (*_nodeCallExpression) _expressionNode() {} -func (*_nodeConditionalExpression) _expressionNode() {} -func (*_nodeDotExpression) _expressionNode() {} -func (*_nodeFunctionLiteral) _expressionNode() {} -func (*_nodeIdentifier) _expressionNode() {} -func (*_nodeLiteral) _expressionNode() {} -func (*_nodeNewExpression) _expressionNode() {} -func (*_nodeObjectLiteral) _expressionNode() {} -func (*_nodeRegExpLiteral) _expressionNode() {} -func (*_nodeSequenceExpression) _expressionNode() {} -func (*_nodeThisExpression) _expressionNode() {} -func (*_nodeUnaryExpression) _expressionNode() {} -func (*_nodeVariableExpression) _expressionNode() {} - -// _statementNode - -func (*_nodeBlockStatement) _statementNode() {} -func (*_nodeBranchStatement) _statementNode() {} -func (*_nodeCaseStatement) _statementNode() {} -func (*_nodeCatchStatement) _statementNode() {} -func (*_nodeDebuggerStatement) _statementNode() {} -func (*_nodeDoWhileStatement) _statementNode() {} -func (*_nodeEmptyStatement) _statementNode() {} -func (*_nodeExpressionStatement) _statementNode() {} -func (*_nodeForInStatement) _statementNode() {} -func (*_nodeForStatement) _statementNode() {} -func (*_nodeIfStatement) _statementNode() {} -func (*_nodeLabelledStatement) _statementNode() {} -func (*_nodeReturnStatement) _statementNode() {} -func (*_nodeSwitchStatement) _statementNode() {} -func (*_nodeThrowStatement) _statementNode() {} -func (*_nodeTryStatement) _statementNode() {} -func (*_nodeVariableStatement) _statementNode() {} -func (*_nodeWhileStatement) _statementNode() {} -func (*_nodeWithStatement) _statementNode() {} +// expressionNode. +func (*nodeArrayLiteral) expressionNode() {} +func (*nodeAssignExpression) expressionNode() {} +func (*nodeBinaryExpression) expressionNode() {} +func (*nodeBracketExpression) expressionNode() {} +func (*nodeCallExpression) expressionNode() {} +func (*nodeConditionalExpression) expressionNode() {} +func (*nodeDotExpression) expressionNode() {} +func (*nodeFunctionLiteral) expressionNode() {} +func (*nodeIdentifier) expressionNode() {} +func (*nodeLiteral) expressionNode() {} +func (*nodeNewExpression) expressionNode() {} +func (*nodeObjectLiteral) expressionNode() {} +func (*nodeRegExpLiteral) expressionNode() {} +func (*nodeSequenceExpression) expressionNode() {} +func (*nodeThisExpression) expressionNode() {} +func (*nodeUnaryExpression) expressionNode() {} +func (*nodeVariableExpression) expressionNode() {} + +// statementNode + +func (*nodeBlockStatement) statementNode() {} +func (*nodeBranchStatement) statementNode() {} +func (*nodeCaseStatement) statementNode() {} +func (*nodeCatchStatement) statementNode() {} +func (*nodeDebuggerStatement) statementNode() {} +func (*nodeDoWhileStatement) statementNode() {} +func (*nodeEmptyStatement) statementNode() {} +func (*nodeExpressionStatement) statementNode() {} +func (*nodeForInStatement) statementNode() {} +func (*nodeForStatement) statementNode() {} +func (*nodeIfStatement) statementNode() {} +func (*nodeLabelledStatement) statementNode() {} +func (*nodeReturnStatement) statementNode() {} +func (*nodeSwitchStatement) statementNode() {} +func (*nodeThrowStatement) statementNode() {} +func (*nodeTryStatement) statementNode() {} +func (*nodeVariableStatement) statementNode() {} +func (*nodeWhileStatement) statementNode() {} +func (*nodeWithStatement) statementNode() {} diff --git a/vendor/github.com/robertkrimen/otto/console.go b/vendor/github.com/robertkrimen/otto/console.go index 948face77..e8d99cf7d 100644 --- a/vendor/github.com/robertkrimen/otto/console.go +++ b/vendor/github.com/robertkrimen/otto/console.go @@ -14,38 +14,33 @@ func formatForConsole(argumentList []Value) string { return strings.Join(output, " ") } -func builtinConsole_log(call FunctionCall) Value { - fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) +func builtinConsoleLog(call FunctionCall) Value { + fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. return Value{} } -func builtinConsole_error(call FunctionCall) Value { - fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) +func builtinConsoleError(call FunctionCall) Value { + fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. return Value{} } // Nothing happens. -func builtinConsole_dir(call FunctionCall) Value { +func builtinConsoleDir(call FunctionCall) Value { return Value{} } -func builtinConsole_time(call FunctionCall) Value { +func builtinConsoleTime(call FunctionCall) Value { return Value{} } -func builtinConsole_timeEnd(call FunctionCall) Value { +func builtinConsoleTimeEnd(call FunctionCall) Value { return Value{} } -func builtinConsole_trace(call FunctionCall) Value { +func builtinConsoleTrace(call FunctionCall) Value { return Value{} } -func builtinConsole_assert(call FunctionCall) Value { +func builtinConsoleAssert(call FunctionCall) Value { return Value{} } - -func (runtime *_runtime) newConsole() *_object { - - return newConsoleObject(runtime) -} diff --git a/vendor/github.com/robertkrimen/otto/consts.go b/vendor/github.com/robertkrimen/otto/consts.go new file mode 100644 index 000000000..f82aebc13 --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/consts.go @@ -0,0 +1,35 @@ +package otto + +const ( + // Common classes. + classStringName = "String" + classGoArrayName = "GoArray" + classGoSliceName = "GoSlice" + classNumberName = "Number" + classDateName = "Date" + classArrayName = "Array" + classFunctionName = "Function" + classObjectName = "Object" + classRegExpName = "RegExp" + classBooleanName = "Boolean" + classMathName = "Math" + classJSONName = "JSON" + + // Error classes. + classErrorName = "Error" + classEvalErrorName = "EvalError" + classTypeErrorName = "TypeError" + classRangeErrorName = "RangeError" + classReferenceErrorName = "ReferenceError" + classSyntaxErrorName = "SyntaxError" + classURIErrorName = "URIError" + + // Common properties. + propertyName = "name" + propertyLength = "length" + propertyPrototype = "prototype" + propertyConstructor = "constructor" + + // Common methods. + methodToString = "toString" +) diff --git a/vendor/github.com/robertkrimen/otto/dbg/dbg.go b/vendor/github.com/robertkrimen/otto/dbg/dbg.go index 8c27fa293..f0916572e 100644 --- a/vendor/github.com/robertkrimen/otto/dbg/dbg.go +++ b/vendor/github.com/robertkrimen/otto/dbg/dbg.go @@ -3,56 +3,55 @@ /* Package dbg is a println/printf/log-debugging utility library. - import ( - Dbg "github.com/robertkrimen/dbg" - ) + import ( + Dbg "github.com/robertkrimen/dbg" + ) - dbg, dbgf := Dbg.New() + dbg, dbgf := Dbg.New() - dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi) - # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793" + dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi) + # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793" - dbgf("With a %s formatting %.2f", "little", math.Pi) - # "2013/01/28 16:51:55 With a little formatting (3.14)" + dbgf("With a %s formatting %.2f", "little", math.Pi) + # "2013/01/28 16:51:55 With a little formatting (3.14)" - dbgf("%/fatal//A fatal debug statement: should not be here") - # "A fatal debug statement: should not be here" - # ...and then, os.Exit(1) + dbgf("%/fatal//A fatal debug statement: should not be here") + # "A fatal debug statement: should not be here" + # ...and then, os.Exit(1) - dbgf("%/panic//Can also panic %s", "this") - # "Can also panic this" - # ...as a panic, equivalent to: panic("Can also panic this") + dbgf("%/panic//Can also panic %s", "this") + # "Can also panic this" + # ...as a panic, equivalent to: panic("Can also panic this") - dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()") - # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()" + dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()") + # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()" - dbgf("%d %d", 1, 2, 3, 4, 5) - # "2013/01/28 17:16:32 Another example: 1 2 3 4 5" + dbgf("%d %d", 1, 2, 3, 4, 5) + # "2013/01/28 17:16:32 Another example: 1 2 3 4 5" - dbgf("%@: Include the function name for a little context (via %s)", "%@") - # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)" + dbgf("%@: Include the function name for a little context (via %s)", "%@") + # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)" By default, dbg uses log (log.Println, log.Printf, log.Panic, etc.) for output. However, you can also provide your own output destination by invoking dbg.New with a customization function: - import ( - "bytes" - Dbg "github.com/robertkrimen/dbg" - "os" - ) - - # dbg to os.Stderr - dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { - dbgr.SetOutput(os.Stderr) - }) - - # A slightly contrived example: - var buffer bytes.Buffer - dbg, dbgf := New(func(dbgr *Dbgr) { - dbgr.SetOutput(&buffer) - }) - + import ( + "bytes" + Dbg "github.com/robertkrimen/dbg" + "os" + ) + + # dbg to os.Stderr + dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { + dbgr.SetOutput(os.Stderr) + }) + + # A slightly contrived example: + var buffer bytes.Buffer + dbg, dbgf := New(func(dbgr *Dbgr) { + dbgr.SetOutput(&buffer) + }) */ package dbg @@ -63,7 +62,7 @@ import ( "log" "os" "regexp" - "runtime" + goruntime "runtime" "strings" "unicode" ) @@ -130,30 +129,28 @@ func parseFormat(format string) (frmt _frmt) { } type Dbgr struct { - emit _emit + emit emit } type DbgFunction func(values ...interface{}) func NewDbgr() *Dbgr { - self := &Dbgr{} - return self + return &Dbgr{} } /* New will create and return a pair of debugging functions. You can customize where they output to by passing in an (optional) customization function: - import ( - Dbg "github.com/robertkrimen/dbg" - "os" - ) - - # dbg to os.Stderr - dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { - dbgr.SetOutput(os.Stderr) - }) + import ( + Dbg "github.com/robertkrimen/dbg" + "os" + ) + # dbg to os.Stderr + dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { + dbgr.SetOutput(os.Stderr) + }) */ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) { dbgr := NewDbgr() @@ -165,26 +162,25 @@ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) { return dbgr.DbgDbgf() } -func (self Dbgr) Dbg(values ...interface{}) { - self.getEmit().emit(_frmt{}, "", values...) +func (d Dbgr) Dbg(values ...interface{}) { + d.getEmit().emit(_frmt{}, "", values...) } -func (self Dbgr) Dbgf(values ...interface{}) { - self.dbgf(values...) +func (d Dbgr) Dbgf(values ...interface{}) { + d.dbgf(values...) } -func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { +func (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { dbg = func(vl ...interface{}) { - self.Dbg(vl...) + d.Dbg(vl...) } dbgf = func(vl ...interface{}) { - self.dbgf(vl...) + d.dbgf(vl...) } return dbg, dbgf // Redundant, but... } -func (self Dbgr) dbgf(values ...interface{}) { - +func (d Dbgr) dbgf(values ...interface{}) { var frmt _frmt if len(values) > 0 { tmp := fmt.Sprint(values[0]) @@ -192,7 +188,7 @@ func (self Dbgr) dbgf(values ...interface{}) { values = values[1:] } - buffer_f := bytes.Buffer{} + buf := bytes.Buffer{} format := frmt.format end := len(format) for at := 0; at < end; { @@ -201,7 +197,7 @@ func (self Dbgr) dbgf(values ...interface{}) { at++ } if at > last { - buffer_f.WriteString(format[last:at]) + buf.WriteString(format[last:at]) } if at >= end { break @@ -211,100 +207,97 @@ func (self Dbgr) dbgf(values ...interface{}) { // format[at] == ? if format[at] == '@' { depth := 2 - pc, _, _, _ := runtime.Caller(depth) - name := runtime.FuncForPC(pc).Name() - buffer_f.WriteString(name) + pc, _, _, _ := goruntime.Caller(depth) + name := goruntime.FuncForPC(pc).Name() + buf.WriteString(name) } else { - buffer_f.WriteString(format[at-1 : at+1]) + buf.WriteString(format[at-1 : at+1]) } at++ } - //values_f := append([]interface{}{}, values[0:frmt.operandCount]...) - values_f := values[0:frmt.operandCount] - values_dbg := values[frmt.operandCount:] - if len(values_dbg) > 0 { + //valuesF := append([]interface{}{}, values[0:frmt.operandCount]...) + valuesF := values[0:frmt.operandCount] + valuesDbg := values[frmt.operandCount:] + if len(valuesDbg) > 0 { // Adjust frmt.format: // (%v instead of %s because: frmt.check) - { - tmp := format - if len(tmp) > 0 { - if unicode.IsSpace(rune(tmp[len(tmp)-1])) { - buffer_f.WriteString("%v") - } else { - buffer_f.WriteString(" %v") - } - } else if frmt.check { - // Performing a check, so no output + tmp := format + if len(tmp) > 0 { + if unicode.IsSpace(rune(tmp[len(tmp)-1])) { + buf.WriteString("%v") } else { - buffer_f.WriteString("%v") + buf.WriteString(" %v") } + } else if frmt.check { + // Performing a check, so no output + } else { + buf.WriteString("%v") } - // Adjust values_f: + // Adjust valuesF: if !frmt.check { tmp := []string{} - for _, value := range values_dbg { + for _, value := range valuesDbg { tmp = append(tmp, fmt.Sprintf("%v", value)) } - // First, make a copy of values_f, so we avoid overwriting values_dbg when appending - values_f = append([]interface{}{}, values_f...) - values_f = append(values_f, strings.Join(tmp, " ")) + // First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending + valuesF = append([]interface{}{}, valuesF...) + valuesF = append(valuesF, strings.Join(tmp, " ")) } } - format = buffer_f.String() + format = buf.String() if frmt.check { // We do not actually emit to the log, but panic if // a non-nil value is detected (e.g. a non-nil error) - for _, value := range values_dbg { + for _, value := range valuesDbg { if value != nil { if format == "" { panic(value) } else { - panic(fmt.Sprintf(format, append(values_f, value)...)) + panic(fmt.Sprintf(format, append(valuesF, value)...)) } } } } else { - self.getEmit().emit(frmt, format, values_f...) + d.getEmit().emit(frmt, format, valuesF...) } } // Idiot-proof &Dbgr{}, etc. -func (self *Dbgr) getEmit() _emit { - if self.emit == nil { - self.emit = standardEmit() +func (d *Dbgr) getEmit() emit { + if d.emit == nil { + d.emit = standardEmit() } - return self.emit + return d.emit } // SetOutput will accept the following as a destination for output: // -// *log.Logger Print*/Panic*/Fatal* of the logger -// io.Writer - -// nil Reset to the default output (os.Stderr) -// "log" Print*/Panic*/Fatal* via the "log" package -// -func (self *Dbgr) SetOutput(output interface{}) { +// *log.Logger Print*/Panic*/Fatal* of the logger +// io.Writer - +// nil Reset to the default output (os.Stderr) +// "log" Print*/Panic*/Fatal* via the "log" package +func (d *Dbgr) SetOutput(output interface{}) { if output == nil { - self.emit = standardEmit() + d.emit = standardEmit() return } switch output := output.(type) { case *log.Logger: - self.emit = _emitLogger{ + d.emit = emitLogger{ logger: output, } return case io.Writer: - self.emit = _emitWriter{ + d.emit = emitWriter{ writer: output, } return case string: if output == "log" { - self.emit = _emitLog{} + d.emit = emitLog{} return } } @@ -315,8 +308,8 @@ func (self *Dbgr) SetOutput(output interface{}) { // = emit = // // ======== // -func standardEmit() _emit { - return _emitWriter{ +func standardEmit() emit { + return emitWriter{ writer: os.Stderr, } } @@ -329,50 +322,50 @@ func ln(tmp string) string { return tmp } -type _emit interface { +type emit interface { emit(_frmt, string, ...interface{}) } -type _emitWriter struct { +type emitWriter struct { writer io.Writer } -func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) { +func (ew emitWriter) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { - fmt.Fprintln(self.writer, values...) + fmt.Fprintln(ew.writer, values...) } else { if frmt.panic { panic(fmt.Sprintf(format, values...)) } - fmt.Fprintf(self.writer, ln(format), values...) + fmt.Fprintf(ew.writer, ln(format), values...) if frmt.fatal { os.Exit(1) } } } -type _emitLogger struct { +type emitLogger struct { logger *log.Logger } -func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) { +func (el emitLogger) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { - self.logger.Println(values...) + el.logger.Println(values...) } else { if frmt.panic { - self.logger.Panicf(format, values...) + el.logger.Panicf(format, values...) } else if frmt.fatal { - self.logger.Fatalf(format, values...) + el.logger.Fatalf(format, values...) } else { - self.logger.Printf(format, values...) + el.logger.Printf(format, values...) } } } -type _emitLog struct { +type emitLog struct { } -func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) { +func (el emitLog) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { log.Println(values...) } else { diff --git a/vendor/github.com/robertkrimen/otto/error.go b/vendor/github.com/robertkrimen/otto/error.go index c8b5af446..ebbfc69fa 100644 --- a/vendor/github.com/robertkrimen/otto/error.go +++ b/vendor/github.com/robertkrimen/otto/error.go @@ -7,65 +7,63 @@ import ( "github.com/robertkrimen/otto/file" ) -type _exception struct { +type exception struct { value interface{} } -func newException(value interface{}) *_exception { - return &_exception{ +func newException(value interface{}) *exception { + return &exception{ value: value, } } -func (self *_exception) eject() interface{} { - value := self.value - self.value = nil // Prevent Go from holding on to the value, whatever it is +func (e *exception) eject() interface{} { + value := e.value + e.value = nil // Prevent Go from holding on to the value, whatever it is return value } -type _error struct { +type ottoError struct { name string message string - trace []_frame + trace []frame offset int } -func (err _error) format() string { - if len(err.name) == 0 { - return err.message +func (e ottoError) format() string { + if len(e.name) == 0 { + return e.message } - if len(err.message) == 0 { - return err.name + if len(e.message) == 0 { + return e.name } - return fmt.Sprintf("%s: %s", err.name, err.message) + return fmt.Sprintf("%s: %s", e.name, e.message) } -func (err _error) formatWithStack() string { - str := err.format() + "\n" - for _, frame := range err.trace { - str += " at " + frame.location() + "\n" +func (e ottoError) formatWithStack() string { + str := e.format() + "\n" + for _, frm := range e.trace { + str += " at " + frm.location() + "\n" } return str } -type _frame struct { - native bool +type frame struct { + fn interface{} + file *file.File nativeFile string + callee string nativeLine int - file *file.File offset int - callee string - fn interface{} + native bool } -var ( - nativeFrame = _frame{} -) +var nativeFrame = frame{} -type _at int +type at int -func (fr _frame) location() string { +func (fr frame) location() string { str := "" switch { @@ -95,48 +93,52 @@ func (fr _frame) location() string { // An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. type Error struct { - _error + ottoError } // Error returns a description of the error // -// TypeError: 'def' is not a function -// -func (err Error) Error() string { - return err.format() +// TypeError: 'def' is not a function +func (e Error) Error() string { + return e.format() } // String returns a description of the error and a trace of where the // error occurred. // -// TypeError: 'def' is not a function -// at xyz (:3:9) -// at :7:1/ -// -func (err Error) String() string { - return err.formatWithStack() +// TypeError: 'def' is not a function +// at xyz (:3:9) +// at :7:1/ +func (e Error) String() string { + return e.formatWithStack() } -func (err _error) describe(format string, in ...interface{}) string { +// GoString returns a description of the error and a trace of where the +// error occurred. Printing with %#v will trigger this behaviour. +func (e Error) GoString() string { + return e.formatWithStack() +} + +func (e ottoError) describe(format string, in ...interface{}) string { return fmt.Sprintf(format, in...) } -func (self _error) messageValue() Value { - if self.message == "" { +func (e ottoError) messageValue() Value { + if e.message == "" { return Value{} } - return toValue_string(self.message) + return stringValue(e.message) } -func (rt *_runtime) typeErrorResult(throw bool) bool { +func (rt *runtime) typeErrorResult(throw bool) bool { if throw { panic(rt.panicTypeError()) } return false } -func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}) _error { - err := _error{ +func newError(rt *runtime, name string, stackFramesToPop int, in ...interface{}) ottoError { + err := ottoError{ name: name, offset: -1, } @@ -144,21 +146,21 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{} length := len(in) if rt != nil && rt.scope != nil { - scope := rt.scope + curScope := rt.scope - for i := 0; i < stackFramesToPop; i++ { - if scope.outer != nil { - scope = scope.outer + for range stackFramesToPop { + if curScope.outer != nil { + curScope = curScope.outer } } - frame := scope.frame + frm := curScope.frame if length > 0 { - if at, ok := in[length-1].(_at); ok { + if atv, ok := in[length-1].(at); ok { in = in[0 : length-1] - if scope != nil { - frame.offset = int(at) + if curScope != nil { + frm.offset = int(atv) } length-- } @@ -169,54 +171,52 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{} limit := rt.traceLimit - err.trace = append(err.trace, frame) - if scope != nil { - for scope = scope.outer; scope != nil; scope = scope.outer { + err.trace = append(err.trace, frm) + if curScope != nil { + for curScope = curScope.outer; curScope != nil; curScope = curScope.outer { if limit--; limit == 0 { break } - if scope.frame.offset >= 0 { - err.trace = append(err.trace, scope.frame) + if curScope.frame.offset >= 0 { + err.trace = append(err.trace, curScope.frame) } } } - } else { - if length > 0 { - description, in = in[0].(string), in[1:] - } + } else if length > 0 { + description, in = in[0].(string), in[1:] } err.message = err.describe(description, in...) return err } -func (rt *_runtime) panicTypeError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicTypeError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "TypeError", 0, argumentList...), } } -func (rt *_runtime) panicReferenceError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicReferenceError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "ReferenceError", 0, argumentList...), } } -func (rt *_runtime) panicURIError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicURIError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "URIError", 0, argumentList...), } } -func (rt *_runtime) panicSyntaxError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicSyntaxError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "SyntaxError", 0, argumentList...), } } -func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicRangeError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "RangeError", 0, argumentList...), } } @@ -224,20 +224,19 @@ func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { func catchPanic(function func()) (err error) { defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() + if excep, ok := caught.(*exception); ok { + caught = excep.eject() } switch caught := caught.(type) { case *Error: err = caught return - case _error: + case ottoError: err = &Error{caught} return case Value: - if vl := caught._object(); vl != nil { - switch vl := vl.value.(type) { - case _error: + if vl := caught.object(); vl != nil { + if vl, ok := vl.value.(ottoError); ok { err = &Error{vl} return } diff --git a/vendor/github.com/robertkrimen/otto/evaluate.go b/vendor/github.com/robertkrimen/otto/evaluate.go index 093054cc3..269b9dd0a 100644 --- a/vendor/github.com/robertkrimen/otto/evaluate.go +++ b/vendor/github.com/robertkrimen/otto/evaluate.go @@ -8,12 +8,12 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_runtime) evaluateMultiply(left float64, right float64) Value { +func (rt *runtime) evaluateMultiply(left float64, right float64) Value { //nolint:unused // TODO 11.5.1 return Value{} } -func (self *_runtime) evaluateDivide(left float64, right float64) Value { +func (rt *runtime) evaluateDivide(left float64, right float64) Value { if math.IsNaN(left) || math.IsNaN(right) { return NaNValue() } @@ -26,63 +26,57 @@ func (self *_runtime) evaluateDivide(left float64, right float64) Value { if math.IsInf(left, 0) { if math.Signbit(left) == math.Signbit(right) { return positiveInfinityValue() - } else { - return negativeInfinityValue() } + return negativeInfinityValue() } if math.IsInf(right, 0) { if math.Signbit(left) == math.Signbit(right) { return positiveZeroValue() - } else { - return negativeZeroValue() } + return negativeZeroValue() } if right == 0 { if math.Signbit(left) == math.Signbit(right) { return positiveInfinityValue() - } else { - return negativeInfinityValue() } + return negativeInfinityValue() } - return toValue_float64(left / right) + return float64Value(left / right) } -func (self *_runtime) evaluateModulo(left float64, right float64) Value { +func (rt *runtime) evaluateModulo(left float64, right float64) Value { //nolint:unused // TODO 11.5.3 return Value{} } -func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { - +func (rt *runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { leftValue := left.resolve() switch operator { - // Additive case token.PLUS: - leftValue = toPrimitive(leftValue) + leftValue = toPrimitiveValue(leftValue) rightValue := right.resolve() - rightValue = toPrimitive(rightValue) + rightValue = toPrimitiveValue(rightValue) if leftValue.IsString() || rightValue.IsString() { - return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) - } else { - return toValue_float64(leftValue.float64() + rightValue.float64()) + return stringValue(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) } + return float64Value(leftValue.float64() + rightValue.float64()) case token.MINUS: rightValue := right.resolve() - return toValue_float64(leftValue.float64() - rightValue.float64()) + return float64Value(leftValue.float64() - rightValue.float64()) // Multiplicative case token.MULTIPLY: rightValue := right.resolve() - return toValue_float64(leftValue.float64() * rightValue.float64()) + return float64Value(leftValue.float64() * rightValue.float64()) case token.SLASH: rightValue := right.resolve() - return self.evaluateDivide(leftValue.float64(), rightValue.float64()) + return rt.evaluateDivide(leftValue.float64(), rightValue.float64()) case token.REMAINDER: rightValue := right.resolve() - return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64())) + return float64Value(math.Mod(leftValue.float64(), rightValue.float64())) // Logical case token.LOGICAL_AND: @@ -90,86 +84,66 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value if !left { return falseValue } - return toValue_bool(right.resolve().bool()) + return boolValue(right.resolve().bool()) case token.LOGICAL_OR: left := leftValue.bool() if left { return trueValue } - return toValue_bool(right.resolve().bool()) + return boolValue(right.resolve().bool()) // Bitwise case token.AND: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) & toInt32(rightValue)) + return int32Value(toInt32(leftValue) & toInt32(rightValue)) case token.OR: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) | toInt32(rightValue)) + return int32Value(toInt32(leftValue) | toInt32(rightValue)) case token.EXCLUSIVE_OR: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) ^ toInt32(rightValue)) + return int32Value(toInt32(leftValue) ^ toInt32(rightValue)) // Shift // (Masking of 0x1f is to restrict the shift to a maximum of 31 places) case token.SHIFT_LEFT: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) + return int32Value(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) case token.SHIFT_RIGHT: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) + return int32Value(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.UNSIGNED_SHIFT_RIGHT: rightValue := right.resolve() // Shifting an unsigned integer is a logical shift - return toValue_uint32(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) + return uint32Value(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.INSTANCEOF: rightValue := right.resolve() if !rightValue.IsObject() { - panic(self.panicTypeError("Expecting a function in instanceof check, but got: %v", rightValue)) + panic(rt.panicTypeError("invalid kind %s for instanceof (expected object)", rightValue.kind)) } - return toValue_bool(rightValue._object().hasInstance(leftValue)) + return boolValue(rightValue.object().hasInstance(leftValue)) case token.IN: rightValue := right.resolve() if !rightValue.IsObject() { - panic(self.panicTypeError()) + panic(rt.panicTypeError("invalid kind %s for in (expected object)", rightValue.kind)) } - return toValue_bool(rightValue._object().hasProperty(leftValue.string())) + return boolValue(rightValue.object().hasProperty(leftValue.string())) } panic(hereBeDragons(operator)) } -func valueKindDispatchKey(left _valueKind, right _valueKind) int { - return (int(left) << 2) + int(right) -} - -var equalDispatch map[int](func(Value, Value) bool) = makeEqualDispatch() - -func makeEqualDispatch() map[int](func(Value, Value) bool) { - key := valueKindDispatchKey - return map[int](func(Value, Value) bool){ - - key(valueNumber, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() }, - key(valueString, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() }, - key(valueObject, valueNumber): func(x Value, y Value) bool { return x.float64() == y.float64() }, - key(valueObject, valueString): func(x Value, y Value) bool { return x.float64() == y.float64() }, - } -} - -type _lessThanResult int +type lessThanResult int const ( - lessThanFalse _lessThanResult = iota + lessThanFalse lessThanResult = iota lessThanTrue lessThanUndefined ) -func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult { - - x := Value{} - y := x - +func calculateLessThan(left Value, right Value, leftFirst bool) lessThanResult { + var x, y Value if leftFirst { x = toNumberPrimitive(left) y = toNumberPrimitive(right) @@ -178,7 +152,7 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult x = toNumberPrimitive(left) } - result := false + var result bool if x.kind != valueString || y.kind != valueString { x, y := x.float64(), y.float64() if math.IsNaN(x) || math.IsNaN(y) { @@ -197,47 +171,46 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult return lessThanFalse } -// FIXME Probably a map is not the most efficient way to do this -var lessThanTable [4](map[_lessThanResult]bool) = [4](map[_lessThanResult]bool){ +// FIXME Probably a map is not the most efficient way to do this. +var lessThanTable [4](map[lessThanResult]bool) = [4](map[lessThanResult]bool){ // < - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: false, lessThanTrue: true, lessThanUndefined: false, }, // > - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: false, lessThanTrue: true, lessThanUndefined: false, }, // <= - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: true, lessThanTrue: false, lessThanUndefined: false, }, // >= - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: true, lessThanTrue: false, lessThanUndefined: false, }, } -func (self *_runtime) calculateComparison(comparator token.Token, left Value, right Value) bool { - +func (rt *runtime) calculateComparison(comparator token.Token, left Value, right Value) bool { // FIXME Use strictEqualityComparison? // TODO This might be redundant now (with regards to evaluateComparison) x := left.resolve() y := right.resolve() - kindEqualKind := false + var kindEqualKind bool + var negate bool result := true - negate := false switch comparator { case token.LESS: @@ -261,27 +234,28 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri negate = true fallthrough case token.EQUAL: - if x.kind == y.kind { + switch { + case x.kind == y.kind: kindEqualKind = true - } else if x.kind <= valueNull && y.kind <= valueNull { + case x.kind <= valueNull && y.kind <= valueNull: result = true - } else if x.kind <= valueNull || y.kind <= valueNull { + case x.kind <= valueNull || y.kind <= valueNull: result = false - } else if x.kind <= valueString && y.kind <= valueString { + case x.kind <= valueString && y.kind <= valueString: result = x.float64() == y.float64() - } else if x.kind == valueBoolean { - result = self.calculateComparison(token.EQUAL, toValue_float64(x.float64()), y) - } else if y.kind == valueBoolean { - result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.float64())) - } else if x.kind == valueObject { - result = self.calculateComparison(token.EQUAL, toPrimitive(x), y) - } else if y.kind == valueObject { - result = self.calculateComparison(token.EQUAL, x, toPrimitive(y)) - } else { - panic(hereBeDragons("Unable to test for equality: %v ==? %v", x, y)) + case x.kind == valueBoolean: + result = rt.calculateComparison(token.EQUAL, float64Value(x.float64()), y) + case y.kind == valueBoolean: + result = rt.calculateComparison(token.EQUAL, x, float64Value(y.float64())) + case x.kind == valueObject: + result = rt.calculateComparison(token.EQUAL, toPrimitiveValue(x), y) + case y.kind == valueObject: + result = rt.calculateComparison(token.EQUAL, x, toPrimitiveValue(y)) + default: + panic(fmt.Sprintf("unknown types for equal: %v ==? %v", x, y)) } default: - panic(fmt.Errorf("Unknown comparator %s", comparator.String())) + panic("unknown comparator " + comparator.String()) } if kindEqualKind { @@ -301,7 +275,7 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri case valueBoolean: result = x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + result = x.object() == y.object() default: goto ERROR } diff --git a/vendor/github.com/robertkrimen/otto/file/README.markdown b/vendor/github.com/robertkrimen/otto/file/README.markdown deleted file mode 100644 index 79757baa8..000000000 --- a/vendor/github.com/robertkrimen/otto/file/README.markdown +++ /dev/null @@ -1,110 +0,0 @@ -# file --- - import "github.com/robertkrimen/otto/file" - -Package file encapsulates the file abstractions used by the ast & parser. - -## Usage - -#### type File - -```go -type File struct { -} -``` - - -#### func NewFile - -```go -func NewFile(filename, src string, base int) *File -``` - -#### func (*File) Base - -```go -func (fl *File) Base() int -``` - -#### func (*File) Name - -```go -func (fl *File) Name() string -``` - -#### func (*File) Source - -```go -func (fl *File) Source() string -``` - -#### type FileSet - -```go -type FileSet struct { -} -``` - -A FileSet represents a set of source files. - -#### func (*FileSet) AddFile - -```go -func (self *FileSet) AddFile(filename, src string) int -``` -AddFile adds a new file with the given filename and src. - -This an internal method, but exported for cross-package use. - -#### func (*FileSet) File - -```go -func (self *FileSet) File(idx Idx) *File -``` - -#### func (*FileSet) Position - -```go -func (self *FileSet) Position(idx Idx) *Position -``` -Position converts an Idx in the FileSet into a Position. - -#### type Idx - -```go -type Idx int -``` - -Idx is a compact encoding of a source position within a file set. It can be -converted into a Position for a more convenient, but much larger, -representation. - -#### type Position - -```go -type Position struct { - Filename string // The filename where the error occurred, if any - Offset int // The src offset - Line int // The line number, starting at 1 - Column int // The column number, starting at 1 (The character count) - -} -``` - -Position describes an arbitrary source position including the filename, line, -and column location. - -#### func (*Position) String - -```go -func (self *Position) String() string -``` -String returns a string in one of several forms: - - file:line:column A valid position with filename - line:column A valid position without filename - file An invalid position with filename - - An invalid position without filename - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/file/file.go b/vendor/github.com/robertkrimen/otto/file/file.go index 9093206e8..99dd60701 100644 --- a/vendor/github.com/robertkrimen/otto/file/file.go +++ b/vendor/github.com/robertkrimen/otto/file/file.go @@ -1,5 +1,4 @@ // Package file encapsulates the file abstractions used by the ast & parser. -// package file import ( @@ -21,13 +20,12 @@ type Position struct { Offset int // The src offset Line int // The line number, starting at 1 Column int // The column number, starting at 1 (The character count) - } // A Position is valid if the line number is > 0. -func (self *Position) isValid() bool { - return self.Line > 0 +func (p *Position) isValid() bool { + return p.Line > 0 } // String returns a string in one of several forms: @@ -36,14 +34,13 @@ func (self *Position) isValid() bool { // line:column A valid position without filename // file An invalid position with filename // - An invalid position without filename -// -func (self *Position) String() string { - str := self.Filename - if self.isValid() { +func (p *Position) String() string { + str := p.Filename + if p.isValid() { if str != "" { str += ":" } - str += fmt.Sprintf("%d:%d", self.Line, self.Column) + str += fmt.Sprintf("%d:%d", p.Line, p.Column) } if str == "" { str = "-" @@ -51,38 +48,37 @@ func (self *Position) String() string { return str } -// FileSet - // A FileSet represents a set of source files. type FileSet struct { - files []*File last *File + files []*File } // AddFile adds a new file with the given filename and src. // // This an internal method, but exported for cross-package use. -func (self *FileSet) AddFile(filename, src string) int { - base := self.nextBase() +func (fs *FileSet) AddFile(filename, src string) int { + base := fs.nextBase() file := &File{ name: filename, src: src, base: base, } - self.files = append(self.files, file) - self.last = file + fs.files = append(fs.files, file) + fs.last = file return base } -func (self *FileSet) nextBase() int { - if self.last == nil { +func (fs *FileSet) nextBase() int { + if fs.last == nil { return 1 } - return self.last.base + len(self.last.src) + 1 + return fs.last.base + len(fs.last.src) + 1 } -func (self *FileSet) File(idx Idx) *File { - for _, file := range self.files { +// File returns the File at idx or nil if not found. +func (fs *FileSet) File(idx Idx) *File { + for _, file := range fs.files { if idx <= Idx(file.base+len(file.src)) { return file } @@ -91,8 +87,8 @@ func (self *FileSet) File(idx Idx) *File { } // Position converts an Idx in the FileSet into a Position. -func (self *FileSet) Position(idx Idx) *Position { - for _, file := range self.files { +func (fs *FileSet) Position(idx Idx) *Position { + for _, file := range fs.files { if idx <= Idx(file.base+len(file.src)) { return file.Position(idx - Idx(file.base)) } @@ -101,13 +97,15 @@ func (self *FileSet) Position(idx Idx) *Position { return nil } +// File represents a file to parse. type File struct { + sm *sourcemap.Consumer name string src string - base int // This will always be 1 or greater - sm *sourcemap.Consumer + base int } +// NewFile returns a new file with the given filename, src and base. func NewFile(filename, src string, base int) *File { return &File{ name: filename, @@ -116,23 +114,28 @@ func NewFile(filename, src string, base int) *File { } } +// WithSourceMap sets the source map of fl. func (fl *File) WithSourceMap(sm *sourcemap.Consumer) *File { fl.sm = sm return fl } +// Name returns the name of fl. func (fl *File) Name() string { return fl.name } +// Source returns the source of fl. func (fl *File) Source() string { return fl.src } +// Base returns the base of fl. func (fl *File) Base() int { return fl.base } +// Position returns the position at idx or nil if not valid. func (fl *File) Position(idx Idx) *Position { position := &Position{} diff --git a/vendor/github.com/robertkrimen/otto/generate.go b/vendor/github.com/robertkrimen/otto/generate.go new file mode 100644 index 000000000..767091e8e --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/generate.go @@ -0,0 +1,4 @@ +package otto + +//go:generate go run ./tools/gen-jscore -output inline.go +//go:generate stringer -type=valueKind -trimprefix=value -output=value_kind.gen.go diff --git a/vendor/github.com/robertkrimen/otto/global.go b/vendor/github.com/robertkrimen/otto/global.go index eb2a2a0fb..a46e6bcfb 100644 --- a/vendor/github.com/robertkrimen/otto/global.go +++ b/vendor/github.com/robertkrimen/otto/global.go @@ -7,12 +7,12 @@ import ( var ( prototypeValueObject = interface{}(nil) - prototypeValueFunction = _nativeFunctionObject{ + prototypeValueFunction = nativeFunctionObject{ call: func(_ FunctionCall) Value { return Value{} }, } - prototypeValueString = _stringASCII("") + prototypeValueString = stringASCII("") // TODO Make this just false? prototypeValueBoolean = Value{ kind: valueBoolean, @@ -22,7 +22,7 @@ var ( kind: valueNumber, value: 0, } - prototypeValueDate = _dateObject{ + prototypeValueDate = dateObject{ epoch: 0, isNaN: false, time: time.Unix(0, 0).UTC(), @@ -31,7 +31,7 @@ var ( value: 0, }, } - prototypeValueRegExp = _regExpObject{ + prototypeValueRegExp = regExpObject{ regularExpression: nil, global: false, ignoreCase: false, @@ -41,104 +41,101 @@ var ( } ) -func newContext() *_runtime { +func newContext() *runtime { + rt := &runtime{} - self := &_runtime{} + rt.globalStash = rt.newObjectStash(nil, nil) + rt.globalObject = rt.globalStash.object - self.globalStash = self.newObjectStash(nil, nil) - self.globalObject = self.globalStash.object + rt.newContext() - _newContext(self) + rt.eval = rt.globalObject.property["eval"].value.(Value).value.(*object) + rt.globalObject.prototype = rt.global.ObjectPrototype - self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object) - self.globalObject.prototype = self.global.ObjectPrototype - - return self + return rt } -func (runtime *_runtime) newBaseObject() *_object { - self := newObject(runtime, "") - return self +func (rt *runtime) newBaseObject() *object { + return newObject(rt, "") } -func (runtime *_runtime) newClassObject(class string) *_object { - return newObject(runtime, class) +func (rt *runtime) newClassObject(class string) *object { + return newObject(rt, class) } -func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object { - self := runtime.newClassObject(class) - self.value = value - return self +func (rt *runtime) newPrimitiveObject(class string, value Value) *object { + o := rt.newClassObject(class) + o.value = value + return o } -func (self *_object) primitiveValue() Value { - switch value := self.value.(type) { +func (o *object) primitiveValue() Value { + switch value := o.value.(type) { case Value: return value - case _stringObject: - return toValue_string(value.String()) + case stringObjecter: + return stringValue(value.String()) } return Value{} } -func (self *_object) hasPrimitive() bool { - switch self.value.(type) { - case Value, _stringObject: +func (o *object) hasPrimitive() bool { //nolint:unused + switch o.value.(type) { + case Value, stringObjecter: return true } return false } -func (runtime *_runtime) newObject() *_object { - self := runtime.newClassObject("Object") - self.prototype = runtime.global.ObjectPrototype - return self +func (rt *runtime) newObject() *object { + o := rt.newClassObject(classObjectName) + o.prototype = rt.global.ObjectPrototype + return o } -func (runtime *_runtime) newArray(length uint32) *_object { - self := runtime.newArrayObject(length) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newArray(length uint32) *object { + o := rt.newArrayObject(length) + o.prototype = rt.global.ArrayPrototype + return o } -func (runtime *_runtime) newArrayOf(valueArray []Value) *_object { - self := runtime.newArray(uint32(len(valueArray))) +func (rt *runtime) newArrayOf(valueArray []Value) *object { + o := rt.newArray(uint32(len(valueArray))) for index, value := range valueArray { if value.isEmpty() { continue } - self.defineProperty(strconv.FormatInt(int64(index), 10), value, 0111, false) + o.defineProperty(strconv.FormatInt(int64(index), 10), value, 0o111, false) } - return self + return o } -func (runtime *_runtime) newString(value Value) *_object { - self := runtime.newStringObject(value) - self.prototype = runtime.global.StringPrototype - return self +func (rt *runtime) newString(value Value) *object { + o := rt.newStringObject(value) + o.prototype = rt.global.StringPrototype + return o } -func (runtime *_runtime) newBoolean(value Value) *_object { - self := runtime.newBooleanObject(value) - self.prototype = runtime.global.BooleanPrototype - return self +func (rt *runtime) newBoolean(value Value) *object { + o := rt.newBooleanObject(value) + o.prototype = rt.global.BooleanPrototype + return o } -func (runtime *_runtime) newNumber(value Value) *_object { - self := runtime.newNumberObject(value) - self.prototype = runtime.global.NumberPrototype - return self +func (rt *runtime) newNumber(value Value) *object { + o := rt.newNumberObject(value) + o.prototype = rt.global.NumberPrototype + return o } -func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object { - +func (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object { pattern := "" flags := "" - if object := patternValue._object(); object != nil && object.class == "RegExp" { + if obj := patternValue.object(); obj != nil && obj.class == classRegExpName { if flagsValue.IsDefined() { - panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another")) + panic(rt.panicTypeError("Cannot supply flags when constructing one RegExp from another")) } - regExp := object.regExpValue() + regExp := obj.regExpValue() pattern = regExp.source flags = regExp.flags } else { @@ -150,72 +147,71 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec } } - return runtime._newRegExp(pattern, flags) + return rt.newRegExpDirect(pattern, flags) } -func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object { - self := runtime.newRegExpObject(pattern, flags) - self.prototype = runtime.global.RegExpPrototype - return self +func (rt *runtime) newRegExpDirect(pattern string, flags string) *object { + o := rt.newRegExpObject(pattern, flags) + o.prototype = rt.global.RegExpPrototype + return o } -// TODO Should (probably) be one argument, right? This is redundant -func (runtime *_runtime) newDate(epoch float64) *_object { - self := runtime.newDateObject(epoch) - self.prototype = runtime.global.DatePrototype - return self +// TODO Should (probably) be one argument, right? This is redundant. +func (rt *runtime) newDate(epoch float64) *object { + o := rt.newDateObject(epoch) + o.prototype = rt.global.DatePrototype + return o } -func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object { - var self *_object +func (rt *runtime) newError(name string, message Value, stackFramesToPop int) *object { switch name { case "EvalError": - return runtime.newEvalError(message) + return rt.newEvalError(message) case "TypeError": - return runtime.newTypeError(message) + return rt.newTypeError(message) case "RangeError": - return runtime.newRangeError(message) + return rt.newRangeError(message) case "ReferenceError": - return runtime.newReferenceError(message) + return rt.newReferenceError(message) case "SyntaxError": - return runtime.newSyntaxError(message) + return rt.newSyntaxError(message) case "URIError": - return runtime.newURIError(message) + return rt.newURIError(message) } - self = runtime.newErrorObject(name, message, stackFramesToPop) - self.prototype = runtime.global.ErrorPrototype + obj := rt.newErrorObject(name, message, stackFramesToPop) + obj.prototype = rt.global.ErrorPrototype if name != "" { - self.defineProperty("name", toValue_string(name), 0111, false) + obj.defineProperty("name", stringValue(name), 0o111, false) } - return self + return obj } -func (runtime *_runtime) newNativeFunction(name, file string, line int, _nativeFunction _nativeFunction) *_object { - self := runtime.newNativeFunctionObject(name, file, line, _nativeFunction, 0) - self.prototype = runtime.global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0100, false) - return self +func (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object { + o := rt.newNativeFunctionObject(name, file, line, fn, 0) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o100, false) + return o } -func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_object { +func (rt *runtime) newNodeFunction(node *nodeFunctionLiteral, scopeEnvironment stasher) *object { // TODO Implement 13.2 fully - self := runtime.newNodeFunctionObject(node, scopeEnvironment) - self.prototype = runtime.global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0101, false) - return self + o := rt.newNodeFunctionObject(node, scopeEnvironment) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o101, false) + return o } // FIXME Only in one place... -func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newBoundFunctionObject(target, this, argumentList) - self.prototype = runtime.global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0100, false) - return self +func (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object { + o := rt.newBoundFunctionObject(target, this, argumentList) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o100, false) + return o } diff --git a/vendor/github.com/robertkrimen/otto/inline.go b/vendor/github.com/robertkrimen/otto/inline.go index 6e5df8393..30e00beec 100644 --- a/vendor/github.com/robertkrimen/otto/inline.go +++ b/vendor/github.com/robertkrimen/otto/inline.go @@ -1,6647 +1,8772 @@ +// Code generated by tools/gen-jscore. DO NOT EDIT. + package otto import ( "math" ) -func _newContext(runtime *_runtime) { - { - runtime.global.ObjectPrototype = &_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: nil, - extensible: true, - value: prototypeValueObject, - } +func (rt *runtime) newContext() { + // Order here is import as definitions depend on each other. + + // Object prototype. + rt.global.ObjectPrototype = &object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: nil, + extensible: true, + value: prototypeValueObject, } - { - runtime.global.FunctionPrototype = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueFunction, - } + + // Function prototype. + rt.global.FunctionPrototype = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueFunction, } - { - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinObject_valueOf, - }, - } - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinObject_toString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinObject_toLocaleString, - }, - } - hasOwnProperty_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "hasOwnProperty", - call: builtinObject_hasOwnProperty, - }, - } - isPrototypeOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isPrototypeOf", - call: builtinObject_isPrototypeOf, - }, - } - propertyIsEnumerable_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "propertyIsEnumerable", - call: builtinObject_propertyIsEnumerable, - }, - } - runtime.global.ObjectPrototype.property = map[string]_property{ - "valueOf": _property{ - mode: 0101, + + // Object prototype property definition. + rt.global.ObjectPrototype.property = map[string]property{ + "hasOwnProperty": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "hasOwnProperty", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "hasOwnProperty", + call: builtinObjectHasOwnProperty, + }, + }, + }, + }, + "isPrototypeOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isPrototypeOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isPrototypeOf", + call: builtinObjectIsPrototypeOf, + }, + }, + }, + }, + "propertyIsEnumerable": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "propertyIsEnumerable", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "propertyIsEnumerable", + call: builtinObjectPropertyIsEnumerable, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinObjectToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinObjectValueOf, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinObjectToLocaleString, + }, + }, + }, + }, + } + rt.global.ObjectPrototype.propertyOrder = []string{ + propertyConstructor, + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + methodToString, + "valueOf", + "toLocaleString", + } + + // Function prototype property definition. + rt.global.FunctionPrototype.property = map[string]property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinFunctionToString, + }, + }, + }, + }, + "apply": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "apply", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "apply", + call: builtinFunctionApply, + }, + }, + }, + }, + "call": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "call", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "call", + call: builtinFunctionCall, + }, + }, + }, + }, + "bind": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "bind", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "bind", + call: builtinFunctionBind, + }, + }, + }, + }, + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + } + rt.global.FunctionPrototype.propertyOrder = []string{ + methodToString, + "apply", + "call", + "bind", + propertyConstructor, + propertyLength, + } + + // Object definition. + rt.global.Object = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classObjectName, + call: builtinObject, + construct: builtinNewObject, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: valueOf_function, + kind: valueNumber, + value: 1, }, }, - "toString": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: toString_function, + value: rt.global.ObjectPrototype, }, }, - "toLocaleString": _property{ - mode: 0101, + "getPrototypeOf": { + mode: 0o101, value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "hasOwnProperty": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getPrototypeOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getPrototypeOf", + call: builtinObjectGetPrototypeOf, + }, + }, + }, + }, + "getOwnPropertyDescriptor": { + mode: 0o101, value: Value{ - kind: valueObject, - value: hasOwnProperty_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getOwnPropertyDescriptor", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getOwnPropertyDescriptor", + call: builtinObjectGetOwnPropertyDescriptor, + }, + }, + }, + }, + "defineProperty": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "defineProperty", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "defineProperty", + call: builtinObjectDefineProperty, + }, + }, + }, + }, + "defineProperties": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "defineProperties", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "defineProperties", + call: builtinObjectDefineProperties, + }, + }, + }, + }, + "create": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "create", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "create", + call: builtinObjectCreate, + }, + }, + }, + }, + "isExtensible": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isExtensible", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isExtensible", + call: builtinObjectIsExtensible, + }, + }, + }, + }, + "preventExtensions": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "preventExtensions", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "preventExtensions", + call: builtinObjectPreventExtensions, + }, + }, + }, + }, + "isSealed": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isSealed", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isSealed", + call: builtinObjectIsSealed, + }, + }, + }, + }, + "seal": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "seal", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "seal", + call: builtinObjectSeal, + }, + }, + }, + }, + "isFrozen": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isFrozen", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isFrozen", + call: builtinObjectIsFrozen, + }, + }, + }, + }, + "freeze": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "freeze", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "freeze", + call: builtinObjectFreeze, + }, + }, + }, + }, + "keys": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "keys", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "keys", + call: builtinObjectKeys, + }, + }, + }, + }, + "values": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "values", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "values", + call: builtinObjectValues, + }, + }, + }, + }, + "getOwnPropertyNames": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getOwnPropertyNames", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getOwnPropertyNames", + call: builtinObjectGetOwnPropertyNames, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "getPrototypeOf", + "getOwnPropertyDescriptor", + "defineProperty", + "defineProperties", + "create", + "isExtensible", + "preventExtensions", + "isSealed", + "seal", + "isFrozen", + "freeze", + "keys", + "values", + "getOwnPropertyNames", + }, + } + + // Object constructor definition. + rt.global.ObjectPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Object, + }, + } + + // Function definition. + rt.global.Function = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classFunctionName, + call: builtinFunction, + construct: builtinNewFunction, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "isPrototypeOf": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: isPrototypeOf_function, + value: rt.global.FunctionPrototype, }, }, - "propertyIsEnumerable": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // Function constructor definition. + rt.global.FunctionPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Function, + }, + } + + // Array prototype. + rt.global.ArrayPrototype = &object{ + runtime: rt, + class: classArrayName, + objectClass: classArray, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: nil, + property: map[string]property{ + propertyLength: { + mode: 0o100, value: Value{ - kind: valueObject, - value: propertyIsEnumerable_function, + kind: valueNumber, + value: uint32(0), }, }, - "constructor": _property{ - mode: 0101, - value: Value{}, - }, - } - runtime.global.ObjectPrototype.propertyOrder = []string{ - "valueOf", - "toString", + "concat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "concat", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "concat", + call: builtinArrayConcat, + }, + }, + }, + }, + "lastIndexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "lastIndexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "lastIndexOf", + call: builtinArrayLastIndexOf, + }, + }, + }, + }, + "pop": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "pop", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "pop", + call: builtinArrayPop, + }, + }, + }, + }, + "push": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "push", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "push", + call: builtinArrayPush, + }, + }, + }, + }, + "reverse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "reverse", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "reverse", + call: builtinArrayReverse, + }, + }, + }, + }, + "shift": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "shift", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "shift", + call: builtinArrayShift, + }, + }, + }, + }, + "unshift": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "unshift", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "unshift", + call: builtinArrayUnshift, + }, + }, + }, + }, + "slice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "slice", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "slice", + call: builtinArraySlice, + }, + }, + }, + }, + "sort": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sort", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sort", + call: builtinArraySort, + }, + }, + }, + }, + "splice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "splice", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "splice", + call: builtinArraySplice, + }, + }, + }, + }, + "indexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "indexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "indexOf", + call: builtinArrayIndexOf, + }, + }, + }, + }, + "join": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "join", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "join", + call: builtinArrayJoin, + }, + }, + }, + }, + "forEach": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "forEach", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "forEach", + call: builtinArrayForEach, + }, + }, + }, + }, + "filter": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "filter", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "filter", + call: builtinArrayFilter, + }, + }, + }, + }, + "map": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "map", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "map", + call: builtinArrayMap, + }, + }, + }, + }, + "every": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "every", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "every", + call: builtinArrayEvery, + }, + }, + }, + }, + "some": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "some", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "some", + call: builtinArraySome, + }, + }, + }, + }, + "reduce": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "reduce", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "reduce", + call: builtinArrayReduce, + }, + }, + }, + }, + "reduceRight": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "reduceRight", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "reduceRight", + call: builtinArrayReduceRight, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinArrayToLocaleString, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinArrayToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyConstructor, + "concat", + "lastIndexOf", + "pop", + "push", + "reverse", + "shift", + "unshift", + "slice", + "sort", + "splice", + "indexOf", + "join", + "forEach", + "filter", + "map", + "every", + "some", + "reduce", + "reduceRight", "toLocaleString", - "hasOwnProperty", - "isPrototypeOf", - "propertyIsEnumerable", - "constructor", - } + methodToString, + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinFunction_toString, - }, - } - apply_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "apply", - call: builtinFunction_apply, - }, - } - call_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "call", - call: builtinFunction_call, - }, - } - bind_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "bind", - call: builtinFunction_bind, - }, - } - runtime.global.FunctionPrototype.property = map[string]_property{ - "toString": _property{ - mode: 0101, + + // Array definition. + rt.global.Array = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classArrayName, + call: builtinArray, + construct: builtinNewArray, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: toString_function, + kind: valueNumber, + value: 1, }, }, - "apply": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: apply_function, + value: rt.global.ArrayPrototype, }, }, - "call": _property{ - mode: 0101, + "isArray": { + mode: 0o101, value: Value{ - kind: valueObject, - value: call_function, - }, - }, - "bind": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isArray", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isArray", + call: builtinArrayIsArray, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "isArray", + }, + } + + // Array constructor definition. + rt.global.ArrayPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Array, + }, + } + + // String prototype. + rt.global.StringPrototype = &object{ + runtime: rt, + class: classStringName, + objectClass: classString, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueString, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: bind_function, + kind: valueNumber, + value: int(0), }, }, - "constructor": _property{ - mode: 0101, - value: Value{}, - }, - "length": _property{ + "charAt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "charAt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "charAt", + call: builtinStringCharAt, + }, + }, + }, + }, + "charCodeAt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "charCodeAt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "charCodeAt", + call: builtinStringCharCodeAt, + }, + }, + }, + }, + "concat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "concat", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "concat", + call: builtinStringConcat, + }, + }, + }, + }, + "indexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "indexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "indexOf", + call: builtinStringIndexOf, + }, + }, + }, + }, + "lastIndexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "lastIndexOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "lastIndexOf", + call: builtinStringLastIndexOf, + }, + }, + }, + }, + "localeCompare": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "localeCompare", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "localeCompare", + call: builtinStringLocaleCompare, + }, + }, + }, + }, + "match": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "match", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "match", + call: builtinStringMatch, + }, + }, + }, + }, + "replace": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "replace", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "replace", + call: builtinStringReplace, + }, + }, + }, + }, + "search": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "search", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "search", + call: builtinStringSearch, + }, + }, + }, + }, + "slice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "slice", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "slice", + call: builtinStringSlice, + }, + }, + }, + }, + "split": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "split", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "split", + call: builtinStringSplit, + }, + }, + }, + }, + "substr": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "substr", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "substr", + call: builtinStringSubstr, + }, + }, + }, + }, + "substring": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "substring", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "substring", + call: builtinStringSubstring, + }, + }, + }, + }, + "startsWith": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "startsWith", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "startsWith", + call: builtinStringStartsWith, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinStringToString, + }, + }, + }, + }, + "trim": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trim", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trim", + call: builtinStringTrim, + }, + }, + }, + }, + "trimLeft": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimLeft", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimLeft", + call: builtinStringTrimLeft, + }, + }, + }, + }, + "trimRight": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimRight", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimRight", + call: builtinStringTrimRight, + }, + }, + }, + }, + "trimStart": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimStart", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimStart", + call: builtinStringTrimStart, + }, + }, + }, + }, + "trimEnd": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trimEnd", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trimEnd", + call: builtinStringTrimEnd, + }, + }, + }, + }, + "toLocaleLowerCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleLowerCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleLowerCase", + call: builtinStringToLocaleLowerCase, + }, + }, + }, + }, + "toLocaleUpperCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleUpperCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleUpperCase", + call: builtinStringToLocaleUpperCase, + }, + }, + }, + }, + "toLowerCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLowerCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLowerCase", + call: builtinStringToLowerCase, + }, + }, + }, + }, + "toUpperCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toUpperCase", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toUpperCase", + call: builtinStringToUpperCase, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinStringValueOf, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyConstructor, + "charAt", + "charCodeAt", + "concat", + "indexOf", + "lastIndexOf", + "localeCompare", + "match", + "replace", + "search", + "slice", + "split", + "substr", + "substring", + "startsWith", + methodToString, + "trim", + "trimLeft", + "trimRight", + "trimStart", + "trimEnd", + "toLocaleLowerCase", + "toLocaleUpperCase", + "toLowerCase", + "toUpperCase", + "valueOf", + }, + } + + // String definition. + rt.global.String = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classStringName, + call: builtinString, + construct: builtinNewString, + }, + property: map[string]property{ + propertyLength: { mode: 0, value: Value{ kind: valueNumber, - value: 0, - }, - }, - } - runtime.global.FunctionPrototype.propertyOrder = []string{ - "toString", - "apply", - "call", - "bind", - "constructor", - "length", - } - } - { - getPrototypeOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getPrototypeOf", - call: builtinObject_getPrototypeOf, - }, - } - getOwnPropertyDescriptor_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getOwnPropertyDescriptor", - call: builtinObject_getOwnPropertyDescriptor, - }, - } - defineProperty_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "defineProperty", - call: builtinObject_defineProperty, - }, - } - defineProperties_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "defineProperties", - call: builtinObject_defineProperties, - }, - } - create_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "create", - call: builtinObject_create, - }, - } - isExtensible_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isExtensible", - call: builtinObject_isExtensible, - }, - } - preventExtensions_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "preventExtensions", - call: builtinObject_preventExtensions, - }, - } - isSealed_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isSealed", - call: builtinObject_isSealed, - }, - } - seal_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "seal", - call: builtinObject_seal, - }, - } - isFrozen_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isFrozen", - call: builtinObject_isFrozen, - }, - } - freeze_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "freeze", - call: builtinObject_freeze, - }, - } - keys_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "keys", - call: builtinObject_keys, - }, - } - getOwnPropertyNames_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getOwnPropertyNames", - call: builtinObject_getOwnPropertyNames, - }, - } - runtime.global.Object = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Object", - call: builtinObject, - construct: builtinNewObject, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ObjectPrototype, - }, - }, - "getPrototypeOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getPrototypeOf_function, - }, - }, - "getOwnPropertyDescriptor": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getOwnPropertyDescriptor_function, - }, - }, - "defineProperty": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: defineProperty_function, - }, - }, - "defineProperties": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: defineProperties_function, - }, - }, - "create": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: create_function, - }, - }, - "isExtensible": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isExtensible_function, - }, - }, - "preventExtensions": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: preventExtensions_function, - }, - }, - "isSealed": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isSealed_function, - }, + value: 1, }, - "seal": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: seal_function, - }, - }, - "isFrozen": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isFrozen_function, - }, - }, - "freeze": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: freeze_function, - }, - }, - "keys": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: keys_function, - }, - }, - "getOwnPropertyNames": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getOwnPropertyNames_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "getPrototypeOf", - "getOwnPropertyDescriptor", - "defineProperty", - "defineProperties", - "create", - "isExtensible", - "preventExtensions", - "isSealed", - "seal", - "isFrozen", - "freeze", - "keys", - "getOwnPropertyNames", }, - } - runtime.global.ObjectPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Object, + value: rt.global.StringPrototype, }, - } - } - { - Function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Function", - call: builtinFunction, - construct: builtinNewFunction, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.FunctionPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.Function = Function - runtime.global.FunctionPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "fromCharCode": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Function, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "fromCharCode", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "fromCharCode", + call: builtinStringFromCharCode, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "fromCharCode", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinArray_toString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinArray_toLocaleString, - }, - } - concat_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "concat", - call: builtinArray_concat, - }, - } - join_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "join", - call: builtinArray_join, - }, - } - splice_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "splice", - call: builtinArray_splice, - }, - } - shift_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "shift", - call: builtinArray_shift, - }, - } - pop_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "pop", - call: builtinArray_pop, - }, - } - push_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "push", - call: builtinArray_push, - }, - } - slice_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "slice", - call: builtinArray_slice, - }, - } - unshift_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "unshift", - call: builtinArray_unshift, - }, - } - reverse_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "reverse", - call: builtinArray_reverse, - }, - } - sort_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "sort", - call: builtinArray_sort, - }, - } - indexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "indexOf", - call: builtinArray_indexOf, - }, - } - lastIndexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "lastIndexOf", - call: builtinArray_lastIndexOf, - }, - } - every_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "every", - call: builtinArray_every, - }, - } - some_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "some", - call: builtinArray_some, - }, - } - forEach_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "forEach", - call: builtinArray_forEach, - }, - } - map_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "map", - call: builtinArray_map, - }, - } - filter_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "filter", - call: builtinArray_filter, - }, - } - reduce_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "reduce", - call: builtinArray_reduce, - }, - } - reduceRight_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "reduceRight", - call: builtinArray_reduceRight, - }, - } - isArray_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isArray", - call: builtinArray_isArray, - }, - } - runtime.global.ArrayPrototype = &_object{ - runtime: runtime, - class: "Array", - objectClass: _classArray, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "length": _property{ - mode: 0100, - value: Value{ - kind: valueNumber, - value: uint32(0), - }, - }, - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "concat": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: concat_function, - }, - }, - "join": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: join_function, - }, - }, - "splice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: splice_function, - }, - }, - "shift": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: shift_function, - }, - }, - "pop": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: pop_function, - }, - }, - "push": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: push_function, - }, - }, - "slice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: slice_function, - }, - }, - "unshift": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: unshift_function, - }, - }, - "reverse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reverse_function, - }, - }, - "sort": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sort_function, - }, - }, - "indexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: indexOf_function, - }, - }, - "lastIndexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: lastIndexOf_function, - }, - }, - "every": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: every_function, - }, - }, - "some": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: some_function, - }, - }, - "forEach": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: forEach_function, - }, - }, - "map": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: map_function, - }, - }, - "filter": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: filter_function, - }, - }, - "reduce": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reduce_function, - }, - }, - "reduceRight": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reduceRight_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "toString", - "toLocaleString", - "concat", - "join", - "splice", - "shift", - "pop", - "push", - "slice", - "unshift", - "reverse", - "sort", - "indexOf", - "lastIndexOf", - "every", - "some", - "forEach", - "map", - "filter", - "reduce", - "reduceRight", - }, - } - runtime.global.Array = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Array", - call: builtinArray, - construct: builtinNewArray, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ArrayPrototype, - }, - }, - "isArray": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isArray_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "isArray", - }, - } - runtime.global.ArrayPrototype.property["constructor"] = - _property{ - mode: 0101, + + // String constructor definition. + rt.global.StringPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.String, + }, + } + + // Boolean prototype. + rt.global.BooleanPrototype = &object{ + runtime: rt, + class: classBooleanName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueBoolean, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Array, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinBooleanToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinBooleanValueOf, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + methodToString, + "valueOf", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinString_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinString_valueOf, - }, - } - charAt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "charAt", - call: builtinString_charAt, - }, - } - charCodeAt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "charCodeAt", - call: builtinString_charCodeAt, - }, - } - concat_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "concat", - call: builtinString_concat, - }, - } - indexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "indexOf", - call: builtinString_indexOf, - }, - } - lastIndexOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "lastIndexOf", - call: builtinString_lastIndexOf, - }, - } - match_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "match", - call: builtinString_match, - }, - } - replace_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "replace", - call: builtinString_replace, - }, - } - search_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "search", - call: builtinString_search, - }, - } - split_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "split", - call: builtinString_split, - }, - } - slice_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "slice", - call: builtinString_slice, - }, - } - substring_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "substring", - call: builtinString_substring, - }, - } - toLowerCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLowerCase", - call: builtinString_toLowerCase, - }, - } - toUpperCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toUpperCase", - call: builtinString_toUpperCase, - }, - } - substr_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "substr", - call: builtinString_substr, - }, - } - trim_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trim", - call: builtinString_trim, - }, - } - trimLeft_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trimLeft", - call: builtinString_trimLeft, - }, - } - trimRight_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trimRight", - call: builtinString_trimRight, - }, - } - localeCompare_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "localeCompare", - call: builtinString_localeCompare, - }, - } - toLocaleLowerCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleLowerCase", - call: builtinString_toLocaleLowerCase, - }, - } - toLocaleUpperCase_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleUpperCase", - call: builtinString_toLocaleUpperCase, - }, - } - fromCharCode_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "fromCharCode", - call: builtinString_fromCharCode, - }, - } - runtime.global.StringPrototype = &_object{ - runtime: runtime, - class: "String", - objectClass: _classString, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueString, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: int(0), - }, - }, - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "charAt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: charAt_function, - }, - }, - "charCodeAt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: charCodeAt_function, - }, - }, - "concat": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: concat_function, - }, - }, - "indexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: indexOf_function, - }, - }, - "lastIndexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: lastIndexOf_function, - }, - }, - "match": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: match_function, - }, - }, - "replace": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: replace_function, - }, - }, - "search": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: search_function, - }, - }, - "split": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: split_function, - }, - }, - "slice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: slice_function, - }, - }, - "substring": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: substring_function, - }, - }, - "toLowerCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLowerCase_function, - }, - }, - "toUpperCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toUpperCase_function, - }, - }, - "substr": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: substr_function, - }, - }, - "trim": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trim_function, - }, - }, - "trimLeft": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trimLeft_function, - }, - }, - "trimRight": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trimRight_function, - }, - }, - "localeCompare": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: localeCompare_function, - }, - }, - "toLocaleLowerCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleLowerCase_function, - }, - }, - "toLocaleUpperCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleUpperCase_function, - }, + + // Boolean definition. + rt.global.Boolean = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classBooleanName, + call: builtinBoolean, + construct: builtinNewBoolean, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - propertyOrder: []string{ - "length", - "toString", - "valueOf", - "charAt", - "charCodeAt", - "concat", - "indexOf", - "lastIndexOf", - "match", - "replace", - "search", - "split", - "slice", - "substring", - "toLowerCase", - "toUpperCase", - "substr", - "trim", - "trimLeft", - "trimRight", - "localeCompare", - "toLocaleLowerCase", - "toLocaleUpperCase", - }, - } - runtime.global.String = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "String", - call: builtinString, - construct: builtinNewString, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.StringPrototype, - }, - }, - "fromCharCode": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: fromCharCode_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "fromCharCode", - }, - } - runtime.global.StringPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.String, + value: rt.global.BooleanPrototype, }, - } + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinBoolean_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinBoolean_valueOf, - }, - } - runtime.global.BooleanPrototype = &_object{ - runtime: runtime, - class: "Boolean", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueBoolean, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "valueOf", - }, - } - runtime.global.Boolean = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Boolean", - call: builtinBoolean, - construct: builtinNewBoolean, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.BooleanPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.BooleanPrototype.property["constructor"] = - _property{ - mode: 0101, + + // Boolean constructor definition. + rt.global.BooleanPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Boolean, + }, + } + + // Number prototype. + rt.global.NumberPrototype = &object{ + runtime: rt, + class: classNumberName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueNumber, + property: map[string]property{ + "toExponential": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Boolean, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toExponential", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toExponential", + call: builtinNumberToExponential, + }, + }, + }, + }, + "toFixed": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toFixed", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toFixed", + call: builtinNumberToFixed, + }, + }, + }, + }, + "toPrecision": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toPrecision", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toPrecision", + call: builtinNumberToPrecision, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinNumberToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinNumberValueOf, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinNumberToLocaleString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "toExponential", + "toFixed", + "toPrecision", + methodToString, + "valueOf", + "toLocaleString", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinNumber_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinNumber_valueOf, - }, - } - toFixed_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toFixed", - call: builtinNumber_toFixed, - }, - } - toExponential_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toExponential", - call: builtinNumber_toExponential, - }, - } - toPrecision_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toPrecision", - call: builtinNumber_toPrecision, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinNumber_toLocaleString, - }, - } - runtime.global.NumberPrototype = &_object{ - runtime: runtime, - class: "Number", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueNumber, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "toFixed": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toFixed_function, - }, - }, - "toExponential": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toExponential_function, - }, - }, - "toPrecision": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toPrecision_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "valueOf", - "toFixed", - "toExponential", - "toPrecision", - "toLocaleString", - }, - } - runtime.global.Number = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Number", - call: builtinNumber, - construct: builtinNewNumber, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.NumberPrototype, - }, - }, - "MAX_VALUE": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.MaxFloat64, - }, - }, - "MIN_VALUE": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.SmallestNonzeroFloat64, - }, - }, - "NaN": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.NaN(), - }, - }, - "NEGATIVE_INFINITY": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Inf(-1), - }, - }, - "POSITIVE_INFINITY": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Inf(+1), - }, + + // Number definition. + rt.global.Number = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classNumberName, + call: builtinNumber, + construct: builtinNewNumber, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - propertyOrder: []string{ - "length", - "prototype", - "MAX_VALUE", - "MIN_VALUE", - "NaN", - "NEGATIVE_INFINITY", - "POSITIVE_INFINITY", - }, - } - runtime.global.NumberPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Number, + value: rt.global.NumberPrototype, }, - } - } - { - abs_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "abs", - call: builtinMath_abs, - }, - } - acos_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "acos", - call: builtinMath_acos, - }, - } - asin_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "asin", - call: builtinMath_asin, - }, - } - atan_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "atan", - call: builtinMath_atan, - }, - } - atan2_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "atan2", - call: builtinMath_atan2, - }, - } - ceil_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "ceil", - call: builtinMath_ceil, - }, - } - cos_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "cos", - call: builtinMath_cos, - }, - } - exp_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "exp", - call: builtinMath_exp, - }, - } - floor_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "floor", - call: builtinMath_floor, - }, - } - log_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "log", - call: builtinMath_log, - }, - } - max_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "max", - call: builtinMath_max, - }, - } - min_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "min", - call: builtinMath_min, - }, - } - pow_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "pow", - call: builtinMath_pow, - }, - } - random_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "random", - call: builtinMath_random, - }, - } - round_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "round", - call: builtinMath_round, - }, - } - sin_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "sin", - call: builtinMath_sin, - }, - } - sqrt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "sqrt", - call: builtinMath_sqrt, - }, - } - tan_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "tan", - call: builtinMath_tan, }, - } - runtime.global.Math = &_object{ - runtime: runtime, - class: "Math", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "abs": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: abs_function, - }, - }, - "acos": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: acos_function, - }, - }, - "asin": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: asin_function, - }, - }, - "atan": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: atan_function, - }, - }, - "atan2": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: atan2_function, - }, - }, - "ceil": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: ceil_function, - }, - }, - "cos": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: cos_function, - }, - }, - "exp": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: exp_function, - }, - }, - "floor": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: floor_function, - }, - }, - "log": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: log_function, - }, - }, - "max": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: max_function, - }, - }, - "min": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: min_function, - }, - }, - "pow": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: pow_function, - }, - }, - "random": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: random_function, - }, - }, - "round": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: round_function, - }, - }, - "sin": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sin_function, - }, - }, - "sqrt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sqrt_function, - }, - }, - "tan": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: tan_function, - }, - }, - "E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.E, - }, - }, - "LN10": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Ln10, - }, - }, - "LN2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Ln2, - }, - }, - "LOG2E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Log2E, - }, + "isNaN": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isNaN", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isNaN", + call: builtinNumberIsNaN, + }, + }, + }, + }, + "MAX_VALUE": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.MaxFloat64, }, - "LOG10E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Log10E, - }, + }, + "MIN_VALUE": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.SmallestNonzeroFloat64, }, - "PI": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Pi, - }, + }, + "NaN": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.NaN(), }, - "SQRT1_2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: sqrt1_2, - }, + }, + "NEGATIVE_INFINITY": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(-1), }, - "SQRT2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Sqrt2, - }, + }, + "POSITIVE_INFINITY": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(+1), }, }, - propertyOrder: []string{ - "abs", - "acos", - "asin", - "atan", - "atan2", - "ceil", - "cos", - "exp", - "floor", - "log", - "max", - "min", - "pow", - "random", - "round", - "sin", - "sqrt", - "tan", - "E", - "LN10", - "LN2", - "LOG2E", - "LOG10E", - "PI", - "SQRT1_2", - "SQRT2", - }, - } + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "isNaN", + "MAX_VALUE", + "MIN_VALUE", + "NaN", + "NEGATIVE_INFINITY", + "POSITIVE_INFINITY", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinDate_toString, - }, - } - toDateString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toDateString", - call: builtinDate_toDateString, - }, - } - toTimeString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toTimeString", - call: builtinDate_toTimeString, - }, - } - toUTCString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toUTCString", - call: builtinDate_toUTCString, - }, - } - toISOString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toISOString", - call: builtinDate_toISOString, - }, - } - toJSON_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toJSON", - call: builtinDate_toJSON, - }, - } - toGMTString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toGMTString", - call: builtinDate_toGMTString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinDate_toLocaleString, - }, - } - toLocaleDateString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleDateString", - call: builtinDate_toLocaleDateString, - }, - } - toLocaleTimeString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toLocaleTimeString", - call: builtinDate_toLocaleTimeString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinDate_valueOf, - }, - } - getTime_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getTime", - call: builtinDate_getTime, - }, - } - getYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getYear", - call: builtinDate_getYear, - }, - } - getFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getFullYear", - call: builtinDate_getFullYear, - }, - } - getUTCFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCFullYear", - call: builtinDate_getUTCFullYear, - }, - } - getMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getMonth", - call: builtinDate_getMonth, - }, - } - getUTCMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCMonth", - call: builtinDate_getUTCMonth, - }, - } - getDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getDate", - call: builtinDate_getDate, - }, - } - getUTCDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCDate", - call: builtinDate_getUTCDate, - }, - } - getDay_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getDay", - call: builtinDate_getDay, - }, - } - getUTCDay_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCDay", - call: builtinDate_getUTCDay, - }, - } - getHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getHours", - call: builtinDate_getHours, - }, - } - getUTCHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCHours", - call: builtinDate_getUTCHours, - }, - } - getMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getMinutes", - call: builtinDate_getMinutes, - }, - } - getUTCMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCMinutes", - call: builtinDate_getUTCMinutes, - }, - } - getSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getSeconds", - call: builtinDate_getSeconds, - }, - } - getUTCSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCSeconds", - call: builtinDate_getUTCSeconds, - }, - } - getMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getMilliseconds", - call: builtinDate_getMilliseconds, - }, - } - getUTCMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getUTCMilliseconds", - call: builtinDate_getUTCMilliseconds, - }, - } - getTimezoneOffset_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "getTimezoneOffset", - call: builtinDate_getTimezoneOffset, - }, - } - setTime_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setTime", - call: builtinDate_setTime, - }, - } - setMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setMilliseconds", - call: builtinDate_setMilliseconds, - }, - } - setUTCMilliseconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCMilliseconds", - call: builtinDate_setUTCMilliseconds, - }, - } - setSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setSeconds", - call: builtinDate_setSeconds, - }, - } - setUTCSeconds_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCSeconds", - call: builtinDate_setUTCSeconds, - }, - } - setMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setMinutes", - call: builtinDate_setMinutes, - }, - } - setUTCMinutes_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCMinutes", - call: builtinDate_setUTCMinutes, - }, - } - setHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 4, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setHours", - call: builtinDate_setHours, - }, - } - setUTCHours_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 4, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCHours", - call: builtinDate_setUTCHours, - }, - } - setDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setDate", - call: builtinDate_setDate, - }, - } - setUTCDate_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCDate", - call: builtinDate_setUTCDate, - }, - } - setMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setMonth", - call: builtinDate_setMonth, - }, - } - setUTCMonth_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCMonth", - call: builtinDate_setUTCMonth, - }, - } - setYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setYear", - call: builtinDate_setYear, - }, - } - setFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setFullYear", - call: builtinDate_setFullYear, - }, - } - setUTCFullYear_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "setUTCFullYear", - call: builtinDate_setUTCFullYear, - }, - } - parse_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parse", - call: builtinDate_parse, - }, - } - UTC_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 7, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "UTC", - call: builtinDate_UTC, - }, - } - now_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "now", - call: builtinDate_now, - }, - } - runtime.global.DatePrototype = &_object{ - runtime: runtime, - class: "Date", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueDate, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "toDateString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toDateString_function, - }, - }, - "toTimeString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toTimeString_function, - }, - }, - "toUTCString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toUTCString_function, - }, - }, - "toISOString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toISOString_function, - }, - }, - "toJSON": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toJSON_function, - }, - }, - "toGMTString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toGMTString_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "toLocaleDateString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleDateString_function, - }, - }, - "toLocaleTimeString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleTimeString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "getTime": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getTime_function, - }, - }, - "getYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getYear_function, - }, - }, - "getFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getFullYear_function, - }, - }, - "getUTCFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCFullYear_function, - }, - }, - "getMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMonth_function, - }, - }, - "getUTCMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMonth_function, - }, - }, - "getDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getDate_function, - }, - }, - "getUTCDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCDate_function, - }, - }, - "getDay": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getDay_function, - }, - }, - "getUTCDay": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCDay_function, - }, - }, - "getHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getHours_function, - }, - }, - "getUTCHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCHours_function, - }, - }, - "getMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMinutes_function, - }, - }, - "getUTCMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMinutes_function, - }, - }, - "getSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getSeconds_function, - }, - }, - "getUTCSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCSeconds_function, - }, - }, - "getMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMilliseconds_function, - }, - }, - "getUTCMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMilliseconds_function, - }, - }, - "getTimezoneOffset": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getTimezoneOffset_function, - }, - }, - "setTime": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setTime_function, - }, - }, - "setMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMilliseconds_function, - }, - }, - "setUTCMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMilliseconds_function, - }, - }, - "setSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setSeconds_function, - }, - }, - "setUTCSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCSeconds_function, - }, - }, - "setMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMinutes_function, - }, + + // Number constructor definition. + rt.global.NumberPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Number, + }, + } + + // Math definition. + rt.global.Math = &object{ + runtime: rt, + class: classMathName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "abs": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "abs", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "abs", + call: builtinMathAbs, + }, + }, + }, + }, + "acos": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "acos", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "acos", + call: builtinMathAcos, + }, + }, + }, + }, + "acosh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "acosh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "acosh", + call: builtinMathAcosh, + }, + }, + }, + }, + "asin": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "asin", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "asin", + call: builtinMathAsin, + }, + }, + }, + }, + "asinh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "asinh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "asinh", + call: builtinMathAsinh, + }, + }, + }, + }, + "atan": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "atan", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "atan", + call: builtinMathAtan, + }, + }, + }, + }, + "atanh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "atanh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "atanh", + call: builtinMathAtanh, + }, + }, + }, + }, + "atan2": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "atan2", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "atan2", + call: builtinMathAtan2, + }, + }, + }, + }, + "cbrt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "cbrt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "cbrt", + call: builtinMathCbrt, + }, + }, + }, + }, + "ceil": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "ceil", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "ceil", + call: builtinMathCeil, + }, + }, + }, + }, + "cos": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "cos", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "cos", + call: builtinMathCos, + }, + }, + }, + }, + "cosh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "cosh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "cosh", + call: builtinMathCosh, + }, + }, + }, + }, + "exp": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "exp", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "exp", + call: builtinMathExp, + }, + }, + }, + }, + "expm1": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "expm1", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "expm1", + call: builtinMathExpm1, + }, + }, + }, + }, + "floor": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "floor", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "floor", + call: builtinMathFloor, + }, + }, + }, + }, + "log": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log", + call: builtinMathLog, + }, + }, + }, + }, + "log10": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log10", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log10", + call: builtinMathLog10, + }, + }, + }, + }, + "log1p": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log1p", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log1p", + call: builtinMathLog1p, + }, + }, + }, + }, + "log2": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log2", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log2", + call: builtinMathLog2, + }, + }, + }, + }, + "max": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "max", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "max", + call: builtinMathMax, + }, + }, + }, + }, + "min": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "min", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "min", + call: builtinMathMin, + }, + }, + }, + }, + "pow": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "pow", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "pow", + call: builtinMathPow, + }, + }, + }, + }, + "random": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "random", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "random", + call: builtinMathRandom, + }, + }, + }, + }, + "round": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "round", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "round", + call: builtinMathRound, + }, + }, + }, + }, + "sin": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sin", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sin", + call: builtinMathSin, + }, + }, + }, + }, + "sinh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sinh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sinh", + call: builtinMathSinh, + }, + }, + }, + }, + "sqrt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "sqrt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "sqrt", + call: builtinMathSqrt, + }, + }, + }, + }, + "tan": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "tan", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "tan", + call: builtinMathTan, + }, + }, + }, + }, + "tanh": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "tanh", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "tanh", + call: builtinMathTanh, + }, + }, + }, + }, + "trunc": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trunc", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trunc", + call: builtinMathTrunc, + }, + }, + }, + }, + "E": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.E, }, - "setUTCMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMinutes_function, - }, - }, - "setHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setHours_function, - }, - }, - "setUTCHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCHours_function, - }, - }, - "setDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setDate_function, - }, - }, - "setUTCDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCDate_function, - }, - }, - "setMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMonth_function, - }, - }, - "setUTCMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMonth_function, - }, - }, - "setYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setYear_function, - }, - }, - "setFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setFullYear_function, - }, - }, - "setUTCFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCFullYear_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "toDateString", - "toTimeString", - "toUTCString", - "toISOString", - "toJSON", - "toGMTString", - "toLocaleString", - "toLocaleDateString", - "toLocaleTimeString", - "valueOf", - "getTime", - "getYear", - "getFullYear", - "getUTCFullYear", - "getMonth", - "getUTCMonth", - "getDate", - "getUTCDate", - "getDay", - "getUTCDay", - "getHours", - "getUTCHours", - "getMinutes", - "getUTCMinutes", - "getSeconds", - "getUTCSeconds", - "getMilliseconds", - "getUTCMilliseconds", - "getTimezoneOffset", - "setTime", - "setMilliseconds", - "setUTCMilliseconds", - "setSeconds", - "setUTCSeconds", - "setMinutes", - "setUTCMinutes", - "setHours", - "setUTCHours", - "setDate", - "setUTCDate", - "setMonth", - "setUTCMonth", - "setYear", - "setFullYear", - "setUTCFullYear", - }, - } - runtime.global.Date = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Date", - call: builtinDate, - construct: builtinNewDate, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 7, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.DatePrototype, - }, - }, - "parse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: parse_function, - }, - }, - "UTC": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: UTC_function, - }, - }, - "now": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: now_function, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - "parse", - "UTC", - "now", - }, - } - runtime.global.DatePrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LN10": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Date, + kind: valueNumber, + value: math.Ln10, }, - } - } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinRegExp_toString, - }, - } - exec_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "exec", - call: builtinRegExp_exec, - }, - } - test_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "test", - call: builtinRegExp_test, - }, - } - compile_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "compile", - call: builtinRegExp_compile, - }, - } - runtime.global.RegExpPrototype = &_object{ - runtime: runtime, - class: "RegExp", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueRegExp, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "exec": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: exec_function, - }, - }, - "test": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: test_function, - }, - }, - "compile": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: compile_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "exec", - "test", - "compile", - }, - } - runtime.global.RegExp = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "RegExp", - call: builtinRegExp, - construct: builtinNewRegExp, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.RegExpPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.RegExpPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LN2": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.RegExp, + kind: valueNumber, + value: math.Ln2, }, - } - } - { - toString_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinError_toString, - }, - } - runtime.global.ErrorPrototype = &_object{ - runtime: runtime, - class: "Error", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "Error", - }, - }, - "message": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "", - }, - }, - }, - propertyOrder: []string{ - "toString", - "name", - "message", - }, - } - runtime.global.Error = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "Error", - call: builtinError, - construct: builtinNewError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.ErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LOG10E": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Error, + kind: valueNumber, + value: math.Log10E, }, - } - } - { - runtime.global.EvalErrorPrototype = &_object{ - runtime: runtime, - class: "EvalError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "EvalError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.EvalError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "EvalError", - call: builtinEvalError, - construct: builtinNewEvalError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.EvalErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.EvalErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "LOG2E": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.EvalError, + kind: valueNumber, + value: math.Log2E, }, - } - } - { - runtime.global.TypeErrorPrototype = &_object{ - runtime: runtime, - class: "TypeError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "TypeError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.TypeError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "TypeError", - call: builtinTypeError, - construct: builtinNewTypeError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.TypeErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.TypeErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "PI": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.TypeError, + kind: valueNumber, + value: math.Pi, }, - } - } - { - runtime.global.RangeErrorPrototype = &_object{ - runtime: runtime, - class: "RangeError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "RangeError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.RangeError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "RangeError", - call: builtinRangeError, - construct: builtinNewRangeError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.RangeErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.RangeErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "SQRT1_2": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.RangeError, + kind: valueNumber, + value: sqrt1_2, }, - } + }, + "SQRT2": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Sqrt2, + }, + }, + }, + propertyOrder: []string{ + "abs", + "acos", + "acosh", + "asin", + "asinh", + "atan", + "atanh", + "atan2", + "cbrt", + "ceil", + "cos", + "cosh", + "exp", + "expm1", + "floor", + "log", + "log10", + "log1p", + "log2", + "max", + "min", + "pow", + "random", + "round", + "sin", + "sinh", + "sqrt", + "tan", + "tanh", + "trunc", + "E", + "LN10", + "LN2", + "LOG10E", + "LOG2E", + "PI", + "SQRT1_2", + "SQRT2", + }, } - { - runtime.global.ReferenceErrorPrototype = &_object{ - runtime: runtime, - class: "ReferenceError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "ReferenceError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.ReferenceError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "ReferenceError", - call: builtinReferenceError, - construct: builtinNewReferenceError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ReferenceErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.ReferenceErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + + // Date prototype. + rt.global.DatePrototype = &object{ + runtime: rt, + class: classDateName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueDate, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.ReferenceError, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinDateToString, + }, + }, + }, + }, + "toDateString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toDateString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toDateString", + call: builtinDateToDateString, + }, + }, + }, + }, + "toTimeString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toTimeString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toTimeString", + call: builtinDateToTimeString, + }, + }, + }, + }, + "toISOString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toISOString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toISOString", + call: builtinDateToISOString, + }, + }, + }, + }, + "toUTCString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toUTCString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toUTCString", + call: builtinDateToUTCString, + }, + }, + }, + }, + "toGMTString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toGMTString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toGMTString", + call: builtinDateToGMTString, + }, + }, + }, + }, + "getDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getDate", + call: builtinDateGetDate, + }, + }, + }, + }, + "setDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setDate", + call: builtinDateSetDate, + }, + }, + }, + }, + "getDay": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getDay", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getDay", + call: builtinDateGetDay, + }, + }, + }, + }, + "getFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getFullYear", + call: builtinDateGetFullYear, + }, + }, + }, + }, + "setFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setFullYear", + call: builtinDateSetFullYear, + }, + }, + }, + }, + "getHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getHours", + call: builtinDateGetHours, + }, + }, + }, + }, + "setHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 4, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setHours", + call: builtinDateSetHours, + }, + }, + }, + }, + "getMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getMilliseconds", + call: builtinDateGetMilliseconds, + }, + }, + }, + }, + "setMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setMilliseconds", + call: builtinDateSetMilliseconds, + }, + }, + }, + }, + "getMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getMinutes", + call: builtinDateGetMinutes, + }, + }, + }, + }, + "setMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setMinutes", + call: builtinDateSetMinutes, + }, + }, + }, + }, + "getMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getMonth", + call: builtinDateGetMonth, + }, + }, + }, + }, + "setMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setMonth", + call: builtinDateSetMonth, + }, + }, + }, + }, + "getSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getSeconds", + call: builtinDateGetSeconds, + }, + }, + }, + }, + "setSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setSeconds", + call: builtinDateSetSeconds, + }, + }, + }, + }, + "getTime": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getTime", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getTime", + call: builtinDateGetTime, + }, + }, + }, + }, + "setTime": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setTime", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setTime", + call: builtinDateSetTime, + }, + }, + }, + }, + "getTimezoneOffset": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getTimezoneOffset", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getTimezoneOffset", + call: builtinDateGetTimezoneOffset, + }, + }, + }, + }, + "getUTCDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCDate", + call: builtinDateGetUTCDate, + }, + }, + }, + }, + "setUTCDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCDate", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCDate", + call: builtinDateSetUTCDate, + }, + }, + }, + }, + "getUTCDay": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCDay", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCDay", + call: builtinDateGetUTCDay, + }, + }, + }, + }, + "getUTCFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCFullYear", + call: builtinDateGetUTCFullYear, + }, + }, + }, + }, + "setUTCFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCFullYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCFullYear", + call: builtinDateSetUTCFullYear, + }, + }, + }, + }, + "getUTCHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCHours", + call: builtinDateGetUTCHours, + }, + }, + }, + }, + "setUTCHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 4, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCHours", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCHours", + call: builtinDateSetUTCHours, + }, + }, + }, + }, + "getUTCMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCMilliseconds", + call: builtinDateGetUTCMilliseconds, + }, + }, + }, + }, + "setUTCMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCMilliseconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCMilliseconds", + call: builtinDateSetUTCMilliseconds, + }, + }, + }, + }, + "getUTCMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCMinutes", + call: builtinDateGetUTCMinutes, + }, + }, + }, + }, + "setUTCMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCMinutes", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCMinutes", + call: builtinDateSetUTCMinutes, + }, + }, + }, + }, + "getUTCMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCMonth", + call: builtinDateGetUTCMonth, + }, + }, + }, + }, + "setUTCMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCMonth", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCMonth", + call: builtinDateSetUTCMonth, + }, + }, + }, + }, + "getUTCSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getUTCSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getUTCSeconds", + call: builtinDateGetUTCSeconds, + }, + }, + }, + }, + "setUTCSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setUTCSeconds", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setUTCSeconds", + call: builtinDateSetUTCSeconds, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "valueOf", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinDateValueOf, + }, + }, + }, + }, + "getYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "getYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "getYear", + call: builtinDateGetYear, + }, + }, + }, + }, + "setYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "setYear", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "setYear", + call: builtinDateSetYear, + }, + }, + }, + }, + "toJSON": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toJSON", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toJSON", + call: builtinDateToJSON, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinDateToLocaleString, + }, + }, + }, + }, + "toLocaleDateString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleDateString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleDateString", + call: builtinDateToLocaleDateString, + }, + }, + }, + }, + "toLocaleTimeString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toLocaleTimeString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "toLocaleTimeString", + call: builtinDateToLocaleTimeString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + methodToString, + "toDateString", + "toTimeString", + "toISOString", + "toUTCString", + "toGMTString", + "getDate", + "setDate", + "getDay", + "getFullYear", + "setFullYear", + "getHours", + "setHours", + "getMilliseconds", + "setMilliseconds", + "getMinutes", + "setMinutes", + "getMonth", + "setMonth", + "getSeconds", + "setSeconds", + "getTime", + "setTime", + "getTimezoneOffset", + "getUTCDate", + "setUTCDate", + "getUTCDay", + "getUTCFullYear", + "setUTCFullYear", + "getUTCHours", + "setUTCHours", + "getUTCMilliseconds", + "setUTCMilliseconds", + "getUTCMinutes", + "setUTCMinutes", + "getUTCMonth", + "setUTCMonth", + "getUTCSeconds", + "setUTCSeconds", + "valueOf", + "getYear", + "setYear", + "toJSON", + "toLocaleString", + "toLocaleDateString", + "toLocaleTimeString", + }, } - { - runtime.global.SyntaxErrorPrototype = &_object{ - runtime: runtime, - class: "SyntaxError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "SyntaxError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.SyntaxError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "SyntaxError", - call: builtinSyntaxError, - construct: builtinNewSyntaxError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.SyntaxErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.SyntaxErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + + // Date definition. + rt.global.Date = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classDateName, + call: builtinDate, + construct: builtinNewDate, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.SyntaxError, + kind: valueNumber, + value: 7, }, - } - } - { - runtime.global.URIErrorPrototype = &_object{ - runtime: runtime, - class: "URIError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "URIError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.URIError = &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "URIError", - call: builtinURIError, - construct: builtinNewURIError, - }, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.URIErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - "length", - "prototype", - }, - } - runtime.global.URIErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.URIError, + value: rt.global.DatePrototype, }, - } + }, + "parse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parse", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parse", + call: builtinDateParse, + }, + }, + }, + }, + "UTC": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 7, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "UTC", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "UTC", + call: builtinDateUTC, + }, + }, + }, + }, + "now": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "now", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "now", + call: builtinDateNow, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "parse", + "UTC", + "now", + }, } - { - parse_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parse", - call: builtinJSON_parse, - }, - } - stringify_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "stringify", - call: builtinJSON_stringify, - }, - } - runtime.global.JSON = &_object{ - runtime: runtime, - class: "JSON", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "parse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: parse_function, - }, - }, - "stringify": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: stringify_function, - }, - }, - }, - propertyOrder: []string{ - "parse", - "stringify", - }, - } + + // Date constructor definition. + rt.global.DatePrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Date, + }, } - { - eval_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "eval", - call: builtinGlobal_eval, - }, - } - parseInt_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parseInt", - call: builtinGlobal_parseInt, - }, - } - parseFloat_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "parseFloat", - call: builtinGlobal_parseFloat, - }, - } - isNaN_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isNaN", - call: builtinGlobal_isNaN, - }, - } - isFinite_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "isFinite", - call: builtinGlobal_isFinite, - }, - } - decodeURI_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "decodeURI", - call: builtinGlobal_decodeURI, - }, - } - decodeURIComponent_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "decodeURIComponent", - call: builtinGlobal_decodeURIComponent, - }, - } - encodeURI_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "encodeURI", - call: builtinGlobal_encodeURI, - }, - } - encodeURIComponent_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "encodeURIComponent", - call: builtinGlobal_encodeURIComponent, - }, - } - escape_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "escape", - call: builtinGlobal_escape, - }, - } - unescape_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "unescape", - call: builtinGlobal_unescape, - }, - } - runtime.globalObject.property = map[string]_property{ - "eval": _property{ - mode: 0101, + + // RegExp prototype. + rt.global.RegExpPrototype = &object{ + runtime: rt, + class: classRegExpName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueRegExp, + property: map[string]property{ + "exec": { + mode: 0o101, value: Value{ - kind: valueObject, - value: eval_function, - }, - }, - "parseInt": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "exec", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "exec", + call: builtinRegExpExec, + }, + }, + }, + }, + "compile": { + mode: 0o101, value: Value{ - kind: valueObject, - value: parseInt_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "compile", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "compile", + call: builtinRegExpCompile, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinRegExpToString, + }, + }, + }, + }, + "test": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "test", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "test", + call: builtinRegExpTest, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "exec", + "compile", + methodToString, + "test", + }, + } + + // RegExp definition. + rt.global.RegExp = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classRegExpName, + call: builtinRegExp, + construct: builtinNewRegExp, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, }, }, - "parseFloat": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: parseFloat_function, + value: rt.global.RegExpPrototype, }, }, - "isNaN": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // RegExp constructor definition. + rt.global.RegExpPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RegExp, + }, + } + + // Error prototype. + rt.global.ErrorPrototype = &object{ + runtime: rt, + class: classErrorName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: isNaN_function, + kind: valueString, + value: classErrorName, }, }, - "isFinite": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: isFinite_function, + kind: valueString, + value: "", }, }, - "decodeURI": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: decodeURI_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // Error definition. + rt.global.Error = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classErrorName, + call: builtinError, + construct: builtinNewError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "decodeURIComponent": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: decodeURIComponent_function, + value: rt.global.ErrorPrototype, }, }, - "encodeURI": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // Error constructor definition. + rt.global.ErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Error, + }, + } + + // EvalError prototype. + rt.global.EvalErrorPrototype = &object{ + runtime: rt, + class: classEvalErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: encodeURI_function, + kind: valueString, + value: classEvalErrorName, }, }, - "encodeURIComponent": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: encodeURIComponent_function, + kind: valueString, + value: "", }, }, - "escape": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: escape_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // EvalError definition. + rt.global.EvalError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classEvalErrorName, + call: builtinEvalError, + construct: builtinNewEvalError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "unescape": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: unescape_function, + value: rt.global.EvalErrorPrototype, }, }, - "Object": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // EvalError constructor definition. + rt.global.EvalErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.EvalError, + }, + } + + // TypeError prototype. + rt.global.TypeErrorPrototype = &object{ + runtime: rt, + class: classTypeErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Object, + kind: valueString, + value: classTypeErrorName, }, }, - "Function": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Function, + kind: valueString, + value: "", }, }, - "Array": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Array, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // TypeError definition. + rt.global.TypeError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classTypeErrorName, + call: builtinTypeError, + construct: builtinNewTypeError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "String": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.String, + value: rt.global.TypeErrorPrototype, }, }, - "Boolean": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // TypeError constructor definition. + rt.global.TypeErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.TypeError, + }, + } + + // RangeError prototype. + rt.global.RangeErrorPrototype = &object{ + runtime: rt, + class: classRangeErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Boolean, + kind: valueString, + value: classRangeErrorName, }, }, - "Number": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Number, + kind: valueString, + value: "", }, }, - "Math": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Math, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // RangeError definition. + rt.global.RangeError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classRangeErrorName, + call: builtinRangeError, + construct: builtinNewRangeError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "Date": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Date, + value: rt.global.RangeErrorPrototype, }, }, - "RegExp": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // RangeError constructor definition. + rt.global.RangeErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RangeError, + }, + } + + // ReferenceError prototype. + rt.global.ReferenceErrorPrototype = &object{ + runtime: rt, + class: classReferenceErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.RegExp, + kind: valueString, + value: classReferenceErrorName, }, }, - "Error": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Error, + kind: valueString, + value: "", }, }, - "EvalError": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.EvalError, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // ReferenceError definition. + rt.global.ReferenceError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classReferenceErrorName, + call: builtinReferenceError, + construct: builtinNewReferenceError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "TypeError": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.TypeError, + value: rt.global.ReferenceErrorPrototype, }, }, - "RangeError": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // ReferenceError constructor definition. + rt.global.ReferenceErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.ReferenceError, + }, + } + + // SyntaxError prototype. + rt.global.SyntaxErrorPrototype = &object{ + runtime: rt, + class: classSyntaxErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.RangeError, + kind: valueString, + value: classSyntaxErrorName, }, }, - "ReferenceError": _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.ReferenceError, + kind: valueString, + value: "", }, }, - "SyntaxError": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.SyntaxError, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // SyntaxError definition. + rt.global.SyntaxError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classSyntaxErrorName, + call: builtinSyntaxError, + construct: builtinNewSyntaxError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "URIError": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.URIError, + value: rt.global.SyntaxErrorPrototype, }, }, - "JSON": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + + // SyntaxError constructor definition. + rt.global.SyntaxErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.SyntaxError, + }, + } + + // URIError prototype. + rt.global.URIErrorPrototype = &object{ + runtime: rt, + class: classURIErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.JSON, + kind: valueString, + value: classURIErrorName, }, }, - "undefined": _property{ - mode: 0, + "message": { + mode: 0o101, value: Value{ - kind: valueUndefined, + kind: valueString, + value: "", }, }, - "NaN": _property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "toString", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyConstructor, + "name", + "message", + methodToString, + }, + } + + // URIError definition. + rt.global.URIError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classURIErrorName, + call: builtinURIError, + construct: builtinNewURIError, + }, + property: map[string]property{ + propertyLength: { mode: 0, value: Value{ kind: valueNumber, - value: math.NaN(), + value: 1, }, }, - "Infinity": _property{ + propertyPrototype: { mode: 0, value: Value{ - kind: valueNumber, - value: math.Inf(+1), - }, - }, - } - runtime.globalObject.propertyOrder = []string{ - "eval", - "parseInt", - "parseFloat", - "isNaN", - "isFinite", - "decodeURI", - "decodeURIComponent", - "encodeURI", - "encodeURIComponent", - "escape", - "unescape", - "Object", - "Function", - "Array", - "String", - "Boolean", - "Number", - "Math", - "Date", - "RegExp", - "Error", - "EvalError", - "TypeError", - "RangeError", - "ReferenceError", - "SyntaxError", - "URIError", - "JSON", - "undefined", - "NaN", - "Infinity", - } - } -} - -func newConsoleObject(runtime *_runtime) *_object { - { - log_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "log", - call: builtinConsole_log, - }, - } - debug_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "debug", - call: builtinConsole_log, - }, - } - info_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "info", - call: builtinConsole_log, - }, - } - error_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "error", - call: builtinConsole_error, - }, - } - warn_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "warn", - call: builtinConsole_error, - }, - } - dir_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "dir", - call: builtinConsole_dir, - }, - } - time_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "time", - call: builtinConsole_time, - }, - } - timeEnd_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "timeEnd", - call: builtinConsole_timeEnd, - }, - } - trace_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "trace", - call: builtinConsole_trace, - }, - } - assert_function := &_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - "length": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - "length", - }, - value: _nativeFunctionObject{ - name: "assert", - call: builtinConsole_assert, - }, - } - return &_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "log": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: log_function, - }, - }, - "debug": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: debug_function, - }, - }, - "info": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: info_function, - }, - }, - "error": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: error_function, - }, - }, - "warn": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: warn_function, - }, - }, - "dir": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: dir_function, - }, - }, - "time": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: time_function, - }, - }, - "timeEnd": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: timeEnd_function, - }, + kind: valueObject, + value: rt.global.URIErrorPrototype, }, - "trace": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trace_function, - }, - }, - "assert": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: assert_function, - }, - }, - }, - propertyOrder: []string{ - "log", - "debug", - "info", - "error", - "warn", - "dir", - "time", - "timeEnd", - "trace", - "assert", }, - } - } -} - -func toValue_int(value int) Value { - return Value{ - kind: valueNumber, - value: value, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, } -} -func toValue_int8(value int8) Value { - return Value{ - kind: valueNumber, - value: value, + // URIError constructor definition. + rt.global.URIErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.URIError, + }, } -} -func toValue_int16(value int16) Value { - return Value{ - kind: valueNumber, - value: value, + // JSON definition. + rt.global.JSON = &object{ + runtime: rt, + class: classJSONName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "parse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parse", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parse", + call: builtinJSONParse, + }, + }, + }, + }, + "stringify": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "stringify", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "stringify", + call: builtinJSONStringify, + }, + }, + }, + }, + }, + propertyOrder: []string{ + "parse", + "stringify", + }, } -} -func toValue_int32(value int32) Value { - return Value{ - kind: valueNumber, - value: value, + // Global properties. + rt.globalObject.property = map[string]property{ + "eval": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "eval", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "eval", + call: builtinGlobalEval, + }, + }, + }, + }, + "parseInt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parseInt", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parseInt", + call: builtinGlobalParseInt, + }, + }, + }, + }, + "parseFloat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "parseFloat", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "parseFloat", + call: builtinGlobalParseFloat, + }, + }, + }, + }, + "isNaN": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isNaN", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isNaN", + call: builtinGlobalIsNaN, + }, + }, + }, + }, + "isFinite": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "isFinite", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "isFinite", + call: builtinGlobalIsFinite, + }, + }, + }, + }, + "decodeURI": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "decodeURI", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "decodeURI", + call: builtinGlobalDecodeURI, + }, + }, + }, + }, + "decodeURIComponent": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "decodeURIComponent", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "decodeURIComponent", + call: builtinGlobalDecodeURIComponent, + }, + }, + }, + }, + "encodeURI": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "encodeURI", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "encodeURI", + call: builtinGlobalEncodeURI, + }, + }, + }, + }, + "encodeURIComponent": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "encodeURIComponent", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "encodeURIComponent", + call: builtinGlobalEncodeURIComponent, + }, + }, + }, + }, + "escape": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "escape", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "escape", + call: builtinGlobalEscape, + }, + }, + }, + }, + "unescape": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "unescape", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "unescape", + call: builtinGlobalUnescape, + }, + }, + }, + }, + classObjectName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Object, + }, + }, + classFunctionName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Function, + }, + }, + classArrayName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Array, + }, + }, + classStringName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.String, + }, + }, + classBooleanName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Boolean, + }, + }, + classNumberName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Number, + }, + }, + classMathName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Math, + }, + }, + classDateName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Date, + }, + }, + classRegExpName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RegExp, + }, + }, + classErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Error, + }, + }, + classEvalErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.EvalError, + }, + }, + classTypeErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.TypeError, + }, + }, + classRangeErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RangeError, + }, + }, + classReferenceErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.ReferenceError, + }, + }, + classSyntaxErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.SyntaxError, + }, + }, + classURIErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.URIError, + }, + }, + classJSONName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.JSON, + }, + }, + "undefined": { + mode: 0, + value: Value{ + kind: valueUndefined, + }, + }, + "NaN": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.NaN(), + }, + }, + "Infinity": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(+1), + }, + }, } -} -func toValue_int64(value int64) Value { - return Value{ - kind: valueNumber, - value: value, + // Global property order. + rt.globalObject.propertyOrder = []string{ + "eval", + "parseInt", + "parseFloat", + "isNaN", + "isFinite", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "escape", + "unescape", + classObjectName, + classFunctionName, + classArrayName, + classStringName, + classBooleanName, + classNumberName, + classMathName, + classDateName, + classRegExpName, + classErrorName, + classEvalErrorName, + classTypeErrorName, + classRangeErrorName, + classReferenceErrorName, + classSyntaxErrorName, + classURIErrorName, + classJSONName, + "undefined", + "NaN", + "Infinity", } } -func toValue_uint(value uint) Value { - return Value{ - kind: valueNumber, - value: value, +func (rt *runtime) newConsole() *object { + return &object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "log": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "log", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "log", + call: builtinConsoleLog, + }, + }, + }, + }, + "debug": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "debug", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "debug", + call: builtinConsoleLog, + }, + }, + }, + }, + "info": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "info", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "info", + call: builtinConsoleLog, + }, + }, + }, + }, + "error": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "error", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "error", + call: builtinConsoleError, + }, + }, + }, + }, + "warn": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "warn", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "warn", + call: builtinConsoleError, + }, + }, + }, + }, + "dir": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "dir", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "dir", + call: builtinConsoleDir, + }, + }, + }, + }, + "time": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "time", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "time", + call: builtinConsoleTime, + }, + }, + }, + }, + "timeEnd": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "timeEnd", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "timeEnd", + call: builtinConsoleTimeEnd, + }, + }, + }, + }, + "trace": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "trace", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "trace", + call: builtinConsoleTrace, + }, + }, + }, + }, + "assert": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + propertyName: { + mode: 0, + value: Value{ + kind: valueString, + value: "assert", + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyName, + }, + value: nativeFunctionObject{ + name: "assert", + call: builtinConsoleAssert, + }, + }, + }, + }, + }, + propertyOrder: []string{ + "log", + "debug", + "info", + "error", + "warn", + "dir", + "time", + "timeEnd", + "trace", + "assert", + }, } } -func toValue_uint8(value uint8) Value { +func intValue(value int) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint16(value uint16) Value { +func int32Value(value int32) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint32(value uint32) Value { +func int64Value(value int64) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint64(value uint64) Value { +func uint16Value(value uint16) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_float32(value float32) Value { +func uint32Value(value uint32) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_float64(value float64) Value { +func float64Value(value float64) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_string(value string) Value { +func stringValue(value string) Value { return Value{ kind: valueString, value: value, } } -func toValue_string16(value []uint16) Value { +func string16Value(value []uint16) Value { return Value{ kind: valueString, value: value, } } -func toValue_bool(value bool) Value { +func boolValue(value bool) Value { return Value{ kind: valueBoolean, value: value, } } -func toValue_object(value *_object) Value { +func objectValue(value *object) Value { return Value{ kind: valueObject, value: value, diff --git a/vendor/github.com/robertkrimen/otto/inline.pl b/vendor/github.com/robertkrimen/otto/inline.pl deleted file mode 100644 index e90290489..000000000 --- a/vendor/github.com/robertkrimen/otto/inline.pl +++ /dev/null @@ -1,1086 +0,0 @@ -#!/usr/bin/env perl - -my $_fmt; -$_fmt = "gofmt"; -$_fmt = "cat -n" if "cat" eq ($ARGV[0] || ""); - -use strict; -use warnings; -use IO::File; - -my $self = __PACKAGE__; - -sub functionLabel ($) { - return "$_[0]_function"; -} - -sub trim ($) { - local $_ = shift; - s/^\s*//, s/\s*$// for $_; - return $_; -} - -open my $fmt, "|-", "$_fmt" or die $!; - -$fmt->print(<<_END_); -package otto - -import ( - "math" -) - -func _newContext(runtime *_runtime) { -@{[ join "\n", $self->newContext() ]} -} - -func newConsoleObject(runtime *_runtime) *_object { -@{[ join "\n", $self->newConsoleObject() ]} -} -_END_ - -for (qw/int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float32 float64/) { - $fmt->print(<<_END_); - -func toValue_$_(value $_) Value { - return Value{ - kind: valueNumber, - value: value, - } -} -_END_ -} - -$fmt->print(<<_END_); - -func toValue_string(value string) Value { - return Value{ - kind: valueString, - value: value, - } -} - -func toValue_string16(value []uint16) Value { - return Value{ - kind: valueString, - value: value, - } -} - -func toValue_bool(value bool) Value { - return Value{ - kind: valueBoolean, - value: value, - } -} - -func toValue_object(value *_object) Value { - return Value{ - kind: valueObject, - value: value, - } -} -_END_ - -close $fmt; - -sub newConsoleObject { - my $self = shift; - - return - $self->block(sub { - my $class = "Console"; - my @got = $self->functionDeclare( - $class, - "log", 0, - "debug:log", 0, - "info:log", 0, - "error", 0, - "warn:error", 0, - "dir", 0, - "time", 0, - "timeEnd", 0, - "trace", 0, - "assert", 0, - ); - return - "return @{[ $self->newObject(@got) ]}" - }), - ; -} - -sub newContext { - my $self = shift; - return - # ObjectPrototype - $self->block(sub { - my $class = "Object"; - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - undef, - "prototypeValueObject", - ), - }), - - # FunctionPrototype - $self->block(sub { - my $class = "Function"; - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueFunction", - ), - }), - - # ObjectPrototype - $self->block(sub { - my $class = "Object"; - my @got = $self->functionDeclare( - $class, - "valueOf", 0, - "toString", 0, - "toLocaleString", 0, - "hasOwnProperty", 1, - "isPrototypeOf", 1, - "propertyIsEnumerable", 1, - ); - my @propertyMap = $self->propertyMap( - @got, - $self->property("constructor", undef), - ); - my $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder =~ s/^propertyOrder: //; - return - ".${class}Prototype.property =", @propertyMap, - ".${class}Prototype.propertyOrder =", $propertyOrder, - }), - - # FunctionPrototype - $self->block(sub { - my $class = "Function"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "apply", 2, - "call", 1, - "bind", 1, - ); - my @propertyMap = $self->propertyMap( - @got, - $self->property("constructor", undef), - $self->property("length", $self->numberValue(0), "0"), - ); - my $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder =~ s/^propertyOrder: //; - return - ".${class}Prototype.property =", @propertyMap, - ".${class}Prototype.propertyOrder =", $propertyOrder, - }), - - # Object - $self->block(sub { - my $class = "Object"; - return - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - "getPrototypeOf", 1, - "getOwnPropertyDescriptor", 2, - "defineProperty", 3, - "defineProperties", 2, - "create", 2, - "isExtensible", 1, - "preventExtensions", 1, - "isSealed", 1, - "seal", 1, - "isFrozen", 1, - "freeze", 1, - "keys", 1, - "getOwnPropertyNames", 1, - ), - ), - }), - - # Function - $self->block(sub { - my $class = "Function"; - return - "Function :=", - $self->globalFunction( - $class, - 1, - ), - ".$class = Function", - }), - - # Array - $self->block(sub { - my $class = "Array"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "toLocaleString", 0, - "concat", 1, - "join", 1, - "splice", 2, - "shift", 0, - "pop", 0, - "push", 1, - "slice", 2, - "unshift", 1, - "reverse", 0, - "sort", 1, - "indexOf", 1, - "lastIndexOf", 1, - "every", 1, - "some", 1, - "forEach", 1, - "map", 1, - "filter", 1, - "reduce", 1, - "reduceRight", 1, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classArray", - ".ObjectPrototype", - undef, - $self->property("length", $self->numberValue("uint32(0)"), "0100"), - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - "isArray", 1, - ), - ), - }), - - # String - $self->block(sub { - my $class = "String"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "valueOf", 0, - "charAt", 1, - "charCodeAt", 1, - "concat", 1, - "indexOf", 1, - "lastIndexOf", 1, - "match", 1, - "replace", 2, - "search", 1, - "split", 2, - "slice", 2, - "substring", 2, - "toLowerCase", 0, - "toUpperCase", 0, - "substr", 2, - "trim", 0, - "trimLeft", 0, - "trimRight", 0, - "localeCompare", 1, - "toLocaleLowerCase", 0, - "toLocaleUpperCase", 0, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classString", - ".ObjectPrototype", - "prototypeValueString", - $self->property("length", $self->numberValue("int(0)"), "0"), - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - "fromCharCode", 1, - ), - ), - }), - - # Boolean - $self->block(sub { - my $class = "Boolean"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "valueOf", 0, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueBoolean", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - ), - }), - - # Number - $self->block(sub { - my $class = "Number"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "valueOf", 0, - "toFixed", 1, - "toExponential", 1, - "toPrecision", 1, - "toLocaleString", 1, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueNumber", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - $self->numberConstantDeclare( - "MAX_VALUE", "math.MaxFloat64", - "MIN_VALUE", "math.SmallestNonzeroFloat64", - "NaN", "math.NaN()", - "NEGATIVE_INFINITY", "math.Inf(-1)", - "POSITIVE_INFINITY", "math.Inf(+1)", - ), - ), - }), - - # Math - $self->block(sub { - my $class = "Math"; - return - ".$class =", - $self->globalObject( - $class, - $self->functionDeclare( - $class, - "abs", 1, - "acos", 1, - "asin", 1, - "atan", 1, - "atan2", 1, - "ceil", 1, - "cos", 1, - "exp", 1, - "floor", 1, - "log", 1, - "max", 2, - "min", 2, - "pow", 2, - "random", 0, - "round", 1, - "sin", 1, - "sqrt", 1, - "tan", 1, - ), - $self->numberConstantDeclare( - "E", "math.E", - "LN10", "math.Ln10", - "LN2", "math.Ln2", - "LOG2E", "math.Log2E", - "LOG10E", "math.Log10E", - "PI", "math.Pi", - "SQRT1_2", "sqrt1_2", - "SQRT2", "math.Sqrt2", - ) - ), - }), - - # Date - $self->block(sub { - my $class = "Date"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "toDateString", 0, - "toTimeString", 0, - "toUTCString", 0, - "toISOString", 0, - "toJSON", 1, - "toGMTString", 0, - "toLocaleString", 0, - "toLocaleDateString", 0, - "toLocaleTimeString", 0, - "valueOf", 0, - "getTime", 0, - "getYear", 0, - "getFullYear", 0, - "getUTCFullYear", 0, - "getMonth", 0, - "getUTCMonth", 0, - "getDate", 0, - "getUTCDate", 0, - "getDay", 0, - "getUTCDay", 0, - "getHours", 0, - "getUTCHours", 0, - "getMinutes", 0, - "getUTCMinutes", 0, - "getSeconds", 0, - "getUTCSeconds", 0, - "getMilliseconds", 0, - "getUTCMilliseconds", 0, - "getTimezoneOffset", 0, - "setTime", 1, - "setMilliseconds", 1, - "setUTCMilliseconds", 1, - "setSeconds", 2, - "setUTCSeconds", 2, - "setMinutes", 3, - "setUTCMinutes", 3, - "setHours", 4, - "setUTCHours", 4, - "setDate", 1, - "setUTCDate", 1, - "setMonth", 2, - "setUTCMonth", 2, - "setYear", 1, - "setFullYear", 3, - "setUTCFullYear", 3, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueDate", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 7, - $self->functionDeclare( - $class, - "parse", 1, - "UTC", 7, - "now", 0, - ), - ), - }), - - # RegExp - $self->block(sub { - my $class = "RegExp"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - "exec", 1, - "test", 1, - "compile", 1, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - "prototypeValueRegExp", - @got, - ), - ".$class =", - $self->globalFunction( - $class, - 2, - $self->functionDeclare( - $class, - ), - ), - }), - - # Error - $self->block(sub { - my $class = "Error"; - my @got = $self->functionDeclare( - $class, - "toString", 0, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ObjectPrototype", - undef, - @got, - $self->property("name", $self->stringValue("Error")), - $self->property("message", $self->stringValue("")), - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - ), - }), - - (map { - my $class = "${_}Error"; - $self->block(sub { - my @got = $self->functionDeclare( - $class, - ); - return - ".${class}Prototype =", - $self->globalPrototype( - $class, - "_classObject", - ".ErrorPrototype", - undef, - @got, - $self->property("name", $self->stringValue($class)), - ), - ".$class =", - $self->globalFunction( - $class, - 1, - $self->functionDeclare( - $class, - ), - ), - }); - } qw/Eval Type Range Reference Syntax URI/), - - # JSON - $self->block(sub { - my $class = "JSON"; - return - ".$class =", - $self->globalObject( - $class, - $self->functionDeclare( - $class, - "parse", 2, - "stringify", 3, - ), - ), - }), - - # Global - $self->block(sub { - my $class = "Global"; - my @got = $self->functionDeclare( - $class, - "eval", 1, - "parseInt", 2, - "parseFloat", 1, - "isNaN", 1, - "isFinite", 1, - "decodeURI", 1, - "decodeURIComponent", 1, - "encodeURI", 1, - "encodeURIComponent", 1, - "escape", 1, - "unescape", 1, - ); - my @propertyMap = $self->propertyMap( - @got, - $self->globalDeclare( - "Object", - "Function", - "Array", - "String", - "Boolean", - "Number", - "Math", - "Date", - "RegExp", - "Error", - "EvalError", - "TypeError", - "RangeError", - "ReferenceError", - "SyntaxError", - "URIError", - "JSON", - ), - $self->property("undefined", $self->undefinedValue(), "0"), - $self->property("NaN", $self->numberValue("math.NaN()"), "0"), - $self->property("Infinity", $self->numberValue("math.Inf(+1)"), "0"), - ); - my $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder =~ s/^propertyOrder: //; - return - "runtime.globalObject.property =", - @propertyMap, - "runtime.globalObject.propertyOrder =", - $propertyOrder, - ; - }), - ; -} - -sub propertyMap { - my $self = shift; - return "map[string]_property{", (join ",\n", @_, ""), "}", -} - -our (@preblock, @postblock); -sub block { - my $self = shift; - local @preblock = (); - local @postblock = (); - my @input = $_[0]->(); - my @output; - while (@input) { - local $_ = shift @input; - if (m/^\./) { - $_ = "runtime.global$_"; - } - if (m/ :?=$/) { - $_ .= shift @input; - } - push @output, $_; - } - return - "{", - @preblock, - @output, - @postblock, - "}", - ; -} - -sub numberConstantDeclare { - my $self = shift; - my @got; - while (@_) { - my $name = shift; - my $value = shift; - push @got, $self->property($name, $self->numberValue($value), "0"), - } - return @got; -} - -sub functionDeclare { - my $self = shift; - my $class = shift; - my $builtin = "builtin${class}"; - my @got; - while (@_) { - my $name = shift; - my $length = shift; - $name = $self->newFunction($name, "${builtin}_", $length); - push @got, $self->functionProperty($name), - } - return @got; -} - -sub globalDeclare { - my $self = shift; - my @got; - while (@_) { - my $name = shift; - push @got, $self->property($name, $self->objectValue("runtime.global.$name"), "0101"), - } - return @got; -} - -sub propertyOrder { - my $self = shift; - my $propertyMap = join "", @_; - - my (@keys) = $propertyMap =~ m/("\w+"):/g; - my $propertyOrder = - join "\n", "propertyOrder: []string{", (join ",\n", @keys, ""), "}"; - return $propertyOrder; -} - -sub globalObject { - my $self = shift; - my $name = shift; - - my $propertyMap = ""; - if (@_) { - $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - $propertyMap = "property: $propertyMap,\n$propertyOrder,"; - } - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "$name", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - $propertyMap -} -_END_ -} - -sub globalFunction { - my $self = shift; - my $name = shift; - my $length = shift; - - my $builtin = "builtin${name}"; - my $builtinNew = "builtinNew${name}"; - my $prototype = "runtime.global.${name}Prototype"; - my $propertyMap = ""; - unshift @_, - $self->property("length", $self->numberValue($length), "0"), - $self->property("prototype", $self->objectValue($prototype), "0"), - ; - - if (@_) { - $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - $propertyMap = "property: $propertyMap,\n$propertyOrder,"; - } - - push @postblock, $self->statement( - "$prototype.property[\"constructor\"] =", - $self->property(undef, $self->objectValue("runtime.global.${name}"), "0101"), - ); - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: @{[ $self->nativeFunctionOf($name, $builtin, $builtinNew) ]}, - $propertyMap -} -_END_ -} - -sub nativeCallFunction { - my $self = shift; - my $name = shift; - my $func = shift; - return trim <<_END_; -_nativeCallFunction{ "$name", $func } -_END_ -} - -sub globalPrototype { - my $self = shift; - my $class = shift; - my $classObject = shift; - my $prototype = shift; - my $value = shift; - - if (!defined $prototype) { - $prototype = "nil"; - } - - if (!defined $value) { - $value = "nil"; - } - - if ($prototype =~ m/^\./) { - $prototype = "runtime.global$prototype"; - } - - my $propertyMap = ""; - if (@_) { - $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - $propertyMap = "property: $propertyMap,\n$propertyOrder,"; - } - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "$class", - objectClass: $classObject, - prototype: $prototype, - extensible: true, - value: $value, - $propertyMap -} -_END_ -} - -sub newFunction { - my $self = shift; - my $name = shift; - my $func = shift; - my $length = shift; - - my @name = ($name, $name); - if ($name =~ m/^(\w+):(\w+)$/) { - @name = ($1, $2); - $name = $name[0]; - } - - if ($func =~ m/^builtin\w+_$/) { - $func = "$func$name[1]"; - } - - my $propertyOrder = ""; - my @propertyMap = ( - $self->property("length", $self->numberValue($length), "0"), - ); - - if (@propertyMap) { - $propertyOrder = $self->propertyOrder(@propertyMap); - $propertyOrder = "$propertyOrder,"; - } - - my $label = functionLabel($name); - push @preblock, $self->statement( - "$label := @{[ trim <<_END_ ]}", -&_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: @{[ join "\n", $self->propertyMap(@propertyMap) ]}, - $propertyOrder - value: @{[ $self->nativeFunctionOf($name, $func) ]}, -} -_END_ - ); - - return $name; -} - -sub newObject { - my $self = shift; - - my $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: $propertyMap, - $propertyOrder, -} -_END_ -} - -sub newPrototypeObject { - my $self = shift; - my $class = shift; - my $objectClass = shift; - my $value = shift; - if (defined $value) { - $value = "value: $value,"; - } - - my $propertyMap = join "\n", $self->propertyMap(@_); - my $propertyOrder = $self->propertyOrder($propertyMap); - - return trim <<_END_; -&_object{ - runtime: runtime, - class: "$class", - objectClass: $objectClass, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: $propertyMap, - $propertyOrder, - $value -} -_END_ -} - -sub functionProperty { - my $self = shift; - my $name = shift; - - return $self->property( - $name, - $self->objectValue(functionLabel($name)) - ); -} - -sub statement { - my $self = shift; - return join "\n", @_; -} - -sub functionOf { - my $self = shift; - my $call = shift; - my $construct = shift; - if ($construct) { - $construct = "construct: $construct,"; - } else { - $construct = ""; - } - - return trim <<_END_ -_functionObject{ - call: $call, - $construct -} -_END_ -} - -sub nativeFunctionOf { - my $self = shift; - my $name = shift; - my $call = shift; - my $construct = shift; - if ($construct) { - $construct = "construct: $construct,"; - } else { - $construct = ""; - } - - return trim <<_END_ -_nativeFunctionObject{ - name: "$name", - call: $call, - $construct -} -_END_ -} - -sub nameProperty { - my $self = shift; - my $name = shift; - my $value = shift; - - return trim <<_END_; -"$name": _property{ - mode: 0101, - value: $value, -} -_END_ -} - -sub numberValue { - my $self = shift; - my $value = shift; - return trim <<_END_; -Value{ - kind: valueNumber, - value: $value, -} -_END_ -} - -sub property { - my $self = shift; - my $name = shift; - my $value = shift; - my $mode = shift; - $mode = "0101" unless defined $mode; - if (! defined $value) { - $value = "Value{}"; - } - if (defined $name) { - return trim <<_END_; -"$name": _property{ - mode: $mode, - value: $value, -} -_END_ - } else { - return trim <<_END_; -_property{ - mode: $mode, - value: $value, -} -_END_ - } - -} - -sub objectProperty { - my $self = shift; - my $name = shift; - my $value = shift; - - return trim <<_END_; -"$name": _property{ - mode: 0101, - value: @{[ $self->objectValue($value)]}, -} -_END_ -} - -sub objectValue { - my $self = shift; - my $value = shift; - return trim <<_END_ -Value{ - kind: valueObject, - value: $value, -} -_END_ -} - -sub stringValue { - my $self = shift; - my $value = shift; - return trim <<_END_ -Value{ - kind: valueString, - value: "$value", -} -_END_ -} - -sub booleanValue { - my $self = shift; - my $value = shift; - return trim <<_END_ -Value{ - kind: valueBoolean, - value: $value, -} -_END_ -} - -sub undefinedValue { - my $self = shift; - return trim <<_END_ -Value{ - kind: valueUndefined, -} -_END_ -} diff --git a/vendor/github.com/robertkrimen/otto/locale.go b/vendor/github.com/robertkrimen/otto/locale.go new file mode 100644 index 000000000..c92fe8964 --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/locale.go @@ -0,0 +1,5 @@ +package otto + +import "golang.org/x/text/language" + +var defaultLanguage = language.MustParse("en-US") diff --git a/vendor/github.com/robertkrimen/otto/object.go b/vendor/github.com/robertkrimen/otto/object.go index 849812c91..40da58f76 100644 --- a/vendor/github.com/robertkrimen/otto/object.go +++ b/vendor/github.com/robertkrimen/otto/object.go @@ -1,78 +1,75 @@ package otto -type _object struct { - runtime *_runtime - - class string - objectClass *_objectClass - value interface{} - - prototype *_object - extensible bool - - property map[string]_property +type object struct { + value interface{} + runtime *runtime + objectClass *objectClass + prototype *object + property map[string]property + class string propertyOrder []string + extensible bool } -func newObject(runtime *_runtime, class string) *_object { - self := &_object{ - runtime: runtime, +func newObject(rt *runtime, class string) *object { + o := &object{ + runtime: rt, class: class, - objectClass: _classObject, - property: make(map[string]_property), + objectClass: classObject, + property: make(map[string]property), extensible: true, } - return self + return o } // 8.12 -// 8.12.1 -func (self *_object) getOwnProperty(name string) *_property { - return self.objectClass.getOwnProperty(self, name) +// 8.12.1. +func (o *object) getOwnProperty(name string) *property { + return o.objectClass.getOwnProperty(o, name) } -// 8.12.2 -func (self *_object) getProperty(name string) *_property { - return self.objectClass.getProperty(self, name) +// 8.12.2. +func (o *object) getProperty(name string) *property { + return o.objectClass.getProperty(o, name) } -// 8.12.3 -func (self *_object) get(name string) Value { - return self.objectClass.get(self, name) +// 8.12.3. +func (o *object) get(name string) Value { + return o.objectClass.get(o, name) } -// 8.12.4 -func (self *_object) canPut(name string) bool { - return self.objectClass.canPut(self, name) +// 8.12.4. +func (o *object) canPut(name string) bool { + return o.objectClass.canPut(o, name) } -// 8.12.5 -func (self *_object) put(name string, value Value, throw bool) { - self.objectClass.put(self, name, value, throw) +// 8.12.5. +func (o *object) put(name string, value Value, throw bool) { + o.objectClass.put(o, name, value, throw) } -// 8.12.6 -func (self *_object) hasProperty(name string) bool { - return self.objectClass.hasProperty(self, name) +// 8.12.6. +func (o *object) hasProperty(name string) bool { + return o.objectClass.hasProperty(o, name) } -func (self *_object) hasOwnProperty(name string) bool { - return self.objectClass.hasOwnProperty(self, name) +func (o *object) hasOwnProperty(name string) bool { + return o.objectClass.hasOwnProperty(o, name) } -type _defaultValueHint int +type defaultValueHint int const ( - defaultValueNoHint _defaultValueHint = iota + defaultValueNoHint defaultValueHint = iota defaultValueHintString defaultValueHintNumber ) -// 8.12.8 -func (self *_object) DefaultValue(hint _defaultValueHint) Value { +// 8.12.8. +func (o *object) DefaultValue(hint defaultValueHint) Value { if hint == defaultValueNoHint { - if self.class == "Date" { + if o.class == classDateName { // Date exception hint = defaultValueHintString } else { @@ -84,72 +81,67 @@ func (self *_object) DefaultValue(hint _defaultValueHint) Value { methodSequence = []string{"toString", "valueOf"} } for _, methodName := range methodSequence { - method := self.get(methodName) + method := o.get(methodName) // FIXME This is redundant... if method.isCallable() { - result := method._object().call(toValue_object(self), nil, false, nativeFrame) + result := method.object().call(objectValue(o), nil, false, nativeFrame) if result.IsPrimitive() { return result } } } - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError("Object.DefaultValue unknown")) } -func (self *_object) String() string { - return self.DefaultValue(defaultValueHintString).string() +func (o *object) String() string { + return o.DefaultValue(defaultValueHintString).string() } -func (self *_object) defineProperty(name string, value Value, mode _propertyMode, throw bool) bool { - return self.defineOwnProperty(name, _property{value, mode}, throw) +func (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint:unparam + return o.defineOwnProperty(name, property{value, mode}, throw) } -// 8.12.9 -func (self *_object) defineOwnProperty(name string, descriptor _property, throw bool) bool { - return self.objectClass.defineOwnProperty(self, name, descriptor, throw) +// 8.12.9. +func (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool { + return o.objectClass.defineOwnProperty(o, name, descriptor, throw) } -func (self *_object) delete(name string, throw bool) bool { - return self.objectClass.delete(self, name, throw) +func (o *object) delete(name string, throw bool) bool { + return o.objectClass.delete(o, name, throw) } -func (self *_object) enumerate(all bool, each func(string) bool) { - self.objectClass.enumerate(self, all, each) +func (o *object) enumerate(all bool, each func(string) bool) { + o.objectClass.enumerate(o, all, each) } -func (self *_object) _exists(name string) bool { - _, exists := self.property[name] - return exists +func (o *object) readProperty(name string) (property, bool) { + prop, exists := o.property[name] + return prop, exists } -func (self *_object) _read(name string) (_property, bool) { - property, exists := self.property[name] - return property, exists -} - -func (self *_object) _write(name string, value interface{}, mode _propertyMode) { +func (o *object) writeProperty(name string, value interface{}, mode propertyMode) { if value == nil { value = Value{} } - _, exists := self.property[name] - self.property[name] = _property{value, mode} - if !exists { - self.propertyOrder = append(self.propertyOrder, name) + if _, exists := o.property[name]; !exists { + o.propertyOrder = append(o.propertyOrder, name) } + o.property[name] = property{value, mode} } -func (self *_object) _delete(name string) { - _, exists := self.property[name] - delete(self.property, name) - if exists { - for index, property := range self.propertyOrder { - if name == property { - if index == len(self.propertyOrder)-1 { - self.propertyOrder = self.propertyOrder[:index] - } else { - self.propertyOrder = append(self.propertyOrder[:index], self.propertyOrder[index+1:]...) - } +func (o *object) deleteProperty(name string) { + if _, exists := o.property[name]; !exists { + return + } + + delete(o.property, name) + for index, prop := range o.propertyOrder { + if name == prop { + if index == len(o.propertyOrder)-1 { + o.propertyOrder = o.propertyOrder[:index] + } else { + o.propertyOrder = append(o.propertyOrder[:index], o.propertyOrder[index+1:]...) } } } diff --git a/vendor/github.com/robertkrimen/otto/object_class.go b/vendor/github.com/robertkrimen/otto/object_class.go index d18b9cede..e77ad8d92 100644 --- a/vendor/github.com/robertkrimen/otto/object_class.go +++ b/vendor/github.com/robertkrimen/otto/object_class.go @@ -4,24 +4,24 @@ import ( "encoding/json" ) -type _objectClass struct { - getOwnProperty func(*_object, string) *_property - getProperty func(*_object, string) *_property - get func(*_object, string) Value - canPut func(*_object, string) bool - put func(*_object, string, Value, bool) - hasProperty func(*_object, string) bool - hasOwnProperty func(*_object, string) bool - defineOwnProperty func(*_object, string, _property, bool) bool - delete func(*_object, string, bool) bool - enumerate func(*_object, bool, func(string) bool) - clone func(*_object, *_object, *_clone) *_object - marshalJSON func(*_object) json.Marshaler +type objectClass struct { + getOwnProperty func(*object, string) *property + getProperty func(*object, string) *property + get func(*object, string) Value + canPut func(*object, string) bool + put func(*object, string, Value, bool) + hasProperty func(*object, string) bool + hasOwnProperty func(*object, string) bool + defineOwnProperty func(*object, string, property, bool) bool + delete func(*object, string, bool) bool + enumerate func(*object, bool, func(string) bool) + clone func(*object, *object, *cloner) *object + marshalJSON func(*object) json.Marshaler } -func objectEnumerate(self *_object, all bool, each func(string) bool) { - for _, name := range self.propertyOrder { - if all || self.property[name].enumerable() { +func objectEnumerate(obj *object, all bool, each func(string) bool) { + for _, name := range obj.propertyOrder { + if all || obj.property[name].enumerable() { if !each(name) { return } @@ -29,20 +29,17 @@ func objectEnumerate(self *_object, all bool, each func(string) bool) { } } -var ( - _classObject, - _classArray, - _classString, - _classArguments, - _classGoStruct, - _classGoMap, - _classGoArray, - _classGoSlice, - _ *_objectClass -) +var classObject, + classArray, + classString, + classArguments, + classGoStruct, + classGoMap, + classGoArray, + classGoSlice *objectClass func init() { - _classObject = &_objectClass{ + classObject = &objectClass{ objectGetOwnProperty, objectGetProperty, objectGet, @@ -57,7 +54,7 @@ func init() { nil, } - _classArray = &_objectClass{ + classArray = &objectClass{ objectGetOwnProperty, objectGetProperty, objectGet, @@ -72,7 +69,7 @@ func init() { nil, } - _classString = &_objectClass{ + classString = &objectClass{ stringGetOwnProperty, objectGetProperty, objectGet, @@ -87,7 +84,7 @@ func init() { nil, } - _classArguments = &_objectClass{ + classArguments = &objectClass{ argumentsGetOwnProperty, objectGetProperty, argumentsGet, @@ -102,7 +99,7 @@ func init() { nil, } - _classGoStruct = &_objectClass{ + classGoStruct = &objectClass{ goStructGetOwnProperty, objectGetProperty, objectGet, @@ -117,7 +114,7 @@ func init() { goStructMarshalJSON, } - _classGoMap = &_objectClass{ + classGoMap = &objectClass{ goMapGetOwnProperty, objectGetProperty, objectGet, @@ -132,7 +129,7 @@ func init() { nil, } - _classGoArray = &_objectClass{ + classGoArray = &objectClass{ goArrayGetOwnProperty, objectGetProperty, objectGet, @@ -147,7 +144,7 @@ func init() { nil, } - _classGoSlice = &_objectClass{ + classGoSlice = &objectClass{ goSliceGetOwnProperty, objectGetProperty, objectGet, @@ -165,86 +162,81 @@ func init() { // Allons-y -// 8.12.1 -func objectGetOwnProperty(self *_object, name string) *_property { - // Return a _copy_ of the property - property, exists := self._read(name) +// 8.12.1. +func objectGetOwnProperty(obj *object, name string) *property { + // Return a _copy_ of the prop + prop, exists := obj.readProperty(name) if !exists { return nil } - return &property + return &prop } -// 8.12.2 -func objectGetProperty(self *_object, name string) *_property { - property := self.getOwnProperty(name) - if property != nil { - return property +// 8.12.2. +func objectGetProperty(obj *object, name string) *property { + prop := obj.getOwnProperty(name) + if prop != nil { + return prop } - if self.prototype != nil { - return self.prototype.getProperty(name) + if obj.prototype != nil { + return obj.prototype.getProperty(name) } return nil } -// 8.12.3 -func objectGet(self *_object, name string) Value { - property := self.getProperty(name) - if property != nil { - return property.get(self) +// 8.12.3. +func objectGet(obj *object, name string) Value { + if prop := obj.getProperty(name); prop != nil { + return prop.get(obj) } return Value{} } -// 8.12.4 -func objectCanPut(self *_object, name string) bool { - canPut, _, _ := _objectCanPut(self, name) +// 8.12.4. +func objectCanPut(obj *object, name string) bool { + canPut, _, _ := objectCanPutDetails(obj, name) return canPut } -func _objectCanPut(self *_object, name string) (canPut bool, property *_property, setter *_object) { - property = self.getOwnProperty(name) - if property != nil { - switch propertyValue := property.value.(type) { +func objectCanPutDetails(obj *object, name string) (canPut bool, prop *property, setter *object) { //nolint:nonamedreturns + prop = obj.getOwnProperty(name) + if prop != nil { + switch propertyValue := prop.value.(type) { case Value: - canPut = property.writable() - return - case _propertyGetSet: + return prop.writable(), prop, nil + case propertyGetSet: setter = propertyValue[1] - canPut = setter != nil - return + return setter != nil, prop, setter default: - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value)) } } - if self.prototype == nil { - return self.extensible, nil, nil + if obj.prototype == nil { + return obj.extensible, nil, nil } - property = self.prototype.getProperty(name) - if property == nil { - return self.extensible, nil, nil + prop = obj.prototype.getProperty(name) + if prop == nil { + return obj.extensible, nil, nil } - switch propertyValue := property.value.(type) { + switch propertyValue := prop.value.(type) { case Value: - if !self.extensible { + if !obj.extensible { return false, nil, nil } - return property.writable(), nil, nil - case _propertyGetSet: + return prop.writable(), nil, nil + case propertyGetSet: setter = propertyValue[1] - canPut = setter != nil - return + return setter != nil, prop, setter default: - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError("unexpected type %T to Object.CanPutDetails", prop.value)) } } -// 8.12.5 -func objectPut(self *_object, name string, value Value, throw bool) { - +// 8.12.5. +func objectPut(obj *object, name string, value Value, throw bool) { if true { // Shortcut... // @@ -254,16 +246,17 @@ func objectPut(self *_object, name string, value Value, throw bool) { // If that were to no longer be the case, we would have to have // something to detect that here, so that we do not use an // incompatible canPut routine - canPut, property, setter := _objectCanPut(self, name) - if !canPut { - self.runtime.typeErrorResult(throw) - } else if setter != nil { - setter.call(toValue(self), []Value{value}, false, nativeFrame) - } else if property != nil { - property.value = value - self.defineOwnProperty(name, *property, throw) - } else { - self.defineProperty(name, value, 0111, throw) + canPut, prop, setter := objectCanPutDetails(obj, name) + switch { + case !canPut: + obj.runtime.typeErrorResult(throw) + case setter != nil: + setter.call(toValue(obj), []Value{value}, false, nativeFrame) + case prop != nil: + prop.value = value + obj.defineOwnProperty(name, *prop, throw) + default: + obj.defineProperty(name, value, 0o111, throw) } return } @@ -271,221 +264,225 @@ func objectPut(self *_object, name string, value Value, throw bool) { // The long way... // // Right now, code should never get here, see above - if !self.canPut(name) { - self.runtime.typeErrorResult(throw) + if !obj.canPut(name) { + obj.runtime.typeErrorResult(throw) return } - property := self.getOwnProperty(name) - if property == nil { - property = self.getProperty(name) - if property != nil { - if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor { - getSet[1].call(toValue(self), []Value{value}, false, nativeFrame) + prop := obj.getOwnProperty(name) + if prop == nil { + prop = obj.getProperty(name) + if prop != nil { + if getSet, isAccessor := prop.value.(propertyGetSet); isAccessor { + getSet[1].call(toValue(obj), []Value{value}, false, nativeFrame) return } } - self.defineProperty(name, value, 0111, throw) - } else { - switch propertyValue := property.value.(type) { - case Value: - property.value = value - self.defineOwnProperty(name, *property, throw) - case _propertyGetSet: - if propertyValue[1] != nil { - propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame) - return - } - if throw { - panic(self.runtime.panicTypeError()) - } - default: - panic(self.runtime.panicTypeError()) + obj.defineProperty(name, value, 0o111, throw) + return + } + + switch propertyValue := prop.value.(type) { + case Value: + prop.value = value + obj.defineOwnProperty(name, *prop, throw) + case propertyGetSet: + if propertyValue[1] != nil { + propertyValue[1].call(toValue(obj), []Value{value}, false, nativeFrame) + return } + if throw { + panic(obj.runtime.panicTypeError("Object.Put nil second parameter to propertyGetSet")) + } + default: + panic(obj.runtime.panicTypeError("Object.Put unexpected type %T", prop.value)) } } -// 8.12.6 -func objectHasProperty(self *_object, name string) bool { - return self.getProperty(name) != nil +// 8.12.6. +func objectHasProperty(obj *object, name string) bool { + return obj.getProperty(name) != nil } -func objectHasOwnProperty(self *_object, name string) bool { - return self.getOwnProperty(name) != nil +func objectHasOwnProperty(obj *object, name string) bool { + return obj.getOwnProperty(name) != nil } -// 8.12.9 -func objectDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - property, exists := self._read(name) - { - if !exists { - if !self.extensible { - goto Reject - } - if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor { - if newGetSet[0] == &_nilGetSetObject { - newGetSet[0] = nil - } - if newGetSet[1] == &_nilGetSetObject { - newGetSet[1] = nil - } - descriptor.value = newGetSet - } - self._write(name, descriptor.value, descriptor.mode) - return true - } - if descriptor.isEmpty() { - return true +// 8.12.9. +func objectDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + reject := func(reason string) bool { + if throw { + panic(obj.runtime.panicTypeError("Object.DefineOwnProperty: %s", reason)) } + return false + } - // TODO Per 8.12.9.6 - We should shortcut here (returning true) if - // the current and new (define) properties are the same - - configurable := property.configurable() - if !configurable { - if descriptor.configurable() { - goto Reject - } - // Test that, if enumerable is set on the property descriptor, then it should - // be the same as the existing property - if descriptor.enumerateSet() && descriptor.enumerable() != property.enumerable() { - goto Reject - } + prop, exists := obj.readProperty(name) + if !exists { + if !obj.extensible { + return reject("not exists and not extensible") } - value, isDataDescriptor := property.value.(Value) - getSet, _ := property.value.(_propertyGetSet) - if descriptor.isGenericDescriptor() { - // GenericDescriptor - } else if isDataDescriptor != descriptor.isDataDescriptor() { - // DataDescriptor <=> AccessorDescriptor - if !configurable { - goto Reject - } - } else if isDataDescriptor && descriptor.isDataDescriptor() { - // DataDescriptor <=> DataDescriptor - if !configurable { - if !property.writable() && descriptor.writable() { - goto Reject - } - if !property.writable() { - if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) { - goto Reject - } - } - } - } else { - // AccessorDescriptor <=> AccessorDescriptor - newGetSet, _ := descriptor.value.(_propertyGetSet) - presentGet, presentSet := true, true - if newGetSet[0] == &_nilGetSetObject { - // Present, but nil + if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor { + if newGetSet[0] == &nilGetSetObject { newGetSet[0] = nil - } else if newGetSet[0] == nil { - // Missing, not even nil - newGetSet[0] = getSet[0] - presentGet = false } - if newGetSet[1] == &_nilGetSetObject { - // Present, but nil + if newGetSet[1] == &nilGetSetObject { newGetSet[1] = nil - } else if newGetSet[1] == nil { - // Missing, not even nil - newGetSet[1] = getSet[1] - presentSet = false - } - if !configurable { - if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) { - goto Reject - } } descriptor.value = newGetSet } - { - // This section will preserve attributes of - // the original property, if necessary - value1 := descriptor.value - if value1 == nil { - value1 = property.value - } else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor { - if newGetSet[0] == &_nilGetSetObject { - newGetSet[0] = nil - } - if newGetSet[1] == &_nilGetSetObject { - newGetSet[1] = nil - } - value1 = newGetSet + obj.writeProperty(name, descriptor.value, descriptor.mode) + return true + } + + if descriptor.isEmpty() { + return true + } + + // TODO Per 8.12.9.6 - We should shortcut here (returning true) if + // the current and new (define) properties are the same + + configurable := prop.configurable() + if !configurable { + if descriptor.configurable() { + return reject("property and descriptor not configurable") + } + // Test that, if enumerable is set on the property descriptor, then it should + // be the same as the existing property + if descriptor.enumerateSet() && descriptor.enumerable() != prop.enumerable() { + return reject("property not configurable and enumerable miss match") + } + } + + value, isDataDescriptor := prop.value.(Value) + getSet, _ := prop.value.(propertyGetSet) + switch { + case descriptor.isGenericDescriptor(): + // GenericDescriptor + case isDataDescriptor != descriptor.isDataDescriptor(): + // DataDescriptor <=> AccessorDescriptor + if !configurable { + return reject("property descriptor not configurable") + } + case isDataDescriptor && descriptor.isDataDescriptor(): + // DataDescriptor <=> DataDescriptor + if !configurable { + if !prop.writable() && descriptor.writable() { + return reject("property not configurable or writeable and descriptor not writeable") } - mode1 := descriptor.mode - if mode1&0222 != 0 { - // TODO Factor this out into somewhere testable - // (Maybe put into switch ...) - mode0 := property.mode - if mode1&0200 != 0 { - if descriptor.isDataDescriptor() { - mode1 &= ^0200 // Turn off "writable" missing - mode1 |= (mode0 & 0100) - } - } - if mode1&020 != 0 { - mode1 |= (mode0 & 010) + if !prop.writable() { + if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) { + return reject("property not configurable or writeable and descriptor not the same") } - if mode1&02 != 0 { - mode1 |= (mode0 & 01) - } - mode1 &= 0311 // 0311 to preserve the non-setting on "writable" } - self._write(name, value1, mode1) } - return true + default: + // AccessorDescriptor <=> AccessorDescriptor + newGetSet, _ := descriptor.value.(propertyGetSet) + presentGet, presentSet := true, true + if newGetSet[0] == &nilGetSetObject { + // Present, but nil + newGetSet[0] = nil + } else if newGetSet[0] == nil { + // Missing, not even nil + newGetSet[0] = getSet[0] + presentGet = false + } + if newGetSet[1] == &nilGetSetObject { + // Present, but nil + newGetSet[1] = nil + } else if newGetSet[1] == nil { + // Missing, not even nil + newGetSet[1] = getSet[1] + presentSet = false + } + if !configurable { + if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) { + return reject("access descriptor not configurable") + } + } + descriptor.value = newGetSet } -Reject: - if throw { - panic(self.runtime.panicTypeError()) + + // This section will preserve attributes of + // the original property, if necessary + value1 := descriptor.value + if value1 == nil { + value1 = prop.value + } else if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor { + if newGetSet[0] == &nilGetSetObject { + newGetSet[0] = nil + } + if newGetSet[1] == &nilGetSetObject { + newGetSet[1] = nil + } + value1 = newGetSet + } + mode1 := descriptor.mode + if mode1&0o222 != 0 { + // TODO Factor this out into somewhere testable + // (Maybe put into switch ...) + mode0 := prop.mode + if mode1&0o200 != 0 { + if descriptor.isDataDescriptor() { + mode1 &= ^0o200 // Turn off "writable" missing + mode1 |= (mode0 & 0o100) + } + } + if mode1&0o20 != 0 { + mode1 |= (mode0 & 0o10) + } + if mode1&0o2 != 0 { + mode1 |= (mode0 & 0o1) + } + mode1 &= 0o311 // 0311 to preserve the non-setting on "writable" } - return false + obj.writeProperty(name, value1, mode1) + + return true } -func objectDelete(self *_object, name string, throw bool) bool { - property_ := self.getOwnProperty(name) - if property_ == nil { +func objectDelete(obj *object, name string, throw bool) bool { + prop := obj.getOwnProperty(name) + if prop == nil { return true } - if property_.configurable() { - self._delete(name) + if prop.configurable() { + obj.deleteProperty(name) return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } -func objectClone(in *_object, out *_object, clone *_clone) *_object { +func objectClone(in *object, out *object, clone *cloner) *object { *out = *in out.runtime = clone.runtime if out.prototype != nil { out.prototype = clone.object(in.prototype) } - out.property = make(map[string]_property, len(in.property)) + out.property = make(map[string]property, len(in.property)) out.propertyOrder = make([]string, len(in.propertyOrder)) copy(out.propertyOrder, in.propertyOrder) - for index, property := range in.property { - out.property[index] = clone.property(property) + for index, prop := range in.property { + out.property[index] = clone.property(prop) } switch value := in.value.(type) { - case _nativeFunctionObject: + case nativeFunctionObject: out.value = value - case _bindFunctionObject: - out.value = _bindFunctionObject{ + case bindFunctionObject: + out.value = bindFunctionObject{ target: clone.object(value.target), this: clone.value(value.this), argumentList: clone.valueArray(value.argumentList), } - case _nodeFunctionObject: - out.value = _nodeFunctionObject{ + case nodeFunctionObject: + out.value = nodeFunctionObject{ node: value.node, stash: clone.stash(value.stash), } - case _argumentsObject: + case argumentsObject: out.value = value.clone(clone) } diff --git a/vendor/github.com/robertkrimen/otto/otto.go b/vendor/github.com/robertkrimen/otto/otto.go index b5b528d53..31b7e3013 100644 --- a/vendor/github.com/robertkrimen/otto/otto.go +++ b/vendor/github.com/robertkrimen/otto/otto.go @@ -3,81 +3,79 @@ Package otto is a JavaScript parser and interpreter written natively in Go. http://godoc.org/github.com/robertkrimen/otto - import ( - "github.com/robertkrimen/otto" - ) + import ( + "github.com/robertkrimen/otto" + ) Run something in the VM - vm := otto.New() - vm.Run(` - abc = 2 + 2; - console.log("The value of abc is " + abc); // 4 - `) + vm := otto.New() + vm.Run(` + abc = 2 + 2; + console.log("The value of abc is " + abc); // 4 + `) Get a value out of the VM - value, err := vm.Get("abc") - value, _ := value.ToInteger() - } + value, err := vm.Get("abc") + value, _ := value.ToInteger() + } Set a number - vm.Set("def", 11) - vm.Run(` - console.log("The value of def is " + def); - // The value of def is 11 - `) + vm.Set("def", 11) + vm.Run(` + console.log("The value of def is " + def); + // The value of def is 11 + `) Set a string - vm.Set("xyzzy", "Nothing happens.") - vm.Run(` - console.log(xyzzy.length); // 16 - `) + vm.Set("xyzzy", "Nothing happens.") + vm.Run(` + console.log(xyzzy.length); // 16 + `) Get the value of an expression - value, _ = vm.Run("xyzzy.length") - { - // value is an int64 with a value of 16 - value, _ := value.ToInteger() - } + value, _ = vm.Run("xyzzy.length") + // iv is an int64 with a value of 16 + iv, _ := value.ToInteger() An error happens - value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") - if err != nil { - // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined - // If there is an error, then value.IsUndefined() is true - ... - } + value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") + if err != nil { + // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined + // If there is an error, then value.IsUndefined() is true + ... + } Set a Go function - vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { - fmt.Printf("Hello, %s.\n", call.Argument(0).String()) - return otto.Value{} - }) + vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { + fmt.Printf("Hello, %s.\n", call.Argument(0).String()) + return otto.Value{} + }) Set a Go function that returns something useful - vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { - right, _ := call.Argument(0).ToInteger() - result, _ := vm.ToValue(2 + right) - return result - }) + vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { + right, _ := call.Argument(0).ToInteger() + result, _ := vm.ToValue(2 + right) + return result + }) Use the functions in JavaScript - result, _ = vm.Run(` - sayHello("Xyzzy"); // Hello, Xyzzy. - sayHello(); // Hello, undefined + result, _ = vm.Run(` + sayHello("Xyzzy"); // Hello, Xyzzy. + sayHello(); // Hello, undefined - result = twoPlus(2.0); // 4 - `) + result = twoPlus(2.0); // 4 + `) -Parser +# Parser A separate parser is available in the parser package if you're just interested in building an AST. @@ -85,23 +83,23 @@ http://godoc.org/github.com/robertkrimen/otto/parser Parse and return an AST - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } + filename := "" // A filename is optional + src := ` + // Sample xyzzy example + (function(){ + if (3.14159 > 0) { + console.log("Hello, World."); + return; + } - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` + var xyzzy = NaN; + console.log("Nothing happens."); + return xyzzy; + })(); + ` - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) + // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList + program, err := parser.ParseFile(nil, filename, src, 0) otto @@ -126,24 +124,24 @@ Optionally include the JavaScript utility-belt library, underscore, with this im For more information: http://github.com/robertkrimen/otto/tree/master/underscore -Caveat Emptor +# Caveat Emptor The following are some limitations with otto: - * "use strict" will parse, but does nothing. - * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. - * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. + - "use strict" will parse, but does nothing. + - The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. + - Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. -Regular Expression Incompatibility +# Regular Expression Incompatibility Go translates JavaScript-style regular expressions into something that is "regexp" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires backtracking for some patterns, and backtracking is not supported by the standard Go engine: https://code.google.com/p/re2/wiki/Syntax Therefore, the following syntax is incompatible: - (?=) // Lookahead (positive), currently a parsing error - (?!) // Lookahead (backhead), currently a parsing error - \1 // Backreference (\1, \2, \3, ...), currently a parsing error + (?=) // Lookahead (positive), currently a parsing error + (?!) // Lookahead (backhead), currently a parsing error + \1 // Backreference (\1, \2, \3, ...), currently a parsing error A brief discussion of these limitations: "Regexp (?!re)" https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E @@ -152,57 +150,57 @@ More information about re2: https://code.google.com/p/re2/ In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript definition, on the other hand, also includes \v, Unicode "Separator, Space", etc. -Halting Problem +# Halting Problem If you want to stop long running executions (like third-party code), you can use the interrupt channel to do this: - package main - - import ( - "errors" - "fmt" - "os" - "time" - - "github.com/robertkrimen/otto" - ) - - var halt = errors.New("Stahp") - - func main() { - runUnsafe(`var abc = [];`) - runUnsafe(` - while (true) { - // Loop forever - }`) - } - - func runUnsafe(unsafe string) { - start := time.Now() - defer func() { - duration := time.Since(start) - if caught := recover(); caught != nil { - if caught == halt { - fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration) - return - } - panic(caught) // Something else happened, repanic! - } - fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) - }() - - vm := otto.New() - vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking - - go func() { - time.Sleep(2 * time.Second) // Stop after two seconds - vm.Interrupt <- func() { - panic(halt) - } - }() - - vm.Run(unsafe) // Here be dragons (risky code) - } + package main + + import ( + "errors" + "fmt" + "os" + "time" + + "github.com/robertkrimen/otto" + ) + + var halt = errors.New("Stahp") + + func main() { + runUnsafe(`var abc = [];`) + runUnsafe(` + while (true) { + // Loop forever + }`) + } + + func runUnsafe(unsafe string) { + start := time.Now() + defer func() { + duration := time.Since(start) + if caught := recover(); caught != nil { + if caught == halt { + fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration) + return + } + panic(caught) // Something else happened, repanic! + } + fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) + }() + + vm := otto.New() + vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking + + go func() { + time.Sleep(2 * time.Second) // Stop after two seconds + vm.Interrupt <- func() { + panic(halt) + } + }() + + vm.Run(unsafe) // Here be dragons (risky code) + } Where is setTimeout/setInterval? @@ -216,52 +214,55 @@ http://github.com/robertkrimen/natto Here is some more discussion of the issue: * http://book.mixu.net/node/ch2.html - * http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 - * http://aaroncrane.co.uk/2009/02/perl_safe_signals/ - */ package otto import ( - "fmt" + "encoding/json" + "errors" "strings" "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/registry" ) -// Otto is the representation of the JavaScript runtime. Each instance of Otto has a self-contained namespace. +// Otto is the representation of the JavaScript runtime. +// Each instance of Otto has a self-contained namespace. type Otto struct { // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. // See "Halting Problem" for more information. Interrupt chan func() - runtime *_runtime + runtime *runtime } -// New will allocate a new JavaScript runtime +// New will allocate a new JavaScript runtime. func New() *Otto { - self := &Otto{ + o := &Otto{ runtime: newContext(), } - self.runtime.otto = self - self.runtime.traceLimit = 10 - self.Set("console", self.runtime.newConsole()) + o.runtime.otto = o + o.runtime.traceLimit = 10 + if err := o.Set("console", o.runtime.newConsole()); err != nil { + panic(err) + } registry.Apply(func(entry registry.Entry) { - self.Run(entry.Source()) + if _, err := o.Run(entry.Source()); err != nil { + panic(err) + } }) - return self + return o } -func (otto *Otto) clone() *Otto { - self := &Otto{ - runtime: otto.runtime.clone(), +func (o *Otto) clone() *Otto { + n := &Otto{ + runtime: o.runtime.clone(), } - self.runtime.otto = self - return self + n.runtime.otto = n + return n } // Run will allocate a new JavaScript runtime, run the given source @@ -273,7 +274,6 @@ func (otto *Otto) clone() *Otto { // src may also be a Script. // // src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. -// func Run(src interface{}) (*Otto, Value, error) { otto := New() value, err := otto.Run(src) // This already does safety checking @@ -290,9 +290,8 @@ func Run(src interface{}) (*Otto, Value, error) { // src may also be a Script. // // src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. -// -func (self Otto) Run(src interface{}) (Value, error) { - value, err := self.runtime.cmpl_run(src, nil) +func (o Otto) Run(src interface{}) (Value, error) { + value, err := o.runtime.cmplRun(src, nil) if !value.safe() { value = Value{} } @@ -304,13 +303,13 @@ func (self Otto) Run(src interface{}) (Value, error) { // By staying in the same scope, the code evaluated has access to everything // already defined in the current stack frame. This is most useful in, for // example, a debugger call. -func (self Otto) Eval(src interface{}) (Value, error) { - if self.runtime.scope == nil { - self.runtime.enterGlobalScope() - defer self.runtime.leaveScope() +func (o Otto) Eval(src interface{}) (Value, error) { + if o.runtime.scope == nil { + o.runtime.enterGlobalScope() + defer o.runtime.leaveScope() } - value, err := self.runtime.cmpl_eval(src, nil) + value, err := o.runtime.cmplEval(src, nil) if !value.safe() { value = Value{} } @@ -321,10 +320,10 @@ func (self Otto) Eval(src interface{}) (Value, error) { // // If there is an error (like the binding does not exist), then the value // will be undefined. -func (self Otto) Get(name string) (Value, error) { +func (o Otto) Get(name string) (Value, error) { value := Value{} err := catchPanic(func() { - value = self.getValue(name) + value = o.getValue(name) }) if !value.safe() { value = Value{} @@ -332,8 +331,8 @@ func (self Otto) Get(name string) (Value, error) { return value, err } -func (self Otto) getValue(name string) Value { - return self.runtime.globalStash.getBinding(name, false) +func (o Otto) getValue(name string) Value { + return o.runtime.globalStash.getBinding(name, false) } // Set the top-level binding of the given name to the given value. @@ -345,29 +344,29 @@ func (self Otto) getValue(name string) Value { // fails), then an error is returned. // // If the top-level binding does not exist, it will be created. -func (self Otto) Set(name string, value interface{}) error { - { - value, err := self.ToValue(value) - if err != nil { - return err - } - err = catchPanic(func() { - self.setValue(name, value) - }) +func (o Otto) Set(name string, value interface{}) error { + val, err := o.ToValue(value) + if err != nil { return err } + + return catchPanic(func() { + o.setValue(name, val) + }) } -func (self Otto) setValue(name string, value Value) { - self.runtime.globalStash.setValue(name, value, false) +func (o Otto) setValue(name string, value Value) { + o.runtime.globalStash.setValue(name, value, false) } -func (self Otto) SetDebuggerHandler(fn func(vm *Otto)) { - self.runtime.debugger = fn +// SetDebuggerHandler sets the debugger handler to fn. +func (o Otto) SetDebuggerHandler(fn func(vm *Otto)) { + o.runtime.debugger = fn } -func (self Otto) SetRandomSource(fn func() float64) { - self.runtime.random = fn +// SetRandomSource sets the random source to fn. +func (o Otto) SetRandomSource(fn func() float64) { + o.runtime.random = fn } // SetStackDepthLimit sets an upper limit to the depth of the JavaScript @@ -378,99 +377,100 @@ func (self Otto) SetRandomSource(fn func() float64) { // JavaScript makes a call to a Go function, otto won't keep track of what // happens outside the interpreter. So if your Go function is infinitely // recursive, you're still in trouble. -func (self Otto) SetStackDepthLimit(limit int) { - self.runtime.stackLimit = limit +func (o Otto) SetStackDepthLimit(limit int) { + o.runtime.stackLimit = limit } // SetStackTraceLimit sets an upper limit to the number of stack frames that // otto will use when formatting an error's stack trace. By default, the limit // is 10. This is consistent with V8 and SpiderMonkey. // -// TODO: expose via `Error.stackTraceLimit` -func (self Otto) SetStackTraceLimit(limit int) { - self.runtime.traceLimit = limit +// TODO: expose via `Error.stackTraceLimit`. +func (o Otto) SetStackTraceLimit(limit int) { + o.runtime.traceLimit = limit } // MakeCustomError creates a new Error object with the given name and message, // returning it as a Value. -func (self Otto) MakeCustomError(name, message string) Value { - return self.runtime.toValue(self.runtime.newError(name, self.runtime.toValue(message), 0)) +func (o Otto) MakeCustomError(name, message string) Value { + return o.runtime.toValue(o.runtime.newError(name, o.runtime.toValue(message), 0)) } // MakeRangeError creates a new RangeError object with the given message, // returning it as a Value. -func (self Otto) MakeRangeError(message string) Value { - return self.runtime.toValue(self.runtime.newRangeError(self.runtime.toValue(message))) +func (o Otto) MakeRangeError(message string) Value { + return o.runtime.toValue(o.runtime.newRangeError(o.runtime.toValue(message))) } // MakeSyntaxError creates a new SyntaxError object with the given message, // returning it as a Value. -func (self Otto) MakeSyntaxError(message string) Value { - return self.runtime.toValue(self.runtime.newSyntaxError(self.runtime.toValue(message))) +func (o Otto) MakeSyntaxError(message string) Value { + return o.runtime.toValue(o.runtime.newSyntaxError(o.runtime.toValue(message))) } // MakeTypeError creates a new TypeError object with the given message, // returning it as a Value. -func (self Otto) MakeTypeError(message string) Value { - return self.runtime.toValue(self.runtime.newTypeError(self.runtime.toValue(message))) +func (o Otto) MakeTypeError(message string) Value { + return o.runtime.toValue(o.runtime.newTypeError(o.runtime.toValue(message))) } // Context is a structure that contains information about the current execution // context. type Context struct { + This Value + Symbols map[string]Value Filename string - Line int - Column int Callee string - Symbols map[string]Value - This Value Stacktrace []string + Line int + Column int } // Context returns the current execution context of the vm, traversing up to // ten stack frames, and skipping any innermost native function stack frames. -func (self Otto) Context() Context { - return self.ContextSkip(10, true) +func (o Otto) Context() Context { + return o.ContextSkip(10, true) } // ContextLimit returns the current execution context of the vm, with a // specific limit on the number of stack frames to traverse, skipping any // innermost native function stack frames. -func (self Otto) ContextLimit(limit int) Context { - return self.ContextSkip(limit, true) +func (o Otto) ContextLimit(limit int) Context { + return o.ContextSkip(limit, true) } // ContextSkip returns the current execution context of the vm, with a // specific limit on the number of stack frames to traverse, optionally // skipping any innermost native function stack frames. -func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { +func (o Otto) ContextSkip(limit int, skipNative bool) Context { // Ensure we are operating in a scope - if self.runtime.scope == nil { - self.runtime.enterGlobalScope() - defer self.runtime.leaveScope() + if o.runtime.scope == nil { + o.runtime.enterGlobalScope() + defer o.runtime.leaveScope() } - scope := self.runtime.scope - frame := scope.frame + curScope := o.runtime.scope + frm := curScope.frame - for skipNative && frame.native && scope.outer != nil { - scope = scope.outer - frame = scope.frame + for skipNative && frm.native && curScope.outer != nil { + curScope = curScope.outer + frm = curScope.frame } // Get location information + var ctx Context ctx.Filename = "" - ctx.Callee = frame.callee + ctx.Callee = frm.callee switch { - case frame.native: - ctx.Filename = frame.nativeFile - ctx.Line = frame.nativeLine + case frm.native: + ctx.Filename = frm.nativeFile + ctx.Line = frm.nativeLine ctx.Column = 0 - case frame.file != nil: + case frm.file != nil: ctx.Filename = "" - if p := frame.file.Position(file.Idx(frame.offset)); p != nil { + if p := frm.file.Position(file.Idx(frm.offset)); p != nil { ctx.Line = p.Line ctx.Column = p.Column @@ -481,14 +481,14 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { } // Get the current scope this Value - ctx.This = toValue_object(scope.this) + ctx.This = objectValue(curScope.this) // Build stacktrace (up to 10 levels deep) ctx.Symbols = make(map[string]Value) - ctx.Stacktrace = append(ctx.Stacktrace, frame.location()) + ctx.Stacktrace = append(ctx.Stacktrace, frm.location()) for limit != 0 { // Get variables - stash := scope.lexical + stash := curScope.lexical for { for _, name := range getStashProperties(stash) { if _, ok := ctx.Symbols[name]; !ok { @@ -501,17 +501,17 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { } } - scope = scope.outer - if scope == nil { + curScope = curScope.outer + if curScope == nil { break } - if scope.frame.offset >= 0 { - ctx.Stacktrace = append(ctx.Stacktrace, scope.frame.location()) + if curScope.frame.offset >= 0 { + ctx.Stacktrace = append(ctx.Stacktrace, curScope.frame.location()) } limit-- } - return + return ctx } // Call the given JavaScript with a given this and arguments. @@ -524,18 +524,16 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { // Call will invoke the function constructor rather than performing a function call. // In this case, the this argument has no effect. // -// // value is a String object -// value, _ := vm.Call("Object", nil, "Hello, World.") +// // value is a String object +// value, _ := vm.Call("Object", nil, "Hello, World.") // -// // Likewise... -// value, _ := vm.Call("new Object", nil, "Hello, World.") +// // Likewise... +// value, _ := vm.Call("new Object", nil, "Hello, World.") // -// // This will perform a concat on the given array and return the result -// // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] -// value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") -// -func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { - +// // This will perform a concat on the given array and return the result +// // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] +// value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") +func (o Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { thisValue := Value{} construct := false @@ -545,21 +543,20 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } // FIXME enterGlobalScope - self.runtime.enterGlobalScope() + o.runtime.enterGlobalScope() defer func() { - self.runtime.leaveScope() + o.runtime.leaveScope() }() if !construct && this == nil { - program, err := self.runtime.cmpl_parse("", source+"()", nil) + program, err := o.runtime.cmplParse("", source+"()", nil) if err == nil { - if node, ok := program.body[0].(*_nodeExpressionStatement); ok { - if node, ok := node.expression.(*_nodeCallExpression); ok { + if node, ok := program.body[0].(*nodeExpressionStatement); ok { + if node, ok2 := node.expression.(*nodeCallExpression); ok2 { var value Value - err := catchPanic(func() { - value = self.runtime.cmpl_evaluate_nodeCallExpression(node, argumentList) - }) - if err != nil { + if err = catchPanic(func() { + value = o.runtime.cmplEvaluateNodeCallExpression(node, argumentList) + }); err != nil { return Value{}, err } return value, nil @@ -567,68 +564,65 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } } } else { - value, err := self.ToValue(this) + value, err := o.ToValue(this) if err != nil { return Value{}, err } thisValue = value } - { - this := thisValue - - fn, err := self.Run(source) - if err != nil { - return Value{}, err - } - - if construct { - result, err := fn.constructSafe(self.runtime, this, argumentList...) - if err != nil { - return Value{}, err - } - return result, nil - } + val := thisValue + fn, err := o.Run(source) + if err != nil { + return Value{}, err + } - result, err := fn.Call(this, argumentList...) - if err != nil { - return Value{}, err + if construct { + result, err2 := fn.constructSafe(o.runtime, val, argumentList...) + if err2 != nil { + return Value{}, err2 } return result, nil } + + result, err := fn.Call(val, argumentList...) + if err != nil { + return Value{}, err + } + return result, nil } // Object will run the given source and return the result as an object. // // For example, accessing an existing object: // -// object, _ := vm.Object(`Number`) +// object, _ := vm.Object(`Number`) // // Or, creating a new object: // -// object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`) +// object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`) // // Or, creating and assigning an object: // -// object, _ := vm.Object(`xyzzy = {}`) -// object.Set("volume", 11) +// object, _ := vm.Object(`xyzzy = {}`) +// object.Set("volume", 11) // // If there is an error (like the source does not result in an object), then // nil and an error is returned. -func (self Otto) Object(source string) (*Object, error) { - value, err := self.runtime.cmpl_run(source, nil) +func (o Otto) Object(source string) (*Object, error) { + value, err := o.runtime.cmplRun(source, nil) if err != nil { return nil, err } if value.IsObject() { return value.Object(), nil } - return nil, fmt.Errorf("value is not an object") + return nil, errors.New("value is not an object") } // ToValue will convert an interface{} value to a value digestible by otto/JavaScript. -func (self Otto) ToValue(value interface{}) (Value, error) { - return self.runtime.safeToValue(value) +func (o Otto) ToValue(value interface{}) (Value, error) { + return o.runtime.safeToValue(value) } // Copy will create a copy/clone of the runtime. @@ -639,64 +633,53 @@ func (self Otto) ToValue(value interface{}) (Value, error) { // etc. into a new runtime. // // Be on the lookout for memory leaks or inadvertent sharing of resources. -func (in *Otto) Copy() *Otto { +func (o *Otto) Copy() *Otto { out := &Otto{ - runtime: in.runtime.clone(), + runtime: o.runtime.clone(), } out.runtime.otto = out return out } -// Object{} - // Object is the representation of a JavaScript object. type Object struct { - object *_object + object *object value Value } -func _newObject(object *_object, value Value) *Object { - // value MUST contain object! - return &Object{ - object: object, - value: value, - } -} - // Call a method on the object. // // It is essentially equivalent to: // -// var method, _ := object.Get(name) -// method.Call(object, argumentList...) +// var method, _ := object.Get(name) +// method.Call(object, argumentList...) // // An undefined value and an error will result if: // -// 1. There is an error during conversion of the argument list -// 2. The property is not actually a function -// 3. An (uncaught) exception is thrown -// -func (self Object) Call(name string, argumentList ...interface{}) (Value, error) { +// 1. There is an error during conversion of the argument list +// 2. The property is not actually a function +// 3. An (uncaught) exception is thrown +func (o Object) Call(name string, argumentList ...interface{}) (Value, error) { // TODO: Insert an example using JavaScript below... // e.g., Object("JSON").Call("stringify", ...) - function, err := self.Get(name) + function, err := o.Get(name) if err != nil { return Value{}, err } - return function.Call(self.Value(), argumentList...) + return function.Call(o.Value(), argumentList...) } -// Value will return self as a value. -func (self Object) Value() Value { - return self.value +// Value returns the value of o. +func (o Object) Value() Value { + return o.value } // Get the value of the property with the given name. -func (self Object) Get(name string) (Value, error) { +func (o Object) Get(name string) (Value, error) { value := Value{} err := catchPanic(func() { - value = self.object.get(name) + value = o.object.get(name) }) if !value.safe() { value = Value{} @@ -708,25 +691,23 @@ func (self Object) Get(name string) (Value, error) { // // An error will result if the setting the property triggers an exception (i.e. read-only), // or there is an error during conversion of the given value. -func (self Object) Set(name string, value interface{}) error { - { - value, err := self.object.runtime.safeToValue(value) - if err != nil { - return err - } - err = catchPanic(func() { - self.object.put(name, value, true) - }) +func (o Object) Set(name string, value interface{}) error { + val, err := o.object.runtime.safeToValue(value) + if err != nil { return err } + + return catchPanic(func() { + o.object.put(name, val, true) + }) } // Keys gets the keys for the given object. // // Equivalent to calling Object.keys on the object. -func (self Object) Keys() []string { +func (o Object) Keys() []string { var keys []string - self.object.enumerate(false, func(name string) bool { + o.object.enumerate(false, func(name string) bool { keys = append(keys, name) return true }) @@ -735,10 +716,10 @@ func (self Object) Keys() []string { // KeysByParent gets the keys (and those of the parents) for the given object, // in order of "closest" to "furthest". -func (self Object) KeysByParent() [][]string { +func (o Object) KeysByParent() [][]string { var a [][]string - for o := self.object; o != nil; o = o.prototype { + for o := o.object; o != nil; o = o.prototype { var l []string o.enumerate(false, func(name string) bool { @@ -756,15 +737,41 @@ func (self Object) KeysByParent() [][]string { // // The return value will (generally) be one of: // -// Object -// Function -// Array -// String -// Number -// Boolean -// Date -// RegExp -// -func (self Object) Class() string { - return self.object.class +// Object +// Function +// Array +// String +// Number +// Boolean +// Date +// RegExp +func (o Object) Class() string { + return o.object.class +} + +// MarshalJSON implements json.Marshaller. +func (o Object) MarshalJSON() ([]byte, error) { + var goValue interface{} + switch value := o.object.value.(type) { + case *goStructObject: + goValue = value.value.Interface() + case *goMapObject: + goValue = value.value.Interface() + case *goArrayObject: + goValue = value.value.Interface() + case *goSliceObject: + goValue = value.value.Interface() + default: + // It's a JS object; pass it to JSON.stringify: + var result []byte + err := catchPanic(func() { + resultVal := builtinJSONStringify(FunctionCall{ + runtime: o.object.runtime, + ArgumentList: []Value{o.value}, + }) + result = []byte(resultVal.String()) + }) + return result, err + } + return json.Marshal(goValue) } diff --git a/vendor/github.com/robertkrimen/otto/otto_.go b/vendor/github.com/robertkrimen/otto/otto_.go index 304a83150..2bf06d27d 100644 --- a/vendor/github.com/robertkrimen/otto/otto_.go +++ b/vendor/github.com/robertkrimen/otto/otto_.go @@ -3,29 +3,28 @@ package otto import ( "fmt" "regexp" - runtime_ "runtime" + goruntime "runtime" "strconv" - "strings" ) -var isIdentifier_Regexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`) +var isIdentifierRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`) -func isIdentifier(string_ string) bool { - return isIdentifier_Regexp.MatchString(string_) +func isIdentifier(value string) bool { + return isIdentifierRegexp.MatchString(value) } -func (self *_runtime) toValueArray(arguments ...interface{}) []Value { +func (rt *runtime) toValueArray(arguments ...interface{}) []Value { length := len(arguments) if length == 1 { if valueArray, ok := arguments[0].([]Value); ok { return valueArray } - return []Value{self.toValue(arguments[0])} + return []Value{rt.toValue(arguments[0])} } valueArray := make([]Value, length) for index, value := range arguments { - valueArray[index] = self.toValue(value) + valueArray[index] = rt.toValue(value) } return valueArray @@ -90,15 +89,13 @@ func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int6 if index < 0 { index = 0 } - } else { - if index > length { - index = length - } + } else if index > length { + index = length } return index } -func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { +func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { //nolint:nonamedreturns start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero) if len(array) == 1 { // If there is only the start argument, then end = size @@ -116,14 +113,14 @@ func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end i return } -func rangeStartLength(source []Value, size int64) (start, length int64) { +func rangeStartLength(source []Value, size int64) (start, length int64) { //nolint:nonamedreturns start = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false) // Assume the second argument is missing or undefined - length = int64(size) + length = size if len(source) == 1 { // If there is only the start argument, then length = size - return + return start, length } lengthValue := valueOfArrayIndex(source, 1) @@ -131,21 +128,13 @@ func rangeStartLength(source []Value, size int64) (start, length int64) { // Which it is not, so get the value as an array index length = lengthValue.number().int64 } - return -} - -func boolFields(input string) (result map[string]bool) { - result = map[string]bool{} - for _, word := range strings.Fields(input) { - result[word] = true - } - return result + return start, length } func hereBeDragons(arguments ...interface{}) string { - pc, _, _, _ := runtime_.Caller(1) - name := runtime_.FuncForPC(pc).Name() - message := fmt.Sprintf("Here be dragons -- %s", name) + pc, _, _, _ := goruntime.Caller(1) //nolint:dogsled + name := goruntime.FuncForPC(pc).Name() + message := "Here be dragons -- " + name if len(arguments) > 0 { message += ": " argument0 := fmt.Sprintf("%s", arguments[0]) @@ -159,20 +148,3 @@ func hereBeDragons(arguments ...interface{}) string { } return message } - -func throwHereBeDragons(arguments ...interface{}) { - panic(hereBeDragons(arguments...)) -} - -func eachPair(list []interface{}, fn func(_0, _1 interface{})) { - for len(list) > 0 { - var _0, _1 interface{} - _0 = list[0] - list = list[1:] // Pop off first - if len(list) > 0 { - _1 = list[0] - list = list[1:] // Pop off second - } - fn(_0, _1) - } -} diff --git a/vendor/github.com/robertkrimen/otto/parser/Makefile b/vendor/github.com/robertkrimen/otto/parser/Makefile deleted file mode 100644 index 766fd4d0b..000000000 --- a/vendor/github.com/robertkrimen/otto/parser/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -.PHONY: test - -test: - go test diff --git a/vendor/github.com/robertkrimen/otto/parser/README.markdown b/vendor/github.com/robertkrimen/otto/parser/README.markdown deleted file mode 100644 index c3cae5b60..000000000 --- a/vendor/github.com/robertkrimen/otto/parser/README.markdown +++ /dev/null @@ -1,190 +0,0 @@ -# parser --- - import "github.com/robertkrimen/otto/parser" - -Package parser implements a parser for JavaScript. - - import ( - "github.com/robertkrimen/otto/parser" - ) - -Parse and return an AST - - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } - - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) - - -### Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -## Usage - -#### func ParseFile - -```go -func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) -``` -ParseFile parses the source code of a single JavaScript/ECMAScript source file -and returns the corresponding ast.Program node. - -If fileSet == nil, ParseFile parses source without a FileSet. If fileSet != nil, -ParseFile first adds filename and src to fileSet. - -The filename argument is optional and is used for labelling errors, etc. - -src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST -always be in UTF-8. - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) - -#### func ParseFunction - -```go -func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) -``` -ParseFunction parses a given parameter list and body as a function and returns -the corresponding ast.FunctionLiteral node. - -The parameter list, if any, should be a comma-separated list of identifiers. - -#### func ReadSource - -```go -func ReadSource(filename string, src interface{}) ([]byte, error) -``` - -#### func TransformRegExp - -```go -func TransformRegExp(pattern string) (string, error) -``` -TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern. - -re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or -backreference (\1, \2, ...) will cause an error. - -re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript -definition, on the other hand, also includes \v, Unicode "Separator, Space", -etc. - -If the pattern is invalid (not valid even in JavaScript), then this function -returns the empty string and an error. - -If the pattern is valid, but incompatible (contains a lookahead or -backreference), then this function returns the transformation (a non-empty -string) AND an error. - -#### type Error - -```go -type Error struct { - Position file.Position - Message string -} -``` - -An Error represents a parsing error. It includes the position where the error -occurred and a message/description. - -#### func (Error) Error - -```go -func (self Error) Error() string -``` - -#### type ErrorList - -```go -type ErrorList []*Error -``` - -ErrorList is a list of *Errors. - -#### func (*ErrorList) Add - -```go -func (self *ErrorList) Add(position file.Position, msg string) -``` -Add adds an Error with given position and message to an ErrorList. - -#### func (ErrorList) Err - -```go -func (self ErrorList) Err() error -``` -Err returns an error equivalent to this ErrorList. If the list is empty, Err -returns nil. - -#### func (ErrorList) Error - -```go -func (self ErrorList) Error() string -``` -Error implements the Error interface. - -#### func (ErrorList) Len - -```go -func (self ErrorList) Len() int -``` - -#### func (ErrorList) Less - -```go -func (self ErrorList) Less(i, j int) bool -``` - -#### func (*ErrorList) Reset - -```go -func (self *ErrorList) Reset() -``` -Reset resets an ErrorList to no errors. - -#### func (ErrorList) Sort - -```go -func (self ErrorList) Sort() -``` - -#### func (ErrorList) Swap - -```go -func (self ErrorList) Swap(i, j int) -``` - -#### type Mode - -```go -type Mode uint -``` - -A Mode value is a set of flags (or 0). They control optional parser -functionality. - -```go -const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) -) -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/parser/dbg.go b/vendor/github.com/robertkrimen/otto/parser/dbg.go deleted file mode 100644 index 3c5f2f698..000000000 --- a/vendor/github.com/robertkrimen/otto/parser/dbg.go +++ /dev/null @@ -1,9 +0,0 @@ -// This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) for github.com/robertkrimen/dbg - -package parser - -import ( - Dbg "github.com/robertkrimen/otto/dbg" -) - -var dbg, dbgf = Dbg.New() diff --git a/vendor/github.com/robertkrimen/otto/parser/error.go b/vendor/github.com/robertkrimen/otto/parser/error.go index e0f74a5cf..94d5a27b1 100644 --- a/vendor/github.com/robertkrimen/otto/parser/error.go +++ b/vendor/github.com/robertkrimen/otto/parser/error.go @@ -9,9 +9,8 @@ import ( ) const ( - err_UnexpectedToken = "Unexpected token %v" - err_UnexpectedEndOfInput = "Unexpected end of input" - err_UnexpectedEscape = "Unexpected escape" + errUnexpectedToken = "Unexpected token %v" + errUnexpectedEndOfInput = "Unexpected end of input" ) // UnexpectedNumber: 'Unexpected number', @@ -21,7 +20,7 @@ const ( // NewlineAfterThrow: 'Illegal newline after throw', // InvalidRegExp: 'Invalid regular expression', // UnterminatedRegExp: 'Invalid regular expression: missing /', -// InvalidLHSInAssignment: 'Invalid left-hand side in assignment', +// InvalidLHSInAssignment: 'invalid left-hand side in assignment', // InvalidLHSInForIn: 'Invalid left-hand side in for-in', // MultipleDefaultsInSwitch: 'More than one default clause in switch statement', // NoCatchOrFinally: 'Missing catch or finally after try', @@ -50,33 +49,33 @@ const ( // An Error represents a parsing error. It includes the position where the error occurred and a message/description. type Error struct { - Position file.Position Message string + Position file.Position } // FIXME Should this be "SyntaxError"? -func (self Error) Error() string { - filename := self.Position.Filename +func (e Error) Error() string { + filename := e.Position.Filename if filename == "" { filename = "(anonymous)" } return fmt.Sprintf("%s: Line %d:%d %s", filename, - self.Position.Line, - self.Position.Column, - self.Message, + e.Position.Line, + e.Position.Column, + e.Message, ) } -func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error { - idx := file.Idx(0) +func (p *parser) error(place interface{}, msg string, msgValues ...interface{}) { + var idx file.Idx switch place := place.(type) { case int: - idx = self.idxOf(place) + idx = p.idxOf(place) case file.Idx: if place == 0 { - idx = self.idxOf(self.chrOffset) + idx = p.idxOf(p.chrOffset) } else { idx = place } @@ -84,58 +83,69 @@ func (self *_parser) error(place interface{}, msg string, msgValues ...interface panic(fmt.Errorf("error(%T, ...)", place)) } - position := self.position(idx) + position := p.position(idx) msg = fmt.Sprintf(msg, msgValues...) - self.errors.Add(position, msg) - return self.errors[len(self.errors)-1] + p.errors.Add(position, msg) } -func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error { +func (p *parser) errorUnexpected(idx file.Idx, chr rune) { if chr == -1 { - return self.error(idx, err_UnexpectedEndOfInput) + p.error(idx, errUnexpectedEndOfInput) + return } - return self.error(idx, err_UnexpectedToken, token.ILLEGAL) + p.error(idx, errUnexpectedToken, token.ILLEGAL) } -func (self *_parser) errorUnexpectedToken(tkn token.Token) error { - switch tkn { - case token.EOF: - return self.error(file.Idx(0), err_UnexpectedEndOfInput) +func (p *parser) errorUnexpectedToken(tkn token.Token) { + if tkn == token.EOF { + p.error(file.Idx(0), errUnexpectedEndOfInput) + return } value := tkn.String() switch tkn { case token.BOOLEAN, token.NULL: - value = self.literal + p.error(p.idx, errUnexpectedToken, p.literal) case token.IDENTIFIER: - return self.error(self.idx, "Unexpected identifier") + p.error(p.idx, "Unexpected identifier") case token.KEYWORD: // TODO Might be a future reserved word - return self.error(self.idx, "Unexpected reserved word") + p.error(p.idx, "Unexpected reserved word") case token.NUMBER: - return self.error(self.idx, "Unexpected number") + p.error(p.idx, "Unexpected number") case token.STRING: - return self.error(self.idx, "Unexpected string") + p.error(p.idx, "Unexpected string") + default: + p.error(p.idx, errUnexpectedToken, value) } - return self.error(self.idx, err_UnexpectedToken, value) } // ErrorList is a list of *Errors. -// -type ErrorList []*Error +type ErrorList []*Error //nolint:errname // Add adds an Error with given position and message to an ErrorList. -func (self *ErrorList) Add(position file.Position, msg string) { - *self = append(*self, &Error{position, msg}) +func (el *ErrorList) Add(position file.Position, msg string) { + *el = append(*el, &Error{Position: position, Message: msg}) } // Reset resets an ErrorList to no errors. -func (self *ErrorList) Reset() { *self = (*self)[0:0] } +func (el *ErrorList) Reset() { + *el = (*el)[0:0] +} -func (self ErrorList) Len() int { return len(self) } -func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] } -func (self ErrorList) Less(i, j int) bool { - x := &self[i].Position - y := &self[j].Position +// Len implement sort.Interface. +func (el *ErrorList) Len() int { + return len(*el) +} + +// Swap implement sort.Interface. +func (el *ErrorList) Swap(i, j int) { + (*el)[i], (*el)[j] = (*el)[j], (*el)[i] +} + +// Less implement sort.Interface. +func (el *ErrorList) Less(i, j int) bool { + x := (*el)[i].Position + y := (*el)[j].Position if x.Filename < y.Filename { return true } @@ -150,26 +160,28 @@ func (self ErrorList) Less(i, j int) bool { return false } -func (self ErrorList) Sort() { - sort.Sort(self) +// Sort sorts el. +func (el *ErrorList) Sort() { + sort.Sort(el) } // Error implements the Error interface. -func (self ErrorList) Error() string { - switch len(self) { +func (el *ErrorList) Error() string { + switch len(*el) { case 0: return "no errors" case 1: - return self[0].Error() + return (*el)[0].Error() + default: + return fmt.Sprintf("%s (and %d more errors)", (*el)[0].Error(), len(*el)-1) } - return fmt.Sprintf("%s (and %d more errors)", self[0].Error(), len(self)-1) } // Err returns an error equivalent to this ErrorList. // If the list is empty, Err returns nil. -func (self ErrorList) Err() error { - if len(self) == 0 { +func (el *ErrorList) Err() error { + if len(*el) == 0 { return nil } - return self + return el } diff --git a/vendor/github.com/robertkrimen/otto/parser/expression.go b/vendor/github.com/robertkrimen/otto/parser/expression.go index 63a169d40..2c8e2994c 100644 --- a/vendor/github.com/robertkrimen/otto/parser/expression.go +++ b/vendor/github.com/robertkrimen/otto/parser/expression.go @@ -8,36 +8,36 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_parser) parseIdentifier() *ast.Identifier { - literal := self.literal - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) +func (p *parser) parseIdentifier() *ast.Identifier { + literal := p.literal + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) } - self.next() + p.next() exp := &ast.Identifier{ Name: literal, Idx: idx, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp } -func (self *_parser) parsePrimaryExpression() ast.Expression { - literal := self.literal - idx := self.idx - switch self.token { +func (p *parser) parsePrimaryExpression() ast.Expression { + literal := p.literal + idx := p.idx + switch p.token { case token.IDENTIFIER: - self.next() + p.next() if len(literal) > 1 { tkn, strict := token.IsKeyword(literal) if tkn == token.KEYWORD { if !strict { - self.error(idx, "Unexpected reserved word") + p.error(idx, "Unexpected reserved word") } } } @@ -46,13 +46,13 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Idx: idx, } case token.NULL: - self.next() + p.next() return &ast.NullLiteral{ Idx: idx, Literal: literal, } case token.BOOLEAN: - self.next() + p.next() value := false switch literal { case "true": @@ -60,7 +60,7 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { case "false": value = false default: - self.error(idx, "Illegal boolean literal") + p.error(idx, "Illegal boolean literal") } return &ast.BooleanLiteral{ Idx: idx, @@ -68,10 +68,10 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.STRING: - self.next() + p.next() value, err := parseStringLiteral(literal[1 : len(literal)-1]) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } return &ast.StringLiteral{ Idx: idx, @@ -79,10 +79,10 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.NUMBER: - self.next() + p.next() value, err := parseNumberLiteral(literal) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) value = 0 } return &ast.NumberLiteral{ @@ -91,79 +91,75 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.SLASH, token.QUOTIENT_ASSIGN: - return self.parseRegExpLiteral() + return p.parseRegExpLiteral() case token.LEFT_BRACE: - return self.parseObjectLiteral() + return p.parseObjectLiteral() case token.LEFT_BRACKET: - return self.parseArrayLiteral() + return p.parseArrayLiteral() case token.LEFT_PARENTHESIS: - self.expect(token.LEFT_PARENTHESIS) - expression := self.parseExpression() - if self.mode&StoreComments != 0 { - self.comments.Unset() + p.expect(token.LEFT_PARENTHESIS) + expression := p.parseExpression() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.RIGHT_PARENTHESIS) return expression case token.THIS: - self.next() + p.next() return &ast.ThisExpression{ Idx: idx, } case token.FUNCTION: - return self.parseFunction(false) + return p.parseFunction(false) } - self.errorUnexpectedToken(self.token) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.errorUnexpectedToken(p.token) + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } -func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { - - offset := self.chrOffset - 1 // Opening slash already gotten - if self.token == token.QUOTIENT_ASSIGN { - offset -= 1 // = +func (p *parser) parseRegExpLiteral() *ast.RegExpLiteral { + offset := p.chrOffset - 1 // Opening slash already gotten + if p.token == token.QUOTIENT_ASSIGN { + offset-- // = } - idx := self.idxOf(offset) + idx := p.idxOf(offset) - pattern, err := self.scanString(offset) - endOffset := self.chrOffset + pattern, err := p.scanString(offset) + endOffset := p.chrOffset - self.next() + p.next() if err == nil { pattern = pattern[1 : len(pattern)-1] } flags := "" - if self.token == token.IDENTIFIER { // gim - - flags = self.literal - self.next() - endOffset = self.chrOffset - 1 + if p.token == token.IDENTIFIER { // gim + flags = p.literal + endOffset = p.chrOffset + p.next() } var value string // TODO 15.10 - { - // Test during parsing that this is a valid regular expression - // Sorry, (?=) and (?!) are invalid (for now) - pattern, err := TransformRegExp(pattern) + // Test during parsing that this is a valid regular expression + // Sorry, (?=) and (?!) are invalid (for now) + pat, err := TransformRegExp(pattern) + if err != nil { + if pat == "" || p.mode&IgnoreRegExpErrors == 0 { + p.error(idx, "Invalid regular expression: %s", err.Error()) + } + } else { + _, err = regexp.Compile(pat) if err != nil { - if pattern == "" || self.mode&IgnoreRegExpErrors == 0 { - self.error(idx, "Invalid regular expression: %s", err.Error()) - } + // We should not get here, ParseRegExp should catch any errors + p.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp error" } else { - _, err = regexp.Compile(pattern) - if err != nil { - // We should not get here, ParseRegExp should catch any errors - self.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp error" - } else { - value = pattern - } + value = pat } } - literal := self.str[offset:endOffset] + literal := p.str[offset:endOffset] return &ast.RegExpLiteral{ Idx: idx, @@ -174,75 +170,73 @@ func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { } } -func (self *_parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression { - - if self.token != token.IDENTIFIER { - idx := self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} +func (p *parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression { + if p.token != token.IDENTIFIER { + idx := p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } - literal := self.literal - idx := self.idx - self.next() + literal := p.literal + idx := p.idx + p.next() node := &ast.VariableExpression{ Name: literal, Idx: idx, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(node) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(node) } if declarationList != nil { *declarationList = append(*declarationList, node) } - if self.token == token.ASSIGN { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.ASSIGN { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - node.Initializer = self.parseAssignmentExpression() + p.next() + node.Initializer = p.parseAssignmentExpression() } return node } -func (self *_parser) parseVariableDeclarationList(var_ file.Idx) []ast.Expression { - +func (p *parser) parseVariableDeclarationList(idx file.Idx) []ast.Expression { var declarationList []*ast.VariableExpression // Avoid bad expressions var list []ast.Expression for { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) } - decl := self.parseVariableDeclaration(&declarationList) + decl := p.parseVariableDeclaration(&declarationList) list = append(list, decl) - if self.token != token.COMMA { + if p.token != token.COMMA { break } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() } - self.scope.declare(&ast.VariableDeclaration{ - Var: var_, + p.scope.declare(&ast.VariableDeclaration{ + Var: idx, List: declarationList, }) return list } -func (self *_parser) parseObjectPropertyKey() (string, string) { - idx, tkn, literal := self.idx, self.token, self.literal +func (p *parser) parseObjectPropertyKey() (string, string) { + idx, tkn, literal := p.idx, p.token, p.literal value := "" - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.KEY) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.KEY) } - self.next() + p.next() switch tkn { case token.IDENTIFIER: @@ -251,7 +245,7 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { var err error _, err = parseNumberLiteral(literal) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } else { value = literal } @@ -259,7 +253,7 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { var err error value, err = parseStringLiteral(literal[1 : len(literal)-1]) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } default: // null, false, class, etc. @@ -270,33 +264,33 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { return literal, value } -func (self *_parser) parseObjectProperty() ast.Property { - literal, value := self.parseObjectPropertyKey() - if literal == "get" && self.token != token.COLON { - idx := self.idx - _, value := self.parseObjectPropertyKey() - parameterList := self.parseFunctionParameterList() +func (p *parser) parseObjectProperty() ast.Property { + literal, value := p.parseObjectPropertyKey() + if literal == "get" && p.token != token.COLON { + idx := p.idx + _, value = p.parseObjectPropertyKey() + parameterList := p.parseFunctionParameterList() node := &ast.FunctionLiteral{ Function: idx, ParameterList: parameterList, } - self.parseFunctionBlock(node) + p.parseFunctionBlock(node) return ast.Property{ Key: value, Kind: "get", Value: node, } - } else if literal == "set" && self.token != token.COLON { - idx := self.idx - _, value := self.parseObjectPropertyKey() - parameterList := self.parseFunctionParameterList() + } else if literal == "set" && p.token != token.COLON { + idx := p.idx + _, value = p.parseObjectPropertyKey() + parameterList := p.parseFunctionParameterList() node := &ast.FunctionLiteral{ Function: idx, ParameterList: parameterList, } - self.parseFunctionBlock(node) + p.parseFunctionBlock(node) return ast.Property{ Key: value, Kind: "set", @@ -304,40 +298,40 @@ func (self *_parser) parseObjectProperty() ast.Property { } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.COLON) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.COLON) } - self.expect(token.COLON) + p.expect(token.COLON) exp := ast.Property{ Key: value, Kind: "value", - Value: self.parseAssignmentExpression(), + Value: p.parseAssignmentExpression(), } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp.Value) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp.Value) } return exp } -func (self *_parser) parseObjectLiteral() ast.Expression { +func (p *parser) parseObjectLiteral() ast.Expression { var value []ast.Property - idx0 := self.expect(token.LEFT_BRACE) - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - value = append(value, self.parseObjectProperty()) - if self.token == token.COMMA { - if self.mode&StoreComments != 0 { - self.comments.Unset() + idx0 := p.expect(token.LEFT_BRACE) + for p.token != token.RIGHT_BRACE && p.token != token.EOF { + value = append(value, p.parseObjectProperty()) + if p.token == token.COMMA { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() continue } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.FINAL) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.FINAL) } - idx1 := self.expect(token.RIGHT_BRACE) + idx1 := p.expect(token.RIGHT_BRACE) return &ast.ObjectLiteral{ LeftBrace: idx0, @@ -346,37 +340,37 @@ func (self *_parser) parseObjectLiteral() ast.Expression { } } -func (self *_parser) parseArrayLiteral() ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) +func (p *parser) parseArrayLiteral() ast.Expression { + idx0 := p.expect(token.LEFT_BRACKET) var value []ast.Expression - for self.token != token.RIGHT_BRACKET && self.token != token.EOF { - if self.token == token.COMMA { + for p.token != token.RIGHT_BRACKET && p.token != token.EOF { + if p.token == token.COMMA { // This kind of comment requires a special empty expression node. - empty := &ast.EmptyExpression{self.idx, self.idx} + empty := &ast.EmptyExpression{Begin: p.idx, End: p.idx} - if self.mode&StoreComments != 0 { - self.comments.SetExpression(empty) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.SetExpression(empty) + p.comments.Unset() } value = append(value, empty) - self.next() + p.next() continue } - exp := self.parseAssignmentExpression() + exp := p.parseAssignmentExpression() value = append(value, exp) - if self.token != token.RIGHT_BRACKET { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token != token.RIGHT_BRACKET { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COMMA) + p.expect(token.COMMA) } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.FINAL) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.FINAL) } - idx1 := self.expect(token.RIGHT_BRACKET) + idx1 := p.expect(token.RIGHT_BRACKET) return &ast.ArrayLiteral{ LeftBracket: idx0, @@ -385,36 +379,34 @@ func (self *_parser) parseArrayLiteral() ast.Expression { } } -func (self *_parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { - if self.mode&StoreComments != 0 { - self.comments.Unset() +func (p *parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { //nolint:nonamedreturns + if p.mode&StoreComments != 0 { + p.comments.Unset() } - idx0 = self.expect(token.LEFT_PARENTHESIS) - if self.token != token.RIGHT_PARENTHESIS { - for { - exp := self.parseAssignmentExpression() - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) - } - argumentList = append(argumentList, exp) - if self.token != token.COMMA { - break - } - if self.mode&StoreComments != 0 { - self.comments.Unset() - } - self.next() + idx0 = p.expect(token.LEFT_PARENTHESIS) + for p.token != token.RIGHT_PARENTHESIS { + exp := p.parseAssignmentExpression() + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) + } + argumentList = append(argumentList, exp) + if p.token != token.COMMA { + break + } + if p.mode&StoreComments != 0 { + p.comments.Unset() } + p.next() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - idx1 = self.expect(token.RIGHT_PARENTHESIS) + idx1 = p.expect(token.RIGHT_PARENTHESIS) return } -func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { - argumentList, idx0, idx1 := self.parseArgumentList() +func (p *parser) parseCallExpression(left ast.Expression) ast.Expression { + argumentList, idx0, idx1 := p.parseArgumentList() exp := &ast.CallExpression{ Callee: left, LeftParenthesis: idx0, @@ -422,25 +414,25 @@ func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { RightParenthesis: idx1, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp } -func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { - period := self.expect(token.PERIOD) +func (p *parser) parseDotMember(left ast.Expression) ast.Expression { + period := p.expect(token.PERIOD) - literal := self.literal - idx := self.idx + literal := p.literal + idx := p.idx if !matchIdentifier.MatchString(literal) { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: period, To: self.idx} + p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadExpression{From: period, To: p.idx} } - self.next() + p.next() return &ast.DotExpression{ Left: left, @@ -451,10 +443,10 @@ func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { } } -func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) - member := self.parseExpression() - idx1 := self.expect(token.RIGHT_BRACKET) +func (p *parser) parseBracketMember(left ast.Expression) ast.Expression { + idx0 := p.expect(token.LEFT_BRACKET) + member := p.parseExpression() + idx1 := p.expect(token.RIGHT_BRACKET) return &ast.BracketExpression{ LeftBracket: idx0, Left: left, @@ -463,125 +455,121 @@ func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { } } -func (self *_parser) parseNewExpression() ast.Expression { - idx := self.expect(token.NEW) - callee := self.parseLeftHandSideExpression() +func (p *parser) parseNewExpression() ast.Expression { + idx := p.expect(token.NEW) + callee := p.parseLeftHandSideExpression() node := &ast.NewExpression{ New: idx, Callee: callee, } - if self.token == token.LEFT_PARENTHESIS { - argumentList, idx0, idx1 := self.parseArgumentList() + if p.token == token.LEFT_PARENTHESIS { + argumentList, idx0, idx1 := p.parseArgumentList() node.ArgumentList = argumentList node.LeftParenthesis = idx0 node.RightParenthesis = idx1 } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(node) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(node) } return node } -func (self *_parser) parseLeftHandSideExpression() ast.Expression { - +func (p *parser) parseLeftHandSideExpression() ast.Expression { var left ast.Expression - if self.token == token.NEW { - left = self.parseNewExpression() + if p.token == token.NEW { + left = p.parseNewExpression() } else { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parsePrimaryExpression() + left = p.parsePrimaryExpression() } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(left) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(left) } for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACKET { - left = self.parseBracketMember(left) - } else { - break + switch p.token { + case token.PERIOD: + left = p.parseDotMember(left) + case token.LEFT_BRACKET: + left = p.parseBracketMember(left) + default: + return left } } - - return left } -func (self *_parser) parseLeftHandSideExpressionAllowCall() ast.Expression { - - allowIn := self.scope.allowIn - self.scope.allowIn = true +func (p *parser) parseLeftHandSideExpressionAllowCall() ast.Expression { + allowIn := p.scope.allowIn + p.scope.allowIn = true defer func() { - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn }() var left ast.Expression - if self.token == token.NEW { + if p.token == token.NEW { var newComments []*ast.Comment - if self.mode&StoreComments != 0 { - newComments = self.comments.FetchAll() - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + newComments = p.comments.FetchAll() + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parseNewExpression() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(left, newComments, ast.LEADING) + left = p.parseNewExpression() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(left, newComments, ast.LEADING) } } else { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parsePrimaryExpression() + left = p.parsePrimaryExpression() } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(left) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(left) } for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACKET { - left = self.parseBracketMember(left) - } else if self.token == token.LEFT_PARENTHESIS { - left = self.parseCallExpression(left) - } else { - break + switch p.token { + case token.PERIOD: + left = p.parseDotMember(left) + case token.LEFT_BRACKET: + left = p.parseBracketMember(left) + case token.LEFT_PARENTHESIS: + left = p.parseCallExpression(left) + default: + return left } } - - return left } -func (self *_parser) parsePostfixExpression() ast.Expression { - operand := self.parseLeftHandSideExpressionAllowCall() +func (p *parser) parsePostfixExpression() ast.Expression { + operand := p.parseLeftHandSideExpressionAllowCall() - switch self.token { + switch p.token { case token.INCREMENT, token.DECREMENT: // Make sure there is no line terminator here - if self.implicitSemicolon { + if p.implicitSemicolon { break } - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() switch operand.(type) { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: default: - self.error(idx, "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.error(idx, "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } exp := &ast.UnaryExpression{ Operator: tkn, @@ -590,8 +578,8 @@ func (self *_parser) parsePostfixExpression() ast.Expression { Postfix: true, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp @@ -600,38 +588,37 @@ func (self *_parser) parsePostfixExpression() ast.Expression { return operand } -func (self *_parser) parseUnaryExpression() ast.Expression { - - switch self.token { +func (p *parser) parseUnaryExpression() ast.Expression { + switch p.token { case token.PLUS, token.MINUS, token.NOT, token.BITWISE_NOT: fallthrough case token.DELETE, token.VOID, token.TYPEOF: - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() return &ast.UnaryExpression{ Operator: tkn, Idx: idx, - Operand: self.parseUnaryExpression(), + Operand: p.parseUnaryExpression(), } case token.INCREMENT, token.DECREMENT: - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - operand := self.parseUnaryExpression() + p.next() + operand := p.parseUnaryExpression() switch operand.(type) { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: default: - self.error(idx, "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.error(idx, "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } return &ast.UnaryExpression{ Operator: tkn, @@ -640,20 +627,20 @@ func (self *_parser) parseUnaryExpression() ast.Expression { } } - return self.parsePostfixExpression() + return p.parsePostfixExpression() } -func (self *_parser) parseMultiplicativeExpression() ast.Expression { - next := self.parseUnaryExpression +func (p *parser) parseMultiplicativeExpression() ast.Expression { + next := p.parseUnaryExpression left := next() - for self.token == token.MULTIPLY || self.token == token.SLASH || - self.token == token.REMAINDER { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.MULTIPLY || p.token == token.SLASH || + p.token == token.REMAINDER { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -665,16 +652,16 @@ func (self *_parser) parseMultiplicativeExpression() ast.Expression { return left } -func (self *_parser) parseAdditiveExpression() ast.Expression { - next := self.parseMultiplicativeExpression +func (p *parser) parseAdditiveExpression() ast.Expression { + next := p.parseMultiplicativeExpression left := next() - for self.token == token.PLUS || self.token == token.MINUS { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.PLUS || p.token == token.MINUS { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -686,17 +673,17 @@ func (self *_parser) parseAdditiveExpression() ast.Expression { return left } -func (self *_parser) parseShiftExpression() ast.Expression { - next := self.parseAdditiveExpression +func (p *parser) parseShiftExpression() ast.Expression { + next := p.parseAdditiveExpression left := next() - for self.token == token.SHIFT_LEFT || self.token == token.SHIFT_RIGHT || - self.token == token.UNSIGNED_SHIFT_RIGHT { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.SHIFT_LEFT || p.token == token.SHIFT_RIGHT || + p.token == token.UNSIGNED_SHIFT_RIGHT { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -708,58 +695,58 @@ func (self *_parser) parseShiftExpression() ast.Expression { return left } -func (self *_parser) parseRelationalExpression() ast.Expression { - next := self.parseShiftExpression +func (p *parser) parseRelationalExpression() ast.Expression { + next := p.parseShiftExpression left := next() - allowIn := self.scope.allowIn - self.scope.allowIn = true + allowIn := p.scope.allowIn + p.scope.allowIn = true defer func() { - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn }() - switch self.token { + switch p.token { case token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL: - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), Comparison: true, } return exp case token.INSTANCEOF: - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), } return exp case token.IN: if !allowIn { return left } - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), } return exp } @@ -767,17 +754,17 @@ func (self *_parser) parseRelationalExpression() ast.Expression { return left } -func (self *_parser) parseEqualityExpression() ast.Expression { - next := self.parseRelationalExpression +func (p *parser) parseEqualityExpression() ast.Expression { + next := p.parseRelationalExpression left := next() - for self.token == token.EQUAL || self.token == token.NOT_EQUAL || - self.token == token.STRICT_EQUAL || self.token == token.STRICT_NOT_EQUAL { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.EQUAL || p.token == token.NOT_EQUAL || + p.token == token.STRICT_EQUAL || p.token == token.STRICT_NOT_EQUAL { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -790,16 +777,16 @@ func (self *_parser) parseEqualityExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseAndExpression() ast.Expression { - next := self.parseEqualityExpression +func (p *parser) parseBitwiseAndExpression() ast.Expression { + next := p.parseEqualityExpression left := next() - for self.token == token.AND { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.AND { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -811,16 +798,16 @@ func (self *_parser) parseBitwiseAndExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { - next := self.parseBitwiseAndExpression +func (p *parser) parseBitwiseExclusiveOrExpression() ast.Expression { + next := p.parseBitwiseAndExpression left := next() - for self.token == token.EXCLUSIVE_OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.EXCLUSIVE_OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -832,16 +819,16 @@ func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseOrExpression() ast.Expression { - next := self.parseBitwiseExclusiveOrExpression +func (p *parser) parseBitwiseOrExpression() ast.Expression { + next := p.parseBitwiseExclusiveOrExpression left := next() - for self.token == token.OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -853,16 +840,16 @@ func (self *_parser) parseBitwiseOrExpression() ast.Expression { return left } -func (self *_parser) parseLogicalAndExpression() ast.Expression { - next := self.parseBitwiseOrExpression +func (p *parser) parseLogicalAndExpression() ast.Expression { + next := p.parseBitwiseOrExpression left := next() - for self.token == token.LOGICAL_AND { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.LOGICAL_AND { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -874,16 +861,16 @@ func (self *_parser) parseLogicalAndExpression() ast.Expression { return left } -func (self *_parser) parseLogicalOrExpression() ast.Expression { - next := self.parseLogicalAndExpression +func (p *parser) parseLogicalOrExpression() ast.Expression { + next := p.parseLogicalAndExpression left := next() - for self.token == token.LOGICAL_OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.LOGICAL_OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -895,24 +882,24 @@ func (self *_parser) parseLogicalOrExpression() ast.Expression { return left } -func (self *_parser) parseConditionlExpression() ast.Expression { - left := self.parseLogicalOrExpression() +func (p *parser) parseConditionalExpression() ast.Expression { + left := p.parseLogicalOrExpression() - if self.token == token.QUESTION_MARK { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.QUESTION_MARK { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() - consequent := self.parseAssignmentExpression() - if self.mode&StoreComments != 0 { - self.comments.Unset() + consequent := p.parseAssignmentExpression() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COLON) + p.expect(token.COLON) exp := &ast.ConditionalExpression{ Test: left, Consequent: consequent, - Alternate: self.parseAssignmentExpression(), + Alternate: p.parseAssignmentExpression(), } return exp @@ -921,12 +908,12 @@ func (self *_parser) parseConditionlExpression() ast.Expression { return left } -func (self *_parser) parseAssignmentExpression() ast.Expression { - left := self.parseConditionlExpression() +func (p *parser) parseAssignmentExpression() ast.Expression { + left := p.parseConditionalExpression() var operator token.Token - switch self.token { + switch p.token { case token.ASSIGN: - operator = self.token + operator = p.token case token.ADD_ASSIGN: operator = token.PLUS case token.SUBTRACT_ASSIGN: @@ -954,27 +941,27 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { } if operator != 0 { - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() switch left.(type) { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: default: - self.error(left.Idx0(), "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.error(left.Idx0(), "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } exp := &ast.AssignExpression{ Left: left, Operator: operator, - Right: self.parseAssignmentExpression(), + Right: p.parseAssignmentExpression(), } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp @@ -983,17 +970,17 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { return left } -func (self *_parser) parseExpression() ast.Expression { - next := self.parseAssignmentExpression +func (p *parser) parseExpression() ast.Expression { + next := p.parseAssignmentExpression left := next() - if self.token == token.COMMA { + if p.token == token.COMMA { sequence := []ast.Expression{left} for { - if self.token != token.COMMA { + if p.token != token.COMMA { break } - self.next() + p.next() sequence = append(sequence, next()) } return &ast.SequenceExpression{ diff --git a/vendor/github.com/robertkrimen/otto/parser/lexer.go b/vendor/github.com/robertkrimen/otto/parser/lexer.go index d9d69e124..dab21d966 100644 --- a/vendor/github.com/robertkrimen/otto/parser/lexer.go +++ b/vendor/github.com/robertkrimen/otto/parser/lexer.go @@ -15,7 +15,7 @@ import ( "github.com/robertkrimen/otto/token" ) -type _chr struct { +type chr struct { //nolint:unused value rune width int } @@ -38,6 +38,53 @@ func digitValue(chr rune) int { return 16 // Larger than any legal digit value } +// See https://www.unicode.org/reports/tr31/ for reference on ID_Start and ID_Continue. +var includeIDStart = []*unicode.RangeTable{ + unicode.Lu, + unicode.Ll, + unicode.Lt, + unicode.Lm, + unicode.Lo, + unicode.Nl, + unicode.Other_ID_Start, +} + +var includeIDContinue = []*unicode.RangeTable{ + unicode.Lu, + unicode.Ll, + unicode.Lt, + unicode.Lm, + unicode.Lo, + unicode.Nl, + unicode.Other_ID_Start, + unicode.Mn, + unicode.Mc, + unicode.Nd, + unicode.Pc, + unicode.Other_ID_Continue, +} + +var exclude = []*unicode.RangeTable{ + unicode.Pattern_Syntax, + unicode.Pattern_White_Space, +} + +func unicodeIDStart(r rune) bool { + if unicode.In(r, exclude...) { + return false + } + + return unicode.In(r, includeIDStart...) +} + +func unicodeIDContinue(r rune) bool { + if unicode.In(r, exclude...) { + return false + } + + return unicode.In(r, includeIDContinue...) +} + func isDigit(chr rune, base int) bool { return digitValue(chr) < base } @@ -45,59 +92,60 @@ func isDigit(chr rune, base int) bool { func isIdentifierStart(chr rune) bool { return chr == '$' || chr == '_' || chr == '\\' || 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' || - chr >= utf8.RuneSelf && unicode.IsLetter(chr) + chr >= utf8.RuneSelf && unicodeIDStart(chr) } func isIdentifierPart(chr rune) bool { return chr == '$' || chr == '_' || chr == '\\' || 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' || '0' <= chr && chr <= '9' || - chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr)) + chr >= utf8.RuneSelf && unicodeIDContinue(chr) } -func (self *_parser) scanIdentifier() (string, error) { - offset := self.chrOffset +func (p *parser) scanIdentifier() (string, error) { + offset := p.chrOffset parse := false - for isIdentifierPart(self.chr) { - if self.chr == '\\' { - distance := self.chrOffset - offset - self.read() - if self.chr != 'u' { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) + for isIdentifierPart(p.chr) { + if p.chr == '\\' { + distance := p.chrOffset - offset + p.read() + if p.chr != 'u' { + return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr)) } parse = true var value rune - for j := 0; j < 4; j++ { - self.read() - decimal, ok := hex2decimal(byte(self.chr)) + for range 4 { + p.read() + decimal, ok := hex2decimal(byte(p.chr)) if !ok { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) + return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr)) } value = value<<4 | decimal } - if value == '\\' { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) - } else if distance == 0 { + switch { + case value == '\\': + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) + case distance == 0: if !isIdentifierStart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) } - } else if distance > 0 { + case distance > 0: if !isIdentifierPart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) } } } - self.read() + p.read() } - literal := string(self.str[offset:self.chrOffset]) + literal := p.str[offset:p.chrOffset] if parse { return parseStringLiteral(literal) } return literal, nil } -// 7.2 -func isLineWhiteSpace(chr rune) bool { +// 7.2. +func isLineWhiteSpace(chr rune) bool { //nolint:unused, deadcode switch chr { case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff': return true @@ -109,7 +157,7 @@ func isLineWhiteSpace(chr rune) bool { return unicode.IsSpace(chr) } -// 7.3 +// 7.3. func isLineTerminator(chr rune) bool { switch chr { case '\u000a', '\u000d', '\u2028', '\u2029': @@ -118,20 +166,19 @@ func isLineTerminator(chr rune) bool { return false } -func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { - - self.implicitSemicolon = false +func (p *parser) scan() (tkn token.Token, literal string, idx file.Idx) { //nolint:nonamedreturns + p.implicitSemicolon = false for { - self.skipWhiteSpace() + p.skipWhiteSpace() - idx = self.idxOf(self.chrOffset) + idx = p.idxOf(p.chrOffset) insertSemicolon := false - switch chr := self.chr; { + switch chr := p.chr; { case isIdentifierStart(chr): var err error - literal, err = self.scanIdentifier() + literal, err = p.scanIdentifier() if err != nil { tkn = token.ILLEGAL break @@ -142,25 +189,21 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { tkn, strict = token.IsKeyword(literal) switch tkn { - case 0: // Not a keyword - if literal == "true" || literal == "false" { - self.insertSemicolon = true - tkn = token.BOOLEAN - return - } else if literal == "null" { - self.insertSemicolon = true - tkn = token.NULL - return + switch literal { + case "true", "false": + p.insertSemicolon = true + return token.BOOLEAN, literal, idx + case "null": + p.insertSemicolon = true + return token.NULL, literal, idx } - case token.KEYWORD: - tkn = token.KEYWORD if strict { // TODO If strict and in strict mode, then this is not a break break } - return + return token.KEYWORD, literal, idx case token.THIS, @@ -169,41 +212,39 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { token.RETURN, token.CONTINUE, token.DEBUGGER: - self.insertSemicolon = true - return + p.insertSemicolon = true + return tkn, literal, idx default: - return - + return tkn, literal, idx } } - self.insertSemicolon = true - tkn = token.IDENTIFIER - return + p.insertSemicolon = true + return token.IDENTIFIER, literal, idx case '0' <= chr && chr <= '9': - self.insertSemicolon = true - tkn, literal = self.scanNumericLiteral(false) - return + p.insertSemicolon = true + tkn, literal = p.scanNumericLiteral(false) + return tkn, literal, idx default: - self.read() + p.read() switch chr { case -1: - if self.insertSemicolon { - self.insertSemicolon = false - self.implicitSemicolon = true + if p.insertSemicolon { + p.insertSemicolon = false + p.implicitSemicolon = true } tkn = token.EOF case '\r', '\n', '\u2028', '\u2029': - self.insertSemicolon = false - self.implicitSemicolon = true - self.comments.AtLineBreak() + p.insertSemicolon = false + p.implicitSemicolon = true + p.comments.AtLineBreak() continue case ':': tkn = token.COLON case '.': - if digitValue(self.chr) < 10 { + if digitValue(p.chr) < 10 { insertSemicolon = true - tkn, literal = self.scanNumericLiteral(true) + tkn, literal = p.scanNumericLiteral(true) } else { tkn = token.PERIOD } @@ -227,68 +268,69 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { tkn = token.RIGHT_BRACE insertSemicolon = true case '+': - tkn = self.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT) + tkn = p.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT) if tkn == token.INCREMENT { insertSemicolon = true } case '-': - tkn = self.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT) + tkn = p.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT) if tkn == token.DECREMENT { insertSemicolon = true } case '*': - tkn = self.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) + tkn = p.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) case '/': - if self.chr == '/' { - if self.mode&StoreComments != 0 { - literal := string(self.readSingleLineComment()) - self.comments.AddComment(ast.NewComment(literal, self.idx)) + switch p.chr { + case '/': + if p.mode&StoreComments != 0 { + comment := string(p.readSingleLineComment()) + p.comments.AddComment(ast.NewComment(comment, idx)) continue } - self.skipSingleLineComment() + p.skipSingleLineComment() continue - } else if self.chr == '*' { - if self.mode&StoreComments != 0 { - literal = string(self.readMultiLineComment()) - self.comments.AddComment(ast.NewComment(literal, self.idx)) + case '*': + if p.mode&StoreComments != 0 { + comment := string(p.readMultiLineComment()) + p.comments.AddComment(ast.NewComment(comment, idx)) continue } - self.skipMultiLineComment() + p.skipMultiLineComment() continue - } else { + default: // Could be division, could be RegExp literal - tkn = self.switch2(token.SLASH, token.QUOTIENT_ASSIGN) + tkn = p.switch2(token.SLASH, token.QUOTIENT_ASSIGN) insertSemicolon = true } case '%': - tkn = self.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) + tkn = p.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) case '^': - tkn = self.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN) + tkn = p.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN) case '<': - tkn = self.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN) + tkn = p.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN) case '>': - tkn = self.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN) + tkn = p.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN) case '=': - tkn = self.switch2(token.ASSIGN, token.EQUAL) - if tkn == token.EQUAL && self.chr == '=' { - self.read() + tkn = p.switch2(token.ASSIGN, token.EQUAL) + if tkn == token.EQUAL && p.chr == '=' { + p.read() tkn = token.STRICT_EQUAL } case '!': - tkn = self.switch2(token.NOT, token.NOT_EQUAL) - if tkn == token.NOT_EQUAL && self.chr == '=' { - self.read() + tkn = p.switch2(token.NOT, token.NOT_EQUAL) + if tkn == token.NOT_EQUAL && p.chr == '=' { + p.read() tkn = token.STRICT_NOT_EQUAL } case '&': - if self.chr == '^' { - self.read() - tkn = self.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) + if p.chr == '^' { + p.read() + tkn = p.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) } else { - tkn = self.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) + tkn = p.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) } case '|': - tkn = self.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) + tkn = p.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) case '~': tkn = token.BITWISE_NOT case '?': @@ -297,49 +339,49 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { insertSemicolon = true tkn = token.STRING var err error - literal, err = self.scanString(self.chrOffset - 1) + literal, err = p.scanString(p.chrOffset - 1) if err != nil { tkn = token.ILLEGAL } default: - self.errorUnexpected(idx, chr) + p.errorUnexpected(idx, chr) tkn = token.ILLEGAL } } - self.insertSemicolon = insertSemicolon - return + p.insertSemicolon = insertSemicolon + return tkn, literal, idx } } -func (self *_parser) switch2(tkn0, tkn1 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch2(tkn0, tkn1 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } return tkn0 } -func (self *_parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() + if p.chr == chr2 { + p.read() return tkn2 } return tkn0 } -func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr2 { + p.read() + if p.chr == '=' { + p.read() return tkn3 } return tkn2 @@ -347,21 +389,21 @@ func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token return tkn0 } -func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr2 { + p.read() + if p.chr == '=' { + p.read() return tkn3 } - if self.chr == chr3 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr3 { + p.read() + if p.chr == '=' { + p.read() return tkn5 } return tkn4 @@ -371,137 +413,137 @@ func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token return tkn0 } -func (self *_parser) chrAt(index int) _chr { - value, width := utf8.DecodeRuneInString(self.str[index:]) - return _chr{ +func (p *parser) chrAt(index int) chr { //nolint:unused + value, width := utf8.DecodeRuneInString(p.str[index:]) + return chr{ value: value, width: width, } } -func (self *_parser) _peek() rune { - if self.offset+1 < self.length { - return rune(self.str[self.offset+1]) +func (p *parser) peek() rune { + if p.offset+1 < p.length { + return rune(p.str[p.offset+1]) } return -1 } -func (self *_parser) read() { - if self.offset < self.length { - self.chrOffset = self.offset - chr, width := rune(self.str[self.offset]), 1 +func (p *parser) read() { + if p.offset < p.length { + p.chrOffset = p.offset + chr, width := rune(p.str[p.offset]), 1 if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) + chr, width = utf8.DecodeRuneInString(p.str[p.offset:]) if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") + p.error(p.chrOffset, "Invalid UTF-8 character") } } - self.offset += width - self.chr = chr + p.offset += width + p.chr = chr } else { - self.chrOffset = self.length - self.chr = -1 // EOF + p.chrOffset = p.length + p.chr = -1 // EOF } } -// This is here since the functions are so similar -func (self *_RegExp_parser) read() { - if self.offset < self.length { - self.chrOffset = self.offset - chr, width := rune(self.str[self.offset]), 1 +// This is here since the functions are so similar. +func (p *regExpParser) read() { + if p.offset < p.length { + p.chrOffset = p.offset + chr, width := rune(p.str[p.offset]), 1 if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) + chr, width = utf8.DecodeRuneInString(p.str[p.offset:]) if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") + p.error(p.chrOffset, "Invalid UTF-8 character") } } - self.offset += width - self.chr = chr + p.offset += width + p.chr = chr } else { - self.chrOffset = self.length - self.chr = -1 // EOF + p.chrOffset = p.length + p.chr = -1 // EOF } } -func (self *_parser) readSingleLineComment() (result []rune) { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { - return +func (p *parser) readSingleLineComment() []rune { + var result []rune + for p.chr != -1 { + p.read() + if isLineTerminator(p.chr) { + return result } - result = append(result, self.chr) + result = append(result, p.chr) } // Get rid of the trailing -1 - result = result[:len(result)-1] - - return -} - -func (self *_parser) readMultiLineComment() (result []rune) { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() - return + return result[:len(result)-1] +} + +func (p *parser) readMultiLineComment() []rune { + var result []rune + p.read() + for p.chr >= 0 { + chr := p.chr + p.read() + if chr == '*' && p.chr == '/' { + p.read() + return result } result = append(result, chr) } - self.errorUnexpected(0, self.chr) + p.errorUnexpected(0, p.chr) - return + return result } -func (self *_parser) skipSingleLineComment() { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { +func (p *parser) skipSingleLineComment() { + for p.chr != -1 { + p.read() + if isLineTerminator(p.chr) { return } } } -func (self *_parser) skipMultiLineComment() { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() +func (p *parser) skipMultiLineComment() { + p.read() + for p.chr >= 0 { + chr := p.chr + p.read() + if chr == '*' && p.chr == '/' { + p.read() return } } - self.errorUnexpected(0, self.chr) + p.errorUnexpected(0, p.chr) } -func (self *_parser) skipWhiteSpace() { +func (p *parser) skipWhiteSpace() { for { - switch self.chr { + switch p.chr { case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff': - self.read() + p.read() continue case '\r': - if self._peek() == '\n' { - self.comments.AtLineBreak() - self.read() + if p.peek() == '\n' { + p.comments.AtLineBreak() + p.read() } fallthrough case '\u2028', '\u2029', '\n': - if self.insertSemicolon { + if p.insertSemicolon { return } - self.comments.AtLineBreak() - self.read() + p.comments.AtLineBreak() + p.read() continue } - if self.chr >= utf8.RuneSelf { - if unicode.IsSpace(self.chr) { - self.read() + if p.chr >= utf8.RuneSelf { + if unicode.IsSpace(p.chr) { + p.read() continue } } @@ -509,141 +551,135 @@ func (self *_parser) skipWhiteSpace() { } } -func (self *_parser) skipLineWhiteSpace() { - for isLineWhiteSpace(self.chr) { - self.read() - } -} - -func (self *_parser) scanMantissa(base int) { - for digitValue(self.chr) < base { - self.read() +func (p *parser) scanMantissa(base int) { + for digitValue(p.chr) < base { + p.read() } } -func (self *_parser) scanEscape(quote rune) { - +func (p *parser) scanEscape(quote rune) { var length, base uint32 - switch self.chr { - //case '0', '1', '2', '3', '4', '5', '6', '7': + switch p.chr { // Octal: // length, base, limit = 3, 8, 255 case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0': - self.read() + p.read() return case '\r', '\n', '\u2028', '\u2029': - self.scanNewline() + p.scanNewline() return case 'x': - self.read() + p.read() length, base = 2, 16 case 'u': - self.read() + p.read() length, base = 4, 16 default: - self.read() // Always make progress + p.read() // Always make progress return } var value uint32 - for ; length > 0 && self.chr != quote && self.chr >= 0; length-- { - digit := uint32(digitValue(self.chr)) + for ; length > 0 && p.chr != quote && p.chr >= 0; length-- { + digit := uint32(digitValue(p.chr)) if digit >= base { break } value = value*base + digit - self.read() + p.read() } } -func (self *_parser) scanString(offset int) (string, error) { +func (p *parser) scanString(offset int) (string, error) { // " ' / - quote := rune(self.str[offset]) + quote := rune(p.str[offset]) - for self.chr != quote { - chr := self.chr + for p.chr != quote { + chr := p.chr if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 { goto newline } - self.read() - if chr == '\\' { + p.read() + switch { + case chr == '\\': if quote == '/' { - if self.chr == '\n' || self.chr == '\r' || self.chr == '\u2028' || self.chr == '\u2029' || self.chr < 0 { + if p.chr == '\n' || p.chr == '\r' || p.chr == '\u2028' || p.chr == '\u2029' || p.chr < 0 { goto newline } - self.read() + p.read() } else { - self.scanEscape(quote) + p.scanEscape(quote) } - } else if chr == '[' && quote == '/' { + case chr == '[' && quote == '/': // Allow a slash (/) in a bracket character class ([...]) // TODO Fix this, this is hacky... quote = -1 - } else if chr == ']' && quote == -1 { + case chr == ']' && quote == -1: quote = '/' } } // " ' / - self.read() + p.read() - return string(self.str[offset:self.chrOffset]), nil + return p.str[offset:p.chrOffset], nil newline: - self.scanNewline() + p.scanNewline() err := "String not terminated" if quote == '/' { err = "Invalid regular expression: missing /" - self.error(self.idxOf(offset), err) + p.error(p.idxOf(offset), err) } return "", errors.New(err) } -func (self *_parser) scanNewline() { - if self.chr == '\r' { - self.read() - if self.chr != '\n' { +func (p *parser) scanNewline() { + if p.chr == '\r' { + p.read() + if p.chr != '\n' { return } } - self.read() + p.read() } -func hex2decimal(chr byte) (value rune, ok bool) { - { - chr := rune(chr) - switch { - case '0' <= chr && chr <= '9': - return chr - '0', true - case 'a' <= chr && chr <= 'f': - return chr - 'a' + 10, true - case 'A' <= chr && chr <= 'F': - return chr - 'A' + 10, true - } - return +func hex2decimal(chr byte) (rune, bool) { + r := rune(chr) + switch { + case '0' <= r && r <= '9': + return r - '0', true + case 'a' <= r && r <= 'f': + return r - 'a' + 10, true + case 'A' <= r && r <= 'F': + return r - 'A' + 10, true + default: + return 0, false } } -func parseNumberLiteral(literal string) (value interface{}, err error) { +func parseNumberLiteral(literal string) (value interface{}, err error) { //nolint:nonamedreturns // TODO Is Uint okay? What about -MAX_UINT value, err = strconv.ParseInt(literal, 0, 64) if err == nil { - return + return value, nil } parseIntErr := err // Save this first error, just in case value, err = strconv.ParseFloat(literal, 64) if err == nil { - return - } else if err.(*strconv.NumError).Err == strconv.ErrRange { + return value, nil + } else if errors.Is(err, strconv.ErrRange) { // Infinity, etc. return value, nil } + // TODO(steve): Fix as this is assigning to err so we know the type. + // Need to understand what this was trying to do? err = parseIntErr - if err.(*strconv.NumError).Err == strconv.ErrRange { + if errors.Is(err, strconv.ErrRange) { if len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') { // Could just be a very large number (e.g. 0x8000000000000000) var value float64 @@ -651,7 +687,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { for _, chr := range literal { digit := digitValue(chr) if digit >= 16 { - goto error + return nil, fmt.Errorf("illegal numeric literal: %v (>= 16)", digit) } value = value*16 + float64(digit) } @@ -659,8 +695,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { } } -error: - return nil, errors.New("Illegal numeric literal") + return nil, errors.New("illegal numeric literal") } func parseStringLiteral(literal string) (string, error) { @@ -729,7 +764,7 @@ func parseStringLiteral(literal string) (string, error) { if len(str) < size { return "", fmt.Errorf("invalid escape: \\%s: len(%q) != %d", string(chr), str, size) } - for j := 0; j < size; j++ { + for j := range size { decimal, ok := hex2decimal(str[j]) if !ok { return "", fmt.Errorf("invalid escape: \\%s: %q", string(chr), str[:size]) @@ -757,8 +792,8 @@ func parseStringLiteral(literal string) (string, error) { if len(str) < j+1 { break } - chr := str[j] - if '0' > chr || chr > '7' { + + if ch := str[j]; '0' > ch || ch > '7' { break } decimal := rune(str[j]) - '0' @@ -788,79 +823,79 @@ func parseStringLiteral(literal string) (string, error) { return buffer.String(), nil } -func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { - - offset := self.chrOffset +func (p *parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { + offset := p.chrOffset tkn := token.NUMBER if decimalPoint { offset-- - self.scanMantissa(10) + p.scanMantissa(10) goto exponent } - if self.chr == '0' { - offset := self.chrOffset - self.read() - if self.chr == 'x' || self.chr == 'X' { + if p.chr == '0' { + chrOffset := p.chrOffset + p.read() + switch p.chr { + case 'x', 'X': // Hexadecimal - self.read() - if isDigit(self.chr, 16) { - self.read() + p.read() + if isDigit(p.chr, 16) { + p.read() } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] + return token.ILLEGAL, p.str[chrOffset:p.chrOffset] } - self.scanMantissa(16) + p.scanMantissa(16) - if self.chrOffset-offset <= 2 { + if p.chrOffset-chrOffset <= 2 { // Only "0x" or "0X" - self.error(0, "Illegal hexadecimal number") + p.error(0, "Illegal hexadecimal number") } goto hexadecimal - } else if self.chr == '.' { + case '.': // Float goto float - } else { + default: // Octal, Float - if self.chr == 'e' || self.chr == 'E' { + if p.chr == 'e' || p.chr == 'E' { goto exponent } - self.scanMantissa(8) - if self.chr == '8' || self.chr == '9' { - return token.ILLEGAL, self.str[offset:self.chrOffset] + p.scanMantissa(8) + if p.chr == '8' || p.chr == '9' { + return token.ILLEGAL, p.str[chrOffset:p.chrOffset] } goto octal } } - self.scanMantissa(10) + p.scanMantissa(10) float: - if self.chr == '.' { - self.read() - self.scanMantissa(10) + if p.chr == '.' { + p.read() + p.scanMantissa(10) } exponent: - if self.chr == 'e' || self.chr == 'E' { - self.read() - if self.chr == '-' || self.chr == '+' { - self.read() + if p.chr == 'e' || p.chr == 'E' { + p.read() + if p.chr == '-' || p.chr == '+' { + p.read() } - if isDecimalDigit(self.chr) { - self.read() - self.scanMantissa(10) + if isDecimalDigit(p.chr) { + p.read() + p.scanMantissa(10) } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] + return token.ILLEGAL, p.str[offset:p.chrOffset] } } hexadecimal: octal: - if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) { - return token.ILLEGAL, self.str[offset:self.chrOffset] + if isIdentifierStart(p.chr) || isDecimalDigit(p.chr) { + return token.ILLEGAL, p.str[offset:p.chrOffset] } - return tkn, self.str[offset:self.chrOffset] + return tkn, p.str[offset:p.chrOffset] } diff --git a/vendor/github.com/robertkrimen/otto/parser/parser.go b/vendor/github.com/robertkrimen/otto/parser/parser.go index 75b7c500c..f0b710d3f 100644 --- a/vendor/github.com/robertkrimen/otto/parser/parser.go +++ b/vendor/github.com/robertkrimen/otto/parser/parser.go @@ -1,44 +1,43 @@ /* Package parser implements a parser for JavaScript. - import ( - "github.com/robertkrimen/otto/parser" - ) + import ( + "github.com/robertkrimen/otto/parser" + ) Parse and return an AST - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } + filename := "" // A filename is optional + src := ` + // Sample xyzzy example + (function(){ + if (3.14159 > 0) { + console.log("Hello, World."); + return; + } - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` + var xyzzy = NaN; + console.log("Nothing happens."); + return xyzzy; + })(); + ` - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) + // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList + program, err := parser.ParseFile(nil, filename, src, 0) -Warning +# Warning The parser and AST interfaces are still works-in-progress (particularly where node types are concerned) and may change in the future. - */ package parser import ( "bytes" "encoding/base64" - "errors" + "fmt" "io" - "io/ioutil" + "os" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" @@ -50,48 +49,43 @@ import ( type Mode uint const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) - StoreComments // Store the comments from source to the comments map -) - -type _parser struct { - str string - length int - base int - - chr rune // The current character - chrOffset int // The offset of current character - offset int // The offset after current character (may be greater than 1) - - idx file.Idx // The index of token - token token.Token // The token - literal string // The literal of the token, if any + // IgnoreRegExpErrors ignores RegExp compatibility errors (allow backtracking). + IgnoreRegExpErrors Mode = 1 << iota - scope *_scope - insertSemicolon bool // If we see a newline, then insert an implicit semicolon - implicitSemicolon bool // An implicit semicolon exists - - errors ErrorList + // StoreComments stores the comments from source to the comments map. + StoreComments +) - recover struct { - // Scratch when trying to seek to the next statement, etc. +type parser struct { + comments *ast.Comments + file *file.File + scope *scope + literal string + str string + errors ErrorList + recover struct { idx file.Idx count int } - - mode Mode - - file *file.File - - comments *ast.Comments + idx file.Idx + token token.Token + offset int + chrOffset int + mode Mode + base int + length int + chr rune + insertSemicolon bool + implicitSemicolon bool // Scratch when trying to seek to the next statement, etc. } +// Parser is implemented by types which can parse JavaScript Code. type Parser interface { Scan() (tkn token.Token, literal string, idx file.Idx) } -func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser { - return &_parser{ +func newParser(filename, src string, base int, sm *sourcemap.Consumer) *parser { + return &parser{ chr: ' ', // This is set so we can start scanning by skipping whitespace str: src, length: len(src), @@ -101,11 +95,12 @@ func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser } } -// Returns a new Parser. +// NewParser returns a new Parser. func NewParser(filename, src string) Parser { - return _newParser(filename, src, 1, nil) + return newParser(filename, src, 1, nil) } +// ReadSource reads code from src if not nil, otherwise reads from filename. func ReadSource(filename string, src interface{}) ([]byte, error) { if src != nil { switch src := src.(type) { @@ -123,15 +118,17 @@ func ReadSource(filename string, src interface{}) ([]byte, error) { return nil, err } return bfr.Bytes(), nil + default: + return nil, fmt.Errorf("invalid src type %T", src) } - return nil, errors.New("invalid source") } - return ioutil.ReadFile(filename) + return os.ReadFile(filename) //nolint:gosec } +// ReadSourceMap reads the source map from src if not nil, otherwise is a noop. func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) { if src == nil { - return nil, nil + return nil, nil //nolint:nilnil } switch src := src.(type) { @@ -140,9 +137,7 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error case []byte: return sourcemap.Parse(filename, src) case *bytes.Buffer: - if src != nil { - return sourcemap.Parse(filename, src.Bytes()) - } + return sourcemap.Parse(filename, src.Bytes()) case io.Reader: var bfr bytes.Buffer if _, err := io.Copy(&bfr, src); err != nil { @@ -151,11 +146,12 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error return sourcemap.Parse(filename, bfr.Bytes()) case *sourcemap.Consumer: return src, nil + default: + return nil, fmt.Errorf("invalid sourcemap type %T", src) } - - return nil, errors.New("invalid sourcemap type") } +// ParseFileWithSourceMap parses the sourcemap returning the resulting Program. func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSource, sourcemapSource interface{}, mode Mode) (*ast.Program, error) { src, err := ReadSource(filename, javascriptSource) if err != nil { @@ -168,7 +164,7 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo if bytes.HasPrefix(lastLine, []byte("//# sourceMappingURL=data:application/json")) { bits := bytes.SplitN(lastLine, []byte(","), 2) if len(bits) == 2 { - if d, err := base64.StdEncoding.DecodeString(string(bits[1])); err == nil { + if d, errDecode := base64.StdEncoding.DecodeString(string(bits[1])); errDecode == nil { sourcemapSource = d } } @@ -185,10 +181,10 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo base = fileSet.AddFile(filename, string(src)) } - parser := _newParser(filename, string(src), base, sm) - parser.mode = mode - program, err := parser.parse() - program.Comments = parser.comments.CommentMap + p := newParser(filename, string(src), base, sm) + p.mode = mode + program, err := p.parse() + program.Comments = p.comments.CommentMap return program, err } @@ -203,9 +199,8 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo // // src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8. // -// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList -// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) -// +// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList +// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) { return ParseFileWithSourceMap(fileSet, filename, src, nil, mode) } @@ -214,13 +209,11 @@ func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mod // corresponding ast.FunctionLiteral node. // // The parameter list, if any, should be a comma-separated list of identifiers. -// func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { - src := "(function(" + parameterList + ") {\n" + body + "\n})" - parser := _newParser("", src, 1, nil) - program, err := parser.parse() + p := newParser("", src, 1, nil) + program, err := p.parse() if err != nil { return nil, err } @@ -231,75 +224,75 @@ func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { // Scan reads a single token from the source at the current offset, increments the offset and // returns the token.Token token, a string literal representing the value of the token (if applicable) // and it's current file.Idx index. -func (self *_parser) Scan() (tkn token.Token, literal string, idx file.Idx) { - return self.scan() +func (p *parser) Scan() (token.Token, string, file.Idx) { + return p.scan() } -func (self *_parser) slice(idx0, idx1 file.Idx) string { - from := int(idx0) - self.base - to := int(idx1) - self.base - if from >= 0 && to <= len(self.str) { - return self.str[from:to] +func (p *parser) slice(idx0, idx1 file.Idx) string { + from := int(idx0) - p.base + to := int(idx1) - p.base + if from >= 0 && to <= len(p.str) { + return p.str[from:to] } return "" } -func (self *_parser) parse() (*ast.Program, error) { - self.next() - program := self.parseProgram() +func (p *parser) parse() (*ast.Program, error) { + p.next() + program := p.parseProgram() if false { - self.errors.Sort() + p.errors.Sort() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(program, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(program, p.comments.FetchAll(), ast.TRAILING) } - return program, self.errors.Err() + return program, p.errors.Err() } -func (self *_parser) next() { - self.token, self.literal, self.idx = self.scan() +func (p *parser) next() { + p.token, p.literal, p.idx = p.scan() } -func (self *_parser) optionalSemicolon() { - if self.token == token.SEMICOLON { - self.next() +func (p *parser) optionalSemicolon() { + if p.token == token.SEMICOLON { + p.next() return } - if self.implicitSemicolon { - self.implicitSemicolon = false + if p.implicitSemicolon { + p.implicitSemicolon = false return } - if self.token != token.EOF && self.token != token.RIGHT_BRACE { - self.expect(token.SEMICOLON) + if p.token != token.EOF && p.token != token.RIGHT_BRACE { + p.expect(token.SEMICOLON) } } -func (self *_parser) semicolon() { - if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE { - if self.implicitSemicolon { - self.implicitSemicolon = false +func (p *parser) semicolon() { + if p.token != token.RIGHT_PARENTHESIS && p.token != token.RIGHT_BRACE { + if p.implicitSemicolon { + p.implicitSemicolon = false return } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) } } -func (self *_parser) idxOf(offset int) file.Idx { - return file.Idx(self.base + offset) +func (p *parser) idxOf(offset int) file.Idx { + return file.Idx(p.base + offset) } -func (self *_parser) expect(value token.Token) file.Idx { - idx := self.idx - if self.token != value { - self.errorUnexpectedToken(self.token) +func (p *parser) expect(value token.Token) file.Idx { + idx := p.idx + if p.token != value { + p.errorUnexpectedToken(p.token) } - self.next() + p.next() return idx } @@ -309,17 +302,17 @@ func lineCount(str string) (int, int) { for index, chr := range str { switch chr { case '\r': - line += 1 + line++ last = index pair = true continue case '\n': if !pair { - line += 1 + line++ } last = index case '\u2028', '\u2029': - line += 1 + line++ last = index + 2 } pair = false @@ -327,11 +320,11 @@ func lineCount(str string) (int, int) { return line, last } -func (self *_parser) position(idx file.Idx) file.Position { +func (p *parser) position(idx file.Idx) file.Position { position := file.Position{} - offset := int(idx) - self.base - str := self.str[:offset] - position.Filename = self.file.Name() + offset := int(idx) - p.base + str := p.str[:offset] + position.Filename = p.file.Name() line, last := lineCount(str) position.Line = 1 + line if last >= 0 { diff --git a/vendor/github.com/robertkrimen/otto/parser/regexp.go b/vendor/github.com/robertkrimen/otto/parser/regexp.go index f614dae74..df4a51b37 100644 --- a/vendor/github.com/robertkrimen/otto/parser/regexp.go +++ b/vendor/github.com/robertkrimen/otto/parser/regexp.go @@ -6,18 +6,15 @@ import ( "strconv" ) -type _RegExp_parser struct { - str string - length int - - chr rune // The current character - chrOffset int // The offset of current character - offset int // The offset after current character (may be greater than 1) - - errors []error - invalid bool // The input is an invalid JavaScript RegExp - - goRegexp *bytes.Buffer +type regExpParser struct { + goRegexp *bytes.Buffer + str string + errors []error + length int + chrOffset int + offset int + chr rune + invalid bool } // TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern. @@ -34,136 +31,134 @@ type _RegExp_parser struct { // If the pattern is valid, but incompatible (contains a lookahead or backreference), // then this function returns the transformation (a non-empty string) AND an error. func TransformRegExp(pattern string) (string, error) { - if pattern == "" { return "", nil } // TODO If without \, if without (?=, (?!, then another shortcut - parser := _RegExp_parser{ + p := regExpParser{ str: pattern, length: len(pattern), goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)), } - parser.read() // Pull in the first character - parser.scan() + p.read() // Pull in the first character + p.scan() var err error - if len(parser.errors) > 0 { - err = parser.errors[0] + if len(p.errors) > 0 { + err = p.errors[0] } - if parser.invalid { + if p.invalid { return "", err } // Might not be re2 compatible, but is still a valid JavaScript RegExp - return parser.goRegexp.String(), err + return p.goRegexp.String(), err } -func (self *_RegExp_parser) scan() { - for self.chr != -1 { - switch self.chr { +func (p *regExpParser) scan() { + for p.chr != -1 { + switch p.chr { case '\\': - self.read() - self.scanEscape(false) + p.read() + p.scanEscape(false) case '(': - self.pass() - self.scanGroup() + p.pass() + p.scanGroup() case '[': - self.pass() - self.scanBracket() + p.pass() + p.scanBracket() case ')': - self.error(-1, "Unmatched ')'") - self.invalid = true - self.pass() + p.error(-1, "Unmatched ')'") + p.invalid = true + p.pass() default: - self.pass() + p.pass() } } } // (...) -func (self *_RegExp_parser) scanGroup() { - str := self.str[self.chrOffset:] +func (p *regExpParser) scanGroup() { + str := p.str[p.chrOffset:] if len(str) > 1 { // A possibility of (?= or (?! if str[0] == '?' { if str[1] == '=' || str[1] == '!' { - self.error(-1, "re2: Invalid (%s) ", self.str[self.chrOffset:self.chrOffset+2]) + p.error(-1, "re2: Invalid (%s) ", p.str[p.chrOffset:p.chrOffset+2]) } } } - for self.chr != -1 && self.chr != ')' { - switch self.chr { + for p.chr != -1 && p.chr != ')' { + switch p.chr { case '\\': - self.read() - self.scanEscape(false) + p.read() + p.scanEscape(false) case '(': - self.pass() - self.scanGroup() + p.pass() + p.scanGroup() case '[': - self.pass() - self.scanBracket() + p.pass() + p.scanBracket() default: - self.pass() + p.pass() continue } } - if self.chr != ')' { - self.error(-1, "Unterminated group") - self.invalid = true + if p.chr != ')' { + p.error(-1, "Unterminated group") + p.invalid = true return } - self.pass() + p.pass() } -// [...] -func (self *_RegExp_parser) scanBracket() { - for self.chr != -1 { - if self.chr == ']' { +// [...]. +func (p *regExpParser) scanBracket() { + for p.chr != -1 { + if p.chr == ']' { break - } else if self.chr == '\\' { - self.read() - self.scanEscape(true) + } else if p.chr == '\\' { + p.read() + p.scanEscape(true) continue } - self.pass() + p.pass() } - if self.chr != ']' { - self.error(-1, "Unterminated character class") - self.invalid = true + if p.chr != ']' { + p.error(-1, "Unterminated character class") + p.invalid = true return } - self.pass() + p.pass() } // \... -func (self *_RegExp_parser) scanEscape(inClass bool) { - offset := self.chrOffset +func (p *regExpParser) scanEscape(inClass bool) { + offset := p.chrOffset var length, base uint32 - switch self.chr { - + switch p.chr { case '0', '1', '2', '3', '4', '5', '6', '7': var value int64 size := 0 for { - digit := int64(digitValue(self.chr)) + digit := int64(digitValue(p.chr)) if digit >= 8 { // Not a valid digit break } value = value*8 + digit - self.read() - size += 1 + p.read() + size++ } if size == 1 { // The number of characters read - _, err := self.goRegexp.Write([]byte{'\\', byte(value) + '0'}) + _, err := p.goRegexp.Write([]byte{'\\', byte(value) + '0'}) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } if value != 0 { // An invalid backreference - self.error(-1, "re2: Invalid \\%d ", value) + p.error(-1, "re2: Invalid \\%d ", value) } return } @@ -174,49 +169,49 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { tmp = tmp[0:3] } tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) + _, err := p.goRegexp.Write(tmp) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } return case '8', '9': size := 0 for { - digit := digitValue(self.chr) + digit := digitValue(p.chr) if digit >= 10 { // Not a valid digit break } - self.read() - size += 1 + p.read() + size++ } - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - _, err = self.goRegexp.WriteString(self.str[offset:self.chrOffset]) + _, err = p.goRegexp.WriteString(p.str[offset:p.chrOffset]) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.error(-1, "re2: Invalid \\%s ", self.str[offset:self.chrOffset]) + p.error(-1, "re2: Invalid \\%s ", p.str[offset:p.chrOffset]) return case 'x': - self.read() + p.read() length, base = 2, 16 case 'u': - self.read() + p.read() length, base = 4, 16 case 'b': if inClass { - _, err := self.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) + _, err := p.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.read() + p.read() return } fallthrough @@ -233,24 +228,25 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { fallthrough case 'f', 'n', 'r', 't', 'v': - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.pass() + p.pass() return case 'c': - self.read() + p.read() var value int64 - if 'a' <= self.chr && self.chr <= 'z' { - value = int64(self.chr) - 'a' + 1 - } else if 'A' <= self.chr && self.chr <= 'Z' { - value = int64(self.chr) - 'A' + 1 - } else { - err := self.goRegexp.WriteByte('c') + switch { + case 'a' <= p.chr && p.chr <= 'z': + value = int64(p.chr) - 'a' + 1 + case 'A' <= p.chr && p.chr <= 'Z': + value = int64(p.chr) - 'A' + 1 + default: + err := p.goRegexp.WriteByte('c') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } return } @@ -261,98 +257,93 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { tmp = tmp[0:3] } tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) + _, err := p.goRegexp.Write(tmp) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.read() + p.read() return default: // $ is an identifier character, so we have to have // a special case for it here - if self.chr == '$' || !isIdentifierPart(self.chr) { + if p.chr == '$' || !isIdentifierPart(p.chr) { // A non-identifier character needs escaping - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - } else { + } else { //nolint:staticcheck // Unescape the character for re2 } - self.pass() + p.pass() return } // Otherwise, we're a \u.... or \x... - valueOffset := self.chrOffset + valueOffset := p.chrOffset var value uint32 - { - length := length - for ; length > 0; length-- { - digit := uint32(digitValue(self.chr)) - if digit >= base { - // Not a valid digit - goto skip - } - value = value*base + digit - self.read() + for length := length; length > 0; length-- { + digit := uint32(digitValue(p.chr)) + if digit >= base { + // Not a valid digit + goto skip } + value = value*base + digit + p.read() } - if length == 4 { - _, err := self.goRegexp.Write([]byte{ + switch length { + case 4: + if _, err := p.goRegexp.Write([]byte{ '\\', 'x', '{', - self.str[valueOffset+0], - self.str[valueOffset+1], - self.str[valueOffset+2], - self.str[valueOffset+3], + p.str[valueOffset+0], + p.str[valueOffset+1], + p.str[valueOffset+2], + p.str[valueOffset+3], '}', - }) - if err != nil { - self.errors = append(self.errors, err) + }); err != nil { + p.errors = append(p.errors, err) } - } else if length == 2 { - _, err := self.goRegexp.Write([]byte{ + case 2: + if _, err := p.goRegexp.Write([]byte{ '\\', 'x', - self.str[valueOffset+0], - self.str[valueOffset+1], - }) - if err != nil { - self.errors = append(self.errors, err) + p.str[valueOffset+0], + p.str[valueOffset+1], + }); err != nil { + p.errors = append(p.errors, err) } - } else { + default: // Should never, ever get here... - self.error(-1, "re2: Illegal branch in scanEscape") + p.error(-1, "re2: Illegal branch in scanEscape") goto skip } return skip: - _, err := self.goRegexp.WriteString(self.str[offset:self.chrOffset]) + _, err := p.goRegexp.WriteString(p.str[offset:p.chrOffset]) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } } -func (self *_RegExp_parser) pass() { - if self.chr != -1 { - _, err := self.goRegexp.WriteRune(self.chr) +func (p *regExpParser) pass() { + if p.chr != -1 { + _, err := p.goRegexp.WriteRune(p.chr) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } } - self.read() + p.read() } // TODO Better error reporting, use the offset, etc. -func (self *_RegExp_parser) error(offset int, msg string, msgValues ...interface{}) error { +func (p *regExpParser) error(offset int, msg string, msgValues ...interface{}) { //nolint:unparam err := fmt.Errorf(msg, msgValues...) - self.errors = append(self.errors, err) - return err + p.errors = append(p.errors, err) } diff --git a/vendor/github.com/robertkrimen/otto/parser/scope.go b/vendor/github.com/robertkrimen/otto/parser/scope.go index e1dbdda13..9f49e47bf 100644 --- a/vendor/github.com/robertkrimen/otto/parser/scope.go +++ b/vendor/github.com/robertkrimen/otto/parser/scope.go @@ -4,41 +4,40 @@ import ( "github.com/robertkrimen/otto/ast" ) -type _scope struct { - outer *_scope +type scope struct { + outer *scope + declarationList []ast.Declaration + labels []string allowIn bool inIteration bool inSwitch bool inFunction bool - declarationList []ast.Declaration - - labels []string } -func (self *_parser) openScope() { - self.scope = &_scope{ - outer: self.scope, +func (p *parser) openScope() { + p.scope = &scope{ + outer: p.scope, allowIn: true, } } -func (self *_parser) closeScope() { - self.scope = self.scope.outer +func (p *parser) closeScope() { + p.scope = p.scope.outer } -func (self *_scope) declare(declaration ast.Declaration) { - self.declarationList = append(self.declarationList, declaration) +func (p *scope) declare(declaration ast.Declaration) { + p.declarationList = append(p.declarationList, declaration) } -func (self *_scope) hasLabel(name string) bool { - for _, label := range self.labels { +func (p *scope) hasLabel(name string) bool { + for _, label := range p.labels { if label == name { return true } } - if self.outer != nil && !self.inFunction { + if p.outer != nil && !p.inFunction { // Crossing a function boundary to look for a label is verboten - return self.outer.hasLabel(name) + return p.outer.hasLabel(name) } return false } diff --git a/vendor/github.com/robertkrimen/otto/parser/statement.go b/vendor/github.com/robertkrimen/otto/parser/statement.go index 804cdfdc0..e6469773f 100644 --- a/vendor/github.com/robertkrimen/otto/parser/statement.go +++ b/vendor/github.com/robertkrimen/otto/parser/statement.go @@ -5,234 +5,233 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_parser) parseBlockStatement() *ast.BlockStatement { +func (p *parser) parseBlockStatement() *ast.BlockStatement { node := &ast.BlockStatement{} // Find comments before the leading brace - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.LEADING) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.LEADING) + p.comments.Unset() } - node.LeftBrace = self.expect(token.LEFT_BRACE) - node.List = self.parseStatementList() + node.LeftBrace = p.expect(token.LEFT_BRACE) + node.List = p.parseStatementList() - if self.mode&StoreComments != 0 { - self.comments.Unset() - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.FINAL) - self.comments.AfterBlock() + if p.mode&StoreComments != 0 { + p.comments.Unset() + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.FINAL) + p.comments.AfterBlock() } - node.RightBrace = self.expect(token.RIGHT_BRACE) + node.RightBrace = p.expect(token.RIGHT_BRACE) // Find comments after the trailing brace - if self.mode&StoreComments != 0 { - self.comments.ResetLineBreak() - self.comments.CommentMap.AddComments(node, self.comments.Fetch(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.ResetLineBreak() + p.comments.CommentMap.AddComments(node, p.comments.Fetch(), ast.TRAILING) } return node } -func (self *_parser) parseEmptyStatement() ast.Statement { - idx := self.expect(token.SEMICOLON) +func (p *parser) parseEmptyStatement() ast.Statement { + idx := p.expect(token.SEMICOLON) return &ast.EmptyStatement{Semicolon: idx} } -func (self *_parser) parseStatementList() (list []ast.Statement) { - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - statement := self.parseStatement() +func (p *parser) parseStatementList() (list []ast.Statement) { //nolint:nonamedreturns + for p.token != token.RIGHT_BRACE && p.token != token.EOF { + statement := p.parseStatement() list = append(list, statement) } - return + return list } -func (self *_parser) parseStatement() ast.Statement { - - if self.token == token.EOF { - self.errorUnexpectedToken(self.token) - return &ast.BadStatement{From: self.idx, To: self.idx + 1} +func (p *parser) parseStatement() ast.Statement { + if p.token == token.EOF { + p.errorUnexpectedToken(p.token) + return &ast.BadStatement{From: p.idx, To: p.idx + 1} } - if self.mode&StoreComments != 0 { - self.comments.ResetLineBreak() + if p.mode&StoreComments != 0 { + p.comments.ResetLineBreak() } - switch self.token { + switch p.token { case token.SEMICOLON: - return self.parseEmptyStatement() + return p.parseEmptyStatement() case token.LEFT_BRACE: - return self.parseBlockStatement() + return p.parseBlockStatement() case token.IF: - return self.parseIfStatement() + return p.parseIfStatement() case token.DO: - statement := self.parseDoWhileStatement() - self.comments.PostProcessNode(statement) + statement := p.parseDoWhileStatement() + p.comments.PostProcessNode(statement) return statement case token.WHILE: - return self.parseWhileStatement() + return p.parseWhileStatement() case token.FOR: - return self.parseForOrForInStatement() + return p.parseForOrForInStatement() case token.BREAK: - return self.parseBreakStatement() + return p.parseBreakStatement() case token.CONTINUE: - return self.parseContinueStatement() + return p.parseContinueStatement() case token.DEBUGGER: - return self.parseDebuggerStatement() + return p.parseDebuggerStatement() case token.WITH: - return self.parseWithStatement() + return p.parseWithStatement() case token.VAR: - return self.parseVariableStatement() + return p.parseVariableStatement() case token.FUNCTION: - return self.parseFunctionStatement() + return p.parseFunctionStatement() case token.SWITCH: - return self.parseSwitchStatement() + return p.parseSwitchStatement() case token.RETURN: - return self.parseReturnStatement() + return p.parseReturnStatement() case token.THROW: - return self.parseThrowStatement() + return p.parseThrowStatement() case token.TRY: - return self.parseTryStatement() + return p.parseTryStatement() } var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - expression := self.parseExpression() + expression := p.parseExpression() - if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && self.token == token.COLON { + if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && p.token == token.COLON { // LabelledStatement - colon := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + colon := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() // : + p.next() // : label := identifier.Name - for _, value := range self.scope.labels { + for _, value := range p.scope.labels { if label == value { - self.error(identifier.Idx0(), "Label '%s' already exists", label) + p.error(identifier.Idx0(), "Label '%s' already exists", label) } } var labelComments []*ast.Comment - if self.mode&StoreComments != 0 { - labelComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + labelComments = p.comments.FetchAll() } - self.scope.labels = append(self.scope.labels, label) // Push the label - statement := self.parseStatement() - self.scope.labels = self.scope.labels[:len(self.scope.labels)-1] // Pop the label + p.scope.labels = append(p.scope.labels, label) // Push the label + statement := p.parseStatement() + p.scope.labels = p.scope.labels[:len(p.scope.labels)-1] // Pop the label exp := &ast.LabelledStatement{ Label: identifier, Colon: colon, Statement: statement, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING) } return exp } - self.optionalSemicolon() + p.optionalSemicolon() statement := &ast.ExpressionStatement{ Expression: expression, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(statement, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(statement, comments, ast.LEADING) } return statement } -func (self *_parser) parseTryStatement() ast.Statement { +func (p *parser) parseTryStatement() ast.Statement { var tryComments []*ast.Comment - if self.mode&StoreComments != 0 { - tryComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + tryComments = p.comments.FetchAll() } node := &ast.TryStatement{ - Try: self.expect(token.TRY), - Body: self.parseBlockStatement(), + Try: p.expect(token.TRY), + Body: p.parseBlockStatement(), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, tryComments, ast.LEADING) - self.comments.CommentMap.AddComments(node.Body, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, tryComments, ast.LEADING) + p.comments.CommentMap.AddComments(node.Body, p.comments.FetchAll(), ast.TRAILING) } - if self.token == token.CATCH { - catch := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.CATCH { + catch := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() + } + p.next() + p.expect(token.LEFT_PARENTHESIS) + if p.token != token.IDENTIFIER { + p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadStatement{From: catch, To: p.idx} } - self.next() - self.expect(token.LEFT_PARENTHESIS) - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadStatement{From: catch, To: self.idx} - } else { - identifier := self.parseIdentifier() - self.expect(token.RIGHT_PARENTHESIS) - node.Catch = &ast.CatchStatement{ - Catch: catch, - Parameter: identifier, - Body: self.parseBlockStatement(), - } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node.Catch.Body, self.comments.FetchAll(), ast.TRAILING) - } + identifier := p.parseIdentifier() + p.expect(token.RIGHT_PARENTHESIS) + node.Catch = &ast.CatchStatement{ + Catch: catch, + Parameter: identifier, + Body: p.parseBlockStatement(), + } + + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node.Catch.Body, p.comments.FetchAll(), ast.TRAILING) } } - if self.token == token.FINALLY { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.FINALLY { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - if self.mode&StoreComments != 0 { - tryComments = self.comments.FetchAll() + p.next() + if p.mode&StoreComments != 0 { + tryComments = p.comments.FetchAll() } - node.Finally = self.parseBlockStatement() + node.Finally = p.parseBlockStatement() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING) } } if node.Catch == nil && node.Finally == nil { - self.error(node.Try, "Missing catch or finally after try") + p.error(node.Try, "Missing catch or finally after try") return &ast.BadStatement{From: node.Try, To: node.Body.Idx1()} } return node } -func (self *_parser) parseFunctionParameterList() *ast.ParameterList { - opening := self.expect(token.LEFT_PARENTHESIS) - if self.mode&StoreComments != 0 { - self.comments.Unset() +func (p *parser) parseFunctionParameterList() *ast.ParameterList { + opening := p.expect(token.LEFT_PARENTHESIS) + if p.mode&StoreComments != 0 { + p.comments.Unset() } var list []*ast.Identifier - for self.token != token.RIGHT_PARENTHESIS && self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) + for p.token != token.RIGHT_PARENTHESIS && p.token != token.EOF { + if p.token != token.IDENTIFIER { + p.expect(token.IDENTIFIER) } else { - identifier := self.parseIdentifier() + identifier := p.parseIdentifier() list = append(list, identifier) } - if self.token != token.RIGHT_PARENTHESIS { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token != token.RIGHT_PARENTHESIS { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COMMA) + p.expect(token.COMMA) } } - closing := self.expect(token.RIGHT_PARENTHESIS) + closing := p.expect(token.RIGHT_PARENTHESIS) return &ast.ParameterList{ Opening: opening, @@ -241,288 +240,272 @@ func (self *_parser) parseFunctionParameterList() *ast.ParameterList { } } -func (self *_parser) parseParameterList() (list []string) { - for self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - } - list = append(list, self.literal) - self.next() - if self.token != token.EOF { - self.expect(token.COMMA) - } - } - return -} - -func (self *_parser) parseFunctionStatement() *ast.FunctionStatement { +func (p *parser) parseFunctionStatement() *ast.FunctionStatement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } function := &ast.FunctionStatement{ - Function: self.parseFunction(true), + Function: p.parseFunction(true), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(function, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(function, comments, ast.LEADING) } return function } -func (self *_parser) parseFunction(declaration bool) *ast.FunctionLiteral { - +func (p *parser) parseFunction(declaration bool) *ast.FunctionLiteral { node := &ast.FunctionLiteral{ - Function: self.expect(token.FUNCTION), + Function: p.expect(token.FUNCTION), } var name *ast.Identifier - if self.token == token.IDENTIFIER { - name = self.parseIdentifier() + if p.token == token.IDENTIFIER { + name = p.parseIdentifier() if declaration { - self.scope.declare(&ast.FunctionDeclaration{ + p.scope.declare(&ast.FunctionDeclaration{ Function: node, }) } } else if declaration { // Use expect error handling - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } node.Name = name - node.ParameterList = self.parseFunctionParameterList() - self.parseFunctionBlock(node) - node.Source = self.slice(node.Idx0(), node.Idx1()) + node.ParameterList = p.parseFunctionParameterList() + p.parseFunctionBlock(node) + node.Source = p.slice(node.Idx0(), node.Idx1()) return node } -func (self *_parser) parseFunctionBlock(node *ast.FunctionLiteral) { - { - self.openScope() - inFunction := self.scope.inFunction - self.scope.inFunction = true - defer func() { - self.scope.inFunction = inFunction - self.closeScope() - }() - node.Body = self.parseBlockStatement() - node.DeclarationList = self.scope.declarationList - } +func (p *parser) parseFunctionBlock(node *ast.FunctionLiteral) { + p.openScope() + inFunction := p.scope.inFunction + p.scope.inFunction = true + defer func() { + p.scope.inFunction = inFunction + p.closeScope() + }() + node.Body = p.parseBlockStatement() + node.DeclarationList = p.scope.declarationList } -func (self *_parser) parseDebuggerStatement() ast.Statement { - idx := self.expect(token.DEBUGGER) +func (p *parser) parseDebuggerStatement() ast.Statement { + idx := p.expect(token.DEBUGGER) node := &ast.DebuggerStatement{ Debugger: idx, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.TRAILING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseReturnStatement() ast.Statement { - idx := self.expect(token.RETURN) +func (p *parser) parseReturnStatement() ast.Statement { + idx := p.expect(token.RETURN) var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - if !self.scope.inFunction { - self.error(idx, "Illegal return statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + if !p.scope.inFunction { + p.error(idx, "Illegal return statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } node := &ast.ReturnStatement{ Return: idx, } - if !self.implicitSemicolon && self.token != token.SEMICOLON && self.token != token.RIGHT_BRACE && self.token != token.EOF { - node.Argument = self.parseExpression() + if !p.implicitSemicolon && p.token != token.SEMICOLON && p.token != token.RIGHT_BRACE && p.token != token.EOF { + node.Argument = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseThrowStatement() ast.Statement { +func (p *parser) parseThrowStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.THROW) + idx := p.expect(token.THROW) - if self.implicitSemicolon { - if self.chr == -1 { // Hackish - self.error(idx, "Unexpected end of input") + if p.implicitSemicolon { + if p.chr == -1 { // Hackish + p.error(idx, "Unexpected end of input") } else { - self.error(idx, "Illegal newline after throw") + p.error(idx, "Illegal newline after throw") } - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } node := &ast.ThrowStatement{ - Throw: self.idx, - Argument: self.parseExpression(), + Throw: idx, + Argument: p.parseExpression(), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseSwitchStatement() ast.Statement { +func (p *parser) parseSwitchStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.SWITCH) - if self.mode&StoreComments != 0 { - comments = append(comments, self.comments.FetchAll()...) + idx := p.expect(token.SWITCH) + if p.mode&StoreComments != 0 { + comments = append(comments, p.comments.FetchAll()...) } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.SwitchStatement{ - Discriminant: self.parseExpression(), + Switch: idx, + Discriminant: p.parseExpression(), Default: -1, } - self.expect(token.RIGHT_PARENTHESIS) - if self.mode&StoreComments != 0 { - comments = append(comments, self.comments.FetchAll()...) + p.expect(token.RIGHT_PARENTHESIS) + if p.mode&StoreComments != 0 { + comments = append(comments, p.comments.FetchAll()...) } - self.expect(token.LEFT_BRACE) + p.expect(token.LEFT_BRACE) - inSwitch := self.scope.inSwitch - self.scope.inSwitch = true + inSwitch := p.scope.inSwitch + p.scope.inSwitch = true defer func() { - self.scope.inSwitch = inSwitch + p.scope.inSwitch = inSwitch }() - for index := 0; self.token != token.EOF; index++ { - if self.token == token.RIGHT_BRACE { - self.next() + for index := 0; p.token != token.EOF; index++ { + if p.token == token.RIGHT_BRACE { + node.RightBrace = p.idx + p.next() break } - clause := self.parseCaseStatement() + clause := p.parseCaseStatement() if clause.Test == nil { if node.Default != -1 { - self.error(clause.Case, "Already saw a default in switch") + p.error(clause.Case, "Already saw a default in switch") } node.Default = index } node.Body = append(node.Body, clause) } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } return node } -func (self *_parser) parseWithStatement() ast.Statement { +func (p *parser) parseWithStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.WITH) + idx := p.expect(token.WITH) var withComments []*ast.Comment - if self.mode&StoreComments != 0 { - withComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + withComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.WithStatement{ - Object: self.parseExpression(), + With: idx, + Object: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.RIGHT_PARENTHESIS) - if self.mode&StoreComments != 0 { - //comments = append(comments, self.comments.FetchAll()...) - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, withComments, ast.WITH) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, withComments, ast.WITH) } - node.Body = self.parseStatement() + node.Body = p.parseStatement() return node } -func (self *_parser) parseCaseStatement() *ast.CaseStatement { +func (p *parser) parseCaseStatement() *ast.CaseStatement { node := &ast.CaseStatement{ - Case: self.idx, + Case: p.idx, } var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() - self.comments.Unset() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() + p.comments.Unset() } - if self.token == token.DEFAULT { - self.next() + if p.token == token.DEFAULT { + p.next() } else { - self.expect(token.CASE) - node.Test = self.parseExpression() + p.expect(token.CASE) + node.Test = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COLON) + p.expect(token.COLON) for { - if self.token == token.EOF || - self.token == token.RIGHT_BRACE || - self.token == token.CASE || - self.token == token.DEFAULT { + if p.token == token.EOF || + p.token == token.RIGHT_BRACE || + p.token == token.CASE || + p.token == token.DEFAULT { break } - consequent := self.parseStatement() + consequent := p.parseStatement() node.Consequent = append(node.Consequent, consequent) } // Link the comments to the case statement - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } return node } -func (self *_parser) parseIterationStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true +func (p *parser) parseIterationStatement() ast.Statement { + inIteration := p.scope.inIteration + p.scope.inIteration = true defer func() { - self.scope.inIteration = inIteration + p.scope.inIteration = inIteration }() - return self.parseStatement() + return p.parseStatement() } -func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { - +func (p *parser) parseForIn(into ast.Expression) *ast.ForInStatement { // Already have consumed " in" - source := self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) - body := self.parseIterationStatement() + source := p.parseExpression() + p.expect(token.RIGHT_PARENTHESIS) + body := p.parseIterationStatement() forin := &ast.ForInStatement{ Into: into, @@ -533,25 +516,24 @@ func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { return forin } -func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { - +func (p *parser) parseFor(initializer ast.Expression) *ast.ForStatement { // Already have consumed " ;" var test, update ast.Expression - if self.token != token.SEMICOLON { - test = self.parseExpression() + if p.token != token.SEMICOLON { + test = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) - if self.token != token.RIGHT_PARENTHESIS { - update = self.parseExpression() + if p.token != token.RIGHT_PARENTHESIS { + update = p.parseExpression() } - self.expect(token.RIGHT_PARENTHESIS) - body := self.parseIterationStatement() + p.expect(token.RIGHT_PARENTHESIS) + body := p.parseIterationStatement() forstatement := &ast.ForStatement{ Initializer: initializer, @@ -563,55 +545,54 @@ func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { return forstatement } -func (self *_parser) parseForOrForInStatement() ast.Statement { +func (p *parser) parseForOrForInStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.FOR) + idx := p.expect(token.FOR) var forComments []*ast.Comment - if self.mode&StoreComments != 0 { - forComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + forComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) var left []ast.Expression forIn := false - if self.token != token.SEMICOLON { - - allowIn := self.scope.allowIn - self.scope.allowIn = false - if self.token == token.VAR { - var_ := self.idx + if p.token != token.SEMICOLON { + allowIn := p.scope.allowIn + p.scope.allowIn = false + if p.token == token.VAR { + tokenIdx := p.idx var varComments []*ast.Comment - if self.mode&StoreComments != 0 { - varComments = self.comments.FetchAll() - self.comments.Unset() + if p.mode&StoreComments != 0 { + varComments = p.comments.FetchAll() + p.comments.Unset() } - self.next() - list := self.parseVariableDeclarationList(var_) - if len(list) == 1 && self.token == token.IN { - if self.mode&StoreComments != 0 { - self.comments.Unset() + p.next() + list := p.parseVariableDeclarationList(tokenIdx) + if len(list) == 1 && p.token == token.IN { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() // in + p.next() // in forIn = true left = []ast.Expression{list[0]} // There is only one declaration } else { left = list } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING) } } else { - left = append(left, self.parseExpression()) - if self.token == token.IN { - self.next() + left = append(left, p.parseExpression()) + if p.token == token.IN { + p.next() forIn = true } } - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn } if forIn { @@ -619,207 +600,212 @@ func (self *_parser) parseForOrForInStatement() ast.Statement { case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression, *ast.VariableExpression: // These are all acceptable default: - self.error(idx, "Invalid left-hand side in for-in") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Invalid left-hand side in for-in") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } - forin := self.parseForIn(left[0]) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(forin, comments, ast.LEADING) - self.comments.CommentMap.AddComments(forin, forComments, ast.FOR) + forin := p.parseForIn(left[0]) + forin.For = idx + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(forin, comments, ast.LEADING) + p.comments.CommentMap.AddComments(forin, forComments, ast.FOR) } return forin } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) initializer := &ast.SequenceExpression{Sequence: left} - forstatement := self.parseFor(initializer) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING) - self.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR) + forstatement := p.parseFor(initializer) + forstatement.For = idx + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING) + p.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR) } return forstatement } -func (self *_parser) parseVariableStatement() *ast.VariableStatement { +func (p *parser) parseVariableStatement() *ast.VariableStatement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.VAR) + idx := p.expect(token.VAR) - list := self.parseVariableDeclarationList(idx) + list := p.parseVariableDeclarationList(idx) statement := &ast.VariableStatement{ Var: idx, List: list, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(statement, comments, ast.LEADING) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(statement, comments, ast.LEADING) + p.comments.Unset() } - self.semicolon() + p.semicolon() return statement } -func (self *_parser) parseDoWhileStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true +func (p *parser) parseDoWhileStatement() ast.Statement { + inIteration := p.scope.inIteration + p.scope.inIteration = true defer func() { - self.scope.inIteration = inIteration + p.scope.inIteration = inIteration }() var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.DO) + idx := p.expect(token.DO) var doComments []*ast.Comment - if self.mode&StoreComments != 0 { - doComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + doComments = p.comments.FetchAll() } - node := &ast.DoWhileStatement{} - if self.token == token.LEFT_BRACE { - node.Body = self.parseBlockStatement() + node := &ast.DoWhileStatement{Do: idx} + if p.token == token.LEFT_BRACE { + node.Body = p.parseBlockStatement() } else { - node.Body = self.parseStatement() + node.Body = p.parseStatement() } - self.expect(token.WHILE) + p.expect(token.WHILE) var whileComments []*ast.Comment - if self.mode&StoreComments != 0 { - whileComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + whileComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) - node.Test = self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) + node.Test = p.parseExpression() + node.RightParenthesis = p.expect(token.RIGHT_PARENTHESIS) + + p.implicitSemicolon = true + p.optionalSemicolon() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, doComments, ast.DO) - self.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, doComments, ast.DO) + p.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) } return node } -func (self *_parser) parseWhileStatement() ast.Statement { +func (p *parser) parseWhileStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.WHILE) + idx := p.expect(token.WHILE) var whileComments []*ast.Comment - if self.mode&StoreComments != 0 { - whileComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + whileComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.WhileStatement{ - Test: self.parseExpression(), + While: idx, + Test: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) - node.Body = self.parseIterationStatement() + p.expect(token.RIGHT_PARENTHESIS) + node.Body = p.parseIterationStatement() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) } return node } -func (self *_parser) parseIfStatement() ast.Statement { +func (p *parser) parseIfStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.IF) + pos := p.expect(token.IF) var ifComments []*ast.Comment - if self.mode&StoreComments != 0 { - ifComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + ifComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.IfStatement{ - If: self.idx, - Test: self.parseExpression(), + If: pos, + Test: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) - if self.token == token.LEFT_BRACE { - node.Consequent = self.parseBlockStatement() + p.expect(token.RIGHT_PARENTHESIS) + if p.token == token.LEFT_BRACE { + node.Consequent = p.parseBlockStatement() } else { - node.Consequent = self.parseStatement() + node.Consequent = p.parseStatement() } - if self.token == token.ELSE { - self.next() - node.Alternate = self.parseStatement() + if p.token == token.ELSE { + p.next() + node.Alternate = p.parseStatement() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, ifComments, ast.IF) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, ifComments, ast.IF) } return node } -func (self *_parser) parseSourceElement() ast.Statement { - statement := self.parseStatement() - //self.comments.Unset() +func (p *parser) parseSourceElement() ast.Statement { + statement := p.parseStatement() return statement } -func (self *_parser) parseSourceElements() []ast.Statement { +func (p *parser) parseSourceElements() []ast.Statement { body := []ast.Statement(nil) for { - if self.token != token.STRING { + if p.token != token.STRING { break } - body = append(body, self.parseSourceElement()) + body = append(body, p.parseSourceElement()) } - for self.token != token.EOF { - body = append(body, self.parseSourceElement()) + for p.token != token.EOF { + body = append(body, p.parseSourceElement()) } return body } -func (self *_parser) parseProgram() *ast.Program { - self.openScope() - defer self.closeScope() +func (p *parser) parseProgram() *ast.Program { + p.openScope() + defer p.closeScope() return &ast.Program{ - Body: self.parseSourceElements(), - DeclarationList: self.scope.declarationList, - File: self.file, + Body: p.parseSourceElements(), + DeclarationList: p.scope.declarationList, + File: p.file, } } -func (self *_parser) parseBreakStatement() ast.Statement { +func (p *parser) parseBreakStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.BREAK) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { + idx := p.expect(token.BREAK) + semicolon := p.implicitSemicolon + if p.token == token.SEMICOLON { semicolon = true - self.next() + p.next() } - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration && !self.scope.inSwitch { + if semicolon || p.token == token.RIGHT_BRACE { + p.implicitSemicolon = false + if !p.scope.inIteration && !p.scope.inSwitch { goto illegal } breakStatement := &ast.BranchStatement{ @@ -827,52 +813,52 @@ func (self *_parser) parseBreakStatement() ast.Statement { Token: token.BREAK, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) - self.comments.CommentMap.AddComments(breakStatement, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) + p.comments.CommentMap.AddComments(breakStatement, p.comments.FetchAll(), ast.TRAILING) } return breakStatement } - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) + if p.token == token.IDENTIFIER { + identifier := p.parseIdentifier() + if !p.scope.hasLabel(identifier.Name) { + p.error(idx, "Undefined label '%s'", identifier.Name) return &ast.BadStatement{From: idx, To: identifier.Idx1()} } - self.semicolon() + p.semicolon() breakStatement := &ast.BranchStatement{ Idx: idx, Token: token.BREAK, Label: identifier, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) } return breakStatement } - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) illegal: - self.error(idx, "Illegal break statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Illegal break statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } -func (self *_parser) parseContinueStatement() ast.Statement { - idx := self.expect(token.CONTINUE) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { +func (p *parser) parseContinueStatement() ast.Statement { + idx := p.expect(token.CONTINUE) + semicolon := p.implicitSemicolon + if p.token == token.SEMICOLON { semicolon = true - self.next() + p.next() } - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration { + if semicolon || p.token == token.RIGHT_BRACE { + p.implicitSemicolon = false + if !p.scope.inIteration { goto illegal } return &ast.BranchStatement{ @@ -881,16 +867,16 @@ func (self *_parser) parseContinueStatement() ast.Statement { } } - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) + if p.token == token.IDENTIFIER { + identifier := p.parseIdentifier() + if !p.scope.hasLabel(identifier.Name) { + p.error(idx, "Undefined label '%s'", identifier.Name) return &ast.BadStatement{From: idx, To: identifier.Idx1()} } - if !self.scope.inIteration { + if !p.scope.inIteration { goto illegal } - self.semicolon() + p.semicolon() return &ast.BranchStatement{ Idx: idx, Token: token.CONTINUE, @@ -898,18 +884,18 @@ func (self *_parser) parseContinueStatement() ast.Statement { } } - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) illegal: - self.error(idx, "Illegal continue statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Illegal continue statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } -// Find the next statement after an error (recover) -func (self *_parser) nextStatement() { +// Find the next statement after an error (recover). +func (p *parser) nextStatement() { for { - switch self.token { + switch p.token { case token.BREAK, token.CONTINUE, token.FOR, token.IF, token.RETURN, token.SWITCH, token.VAR, token.DO, token.TRY, token.WITH, @@ -918,13 +904,13 @@ func (self *_parser) nextStatement() { // sync or if it has not reached 10 next calls without // progress. Otherwise consume at least one token to // avoid an endless parser loop - if self.idx == self.recover.idx && self.recover.count < 10 { - self.recover.count++ + if p.idx == p.recover.idx && p.recover.count < 10 { + p.recover.count++ return } - if self.idx > self.recover.idx { - self.recover.idx = self.idx - self.recover.count = 0 + if p.idx > p.recover.idx { + p.recover.idx = p.idx + p.recover.count = 0 return } // Reaching here indicates a parser bug, likely an @@ -935,6 +921,6 @@ func (self *_parser) nextStatement() { case token.EOF: return } - self.next() + p.next() } } diff --git a/vendor/github.com/robertkrimen/otto/property.go b/vendor/github.com/robertkrimen/otto/property.go index 5445eccde..768d6e567 100644 --- a/vendor/github.com/robertkrimen/otto/property.go +++ b/vendor/github.com/robertkrimen/otto/property.go @@ -2,88 +2,87 @@ package otto // property -type _propertyMode int +type propertyMode int const ( - modeWriteMask _propertyMode = 0700 - modeEnumerateMask = 0070 - modeConfigureMask = 0007 - modeOnMask = 0111 - modeOffMask = 0000 - modeSetMask = 0222 // If value is 2, then mode is neither "On" nor "Off" + modeWriteMask propertyMode = 0o700 + modeEnumerateMask propertyMode = 0o070 + modeConfigureMask propertyMode = 0o007 + modeOnMask propertyMode = 0o111 + modeSetMask propertyMode = 0o222 // If value is 2, then mode is neither "On" nor "Off" ) -type _propertyGetSet [2]*_object +type propertyGetSet [2]*object -var _nilGetSetObject _object = _object{} +var nilGetSetObject = object{} -type _property struct { +type property struct { value interface{} - mode _propertyMode + mode propertyMode } -func (self _property) writable() bool { - return self.mode&modeWriteMask == modeWriteMask&modeOnMask +func (p property) writable() bool { + return p.mode&modeWriteMask == modeWriteMask&modeOnMask } -func (self *_property) writeOn() { - self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask) +func (p *property) writeOn() { + p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask) } -func (self *_property) writeOff() { - self.mode &= ^modeWriteMask +func (p *property) writeOff() { + p.mode &= ^modeWriteMask } -func (self *_property) writeClear() { - self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask) +func (p *property) writeClear() { + p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask) } -func (self _property) writeSet() bool { - return 0 == self.mode&modeWriteMask&modeSetMask +func (p property) writeSet() bool { + return p.mode&modeWriteMask&modeSetMask == 0 } -func (self _property) enumerable() bool { - return self.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask +func (p property) enumerable() bool { + return p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask } -func (self *_property) enumerateOn() { - self.mode = (self.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask) +func (p *property) enumerateOn() { + p.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask) } -func (self *_property) enumerateOff() { - self.mode &= ^modeEnumerateMask +func (p *property) enumerateOff() { + p.mode &= ^modeEnumerateMask } -func (self _property) enumerateSet() bool { - return 0 == self.mode&modeEnumerateMask&modeSetMask +func (p property) enumerateSet() bool { + return p.mode&modeEnumerateMask&modeSetMask == 0 } -func (self _property) configurable() bool { - return self.mode&modeConfigureMask == modeConfigureMask&modeOnMask +func (p property) configurable() bool { + return p.mode&modeConfigureMask == modeConfigureMask&modeOnMask } -func (self *_property) configureOn() { - self.mode = (self.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask) +func (p *property) configureOn() { + p.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask) } -func (self *_property) configureOff() { - self.mode &= ^modeConfigureMask +func (p *property) configureOff() { + p.mode &= ^modeConfigureMask } -func (self _property) configureSet() bool { - return 0 == self.mode&modeConfigureMask&modeSetMask +func (p property) configureSet() bool { //nolint:unused + return p.mode&modeConfigureMask&modeSetMask == 0 } -func (self _property) copy() *_property { - property := self - return &property +func (p property) copy() *property { //nolint:unused + cpy := p + return &cpy } -func (self _property) get(this *_object) Value { - switch value := self.value.(type) { +func (p property) get(this *object) Value { + switch value := p.value.(type) { case Value: return value - case _propertyGetSet: + case propertyGetSet: if value[0] != nil { return value[0].call(toValue(this), nil, false, nativeFrame) } @@ -91,130 +90,129 @@ func (self _property) get(this *_object) Value { return Value{} } -func (self _property) isAccessorDescriptor() bool { - setGet, test := self.value.(_propertyGetSet) +func (p property) isAccessorDescriptor() bool { + setGet, test := p.value.(propertyGetSet) return test && (setGet[0] != nil || setGet[1] != nil) } -func (self _property) isDataDescriptor() bool { - if self.writeSet() { // Either "On" or "Off" +func (p property) isDataDescriptor() bool { + if p.writeSet() { // Either "On" or "Off" return true } - value, valid := self.value.(Value) + value, valid := p.value.(Value) return valid && !value.isEmpty() } -func (self _property) isGenericDescriptor() bool { - return !(self.isDataDescriptor() || self.isAccessorDescriptor()) +func (p property) isGenericDescriptor() bool { + return !(p.isDataDescriptor() || p.isAccessorDescriptor()) } -func (self _property) isEmpty() bool { - return self.mode == 0222 && self.isGenericDescriptor() +func (p property) isEmpty() bool { + return p.mode == 0o222 && p.isGenericDescriptor() } // _enumerableValue, _enumerableTrue, _enumerableFalse? // .enumerableValue() .enumerableExists() -func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { - objectDescriptor := value._object() +func toPropertyDescriptor(rt *runtime, value Value) property { + objectDescriptor := value.object() if objectDescriptor == nil { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("toPropertyDescriptor on nil")) } - { - descriptor.mode = modeSetMask // Initially nothing is set - if objectDescriptor.hasProperty("enumerable") { - if objectDescriptor.get("enumerable").bool() { - descriptor.enumerateOn() - } else { - descriptor.enumerateOff() - } + var descriptor property + descriptor.mode = modeSetMask // Initially nothing is set + if objectDescriptor.hasProperty("enumerable") { + if objectDescriptor.get("enumerable").bool() { + descriptor.enumerateOn() + } else { + descriptor.enumerateOff() } + } - if objectDescriptor.hasProperty("configurable") { - if objectDescriptor.get("configurable").bool() { - descriptor.configureOn() - } else { - descriptor.configureOff() - } + if objectDescriptor.hasProperty("configurable") { + if objectDescriptor.get("configurable").bool() { + descriptor.configureOn() + } else { + descriptor.configureOff() } + } - if objectDescriptor.hasProperty("writable") { - if objectDescriptor.get("writable").bool() { - descriptor.writeOn() - } else { - descriptor.writeOff() - } + if objectDescriptor.hasProperty("writable") { + if objectDescriptor.get("writable").bool() { + descriptor.writeOn() + } else { + descriptor.writeOff() } } - var getter, setter *_object + var getter, setter *object getterSetter := false if objectDescriptor.hasProperty("get") { - value := objectDescriptor.get("get") - if value.IsDefined() { - if !value.isCallable() { - panic(rt.panicTypeError()) + val := objectDescriptor.get("get") + if val.IsDefined() { + if !val.isCallable() { + panic(rt.panicTypeError("toPropertyDescriptor get not callable")) } - getter = value._object() + getter = val.object() getterSetter = true } else { - getter = &_nilGetSetObject + getter = &nilGetSetObject getterSetter = true } } if objectDescriptor.hasProperty("set") { - value := objectDescriptor.get("set") - if value.IsDefined() { - if !value.isCallable() { - panic(rt.panicTypeError()) + val := objectDescriptor.get("set") + if val.IsDefined() { + if !val.isCallable() { + panic(rt.panicTypeError("toPropertyDescriptor set not callable")) } - setter = value._object() + setter = val.object() getterSetter = true } else { - setter = &_nilGetSetObject + setter = &nilGetSetObject getterSetter = true } } if getterSetter { if descriptor.writeSet() { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("toPropertyDescriptor descriptor writeSet")) } - descriptor.value = _propertyGetSet{getter, setter} + descriptor.value = propertyGetSet{getter, setter} } if objectDescriptor.hasProperty("value") { if getterSetter { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("toPropertyDescriptor value getterSetter")) } descriptor.value = objectDescriptor.get("value") } - return + return descriptor } -func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object { - object := self.newObject() +func (rt *runtime) fromPropertyDescriptor(descriptor property) *object { + obj := rt.newObject() if descriptor.isDataDescriptor() { - object.defineProperty("value", descriptor.value.(Value), 0111, false) - object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false) + obj.defineProperty("value", descriptor.value.(Value), 0o111, false) + obj.defineProperty("writable", boolValue(descriptor.writable()), 0o111, false) } else if descriptor.isAccessorDescriptor() { - getSet := descriptor.value.(_propertyGetSet) + getSet := descriptor.value.(propertyGetSet) get := Value{} if getSet[0] != nil { - get = toValue_object(getSet[0]) + get = objectValue(getSet[0]) } set := Value{} if getSet[1] != nil { - set = toValue_object(getSet[1]) + set = objectValue(getSet[1]) } - object.defineProperty("get", get, 0111, false) - object.defineProperty("set", set, 0111, false) + obj.defineProperty("get", get, 0o111, false) + obj.defineProperty("set", set, 0o111, false) } - object.defineProperty("enumerable", toValue_bool(descriptor.enumerable()), 0111, false) - object.defineProperty("configurable", toValue_bool(descriptor.configurable()), 0111, false) - return object + obj.defineProperty("enumerable", boolValue(descriptor.enumerable()), 0o111, false) + obj.defineProperty("configurable", boolValue(descriptor.configurable()), 0o111, false) + return obj } diff --git a/vendor/github.com/robertkrimen/otto/registry/README.markdown b/vendor/github.com/robertkrimen/otto/registry/README.markdown deleted file mode 100644 index ba2d38909..000000000 --- a/vendor/github.com/robertkrimen/otto/registry/README.markdown +++ /dev/null @@ -1,51 +0,0 @@ -# registry --- - import "github.com/robertkrimen/otto/registry" - -Package registry is an expirmental package to facillitate altering the otto -runtime via import. - -This interface can change at any time. - -## Usage - -#### func Apply - -```go -func Apply(callback func(Entry)) -``` - -#### type Entry - -```go -type Entry struct { -} -``` - - -#### func Register - -```go -func Register(source func() string) *Entry -``` - -#### func (*Entry) Disable - -```go -func (self *Entry) Disable() -``` - -#### func (*Entry) Enable - -```go -func (self *Entry) Enable() -``` - -#### func (Entry) Source - -```go -func (self Entry) Source() string -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/registry/registry.go b/vendor/github.com/robertkrimen/otto/registry/registry.go index 966638ac4..f20b5ff32 100644 --- a/vendor/github.com/robertkrimen/otto/registry/registry.go +++ b/vendor/github.com/robertkrimen/otto/registry/registry.go @@ -1,17 +1,17 @@ -/* -Package registry is an expirmental package to facillitate altering the otto runtime via import. - -This interface can change at any time. -*/ +// Package registry is an experimental package to facilitate altering the otto runtime via import. +// +// This interface can change at any time. package registry var registry []*Entry = make([]*Entry, 0) +// Entry represents a registry entry. type Entry struct { - active bool source func() string + active bool } +// newEntry returns a new Entry for source. func newEntry(source func() string) *Entry { return &Entry{ active: true, @@ -19,18 +19,22 @@ func newEntry(source func() string) *Entry { } } -func (self *Entry) Enable() { - self.active = true +// Enable enables the entry. +func (e *Entry) Enable() { + e.active = true } -func (self *Entry) Disable() { - self.active = false +// Disable disables the entry. +func (e *Entry) Disable() { + e.active = false } -func (self Entry) Source() string { - return self.source() +// Source returns the source of the entry. +func (e Entry) Source() string { + return e.source() } +// Apply applies callback to all registry entries. func Apply(callback func(Entry)) { for _, entry := range registry { if !entry.active { @@ -40,6 +44,7 @@ func Apply(callback func(Entry)) { } } +// Register registers a new Entry for source. func Register(source func() string) *Entry { entry := newEntry(source) registry = append(registry, entry) diff --git a/vendor/github.com/robertkrimen/otto/result.go b/vendor/github.com/robertkrimen/otto/result.go index 63642e7d0..abda3353c 100644 --- a/vendor/github.com/robertkrimen/otto/result.go +++ b/vendor/github.com/robertkrimen/otto/result.go @@ -1,30 +1,28 @@ package otto -import () - -type _resultKind int +type resultKind int const ( - resultNormal _resultKind = iota + _ resultKind = iota resultReturn resultBreak resultContinue ) -type _result struct { - kind _resultKind +type result struct { value Value target string + kind resultKind } -func newReturnResult(value Value) _result { - return _result{resultReturn, value, ""} +func newReturnResult(value Value) result { + return result{kind: resultReturn, value: value, target: ""} } -func newContinueResult(target string) _result { - return _result{resultContinue, emptyValue, target} +func newContinueResult(target string) result { + return result{kind: resultContinue, value: emptyValue, target: target} } -func newBreakResult(target string) _result { - return _result{resultBreak, emptyValue, target} +func newBreakResult(target string) result { + return result{kind: resultBreak, value: emptyValue, target: target} } diff --git a/vendor/github.com/robertkrimen/otto/runtime.go b/vendor/github.com/robertkrimen/otto/runtime.go index 9941278f6..702623673 100644 --- a/vendor/github.com/robertkrimen/otto/runtime.go +++ b/vendor/github.com/robertkrimen/otto/runtime.go @@ -2,12 +2,13 @@ package otto import ( "encoding" + "encoding/json" "errors" "fmt" "math" "path" "reflect" - "runtime" + goruntime "runtime" "strconv" "strings" "sync" @@ -16,179 +17,177 @@ import ( "github.com/robertkrimen/otto/parser" ) -type _global struct { - Object *_object // Object( ... ), new Object( ... ) - 1 (length) - Function *_object // Function( ... ), new Function( ... ) - 1 - Array *_object // Array( ... ), new Array( ... ) - 1 - String *_object // String( ... ), new String( ... ) - 1 - Boolean *_object // Boolean( ... ), new Boolean( ... ) - 1 - Number *_object // Number( ... ), new Number( ... ) - 1 - Math *_object - Date *_object // Date( ... ), new Date( ... ) - 7 - RegExp *_object // RegExp( ... ), new RegExp( ... ) - 2 - Error *_object // Error( ... ), new Error( ... ) - 1 - EvalError *_object - TypeError *_object - RangeError *_object - ReferenceError *_object - SyntaxError *_object - URIError *_object - JSON *_object - - ObjectPrototype *_object // Object.prototype - FunctionPrototype *_object // Function.prototype - ArrayPrototype *_object // Array.prototype - StringPrototype *_object // String.prototype - BooleanPrototype *_object // Boolean.prototype - NumberPrototype *_object // Number.prototype - DatePrototype *_object // Date.prototype - RegExpPrototype *_object // RegExp.prototype - ErrorPrototype *_object // Error.prototype - EvalErrorPrototype *_object - TypeErrorPrototype *_object - RangeErrorPrototype *_object - ReferenceErrorPrototype *_object - SyntaxErrorPrototype *_object - URIErrorPrototype *_object +type global struct { + Object *object // Object( ... ), new Object( ... ) - 1 (length) + Function *object // Function( ... ), new Function( ... ) - 1 + Array *object // Array( ... ), new Array( ... ) - 1 + String *object // String( ... ), new String( ... ) - 1 + Boolean *object // Boolean( ... ), new Boolean( ... ) - 1 + Number *object // Number( ... ), new Number( ... ) - 1 + Math *object + Date *object // Date( ... ), new Date( ... ) - 7 + RegExp *object // RegExp( ... ), new RegExp( ... ) - 2 + Error *object // Error( ... ), new Error( ... ) - 1 + EvalError *object + TypeError *object + RangeError *object + ReferenceError *object + SyntaxError *object + URIError *object + JSON *object + + ObjectPrototype *object // Object.prototype + FunctionPrototype *object // Function.prototype + ArrayPrototype *object // Array.prototype + StringPrototype *object // String.prototype + BooleanPrototype *object // Boolean.prototype + NumberPrototype *object // Number.prototype + DatePrototype *object // Date.prototype + RegExpPrototype *object // RegExp.prototype + ErrorPrototype *object // Error.prototype + EvalErrorPrototype *object + TypeErrorPrototype *object + RangeErrorPrototype *object + ReferenceErrorPrototype *object + SyntaxErrorPrototype *object + URIErrorPrototype *object } -type _runtime struct { - global _global - globalObject *_object - globalStash *_objectStash - scope *_scope +type runtime struct { + global global + globalObject *object + globalStash *objectStash + scope *scope otto *Otto - eval *_object // The builtin eval, for determine indirect versus direct invocation + eval *object debugger func(*Otto) random func() float64 + labels []string stackLimit int traceLimit int - - labels []string // FIXME - lck sync.Mutex + lck sync.Mutex } -func (self *_runtime) enterScope(scope *_scope) { - scope.outer = self.scope - if self.scope != nil { - if self.stackLimit != 0 && self.scope.depth+1 >= self.stackLimit { - panic(self.panicRangeError("Maximum call stack size exceeded")) +func (rt *runtime) enterScope(scop *scope) { + scop.outer = rt.scope + if rt.scope != nil { + if rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit { + panic(rt.panicRangeError("Maximum call stack size exceeded")) } - scope.depth = self.scope.depth + 1 + scop.depth = rt.scope.depth + 1 } - self.scope = scope + rt.scope = scop } -func (self *_runtime) leaveScope() { - self.scope = self.scope.outer +func (rt *runtime) leaveScope() { + rt.scope = rt.scope.outer } -// FIXME This is used in two places (cloning) -func (self *_runtime) enterGlobalScope() { - self.enterScope(newScope(self.globalStash, self.globalStash, self.globalObject)) +// FIXME This is used in two places (cloning). +func (rt *runtime) enterGlobalScope() { + rt.enterScope(newScope(rt.globalStash, rt.globalStash, rt.globalObject)) } -func (self *_runtime) enterFunctionScope(outer _stash, this Value) *_fnStash { +func (rt *runtime) enterFunctionScope(outer stasher, this Value) *fnStash { if outer == nil { - outer = self.globalStash + outer = rt.globalStash } - stash := self.newFunctionStash(outer) - var thisObject *_object + stash := rt.newFunctionStash(outer) + var thisObject *object switch this.kind { case valueUndefined, valueNull: - thisObject = self.globalObject + thisObject = rt.globalObject default: - thisObject = self.toObject(this) + thisObject = rt.toObject(this) } - self.enterScope(newScope(stash, stash, thisObject)) + rt.enterScope(newScope(stash, stash, thisObject)) return stash } -func (self *_runtime) putValue(reference _reference, value Value) { +func (rt *runtime) putValue(reference referencer, value Value) { name := reference.putValue(value) if name != "" { // Why? -- If reference.base == nil // strict = false - self.globalObject.defineProperty(name, value, 0111, false) + rt.globalObject.defineProperty(name, value, 0o111, false) } } -func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exception bool) { +func (rt *runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, isException bool) { //nolint:nonamedreturns // resultValue = The value of the block (e.g. the last statement) // throw = Something was thrown // throwValue = The value of what was thrown // other = Something that changes flow (return, break, continue) that is not a throw - // Otherwise, some sort of unknown panic happened, we'll just propagate it + // Otherwise, some sort of unknown panic happened, we'll just propagate it. defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() + if excep, ok := caught.(*exception); ok { + caught = excep.eject() } switch caught := caught.(type) { - case _error: - exception = true - tryValue = toValue_object(self.newError(caught.name, caught.messageValue(), 0)) + case ottoError: + isException = true + tryValue = objectValue(rt.newErrorObjectError(caught)) case Value: - exception = true + isException = true tryValue = caught default: - panic(caught) + isException = true + tryValue = toValue(caught) } } }() - tryValue = inner() - return + return inner(), false } -// toObject - -func (self *_runtime) toObject(value Value) *_object { +func (rt *runtime) toObject(value Value) *object { switch value.kind { case valueEmpty, valueUndefined, valueNull: - panic(self.panicTypeError()) + panic(rt.panicTypeError("toObject unsupported kind %s", value.kind)) case valueBoolean: - return self.newBoolean(value) + return rt.newBoolean(value) case valueString: - return self.newString(value) + return rt.newString(value) case valueNumber: - return self.newNumber(value) + return rt.newNumber(value) case valueObject: - return value._object() + return value.object() + default: + panic(rt.panicTypeError("toObject unknown kind %s", value.kind)) } - panic(self.panicTypeError()) } -func (self *_runtime) objectCoerce(value Value) (*_object, error) { +func (rt *runtime) objectCoerce(value Value) (*object, error) { switch value.kind { case valueUndefined: return nil, errors.New("undefined") case valueNull: return nil, errors.New("null") case valueBoolean: - return self.newBoolean(value), nil + return rt.newBoolean(value), nil case valueString: - return self.newString(value), nil + return rt.newString(value), nil case valueNumber: - return self.newNumber(value), nil + return rt.newNumber(value), nil case valueObject: - return value._object(), nil + return value.object(), nil + default: + panic(rt.panicTypeError("objectCoerce unknown kind %s", value.kind)) } - panic(self.panicTypeError()) } -func checkObjectCoercible(rt *_runtime, value Value) { +func checkObjectCoercible(rt *runtime, value Value) { isObject, mustCoerce := testObjectCoercible(value) if !isObject && !mustCoerce { - panic(rt.panicTypeError()) + panic(rt.panicTypeError("checkObjectCoercible not object or mustCoerce")) } } -// testObjectCoercible - -func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { +// testObjectCoercible. +func testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint:nonamedreturns switch value.kind { case valueReference, valueEmpty, valueNull, valueUndefined: return false, false @@ -197,21 +196,21 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { case valueObject: return true, false default: - panic("this should never happen") + panic(fmt.Sprintf("testObjectCoercible unknown kind %s", value.kind)) } } -func (self *_runtime) safeToValue(value interface{}) (Value, error) { +func (rt *runtime) safeToValue(value interface{}) (Value, error) { result := Value{} err := catchPanic(func() { - result = self.toValue(value) + result = rt.toValue(value) }) return result, err } // convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics. // This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily. -func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { +func (rt *runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { val := reflect.ValueOf(v.export()) if val.Kind() == t.Kind() { @@ -230,20 +229,20 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { return reflect.ValueOf(f64) case reflect.Float32: if reflect.Zero(t).OverflowFloat(f64) { - panic(self.panicRangeError("converting float64 to float32 would overflow")) + panic(rt.panicRangeError("converting float64 to float32 would overflow")) } return val.Convert(t) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: i64 := int64(f64) if float64(i64) != f64 { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t))) } // The float represents an integer val = reflect.ValueOf(i64) default: - panic(self.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t))) + panic(rt.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t))) } } @@ -253,17 +252,19 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if reflect.Zero(t).OverflowInt(i64) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if i64 < 0 { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t))) } if reflect.Zero(t).OverflowUint(uint64(i64)) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) + case reflect.Float32, reflect.Float64: + return val.Convert(t) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: @@ -271,111 +272,165 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if reflect.Zero(t).OverflowUint(u64) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) + case reflect.Float32, reflect.Float64: + return val.Convert(t) } } - panic(self.panicTypeError(fmt.Sprintf("unsupported type %v for numeric conversion", val.Type()))) + panic(rt.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t))) } -var typeOfValue = reflect.TypeOf(Value{}) +func fieldIndexByName(t reflect.Type, name string) []int { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + + for i := range t.NumField() { + f := t.Field(i) + + if !validGoStructName(f.Name) { + continue + } + + if f.Anonymous { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + + if f.Type.Kind() == reflect.Struct { + if a := fieldIndexByName(f.Type, name); a != nil { + return append([]int{i}, a...) + } + } + } + + if a := strings.SplitN(f.Tag.Get("json"), ",", 2); a[0] != "" { + if a[0] == "-" { + continue + } + + if a[0] == name { + return []int{i} + } + } + + if f.Name == name { + return []int{i} + } + } + + return nil +} + +var ( + typeOfValue = reflect.TypeOf(Value{}) + typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{}) +) // convertCallParameter converts request val to type t if possible. // If the conversion fails due to overflow or type miss-match then it panics. // If no conversion is known then the original value is returned. -func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Value { +func (rt *runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) { if t == typeOfValue { - return reflect.ValueOf(v) + return reflect.ValueOf(v), nil + } + + if t == typeOfJSONRawMessage { + if d, err := json.Marshal(v.export()); err == nil { + return reflect.ValueOf(d), nil + } } if v.kind == valueObject { - if gso, ok := v._object().value.(*_goStructObject); ok { + if gso, ok := v.object().value.(*goStructObject); ok { if gso.value.Type().AssignableTo(t) { // please see TestDynamicFunctionReturningInterface for why this exists if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) { - return gso.value.Convert(t) - } else { - return gso.value + return gso.value.Convert(t), nil } + return gso.value, nil } } - if gao, ok := v._object().value.(*_goArrayObject); ok { + if gao, ok := v.object().value.(*goArrayObject); ok { if gao.value.Type().AssignableTo(t) { // please see TestDynamicFunctionReturningInterface for why this exists if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) { - return gao.value.Convert(t) - } else { - return gao.value + return gao.value.Convert(t), nil } + return gao.value, nil } } } - if t.Kind() == reflect.Interface { + tk := t.Kind() + + if tk == reflect.Interface { e := v.export() if e == nil { - return reflect.Zero(t) + return reflect.Zero(t), nil } iv := reflect.ValueOf(e) if iv.Type().AssignableTo(t) { - return iv + return iv, nil } } - tk := t.Kind() - if tk == reflect.Ptr { switch v.kind { case valueEmpty, valueNull, valueUndefined: - return reflect.Zero(t) + return reflect.Zero(t), nil default: var vv reflect.Value - if err := catchPanic(func() { vv = self.convertCallParameter(v, t.Elem()) }); err == nil { - if vv.CanAddr() { - return vv.Addr() - } + vv, err := rt.convertCallParameter(v, t.Elem()) + if err != nil { + return reflect.Zero(t), fmt.Errorf("can't convert to %s: %w", t, err) + } - pv := reflect.New(vv.Type()) - pv.Elem().Set(vv) - return pv + if vv.CanAddr() { + return vv.Addr(), nil } + + pv := reflect.New(vv.Type()) + pv.Elem().Set(vv) + return pv, nil } } switch tk { case reflect.Bool: - return reflect.ValueOf(v.bool()) + return reflect.ValueOf(v.bool()), nil case reflect.String: switch v.kind { case valueString: - return reflect.ValueOf(v.value) + return reflect.ValueOf(v.value), nil case valueNumber: - return reflect.ValueOf(fmt.Sprintf("%v", v.value)) + return reflect.ValueOf(fmt.Sprintf("%v", v.value)), nil } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: - switch v.kind { - case valueNumber: - return self.convertNumeric(v, t) + if v.kind == valueNumber { + return rt.convertNumeric(v, t), nil } case reflect.Slice: - if o := v._object(); o != nil { - if lv := o.get("length"); lv.IsNumber() { + if o := v.object(); o != nil { + if lv := o.get(propertyLength); lv.IsNumber() { l := lv.number().int64 s := reflect.MakeSlice(t, int(l), int(l)) tt := t.Elem() - if o.class == "Array" { - for i := int64(0); i < l; i++ { + switch o.class { + case classArrayName: + for i := range l { p, ok := o.property[strconv.FormatInt(i, 10)] if !ok { continue @@ -386,22 +441,24 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu continue } - ev := self.convertCallParameter(e, tt) + ev, err := rt.convertCallParameter(e, tt) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err) + } s.Index(int(i)).Set(ev) } - } else if o.class == "GoArray" { - + case classGoArrayName, classGoSliceName: var gslice bool switch o.value.(type) { - case *_goSliceObject: + case *goSliceObject: gslice = true - case *_goArrayObject: + case *goArrayObject: gslice = false } - for i := int64(0); i < l; i++ { - var p *_property + for i := range l { + var p *property if gslice { p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10)) } else { @@ -416,32 +473,46 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu continue } - ev := self.convertCallParameter(e, tt) + ev, err := rt.convertCallParameter(e, tt) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err) + } s.Index(int(i)).Set(ev) } } - return s + return s, nil } } case reflect.Map: - if o := v._object(); o != nil && t.Key().Kind() == reflect.String { + if o := v.object(); o != nil && t.Key().Kind() == reflect.String { m := reflect.MakeMap(t) + var err error + o.enumerate(false, func(k string) bool { - m.SetMapIndex(reflect.ValueOf(k), self.convertCallParameter(o.get(k), t.Elem())) + v, verr := rt.convertCallParameter(o.get(k), t.Elem()) + if verr != nil { + err = fmt.Errorf("couldn't convert property %q of %s: %w", k, t, verr) + return false + } + m.SetMapIndex(reflect.ValueOf(k), v) return true }) - return m + if err != nil { + return reflect.Zero(t), err + } + + return m, nil } case reflect.Func: if t.NumOut() > 1 { - panic(self.panicTypeError("converting JavaScript values to Go functions with more than one return value is currently not supported")) + return reflect.Zero(t), errors.New("converting JavaScript values to Go functions with more than one return value is currently not supported") } - if o := v._object(); o != nil && o.class == "Function" { + if o := v.object(); o != nil && o.class == classFunctionName { return reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value { l := make([]interface{}, len(args)) for i, a := range args { @@ -459,53 +530,32 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu return nil } - return []reflect.Value{self.convertCallParameter(rv, t.Out(0))} - }) + r, err := rt.convertCallParameter(rv, t.Out(0)) + if err != nil { + panic(rt.panicTypeError("convertCallParameter Func: %s", err)) + } + + return []reflect.Value{r} + }), nil } case reflect.Struct: - if o := v._object(); o != nil && o.class == "Object" { + if o := v.object(); o != nil && o.class == classObjectName { s := reflect.New(t) for _, k := range o.propertyOrder { - var f *reflect.StructField - - for i := 0; i < t.NumField(); i++ { - ff := t.Field(i) - - if j := ff.Tag.Get("json"); j != "" { - if j == "-" { - continue - } - - a := strings.Split(j, ",") - - if a[0] == k { - f = &ff - break - } - } - - if ff.Name == k { - f = &ff - break - } - - if strings.EqualFold(ff.Name, k) { - f = &ff - } - } + idx := fieldIndexByName(t, k) - if f == nil { - panic(self.panicTypeError("can't convert object; field %q was supplied but does not exist on target %v", k, t)) + if idx == nil { + return reflect.Zero(t), fmt.Errorf("can't convert property %q of %s: field does not exist", k, t) } ss := s - for _, i := range f.Index { + for _, i := range idx { if ss.Kind() == reflect.Ptr { if ss.IsNil() { if !ss.CanSet() { - panic(self.panicTypeError("can't set embedded pointer to unexported struct: %v", ss.Type().Elem())) + return reflect.Zero(t), fmt.Errorf("can't convert property %q of %s: %s is unexported", k, t, ss.Type().Elem()) } ss.Set(reflect.New(ss.Type().Elem())) @@ -517,42 +567,48 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu ss = ss.Field(i) } - ss.Set(self.convertCallParameter(o.get(k), ss.Type())) + v, err := rt.convertCallParameter(o.get(k), ss.Type()) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %w", k, t, err) + } + + ss.Set(v) } - return s.Elem() + return s.Elem(), nil } } if tk == reflect.String { - if o := v._object(); o != nil && o.hasProperty("toString") { + if o := v.object(); o != nil && o.hasProperty("toString") { if fn := o.get("toString"); fn.IsFunction() { sv, err := fn.Call(v) if err != nil { - panic(err) + return reflect.Zero(t), fmt.Errorf("couldn't call toString: %w", err) } - var r reflect.Value - if err := catchPanic(func() { r = self.convertCallParameter(sv, t) }); err == nil { - return r + r, err := rt.convertCallParameter(sv, t) + if err != nil { + return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %w", err) } + return r, nil } } - return reflect.ValueOf(v.String()) + return reflect.ValueOf(v.String()), nil } if v.kind == valueString { var s encoding.TextUnmarshaler - if reflect.PtrTo(t).Implements(reflect.TypeOf(&s).Elem()) { + if reflect.PointerTo(t).Implements(reflect.TypeOf(&s).Elem()) { r := reflect.New(t) if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil { - panic(self.panicSyntaxError("can't convert to %s: %s", t.String(), err.Error())) + return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %w", t.String(), err) } - return r.Elem() + return r.Elem(), nil } } @@ -572,10 +628,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu s = v.Class() } - panic(self.panicTypeError("can't convert from %q to %q", s, t.String())) + return reflect.Zero(t), fmt.Errorf("can't convert from %q to %q", s, t) } -func (self *_runtime) toValue(value interface{}) Value { +func (rt *runtime) toValue(value interface{}) Value { + rv, ok := value.(reflect.Value) + if ok { + value = rv.Interface() + } + switch value := value.(type) { case Value: return value @@ -583,165 +644,171 @@ func (self *_runtime) toValue(value interface{}) Value { var name, file string var line int pc := reflect.ValueOf(value).Pointer() - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) if fn != nil { name = fn.Name() file, line = fn.FileLine(pc) file = path.Base(file) } - return toValue_object(self.newNativeFunction(name, file, line, value)) - case _nativeFunction: + return objectValue(rt.newNativeFunction(name, file, line, value)) + case nativeFunction: var name, file string var line int pc := reflect.ValueOf(value).Pointer() - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) if fn != nil { name = fn.Name() file, line = fn.FileLine(pc) file = path.Base(file) } - return toValue_object(self.newNativeFunction(name, file, line, value)) - case Object, *Object, _object, *_object: + return objectValue(rt.newNativeFunction(name, file, line, value)) + case Object, *Object, object, *object: // Nothing happens. // FIXME We should really figure out what can come here. // This catch-all is ugly. default: - { - value := reflect.ValueOf(value) - - switch value.Kind() { - case reflect.Ptr: - switch reflect.Indirect(value).Kind() { - case reflect.Struct: - return toValue_object(self.newGoStructObject(value)) - case reflect.Array: - return toValue_object(self.newGoArray(value)) - } + val := reflect.ValueOf(value) + if ok && val.Kind() == rv.Kind() { + // Use passed in rv which may be writable. + val = rv + } + + switch val.Kind() { + case reflect.Ptr: + switch reflect.Indirect(val).Kind() { case reflect.Struct: - return toValue_object(self.newGoStructObject(value)) - case reflect.Map: - return toValue_object(self.newGoMapObject(value)) - case reflect.Slice: - return toValue_object(self.newGoSlice(value)) + return objectValue(rt.newGoStructObject(val)) case reflect.Array: - return toValue_object(self.newGoArray(value)) - case reflect.Func: - var name, file string - var line int - if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr { - pc := v.Pointer() - fn := runtime.FuncForPC(pc) - if fn != nil { - name = fn.Name() - file, line = fn.FileLine(pc) - file = path.Base(file) - } + return objectValue(rt.newGoArray(val)) + } + case reflect.Struct: + return objectValue(rt.newGoStructObject(val)) + case reflect.Map: + return objectValue(rt.newGoMapObject(val)) + case reflect.Slice: + return objectValue(rt.newGoSlice(val)) + case reflect.Array: + return objectValue(rt.newGoArray(val)) + case reflect.Func: + var name, file string + var line int + if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr { + pc := v.Pointer() + fn := goruntime.FuncForPC(pc) + if fn != nil { + name = fn.Name() + file, line = fn.FileLine(pc) + file = path.Base(file) } + } - typ := value.Type() + typ := val.Type() - return toValue_object(self.newNativeFunction(name, file, line, func(c FunctionCall) Value { - nargs := typ.NumIn() + return objectValue(rt.newNativeFunction(name, file, line, func(c FunctionCall) Value { + nargs := typ.NumIn() - if len(c.ArgumentList) != nargs { - if typ.IsVariadic() { - if len(c.ArgumentList) < nargs-1 { - panic(self.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList)))) - } - } else { - panic(self.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList)))) + if len(c.ArgumentList) != nargs { + if typ.IsVariadic() { + if len(c.ArgumentList) < nargs-1 { + panic(rt.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList)))) } + } else { + panic(rt.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList)))) } + } - in := make([]reflect.Value, len(c.ArgumentList)) + in := make([]reflect.Value, len(c.ArgumentList)) - callSlice := false + callSlice := false - for i, a := range c.ArgumentList { - var t reflect.Type + for i, a := range c.ArgumentList { + var t reflect.Type - n := i - if n >= nargs-1 && typ.IsVariadic() { - if n > nargs-1 { - n = nargs - 1 - } - - t = typ.In(n).Elem() - } else { - t = typ.In(n) + n := i + if n >= nargs-1 && typ.IsVariadic() { + if n > nargs-1 { + n = nargs - 1 } - // if this is a variadic Go function, and the caller has supplied - // exactly the number of JavaScript arguments required, and this - // is the last JavaScript argument, try treating the it as the - // actual set of variadic Go arguments. if that succeeds, break - // out of the loop. - if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 { - var v reflect.Value - if err := catchPanic(func() { v = self.convertCallParameter(a, typ.In(n)) }); err == nil { - in[i] = v - callSlice = true - break - } - } + t = typ.In(n).Elem() + } else { + t = typ.In(n) + } - in[i] = self.convertCallParameter(a, t) + // if this is a variadic Go function, and the caller has supplied + // exactly the number of JavaScript arguments required, and this + // is the last JavaScript argument, try treating the it as the + // actual set of variadic Go arguments. if that succeeds, break + // out of the loop. + if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 { + if v, err := rt.convertCallParameter(a, typ.In(n)); err == nil { + in[i] = v + callSlice = true + break + } } - var out []reflect.Value - if callSlice { - out = value.CallSlice(in) - } else { - out = value.Call(in) + v, err := rt.convertCallParameter(a, t) + if err != nil { + panic(rt.panicTypeError(err.Error())) } - switch len(out) { - case 0: - return Value{} - case 1: - return self.toValue(out[0].Interface()) - default: - s := make([]interface{}, len(out)) - for i, v := range out { - s[i] = self.toValue(v.Interface()) - } + in[i] = v + } - return self.toValue(s) + var out []reflect.Value + if callSlice { + out = val.CallSlice(in) + } else { + out = val.Call(in) + } + + switch len(out) { + case 0: + return Value{} + case 1: + return rt.toValue(out[0].Interface()) + default: + s := make([]interface{}, len(out)) + for i, v := range out { + s[i] = rt.toValue(v.Interface()) } - })) - } + + return rt.toValue(s) + } + })) } } return toValue(value) } -func (runtime *_runtime) newGoSlice(value reflect.Value) *_object { - self := runtime.newGoSliceObject(value) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newGoSlice(value reflect.Value) *object { + obj := rt.newGoSliceObject(value) + obj.prototype = rt.global.ArrayPrototype + return obj } -func (runtime *_runtime) newGoArray(value reflect.Value) *_object { - self := runtime.newGoArrayObject(value) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newGoArray(value reflect.Value) *object { + obj := rt.newGoArrayObject(value) + obj.prototype = rt.global.ArrayPrototype + return obj } -func (runtime *_runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) { +func (rt *runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) { return parser.ParseFileWithSourceMap(nil, filename, src, sm, 0) } -func (runtime *_runtime) cmpl_parse(filename string, src, sm interface{}) (*_nodeProgram, error) { +func (rt *runtime) cmplParse(filename string, src, sm interface{}) (*nodeProgram, error) { program, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0) if err != nil { return nil, err } - return cmpl_parse(program), nil + return cmplParse(program), nil } -func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Program, error) { +func (rt *runtime) parseSource(src, sm interface{}) (*nodeProgram, *ast.Program, error) { switch src := src.(type) { case *ast.Program: return nil, src, nil @@ -749,22 +816,22 @@ func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Prog return src.program, nil, nil } - program, err := self.parse("", src, sm) + program, err := rt.parse("", src, sm) return nil, program, err } -func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, error) { +func (rt *runtime) cmplRunOrEval(src, sm interface{}, eval bool) (Value, error) { result := Value{} - cmpl_program, program, err := self.parseSource(src, sm) + node, program, err := rt.parseSource(src, sm) if err != nil { return result, err } - if cmpl_program == nil { - cmpl_program = cmpl_parse(program) + if node == nil { + node = cmplParse(program) } err = catchPanic(func() { - result = self.cmpl_evaluate_nodeProgram(cmpl_program, eval) + result = rt.cmplEvaluateNodeProgram(node, eval) }) switch result.kind { case valueEmpty: @@ -775,33 +842,32 @@ func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, err return result, err } -func (self *_runtime) cmpl_run(src, sm interface{}) (Value, error) { - return self.cmpl_runOrEval(src, sm, false) +func (rt *runtime) cmplRun(src, sm interface{}) (Value, error) { + return rt.cmplRunOrEval(src, sm, false) } -func (self *_runtime) cmpl_eval(src, sm interface{}) (Value, error) { - return self.cmpl_runOrEval(src, sm, true) +func (rt *runtime) cmplEval(src, sm interface{}) (Value, error) { + return rt.cmplRunOrEval(src, sm, true) } -func (self *_runtime) parseThrow(err error) { +func (rt *runtime) parseThrow(err error) { if err == nil { return } - switch err := err.(type) { - case parser.ErrorList: - { - err := err[0] - if err.Message == "Invalid left-hand side in assignment" { - panic(self.panicReferenceError(err.Message)) - } - panic(self.panicSyntaxError(err.Message)) + + var errl parser.ErrorList + if errors.Is(err, &errl) { + err := errl[0] + if err.Message == "invalid left-hand side in assignment" { + panic(rt.panicReferenceError(err.Message)) } + panic(rt.panicSyntaxError(err.Message)) } - panic(self.panicSyntaxError(err.Error())) + panic(rt.panicSyntaxError(err.Error())) } -func (self *_runtime) cmpl_parseOrThrow(src, sm interface{}) *_nodeProgram { - program, err := self.cmpl_parse("", src, sm) - self.parseThrow(err) // Will panic/throw appropriately +func (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram { + program, err := rt.cmplParse("", src, sm) + rt.parseThrow(err) // Will panic/throw appropriately return program } diff --git a/vendor/github.com/robertkrimen/otto/scope.go b/vendor/github.com/robertkrimen/otto/scope.go index 465e6b98c..c535c3166 100644 --- a/vendor/github.com/robertkrimen/otto/scope.go +++ b/vendor/github.com/robertkrimen/otto/scope.go @@ -1,33 +1,18 @@ package otto -// _scope: -// entryFile -// entryIdx -// top? -// outer => nil - -// _stash: -// lexical -// variable -// -// _thisStash (ObjectEnvironment) -// _fnStash -// _dclStash - -// An ECMA-262 ExecutionContext -type _scope struct { - lexical _stash - variable _stash - this *_object - eval bool // Replace this with kind? - outer *_scope +// An ECMA-262 ExecutionContext. +type scope struct { + lexical stasher + variable stasher + this *object + outer *scope + frame frame depth int - - frame _frame + eval bool } -func newScope(lexical _stash, variable _stash, this *_object) *_scope { - return &_scope{ +func newScope(lexical stasher, variable stasher, this *object) *scope { + return &scope{ lexical: lexical, variable: variable, this: this, diff --git a/vendor/github.com/robertkrimen/otto/script.go b/vendor/github.com/robertkrimen/otto/script.go index 2ae890ecd..077a916df 100644 --- a/vendor/github.com/robertkrimen/otto/script.go +++ b/vendor/github.com/robertkrimen/otto/script.go @@ -6,16 +6,16 @@ import ( "errors" ) +// ErrVersion is an error which represents a version mismatch. var ErrVersion = errors.New("version mismatch") var scriptVersion = "2014-04-13/1" // Script is a handle for some (reusable) JavaScript. // Passing a Script value to a run method will evaluate the JavaScript. -// type Script struct { version string - program *_nodeProgram + program *nodeProgram filename string src string } @@ -23,26 +23,24 @@ type Script struct { // Compile will parse the given source and return a Script value or nil and // an error if there was a problem during compilation. // -// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) -// vm.Run(script) -// -func (self *Otto) Compile(filename string, src interface{}) (*Script, error) { - return self.CompileWithSourceMap(filename, src, nil) +// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) +// vm.Run(script) +func (o *Otto) Compile(filename string, src interface{}) (*Script, error) { + return o.CompileWithSourceMap(filename, src, nil) } // CompileWithSourceMap does the same thing as Compile, but with the obvious // difference of applying a source map. -func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) { - program, err := self.runtime.parse(filename, src, sm) +func (o *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) { + program, err := o.runtime.parse(filename, src, sm) if err != nil { return nil, err } - cmpl_program := cmpl_parse(program) - + node := cmplParse(program) script := &Script{ version: scriptVersion, - program: cmpl_program, + program: node, filename: filename, src: program.File.Source(), } @@ -50,31 +48,30 @@ func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*S return script, nil } -func (self *Script) String() string { - return "// " + self.filename + "\n" + self.src +func (s *Script) String() string { + return "// " + s.filename + "\n" + s.src } // MarshalBinary will marshal a script into a binary form. A marshalled script // that is later unmarshalled can be executed on the same version of the otto runtime. // // The binary format can change at any time and should be considered unspecified and opaque. -// -func (self *Script) marshalBinary() ([]byte, error) { +func (s *Script) marshalBinary() ([]byte, error) { var bfr bytes.Buffer encoder := gob.NewEncoder(&bfr) - err := encoder.Encode(self.version) + err := encoder.Encode(s.version) if err != nil { return nil, err } - err = encoder.Encode(self.program) + err = encoder.Encode(s.program) if err != nil { return nil, err } - err = encoder.Encode(self.filename) + err = encoder.Encode(s.filename) if err != nil { return nil, err } - err = encoder.Encode(self.src) + err = encoder.Encode(s.src) if err != nil { return nil, err } @@ -86,34 +83,27 @@ func (self *Script) marshalBinary() ([]byte, error) { // will return an error. // // The binary format can change at any time and should be considered unspecified and opaque. -// -func (self *Script) unmarshalBinary(data []byte) error { +func (s *Script) unmarshalBinary(data []byte) (err error) { //nolint:nonamedreturns decoder := gob.NewDecoder(bytes.NewReader(data)) - err := decoder.Decode(&self.version) - if err != nil { - goto error + defer func() { + if err != nil { + s.version = "" + s.program = nil + s.filename = "" + s.src = "" + } + }() + if err = decoder.Decode(&s.version); err != nil { + return err } - if self.version != scriptVersion { - err = ErrVersion - goto error + if s.version != scriptVersion { + return ErrVersion } - err = decoder.Decode(&self.program) - if err != nil { - goto error + if err = decoder.Decode(&s.program); err != nil { + return err } - err = decoder.Decode(&self.filename) - if err != nil { - goto error - } - err = decoder.Decode(&self.src) - if err != nil { - goto error + if err = decoder.Decode(&s.filename); err != nil { + return err } - return nil -error: - self.version = "" - self.program = nil - self.filename = "" - self.src = "" - return err + return decoder.Decode(&s.src) } diff --git a/vendor/github.com/robertkrimen/otto/stash.go b/vendor/github.com/robertkrimen/otto/stash.go index 0d3ffa511..85ee26d81 100644 --- a/vendor/github.com/robertkrimen/otto/stash.go +++ b/vendor/github.com/robertkrimen/otto/stash.go @@ -4,172 +4,160 @@ import ( "fmt" ) -// ====== -// _stash -// ====== +// stasher is implemented by types which can stash data. +type stasher interface { + hasBinding(name string) bool // + createBinding(name string, deletable bool, value Value) // CreateMutableBinding + setBinding(name string, value Value, strict bool) // SetMutableBinding + getBinding(name string, throw bool) Value // GetBindingValue + deleteBinding(name string) bool // + setValue(name string, value Value, throw bool) // createBinding + setBinding -type _stash interface { - hasBinding(string) bool // - createBinding(string, bool, Value) // CreateMutableBinding - setBinding(string, Value, bool) // SetMutableBinding - getBinding(string, bool) Value // GetBindingValue - deleteBinding(string) bool // - setValue(string, Value, bool) // createBinding + setBinding + outer() stasher + runtime() *runtime - outer() _stash - runtime() *_runtime + newReference(name string, strict bool, atv at) referencer - newReference(string, bool, _at) _reference - - clone(clone *_clone) _stash + clone(cloner *cloner) stasher } -// ========== -// _objectStash -// ========== - -type _objectStash struct { - _runtime *_runtime - _outer _stash - object *_object +type objectStash struct { + rt *runtime + outr stasher + object *object } -func (self *_objectStash) runtime() *_runtime { - return self._runtime +func (s *objectStash) runtime() *runtime { + return s.rt } -func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash { - if object == nil { - object = runtime.newBaseObject() - object.class = "environment" +func (rt *runtime) newObjectStash(obj *object, outer stasher) *objectStash { + if obj == nil { + obj = rt.newBaseObject() + obj.class = "environment" } - return &_objectStash{ - _runtime: runtime, - _outer: outer, - object: object, + return &objectStash{ + rt: rt, + outr: outer, + object: obj, } } -func (in *_objectStash) clone(clone *_clone) _stash { - out, exists := clone.objectStash(in) +func (s *objectStash) clone(c *cloner) stasher { + out, exists := c.objectStash(s) if exists { return out } - *out = _objectStash{ - clone.runtime, - clone.stash(in._outer), - clone.object(in.object), + *out = objectStash{ + c.runtime, + c.stash(s.outr), + c.object(s.object), } return out } -func (self *_objectStash) hasBinding(name string) bool { - return self.object.hasProperty(name) +func (s *objectStash) hasBinding(name string) bool { + return s.object.hasProperty(name) } -func (self *_objectStash) createBinding(name string, deletable bool, value Value) { - if self.object.hasProperty(name) { +func (s *objectStash) createBinding(name string, deletable bool, value Value) { + if s.object.hasProperty(name) { panic(hereBeDragons()) } - mode := _propertyMode(0111) + mode := propertyMode(0o111) if !deletable { - mode = _propertyMode(0110) + mode = propertyMode(0o110) } // TODO False? - self.object.defineProperty(name, value, mode, false) + s.object.defineProperty(name, value, mode, false) } -func (self *_objectStash) setBinding(name string, value Value, strict bool) { - self.object.put(name, value, strict) +func (s *objectStash) setBinding(name string, value Value, strict bool) { + s.object.put(name, value, strict) } -func (self *_objectStash) setValue(name string, value Value, throw bool) { - if !self.hasBinding(name) { - self.createBinding(name, true, value) // Configurable by default +func (s *objectStash) setValue(name string, value Value, throw bool) { + if !s.hasBinding(name) { + s.createBinding(name, true, value) // Configurable by default } else { - self.setBinding(name, value, throw) + s.setBinding(name, value, throw) } } -func (self *_objectStash) getBinding(name string, throw bool) Value { - if self.object.hasProperty(name) { - return self.object.get(name) +func (s *objectStash) getBinding(name string, throw bool) Value { + if s.object.hasProperty(name) { + return s.object.get(name) } if throw { // strict? - panic(self._runtime.panicReferenceError("Not Defined", name)) + panic(s.rt.panicReferenceError("Not Defined", name)) } return Value{} } -func (self *_objectStash) deleteBinding(name string) bool { - return self.object.delete(name, false) +func (s *objectStash) deleteBinding(name string) bool { + return s.object.delete(name, false) } -func (self *_objectStash) outer() _stash { - return self._outer +func (s *objectStash) outer() stasher { + return s.outr } -func (self *_objectStash) newReference(name string, strict bool, at _at) _reference { - return newPropertyReference(self._runtime, self.object, name, strict, at) +func (s *objectStash) newReference(name string, strict bool, atv at) referencer { + return newPropertyReference(s.rt, s.object, name, strict, atv) } -// ========= -// _dclStash -// ========= - -type _dclStash struct { - _runtime *_runtime - _outer _stash - property map[string]_dclProperty +type dclStash struct { + rt *runtime + outr stasher + property map[string]dclProperty } -type _dclProperty struct { +type dclProperty struct { value Value mutable bool deletable bool readable bool } -func (runtime *_runtime) newDeclarationStash(outer _stash) *_dclStash { - return &_dclStash{ - _runtime: runtime, - _outer: outer, - property: map[string]_dclProperty{}, +func (rt *runtime) newDeclarationStash(outer stasher) *dclStash { + return &dclStash{ + rt: rt, + outr: outer, + property: map[string]dclProperty{}, } } -func (in *_dclStash) clone(clone *_clone) _stash { - out, exists := clone.dclStash(in) +func (s *dclStash) clone(c *cloner) stasher { + out, exists := c.dclStash(s) if exists { return out } - property := make(map[string]_dclProperty, len(in.property)) - for index, value := range in.property { - property[index] = clone.dclProperty(value) + prop := make(map[string]dclProperty, len(s.property)) + for index, value := range s.property { + prop[index] = c.dclProperty(value) } - *out = _dclStash{ - clone.runtime, - clone.stash(in._outer), - property, + *out = dclStash{ + c.runtime, + c.stash(s.outr), + prop, } return out } -func (self *_dclStash) hasBinding(name string) bool { - _, exists := self.property[name] +func (s *dclStash) hasBinding(name string) bool { + _, exists := s.property[name] return exists } -func (self *_dclStash) runtime() *_runtime { - return self._runtime +func (s *dclStash) runtime() *runtime { + return s.rt } -func (self *_dclStash) createBinding(name string, deletable bool, value Value) { - _, exists := self.property[name] - if exists { +func (s *dclStash) createBinding(name string, deletable bool, value Value) { + if _, exists := s.property[name]; exists { panic(fmt.Errorf("createBinding: %s: already exists", name)) } - self.property[name] = _dclProperty{ + s.property[name] = dclProperty{ value: value, mutable: true, deletable: deletable, @@ -177,62 +165,62 @@ func (self *_dclStash) createBinding(name string, deletable bool, value Value) { } } -func (self *_dclStash) setBinding(name string, value Value, strict bool) { - property, exists := self.property[name] +func (s *dclStash) setBinding(name string, value Value, strict bool) { + prop, exists := s.property[name] if !exists { panic(fmt.Errorf("setBinding: %s: missing", name)) } - if property.mutable { - property.value = value - self.property[name] = property + if prop.mutable { + prop.value = value + s.property[name] = prop } else { - self._runtime.typeErrorResult(strict) + s.rt.typeErrorResult(strict) } } -func (self *_dclStash) setValue(name string, value Value, throw bool) { - if !self.hasBinding(name) { - self.createBinding(name, false, value) // NOT deletable by default +func (s *dclStash) setValue(name string, value Value, throw bool) { + if !s.hasBinding(name) { + s.createBinding(name, false, value) // NOT deletable by default } else { - self.setBinding(name, value, throw) + s.setBinding(name, value, throw) } } -// FIXME This is called a __lot__ -func (self *_dclStash) getBinding(name string, throw bool) Value { - property, exists := self.property[name] +// FIXME This is called a __lot__. +func (s *dclStash) getBinding(name string, throw bool) Value { + prop, exists := s.property[name] if !exists { panic(fmt.Errorf("getBinding: %s: missing", name)) } - if !property.mutable && !property.readable { + if !prop.mutable && !prop.readable { if throw { // strict? - panic(self._runtime.panicTypeError()) + panic(s.rt.panicTypeError("getBinding property %s not mutable and not readable", name)) } return Value{} } - return property.value + return prop.value } -func (self *_dclStash) deleteBinding(name string) bool { - property, exists := self.property[name] +func (s *dclStash) deleteBinding(name string) bool { + prop, exists := s.property[name] if !exists { return true } - if !property.deletable { + if !prop.deletable { return false } - delete(self.property, name) + delete(s.property, name) return true } -func (self *_dclStash) outer() _stash { - return self._outer +func (s *dclStash) outer() stasher { + return s.outr } -func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference { - return &_stashReference{ +func (s *dclStash) newReference(name string, strict bool, _ at) referencer { + return &stashReference{ name: name, - base: self, + base: s, } } @@ -240,57 +228,62 @@ func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference // _fnStash // ======== -type _fnStash struct { - _dclStash - arguments *_object +type fnStash struct { + dclStash + arguments *object indexOfArgumentName map[string]string } -func (runtime *_runtime) newFunctionStash(outer _stash) *_fnStash { - return &_fnStash{ - _dclStash: _dclStash{ - _runtime: runtime, - _outer: outer, - property: map[string]_dclProperty{}, +func (rt *runtime) newFunctionStash(outer stasher) *fnStash { + return &fnStash{ + dclStash: dclStash{ + rt: rt, + outr: outer, + property: map[string]dclProperty{}, }, } } -func (in *_fnStash) clone(clone *_clone) _stash { - out, exists := clone.fnStash(in) +func (s *fnStash) clone(c *cloner) stasher { + out, exists := c.fnStash(s) if exists { return out } - dclStash := in._dclStash.clone(clone).(*_dclStash) - index := make(map[string]string, len(in.indexOfArgumentName)) - for name, value := range in.indexOfArgumentName { + dclStash := s.dclStash.clone(c).(*dclStash) + index := make(map[string]string, len(s.indexOfArgumentName)) + for name, value := range s.indexOfArgumentName { index[name] = value } - *out = _fnStash{ - _dclStash: *dclStash, - arguments: clone.object(in.arguments), + *out = fnStash{ + dclStash: *dclStash, + arguments: c.object(s.arguments), indexOfArgumentName: index, } return out } -func getStashProperties(stash _stash) (keys []string) { +// getStashProperties returns the properties from stash. +func getStashProperties(stash stasher) []string { switch vars := stash.(type) { - case *_dclStash: + case *dclStash: + keys := make([]string, 0, len(vars.property)) for k := range vars.property { keys = append(keys, k) } - case *_fnStash: + return keys + case *fnStash: + keys := make([]string, 0, len(vars.property)) for k := range vars.property { keys = append(keys, k) } - case *_objectStash: + return keys + case *objectStash: + keys := make([]string, 0, len(vars.object.property)) for k := range vars.object.property { keys = append(keys, k) } + return keys default: panic("unknown stash type") } - - return } diff --git a/vendor/github.com/robertkrimen/otto/token/Makefile b/vendor/github.com/robertkrimen/otto/token/Makefile deleted file mode 100644 index 1e85c7348..000000000 --- a/vendor/github.com/robertkrimen/otto/token/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -token_const.go: tokenfmt - ./$^ | gofmt > $@ diff --git a/vendor/github.com/robertkrimen/otto/token/README.markdown b/vendor/github.com/robertkrimen/otto/token/README.markdown deleted file mode 100644 index ff3b16104..000000000 --- a/vendor/github.com/robertkrimen/otto/token/README.markdown +++ /dev/null @@ -1,171 +0,0 @@ -# token --- - import "github.com/robertkrimen/otto/token" - -Package token defines constants representing the lexical tokens of JavaScript -(ECMA5). - -## Usage - -```go -const ( - ILLEGAL - EOF - COMMENT - KEYWORD - - STRING - BOOLEAN - NULL - NUMBER - IDENTIFIER - - PLUS // + - MINUS // - - MULTIPLY // * - SLASH // / - REMAINDER // % - - AND // & - OR // | - EXCLUSIVE_OR // ^ - SHIFT_LEFT // << - SHIFT_RIGHT // >> - UNSIGNED_SHIFT_RIGHT // >>> - AND_NOT // &^ - - ADD_ASSIGN // += - SUBTRACT_ASSIGN // -= - MULTIPLY_ASSIGN // *= - QUOTIENT_ASSIGN // /= - REMAINDER_ASSIGN // %= - - AND_ASSIGN // &= - OR_ASSIGN // |= - EXCLUSIVE_OR_ASSIGN // ^= - SHIFT_LEFT_ASSIGN // <<= - SHIFT_RIGHT_ASSIGN // >>= - UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>= - AND_NOT_ASSIGN // &^= - - LOGICAL_AND // && - LOGICAL_OR // || - INCREMENT // ++ - DECREMENT // -- - - EQUAL // == - STRICT_EQUAL // === - LESS // < - GREATER // > - ASSIGN // = - NOT // ! - - BITWISE_NOT // ~ - - NOT_EQUAL // != - STRICT_NOT_EQUAL // !== - LESS_OR_EQUAL // <= - GREATER_OR_EQUAL // >= - - LEFT_PARENTHESIS // ( - LEFT_BRACKET // [ - LEFT_BRACE // { - COMMA // , - PERIOD // . - - RIGHT_PARENTHESIS // ) - RIGHT_BRACKET // ] - RIGHT_BRACE // } - SEMICOLON // ; - COLON // : - QUESTION_MARK // ? - - IF - IN - DO - - VAR - FOR - NEW - TRY - - THIS - ELSE - CASE - VOID - WITH - - WHILE - BREAK - CATCH - THROW - - RETURN - TYPEOF - DELETE - SWITCH - - DEFAULT - FINALLY - - FUNCTION - CONTINUE - DEBUGGER - - INSTANCEOF -) -``` - -#### type Token - -```go -type Token int -``` - -Token is the set of lexical tokens in JavaScript (ECMA5). - -#### func IsKeyword - -```go -func IsKeyword(literal string) (Token, bool) -``` -IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token if -the literal is a future keyword (const, let, class, super, ...), or 0 if the -literal is not a keyword. - -If the literal is a keyword, IsKeyword returns a second value indicating if the -literal is considered a future keyword in strict-mode only. - -7.6.1.2 Future Reserved Words: - - const - class - enum - export - extends - import - super - -7.6.1.2 Future Reserved Words (strict): - - implements - interface - let - package - private - protected - public - static - -#### func (Token) String - -```go -func (tkn Token) String() string -``` -String returns the string corresponding to the token. For operators, delimiters, -and keywords the string is the actual token string (e.g., for the token PLUS, -the String() is "+"). For all other tokens the string corresponds to the token -name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER"). - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/token/generate.go b/vendor/github.com/robertkrimen/otto/token/generate.go new file mode 100644 index 000000000..3c02aee75 --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/token/generate.go @@ -0,0 +1,3 @@ +package token + +//go:generate go run ../tools/gen-tokens -output token_const.go diff --git a/vendor/github.com/robertkrimen/otto/token/token.go b/vendor/github.com/robertkrimen/otto/token/token.go index 0e941ac96..9fee9e1ef 100644 --- a/vendor/github.com/robertkrimen/otto/token/token.go +++ b/vendor/github.com/robertkrimen/otto/token/token.go @@ -13,66 +13,18 @@ type Token int // token string (e.g., for the token PLUS, the String() is // "+"). For all other tokens the string corresponds to the token // name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER"). -// func (tkn Token) String() string { - if 0 == tkn { + switch { + case tkn == 0: return "UNKNOWN" - } - if tkn < Token(len(token2string)) { + case tkn < Token(len(token2string)): return token2string[tkn] + default: + return "token(" + strconv.Itoa(int(tkn)) + ")" } - return "token(" + strconv.Itoa(int(tkn)) + ")" -} - -// This is not used for anything -func (tkn Token) precedence(in bool) int { - - switch tkn { - case LOGICAL_OR: - return 1 - - case LOGICAL_AND: - return 2 - - case OR, OR_ASSIGN: - return 3 - - case EXCLUSIVE_OR: - return 4 - - case AND, AND_ASSIGN, AND_NOT, AND_NOT_ASSIGN: - return 5 - - case EQUAL, - NOT_EQUAL, - STRICT_EQUAL, - STRICT_NOT_EQUAL: - return 6 - - case LESS, GREATER, LESS_OR_EQUAL, GREATER_OR_EQUAL, INSTANCEOF: - return 7 - - case IN: - if in { - return 7 - } - return 0 - - case SHIFT_LEFT, SHIFT_RIGHT, UNSIGNED_SHIFT_RIGHT: - fallthrough - case SHIFT_LEFT_ASSIGN, SHIFT_RIGHT_ASSIGN, UNSIGNED_SHIFT_RIGHT_ASSIGN: - return 8 - - case PLUS, MINUS, ADD_ASSIGN, SUBTRACT_ASSIGN: - return 9 - - case MULTIPLY, SLASH, REMAINDER, MULTIPLY_ASSIGN, QUOTIENT_ASSIGN, REMAINDER_ASSIGN: - return 11 - } - return 0 } -type _keyword struct { +type keyword struct { token Token futureKeyword bool strict bool @@ -86,31 +38,30 @@ type _keyword struct { // // 7.6.1.2 Future Reserved Words: // -// const -// class -// enum -// export -// extends -// import -// super +// const +// class +// enum +// export +// extends +// import +// super // // 7.6.1.2 Future Reserved Words (strict): // -// implements -// interface -// let -// package -// private -// protected -// public -// static -// +// implements +// interface +// let +// package +// private +// protected +// public +// static func IsKeyword(literal string) (Token, bool) { - if keyword, exists := keywordTable[literal]; exists { - if keyword.futureKeyword { - return KEYWORD, keyword.strict + if kw, exists := keywordTable[literal]; exists { + if kw.futureKeyword { + return KEYWORD, kw.strict } - return keyword.token, false + return kw.token, false } return 0, false } diff --git a/vendor/github.com/robertkrimen/otto/token/token_const.go b/vendor/github.com/robertkrimen/otto/token/token_const.go index b1d83c6de..09ba01781 100644 --- a/vendor/github.com/robertkrimen/otto/token/token_const.go +++ b/vendor/github.com/robertkrimen/otto/token/token_const.go @@ -1,25 +1,28 @@ +// Code generated by tools/gen-tokens. DO NOT EDIT. + package token const ( _ Token = iota + // Control. ILLEGAL EOF COMMENT KEYWORD - + // Types. STRING BOOLEAN NULL NUMBER IDENTIFIER - + // Maths. PLUS // + MINUS // - MULTIPLY // * SLASH // / REMAINDER // % - + // Logical and bitwise operators. AND // & OR // | EXCLUSIVE_OR // ^ @@ -27,13 +30,13 @@ const ( SHIFT_RIGHT // >> UNSIGNED_SHIFT_RIGHT // >>> AND_NOT // &^ - + // Math assignments. ADD_ASSIGN // += SUBTRACT_ASSIGN // -= MULTIPLY_ASSIGN // *= QUOTIENT_ASSIGN // /= REMAINDER_ASSIGN // %= - + // Math and bitwise assignments. AND_ASSIGN // &= OR_ASSIGN // |= EXCLUSIVE_OR_ASSIGN // ^= @@ -41,74 +44,73 @@ const ( SHIFT_RIGHT_ASSIGN // >>= UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>= AND_NOT_ASSIGN // &^= - + // Logical operators and decrement / increment. LOGICAL_AND // && LOGICAL_OR // || INCREMENT // ++ DECREMENT // -- - + // Comparison operators. EQUAL // == STRICT_EQUAL // === LESS // < GREATER // > ASSIGN // = NOT // ! - + // Bitwise not. BITWISE_NOT // ~ - + // Comparison operators. NOT_EQUAL // != STRICT_NOT_EQUAL // !== LESS_OR_EQUAL // <= GREATER_OR_EQUAL // >= - + // Left operators. LEFT_PARENTHESIS // ( LEFT_BRACKET // [ LEFT_BRACE // { COMMA // , PERIOD // . - + // Right operators. RIGHT_PARENTHESIS // ) RIGHT_BRACKET // ] RIGHT_BRACE // } SEMICOLON // ; COLON // : QUESTION_MARK // ? - - firstKeyword + // Basic flow - keywords below here. + _ IF IN DO - + // Declarations. VAR FOR NEW TRY - + // Advanced flow. THIS ELSE CASE VOID WITH - + // Loops. WHILE BREAK CATCH THROW - + // Functions. RETURN TYPEOF DELETE SWITCH - + // Fallback identifiers. DEFAULT FINALLY - + // Miscellaneous. FUNCTION CONTINUE DEBUGGER - + // Instance of. INSTANCEOF - lastKeyword ) var token2string = [...]string{ @@ -199,149 +201,149 @@ var token2string = [...]string{ INSTANCEOF: "instanceof", } -var keywordTable = map[string]_keyword{ - "if": _keyword{ +var keywordTable = map[string]keyword{ + "if": { token: IF, }, - "in": _keyword{ + "in": { token: IN, }, - "do": _keyword{ + "do": { token: DO, }, - "var": _keyword{ + "var": { token: VAR, }, - "for": _keyword{ + "for": { token: FOR, }, - "new": _keyword{ + "new": { token: NEW, }, - "try": _keyword{ + "try": { token: TRY, }, - "this": _keyword{ + "this": { token: THIS, }, - "else": _keyword{ + "else": { token: ELSE, }, - "case": _keyword{ + "case": { token: CASE, }, - "void": _keyword{ + "void": { token: VOID, }, - "with": _keyword{ + "with": { token: WITH, }, - "while": _keyword{ + "while": { token: WHILE, }, - "break": _keyword{ + "break": { token: BREAK, }, - "catch": _keyword{ + "catch": { token: CATCH, }, - "throw": _keyword{ + "throw": { token: THROW, }, - "return": _keyword{ + "return": { token: RETURN, }, - "typeof": _keyword{ + "typeof": { token: TYPEOF, }, - "delete": _keyword{ + "delete": { token: DELETE, }, - "switch": _keyword{ + "switch": { token: SWITCH, }, - "default": _keyword{ + "default": { token: DEFAULT, }, - "finally": _keyword{ + "finally": { token: FINALLY, }, - "function": _keyword{ + "function": { token: FUNCTION, }, - "continue": _keyword{ + "continue": { token: CONTINUE, }, - "debugger": _keyword{ + "debugger": { token: DEBUGGER, }, - "instanceof": _keyword{ + "instanceof": { token: INSTANCEOF, }, - "const": _keyword{ + "const": { token: KEYWORD, futureKeyword: true, }, - "class": _keyword{ + "class": { token: KEYWORD, futureKeyword: true, }, - "enum": _keyword{ + "enum": { token: KEYWORD, futureKeyword: true, }, - "export": _keyword{ + "export": { token: KEYWORD, futureKeyword: true, }, - "extends": _keyword{ + "extends": { token: KEYWORD, futureKeyword: true, }, - "import": _keyword{ + "import": { token: KEYWORD, futureKeyword: true, }, - "super": _keyword{ + "super": { token: KEYWORD, futureKeyword: true, }, - "implements": _keyword{ + "implements": { token: KEYWORD, futureKeyword: true, strict: true, }, - "interface": _keyword{ + "interface": { token: KEYWORD, futureKeyword: true, strict: true, }, - "let": _keyword{ + "let": { token: KEYWORD, futureKeyword: true, strict: true, }, - "package": _keyword{ + "package": { token: KEYWORD, futureKeyword: true, strict: true, }, - "private": _keyword{ + "private": { token: KEYWORD, futureKeyword: true, strict: true, }, - "protected": _keyword{ + "protected": { token: KEYWORD, futureKeyword: true, strict: true, }, - "public": _keyword{ + "public": { token: KEYWORD, futureKeyword: true, strict: true, }, - "static": _keyword{ + "static": { token: KEYWORD, futureKeyword: true, strict: true, diff --git a/vendor/github.com/robertkrimen/otto/token/tokenfmt b/vendor/github.com/robertkrimen/otto/token/tokenfmt deleted file mode 100644 index 63dd5d9e6..000000000 --- a/vendor/github.com/robertkrimen/otto/token/tokenfmt +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -my (%token, @order, @keywords); - -{ - my $keywords; - my @const; - push @const, <<_END_; -package token - -const( - _ Token = iota -_END_ - - for (split m/\n/, <<_END_) { -ILLEGAL -EOF -COMMENT -KEYWORD - -STRING -BOOLEAN -NULL -NUMBER -IDENTIFIER - -PLUS + -MINUS - -MULTIPLY * -SLASH / -REMAINDER % - -AND & -OR | -EXCLUSIVE_OR ^ -SHIFT_LEFT << -SHIFT_RIGHT >> -UNSIGNED_SHIFT_RIGHT >>> -AND_NOT &^ - -ADD_ASSIGN += -SUBTRACT_ASSIGN -= -MULTIPLY_ASSIGN *= -QUOTIENT_ASSIGN /= -REMAINDER_ASSIGN %= - -AND_ASSIGN &= -OR_ASSIGN |= -EXCLUSIVE_OR_ASSIGN ^= -SHIFT_LEFT_ASSIGN <<= -SHIFT_RIGHT_ASSIGN >>= -UNSIGNED_SHIFT_RIGHT_ASSIGN >>>= -AND_NOT_ASSIGN &^= - -LOGICAL_AND && -LOGICAL_OR || -INCREMENT ++ -DECREMENT -- - -EQUAL == -STRICT_EQUAL === -LESS < -GREATER > -ASSIGN = -NOT ! - -BITWISE_NOT ~ - -NOT_EQUAL != -STRICT_NOT_EQUAL !== -LESS_OR_EQUAL <= -GREATER_OR_EQUAL <= - -LEFT_PARENTHESIS ( -LEFT_BRACKET [ -LEFT_BRACE { -COMMA , -PERIOD . - -RIGHT_PARENTHESIS ) -RIGHT_BRACKET ] -RIGHT_BRACE } -SEMICOLON ; -COLON : -QUESTION_MARK ? - -firstKeyword -IF -IN -DO - -VAR -FOR -NEW -TRY - -THIS -ELSE -CASE -VOID -WITH - -WHILE -BREAK -CATCH -THROW - -RETURN -TYPEOF -DELETE -SWITCH - -DEFAULT -FINALLY - -FUNCTION -CONTINUE -DEBUGGER - -INSTANCEOF -lastKeyword -_END_ - chomp; - - next if m/^\s*#/; - - my ($name, $symbol) = m/(\w+)\s*(\S+)?/; - - if (defined $symbol) { - push @order, $name; - push @const, "$name // $symbol"; - $token{$name} = $symbol; - } elsif (defined $name) { - $keywords ||= $name eq 'firstKeyword'; - - push @const, $name; - #$const[-1] .= " Token = iota" if 2 == @const; - if ($name =~ m/^([A-Z]+)/) { - push @keywords, $name if $keywords; - push @order, $name; - if ($token{SEMICOLON}) { - $token{$name} = lc $1; - } else { - $token{$name} = $name; - } - } - } else { - push @const, ""; - } - - } - push @const, ")"; - print join "\n", @const, ""; -} - -{ - print <<_END_; - -var token2string = [...]string{ -_END_ - for my $name (@order) { - print "$name: \"$token{$name}\",\n"; - } - print <<_END_; -} -_END_ - - print <<_END_; - -var keywordTable = map[string]_keyword{ -_END_ - for my $name (@keywords) { - print <<_END_ - "@{[ lc $name ]}": _keyword{ - token: $name, - }, -_END_ - } - - for my $name (qw/ - const - class - enum - export - extends - import - super - /) { - print <<_END_ - "$name": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, -_END_ - } - - for my $name (qw/ - implements - interface - let - package - private - protected - public - static - /) { - print <<_END_ - "$name": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, -_END_ - } - - print <<_END_; -} -_END_ -} diff --git a/vendor/github.com/robertkrimen/otto/type_arguments.go b/vendor/github.com/robertkrimen/otto/type_arguments.go index 841d75855..7f2a83dc7 100644 --- a/vendor/github.com/robertkrimen/otto/type_arguments.go +++ b/vendor/github.com/robertkrimen/otto/type_arguments.go @@ -4,103 +4,97 @@ import ( "strconv" ) -func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, stash _stash, length int) *_object { - self := runtime.newClassObject("Arguments") +func (rt *runtime) newArgumentsObject(indexOfParameterName []string, stash stasher, length int) *object { + obj := rt.newClassObject("Arguments") - for index, _ := range indexOfParameterName { + for index := range indexOfParameterName { name := strconv.FormatInt(int64(index), 10) - objectDefineOwnProperty(self, name, _property{Value{}, 0111}, false) + objectDefineOwnProperty(obj, name, property{Value{}, 0o111}, false) } - self.objectClass = _classArguments - self.value = _argumentsObject{ + obj.objectClass = classArguments + obj.value = argumentsObject{ indexOfParameterName: indexOfParameterName, stash: stash, } - self.prototype = runtime.global.ObjectPrototype + obj.prototype = rt.global.ObjectPrototype - self.defineProperty("length", toValue_int(length), 0101, false) + obj.defineProperty(propertyLength, intValue(length), 0o101, false) - return self + return obj } -type _argumentsObject struct { +type argumentsObject struct { + stash stasher indexOfParameterName []string - // function(abc, def, ghi) - // indexOfParameterName[0] = "abc" - // indexOfParameterName[1] = "def" - // indexOfParameterName[2] = "ghi" - // ... - stash _stash } -func (in _argumentsObject) clone(clone *_clone) _argumentsObject { - indexOfParameterName := make([]string, len(in.indexOfParameterName)) - copy(indexOfParameterName, in.indexOfParameterName) - return _argumentsObject{ - indexOfParameterName, - clone.stash(in.stash), +func (o argumentsObject) clone(c *cloner) argumentsObject { + indexOfParameterName := make([]string, len(o.indexOfParameterName)) + copy(indexOfParameterName, o.indexOfParameterName) + return argumentsObject{ + indexOfParameterName: indexOfParameterName, + stash: c.stash(o.stash), } } -func (self _argumentsObject) get(name string) (Value, bool) { +func (o argumentsObject) get(name string) (Value, bool) { index := stringToArrayIndex(name) - if index >= 0 && index < int64(len(self.indexOfParameterName)) { - name := self.indexOfParameterName[index] - if name == "" { + if index >= 0 && index < int64(len(o.indexOfParameterName)) { + if name = o.indexOfParameterName[index]; name == "" { return Value{}, false } - return self.stash.getBinding(name, false), true + return o.stash.getBinding(name, false), true } return Value{}, false } -func (self _argumentsObject) put(name string, value Value) { +func (o argumentsObject) put(name string, value Value) { index := stringToArrayIndex(name) - name = self.indexOfParameterName[index] - self.stash.setBinding(name, value, false) + name = o.indexOfParameterName[index] + o.stash.setBinding(name, value, false) } -func (self _argumentsObject) delete(name string) { +func (o argumentsObject) delete(name string) { index := stringToArrayIndex(name) - self.indexOfParameterName[index] = "" + o.indexOfParameterName[index] = "" } -func argumentsGet(self *_object, name string) Value { - if value, exists := self.value.(_argumentsObject).get(name); exists { +func argumentsGet(obj *object, name string) Value { + if value, exists := obj.value.(argumentsObject).get(name); exists { return value } - return objectGet(self, name) + return objectGet(obj, name) } -func argumentsGetOwnProperty(self *_object, name string) *_property { - property := objectGetOwnProperty(self, name) - if value, exists := self.value.(_argumentsObject).get(name); exists { - property.value = value +func argumentsGetOwnProperty(obj *object, name string) *property { + prop := objectGetOwnProperty(obj, name) + if value, exists := obj.value.(argumentsObject).get(name); exists { + prop.value = value } - return property + return prop } -func argumentsDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - if _, exists := self.value.(_argumentsObject).get(name); exists { - if !objectDefineOwnProperty(self, name, descriptor, false) { - return self.runtime.typeErrorResult(throw) +func argumentsDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if _, exists := obj.value.(argumentsObject).get(name); exists { + if !objectDefineOwnProperty(obj, name, descriptor, false) { + return obj.runtime.typeErrorResult(throw) } if value, valid := descriptor.value.(Value); valid { - self.value.(_argumentsObject).put(name, value) + obj.value.(argumentsObject).put(name, value) } return true } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func argumentsDelete(self *_object, name string, throw bool) bool { - if !objectDelete(self, name, throw) { +func argumentsDelete(obj *object, name string, throw bool) bool { + if !objectDelete(obj, name, throw) { return false } - if _, exists := self.value.(_argumentsObject).get(name); exists { - self.value.(_argumentsObject).delete(name) + if _, exists := obj.value.(argumentsObject).get(name); exists { + obj.value.(argumentsObject).delete(name) } return true } diff --git a/vendor/github.com/robertkrimen/otto/type_array.go b/vendor/github.com/robertkrimen/otto/type_array.go index c8a974b02..cb673544c 100644 --- a/vendor/github.com/robertkrimen/otto/type_array.go +++ b/vendor/github.com/robertkrimen/otto/type_array.go @@ -4,34 +4,43 @@ import ( "strconv" ) -func (runtime *_runtime) newArrayObject(length uint32) *_object { - self := runtime.newObject() - self.class = "Array" - self.defineProperty("length", toValue_uint32(length), 0100, false) - self.objectClass = _classArray - return self +func (rt *runtime) newArrayObject(length uint32) *object { + obj := rt.newObject() + obj.class = classArrayName + obj.defineProperty(propertyLength, uint32Value(length), 0o100, false) + obj.objectClass = classArray + return obj } -func isArray(object *_object) bool { - return object != nil && (object.class == "Array" || object.class == "GoArray") +func isArray(obj *object) bool { + if obj == nil { + return false + } + + switch obj.class { + case classArrayName, classGoArrayName, classGoSliceName: + return true + default: + return false + } } -func objectLength(object *_object) uint32 { - if object == nil { +func objectLength(obj *object) uint32 { + if obj == nil { return 0 } - switch object.class { - case "Array": - return object.get("length").value.(uint32) - case "String": - return uint32(object.get("length").value.(int)) - case "GoArray": - return uint32(object.get("length").value.(int)) + switch obj.class { + case classArrayName: + return obj.get(propertyLength).value.(uint32) + case classStringName: + return uint32(obj.get(propertyLength).value.(int)) + case classGoArrayName, classGoSliceName: + return uint32(obj.get(propertyLength).value.(int)) } return 0 } -func arrayUint32(rt *_runtime, value Value) uint32 { +func arrayUint32(rt *runtime, value Value) uint32 { nm := value.number() if nm.kind != numberInteger || !isUint32(nm.int64) { // FIXME @@ -40,70 +49,72 @@ func arrayUint32(rt *_runtime, value Value) uint32 { return uint32(nm.int64) } -func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - lengthProperty := self.getOwnProperty("length") +func arrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + lengthProperty := obj.getOwnProperty(propertyLength) lengthValue, valid := lengthProperty.value.(Value) if !valid { panic("Array.length != Value{}") } + + reject := func(reason string) bool { + if throw { + panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %s", reason)) + } + return false + } length := lengthValue.value.(uint32) - if name == "length" { + if name == propertyLength { if descriptor.value == nil { - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } newLengthValue, isValue := descriptor.value.(Value) if !isValue { - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError("Array.DefineOwnProperty %q is not a value", descriptor.value)) } - newLength := arrayUint32(self.runtime, newLengthValue) - descriptor.value = toValue_uint32(newLength) + newLength := arrayUint32(obj.runtime, newLengthValue) + descriptor.value = uint32Value(newLength) if newLength > length { - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } if !lengthProperty.writable() { - goto Reject + return reject("property length for not writable") } newWritable := true - if descriptor.mode&0700 == 0 { + if descriptor.mode&0o700 == 0 { // If writable is off newWritable = false - descriptor.mode |= 0100 + descriptor.mode |= 0o100 } - if !objectDefineOwnProperty(self, name, descriptor, throw) { + if !objectDefineOwnProperty(obj, name, descriptor, throw) { return false } for newLength < length { length-- - if !self.delete(strconv.FormatInt(int64(length), 10), false) { - descriptor.value = toValue_uint32(length + 1) + if !obj.delete(strconv.FormatInt(int64(length), 10), false) { + descriptor.value = uint32Value(length + 1) if !newWritable { - descriptor.mode &= 0077 + descriptor.mode &= 0o077 } - objectDefineOwnProperty(self, name, descriptor, false) - goto Reject + objectDefineOwnProperty(obj, name, descriptor, false) + return reject("delete failed") } } if !newWritable { - descriptor.mode &= 0077 - objectDefineOwnProperty(self, name, descriptor, false) + descriptor.mode &= 0o077 + objectDefineOwnProperty(obj, name, descriptor, false) } } else if index := stringToArrayIndex(name); index >= 0 { if index >= int64(length) && !lengthProperty.writable() { - goto Reject + return reject("property length not writable") } - if !objectDefineOwnProperty(self, strconv.FormatInt(index, 10), descriptor, false) { - goto Reject + if !objectDefineOwnProperty(obj, strconv.FormatInt(index, 10), descriptor, false) { + return reject("Object.DefineOwnProperty failed") } if index >= int64(length) { - lengthProperty.value = toValue_uint32(uint32(index + 1)) - objectDefineOwnProperty(self, "length", *lengthProperty, false) + lengthProperty.value = uint32Value(uint32(index + 1)) + objectDefineOwnProperty(obj, propertyLength, *lengthProperty, false) return true } } - return objectDefineOwnProperty(self, name, descriptor, throw) -Reject: - if throw { - panic(self.runtime.panicTypeError()) - } - return false + return objectDefineOwnProperty(obj, name, descriptor, throw) } diff --git a/vendor/github.com/robertkrimen/otto/type_boolean.go b/vendor/github.com/robertkrimen/otto/type_boolean.go index afc45c69b..3620553cd 100644 --- a/vendor/github.com/robertkrimen/otto/type_boolean.go +++ b/vendor/github.com/robertkrimen/otto/type_boolean.go @@ -1,13 +1,5 @@ package otto -import ( - "strconv" -) - -func (runtime *_runtime) newBooleanObject(value Value) *_object { - return runtime.newPrimitiveObject("Boolean", toValue_bool(value.bool())) -} - -func booleanToString(value bool) string { - return strconv.FormatBool(value) +func (rt *runtime) newBooleanObject(value Value) *object { + return rt.newPrimitiveObject(classBooleanName, boolValue(value.bool())) } diff --git a/vendor/github.com/robertkrimen/otto/type_date.go b/vendor/github.com/robertkrimen/otto/type_date.go index 7079e649c..d35d1e69d 100644 --- a/vendor/github.com/robertkrimen/otto/type_date.go +++ b/vendor/github.com/robertkrimen/otto/type_date.go @@ -7,23 +7,22 @@ import ( Time "time" ) -type _dateObject struct { - time Time.Time // Time from the "time" package, a cached version of time - epoch int64 +type dateObject struct { + time Time.Time value Value + epoch int64 isNaN bool } -var ( - invalidDateObject = _dateObject{ - time: Time.Time{}, - epoch: -1, - value: NaNValue(), - isNaN: true, - } -) +var invalidDateObject = dateObject{ + time: Time.Time{}, + epoch: -1, + value: NaNValue(), + isNaN: true, +} -type _ecmaTime struct { +type ecmaTime struct { + location *Time.Location year int month int day int @@ -31,80 +30,73 @@ type _ecmaTime struct { minute int second int millisecond int - location *Time.Location // Basically, either local or UTC } -func ecmaTime(goTime Time.Time) _ecmaTime { - return _ecmaTime{ - goTime.Year(), - dateFromGoMonth(goTime.Month()), - goTime.Day(), - goTime.Hour(), - goTime.Minute(), - goTime.Second(), - goTime.Nanosecond() / (100 * 100 * 100), - goTime.Location(), +func newEcmaTime(goTime Time.Time) ecmaTime { + return ecmaTime{ + year: goTime.Year(), + month: dateFromGoMonth(goTime.Month()), + day: goTime.Day(), + hour: goTime.Hour(), + minute: goTime.Minute(), + second: goTime.Second(), + millisecond: goTime.Nanosecond() / (100 * 100 * 100), + location: goTime.Location(), } } -func (self *_ecmaTime) goTime() Time.Time { +func (t *ecmaTime) goTime() Time.Time { return Time.Date( - self.year, - dateToGoMonth(self.month), - self.day, - self.hour, - self.minute, - self.second, - self.millisecond*(100*100*100), - self.location, + t.year, + dateToGoMonth(t.month), + t.day, + t.hour, + t.minute, + t.second, + t.millisecond*(100*100*100), + t.location, ) } -func (self *_dateObject) Time() Time.Time { - return self.time -} - -func (self *_dateObject) Epoch() int64 { - return self.epoch +func (d *dateObject) Time() Time.Time { + return d.time } -func (self *_dateObject) Value() Value { - return self.value +func (d *dateObject) Epoch() int64 { + return d.epoch } -// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1 -func (self *_dateObject) SetNaN() { - self.time = Time.Time{} - self.epoch = -1 - self.value = NaNValue() - self.isNaN = true +func (d *dateObject) Value() Value { + return d.value } -func (self *_dateObject) SetTime(time Time.Time) { - self.Set(timeToEpoch(time)) +// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1. +func (d *dateObject) SetNaN() { + d.time = Time.Time{} + d.epoch = -1 + d.value = NaNValue() + d.isNaN = true } -func epoch2dateObject(epoch float64) _dateObject { - date := _dateObject{} - date.Set(epoch) - return date +func (d *dateObject) SetTime(time Time.Time) { + d.Set(timeToEpoch(time)) } -func (self *_dateObject) Set(epoch float64) { +func (d *dateObject) Set(epoch float64) { // epoch - self.epoch = epochToInteger(epoch) + d.epoch = epochToInteger(epoch) // time time, err := epochToTime(epoch) - self.time = time // Is either a valid time, or the zero-value for time.Time + d.time = time // Is either a valid time, or the zero-value for time.Time // value & isNaN if err != nil { - self.isNaN = true - self.epoch = -1 - self.value = NaNValue() + d.isNaN = true + d.epoch = -1 + d.value = NaNValue() } else { - self.value = toValue_int64(self.epoch) + d.value = int64Value(d.epoch) } } @@ -115,48 +107,49 @@ func epochToInteger(value float64) int64 { return int64(math.Ceil(value)) } -func epochToTime(value float64) (time Time.Time, err error) { +func epochToTime(value float64) (Time.Time, error) { epochWithMilli := value if math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) { - err = fmt.Errorf("Invalid time %v", value) - return + return Time.Time{}, fmt.Errorf("invalid time %v", value) } epoch := int64(epochWithMilli / 1000) milli := int64(epochWithMilli) % 1000 - time = Time.Unix(int64(epoch), milli*1000000).UTC() - return + return Time.Unix(epoch, milli*1000000).In(utcTimeZone), nil } func timeToEpoch(time Time.Time) float64 { - return float64(time.UnixNano() / (1000 * 1000)) + return float64(time.UnixMilli()) } -func (runtime *_runtime) newDateObject(epoch float64) *_object { - self := runtime.newObject() - self.class = "Date" +func (rt *runtime) newDateObject(epoch float64) *object { + obj := rt.newObject() + obj.class = classDateName // FIXME This is ugly... - date := _dateObject{} + date := dateObject{} date.Set(epoch) - self.value = date - return self + obj.value = date + return obj } -func (self *_object) dateValue() _dateObject { - value, _ := self.value.(_dateObject) +func (o *object) dateValue() dateObject { + value, _ := o.value.(dateObject) return value } -func dateObjectOf(rt *_runtime, _dateObject *_object) _dateObject { - if _dateObject == nil || _dateObject.class != "Date" { - panic(rt.panicTypeError()) +func dateObjectOf(rt *runtime, date *object) dateObject { + if date == nil { + panic(rt.panicTypeError("Date.ObjectOf is nil")) } - return _dateObject.dateValue() + if date.class != classDateName { + panic(rt.panicTypeError("Date.ObjectOf %q != %q", date.class, classDateName)) + } + return date.dateValue() } -// JavaScript is 0-based, Go is 1-based (15.9.1.4) +// JavaScript is 0-based, Go is 1-based (15.9.1.4). func dateToGoMonth(month int) Time.Month { return Time.Month(month + 1) } @@ -165,17 +158,12 @@ func dateFromGoMonth(month Time.Month) int { return int(month) - 1 } -// Both JavaScript & Go are 0-based (Sunday == 0) -func dateToGoDay(day int) Time.Weekday { - return Time.Weekday(day) -} - func dateFromGoDay(day Time.Weekday) int { return int(day) } -func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) { - +// newDateTime returns the epoch of date contained in argumentList for location. +func newDateTime(argumentList []Value, location *Time.Location) float64 { pick := func(index int, default_ float64) (float64, bool) { if index >= len(argumentList) { return default_, false @@ -187,29 +175,41 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) return value, false } - if len(argumentList) >= 2 { // 2-argument, 3-argument, ... + switch len(argumentList) { + case 0: // 0-argument + time := Time.Now().In(utcTimeZone) + return timeToEpoch(time) + case 1: // 1-argument + value := valueOfArrayIndex(argumentList, 0) + value = toPrimitiveValue(value) + if value.IsString() { + return dateParse(value.string()) + } + + return value.float64() + default: // 2-argument, 3-argument, ... var year, month, day, hour, minute, second, millisecond float64 var invalid bool if year, invalid = pick(0, 1900.0); invalid { - goto INVALID + return math.NaN() } if month, invalid = pick(1, 0.0); invalid { - goto INVALID + return math.NaN() } if day, invalid = pick(2, 1.0); invalid { - goto INVALID + return math.NaN() } if hour, invalid = pick(3, 0.0); invalid { - goto INVALID + return math.NaN() } if minute, invalid = pick(4, 0.0); invalid { - goto INVALID + return math.NaN() } if second, invalid = pick(5, 0.0); invalid { - goto INVALID + return math.NaN() } if millisecond, invalid = pick(6, 0.0); invalid { - goto INVALID + return math.NaN() } if year >= 0 && year <= 99 { @@ -218,23 +218,7 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) time := Time.Date(int(year), dateToGoMonth(int(month)), int(day), int(hour), int(minute), int(second), int(millisecond)*1000*1000, location) return timeToEpoch(time) - - } else if len(argumentList) == 0 { // 0-argument - time := Time.Now().UTC() - return timeToEpoch(time) - } else { // 1-argument - value := valueOfArrayIndex(argumentList, 0) - value = toPrimitive(value) - if value.IsString() { - return dateParse(value.string()) - } - - return value.float64() } - -INVALID: - epoch = math.NaN() - return } var ( @@ -251,6 +235,10 @@ var ( "2006-01T15:04:05", "2006-01-02T15:04:05", + "2006/01", + "2006/01/02", + "2006/01/02 15:04:05", + "2006T15:04:05.000", "2006-01T15:04:05.000", "2006-01-02T15:04:05.000", @@ -272,28 +260,30 @@ var ( matchDateTimeZone = regexp.MustCompile(`^(.*)(?:(Z)|([\+\-]\d{2}):(\d{2}))$`) ) -func dateParse(date string) (epoch float64) { +// dateParse returns the epoch of the parsed date. +func dateParse(date string) float64 { // YYYY-MM-DDTHH:mm:ss.sssZ var time Time.Time var err error - { - date := date - if match := matchDateTimeZone.FindStringSubmatch(date); match != nil { - if match[2] == "Z" { - date = match[1] + "+0000" - } else { - date = match[1] + match[3] + match[4] - } + + if match := matchDateTimeZone.FindStringSubmatch(date); match != nil { + if match[2] == "Z" { + date = match[1] + "+0000" + } else { + date = match[1] + match[3] + match[4] } - for _, layout := range dateLayoutList { - time, err = Time.Parse(layout, date) - if err == nil { - break - } + } + + for _, layout := range dateLayoutList { + time, err = Time.Parse(layout, date) + if err == nil { + break } } + if err != nil { return math.NaN() } - return float64(time.UnixNano()) / (1000 * 1000) // UnixMilli() + + return float64(time.UnixMilli()) } diff --git a/vendor/github.com/robertkrimen/otto/type_error.go b/vendor/github.com/robertkrimen/otto/type_error.go index 84e5d79b1..3ad9d6bda 100644 --- a/vendor/github.com/robertkrimen/otto/type_error.go +++ b/vendor/github.com/robertkrimen/otto/type_error.go @@ -1,24 +1,58 @@ package otto -func (rt *_runtime) newErrorObject(name string, message Value, stackFramesToPop int) *_object { - self := rt.newClassObject("Error") +func (rt *runtime) newErrorObject(name string, message Value, stackFramesToPop int) *object { + obj := rt.newClassObject(classErrorName) if message.IsDefined() { - msg := message.string() - self.defineProperty("message", toValue_string(msg), 0111, false) - self.value = newError(rt, name, stackFramesToPop, msg) + err := newError(rt, name, stackFramesToPop, "%s", message.string()) + obj.defineProperty("message", err.messageValue(), 0o111, false) + obj.value = err } else { - self.value = newError(rt, name, stackFramesToPop) + obj.value = newError(rt, name, stackFramesToPop) } - self.defineOwnProperty("stack", _property{ - value: _propertyGetSet{ + obj.defineOwnProperty("stack", property{ + value: propertyGetSet{ rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value { - return toValue_string(self.value.(_error).formatWithStack()) + return stringValue(obj.value.(ottoError).formatWithStack()) }), - &_nilGetSetObject, + &nilGetSetObject, }, mode: modeConfigureMask & modeOnMask, }, false) - return self + return obj +} + +func (rt *runtime) newErrorObjectError(err ottoError) *object { + obj := rt.newClassObject(classErrorName) + obj.defineProperty("message", err.messageValue(), 0o111, false) + obj.value = err + switch err.name { + case "EvalError": + obj.prototype = rt.global.EvalErrorPrototype + case "TypeError": + obj.prototype = rt.global.TypeErrorPrototype + case "RangeError": + obj.prototype = rt.global.RangeErrorPrototype + case "ReferenceError": + obj.prototype = rt.global.ReferenceErrorPrototype + case "SyntaxError": + obj.prototype = rt.global.SyntaxErrorPrototype + case "URIError": + obj.prototype = rt.global.URIErrorPrototype + default: + obj.prototype = rt.global.ErrorPrototype + } + + obj.defineOwnProperty("stack", property{ + value: propertyGetSet{ + rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value { + return stringValue(obj.value.(ottoError).formatWithStack()) + }), + &nilGetSetObject, + }, + mode: modeConfigureMask & modeOnMask, + }, false) + + return obj } diff --git a/vendor/github.com/robertkrimen/otto/type_function.go b/vendor/github.com/robertkrimen/otto/type_function.go index ad4b1f16f..41e63933e 100644 --- a/vendor/github.com/robertkrimen/otto/type_function.go +++ b/vendor/github.com/robertkrimen/otto/type_function.go @@ -1,20 +1,20 @@ package otto -// _constructFunction -type _constructFunction func(*_object, []Value) Value +// constructFunction. +type constructFunction func(*object, []Value) Value -// 13.2.2 [[Construct]] -func defaultConstruct(fn *_object, argumentList []Value) Value { - object := fn.runtime.newObject() - object.class = "Object" +// 13.2.2 [[Construct]]. +func defaultConstruct(fn *object, argumentList []Value) Value { + obj := fn.runtime.newObject() + obj.class = classObjectName prototype := fn.get("prototype") if prototype.kind != valueObject { - prototype = toValue_object(fn.runtime.global.ObjectPrototype) + prototype = objectValue(fn.runtime.global.ObjectPrototype) } - object.prototype = prototype._object() + obj.prototype = prototype.object() - this := toValue_object(object) + this := objectValue(obj) value := fn.call(this, argumentList, false, nativeFrame) if value.kind == valueObject { return value @@ -22,176 +22,165 @@ func defaultConstruct(fn *_object, argumentList []Value) Value { return this } -// _nativeFunction -type _nativeFunction func(FunctionCall) Value +// nativeFunction. +type nativeFunction func(FunctionCall) Value -// ===================== // -// _nativeFunctionObject // -// ===================== // - -type _nativeFunctionObject struct { +// nativeFunctionObject. +type nativeFunctionObject struct { + call nativeFunction + construct constructFunction name string file string line int - call _nativeFunction // [[Call]] - construct _constructFunction // [[Construct]] } -func (runtime *_runtime) _newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object { - self := runtime.newClassObject("Function") - self.value = _nativeFunctionObject{ +func (rt *runtime) newNativeFunctionProperty(name, file string, line int, native nativeFunction, length int) *object { + o := rt.newClassObject(classFunctionName) + o.value = nativeFunctionObject{ name: name, file: file, line: line, call: native, construct: defaultConstruct, } - self.defineProperty("name", toValue_string(name), 0000, false) - self.defineProperty("length", toValue_int(length), 0000, false) - return self + o.defineProperty("name", stringValue(name), 0o000, false) + o.defineProperty(propertyLength, intValue(length), 0o000, false) + return o } -func (runtime *_runtime) newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object { - self := runtime._newNativeFunctionObject(name, file, line, native, length) - self.defineOwnProperty("caller", _property{ - value: _propertyGetSet{ - runtime._newNativeFunctionObject("get", "internal", 0, func(fc FunctionCall) Value { - for sc := runtime.scope; sc != nil; sc = sc.outer { - if sc.frame.fn == self { +func (rt *runtime) newNativeFunctionObject(name, file string, line int, native nativeFunction, length int) *object { + o := rt.newNativeFunctionProperty(name, file, line, native, length) + o.defineOwnProperty("caller", property{ + value: propertyGetSet{ + rt.newNativeFunctionProperty("get", "internal", 0, func(fc FunctionCall) Value { + for sc := rt.scope; sc != nil; sc = sc.outer { + if sc.frame.fn == o { if sc.outer == nil || sc.outer.frame.fn == nil { return nullValue } - return runtime.toValue(sc.outer.frame.fn) + return rt.toValue(sc.outer.frame.fn) } } return nullValue }, 0), - &_nilGetSetObject, + &nilGetSetObject, }, - mode: 0000, + mode: 0o000, }, false) - return self + return o } -// =================== // -// _bindFunctionObject // -// =================== // - -type _bindFunctionObject struct { - target *_object +// bindFunctionObject. +type bindFunctionObject struct { + target *object this Value argumentList []Value } -func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newClassObject("Function") - self.value = _bindFunctionObject{ +func (rt *runtime) newBoundFunctionObject(target *object, this Value, argumentList []Value) *object { + o := rt.newClassObject(classFunctionName) + o.value = bindFunctionObject{ target: target, this: this, argumentList: argumentList, } - length := int(toInt32(target.get("length"))) + length := int(toInt32(target.get(propertyLength))) length -= len(argumentList) if length < 0 { length = 0 } - self.defineProperty("name", toValue_string("bound "+target.get("name").String()), 0000, false) - self.defineProperty("length", toValue_int(length), 0000, false) - self.defineProperty("caller", Value{}, 0000, false) // TODO Should throw a TypeError - self.defineProperty("arguments", Value{}, 0000, false) // TODO Should throw a TypeError - return self + o.defineProperty("name", stringValue("bound "+target.get("name").String()), 0o000, false) + o.defineProperty(propertyLength, intValue(length), 0o000, false) + o.defineProperty("caller", Value{}, 0o000, false) // TODO Should throw a TypeError + o.defineProperty("arguments", Value{}, 0o000, false) // TODO Should throw a TypeError + return o } -// [[Construct]] -func (fn _bindFunctionObject) construct(argumentList []Value) Value { - object := fn.target - switch value := object.value.(type) { - case _nativeFunctionObject: - return value.construct(object, fn.argumentList) - case _nodeFunctionObject: +// [[Construct]]. +func (fn bindFunctionObject) construct(argumentList []Value) Value { + obj := fn.target + switch value := obj.value.(type) { + case nativeFunctionObject: + return value.construct(obj, fn.argumentList) + case nodeFunctionObject: argumentList = append(fn.argumentList, argumentList...) - return object.construct(argumentList) + return obj.construct(argumentList) + default: + panic(fn.target.runtime.panicTypeError("construct unknown type %T", obj.value)) } - panic(fn.target.runtime.panicTypeError()) } -// =================== // -// _nodeFunctionObject // -// =================== // - -type _nodeFunctionObject struct { - node *_nodeFunctionLiteral - stash _stash +// nodeFunctionObject. +type nodeFunctionObject struct { + node *nodeFunctionLiteral + stash stasher } -func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, stash _stash) *_object { - self := runtime.newClassObject("Function") - self.value = _nodeFunctionObject{ +func (rt *runtime) newNodeFunctionObject(node *nodeFunctionLiteral, stash stasher) *object { + o := rt.newClassObject(classFunctionName) + o.value = nodeFunctionObject{ node: node, stash: stash, } - self.defineProperty("name", toValue_string(node.name), 0000, false) - self.defineProperty("length", toValue_int(len(node.parameterList)), 0000, false) - self.defineOwnProperty("caller", _property{ - value: _propertyGetSet{ - runtime.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value { - for sc := runtime.scope; sc != nil; sc = sc.outer { - if sc.frame.fn == self { + o.defineProperty("name", stringValue(node.name), 0o000, false) + o.defineProperty(propertyLength, intValue(len(node.parameterList)), 0o000, false) + o.defineOwnProperty("caller", property{ + value: propertyGetSet{ + rt.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value { + for sc := rt.scope; sc != nil; sc = sc.outer { + if sc.frame.fn == o { if sc.outer == nil || sc.outer.frame.fn == nil { return nullValue } - return runtime.toValue(sc.outer.frame.fn) + return rt.toValue(sc.outer.frame.fn) } } return nullValue }), - &_nilGetSetObject, + &nilGetSetObject, }, - mode: 0000, + mode: 0o000, }, false) - return self + return o } -// ======= // -// _object // -// ======= // - -func (self *_object) isCall() bool { - switch fn := self.value.(type) { - case _nativeFunctionObject: +// _object. +func (o *object) isCall() bool { + switch fn := o.value.(type) { + case nativeFunctionObject: return fn.call != nil - case _bindFunctionObject: + case bindFunctionObject: return true - case _nodeFunctionObject: + case nodeFunctionObject: return true + default: + return false } - return false } -func (self *_object) call(this Value, argumentList []Value, eval bool, frame _frame) Value { - switch fn := self.value.(type) { - - case _nativeFunctionObject: +func (o *object) call(this Value, argumentList []Value, eval bool, frm frame) Value { //nolint:unparam // Isn't currently used except in recursive self. + switch fn := o.value.(type) { + case nativeFunctionObject: // Since eval is a native function, we only have to check for it here if eval { - eval = self == self.runtime.eval // If eval is true, then it IS a direct eval + eval = o == o.runtime.eval // If eval is true, then it IS a direct eval } // Enter a scope, name from the native object... - rt := self.runtime + rt := o.runtime if rt.scope != nil && !eval { rt.enterFunctionScope(rt.scope.lexical, this) - rt.scope.frame = _frame{ + rt.scope.frame = frame{ native: true, nativeFile: fn.file, nativeLine: fn.line, callee: fn.name, file: nil, - fn: self, + fn: o, } defer func() { rt.leaveScope() @@ -199,78 +188,77 @@ func (self *_object) call(this Value, argumentList []Value, eval bool, frame _fr } return fn.call(FunctionCall{ - runtime: self.runtime, + runtime: o.runtime, eval: eval, This: this, ArgumentList: argumentList, - Otto: self.runtime.otto, + Otto: o.runtime.otto, }) - case _bindFunctionObject: + case bindFunctionObject: // TODO Passthrough site, do not enter a scope argumentList = append(fn.argumentList, argumentList...) - return fn.target.call(fn.this, argumentList, false, frame) + return fn.target.call(fn.this, argumentList, false, frm) - case _nodeFunctionObject: - rt := self.runtime + case nodeFunctionObject: + rt := o.runtime stash := rt.enterFunctionScope(fn.stash, this) - rt.scope.frame = _frame{ + rt.scope.frame = frame{ callee: fn.node.name, file: fn.node.file, - fn: self, + fn: o, } defer func() { rt.leaveScope() }() - callValue := rt.cmpl_call_nodeFunction(self, stash, fn.node, this, argumentList) - if value, valid := callValue.value.(_result); valid { + callValue := rt.cmplCallNodeFunction(o, stash, fn.node, argumentList) + if value, valid := callValue.value.(result); valid { return value.value } return callValue } - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } -func (self *_object) construct(argumentList []Value) Value { - switch fn := self.value.(type) { - - case _nativeFunctionObject: +func (o *object) construct(argumentList []Value) Value { + switch fn := o.value.(type) { + case nativeFunctionObject: if fn.call == nil { - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } if fn.construct == nil { - panic(self.runtime.panicTypeError("%v is not a constructor", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a constructor", objectValue(o))) } - return fn.construct(self, argumentList) + return fn.construct(o, argumentList) - case _bindFunctionObject: + case bindFunctionObject: return fn.construct(argumentList) - case _nodeFunctionObject: - return defaultConstruct(self, argumentList) + case nodeFunctionObject: + return defaultConstruct(o, argumentList) } - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } -// 15.3.5.3 -func (self *_object) hasInstance(of Value) bool { - if !self.isCall() { +// 15.3.5.3. +func (o *object) hasInstance(of Value) bool { + if !o.isCall() { // We should not have a hasInstance method - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError("Object.hasInstance not callable")) } if !of.IsObject() { return false } - prototype := self.get("prototype") + prototype := o.get("prototype") if !prototype.IsObject() { - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError("Object.hasInstance prototype %q is not an object", prototype)) } - prototypeObject := prototype._object() + prototypeObject := prototype.object() - value := of._object().prototype + value := of.object().prototype for value != nil { if value == prototypeObject { return true @@ -280,61 +268,55 @@ func (self *_object) hasInstance(of Value) bool { return false } -// ============ // -// FunctionCall // -// ============ // - // FunctionCall is an encapsulation of a JavaScript function call. type FunctionCall struct { - runtime *_runtime - _thisObject *_object - eval bool // This call is a direct call to eval - This Value - ArgumentList []Value + runtime *runtime + thisObj *object Otto *Otto + ArgumentList []Value + eval bool } // Argument will return the value of the argument at the given index. // // If no such argument exists, undefined is returned. -func (self FunctionCall) Argument(index int) Value { - return valueOfArrayIndex(self.ArgumentList, index) +func (f FunctionCall) Argument(index int) Value { + return valueOfArrayIndex(f.ArgumentList, index) } -func (self FunctionCall) getArgument(index int) (Value, bool) { - return getValueOfArrayIndex(self.ArgumentList, index) +func (f FunctionCall) getArgument(index int) (Value, bool) { + return getValueOfArrayIndex(f.ArgumentList, index) } -func (self FunctionCall) slice(index int) []Value { - if index < len(self.ArgumentList) { - return self.ArgumentList[index:] +func (f FunctionCall) slice(index int) []Value { + if index < len(f.ArgumentList) { + return f.ArgumentList[index:] } return []Value{} } -func (self *FunctionCall) thisObject() *_object { - if self._thisObject == nil { - this := self.This.resolve() // FIXME Is this right? - self._thisObject = self.runtime.toObject(this) +func (f *FunctionCall) thisObject() *object { + if f.thisObj == nil { + this := f.This.resolve() // FIXME Is this right? + f.thisObj = f.runtime.toObject(this) } - return self._thisObject + return f.thisObj } -func (self *FunctionCall) thisClassObject(class string) *_object { - thisObject := self.thisObject() - if thisObject.class != class { - panic(self.runtime.panicTypeError()) +func (f *FunctionCall) thisClassObject(class string) *object { + if o := f.thisObject(); o.class != class { + panic(f.runtime.panicTypeError("Function.Class %s != %s", o.class, class)) } - return self._thisObject + return f.thisObj } -func (self FunctionCall) toObject(value Value) *_object { - return self.runtime.toObject(value) +func (f FunctionCall) toObject(value Value) *object { + return f.runtime.toObject(value) } // CallerLocation will return file location information (file:line:pos) where this function is being called. -func (self FunctionCall) CallerLocation() string { +func (f FunctionCall) CallerLocation() string { // see error.go for location() - return self.runtime.scope.outer.frame.location() + return f.runtime.scope.outer.frame.location() } diff --git a/vendor/github.com/robertkrimen/otto/type_go_array.go b/vendor/github.com/robertkrimen/otto/type_go_array.go index 13a0b10f2..397c017ff 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_array.go +++ b/vendor/github.com/robertkrimen/otto/type_go_array.go @@ -5,48 +5,64 @@ import ( "strconv" ) -func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "GoArray" - self.objectClass = _classGoArray - self.value = _newGoArrayObject(value) - return self +func (rt *runtime) newGoArrayObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classGoArrayName + o.objectClass = classGoArray + o.value = newGoArrayObject(value) + return o } -type _goArrayObject struct { +type goArrayObject struct { value reflect.Value writable bool - propertyMode _propertyMode + propertyMode propertyMode } -func _newGoArrayObject(value reflect.Value) *_goArrayObject { - writable := value.Kind() == reflect.Ptr // The Array is addressable (like a Slice) - mode := _propertyMode(0010) +func newGoArrayObject(value reflect.Value) *goArrayObject { + writable := value.Kind() == reflect.Ptr || value.CanSet() // The Array is addressable (like a Slice) + mode := propertyMode(0o010) if writable { - mode = 0110 + mode = 0o110 } - self := &_goArrayObject{ + + return &goArrayObject{ value: value, writable: writable, propertyMode: mode, } - return self } -func (self _goArrayObject) getValue(index int64) (reflect.Value, bool) { - value := reflect.Indirect(self.value) +func (o goArrayObject) getValue(name string) (reflect.Value, bool) { //nolint:unused + if index, err := strconv.ParseInt(name, 10, 64); err != nil { + v, ok := o.getValueIndex(index) + if ok { + return v, ok + } + } + + if m := o.value.MethodByName(name); m.IsValid() { + return m, true + } + + return reflect.Value{}, false +} + +func (o goArrayObject) getValueIndex(index int64) (reflect.Value, bool) { + value := reflect.Indirect(o.value) if index < int64(value.Len()) { return value.Index(int(index)), true } + return reflect.Value{}, false } -func (self _goArrayObject) setValue(index int64, value Value) bool { - indexValue, exists := self.getValue(index) +func (o goArrayObject) setValue(index int64, value Value) bool { + indexValue, exists := o.getValueIndex(index) if !exists { return false } - reflectValue, err := value.toReflectValue(reflect.Indirect(self.value).Type().Elem().Kind()) + reflectValue, err := value.toReflectValue(reflect.Indirect(o.value).Type().Elem()) if err != nil { panic(err) } @@ -54,81 +70,87 @@ func (self _goArrayObject) setValue(index int64, value Value) bool { return true } -func goArrayGetOwnProperty(self *_object, name string) *_property { +func goArrayGetOwnProperty(obj *object, name string) *property { // length - if name == "length" { - return &_property{ - value: toValue(reflect.Indirect(self.value.(*_goArrayObject).value).Len()), + if name == propertyLength { + return &property{ + value: toValue(reflect.Indirect(obj.value.(*goArrayObject).value).Len()), mode: 0, } } // .0, .1, .2, ... - index := stringToArrayIndex(name) - if index >= 0 { - object := self.value.(*_goArrayObject) + if index := stringToArrayIndex(name); index >= 0 { + goObj := obj.value.(*goArrayObject) value := Value{} - reflectValue, exists := object.getValue(index) + reflectValue, exists := goObj.getValueIndex(index) if exists { - value = self.runtime.toValue(reflectValue.Interface()) + value = obj.runtime.toValue(reflectValue.Interface()) } - return &_property{ + return &property{ value: value, - mode: object.propertyMode, + mode: goObj.propertyMode, + } + } + + if method := obj.value.(*goArrayObject).value.MethodByName(name); method.IsValid() { + return &property{ + obj.runtime.toValue(method.Interface()), + 0o110, } } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } -func goArrayEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goArrayObject) +func goArrayEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goArrayObject) // .0, .1, .2, ... - for index, length := 0, object.value.Len(); index < length; index++ { + for index, length := 0, goObj.value.Len(); index < length; index++ { name := strconv.FormatInt(int64(index), 10) if !each(name) { return } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - if name == "length" { - return self.runtime.typeErrorResult(throw) +func goArrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if name == propertyLength { + return obj.runtime.typeErrorResult(throw) } else if index := stringToArrayIndex(name); index >= 0 { - object := self.value.(*_goArrayObject) - if object.writable { - if self.value.(*_goArrayObject).setValue(index, descriptor.value.(Value)) { + goObj := obj.value.(*goArrayObject) + if goObj.writable { + if obj.value.(*goArrayObject).setValue(index, descriptor.value.(Value)) { return true } } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func goArrayDelete(self *_object, name string, throw bool) bool { +func goArrayDelete(obj *object, name string, throw bool) bool { // length - if name == "length" { - return self.runtime.typeErrorResult(throw) + if name == propertyLength { + return obj.runtime.typeErrorResult(throw) } // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - object := self.value.(*_goArrayObject) - if object.writable { - indexValue, exists := object.getValue(index) + goObj := obj.value.(*goArrayObject) + if goObj.writable { + indexValue, exists := goObj.getValueIndex(index) if exists { - indexValue.Set(reflect.Zero(reflect.Indirect(object.value).Type().Elem())) + indexValue.Set(reflect.Zero(reflect.Indirect(goObj.value).Type().Elem())) return true } } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return self.delete(name, throw) + return obj.delete(name, throw) } diff --git a/vendor/github.com/robertkrimen/otto/type_go_map.go b/vendor/github.com/robertkrimen/otto/type_go_map.go index 41b9ac0de..d4953bfde 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_map.go +++ b/vendor/github.com/robertkrimen/otto/type_go_map.go @@ -4,69 +4,82 @@ import ( "reflect" ) -func (runtime *_runtime) newGoMapObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "Object" // TODO Should this be something else? - self.objectClass = _classGoMap - self.value = _newGoMapObject(value) - return self +func (rt *runtime) newGoMapObject(value reflect.Value) *object { + obj := rt.newObject() + obj.class = classObjectName // TODO Should this be something else? + obj.objectClass = classGoMap + obj.value = newGoMapObject(value) + return obj } -type _goMapObject struct { +type goMapObject struct { + keyType reflect.Type + valueType reflect.Type value reflect.Value - keyKind reflect.Kind - valueKind reflect.Kind } -func _newGoMapObject(value reflect.Value) *_goMapObject { +func newGoMapObject(value reflect.Value) *goMapObject { if value.Kind() != reflect.Map { dbgf("%/panic//%@: %v != reflect.Map", value.Kind()) } - self := &_goMapObject{ + return &goMapObject{ value: value, - keyKind: value.Type().Key().Kind(), - valueKind: value.Type().Elem().Kind(), + keyType: value.Type().Key(), + valueType: value.Type().Elem(), } - return self } -func (self _goMapObject) toKey(name string) reflect.Value { - reflectValue, err := stringToReflectValue(name, self.keyKind) +func (o goMapObject) toKey(name string) reflect.Value { + reflectValue, err := stringToReflectValue(name, o.keyType.Kind()) if err != nil { panic(err) } return reflectValue } -func (self _goMapObject) toValue(value Value) reflect.Value { - reflectValue, err := value.toReflectValue(self.valueKind) +func (o goMapObject) toValue(value Value) reflect.Value { + reflectValue, err := value.toReflectValue(o.valueType) if err != nil { panic(err) } return reflectValue } -func goMapGetOwnProperty(self *_object, name string) *_property { - object := self.value.(*_goMapObject) - value := object.value.MapIndex(object.toKey(name)) +func goMapGetOwnProperty(obj *object, name string) *property { + goObj := obj.value.(*goMapObject) + + // an error here means that the key referenced by `name` could not possibly + // be a property of this object, so it should be safe to ignore this error + // + // TODO: figure out if any cases from + // https://go.dev/ref/spec#Comparison_operators meet the criteria of 1) + // being possible to represent as a string, 2) being possible to reconstruct + // from a string, and 3) having a meaningful failure case in this context + // other than "key does not exist" + key, err := stringToReflectValue(name, goObj.keyType.Kind()) + if err != nil { + return nil + } + + value := goObj.value.MapIndex(key) if value.IsValid() { - return &_property{self.runtime.toValue(value.Interface()), 0111} + return &property{obj.runtime.toValue(value.Interface()), 0o111} } // Other methods - if method := self.value.(*_goMapObject).value.MethodByName(name); (method != reflect.Value{}) { - return &_property{ - value: self.runtime.toValue(method.Interface()), - mode: 0110, + if method := obj.value.(*goMapObject).value.MethodByName(name); method.IsValid() { + return &property{ + value: obj.runtime.toValue(method.Interface()), + mode: 0o110, } } return nil } -func goMapEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goMapObject) - keys := object.value.MapKeys() +func goMapEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goMapObject) + keys := goObj.value.MapKeys() for _, key := range keys { if !each(toValue(key).String()) { return @@ -74,22 +87,22 @@ func goMapEnumerate(self *_object, all bool, each func(string) bool) { } } -func goMapDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - object := self.value.(*_goMapObject) +func goMapDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + goObj := obj.value.(*goMapObject) // TODO ...or 0222 - if descriptor.mode != 0111 { - return self.runtime.typeErrorResult(throw) + if descriptor.mode != 0o111 { + return obj.runtime.typeErrorResult(throw) } if !descriptor.isDataDescriptor() { - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - object.value.SetMapIndex(object.toKey(name), object.toValue(descriptor.value.(Value))) + goObj.value.SetMapIndex(goObj.toKey(name), goObj.toValue(descriptor.value.(Value))) return true } -func goMapDelete(self *_object, name string, throw bool) bool { - object := self.value.(*_goMapObject) - object.value.SetMapIndex(object.toKey(name), reflect.Value{}) +func goMapDelete(obj *object, name string, throw bool) bool { + goObj := obj.value.(*goMapObject) + goObj.value.SetMapIndex(goObj.toKey(name), reflect.Value{}) // FIXME return true } diff --git a/vendor/github.com/robertkrimen/otto/type_go_slice.go b/vendor/github.com/robertkrimen/otto/type_go_slice.go index 78c69e684..e9acfa335 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_slice.go +++ b/vendor/github.com/robertkrimen/otto/type_go_slice.go @@ -5,122 +5,149 @@ import ( "strconv" ) -func (runtime *_runtime) newGoSliceObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "GoArray" // TODO GoSlice? - self.objectClass = _classGoSlice - self.value = _newGoSliceObject(value) - return self +func (rt *runtime) newGoSliceObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classGoSliceName + o.objectClass = classGoSlice + o.value = newGoSliceObject(value) + return o } -type _goSliceObject struct { +type goSliceObject struct { value reflect.Value } -func _newGoSliceObject(value reflect.Value) *_goSliceObject { - self := &_goSliceObject{ +func newGoSliceObject(value reflect.Value) *goSliceObject { + return &goSliceObject{ value: value, } - return self } -func (self _goSliceObject) getValue(index int64) (reflect.Value, bool) { - if index < int64(self.value.Len()) { - return self.value.Index(int(index)), true +func (o goSliceObject) getValue(index int64) (reflect.Value, bool) { + if index < int64(o.value.Len()) { + return o.value.Index(int(index)), true } return reflect.Value{}, false } -func (self _goSliceObject) setValue(index int64, value Value) bool { - indexValue, exists := self.getValue(index) - if !exists { - return false +func (o *goSliceObject) setLength(value Value) { + want, err := value.ToInteger() + if err != nil { + panic(err) } - reflectValue, err := value.toReflectValue(self.value.Type().Elem().Kind()) + + wantInt := int(want) + switch { + case wantInt == o.value.Len(): + // No change needed. + case wantInt < o.value.Cap(): + // Fits in current capacity. + o.value.SetLen(wantInt) + default: + // Needs expanding. + newSlice := reflect.MakeSlice(o.value.Type(), wantInt, wantInt) + reflect.Copy(newSlice, o.value) + o.value = newSlice + } +} + +func (o *goSliceObject) setValue(index int64, value Value) bool { + reflectValue, err := value.toReflectValue(o.value.Type().Elem()) if err != nil { panic(err) } + + indexValue, exists := o.getValue(index) + if !exists { + if int64(o.value.Len()) == index { + // Trying to append e.g. slice.push(...), allow it. + o.value = reflect.Append(o.value, reflectValue) + return true + } + return false + } + indexValue.Set(reflectValue) return true } -func goSliceGetOwnProperty(self *_object, name string) *_property { +func goSliceGetOwnProperty(obj *object, name string) *property { // length - if name == "length" { - return &_property{ - value: toValue(self.value.(*_goSliceObject).value.Len()), - mode: 0, + if name == propertyLength { + return &property{ + value: toValue(obj.value.(*goSliceObject).value.Len()), + mode: 0o110, } } // .0, .1, .2, ... - index := stringToArrayIndex(name) - if index >= 0 { + if index := stringToArrayIndex(name); index >= 0 { value := Value{} - reflectValue, exists := self.value.(*_goSliceObject).getValue(index) + reflectValue, exists := obj.value.(*goSliceObject).getValue(index) if exists { - value = self.runtime.toValue(reflectValue.Interface()) + value = obj.runtime.toValue(reflectValue.Interface()) } - return &_property{ + return &property{ value: value, - mode: 0110, + mode: 0o110, } } // Other methods - if method := self.value.(*_goSliceObject).value.MethodByName(name); (method != reflect.Value{}) { - return &_property{ - value: self.runtime.toValue(method.Interface()), - mode: 0110, + if method := obj.value.(*goSliceObject).value.MethodByName(name); method.IsValid() { + return &property{ + value: obj.runtime.toValue(method.Interface()), + mode: 0o110, } } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } -func goSliceEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goSliceObject) +func goSliceEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goSliceObject) // .0, .1, .2, ... - for index, length := 0, object.value.Len(); index < length; index++ { + for index, length := 0, goObj.value.Len(); index < length; index++ { name := strconv.FormatInt(int64(index), 10) if !each(name) { return } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goSliceDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - if name == "length" { - return self.runtime.typeErrorResult(throw) +func goSliceDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if name == propertyLength { + obj.value.(*goSliceObject).setLength(descriptor.value.(Value)) + return true } else if index := stringToArrayIndex(name); index >= 0 { - if self.value.(*_goSliceObject).setValue(index, descriptor.value.(Value)) { + if obj.value.(*goSliceObject).setValue(index, descriptor.value.(Value)) { return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func goSliceDelete(self *_object, name string, throw bool) bool { +func goSliceDelete(obj *object, name string, throw bool) bool { // length - if name == "length" { - return self.runtime.typeErrorResult(throw) + if name == propertyLength { + return obj.runtime.typeErrorResult(throw) } // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - object := self.value.(*_goSliceObject) - indexValue, exists := object.getValue(index) + goObj := obj.value.(*goSliceObject) + indexValue, exists := goObj.getValue(index) if exists { - indexValue.Set(reflect.Zero(object.value.Type().Elem())) + indexValue.Set(reflect.Zero(goObj.value.Type().Elem())) return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return self.delete(name, throw) + return obj.delete(name, throw) } diff --git a/vendor/github.com/robertkrimen/otto/type_go_struct.go b/vendor/github.com/robertkrimen/otto/type_go_struct.go index 608ac6660..a61de82d2 100644 --- a/vendor/github.com/robertkrimen/otto/type_go_struct.go +++ b/vendor/github.com/robertkrimen/otto/type_go_struct.go @@ -13,36 +13,39 @@ import ( // 1. Creating a new struct every time // 2. Creating an addressable? struct in the constructor -func (runtime *_runtime) newGoStructObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = "Object" // TODO Should this be something else? - self.objectClass = _classGoStruct - self.value = _newGoStructObject(value) - return self +func (rt *runtime) newGoStructObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classObjectName // TODO Should this be something else? + o.objectClass = classGoStruct + o.value = newGoStructObject(value) + return o } -type _goStructObject struct { +type goStructObject struct { value reflect.Value } -func _newGoStructObject(value reflect.Value) *_goStructObject { +func newGoStructObject(value reflect.Value) *goStructObject { if reflect.Indirect(value).Kind() != reflect.Struct { dbgf("%/panic//%@: %v != reflect.Struct", value.Kind()) } - self := &_goStructObject{ + return &goStructObject{ value: value, } - return self } -func (self _goStructObject) getValue(name string) reflect.Value { +func (o goStructObject) getValue(name string) reflect.Value { + if idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) > 0 { + return reflect.Indirect(o.value).FieldByIndex(idx) + } + if validGoStructName(name) { - // Do not reveal hidden or unexported fields - if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) { + // Do not reveal hidden or unexported fields. + if field := reflect.Indirect(o.value).FieldByName(name); field.IsValid() { return field } - if method := self.value.MethodByName(name); (method != reflect.Value{}) { + if method := o.value.MethodByName(name); method.IsValid() { return method } } @@ -50,37 +53,37 @@ func (self _goStructObject) getValue(name string) reflect.Value { return reflect.Value{} } -func (self _goStructObject) field(name string) (reflect.StructField, bool) { - return reflect.Indirect(self.value).Type().FieldByName(name) +func (o goStructObject) fieldIndex(name string) []int { //nolint:unused + return fieldIndexByName(reflect.Indirect(o.value).Type(), name) } -func (self _goStructObject) method(name string) (reflect.Method, bool) { - return reflect.Indirect(self.value).Type().MethodByName(name) +func (o goStructObject) method(name string) (reflect.Method, bool) { //nolint:unused + return reflect.Indirect(o.value).Type().MethodByName(name) } -func (self _goStructObject) setValue(name string, value Value) bool { - field, exists := self.field(name) - if !exists { +func (o goStructObject) setValue(rt *runtime, name string, value Value) bool { + if idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) == 0 { return false } - fieldValue := self.getValue(name) - reflectValue, err := value.toReflectValue(field.Type.Kind()) + + fieldValue := o.getValue(name) + converted, err := rt.convertCallParameter(value, fieldValue.Type()) if err != nil { - panic(err) + panic(rt.panicTypeError("Object.setValue convertCallParameter: %s", err)) } - fieldValue.Set(reflectValue) + fieldValue.Set(converted) return true } -func goStructGetOwnProperty(self *_object, name string) *_property { - object := self.value.(*_goStructObject) - value := object.getValue(name) +func goStructGetOwnProperty(obj *object, name string) *property { + goObj := obj.value.(*goStructObject) + value := goObj.getValue(name) if value.IsValid() { - return &_property{self.runtime.toValue(value.Interface()), 0110} + return &property{obj.runtime.toValue(value), 0o110} } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } func validGoStructName(name string) bool { @@ -90,12 +93,12 @@ func validGoStructName(name string) bool { return 'A' <= name[0] && name[0] <= 'Z' // TODO What about Unicode? } -func goStructEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goStructObject) +func goStructEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goStructObject) // Enumerate fields - for index := 0; index < reflect.Indirect(object.value).NumField(); index++ { - name := reflect.Indirect(object.value).Type().Field(index).Name + for index := range reflect.Indirect(goObj.value).NumField() { + name := reflect.Indirect(goObj.value).Type().Field(index).Name if validGoStructName(name) { if !each(name) { return @@ -104,8 +107,8 @@ func goStructEnumerate(self *_object, all bool, each func(string) bool) { } // Enumerate methods - for index := 0; index < object.value.NumMethod(); index++ { - name := object.value.Type().Method(index).Name + for index := range goObj.value.NumMethod() { + name := goObj.value.Type().Method(index).Name if validGoStructName(name) { if !each(name) { return @@ -113,34 +116,31 @@ func goStructEnumerate(self *_object, all bool, each func(string) bool) { } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goStructCanPut(self *_object, name string) bool { - object := self.value.(*_goStructObject) - value := object.getValue(name) +func goStructCanPut(obj *object, name string) bool { + goObj := obj.value.(*goStructObject) + value := goObj.getValue(name) if value.IsValid() { return true } - return objectCanPut(self, name) + return objectCanPut(obj, name) } -func goStructPut(self *_object, name string, value Value, throw bool) { - object := self.value.(*_goStructObject) - if object.setValue(name, value) { +func goStructPut(obj *object, name string, value Value, throw bool) { + goObj := obj.value.(*goStructObject) + if goObj.setValue(obj.runtime, name, value) { return } - objectPut(self, name, value, throw) + objectPut(obj, name, value, throw) } -func goStructMarshalJSON(self *_object) json.Marshaler { - object := self.value.(*_goStructObject) - goValue := reflect.Indirect(object.value).Interface() - switch marshaler := goValue.(type) { - case json.Marshaler: - return marshaler - } - return nil +func goStructMarshalJSON(obj *object) json.Marshaler { + goObj := obj.value.(*goStructObject) + goValue := reflect.Indirect(goObj.value).Interface() + marshaler, _ := goValue.(json.Marshaler) + return marshaler } diff --git a/vendor/github.com/robertkrimen/otto/type_number.go b/vendor/github.com/robertkrimen/otto/type_number.go index 28de4444c..4201c9268 100644 --- a/vendor/github.com/robertkrimen/otto/type_number.go +++ b/vendor/github.com/robertkrimen/otto/type_number.go @@ -1,5 +1,5 @@ package otto -func (runtime *_runtime) newNumberObject(value Value) *_object { - return runtime.newPrimitiveObject("Number", value.numberValue()) +func (rt *runtime) newNumberObject(value Value) *object { + return rt.newPrimitiveObject(classNumberName, value.numberValue()) } diff --git a/vendor/github.com/robertkrimen/otto/type_reference.go b/vendor/github.com/robertkrimen/otto/type_reference.go index fd770c6f4..1d2d0d3e3 100644 --- a/vendor/github.com/robertkrimen/otto/type_reference.go +++ b/vendor/github.com/robertkrimen/otto/type_reference.go @@ -1,103 +1,93 @@ package otto -type _reference interface { - invalid() bool // IsUnresolvableReference - getValue() Value // getValue - putValue(Value) string // PutValue +type referencer interface { + invalid() bool // IsUnresolvableReference + getValue() Value // getValue + putValue(value Value) string // PutValue delete() bool } // PropertyReference -type _propertyReference struct { +type propertyReference struct { + base *object + runtime *runtime name string + at at strict bool - base *_object - runtime *_runtime - at _at } -func newPropertyReference(rt *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { - return &_propertyReference{ +func newPropertyReference(rt *runtime, base *object, name string, strict bool, atv at) *propertyReference { + return &propertyReference{ runtime: rt, name: name, strict: strict, base: base, - at: at, + at: atv, } } -func (self *_propertyReference) invalid() bool { - return self.base == nil +func (pr *propertyReference) invalid() bool { + return pr.base == nil } -func (self *_propertyReference) getValue() Value { - if self.base == nil { - panic(self.runtime.panicReferenceError("'%s' is not defined", self.name, self.at)) +func (pr *propertyReference) getValue() Value { + if pr.base == nil { + panic(pr.runtime.panicReferenceError("'%s' is not defined", pr.name, pr.at)) } - return self.base.get(self.name) + return pr.base.get(pr.name) } -func (self *_propertyReference) putValue(value Value) string { - if self.base == nil { - return self.name +func (pr *propertyReference) putValue(value Value) string { + if pr.base == nil { + return pr.name } - self.base.put(self.name, value, self.strict) + pr.base.put(pr.name, value, pr.strict) return "" } -func (self *_propertyReference) delete() bool { - if self.base == nil { +func (pr *propertyReference) delete() bool { + if pr.base == nil { // TODO Throw an error if strict return true } - return self.base.delete(self.name, self.strict) + return pr.base.delete(pr.name, pr.strict) } -// ArgumentReference - -func newArgumentReference(runtime *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { - if base == nil { - panic(hereBeDragons()) - } - return newPropertyReference(runtime, base, name, strict, at) -} - -type _stashReference struct { +type stashReference struct { + base stasher name string strict bool - base _stash } -func (self *_stashReference) invalid() bool { +func (sr *stashReference) invalid() bool { return false // The base (an environment) will never be nil } -func (self *_stashReference) getValue() Value { - return self.base.getBinding(self.name, self.strict) +func (sr *stashReference) getValue() Value { + return sr.base.getBinding(sr.name, sr.strict) } -func (self *_stashReference) putValue(value Value) string { - self.base.setValue(self.name, value, self.strict) +func (sr *stashReference) putValue(value Value) string { + sr.base.setValue(sr.name, value, sr.strict) return "" } -func (self *_stashReference) delete() bool { - if self.base == nil { +func (sr *stashReference) delete() bool { + if sr.base == nil { // This should never be reached, but just in case return false } - return self.base.deleteBinding(self.name) + return sr.base.deleteBinding(sr.name) } -// getIdentifierReference - -func getIdentifierReference(runtime *_runtime, stash _stash, name string, strict bool, at _at) _reference { +// getIdentifierReference. +func getIdentifierReference(rt *runtime, stash stasher, name string, strict bool, atv at) referencer { if stash == nil { - return newPropertyReference(runtime, nil, name, strict, at) + return newPropertyReference(rt, nil, name, strict, atv) } if stash.hasBinding(name) { - return stash.newReference(name, strict, at) + return stash.newReference(name, strict, atv) } - return getIdentifierReference(runtime, stash.outer(), name, strict, at) + return getIdentifierReference(rt, stash.outer(), name, strict, atv) } diff --git a/vendor/github.com/robertkrimen/otto/type_regexp.go b/vendor/github.com/robertkrimen/otto/type_regexp.go index 57fe31640..c1370e64e 100644 --- a/vendor/github.com/robertkrimen/otto/type_regexp.go +++ b/vendor/github.com/robertkrimen/otto/type_regexp.go @@ -3,23 +3,22 @@ package otto import ( "fmt" "regexp" - "unicode/utf8" "github.com/robertkrimen/otto/parser" ) -type _regExpObject struct { +type regExpObject struct { regularExpression *regexp.Regexp + source string + flags string global bool ignoreCase bool multiline bool - source string - flags string } -func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object { - self := runtime.newObject() - self.class = "RegExp" +func (rt *runtime) newRegExpObject(pattern string, flags string) *object { + o := rt.newObject() + o.class = classRegExpName global := false ignoreCase := false @@ -32,18 +31,18 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object switch chr { case 'g': if global { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } global = true case 'm': if multiline { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } multiline = true re2flags += "m" case 'i': if ignoreCase { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } ignoreCase = true re2flags += "i" @@ -52,7 +51,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object re2pattern, err := parser.TransformRegExp(pattern) if err != nil { - panic(runtime.panicTypeError("Invalid regular expression: %s", err.Error())) + panic(rt.panicTypeError("Invalid regular expression: %s", err.Error())) } if len(re2flags) > 0 { re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern) @@ -60,10 +59,10 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object regularExpression, err := regexp.Compile(re2pattern) if err != nil { - panic(runtime.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) + panic(rt.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) } - self.value = _regExpObject{ + o.value = regExpObject{ regularExpression: regularExpression, global: global, ignoreCase: ignoreCase, @@ -71,21 +70,21 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object source: pattern, flags: flags, } - self.defineProperty("global", toValue_bool(global), 0, false) - self.defineProperty("ignoreCase", toValue_bool(ignoreCase), 0, false) - self.defineProperty("multiline", toValue_bool(multiline), 0, false) - self.defineProperty("lastIndex", toValue_int(0), 0100, false) - self.defineProperty("source", toValue_string(pattern), 0, false) - return self + o.defineProperty("global", boolValue(global), 0, false) + o.defineProperty("ignoreCase", boolValue(ignoreCase), 0, false) + o.defineProperty("multiline", boolValue(multiline), 0, false) + o.defineProperty("lastIndex", intValue(0), 0o100, false) + o.defineProperty("source", stringValue(pattern), 0, false) + return o } -func (self *_object) regExpValue() _regExpObject { - value, _ := self.value.(_regExpObject) +func (o *object) regExpValue() regExpObject { + value, _ := o.value.(regExpObject) return value } -func execRegExp(this *_object, target string) (match bool, result []int) { - if this.class != "RegExp" { +func execRegExp(this *object, target string) (bool, []int) { + if this.class != classRegExpName { panic(this.runtime.panicTypeError("Calling RegExp.exec on a non-RegExp object")) } lastIndex := this.get("lastIndex").number().int64 @@ -94,53 +93,52 @@ func execRegExp(this *_object, target string) (match bool, result []int) { if !global { index = 0 } + + var result []int if 0 > index || index > int64(len(target)) { } else { result = this.regExpValue().regularExpression.FindStringSubmatchIndex(target[index:]) } + if result == nil { - //this.defineProperty("lastIndex", toValue_(0), 0111, true) - this.put("lastIndex", toValue_int(0), true) - return // !match + this.put("lastIndex", intValue(0), true) + return false, nil } - match = true + startIndex := index endIndex := int(lastIndex) + result[1] // We do this shift here because the .FindStringSubmatchIndex above // was done on a local subordinate slice of the string, not the whole string - for index, _ := range result { - result[index] += int(startIndex) + for index, offset := range result { + if offset != -1 { + result[index] += int(startIndex) + } } if global { - //this.defineProperty("lastIndex", toValue_(endIndex), 0111, true) - this.put("lastIndex", toValue_int(endIndex), true) + this.put("lastIndex", intValue(endIndex), true) } - return // match + + return true, result } -func execResultToArray(runtime *_runtime, target string, result []int) *_object { +func execResultToArray(rt *runtime, target string, result []int) *object { captureCount := len(result) / 2 valueArray := make([]Value, captureCount) - for index := 0; index < captureCount; index++ { + for index := range captureCount { offset := 2 * index if result[offset] != -1 { - valueArray[index] = toValue_string(target[result[offset]:result[offset+1]]) + valueArray[index] = stringValue(target[result[offset]:result[offset+1]]) } else { valueArray[index] = Value{} } } matchIndex := result[0] if matchIndex != 0 { - matchIndex = 0 - // Find the rune index in the string, not the byte index - for index := 0; index < result[0]; { - _, size := utf8.DecodeRuneInString(target[index:]) - matchIndex += 1 - index += size - } + // Find the utf16 index in the string, not the byte index. + matchIndex = utf16Length(target[:matchIndex]) } - match := runtime.newArrayOf(valueArray) - match.defineProperty("input", toValue_string(target), 0111, false) - match.defineProperty("index", toValue_int(matchIndex), 0111, false) + match := rt.newArrayOf(valueArray) + match.defineProperty("input", stringValue(target), 0o111, false) + match.defineProperty("index", intValue(matchIndex), 0o111, false) return match } diff --git a/vendor/github.com/robertkrimen/otto/type_string.go b/vendor/github.com/robertkrimen/otto/type_string.go index ef3afa42b..252c1ae63 100644 --- a/vendor/github.com/robertkrimen/otto/type_string.go +++ b/vendor/github.com/robertkrimen/otto/type_string.go @@ -2,110 +2,112 @@ package otto import ( "strconv" + "unicode/utf16" "unicode/utf8" ) -type _stringObject interface { +type stringObjecter interface { Length() int - At(int) rune + At(at int) rune String() string } -type _stringASCII string +type stringASCII string -func (str _stringASCII) Length() int { +func (str stringASCII) Length() int { return len(str) } -func (str _stringASCII) At(at int) rune { +func (str stringASCII) At(at int) rune { return rune(str[at]) } -func (str _stringASCII) String() string { +func (str stringASCII) String() string { return string(str) } -type _stringWide struct { - string string - length int - runes []rune +type stringWide struct { + string string + value16 []uint16 } -func (str _stringWide) Length() int { - return str.length +func (str stringWide) Length() int { + if str.value16 == nil { + str.value16 = utf16.Encode([]rune(str.string)) + } + return len(str.value16) } -func (str _stringWide) At(at int) rune { - if str.runes == nil { - str.runes = []rune(str.string) +func (str stringWide) At(at int) rune { + if str.value16 == nil { + str.value16 = utf16.Encode([]rune(str.string)) } - return str.runes[at] + return rune(str.value16[at]) } -func (str _stringWide) String() string { +func (str stringWide) String() string { return str.string } -func _newStringObject(str string) _stringObject { - for i := 0; i < len(str); i++ { +func newStringObject(str string) stringObjecter { + for i := range len(str) { if str[i] >= utf8.RuneSelf { goto wide } } - return _stringASCII(str) + return stringASCII(str) wide: - return &_stringWide{ + return &stringWide{ string: str, - length: utf8.RuneCountInString(str), } } -func stringAt(str _stringObject, index int) rune { +func stringAt(str stringObjecter, index int) rune { if 0 <= index && index < str.Length() { return str.At(index) } return utf8.RuneError } -func (runtime *_runtime) newStringObject(value Value) *_object { - str := _newStringObject(value.string()) +func (rt *runtime) newStringObject(value Value) *object { + str := newStringObject(value.string()) - self := runtime.newClassObject("String") - self.defineProperty("length", toValue_int(str.Length()), 0, false) - self.objectClass = _classString - self.value = str - return self + obj := rt.newClassObject(classStringName) + obj.defineProperty(propertyLength, intValue(str.Length()), 0, false) + obj.objectClass = classString + obj.value = str + return obj } -func (self *_object) stringValue() _stringObject { - if str, ok := self.value.(_stringObject); ok { +func (o *object) stringValue() stringObjecter { + if str, ok := o.value.(stringObjecter); ok { return str } return nil } -func stringEnumerate(self *_object, all bool, each func(string) bool) { - if str := self.stringValue(); str != nil { +func stringEnumerate(obj *object, all bool, each func(string) bool) { + if str := obj.stringValue(); str != nil { length := str.Length() - for index := 0; index < length; index++ { + for index := range length { if !each(strconv.FormatInt(int64(index), 10)) { return } } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func stringGetOwnProperty(self *_object, name string) *_property { - if property := objectGetOwnProperty(self, name); property != nil { - return property +func stringGetOwnProperty(obj *object, name string) *property { + if prop := objectGetOwnProperty(obj, name); prop != nil { + return prop } // TODO Test a string of length >= +int32 + 1? if index := stringToArrayIndex(name); index >= 0 { - if chr := stringAt(self.stringValue(), int(index)); chr != utf8.RuneError { - return &_property{toValue_string(string(chr)), 0} + if chr := stringAt(obj.stringValue(), int(index)); chr != utf8.RuneError { + return &property{stringValue(string(chr)), 0} } } return nil diff --git a/vendor/github.com/robertkrimen/otto/value.go b/vendor/github.com/robertkrimen/otto/value.go index 90c140604..183c23171 100644 --- a/vendor/github.com/robertkrimen/otto/value.go +++ b/vendor/github.com/robertkrimen/otto/value.go @@ -1,6 +1,7 @@ package otto import ( + "encoding/json" "fmt" "math" "reflect" @@ -8,17 +9,17 @@ import ( "unicode/utf16" ) -type _valueKind int +type valueKind int const ( - valueUndefined _valueKind = iota + valueUndefined valueKind = iota valueNull valueNumber valueString valueBoolean valueObject - // These are invalid outside of the runtime + // These are invalid outside of the runtime. valueEmpty valueResult valueReference @@ -26,12 +27,12 @@ const ( // Value is the representation of a JavaScript value. type Value struct { - kind _valueKind value interface{} + kind valueKind } -func (value Value) safe() bool { - return value.kind < valueEmpty +func (v Value) safe() bool { + return v.kind < valueEmpty } var ( @@ -53,8 +54,8 @@ func ToValue(value interface{}) (Value, error) { return result, err } -func (value Value) isEmpty() bool { - return value.kind == valueEmpty +func (v Value) isEmpty() bool { + return v.kind == valueEmpty } // Undefined @@ -65,13 +66,13 @@ func UndefinedValue() Value { } // IsDefined will return false if the value is undefined, and true otherwise. -func (value Value) IsDefined() bool { - return value.kind != valueUndefined +func (v Value) IsDefined() bool { + return v.kind != valueUndefined } // IsUndefined will return true if the value is undefined, and false otherwise. -func (value Value) IsUndefined() bool { - return value.kind == valueUndefined +func (v Value) IsUndefined() bool { + return v.kind == valueUndefined } // NullValue will return a Value representing null. @@ -80,91 +81,79 @@ func NullValue() Value { } // IsNull will return true if the value is null, and false otherwise. -func (value Value) IsNull() bool { - return value.kind == valueNull +func (v Value) IsNull() bool { + return v.kind == valueNull } // --- -func (value Value) isCallable() bool { - switch value := value.value.(type) { - case *_object: - return value.isCall() - } - return false +func (v Value) isCallable() bool { + o, ok := v.value.(*object) + return ok && o.isCall() } // Call the value as a function with the given this value and argument list and // return the result of invocation. It is essentially equivalent to: // -// value.apply(thisValue, argumentList) +// value.apply(thisValue, argumentList) // // An undefined value and an error will result if: // -// 1. There is an error during conversion of the argument list -// 2. The value is not actually a function -// 3. An (uncaught) exception is thrown -// -func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) { +// 1. There is an error during conversion of the argument list +// 2. The value is not actually a function +// 3. An (uncaught) exception is thrown +func (v Value) Call(this Value, argumentList ...interface{}) (Value, error) { result := Value{} err := catchPanic(func() { // FIXME - result = value.call(nil, this, argumentList...) + result = v.call(nil, this, argumentList...) }) - if !value.safe() { - value = Value{} + if !v.safe() { + v = Value{} } return result, err } -func (value Value) call(rt *_runtime, this Value, argumentList ...interface{}) Value { - switch function := value.value.(type) { - case *_object: +func (v Value) call(rt *runtime, this Value, argumentList ...interface{}) Value { + if function, ok := v.value.(*object); ok { return function.call(this, function.runtime.toValueArray(argumentList...), false, nativeFrame) } - if rt == nil { - panic("FIXME TypeError") - } - panic(rt.panicTypeError()) + panic(rt.panicTypeError("call %q is not an object", v.value)) } -func (value Value) constructSafe(rt *_runtime, this Value, argumentList ...interface{}) (Value, error) { +func (v Value) constructSafe(rt *runtime, this Value, argumentList ...interface{}) (Value, error) { result := Value{} err := catchPanic(func() { - result = value.construct(rt, this, argumentList...) + result = v.construct(rt, this, argumentList...) }) return result, err } -func (value Value) construct(rt *_runtime, this Value, argumentList ...interface{}) Value { - switch fn := value.value.(type) { - case *_object: +func (v Value) construct(rt *runtime, this Value, argumentList ...interface{}) Value { //nolint:unparam + if fn, ok := v.value.(*object); ok { return fn.construct(fn.runtime.toValueArray(argumentList...)) } - if rt == nil { - panic("FIXME TypeError") - } - panic(rt.panicTypeError()) + panic(rt.panicTypeError("construct %q is not an object", v.value)) } // IsPrimitive will return true if value is a primitive (any kind of primitive). -func (value Value) IsPrimitive() bool { - return !value.IsObject() +func (v Value) IsPrimitive() bool { + return !v.IsObject() } // IsBoolean will return true if value is a boolean (primitive). -func (value Value) IsBoolean() bool { - return value.kind == valueBoolean +func (v Value) IsBoolean() bool { + return v.kind == valueBoolean } // IsNumber will return true if value is a number (primitive). -func (value Value) IsNumber() bool { - return value.kind == valueNumber +func (v Value) IsNumber() bool { + return v.kind == valueNumber } // IsNaN will return true if value is NaN (or would convert to NaN). -func (value Value) IsNaN() bool { - switch value := value.value.(type) { +func (v Value) IsNaN() bool { + switch value := v.value.(type) { case float64: return math.IsNaN(value) case float32: @@ -175,99 +164,98 @@ func (value Value) IsNaN() bool { return false } - return math.IsNaN(value.float64()) + return math.IsNaN(v.float64()) } // IsString will return true if value is a string (primitive). -func (value Value) IsString() bool { - return value.kind == valueString +func (v Value) IsString() bool { + return v.kind == valueString } // IsObject will return true if value is an object. -func (value Value) IsObject() bool { - return value.kind == valueObject +func (v Value) IsObject() bool { + return v.kind == valueObject } // IsFunction will return true if value is a function. -func (value Value) IsFunction() bool { - if value.kind != valueObject { +func (v Value) IsFunction() bool { + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Function" + return v.value.(*object).class == classFunctionName } // Class will return the class string of the value or the empty string if value is not an object. // // The return value will (generally) be one of: // -// Object -// Function -// Array -// String -// Number -// Boolean -// Date -// RegExp -// -func (value Value) Class() string { - if value.kind != valueObject { +// Object +// Function +// Array +// String +// Number +// Boolean +// Date +// RegExp +func (v Value) Class() string { + if v.kind != valueObject { return "" } - return value.value.(*_object).class + return v.value.(*object).class } -func (value Value) isArray() bool { - if value.kind != valueObject { +func (v Value) isArray() bool { //nolint:unused + if v.kind != valueObject { return false } - return isArray(value.value.(*_object)) + return isArray(v.value.(*object)) } -func (value Value) isStringObject() bool { - if value.kind != valueObject { +func (v Value) isStringObject() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "String" + return v.value.(*object).class == classStringName } -func (value Value) isBooleanObject() bool { - if value.kind != valueObject { +func (v Value) isBooleanObject() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Boolean" + return v.value.(*object).class == classBooleanName } -func (value Value) isNumberObject() bool { - if value.kind != valueObject { +func (v Value) isNumberObject() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Number" + return v.value.(*object).class == classNumberName } -func (value Value) isDate() bool { - if value.kind != valueObject { +func (v Value) isDate() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Date" + return v.value.(*object).class == classDateName } -func (value Value) isRegExp() bool { - if value.kind != valueObject { +func (v Value) isRegExp() bool { + if v.kind != valueObject { return false } - return value.value.(*_object).class == "RegExp" + return v.value.(*object).class == classRegExpName } -func (value Value) isError() bool { - if value.kind != valueObject { +func (v Value) isError() bool { //nolint:unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == "Error" + return v.value.(*object).class == classErrorName } // --- -func toValue_reflectValuePanic(value interface{}, kind reflect.Kind) { +func reflectValuePanic(value interface{}, kind reflect.Kind) { // FIXME? switch kind { case reflect.Struct: @@ -284,46 +272,46 @@ func toValue(value interface{}) Value { case Value: return value case bool: - return Value{valueBoolean, value} + return Value{kind: valueBoolean, value: value} case int: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int8: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int16: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int32: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case int64: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint8: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint16: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint32: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case uint64: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case float32: - return Value{valueNumber, float64(value)} + return Value{kind: valueNumber, value: float64(value)} case float64: - return Value{valueNumber, value} + return Value{kind: valueNumber, value: value} case []uint16: - return Value{valueString, value} + return Value{kind: valueString, value: value} case string: - return Value{valueString, value} + return Value{kind: valueString, value: value} // A rune is actually an int32, which is handled above - case *_object: - return Value{valueObject, value} + case *object: + return Value{kind: valueObject, value: value} case *Object: - return Value{valueObject, value.object} + return Value{kind: valueObject, value: value.object} case Object: - return Value{valueObject, value.object} - case _reference: // reference is an interface (already a pointer) - return Value{valueReference, value} - case _result: - return Value{valueResult, value} + return Value{kind: valueObject, value: value.object} + case referencer: // reference is an interface (already a pointer) + return Value{kind: valueReference, value: value} + case result: + return Value{kind: valueResult, value: value} case nil: // TODO Ugh. return Value{} @@ -341,35 +329,35 @@ func toValue(value interface{}) Value { } switch value.Kind() { case reflect.Bool: - return Value{valueBoolean, bool(value.Bool())} + return Value{kind: valueBoolean, value: value.Bool()} case reflect.Int: - return Value{valueNumber, int(value.Int())} + return Value{kind: valueNumber, value: int(value.Int())} case reflect.Int8: - return Value{valueNumber, int8(value.Int())} + return Value{kind: valueNumber, value: int8(value.Int())} case reflect.Int16: - return Value{valueNumber, int16(value.Int())} + return Value{kind: valueNumber, value: int16(value.Int())} case reflect.Int32: - return Value{valueNumber, int32(value.Int())} + return Value{kind: valueNumber, value: int32(value.Int())} case reflect.Int64: - return Value{valueNumber, int64(value.Int())} + return Value{kind: valueNumber, value: value.Int()} case reflect.Uint: - return Value{valueNumber, uint(value.Uint())} + return Value{kind: valueNumber, value: uint(value.Uint())} case reflect.Uint8: - return Value{valueNumber, uint8(value.Uint())} + return Value{kind: valueNumber, value: uint8(value.Uint())} case reflect.Uint16: - return Value{valueNumber, uint16(value.Uint())} + return Value{kind: valueNumber, value: uint16(value.Uint())} case reflect.Uint32: - return Value{valueNumber, uint32(value.Uint())} + return Value{kind: valueNumber, value: uint32(value.Uint())} case reflect.Uint64: - return Value{valueNumber, uint64(value.Uint())} + return Value{kind: valueNumber, value: value.Uint()} case reflect.Float32: - return Value{valueNumber, float32(value.Float())} + return Value{kind: valueNumber, value: float32(value.Float())} case reflect.Float64: - return Value{valueNumber, float64(value.Float())} + return Value{kind: valueNumber, value: value.Float()} case reflect.String: - return Value{valueString, string(value.String())} + return Value{kind: valueString, value: value.String()} default: - toValue_reflectValuePanic(value.Interface(), value.Kind()) + reflectValuePanic(value.Interface(), value.Kind()) } default: return toValue(reflect.ValueOf(value)) @@ -381,89 +369,88 @@ func toValue(value interface{}) Value { // String will return the value as a string. // // This method will make return the empty string if there is an error. -func (value Value) String() string { - result := "" - catchPanic(func() { - result = value.string() +func (v Value) String() string { + var result string + catchPanic(func() { //nolint:errcheck, gosec + result = v.string() }) return result } // ToBoolean will convert the value to a boolean (bool). // -// ToValue(0).ToBoolean() => false -// ToValue("").ToBoolean() => false -// ToValue(true).ToBoolean() => true -// ToValue(1).ToBoolean() => true -// ToValue("Nothing happens").ToBoolean() => true +// ToValue(0).ToBoolean() => false +// ToValue("").ToBoolean() => false +// ToValue(true).ToBoolean() => true +// ToValue(1).ToBoolean() => true +// ToValue("Nothing happens").ToBoolean() => true // // If there is an error during the conversion process (like an uncaught exception), then the result will be false and an error. -func (value Value) ToBoolean() (bool, error) { +func (v Value) ToBoolean() (bool, error) { result := false err := catchPanic(func() { - result = value.bool() + result = v.bool() }) return result, err } -func (value Value) numberValue() Value { - if value.kind == valueNumber { - return value +func (v Value) numberValue() Value { + if v.kind == valueNumber { + return v } - return Value{valueNumber, value.float64()} + return Value{kind: valueNumber, value: v.float64()} } // ToFloat will convert the value to a number (float64). // -// ToValue(0).ToFloat() => 0. -// ToValue(1.1).ToFloat() => 1.1 -// ToValue("11").ToFloat() => 11. +// ToValue(0).ToFloat() => 0. +// ToValue(1.1).ToFloat() => 1.1 +// ToValue("11").ToFloat() => 11. // // If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -func (value Value) ToFloat() (float64, error) { +func (v Value) ToFloat() (float64, error) { result := float64(0) err := catchPanic(func() { - result = value.float64() + result = v.float64() }) return result, err } // ToInteger will convert the value to a number (int64). // -// ToValue(0).ToInteger() => 0 -// ToValue(1.1).ToInteger() => 1 -// ToValue("11").ToInteger() => 11 +// ToValue(0).ToInteger() => 0 +// ToValue(1.1).ToInteger() => 1 +// ToValue("11").ToInteger() => 11 // // If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -func (value Value) ToInteger() (int64, error) { +func (v Value) ToInteger() (int64, error) { result := int64(0) err := catchPanic(func() { - result = value.number().int64 + result = v.number().int64 }) return result, err } // ToString will convert the value to a string (string). // -// ToValue(0).ToString() => "0" -// ToValue(false).ToString() => "false" -// ToValue(1.1).ToString() => "1.1" -// ToValue("11").ToString() => "11" -// ToValue('Nothing happens.').ToString() => "Nothing happens." +// ToValue(0).ToString() => "0" +// ToValue(false).ToString() => "false" +// ToValue(1.1).ToString() => "1.1" +// ToValue("11").ToString() => "11" +// ToValue('Nothing happens.').ToString() => "Nothing happens." // // If there is an error during the conversion process (like an uncaught exception), then the result will be the empty string ("") and an error. -func (value Value) ToString() (string, error) { +func (v Value) ToString() (string, error) { result := "" err := catchPanic(func() { - result = value.string() + result = v.string() }) return result, err } -func (value Value) _object() *_object { - switch value := value.value.(type) { - case *_object: - return value +func (v Value) object() *object { + if v, ok := v.value.(*object); ok { + return v } return nil } @@ -471,160 +458,137 @@ func (value Value) _object() *_object { // Object will return the object of the value, or nil if value is not an object. // // This method will not do any implicit conversion. For example, calling this method on a string primitive value will not return a String object. -func (value Value) Object() *Object { - switch object := value.value.(type) { - case *_object: - return _newObject(object, value) +func (v Value) Object() *Object { + if obj, ok := v.value.(*object); ok { + return &Object{ + object: obj, + value: v, + } } return nil } -func (value Value) reference() _reference { - switch value := value.value.(type) { - case _reference: - return value - } - return nil +func (v Value) reference() referencer { + value, _ := v.value.(referencer) + return value } -func (value Value) resolve() Value { - switch value := value.value.(type) { - case _reference: +func (v Value) resolve() Value { + if value, ok := v.value.(referencer); ok { return value.getValue() } - return value + return v } var ( - __NaN__ float64 = math.NaN() - __PositiveInfinity__ float64 = math.Inf(+1) - __NegativeInfinity__ float64 = math.Inf(-1) - __PositiveZero__ float64 = 0 - __NegativeZero__ float64 = math.Float64frombits(0 | (1 << 63)) + nan float64 = math.NaN() + positiveInfinity float64 = math.Inf(+1) + negativeInfinity float64 = math.Inf(-1) + positiveZero float64 = 0 + negativeZero float64 = math.Float64frombits(0 | (1 << 63)) ) -func positiveInfinity() float64 { - return __PositiveInfinity__ -} - -func negativeInfinity() float64 { - return __NegativeInfinity__ -} - -func positiveZero() float64 { - return __PositiveZero__ -} - -func negativeZero() float64 { - return __NegativeZero__ -} - // NaNValue will return a value representing NaN. // // It is equivalent to: // -// ToValue(math.NaN()) -// +// ToValue(math.NaN()) func NaNValue() Value { - return Value{valueNumber, __NaN__} + return Value{kind: valueNumber, value: nan} } func positiveInfinityValue() Value { - return Value{valueNumber, __PositiveInfinity__} + return Value{kind: valueNumber, value: positiveInfinity} } func negativeInfinityValue() Value { - return Value{valueNumber, __NegativeInfinity__} + return Value{kind: valueNumber, value: negativeInfinity} } func positiveZeroValue() Value { - return Value{valueNumber, __PositiveZero__} + return Value{kind: valueNumber, value: positiveZero} } func negativeZeroValue() Value { - return Value{valueNumber, __NegativeZero__} + return Value{kind: valueNumber, value: negativeZero} } // TrueValue will return a value representing true. // // It is equivalent to: // -// ToValue(true) -// +// ToValue(true) func TrueValue() Value { - return Value{valueBoolean, true} + return Value{kind: valueBoolean, value: true} } // FalseValue will return a value representing false. // // It is equivalent to: // -// ToValue(false) -// +// ToValue(false) func FalseValue() Value { - return Value{valueBoolean, false} + return Value{kind: valueBoolean, value: false} } func sameValue(x Value, y Value) bool { if x.kind != y.kind { return false } - result := false + switch x.kind { case valueUndefined, valueNull: - result = true + return true case valueNumber: x := x.float64() y := y.float64() if math.IsNaN(x) && math.IsNaN(y) { - result = true - } else { - result = x == y - if result && x == 0 { + return true + } + + if x == y { + if x == 0 { // Since +0 != -0 - result = math.Signbit(x) == math.Signbit(y) + return math.Signbit(x) == math.Signbit(y) } + return true } + return false case valueString: - result = x.string() == y.string() + return x.string() == y.string() case valueBoolean: - result = x.bool() == y.bool() + return x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + return x.object() == y.object() default: panic(hereBeDragons()) } - - return result } func strictEqualityComparison(x Value, y Value) bool { if x.kind != y.kind { return false } - result := false + switch x.kind { case valueUndefined, valueNull: - result = true + return true case valueNumber: x := x.float64() y := y.float64() if math.IsNaN(x) && math.IsNaN(y) { - result = false - } else { - result = x == y + return false } + return x == y case valueString: - result = x.string() == y.string() + return x.string() == y.string() case valueBoolean: - result = x.bool() == y.bool() + return x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + return x.object() == y.object() default: panic(hereBeDragons()) } - - return result } // Export will attempt to convert the value to a Go representation @@ -636,71 +600,80 @@ func strictEqualityComparison(x Value, y Value) bool { // If a reasonable conversion is not possible, then the original // value is returned. // -// undefined -> nil (FIXME?: Should be Value{}) -// null -> nil -// boolean -> bool -// number -> A number type (int, float32, uint64, ...) -// string -> string -// Array -> []interface{} -// Object -> map[string]interface{} -// -func (self Value) Export() (interface{}, error) { - return self.export(), nil -} - -func (self Value) export() interface{} { - - switch self.kind { +// undefined -> nil (FIXME?: Should be Value{}) +// null -> nil +// boolean -> bool +// number -> A number type (int, float32, uint64, ...) +// string -> string +// Array -> []interface{} +// Object -> map[string]interface{} +func (v Value) Export() (interface{}, error) { + return v.export(), nil +} + +func (v Value) export() interface{} { + switch v.kind { case valueUndefined: return nil case valueNull: return nil case valueNumber, valueBoolean: - return self.value + return v.value case valueString: - switch value := self.value.(type) { + switch value := v.value.(type) { case string: return value case []uint16: return string(utf16.Decode(value)) } case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: + obj := v.object() + switch value := obj.value.(type) { + case *goStructObject: return value.value.Interface() - case *_goMapObject: + case *goMapObject: return value.value.Interface() - case *_goArrayObject: + case *goArrayObject: return value.value.Interface() - case *_goSliceObject: + case *goSliceObject: return value.value.Interface() } - if object.class == "Array" { + if obj.class == classArrayName { result := make([]interface{}, 0) - lengthValue := object.get("length") + lengthValue := obj.get(propertyLength) length := lengthValue.value.(uint32) kind := reflect.Invalid + keyKind := reflect.Invalid + elemKind := reflect.Invalid state := 0 var t reflect.Type - for index := uint32(0); index < length; index += 1 { + for index := range length { name := strconv.FormatInt(int64(index), 10) - if !object.hasProperty(name) { + if !obj.hasProperty(name) { continue } - value := object.get(name).export() + value := obj.get(name).export() t = reflect.TypeOf(value) - var k reflect.Kind + var k, kk, ek reflect.Kind if t != nil { k = t.Kind() + switch k { + case reflect.Map: + kk = t.Key().Kind() + fallthrough + case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: + ek = t.Elem().Kind() + } } if state == 0 { kind = k + keyKind = kk + elemKind = ek state = 1 - } else if state == 1 && kind != k { + } else if state == 1 && (kind != k || keyKind != kk || elemKind != ek) { state = 2 } @@ -718,29 +691,29 @@ func (self Value) export() interface{} { val.Index(i).Set(reflect.ValueOf(v)) } return val.Interface() - } else { - result := make(map[string]interface{}) - // TODO Should we export everything? Or just what is enumerable? - object.enumerate(false, func(name string) bool { - value := object.get(name) - if value.IsDefined() { - result[name] = value.export() - } - return true - }) - return result } + + result := make(map[string]interface{}) + // TODO Should we export everything? Or just what is enumerable? + obj.enumerate(false, func(name string) bool { + value := obj.get(name) + if value.IsDefined() { + result[name] = value.export() + } + return true + }) + return result } - if self.safe() { - return self + if v.safe() { + return v } return Value{} } -func (self Value) evaluateBreakContinue(labels []string) _resultKind { - result := self.value.(_result) +func (v Value) evaluateBreakContinue(labels []string) resultKind { + result := v.value.(result) if result.kind == resultBreak || result.kind == resultContinue { for _, label := range labels { if label == result.target { @@ -751,8 +724,8 @@ func (self Value) evaluateBreakContinue(labels []string) _resultKind { return resultReturn } -func (self Value) evaluateBreak(labels []string) _resultKind { - result := self.value.(_result) +func (v Value) evaluateBreak(labels []string) resultKind { + result := v.value.(result) if result.kind == resultBreak { for _, label := range labels { if label == result.target { @@ -763,44 +736,14 @@ func (self Value) evaluateBreak(labels []string) _resultKind { return resultReturn } -func (self Value) exportNative() interface{} { - - switch self.kind { - case valueUndefined: - return self - case valueNull: - return nil - case valueNumber, valueBoolean: - return self.value - case valueString: - switch value := self.value.(type) { - case string: - return value - case []uint16: - return string(utf16.Decode(value)) - } - case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: - return value.value.Interface() - case *_goMapObject: - return value.value.Interface() - case *_goArrayObject: - return value.value.Interface() - case *_goSliceObject: - return value.value.Interface() - } - } - - return self -} - // Make a best effort to return a reflect.Value corresponding to reflect.Kind, but // fallback to just returning the Go value we have handy. -func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { - if kind != reflect.Float32 && kind != reflect.Float64 && kind != reflect.Interface { - switch value := value.value.(type) { +func (v Value) toReflectValue(typ reflect.Type) (reflect.Value, error) { + kind := typ.Kind() + switch kind { + case reflect.Float32, reflect.Float64, reflect.Interface: + default: + switch value := v.value.(type) { case float32: _, frac := math.Modf(float64(value)) if frac > 0 { @@ -816,101 +759,90 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { switch kind { case reflect.Bool: // Bool - return reflect.ValueOf(value.bool()), nil + return reflect.ValueOf(v.bool()).Convert(typ), nil case reflect.Int: // Int // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of int64 - tmp := toIntegerFloat(value) - if tmp < float_minInt || tmp > float_maxInt { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < floatMinInt || tmp > floatMaxInt { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, v) } + return reflect.ValueOf(int(tmp)).Convert(typ), nil case reflect.Int8: // Int8 - tmp := value.number().int64 - if tmp < int64_minInt8 || tmp > int64_maxInt8 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, value) - } else { - return reflect.ValueOf(int8(tmp)), nil + tmp := v.number().int64 + if tmp < int64MinInt8 || tmp > int64MaxInt8 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, v) } + return reflect.ValueOf(int8(tmp)).Convert(typ), nil case reflect.Int16: // Int16 - tmp := value.number().int64 - if tmp < int64_minInt16 || tmp > int64_maxInt16 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, value) - } else { - return reflect.ValueOf(int16(tmp)), nil + tmp := v.number().int64 + if tmp < int64MinInt16 || tmp > int64MaxInt16 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, v) } + return reflect.ValueOf(int16(tmp)).Convert(typ), nil case reflect.Int32: // Int32 - tmp := value.number().int64 - if tmp < int64_minInt32 || tmp > int64_maxInt32 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, value) - } else { - return reflect.ValueOf(int32(tmp)), nil + tmp := v.number().int64 + if tmp < int64MinInt32 || tmp > int64MaxInt32 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, v) } + return reflect.ValueOf(int32(tmp)).Convert(typ), nil case reflect.Int64: // Int64 // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of int64 - tmp := toIntegerFloat(value) - if tmp < float_minInt64 || tmp > float_maxInt64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int64(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < floatMinInt64 || tmp > floatMaxInt64 { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, v) } + return reflect.ValueOf(int64(tmp)).Convert(typ), nil case reflect.Uint: // Uint // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of uint - tmp := toIntegerFloat(value) - if tmp < 0 || tmp > float_maxUint { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, value) - } else { - return reflect.ValueOf(uint(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < 0 || tmp > floatMaxUint { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, v) } + return reflect.ValueOf(uint(tmp)).Convert(typ), nil case reflect.Uint8: // Uint8 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint8 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, value) - } else { - return reflect.ValueOf(uint8(tmp)), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint8 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, v) } + return reflect.ValueOf(uint8(tmp)).Convert(typ), nil case reflect.Uint16: // Uint16 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint16 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, value) - } else { - return reflect.ValueOf(uint16(tmp)), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint16 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, v) } + return reflect.ValueOf(uint16(tmp)).Convert(typ), nil case reflect.Uint32: // Uint32 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint32 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, value) - } else { - return reflect.ValueOf(uint32(tmp)), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint32 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, v) } + return reflect.ValueOf(uint32(tmp)).Convert(typ), nil case reflect.Uint64: // Uint64 // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of uint64 - tmp := toIntegerFloat(value) - if tmp < 0 || tmp > float_maxUint64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, value) - } else { - return reflect.ValueOf(uint64(tmp)), nil + tmp := toIntegerFloat(v) + if tmp < 0 || tmp > floatMaxUint64 { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, v) } + return reflect.ValueOf(uint64(tmp)).Convert(typ), nil case reflect.Float32: // Float32 - tmp := value.float64() + tmp := v.float64() tmp1 := tmp if 0 > tmp1 { tmp1 = -tmp1 } if tmp1 > 0 && (tmp1 < math.SmallestNonzeroFloat32 || tmp1 > math.MaxFloat32) { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, value) - } else { - return reflect.ValueOf(float32(tmp)), nil + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, v) } + return reflect.ValueOf(float32(tmp)).Convert(typ), nil case reflect.Float64: // Float64 - value := value.float64() - return reflect.ValueOf(float64(value)), nil + value := v.float64() + return reflect.ValueOf(value).Convert(typ), nil case reflect.String: // String - return reflect.ValueOf(value.string()), nil + return reflect.ValueOf(v.string()).Convert(typ), nil case reflect.Invalid: // Invalid case reflect.Complex64: // FIXME? Complex64 case reflect.Complex128: // FIXME? Complex128 @@ -919,29 +851,33 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { case reflect.Ptr: // FIXME? Ptr case reflect.UnsafePointer: // FIXME? UnsafePointer default: - switch value.kind { + switch v.kind { case valueObject: - object := value._object() - switch vl := object.value.(type) { - case *_goStructObject: // Struct + obj := v.object() + switch vl := obj.value.(type) { + case *goStructObject: // Struct return reflect.ValueOf(vl.value.Interface()), nil - case *_goMapObject: // Map + case *goMapObject: // Map return reflect.ValueOf(vl.value.Interface()), nil - case *_goArrayObject: // Array + case *goArrayObject: // Array return reflect.ValueOf(vl.value.Interface()), nil - case *_goSliceObject: // Slice + case *goSliceObject: // Slice return reflect.ValueOf(vl.value.Interface()), nil } - return reflect.ValueOf(value.exportNative()), nil + exported := reflect.ValueOf(v.export()) + if exported.Type().ConvertibleTo(typ) { + return exported.Convert(typ), nil + } + return reflect.Value{}, fmt.Errorf("TypeError: could not convert %v to reflect.Type: %v", exported, typ) case valueEmpty, valueResult, valueReference: // These are invalid, and should panic default: - return reflect.ValueOf(value.value), nil + return reflect.ValueOf(v.value), nil } } // FIXME Should this end up as a TypeError? - panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Kind: %v", value.kind, value, kind)) + panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Type: %v", v.kind, v, typ)) } func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error) { @@ -981,7 +917,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(int64(value)), nil + return reflect.ValueOf(value), nil case reflect.Uint: value, err := strconv.ParseUint(value, 0, 0) if err != nil { @@ -1011,7 +947,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(uint64(value)), nil + return reflect.ValueOf(value), nil case reflect.Float32: value, err := strconv.ParseFloat(value, 32) if err != nil { @@ -1023,7 +959,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(float64(value)), nil + return reflect.ValueOf(value), nil case reflect.String: return reflect.ValueOf(value), nil } @@ -1031,3 +967,18 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error // FIXME This should end up as a TypeError? panic(fmt.Errorf("invalid conversion of %q to reflect.Kind: %v", value, kind)) } + +// MarshalJSON implements json.Marshaller. +func (v Value) MarshalJSON() ([]byte, error) { + switch v.kind { + case valueUndefined, valueNull: + return []byte("null"), nil + case valueBoolean, valueNumber: + return json.Marshal(v.value) + case valueString: + return json.Marshal(v.string()) + case valueObject: + return v.Object().MarshalJSON() + } + return nil, fmt.Errorf("invalid type %v", v.kind) +} diff --git a/vendor/github.com/robertkrimen/otto/value_boolean.go b/vendor/github.com/robertkrimen/otto/value_boolean.go index b631507b0..670ecab07 100644 --- a/vendor/github.com/robertkrimen/otto/value_boolean.go +++ b/vendor/github.com/robertkrimen/otto/value_boolean.go @@ -7,37 +7,34 @@ import ( "unicode/utf16" ) -func (value Value) bool() bool { - if value.kind == valueBoolean { - return value.value.(bool) +func (v Value) bool() bool { + if v.kind == valueBoolean { + return v.value.(bool) } - if value.IsUndefined() { + if v.IsUndefined() || v.IsNull() { return false } - if value.IsNull() { - return false - } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: return value case int, int8, int16, int32, int64: - return 0 != reflect.ValueOf(value).Int() + return reflect.ValueOf(value).Int() != 0 case uint, uint8, uint16, uint32, uint64: - return 0 != reflect.ValueOf(value).Uint() + return reflect.ValueOf(value).Uint() != 0 case float32: - return 0 != value + return value != 0 case float64: if math.IsNaN(value) || value == 0 { return false } return true case string: - return 0 != len(value) + return len(value) != 0 case []uint16: - return 0 != len(utf16.Decode(value)) + return len(utf16.Decode(value)) != 0 } - if value.IsObject() { + if v.IsObject() { return true } - panic(fmt.Errorf("toBoolean(%T)", value.value)) + panic(fmt.Sprintf("unexpected boolean type %T", v.value)) } diff --git a/vendor/github.com/robertkrimen/otto/value_kind.gen.go b/vendor/github.com/robertkrimen/otto/value_kind.gen.go new file mode 100644 index 000000000..cf99c0a7f --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/value_kind.gen.go @@ -0,0 +1,31 @@ +// Code generated by "stringer -type=valueKind -trimprefix=value -output=value_kind.gen.go"; DO NOT EDIT. + +package otto + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[valueUndefined-0] + _ = x[valueNull-1] + _ = x[valueNumber-2] + _ = x[valueString-3] + _ = x[valueBoolean-4] + _ = x[valueObject-5] + _ = x[valueEmpty-6] + _ = x[valueResult-7] + _ = x[valueReference-8] +} + +const _valueKind_name = "UndefinedNullNumberStringBooleanObjectEmptyResultReference" + +var _valueKind_index = [...]uint8{0, 9, 13, 19, 25, 32, 38, 43, 49, 58} + +func (i valueKind) String() string { + if i < 0 || i >= valueKind(len(_valueKind_index)-1) { + return "valueKind(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _valueKind_name[_valueKind_index[i]:_valueKind_index[i+1]] +} diff --git a/vendor/github.com/robertkrimen/otto/value_number.go b/vendor/github.com/robertkrimen/otto/value_number.go index 8cbf136d2..6f14b4bb5 100644 --- a/vendor/github.com/robertkrimen/otto/value_number.go +++ b/vendor/github.com/robertkrimen/otto/value_number.go @@ -1,6 +1,7 @@ package otto import ( + "errors" "fmt" "math" "regexp" @@ -11,24 +12,25 @@ import ( var stringToNumberParseInteger = regexp.MustCompile(`^(?:0[xX])`) func parseNumber(value string) float64 { - value = strings.Trim(value, builtinString_trim_whitespace) + value = strings.Trim(value, builtinStringTrimWhitespace) if value == "" { return 0 } - parseFloat := false - if strings.IndexRune(value, '.') != -1 { + var parseFloat bool + switch { + case strings.ContainsRune(value, '.'): parseFloat = true - } else if stringToNumberParseInteger.MatchString(value) { + case stringToNumberParseInteger.MatchString(value): parseFloat = false - } else { + default: parseFloat = true } if parseFloat { number, err := strconv.ParseFloat(value, 64) - if err != nil && err.(*strconv.NumError).Err != strconv.ErrRange { + if err != nil && !errors.Is(err, strconv.ErrRange) { return math.NaN() } return number @@ -41,14 +43,14 @@ func parseNumber(value string) float64 { return float64(number) } -func (value Value) float64() float64 { - switch value.kind { +func (v Value) float64() float64 { + switch v.kind { case valueUndefined: return math.NaN() case valueNull: return 0 } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: if value { return 1 @@ -78,89 +80,65 @@ func (value Value) float64() float64 { return value case string: return parseNumber(value) - case *_object: + case *object: return value.DefaultValue(defaultValueHintNumber).float64() } - panic(fmt.Errorf("toFloat(%T)", value.value)) + panic(fmt.Errorf("toFloat(%T)", v.value)) } const ( - float_2_64 float64 = 18446744073709551616.0 - float_2_63 float64 = 9223372036854775808.0 - float_2_32 float64 = 4294967296.0 - float_2_31 float64 = 2147483648.0 - float_2_16 float64 = 65536.0 - integer_2_32 int64 = 4294967296 - integer_2_31 int64 = 2146483648 - sqrt1_2 float64 = math.Sqrt2 / 2 + sqrt1_2 float64 = math.Sqrt2 / 2 ) const ( - maxInt8 = math.MaxInt8 - minInt8 = math.MinInt8 - maxInt16 = math.MaxInt16 - minInt16 = math.MinInt16 - maxInt32 = math.MaxInt32 - minInt32 = math.MinInt32 - maxInt64 = math.MaxInt64 - minInt64 = math.MinInt64 - maxUint8 = math.MaxUint8 - maxUint16 = math.MaxUint16 maxUint32 = math.MaxUint32 - maxUint64 = math.MaxUint64 - maxUint = ^uint(0) - minUint = 0 maxInt = int(^uint(0) >> 1) - minInt = -maxInt - 1 - - // int64 - int64_maxInt int64 = int64(maxInt) - int64_minInt int64 = int64(minInt) - int64_maxInt8 int64 = math.MaxInt8 - int64_minInt8 int64 = math.MinInt8 - int64_maxInt16 int64 = math.MaxInt16 - int64_minInt16 int64 = math.MinInt16 - int64_maxInt32 int64 = math.MaxInt32 - int64_minInt32 int64 = math.MinInt32 - int64_maxUint8 int64 = math.MaxUint8 - int64_maxUint16 int64 = math.MaxUint16 - int64_maxUint32 int64 = math.MaxUint32 - - // float64 - float_maxInt float64 = float64(int(^uint(0) >> 1)) - float_minInt float64 = float64(int(-maxInt - 1)) - float_minUint float64 = float64(0) - float_maxUint float64 = float64(uint(^uint(0))) - float_minUint64 float64 = float64(0) - float_maxUint64 float64 = math.MaxUint64 - float_maxInt64 float64 = math.MaxInt64 - float_minInt64 float64 = math.MinInt64 + + // int64. + int64MaxInt8 int64 = math.MaxInt8 + int64MinInt8 int64 = math.MinInt8 + int64MaxInt16 int64 = math.MaxInt16 + int64MinInt16 int64 = math.MinInt16 + int64MaxInt32 int64 = math.MaxInt32 + int64MinInt32 int64 = math.MinInt32 + int64MaxUint8 int64 = math.MaxUint8 + int64MaxUint16 int64 = math.MaxUint16 + int64MaxUint32 int64 = math.MaxUint32 + + // float64. + floatMaxInt float64 = float64(int(^uint(0) >> 1)) + floatMinInt float64 = float64(-maxInt - 1) + floatMaxUint float64 = float64(^uint(0)) + floatMaxUint64 float64 = math.MaxUint64 + floatMaxInt64 float64 = math.MaxInt64 + floatMinInt64 float64 = math.MinInt64 ) func toIntegerFloat(value Value) float64 { float := value.float64() - if math.IsInf(float, 0) { - } else if math.IsNaN(float) { - float = 0 - } else if float > 0 { - float = math.Floor(float) - } else { - float = math.Ceil(float) + switch { + case math.IsInf(float, 0): + return float + case math.IsNaN(float): + return 0 + case float > 0: + return math.Floor(float) + default: + return math.Ceil(float) } - return float } -type _numberKind int +type numberKind int const ( - numberInteger _numberKind = iota // 3.0 => 3.0 - numberFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1 - numberInfinity // Infinity => 2**63-1 - numberNaN // NaN => 0 + numberInteger numberKind = iota // 3.0 => 3.0 + numberFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1 + numberInfinity // Infinity => 2**63-1 + numberNaN // NaN => 0 ) type _number struct { - kind _numberKind + kind numberKind int64 int64 float64 float64 } @@ -168,59 +146,60 @@ type _number struct { // FIXME // http://www.goinggo.net/2013/08/gustavos-ieee-754-brain-teaser.html // http://bazaar.launchpad.net/~niemeyer/strepr/trunk/view/6/strepr.go#L160 -func (value Value) number() (number _number) { - switch value := value.value.(type) { +func (v Value) number() _number { + var num _number + switch value := v.value.(type) { case int8: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int16: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint8: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint16: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint32: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int64: - number.int64 = value - return + num.int64 = value + return num } - float := value.float64() + float := v.float64() if float == 0 { - return + return num } - number.kind = numberFloat - number.float64 = float + num.kind = numberFloat + num.float64 = float if math.IsNaN(float) { - number.kind = numberNaN - return + num.kind = numberNaN + return num } if math.IsInf(float, 0) { - number.kind = numberInfinity + num.kind = numberInfinity } - if float >= float_maxInt64 { - number.int64 = math.MaxInt64 - return + if float >= floatMaxInt64 { + num.int64 = math.MaxInt64 + return num } - if float <= float_minInt64 { - number.int64 = math.MinInt64 - return + if float <= floatMinInt64 { + num.int64 = math.MinInt64 + return num } - integer := float64(0) + var integer float64 if float > 0 { integer = math.Floor(float) } else { @@ -228,97 +207,130 @@ func (value Value) number() (number _number) { } if float == integer { - number.kind = numberInteger + num.kind = numberInteger } - number.int64 = int64(float) - return + num.int64 = int64(float) + return num } -// ECMA 262: 9.5 +// ECMA 262: 9.5. func toInt32(value Value) int32 { - { - switch value := value.value.(type) { - case int8: - return int32(value) - case int16: - return int32(value) - case int32: - return value - } + switch value := value.value.(type) { + case int8: + return int32(value) + case int16: + return int32(value) + case int32: + return value } + floatValue := value.float64() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { - return 0 - } - if floatValue == 0 { // This will work for +0 & -0 + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 { return 0 } - remainder := math.Mod(floatValue, float_2_32) - if remainder > 0 { - remainder = math.Floor(remainder) - } else { - remainder = math.Ceil(remainder) + float_2_32 - } - if remainder > float_2_31 { - return int32(remainder - float_2_32) - } - return int32(remainder) + + // Convert to int64 before int32 to force correct wrapping. + return int32(int64(floatValue)) } func toUint32(value Value) uint32 { - { - switch value := value.value.(type) { - case int8: - return uint32(value) - case int16: - return uint32(value) - case uint8: - return uint32(value) - case uint16: - return uint32(value) - case uint32: - return value - } + switch value := value.value.(type) { + case int8: + return uint32(value) + case int16: + return uint32(value) + case uint8: + return uint32(value) + case uint16: + return uint32(value) + case uint32: + return value } + floatValue := value.float64() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { - return 0 - } - if floatValue == 0 { + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 { return 0 } - remainder := math.Mod(floatValue, float_2_32) - if remainder > 0 { - remainder = math.Floor(remainder) - } else { - remainder = math.Ceil(remainder) + float_2_32 - } - return uint32(remainder) + + // Convert to int64 before uint32 to force correct wrapping. + return uint32(int64(floatValue)) } +// ECMA 262 - 6.0 - 7.1.8. func toUint16(value Value) uint16 { - { - switch value := value.value.(type) { - case int8: - return uint16(value) - case uint8: - return uint16(value) - case uint16: - return value - } + switch value := value.value.(type) { + case int8: + return uint16(value) + case uint8: + return uint16(value) + case uint16: + return value } + floatValue := value.float64() - if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { + if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 { return 0 } - if floatValue == 0 { + + // Convert to int64 before uint16 to force correct wrapping. + return uint16(int64(floatValue)) +} + +// toIntSign returns sign of a number converted to -1, 0 ,1. +func toIntSign(value Value) int { + switch value := value.value.(type) { + case int8: + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } + + return 0 + case int16: + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } + + return 0 + case int32: + if value > 0 { + return 1 + } else if value < 0 { + return -1 + } + + return 0 + case uint8: + if value > 0 { + return 1 + } + + return 0 + case uint16: + if value > 0 { + return 1 + } + + return 0 + case uint32: + if value > 0 { + return 1 + } + return 0 } - remainder := math.Mod(floatValue, float_2_16) - if remainder > 0 { - remainder = math.Floor(remainder) - } else { - remainder = math.Ceil(remainder) + float_2_16 + floatValue := value.float64() + switch { + case math.IsNaN(floatValue), math.IsInf(floatValue, 0): + return 0 + case floatValue == 0: + return 0 + case floatValue > 0: + return 1 + default: + return -1 } - return uint16(remainder) } diff --git a/vendor/github.com/robertkrimen/otto/value_primitive.go b/vendor/github.com/robertkrimen/otto/value_primitive.go index 11ed329d1..23f8e81d4 100644 --- a/vendor/github.com/robertkrimen/otto/value_primitive.go +++ b/vendor/github.com/robertkrimen/otto/value_primitive.go @@ -1,23 +1,20 @@ package otto -func toStringPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueHintString) -} - func toNumberPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueHintNumber) + return toPrimitive(value, defaultValueHintNumber) } -func toPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueNoHint) +func toPrimitiveValue(value Value) Value { + return toPrimitive(value, defaultValueNoHint) } -func _toPrimitive(value Value, hint _defaultValueHint) Value { +func toPrimitive(value Value, hint defaultValueHint) Value { switch value.kind { case valueNull, valueUndefined, valueNumber, valueString, valueBoolean: return value case valueObject: - return value._object().DefaultValue(hint) + return value.object().DefaultValue(hint) + default: + panic(hereBeDragons(value.kind, value)) } - panic(hereBeDragons(value.kind, value)) } diff --git a/vendor/github.com/robertkrimen/otto/value_string.go b/vendor/github.com/robertkrimen/otto/value_string.go index 0fbfd6b25..2af5bc3a8 100644 --- a/vendor/github.com/robertkrimen/otto/value_string.go +++ b/vendor/github.com/robertkrimen/otto/value_string.go @@ -31,12 +31,15 @@ func floatToString(value float64, bitsize int) string { func numberToStringRadix(value Value, radix int) string { float := value.float64() - if math.IsNaN(float) { + switch { + case math.IsNaN(float): return "NaN" - } else if math.IsInf(float, 1) { + case math.IsInf(float, 1): return "Infinity" - } else if math.IsInf(float, -1) { + case math.IsInf(float, -1): return "-Infinity" + case float == 0: + return "0" } // FIXME This is very broken // Need to do proper radix conversion for floats, ... @@ -44,22 +47,22 @@ func numberToStringRadix(value Value, radix int) string { return strconv.FormatInt(int64(float), radix) } -func (value Value) string() string { - if value.kind == valueString { - switch value := value.value.(type) { +func (v Value) string() string { + if v.kind == valueString { + switch value := v.value.(type) { case string: return value case []uint16: return string(utf16.Decode(value)) } } - if value.IsUndefined() { + if v.IsUndefined() { return "undefined" } - if value.IsNull() { + if v.IsNull() { return "null" } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: return strconv.FormatBool(value) case int: @@ -96,8 +99,8 @@ func (value Value) string() string { return string(utf16.Decode(value)) case string: return value - case *_object: + case *object: return value.DefaultValue(defaultValueHintString).string() } - panic(fmt.Errorf("%v.string( %T)", value.value, value.value)) + panic(fmt.Errorf("%v.string( %T)", v.value, v.value)) } diff --git a/vendor/github.com/spf13/cast/.gitignore b/vendor/github.com/spf13/cast/.gitignore index 836562412..53053a8ac 100644 --- a/vendor/github.com/spf13/cast/.gitignore +++ b/vendor/github.com/spf13/cast/.gitignore @@ -21,3 +21,5 @@ _testmain.go *.exe *.test + +*.bench diff --git a/vendor/github.com/spf13/cast/Makefile b/vendor/github.com/spf13/cast/Makefile new file mode 100644 index 000000000..f01a5dbb6 --- /dev/null +++ b/vendor/github.com/spf13/cast/Makefile @@ -0,0 +1,40 @@ +GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2) + +.PHONY: check fmt lint test test-race vet test-cover-html help +.DEFAULT_GOAL := help + +check: test-race fmt vet lint ## Run tests and linters + +test: ## Run tests + go test ./... + +test-race: ## Run tests with race detector + go test -race ./... + +fmt: ## Run gofmt linter +ifeq "$(GOVERSION)" "12" + @for d in `go list` ; do \ + if [ "`gofmt -l -s $$GOPATH/src/$$d | tee /dev/stderr`" ]; then \ + echo "^ improperly formatted go files" && echo && exit 1; \ + fi \ + done +endif + +lint: ## Run golint linter + @for d in `go list` ; do \ + if [ "`golint $$d | tee /dev/stderr`" ]; then \ + echo "^ golint errors!" && echo && exit 1; \ + fi \ + done + +vet: ## Run go vet linter + @if [ "`go vet | tee /dev/stderr`" ]; then \ + echo "^ go vet errors!" && echo && exit 1; \ + fi + +test-cover-html: ## Generate test coverage report + go test -coverprofile=coverage.out -covermode=count + go tool cover -func=coverage.out + +help: + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md index af7a1fdc0..0e9e14593 100644 --- a/vendor/github.com/spf13/cast/README.md +++ b/vendor/github.com/spf13/cast/README.md @@ -1,5 +1,9 @@ -cast -==== +# cast + +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/ci.yaml) +[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast) Easy and safe casting from one type to another in Go @@ -14,7 +18,7 @@ interface into a bool, etc. Cast does this intelligently when an obvious conversion is possible. It doesn’t make any attempts to guess what you meant, for example you can only convert a string to an int when it is a string representation of an int such as “8”. Cast was developed for use in -[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON +[Hugo](https://gohugo.io), a website engine which uses YAML, TOML or JSON for meta data. ## Why use Cast? @@ -69,4 +73,3 @@ the code for a complete set. var eight interface{} = 8 cast.ToInt(eight) // 8 cast.ToInt(nil) // 0 - diff --git a/vendor/github.com/spf13/cast/cast.go b/vendor/github.com/spf13/cast/cast.go index de5a68678..0cfe9418d 100644 --- a/vendor/github.com/spf13/cast/cast.go +++ b/vendor/github.com/spf13/cast/cast.go @@ -3,76 +3,174 @@ // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. +// Package cast provides easy and safe casting in Go. package cast import "time" +// ToBool casts an interface to a bool type. func ToBool(i interface{}) bool { v, _ := ToBoolE(i) return v } +// ToTime casts an interface to a time.Time type. func ToTime(i interface{}) time.Time { v, _ := ToTimeE(i) return v } +func ToTimeInDefaultLocation(i interface{}, location *time.Location) time.Time { + v, _ := ToTimeInDefaultLocationE(i, location) + return v +} + +// ToDuration casts an interface to a time.Duration type. func ToDuration(i interface{}) time.Duration { v, _ := ToDurationE(i) return v } +// ToFloat64 casts an interface to a float64 type. func ToFloat64(i interface{}) float64 { v, _ := ToFloat64E(i) return v } +// ToFloat32 casts an interface to a float32 type. +func ToFloat32(i interface{}) float32 { + v, _ := ToFloat32E(i) + return v +} + +// ToInt64 casts an interface to an int64 type. func ToInt64(i interface{}) int64 { v, _ := ToInt64E(i) return v } +// ToInt32 casts an interface to an int32 type. +func ToInt32(i interface{}) int32 { + v, _ := ToInt32E(i) + return v +} + +// ToInt16 casts an interface to an int16 type. +func ToInt16(i interface{}) int16 { + v, _ := ToInt16E(i) + return v +} + +// ToInt8 casts an interface to an int8 type. +func ToInt8(i interface{}) int8 { + v, _ := ToInt8E(i) + return v +} + +// ToInt casts an interface to an int type. func ToInt(i interface{}) int { v, _ := ToIntE(i) return v } +// ToUint casts an interface to a uint type. +func ToUint(i interface{}) uint { + v, _ := ToUintE(i) + return v +} + +// ToUint64 casts an interface to a uint64 type. +func ToUint64(i interface{}) uint64 { + v, _ := ToUint64E(i) + return v +} + +// ToUint32 casts an interface to a uint32 type. +func ToUint32(i interface{}) uint32 { + v, _ := ToUint32E(i) + return v +} + +// ToUint16 casts an interface to a uint16 type. +func ToUint16(i interface{}) uint16 { + v, _ := ToUint16E(i) + return v +} + +// ToUint8 casts an interface to a uint8 type. +func ToUint8(i interface{}) uint8 { + v, _ := ToUint8E(i) + return v +} + +// ToString casts an interface to a string type. func ToString(i interface{}) string { v, _ := ToStringE(i) return v } +// ToStringMapString casts an interface to a map[string]string type. func ToStringMapString(i interface{}) map[string]string { v, _ := ToStringMapStringE(i) return v } +// ToStringMapStringSlice casts an interface to a map[string][]string type. func ToStringMapStringSlice(i interface{}) map[string][]string { v, _ := ToStringMapStringSliceE(i) return v } +// ToStringMapBool casts an interface to a map[string]bool type. func ToStringMapBool(i interface{}) map[string]bool { v, _ := ToStringMapBoolE(i) return v } +// ToStringMapInt casts an interface to a map[string]int type. +func ToStringMapInt(i interface{}) map[string]int { + v, _ := ToStringMapIntE(i) + return v +} + +// ToStringMapInt64 casts an interface to a map[string]int64 type. +func ToStringMapInt64(i interface{}) map[string]int64 { + v, _ := ToStringMapInt64E(i) + return v +} + +// ToStringMap casts an interface to a map[string]interface{} type. func ToStringMap(i interface{}) map[string]interface{} { v, _ := ToStringMapE(i) return v } +// ToSlice casts an interface to a []interface{} type. func ToSlice(i interface{}) []interface{} { v, _ := ToSliceE(i) return v } +// ToBoolSlice casts an interface to a []bool type. +func ToBoolSlice(i interface{}) []bool { + v, _ := ToBoolSliceE(i) + return v +} + +// ToStringSlice casts an interface to a []string type. func ToStringSlice(i interface{}) []string { v, _ := ToStringSliceE(i) return v } +// ToIntSlice casts an interface to a []int type. func ToIntSlice(i interface{}) []int { v, _ := ToIntSliceE(i) return v } + +// ToDurationSlice casts an interface to a []time.Duration type. +func ToDurationSlice(i interface{}) []time.Duration { + v, _ := ToDurationSliceE(i) + return v +} diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go index 237789644..cd9c04885 100644 --- a/vendor/github.com/spf13/cast/caste.go +++ b/vendor/github.com/spf13/cast/caste.go @@ -6,62 +6,102 @@ package cast import ( + "encoding/json" + "errors" "fmt" "html/template" "reflect" "strconv" "strings" "time" - - jww "github.com/spf13/jwalterweatherman" ) -// ToTimeE casts an empty interface to time.Time. +var errNegativeNotAllowed = errors.New("unable to cast negative value") + +type float64EProvider interface { + Float64() (float64, error) +} + +type float64Provider interface { + Float64() float64 +} + +// ToTimeE casts an interface to a time.Time type. func ToTimeE(i interface{}) (tim time.Time, err error) { + return ToTimeInDefaultLocationE(i, time.UTC) +} + +// ToTimeInDefaultLocationE casts an empty interface to time.Time, +// interpreting inputs without a timezone to be in the given location, +// or the local timezone if nil. +func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) { i = indirect(i) - jww.DEBUG.Println("ToTimeE called on type:", reflect.TypeOf(i)) - switch s := i.(type) { + switch v := i.(type) { case time.Time: - return s, nil + return v, nil case string: - d, e := StringToDate(s) - if e == nil { - return d, nil + return StringToDateInDefaultLocation(v, location) + case json.Number: + s, err1 := ToInt64E(v) + if err1 != nil { + return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) } - return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e) + return time.Unix(s, 0), nil + case int: + return time.Unix(int64(v), 0), nil + case int64: + return time.Unix(v, 0), nil + case int32: + return time.Unix(int64(v), 0), nil + case uint: + return time.Unix(int64(v), 0), nil + case uint64: + return time.Unix(int64(v), 0), nil + case uint32: + return time.Unix(int64(v), 0), nil default: - return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i) + return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) } } -// ToDurationE casts an empty interface to time.Duration. +// ToDurationE casts an interface to a time.Duration type. func ToDurationE(i interface{}) (d time.Duration, err error) { i = indirect(i) - jww.DEBUG.Println("ToDurationE called on type:", reflect.TypeOf(i)) switch s := i.(type) { case time.Duration: return s, nil - case int64: - d = time.Duration(s) + case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8: + d = time.Duration(ToInt64(s)) return - case float64: - d = time.Duration(s) + case float32, float64: + d = time.Duration(ToFloat64(s)) return case string: - d, err = time.ParseDuration(s) + if strings.ContainsAny(s, "nsuµmh") { + d, err = time.ParseDuration(s) + } else { + d, err = time.ParseDuration(s + "ns") + } + return + case float64EProvider: + var v float64 + v, err = s.Float64() + d = time.Duration(v) + return + case float64Provider: + d = time.Duration(s.Float64()) return default: - err = fmt.Errorf("Unable to Cast %#v to Duration\n", i) + err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i) return } } -// ToBoolE casts an empty interface to a bool. +// ToBoolE casts an interface to a bool type. func ToBoolE(i interface{}) (bool, error) { i = indirect(i) - jww.DEBUG.Println("ToBoolE called on type:", reflect.TypeOf(i)) switch b := i.(type) { case bool: @@ -69,21 +109,52 @@ func ToBoolE(i interface{}) (bool, error) { case nil: return false, nil case int: - if i.(int) != 0 { - return true, nil - } - return false, nil + return b != 0, nil + case int64: + return b != 0, nil + case int32: + return b != 0, nil + case int16: + return b != 0, nil + case int8: + return b != 0, nil + case uint: + return b != 0, nil + case uint64: + return b != 0, nil + case uint32: + return b != 0, nil + case uint16: + return b != 0, nil + case uint8: + return b != 0, nil + case float64: + return b != 0, nil + case float32: + return b != 0, nil + case time.Duration: + return b != 0, nil case string: return strconv.ParseBool(i.(string)) + case json.Number: + v, err := ToInt64E(b) + if err == nil { + return v != 0, nil + } + return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) default: - return false, fmt.Errorf("Unable to Cast %#v to bool", i) + return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) } } -// ToFloat64E casts an empty interface to a float64. +// ToFloat64E casts an interface to a float64 type. func ToFloat64E(i interface{}) (float64, error) { i = indirect(i) - jww.DEBUG.Println("ToFloat64E called on type:", reflect.TypeOf(i)) + + intv, ok := toInt(i) + if ok { + return float64(intv), nil + } switch s := i.(type) { case float64: @@ -98,63 +169,318 @@ func ToFloat64E(i interface{}) (float64, error) { return float64(s), nil case int8: return float64(s), nil - case int: + case uint: + return float64(s), nil + case uint64: + return float64(s), nil + case uint32: + return float64(s), nil + case uint16: + return float64(s), nil + case uint8: return float64(s), nil case string: v, err := strconv.ParseFloat(s, 64) if err == nil { - return float64(v), nil + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case float64EProvider: + v, err := s.Float64() + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case float64Provider: + return s.Float64(), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + } +} + +// ToFloat32E casts an interface to a float32 type. +func ToFloat32E(i interface{}) (float32, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return float32(intv), nil + } + + switch s := i.(type) { + case float64: + return float32(s), nil + case float32: + return s, nil + case int64: + return float32(s), nil + case int32: + return float32(s), nil + case int16: + return float32(s), nil + case int8: + return float32(s), nil + case uint: + return float32(s), nil + case uint64: + return float32(s), nil + case uint32: + return float32(s), nil + case uint16: + return float32(s), nil + case uint8: + return float32(s), nil + case string: + v, err := strconv.ParseFloat(s, 32) + if err == nil { + return float32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case float64EProvider: + v, err := s.Float64() + if err == nil { + return float32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case float64Provider: + return float32(s.Float64()), nil + case bool: + if s { + return 1, nil } - return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) + return 0, nil + case nil: + return 0, nil default: - return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) } } -// ToInt64E casts an empty interface to an int64. +// ToInt64E casts an interface to an int64 type. func ToInt64E(i interface{}) (int64, error) { i = indirect(i) - jww.DEBUG.Println("ToInt64E called on type:", reflect.TypeOf(i)) + + intv, ok := toInt(i) + if ok { + return int64(intv), nil + } switch s := i.(type) { case int64: return s, nil - case int: - return int64(s), nil case int32: return int64(s), nil case int16: return int64(s), nil case int8: return int64(s), nil + case uint: + return int64(s), nil + case uint64: + return int64(s), nil + case uint32: + return int64(s), nil + case uint16: + return int64(s), nil + case uint8: + return int64(s), nil + case float64: + return int64(s), nil + case float32: + return int64(s), nil case string: - v, err := strconv.ParseInt(s, 0, 0) + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) if err == nil { return v, nil } - return 0, fmt.Errorf("Unable to Cast %#v to int64", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case json.Number: + return ToInt64E(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + } +} + +// ToInt32E casts an interface to an int32 type. +func ToInt32E(i interface{}) (int32, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return int32(intv), nil + } + + switch s := i.(type) { + case int64: + return int32(s), nil + case int32: + return s, nil + case int16: + return int32(s), nil + case int8: + return int32(s), nil + case uint: + return int32(s), nil + case uint64: + return int32(s), nil + case uint32: + return int32(s), nil + case uint16: + return int32(s), nil + case uint8: + return int32(s), nil case float64: - return int64(s), nil + return int32(s), nil + case float32: + return int32(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + return int32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + case json.Number: + return ToInt32E(string(s)) case bool: - if bool(s) { - return int64(1), nil + if s { + return 1, nil } - return int64(0), nil + return 0, nil case nil: - return int64(0), nil + return 0, nil default: - return int64(0), fmt.Errorf("Unable to Cast %#v to int64", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) } } -// ToIntE casts an empty interface to an int. -func ToIntE(i interface{}) (int, error) { +// ToInt16E casts an interface to an int16 type. +func ToInt16E(i interface{}) (int16, error) { i = indirect(i) - jww.DEBUG.Println("ToIntE called on type:", reflect.TypeOf(i)) + + intv, ok := toInt(i) + if ok { + return int16(intv), nil + } switch s := i.(type) { - case int: + case int64: + return int16(s), nil + case int32: + return int16(s), nil + case int16: + return s, nil + case int8: + return int16(s), nil + case uint: + return int16(s), nil + case uint64: + return int16(s), nil + case uint32: + return int16(s), nil + case uint16: + return int16(s), nil + case uint8: + return int16(s), nil + case float64: + return int16(s), nil + case float32: + return int16(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + return int16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + case json.Number: + return ToInt16E(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + } +} + +// ToInt8E casts an interface to an int8 type. +func ToInt8E(i interface{}) (int8, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return int8(intv), nil + } + + switch s := i.(type) { + case int64: + return int8(s), nil + case int32: + return int8(s), nil + case int16: + return int8(s), nil + case int8: return s, nil + case uint: + return int8(s), nil + case uint64: + return int8(s), nil + case uint32: + return int8(s), nil + case uint16: + return int8(s), nil + case uint8: + return int8(s), nil + case float64: + return int8(s), nil + case float32: + return int8(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + return int8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + case json.Number: + return ToInt8E(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + } +} + +// ToIntE casts an interface to an int type. +func ToIntE(i interface{}) (int, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return intv, nil + } + + switch s := i.(type) { case int64: return int(s), nil case int32: @@ -163,23 +489,417 @@ func ToIntE(i interface{}) (int, error) { return int(s), nil case int8: return int(s), nil + case uint: + return int(s), nil + case uint64: + return int(s), nil + case uint32: + return int(s), nil + case uint16: + return int(s), nil + case uint8: + return int(s), nil + case float64: + return int(s), nil + case float32: + return int(s), nil case string: - v, err := strconv.ParseInt(s, 0, 0) + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) if err == nil { return int(v), nil } - return 0, fmt.Errorf("Unable to Cast %#v to int", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case json.Number: + return ToIntE(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + } +} + +// ToUintE casts an interface to a uint type. +func ToUintE(i interface{}) (uint, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + case json.Number: + return ToUintE(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case uint: + return s, nil + case uint64: + return uint(s), nil + case uint32: + return uint(s), nil + case uint16: + return uint(s), nil + case uint8: + return uint(s), nil case float64: - return int(s), nil + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + } +} + +// ToUint64E casts an interface to a uint64 type. +func ToUint64E(i interface{}) (uint64, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint64(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint64(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + case json.Number: + return ToUint64E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case uint: + return uint64(s), nil + case uint64: + return s, nil + case uint32: + return uint64(s), nil + case uint16: + return uint64(s), nil + case uint8: + return uint64(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil case bool: - if bool(s) { + if s { return 1, nil } return 0, nil case nil: return 0, nil default: - return 0, fmt.Errorf("Unable to Cast %#v to int", i) + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + } +} + +// ToUint32E casts an interface to a uint32 type. +func ToUint32E(i interface{}) (uint32, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint32(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + case json.Number: + return ToUint32E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case uint: + return uint32(s), nil + case uint64: + return uint32(s), nil + case uint32: + return s, nil + case uint16: + return uint32(s), nil + case uint8: + return uint32(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + } +} + +// ToUint16E casts an interface to a uint16 type. +func ToUint16E(i interface{}) (uint16, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint16(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + case json.Number: + return ToUint16E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case uint: + return uint16(s), nil + case uint64: + return uint16(s), nil + case uint32: + return uint16(s), nil + case uint16: + return s, nil + case uint8: + return uint16(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + } +} + +// ToUint8E casts an interface to a uint type. +func ToUint8E(i interface{}) (uint8, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + if intv < 0 { + return 0, errNegativeNotAllowed + } + return uint8(intv), nil + } + + switch s := i.(type) { + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) + if err == nil { + if v < 0 { + return 0, errNegativeNotAllowed + } + return uint8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) + case json.Number: + return ToUint8E(string(s)) + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case uint: + return uint8(s), nil + case uint64: + return uint8(s), nil + case uint32: + return uint8(s), nil + case uint16: + return uint8(s), nil + case uint8: + return s, nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) } } @@ -212,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} { return nil } - var errorType = reflect.TypeOf((*error)(nil)).Elem() - var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + errorType := reflect.TypeOf((*error)(nil)).Elem() + fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem() v := reflect.ValueOf(a) for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { @@ -222,10 +942,9 @@ func indirectToStringerOrError(a interface{}) interface{} { return v.Interface() } -// ToStringE casts an empty interface to a string. +// ToStringE casts an interface to a string type. func ToStringE(i interface{}) (string, error) { i = indirectToStringerOrError(i) - jww.DEBUG.Println("ToStringE called on type:", reflect.TypeOf(i)) switch s := i.(type) { case string: @@ -233,11 +952,31 @@ func ToStringE(i interface{}) (string, error) { case bool: return strconv.FormatBool(s), nil case float64: - return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil - case int64: - return strconv.FormatInt(i.(int64), 10), nil + return strconv.FormatFloat(s, 'f', -1, 64), nil + case float32: + return strconv.FormatFloat(float64(s), 'f', -1, 32), nil case int: - return strconv.FormatInt(int64(i.(int)), 10), nil + return strconv.Itoa(s), nil + case int64: + return strconv.FormatInt(s, 10), nil + case int32: + return strconv.Itoa(int(s)), nil + case int16: + return strconv.FormatInt(int64(s), 10), nil + case int8: + return strconv.FormatInt(int64(s), 10), nil + case uint: + return strconv.FormatUint(uint64(s), 10), nil + case uint64: + return strconv.FormatUint(uint64(s), 10), nil + case uint32: + return strconv.FormatUint(uint64(s), 10), nil + case uint16: + return strconv.FormatUint(uint64(s), 10), nil + case uint8: + return strconv.FormatUint(uint64(s), 10), nil + case json.Number: + return s.String(), nil case []byte: return string(s), nil case template.HTML: @@ -257,15 +996,13 @@ func ToStringE(i interface{}) (string, error) { case error: return s.Error(), nil default: - return "", fmt.Errorf("Unable to Cast %#v to string", i) + return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i) } } -// ToStringMapStringE casts an empty interface to a map[string]string. +// ToStringMapStringE casts an interface to a map[string]string type. func ToStringMapStringE(i interface{}) (map[string]string, error) { - jww.DEBUG.Println("ToStringMapStringE called on type:", reflect.TypeOf(i)) - - var m = map[string]string{} + m := map[string]string{} switch v := i.(type) { case map[string]string: @@ -285,16 +1022,17 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) { m[ToString(k)] = ToString(val) } return m, nil + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i) } } -// ToStringMapStringSliceE casts an empty interface to a map[string][]string. +// ToStringMapStringSliceE casts an interface to a map[string][]string type. func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { - jww.DEBUG.Println("ToStringMapStringSliceE called on type:", reflect.TypeOf(i)) - - var m = map[string][]string{} + m := map[string][]string{} switch v := i.(type) { case map[string][]string: @@ -310,7 +1048,14 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { } case map[string]interface{}: for k, val := range v { - m[ToString(k)] = []string{ToString(val)} + switch vt := val.(type) { + case []interface{}: + m[ToString(k)] = ToStringSlice(vt) + case []string: + m[ToString(k)] = vt + default: + m[ToString(k)] = []string{ToString(val)} + } } return m, nil case map[interface{}][]string: @@ -332,25 +1077,26 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { for k, val := range v { key, err := ToStringE(k) if err != nil { - return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) } value, err := ToStringSliceE(val) if err != nil { - return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) } m[key] = value } + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) } return m, nil } -// ToStringMapBoolE casts an empty interface to a map[string]bool. +// ToStringMapBoolE casts an interface to a map[string]bool type. func ToStringMapBoolE(i interface{}) (map[string]bool, error) { - jww.DEBUG.Println("ToStringMapBoolE called on type:", reflect.TypeOf(i)) - - var m = map[string]bool{} + m := map[string]bool{} switch v := i.(type) { case map[interface{}]interface{}: @@ -365,16 +1111,17 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) { return m, nil case map[string]bool: return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i) } } -// ToStringMapE casts an empty interface to a map[string]interface{}. +// ToStringMapE casts an interface to a map[string]interface{} type. func ToStringMapE(i interface{}) (map[string]interface{}, error) { - jww.DEBUG.Println("ToStringMapE called on type:", reflect.TypeOf(i)) - - var m = map[string]interface{}{} + m := map[string]interface{}{} switch v := i.(type) { case map[interface{}]interface{}: @@ -384,37 +1131,143 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) { return m, nil case map[string]interface{}: return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err default: - return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i) + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i) } } -// ToSliceE casts an empty interface to a []interface{}. -func ToSliceE(i interface{}) ([]interface{}, error) { - jww.DEBUG.Println("ToSliceE called on type:", reflect.TypeOf(i)) +// ToStringMapIntE casts an interface to a map[string]int{} type. +func ToStringMapIntE(i interface{}) (map[string]int, error) { + m := map[string]int{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt(val) + } + return m, nil + case map[string]int: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToIntE(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} +// ToStringMapInt64E casts an interface to a map[string]int64{} type. +func ToStringMapInt64E(i interface{}) (map[string]int64, error) { + m := map[string]int64{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt64(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt64(val) + } + return m, nil + case map[string]int64: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToInt64E(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} + +// ToSliceE casts an interface to a []interface{} type. +func ToSliceE(i interface{}) ([]interface{}, error) { var s []interface{} switch v := i.(type) { case []interface{}: - for _, u := range v { - s = append(s, u) - } - return s, nil + return append(s, v...), nil case []map[string]interface{}: for _, u := range v { s = append(s, u) } return s, nil default: - return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i)) + return s, fmt.Errorf("unable to cast %#v of type %T to []interface{}", i, i) } } -// ToStringSliceE casts an empty interface to a []string. -func ToStringSliceE(i interface{}) ([]string, error) { - jww.DEBUG.Println("ToStringSliceE called on type:", reflect.TypeOf(i)) +// ToBoolSliceE casts an interface to a []bool type. +func ToBoolSliceE(i interface{}) ([]bool, error) { + if i == nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + + switch v := i.(type) { + case []bool: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]bool, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToBoolE(s.Index(j).Interface()) + if err != nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + a[j] = val + } + return a, nil + default: + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } +} +// ToStringSliceE casts an interface to a []string type. +func ToStringSliceE(i interface{}) ([]string, error) { var a []string switch v := i.(type) { @@ -425,25 +1278,58 @@ func ToStringSliceE(i interface{}) ([]string, error) { return a, nil case []string: return v, nil + case []int8: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int32: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int64: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []float32: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []float64: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil case string: return strings.Fields(v), nil + case []error: + for _, err := range i.([]error) { + a = append(a, err.Error()) + } + return a, nil case interface{}: str, err := ToStringE(v) if err != nil { - return a, fmt.Errorf("Unable to Cast %#v to []string", i) + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) } return []string{str}, nil default: - return a, fmt.Errorf("Unable to Cast %#v to []string", i) + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) } } -// ToIntSliceE casts an empty interface to a []int. +// ToIntSliceE casts an interface to a []int type. func ToIntSliceE(i interface{}) ([]int, error) { - jww.DEBUG.Println("ToIntSliceE called on type:", reflect.TypeOf(i)) - if i == nil { - return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) } switch v := i.(type) { @@ -459,42 +1345,166 @@ func ToIntSliceE(i interface{}) ([]int, error) { for j := 0; j < s.Len(); j++ { val, err := ToIntE(s.Index(j).Interface()) if err != nil { - return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) } a[j] = val } return a, nil default: - return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) } } -// StringToDate casts an empty interface to a time.Time. +// ToDurationSliceE casts an interface to a []time.Duration type. +func ToDurationSliceE(i interface{}) ([]time.Duration, error) { + if i == nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + + switch v := i.(type) { + case []time.Duration: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]time.Duration, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToDurationE(s.Index(j).Interface()) + if err != nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + a[j] = val + } + return a, nil + default: + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } +} + +// StringToDate attempts to parse a string into a time.Time type using a +// predefined list of formats. If no suitable format is found, an error is +// returned. func StringToDate(s string) (time.Time, error) { - return parseDateWith(s, []string{ - time.RFC3339, - "2006-01-02T15:04:05", // iso8601 without timezone - time.RFC1123Z, - time.RFC1123, - time.RFC822Z, - time.RFC822, - time.ANSIC, - time.UnixDate, - time.RubyDate, - "2006-01-02 15:04:05Z07:00", - "02 Jan 06 15:04 MST", - "2006-01-02", - "02 Jan 2006", - "2006-01-02 15:04:05 -07:00", - "2006-01-02 15:04:05 -0700", - }) -} - -func parseDateWith(s string, dates []string) (d time.Time, e error) { - for _, dateType := range dates { - if d, e = time.Parse(dateType, s); e == nil { + return parseDateWith(s, time.UTC, timeFormats) +} + +// StringToDateInDefaultLocation casts an empty interface to a time.Time, +// interpreting inputs without a timezone to be in the given location, +// or the local timezone if nil. +func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) { + return parseDateWith(s, location, timeFormats) +} + +type timeFormatType int + +const ( + timeFormatNoTimezone timeFormatType = iota + timeFormatNamedTimezone + timeFormatNumericTimezone + timeFormatNumericAndNamedTimezone + timeFormatTimeOnly +) + +type timeFormat struct { + format string + typ timeFormatType +} + +func (f timeFormat) hasTimezone() bool { + // We don't include the formats with only named timezones, see + // https://github.com/golang/go/issues/19694#issuecomment-289103522 + return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone +} + +var timeFormats = []timeFormat{ + // Keep common formats at the top. + {"2006-01-02", timeFormatNoTimezone}, + {time.RFC3339, timeFormatNumericTimezone}, + {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone + {time.RFC1123Z, timeFormatNumericTimezone}, + {time.RFC1123, timeFormatNamedTimezone}, + {time.RFC822Z, timeFormatNumericTimezone}, + {time.RFC822, timeFormatNamedTimezone}, + {time.RFC850, timeFormatNamedTimezone}, + {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() + {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon + {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon + {"2006-01-02 15:04:05", timeFormatNoTimezone}, + {time.ANSIC, timeFormatNoTimezone}, + {time.UnixDate, timeFormatNamedTimezone}, + {time.RubyDate, timeFormatNumericTimezone}, + {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, + {"02 Jan 2006", timeFormatNoTimezone}, + {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, + {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, + {time.Kitchen, timeFormatTimeOnly}, + {time.Stamp, timeFormatTimeOnly}, + {time.StampMilli, timeFormatTimeOnly}, + {time.StampMicro, timeFormatTimeOnly}, + {time.StampNano, timeFormatTimeOnly}, +} + +func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) { + for _, format := range formats { + if d, e = time.Parse(format.format, s); e == nil { + + // Some time formats have a zone name, but no offset, so it gets + // put in that zone name (not the default one passed in to us), but + // without that zone's offset. So set the location manually. + if format.typ <= timeFormatNamedTimezone { + if location == nil { + location = time.Local + } + year, month, day := d.Date() + hour, min, sec := d.Clock() + d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location) + } + return } } - return d, fmt.Errorf("Unable to parse date: %s", s) + return d, fmt.Errorf("unable to parse date: %s", s) +} + +// jsonStringToObject attempts to unmarshall a string as JSON into +// the object passed as pointer. +func jsonStringToObject(s string, v interface{}) error { + data := []byte(s) + return json.Unmarshal(data, v) +} + +// toInt returns the int value of v if v or v's underlying type +// is an int. +// Note that this will return false for int64 etc. types. +func toInt(v interface{}) (int, bool) { + switch v := v.(type) { + case int: + return v, true + case time.Weekday: + return int(v), true + case time.Month: + return int(v), true + default: + return 0, false + } +} + +func trimZeroDecimal(s string) string { + var foundZero bool + for i := len(s); i > 0; i-- { + switch s[i-1] { + case '.': + if foundZero { + return s[:i-1] + } + case '0': + foundZero = true + default: + return s + } + } + return s } diff --git a/vendor/github.com/spf13/cast/timeformattype_string.go b/vendor/github.com/spf13/cast/timeformattype_string.go new file mode 100644 index 000000000..1524fc82c --- /dev/null +++ b/vendor/github.com/spf13/cast/timeformattype_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type timeFormatType"; DO NOT EDIT. + +package cast + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[timeFormatNoTimezone-0] + _ = x[timeFormatNamedTimezone-1] + _ = x[timeFormatNumericTimezone-2] + _ = x[timeFormatNumericAndNamedTimezone-3] + _ = x[timeFormatTimeOnly-4] +} + +const _timeFormatType_name = "timeFormatNoTimezonetimeFormatNamedTimezonetimeFormatNumericTimezonetimeFormatNumericAndNamedTimezonetimeFormatTimeOnly" + +var _timeFormatType_index = [...]uint8{0, 20, 43, 68, 101, 119} + +func (i timeFormatType) String() string { + if i < 0 || i >= timeFormatType(len(_timeFormatType_index)-1) { + return "timeFormatType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _timeFormatType_name[_timeFormatType_index[i]:_timeFormatType_index[i+1]] +} diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore index 36d1a84d3..c7b459e4d 100644 --- a/vendor/github.com/spf13/cobra/.gitignore +++ b/vendor/github.com/spf13/cobra/.gitignore @@ -19,6 +19,21 @@ _cgo_export.* _testmain.go -*.exe +# Vim files https://github.com/github/gitignore/blob/master/Global/Vim.gitignore +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags +*.exe cobra.test +bin + +.idea/ +*.iml diff --git a/vendor/github.com/spf13/cobra/.golangci.yml b/vendor/github.com/spf13/cobra/.golangci.yml new file mode 100644 index 000000000..2c8f4808c --- /dev/null +++ b/vendor/github.com/spf13/cobra/.golangci.yml @@ -0,0 +1,57 @@ +# Copyright 2013-2023 The Cobra Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +run: + deadline: 5m + +linters: + disable-all: true + enable: + #- bodyclose + # - deadcode ! deprecated since v1.49.0; replaced by 'unused' + #- depguard + #- dogsled + #- dupl + - errcheck + #- exhaustive + #- funlen + #- gochecknoinits + - goconst + - gocritic + #- gocyclo + - gofmt + - goimports + #- gomnd + #- goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + #- lll + - misspell + #- nakedret + #- noctx + - nolintlint + #- rowserrcheck + #- scopelint + - staticcheck + #- structcheck ! deprecated since v1.49.0; replaced by 'unused' + - stylecheck + #- typecheck + - unconvert + #- unparam + - unused + # - varcheck ! deprecated since v1.49.0; replaced by 'unused' + #- whitespace + fast: false diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml deleted file mode 100644 index 2bbf62312..000000000 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go -go: - - 1.4.3 - - 1.5.4 - - 1.6.2 - - tip - -matrix: - allow_failures: - - go: tip - -before_install: - - mkdir -p bin - - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.4.3/shellcheck - - chmod +x bin/shellcheck -script: - - PATH=$PATH:$PWD/bin go test -v ./... - - go build diff --git a/vendor/github.com/spf13/cobra/CONDUCT.md b/vendor/github.com/spf13/cobra/CONDUCT.md new file mode 100644 index 000000000..9d16f88fd --- /dev/null +++ b/vendor/github.com/spf13/cobra/CONDUCT.md @@ -0,0 +1,37 @@ +## Cobra User Contract + +### Versioning +Cobra will follow a steady release cadence. Non breaking changes will be released as minor versions quarterly. Patch bug releases are at the discretion of the maintainers. Users can expect security patch fixes to be released within relatively short order of a CVE becoming known. For more information on security patch fixes see the CVE section below. Releases will follow [Semantic Versioning](https://semver.org/). Users tracking the Master branch should expect unpredictable breaking changes as the project continues to move forward. For stability, it is highly recommended to use a release. + +### Backward Compatibility +We will maintain two major releases in a moving window. The N-1 release will only receive bug fixes and security updates and will be dropped once N+1 is released. + +### Deprecation +Deprecation of Go versions or dependent packages will only occur in major releases. To reduce the change of this taking users by surprise, any large deprecation will be preceded by an announcement in the [#cobra slack channel](https://gophers.slack.com/archives/CD3LP1199) and an Issue on Github. + +### CVE +Maintainers will make every effort to release security patches in the case of a medium to high severity CVE directly impacting the library. The speed in which these patches reach a release is up to the discretion of the maintainers. A low severity CVE may be a lower priority than a high severity one. + +### Communication +Cobra maintainers will use GitHub issues and the [#cobra slack channel](https://gophers.slack.com/archives/CD3LP1199) as the primary means of communication with the community. This is to foster open communication with all users and contributors. + +### Breaking Changes +Breaking changes are generally allowed in the master branch, as this is the branch used to develop the next release of Cobra. + +There may be times, however, when master is closed for breaking changes. This is likely to happen as we near the release of a new version. + +Breaking changes are not allowed in release branches, as these represent minor versions that have already been released. These version have consumers who expect the APIs, behaviors, etc, to remain stable during the lifetime of the patch stream for the minor release. + +Examples of breaking changes include: +- Removing or renaming exported constant, variable, type, or function. +- Updating the version of critical libraries such as `spf13/pflag`, `spf13/viper` etc... + - Some version updates may be acceptable for picking up bug fixes, but maintainers must exercise caution when reviewing. + +There may, at times, need to be exceptions where breaking changes are allowed in release branches. These are at the discretion of the project's maintainers, and must be carefully considered before merging. + +### CI Testing +Maintainers will ensure the Cobra test suite utilizes the current supported versions of Golang. + +### Disclaimer +Changes to this document and the contents therein are at the discretion of the maintainers. +None of the contents of this document are legally binding in any way to the maintainers or the users. diff --git a/vendor/github.com/spf13/cobra/CONTRIBUTING.md b/vendor/github.com/spf13/cobra/CONTRIBUTING.md new file mode 100644 index 000000000..6f356e6a8 --- /dev/null +++ b/vendor/github.com/spf13/cobra/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing to Cobra + +Thank you so much for contributing to Cobra. We appreciate your time and help. +Here are some guidelines to help you get started. + +## Code of Conduct + +Be kind and respectful to the members of the community. Take time to educate +others who are seeking help. Harassment of any kind will not be tolerated. + +## Questions + +If you have questions regarding Cobra, feel free to ask it in the community +[#cobra Slack channel][cobra-slack] + +## Filing a bug or feature + +1. Before filing an issue, please check the existing issues to see if a + similar one was already opened. If there is one already opened, feel free + to comment on it. +1. If you believe you've found a bug, please provide detailed steps of + reproduction, the version of Cobra and anything else you believe will be + useful to help troubleshoot it (e.g. OS environment, environment variables, + etc...). Also state the current behavior vs. the expected behavior. +1. If you'd like to see a feature or an enhancement please open an issue with + a clear title and description of what the feature is and why it would be + beneficial to the project and its users. + +## Submitting changes + +1. CLA: Upon submitting a Pull Request (PR), contributors will be prompted to + sign a CLA. Please sign the CLA :slightly_smiling_face: +1. Tests: If you are submitting code, please ensure you have adequate tests + for the feature. Tests can be run via `go test ./...` or `make test`. +1. Since this is golang project, ensure the new code is properly formatted to + ensure code consistency. Run `make all`. + +### Quick steps to contribute + +1. Fork the project. +1. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`) +1. Create your feature branch (`git checkout -b my-new-feature`) +1. Make changes and run tests (`make test`) +1. Add them to staging (`git add .`) +1. Commit your changes (`git commit -m 'Add some feature'`) +1. Push to the branch (`git push origin my-new-feature`) +1. Create new pull request + + +[cobra-slack]: https://gophers.slack.com/archives/CD3LP1199 diff --git a/vendor/github.com/spf13/cobra/MAINTAINERS b/vendor/github.com/spf13/cobra/MAINTAINERS new file mode 100644 index 000000000..4c5ac3dd9 --- /dev/null +++ b/vendor/github.com/spf13/cobra/MAINTAINERS @@ -0,0 +1,13 @@ +maintainers: +- spf13 +- johnSchnake +- jpmcb +- marckhouzam +inactive: +- anthonyfok +- bep +- bogem +- broady +- eparis +- jharshman +- wfernandes diff --git a/vendor/github.com/spf13/cobra/Makefile b/vendor/github.com/spf13/cobra/Makefile new file mode 100644 index 000000000..0da8d7aa0 --- /dev/null +++ b/vendor/github.com/spf13/cobra/Makefile @@ -0,0 +1,35 @@ +BIN="./bin" +SRC=$(shell find . -name "*.go") + +ifeq (, $(shell which golangci-lint)) +$(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh") +endif + +.PHONY: fmt lint test install_deps clean + +default: all + +all: fmt test + +fmt: + $(info ******************** checking formatting ********************) + @test -z $(shell gofmt -l $(SRC)) || (gofmt -d $(SRC); exit 1) + +lint: + $(info ******************** running lint tools ********************) + golangci-lint run -v + +test: install_deps + $(info ******************** running tests ********************) + go test -v ./... + +richtest: install_deps + $(info ******************** running tests with kyoh86/richgo ********************) + richgo test -v ./... + +install_deps: + $(info ******************** downloading dependencies ********************) + go get -v ./... + +clean: + rm -rf $(BIN) diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 34c79eb8e..6444f4b7f 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -1,64 +1,35 @@ -![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) +![cobra logo](assets/CobraMain.png) -Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files. +Cobra is a library for creating powerful modern CLI applications. -Many of the most widely used Go projects are built using Cobra including: +Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), +[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to +name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra. -* [Kubernetes](http://kubernetes.io/) -* [Hugo](http://gohugo.io) -* [rkt](https://github.com/coreos/rkt) -* [etcd](https://github.com/coreos/etcd) -* [Docker (distribution)](https://github.com/docker/distribution) -* [OpenShift](https://www.openshift.com/) -* [Delve](https://github.com/derekparker/delve) -* [GopherJS](http://www.gopherjs.org/) -* [CockroachDB](http://www.cockroachlabs.com/) -* [Bleve](http://www.blevesearch.com/) -* [ProjectAtomic (enterprise)](http://www.projectatomic.io/) -* [Parse (CLI)](https://parse.com/) -* [GiantSwarm's swarm](https://github.com/giantswarm/cli) -* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) - - -[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) -[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) -[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) - -![cobra](https://cloud.githubusercontent.com/assets/173412/10911369/84832a8e-8212-11e5-9f82-cc96660a4794.gif) +[![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) +[![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra) +[![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199) # Overview Cobra is a library providing a simple interface to create powerful modern CLI interfaces similar to git & go tools. -Cobra is also an application that will generate your application scaffolding to rapidly -develop a Cobra-based application. - Cobra provides: * Easy subcommand-based CLIs: `app server`, `app fetch`, etc. * Fully POSIX-compliant flags (including short & long versions) * Nested subcommands * Global, local and cascading flags -* Easy generation of applications & commands with `cobra create appname` & `cobra add cmdname` * Intelligent suggestions (`app srver`... did you mean `app server`?) * Automatic help generation for commands and flags -* Automatic detailed help for `app help [command]` +* Grouping help for subcommands * Automatic help flag recognition of `-h`, `--help`, etc. -* Automatically generated bash autocomplete for your application +* Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell) * Automatically generated man pages for your application * Command aliases so you can change things without breaking them -* The flexibilty to define your own help, usage, etc. -* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps - -Cobra has an exceptionally clean interface and simple design without needless -constructors or initialization methods. - -Applications built with Cobra commands are designed to be as user-friendly as -possible. Flags can be placed before or after the command (as long as a -confusing space isn’t provided). Both short and long flags can be used. A -command need not even be fully typed. Help is automatically generated and -available for the application or for a specific command using either the help -command or the `--help` flag. +* The flexibility to define your own help, usage, etc. +* Optional seamless integration with [viper](https://github.com/spf13/viper) for 12-factor apps # Concepts @@ -66,23 +37,23 @@ Cobra is built on a structure of commands, arguments & flags. **Commands** represent actions, **Args** are things and **Flags** are modifiers for those actions. -The best applications will read like sentences when used. Users will know how -to use the application because they will natively understand how to use it. +The best applications read like sentences when used, and as a result, users +intuitively know how to interact with them. The pattern to follow is -`APPNAME VERB NOUN --ADJECTIVE.` +`APPNAME VERB NOUN --ADJECTIVE` or -`APPNAME COMMAND ARG --FLAG` +`APPNAME COMMAND ARG --FLAG`. A few good real world examples may better illustrate this point. In the following example, 'server' is a command, and 'port' is a flag: - > hugo server --port=1313 + hugo server --port=1313 In this command we are telling Git to clone the url bare. - > git clone URL --bare + git clone URL --bare ## Commands @@ -92,20 +63,11 @@ have children commands and optionally run an action. In the example above, 'server' is the command. -A Command has the following structure: - -```go -type Command struct { - Use string // The one-line usage message. - Short string // The short description shown in the 'help' output. - Long string // The long message shown in the 'help ' output. - Run func(cmd *Command, args []string) // Run runs the command. -} -``` +[More about cobra.Command](https://pkg.go.dev/github.com/spf13/cobra#Command) ## Flags -A Flag is a way to modify the behavior of a command. Cobra supports +A flag is a way to modify the behavior of a command. Cobra supports fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). A Cobra command can define flags that persist through to children commands and flags that are only available to that command. @@ -113,780 +75,38 @@ and flags that are only available to that command. In the example above, 'port' is the flag. Flag functionality is provided by the [pflag -library](https://github.com/ogier/pflag), a fork of the flag standard library +library](https://github.com/spf13/pflag), a fork of the flag standard library which maintains the same interface while adding POSIX compliance. -## Usage - -Cobra works by creating a set of commands and then organizing them into a tree. -The tree defines the structure of the application. - -Once each command is defined with its corresponding flags, then the -tree is assigned to the commander which is finally executed. - # Installing Using Cobra is easy. First, use `go get` to install the latest version -of the library. This command will install the `cobra` generator executible -along with the library: - - > go get -v github.com/spf13/cobra/cobra - -Next, include Cobra in your application: - -```go -import "github.com/spf13/cobra" -``` - -# Getting Started - -While you are welcome to provide your own organization, typically a Cobra based -application will follow the following organizational structure. - -``` - ▾ appName/ - ▾ cmd/ - add.go - your.go - commands.go - here.go - main.go -``` - -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. - -```go -package main - -import "{pathToYourApp}/cmd" - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} -``` - -## Using the Cobra Generator - -Cobra provides its own program that will create your application and add any -commands you want. It's the easiest way to incorporate Cobra into your application. - -### cobra init - -The `cobra init [yourApp]` command will create your initial application code -for you. It is a very powerful application that will populate your program with -the right structure so you can immediately enjoy all the benefits of Cobra. It -will also automatically apply the license you specify to your application. - -Cobra init is pretty smart. You can provide it a full path, or simply a path -similar to what is expected in the import. - -``` -cobra init github.com/spf13/newAppName -``` - -### cobra add - -Once an application is initialized Cobra can create additional commands for you. -Let's say you created an app and you wanted the following commands for it: - -* app serve -* app config -* app config create - -In your project directory (where your main.go file is) you would run the following: - -``` -cobra add serve -cobra add config -cobra add create -p 'configCmd' -``` - -Once you have run these three commands you would have an app structure that would look like: - -``` - ▾ app/ - ▾ cmd/ - serve.go - config.go - create.go - main.go -``` - -at this point you can run `go run main.go` and it would run your app. `go run -main.go serve`, `go run main.go config`, `go run main.go config create` along -with `go run main.go help serve`, etc would all work. - -Obviously you haven't added your own code to these yet, the commands are ready -for you to give them their tasks. Have fun. - -### Configuring the cobra generator - -The cobra generator will be easier to use if you provide a simple configuration -file which will help you eliminate providing a bunch of repeated information in -flags over and over. - -An example ~/.cobra.yaml file: - -```yaml -author: Steve Francia -license: MIT -``` - -You can specify no license by setting `license` to `none` or you can specify -a custom license: - -```yaml -license: - header: This file is part of {{ .appName }}. - text: | - {{ .copyright }} - - This is my license. There are many like it, but this one is mine. - My license is my best friend. It is my life. I must master it as I must - master my life. -``` - -## Manually implementing Cobra - -To manually implement cobra you need to create a bare main.go file and a RootCmd file. -You will optionally provide additional commands as you see fit. - -### Create the root command - -The root command represents your binary itself. - - -#### Manually create rootCmd - -Cobra doesn't require any special constructors. Simply create your commands. - -Ideally you place this in app/cmd/root.go: - -```go -var RootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, -} -``` - -You will additionally define flags and handle configuration in your init() function. - -for example cmd/root.go: - -```go -func init() { - cobra.OnInitialize(initConfig) - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") - RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") - RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") - RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") - viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) - viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") -} -``` - -### Create your main.go - -With the root command you need to have your main function execute it. -Execute should be run on the root for clarity, though it can be called on any command. - -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. - -```go -package main - -import "{pathToYourApp}/cmd" - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} -``` - - -### Create additional commands - -Additional commands can be defined and typically are each given their own file -inside of the cmd/ directory. - -If you wanted to create a version command you would create cmd/version.go and -populate it with the following: - -```go -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - RootCmd.AddCommand(versionCmd) -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, -} -``` - -### Attach command to its parent - - -If you notice in the above example we attach the command to its parent. In -this case the parent is the rootCmd. In this example we are attaching it to the -root, but commands can be attached at any level. - -```go -RootCmd.AddCommand(versionCmd) -``` - -### Remove a command from its parent - -Removing a command is not a common action in simple programs, but it allows 3rd -parties to customize an existing command tree. +of the library. -In this example, we remove the existing `VersionCmd` command of an existing -root command, and we replace it with our own version: - -```go -mainlib.RootCmd.RemoveCommand(mainlib.VersionCmd) -mainlib.RootCmd.AddCommand(versionCmd) -``` - -## Working with Flags - -Flags provide modifiers to control how the action command operates. - -### Assign flags to a command - -Since the flags are defined and used in different locations, we need to -define a variable outside with the correct scope to assign the flag to -work with. - -```go -var Verbose bool -var Source string -``` - -There are two different approaches to assign a flag. - -### Persistent Flags - -A flag can be 'persistent' meaning that this flag will be available to the -command it's assigned to as well as every command under that command. For -global flags, assign a flag as a persistent flag on the root. - -```go -RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") -``` - -### Local Flags - -A flag can also be assigned locally which will only apply to that specific command. - -```go -RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") -``` - - -## Example - -In the example below, we have defined three commands. Two are at the top level -and one (cmdTimes) is a child of one of the top commands. In this case the root -is not executable meaning that a subcommand is required. This is accomplished -by not providing a 'Run' for the 'rootCmd'. - -We have only defined one flag for a single command. - -More documentation about flags is available at https://github.com/spf13/pflag - -```go -package main - -import ( - "fmt" - "strings" - - "github.com/spf13/cobra" -) - -func main() { - - var echoTimes int - - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. - For many years people have printed back to the screen. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. - Echo works a lot like print, except it has a child command. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdTimes = &cobra.Command{ - Use: "times [# times] [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing - a count and a string.`, - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } - - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() -} ``` - -For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). - -## The Help Command - -Cobra automatically adds a help command to your application when you have subcommands. -This will be called when a user runs 'app help'. Additionally, help will also -support all other commands as input. Say, for instance, you have a command called -'create' without any additional configuration; Cobra will work when 'app help -create' is called. Every command will automatically have the '--help' flag added. - -### Example - -The following output is automatically generated by Cobra. Nothing beyond the -command and flag definitions are needed. - - > hugo help - - hugo is the main command, used to build your Hugo site. - - Hugo is a Fast and Flexible Static Site Generator - built with love by spf13 and friends in Go. - - Complete documentation is available at http://gohugo.io/. - - Usage: - hugo [flags] - hugo [command] - - Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. - - Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - - Use "hugo [command] --help" for more information about a command. - - -Help is just a command like any other. There is no special logic or behavior -around it. In fact, you can provide your own if you want. - -### Defining your own help - -You can provide your own Help command or your own template for the default command to use. - -The default help command is - -```go -func (c *Command) initHelp() { - if c.helpCommand == nil { - c.helpCommand = &Command{ - Use: "help [command]", - Short: "Help about any command", - Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - Run: c.HelpFunc(), - } - } - c.AddCommand(c.helpCommand) -} +go get -u github.com/spf13/cobra@latest ``` -You can provide your own command, function or template through the following methods: - -```go -command.SetHelpCommand(cmd *Command) - -command.SetHelpFunc(f func(*Command, []string)) - -command.SetHelpTemplate(s string) -``` - -The latter two will also apply to any children commands. - -## Usage - -When the user provides an invalid flag or invalid command, Cobra responds by -showing the user the 'usage'. - -### Example -You may recognize this from the help above. That's because the default help -embeds the usage as part of its output. - - Usage: - hugo [flags] - hugo [command] - - Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. - - Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - -### Defining your own usage -You can provide your own usage function or template for Cobra to use. - -The default usage function is: - -```go -return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) - return err -} -``` - -Like help, the function and template are overridable through public methods: - -```go -command.SetUsageFunc(f func(*Command) error) - -command.SetUsageTemplate(s string) -``` - -## PreRun or PostRun Hooks - -It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherrited by children if they do not declare their own. These function are run in the following order: - -- `PersistentPreRun` -- `PreRun` -- `Run` -- `PostRun` -- `PersistentPostRun` - -An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: - -```go -package main - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func main() { - - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } - - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } - - rootCmd.AddCommand(subCmd) - - rootCmd.SetArgs([]string{""}) - _ = rootCmd.Execute() - fmt.Print("\n") - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - _ = rootCmd.Execute() -} -``` - - -## Alternative Error Handling - -Cobra also has functions where the return signature is an error. This allows for errors to bubble up to the top, -providing a way to handle the errors in one location. The current list of functions that return an error is: - -* PersistentPreRunE -* PreRunE -* RunE -* PostRunE -* PersistentPostRunE - -If you would like to silence the default `error` and `usage` output in favor of your own, you can set `SilenceUsage` -and `SilenceErrors` to `false` on the command. A child command respects these flags if they are set on the parent -command. - -**Example Usage using RunE:** - -```go -package main - -import ( - "errors" - "log" - - "github.com/spf13/cobra" -) - -func main() { - var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - RunE: func(cmd *cobra.Command, args []string) error { - // Do Stuff Here - return errors.New("some random error") - }, - } - - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } -} -``` - -## Suggestions when "unknown command" happens - -Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: - -``` -$ hugo srever -Error: unknown command "srever" for "hugo" - -Did you mean this? - server - -Run 'hugo --help' for usage. -``` - -Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. - -If you need to disable suggestions or tweak the string distance in your command, use: - -```go -command.DisableSuggestions = true -``` - -or +Next, include Cobra in your application: ```go -command.SuggestionsMinimumDistance = 1 +import "github.com/spf13/cobra" ``` -You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example: - -``` -$ kubectl remove -Error: unknown command "remove" for "kubectl" +# Usage +`cobra-cli` is a command line program to generate cobra applications and command files. +It will bootstrap your application scaffolding to rapidly +develop a Cobra-based application. It is the easiest way to incorporate Cobra into your application. -Did you mean this? - delete +It can be installed by running: -Run 'kubectl help' for usage. ``` - -## Generating Markdown-formatted documentation for your command - -Cobra can generate a Markdown-formatted document based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Markdown Docs](doc/md_docs.md). - -## Generating man pages for your command - -Cobra can generate a man page based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Man Docs](doc/man_docs.md). - -## Generating bash completions for your command - -Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). - -## Debugging - -Cobra provides a ‘DebugFlags’ method on a command which, when called, will print -out everything Cobra knows about the flags for each command. - -### Example - -```go -command.DebugFlags() +go install github.com/spf13/cobra-cli@latest ``` -## Release Notes -* **0.9.0** June 17, 2014 - * flags can appears anywhere in the args (provided they are unambiguous) - * --help prints usage screen for app or command - * Prefix matching for commands - * Cleaner looking help and usage output - * Extensive test suite -* **0.8.0** Nov 5, 2013 - * Reworked interface to remove commander completely - * Command now primary structure - * No initialization needed - * Usage & Help templates & functions definable at any level - * Updated Readme -* **0.7.0** Sept 24, 2013 - * Needs more eyes - * Test suite - * Support for automatic error messages - * Support for help command - * Support for printing to any io.Writer instead of os.Stderr - * Support for persistent flags which cascade down tree - * Ready for integration into Hugo -* **0.1.0** Sept 3, 2013 - * Implement first draft - -## Extensions - -Libraries for extending Cobra: - -* [cmdns](https://github.com/gosuri/cmdns): Enables name spacing a command's immediate children. It provides an alternative way to structure subcommands, similar to `heroku apps:create` and `ovrclk clusters:launch`. - -## ToDo -* Launch proper documentation site - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request - -## Contributors - -Names in no particular order: - -* [spf13](https://github.com/spf13), -[eparis](https://github.com/eparis), -[bep](https://github.com/bep), and many more! - -## License +For complete details on using the Cobra-CLI generator, please read [The Cobra Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) -Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) +For complete details on using the Cobra library, please read the [The Cobra User Guide](site/content/user_guide.md). +# License -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/spf13/cobra/trend.png)](https://bitdeli.com/free "Bitdeli Badge") +Cobra is released under the Apache 2.0 license. See [LICENSE.txt](LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/active_help.go b/vendor/github.com/spf13/cobra/active_help.go new file mode 100644 index 000000000..25c30e3cc --- /dev/null +++ b/vendor/github.com/spf13/cobra/active_help.go @@ -0,0 +1,60 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "fmt" + "os" +) + +const ( + activeHelpMarker = "_activeHelp_ " + // The below values should not be changed: programs will be using them explicitly + // in their user documentation, and users will be using them explicitly. + activeHelpEnvVarSuffix = "ACTIVE_HELP" + activeHelpGlobalEnvVar = configEnvVarGlobalPrefix + "_" + activeHelpEnvVarSuffix + activeHelpGlobalDisable = "0" +) + +// AppendActiveHelp adds the specified string to the specified array to be used as ActiveHelp. +// Such strings will be processed by the completion script and will be shown as ActiveHelp +// to the user. +// The array parameter should be the array that will contain the completions. +// This function can be called multiple times before and/or after completions are added to +// the array. Each time this function is called with the same array, the new +// ActiveHelp line will be shown below the previous ones when completion is triggered. +func AppendActiveHelp(compArray []string, activeHelpStr string) []string { + return append(compArray, fmt.Sprintf("%s%s", activeHelpMarker, activeHelpStr)) +} + +// GetActiveHelpConfig returns the value of the ActiveHelp environment variable +// _ACTIVE_HELP where is the name of the root command in upper +// case, with all non-ASCII-alphanumeric characters replaced by `_`. +// It will always return "0" if the global environment variable COBRA_ACTIVE_HELP +// is set to "0". +func GetActiveHelpConfig(cmd *Command) string { + activeHelpCfg := os.Getenv(activeHelpGlobalEnvVar) + if activeHelpCfg != activeHelpGlobalDisable { + activeHelpCfg = os.Getenv(activeHelpEnvVar(cmd.Root().Name())) + } + return activeHelpCfg +} + +// activeHelpEnvVar returns the name of the program-specific ActiveHelp environment +// variable. It has the format _ACTIVE_HELP where is the name of the +// root command in upper case, with all non-ASCII-alphanumeric characters replaced by `_`. +func activeHelpEnvVar(name string) string { + return configEnvVar(name, activeHelpEnvVarSuffix) +} diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go new file mode 100644 index 000000000..ed1e70cea --- /dev/null +++ b/vendor/github.com/spf13/cobra/args.go @@ -0,0 +1,131 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "fmt" + "strings" +) + +type PositionalArgs func(cmd *Command, args []string) error + +// legacyArgs validation has the following behaviour: +// - root commands with no subcommands can take arbitrary arguments +// - root commands with subcommands will do subcommand validity checking +// - subcommands will always accept arbitrary arguments +func legacyArgs(cmd *Command, args []string) error { + // no subcommand, always take args + if !cmd.HasSubCommands() { + return nil + } + + // root command with subcommands, do subcommand checking. + if !cmd.HasParent() && len(args) > 0 { + return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + return nil +} + +// NoArgs returns an error if any args are included. +func NoArgs(cmd *Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath()) + } + return nil +} + +// OnlyValidArgs returns an error if there are any positional args that are not in +// the `ValidArgs` field of `Command` +func OnlyValidArgs(cmd *Command, args []string) error { + if len(cmd.ValidArgs) > 0 { + // Remove any description that may be included in ValidArgs. + // A description is following a tab character. + validArgs := make([]string, 0, len(cmd.ValidArgs)) + for _, v := range cmd.ValidArgs { + validArgs = append(validArgs, strings.SplitN(v, "\t", 2)[0]) + } + for _, v := range args { + if !stringInSlice(v, validArgs) { + return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + } + } + return nil +} + +// ArbitraryArgs never returns an error. +func ArbitraryArgs(cmd *Command, args []string) error { + return nil +} + +// MinimumNArgs returns an error if there is not at least N args. +func MinimumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < n { + return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args)) + } + return nil + } +} + +// MaximumNArgs returns an error if there are more than N args. +func MaximumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) > n { + return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// ExactArgs returns an error if there are not exactly n args. +func ExactArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) != n { + return fmt.Errorf("accepts %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// RangeArgs returns an error if the number of args is not within the expected range. +func RangeArgs(min int, max int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < min || len(args) > max { + return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args)) + } + return nil + } +} + +// MatchAll allows combining several PositionalArgs to work in concert. +func MatchAll(pargs ...PositionalArgs) PositionalArgs { + return func(cmd *Command, args []string) error { + for _, parg := range pargs { + if err := parg(cmd, args); err != nil { + return err + } + } + return nil + } +} + +// ExactValidArgs returns an error if there are not exactly N positional args OR +// there are any positional args that are not in the `ValidArgs` field of `Command` +// +// Deprecated: use MatchAll(ExactArgs(n), OnlyValidArgs) instead +func ExactValidArgs(n int) PositionalArgs { + return MatchAll(ExactArgs(n), OnlyValidArgs) +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 3f33bb0ec..f4d198cbc 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,6 +1,21 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( + "bytes" "fmt" "io" "os" @@ -10,35 +25,33 @@ import ( "github.com/spf13/pflag" ) +// Annotations for Bash completion. const ( - BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extentions" + BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" BashCompCustom = "cobra_annotation_bash_completion_custom" BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag" BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" ) -func preamble(out io.Writer, name string) error { - _, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name) - if err != nil { - return err - } - _, err = fmt.Fprint(out, ` -__debug() +func writePreamble(buf io.StringWriter, name string) { + WriteStringAndCheck(buf, fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) + WriteStringAndCheck(buf, fmt.Sprintf(` +__%[1]s_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } # Homebrew on Macs have version 1.3 of bash-completion which doesn't include # _init_completion. This is a very minimal version of that function. -__my_init_completion() +__%[1]s_init_completion() { COMPREPLY=() _get_comp_words_by_ref "$@" cur prev words cword } -__index_of_word() +__%[1]s_index_of_word() { local w word=$1 shift @@ -50,7 +63,7 @@ __index_of_word() index=-1 } -__contains_word() +__%[1]s_contains_word() { local w word=$1; shift for w in "$@"; do @@ -59,9 +72,104 @@ __contains_word() return 1 } -__handle_reply() +__%[1]s_handle_go_custom_completion() +{ + __%[1]s_debug "${FUNCNAME[0]}: cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}" + + local shellCompDirectiveError=%[3]d + local shellCompDirectiveNoSpace=%[4]d + local shellCompDirectiveNoFileComp=%[5]d + local shellCompDirectiveFilterFileExt=%[6]d + local shellCompDirectiveFilterDirs=%[7]d + + local out requestComp lastParam lastChar comp directive args + + # Prepare the command to request completions for the program. + # Calling ${words[0]} instead of directly %[1]s allows handling aliases + args=("${words[@]:1}") + # Disable ActiveHelp which is not supported for bash completion v1 + requestComp="%[8]s=0 ${words[0]} %[2]s ${args[*]}" + + lastParam=${words[$((${#words[@]}-1))]} + lastChar=${lastParam:$((${#lastParam}-1)):1} + __%[1]s_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}" + + if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then + # If the last parameter is complete (there is a space following it) + # We add an extra empty parameter so we can indicate this to the go method. + __%[1]s_debug "${FUNCNAME[0]}: Adding extra empty parameter" + requestComp="${requestComp} \"\"" + fi + + __%[1]s_debug "${FUNCNAME[0]}: calling ${requestComp}" + # Use eval to handle any environment variables and such + out=$(eval "${requestComp}" 2>/dev/null) + + # Extract the directive integer at the very end of the output following a colon (:) + directive=${out##*:} + # Remove the directive + out=${out%%:*} + if [ "${directive}" = "${out}" ]; then + # There is not directive specified + directive=0 + fi + __%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}" + __%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out}" + + if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then + # Error code. No completion. + __%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code" + return + else + if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then + if [[ $(type -t compopt) = "builtin" ]]; then + __%[1]s_debug "${FUNCNAME[0]}: activating no space" + compopt -o nospace + fi + fi + if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then + if [[ $(type -t compopt) = "builtin" ]]; then + __%[1]s_debug "${FUNCNAME[0]}: activating no file completion" + compopt +o default + fi + fi + fi + + if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then + # File extension filtering + local fullFilter filter filteringCmd + # Do not use quotes around the $out variable or else newline + # characters will be kept. + for filter in ${out}; do + fullFilter+="$filter|" + done + + filteringCmd="_filedir $fullFilter" + __%[1]s_debug "File filtering command: $filteringCmd" + $filteringCmd + elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then + # File completion for directories only + local subdir + # Use printf to strip any trailing newline + subdir=$(printf "%%s" "${out}") + if [ -n "$subdir" ]; then + __%[1]s_debug "Listing directories in $subdir" + __%[1]s_handle_subdirs_in_dir_flag "$subdir" + else + __%[1]s_debug "Listing directories in ." + _filedir -d + fi + else + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${out}" -- "$cur") + fi +} + +__%[1]s_handle_reply() { - __debug "${FUNCNAME[0]}" + __%[1]s_debug "${FUNCNAME[0]}" + local comp case $cur in -*) if [[ $(type -t compopt) = "builtin" ]]; then @@ -73,7 +181,9 @@ __handle_reply() else allflags=("${flags[*]} ${two_word_flags[*]}") fi - COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") ) + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${allflags[*]}" -- "$cur") if [[ $(type -t compopt) = "builtin" ]]; then [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace fi @@ -86,25 +196,31 @@ __handle_reply() local index flag flag="${cur%%=*}" - __index_of_word "${flag}" "${flags_with_completion[@]}" + __%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}" + COMPREPLY=() if [[ ${index} -ge 0 ]]; then - COMPREPLY=() PREFIX="" cur="${cur#*=}" ${flags_completion[${index}]} - if [ -n "${ZSH_VERSION}" ]; then - # zfs completion needs --flag= prefix + if [ -n "${ZSH_VERSION:-}" ]; then + # zsh completion needs --flag= prefix eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" fi fi fi - return 0; + + if [[ -z "${flag_parsing_disabled}" ]]; then + # If flag parsing is enabled, we have completed the flags and can return. + # If flag parsing is disabled, we may not know all (or any) of the flags, so we fallthrough + # to possibly call handle_go_custom_completion. + return 0; + fi ;; esac # check if we are handling a flag with special work handling local index - __index_of_word "${prev}" "${flags_with_completion[@]}" + __%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}" if [[ ${index} -ge 0 ]]; then ${flags_completion[${index}]} return @@ -116,68 +232,99 @@ __handle_reply() fi local completions + completions=("${commands[@]}") + if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then + completions+=("${must_have_one_noun[@]}") + elif [[ -n "${has_completion_function}" ]]; then + # if a go completion function is provided, defer to that function + __%[1]s_handle_go_custom_completion + fi if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then - completions=("${must_have_one_flag[@]}") - elif [[ ${#must_have_one_noun[@]} -ne 0 ]]; then - completions=("${must_have_one_noun[@]}") - else - completions=("${commands[@]}") + completions+=("${must_have_one_flag[@]}") fi - COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${completions[*]}" -- "$cur") if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then - COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") ) + while IFS='' read -r comp; do + COMPREPLY+=("$comp") + done < <(compgen -W "${noun_aliases[*]}" -- "$cur") fi if [[ ${#COMPREPLY[@]} -eq 0 ]]; then - declare -F __custom_func >/dev/null && __custom_func + if declare -F __%[1]s_custom_func >/dev/null; then + # try command name qualified custom func + __%[1]s_custom_func + else + # otherwise fall back to unqualified for compatibility + declare -F __custom_func >/dev/null && __custom_func + fi fi - __ltrim_colon_completions "$cur" + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi + + # If there is only 1 completion and it is a flag with an = it will be completed + # but we don't want a space after the = + if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then + compopt -o nospace + fi } # The arguments should be in the form "ext1|ext2|extn" -__handle_filename_extension_flag() +__%[1]s_handle_filename_extension_flag() { local ext="$1" _filedir "@(${ext})" } -__handle_subdirs_in_dir_flag() +__%[1]s_handle_subdirs_in_dir_flag() { local dir="$1" - pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 + pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return } -__handle_flag() +__%[1]s_handle_flag() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" # if a command required a flag, and we found it, unset must_have_one_flag() local flagname=${words[c]} - local flagvalue + local flagvalue="" # if the word contained an = if [[ ${words[c]} == *"="* ]]; then flagvalue=${flagname#*=} # take in as flagvalue after the = flagname=${flagname%%=*} # strip everything after the = flagname="${flagname}=" # but put the = back fi - __debug "${FUNCNAME[0]}: looking for ${flagname}" - if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then + __%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}" + if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then must_have_one_flag=() fi + # if you set a flag which only applies to this command, don't show subcommands + if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + commands=() + fi + # keep flag value with flagname as flaghash - if [ -n "${flagvalue}" ] ; then - flaghash[${flagname}]=${flagvalue} - elif [ -n "${words[ $((c+1)) ]}" ] ; then - flaghash[${flagname}]=${words[ $((c+1)) ]} - else - flaghash[${flagname}]="true" # pad "true" for bool flag + # flaghash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then + if [ -n "${flagvalue}" ] ; then + flaghash[${flagname}]=${flagvalue} + elif [ -n "${words[ $((c+1)) ]}" ] ; then + flaghash[${flagname}]=${words[ $((c+1)) ]} + else + flaghash[${flagname}]="true" # pad "true" for bool flag + fi fi # skip the argument to a two word flag - if __contains_word "${words[c]}" "${two_word_flags[@]}"; then + if [[ ${words[c]} != *"="* ]] && __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then + __%[1]s_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument" c=$((c+1)) # if we are looking for a flags value, don't show commands if [[ $c -eq $cword ]]; then @@ -189,13 +336,13 @@ __handle_flag() } -__handle_noun() +__%[1]s_handle_noun() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" - if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then + if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then must_have_one_noun=() - elif __contains_word "${words[c]}" "${noun_aliases[@]}"; then + elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then must_have_one_noun=() fi @@ -203,400 +350,360 @@ __handle_noun() c=$((c+1)) } -__handle_command() +__%[1]s_handle_command() { - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" local next_command if [[ -n ${last_command} ]]; then next_command="_${last_command}_${words[c]//:/__}" else if [[ $c -eq 0 ]]; then - next_command="_$(basename "${words[c]//:/__}")" + next_command="_%[1]s_root_command" else next_command="_${words[c]//:/__}" fi fi c=$((c+1)) - __debug "${FUNCNAME[0]}: looking for ${next_command}" - declare -F $next_command >/dev/null && $next_command + __%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}" + declare -F "$next_command" >/dev/null && $next_command } -__handle_word() +__%[1]s_handle_word() { if [[ $c -ge $cword ]]; then - __handle_reply + __%[1]s_handle_reply return fi - __debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" if [[ "${words[c]}" == -* ]]; then - __handle_flag - elif __contains_word "${words[c]}" "${commands[@]}"; then - __handle_command - elif [[ $c -eq 0 ]] && __contains_word "$(basename "${words[c]}")" "${commands[@]}"; then - __handle_command + __%[1]s_handle_flag + elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then + __%[1]s_handle_command + elif [[ $c -eq 0 ]]; then + __%[1]s_handle_command + elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then + # aliashash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then + words[c]=${aliashash[${words[c]}]} + __%[1]s_handle_command + else + __%[1]s_handle_noun + fi else - __handle_noun + __%[1]s_handle_noun fi - __handle_word + __%[1]s_handle_word } -`) - return err +`, name, ShellCompNoDescRequestCmd, + ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) } -func postscript(w io.Writer, name string) error { - name = strings.Replace(name, ":", "__", -1) - _, err := fmt.Fprintf(w, "__start_%s()\n", name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `{ - local cur prev words cword +func writePostscript(buf io.StringWriter, name string) { + name = strings.ReplaceAll(name, ":", "__") + WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name)) + WriteStringAndCheck(buf, fmt.Sprintf(`{ + local cur prev words cword split declare -A flaghash 2>/dev/null || : + declare -A aliashash 2>/dev/null || : if declare -F _init_completion >/dev/null 2>&1; then _init_completion -s || return else - __my_init_completion -n "=" || return + __%[1]s_init_completion -n "=" || return fi local c=0 + local flag_parsing_disabled= local flags=() local two_word_flags=() + local local_nonpersistent_flags=() local flags_with_completion=() local flags_completion=() - local commands=("%s") + local commands=("%[1]s") + local command_aliases=() local must_have_one_flag=() local must_have_one_noun=() - local last_command + local has_completion_function="" + local last_command="" local nouns=() + local noun_aliases=() - __handle_word + __%[1]s_handle_word } -`, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then +`, name)) + WriteStringAndCheck(buf, fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then complete -o default -F __start_%s %s else complete -o default -o nospace -F __start_%s %s fi -`, name, name, name, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n") - return err +`, name, name, name, name)) + WriteStringAndCheck(buf, "# ex: ts=4 sw=4 et filetype=sh\n") } -func writeCommands(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil { - return err - } +func writeCommands(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " commands=()\n") for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c == cmd.helpCommand { + if !c.IsAvailableCommand() && c != cmd.helpCommand { continue } - if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" commands+=(%q)\n", c.Name())) + writeCmdAliases(buf, c) } - _, err := fmt.Fprintf(w, "\n") - return err + WriteStringAndCheck(buf, "\n") } -func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error { +func writeFlagHandler(buf io.StringWriter, name string, annotations map[string][]string, cmd *Command) { for key, value := range annotations { switch key { case BashCompFilenameExt: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) > 0 { - ext := "__handle_filename_extension_flag " + strings.Join(value, "|") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|") } else { - ext := "_filedir" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir" } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", ext)) case BashCompCustom: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + if len(value) > 0 { handlers := strings.Join(value, "; ") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers) + WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", handlers)) } else { - _, err = fmt.Fprintf(w, " flags_completion+=(:)\n") - } - if err != nil { - return err + WriteStringAndCheck(buf, " flags_completion+=(:)\n") } case BashCompSubdirsInDir: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) + WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) == 1 { - ext := "__handle_subdirs_in_dir_flag " + value[0] - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0] } else { - ext := "_filedir -d" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir -d" } + WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", ext)) } } - return nil } -func writeShortFlag(flag *pflag.Flag, w io.Writer) error { - b := (flag.Value.Type() == "bool") +const cbn = "\")\n" + +func writeShortFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) { name := flag.Shorthand format := " " - if !b { + if len(flag.NoOptDefVal) == 0 { format += "two_word_" } - format += "flags+=(\"-%s\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return writeFlagHandler("-"+name, flag.Annotations, w) + format += "flags+=(\"-%s" + cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) + writeFlagHandler(buf, "-"+name, flag.Annotations, cmd) } -func writeFlag(flag *pflag.Flag, w io.Writer) error { - b := (flag.Value.Type() == "bool") +func writeFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) { name := flag.Name format := " flags+=(\"--%s" - if !b { + if len(flag.NoOptDefVal) == 0 { format += "=" } - format += "\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err + format += cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) + if len(flag.NoOptDefVal) == 0 { + format = " two_word_flags+=(\"--%s" + cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) } - return writeFlagHandler("--"+name, flag.Annotations, w) + writeFlagHandler(buf, "--"+name, flag.Annotations, cmd) } -func writeFlags(cmd *Command, w io.Writer) error { - _, err := fmt.Fprintf(w, ` flags=() +func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { + name := flag.Name + format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn + if len(flag.NoOptDefVal) == 0 { + format += " local_nonpersistent_flags+=(\"--%[1]s=" + cbn + } + WriteStringAndCheck(buf, fmt.Sprintf(format, name)) + if len(flag.Shorthand) > 0 { + WriteStringAndCheck(buf, fmt.Sprintf(" local_nonpersistent_flags+=(\"-%s\")\n", flag.Shorthand)) + } +} + +// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags +func prepareCustomAnnotationsForFlags(cmd *Command) { + flagCompletionMutex.RLock() + defer flagCompletionMutex.RUnlock() + for flag := range flagCompletionFunctions { + // Make sure the completion script calls the __*_go_custom_completion function for + // every registered flag. We need to do this here (and not when the flag was registered + // for completion) so that we can know the root command name for the prefix + // of ___go_custom_completion + if flag.Annotations == nil { + flag.Annotations = map[string][]string{} + } + flag.Annotations[BashCompCustom] = []string{fmt.Sprintf("__%[1]s_handle_go_custom_completion", cmd.Root().Name())} + } +} + +func writeFlags(buf io.StringWriter, cmd *Command) { + prepareCustomAnnotationsForFlags(cmd) + WriteStringAndCheck(buf, ` flags=() two_word_flags=() + local_nonpersistent_flags=() flags_with_completion=() flags_completion=() `) - if err != nil { - return err + + if cmd.DisableFlagParsing { + WriteStringAndCheck(buf, " flag_parsing_disabled=1\n") } - var visitErr error + + localNonPersistentFlags := cmd.LocalNonPersistentFlags() cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { - if err := writeFlag(flag, w); err != nil { - visitErr = err + if nonCompletableFlag(flag) { return } + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag, cmd) + } + // localNonPersistentFlags are used to stop the completion of subcommands when one is set + // if TraverseChildren is true we should allow to complete subcommands + if localNonPersistentFlags.Lookup(flag.Name) != nil && !cmd.Root().TraverseChildren { + writeLocalNonPersistentFlag(buf, flag) } }) - if visitErr != nil { - return visitErr - } cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { - if err := writeFlag(flag, w); err != nil { - visitErr = err + if nonCompletableFlag(flag) { return } + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag, cmd) } }) - if visitErr != nil { - return visitErr - } - _, err = fmt.Fprintf(w, "\n") - return err + WriteStringAndCheck(buf, "\n") } -func writeRequiredFlag(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil { - return err - } +func writeRequiredFlag(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " must_have_one_flag=()\n") flags := cmd.NonInheritedFlags() - var visitErr error flags.VisitAll(func(flag *pflag.Flag) { - for key := range flag.Annotations { - switch key { - case BashCompOneRequiredFlag: - format := " must_have_one_flag+=(\"--%s" - b := (flag.Value.Type() == "bool") - if !b { - format += "=" - } - format += "\")\n" - if _, err := fmt.Fprintf(w, format, flag.Name); err != nil { - visitErr = err - return - } - - if len(flag.Shorthand) > 0 { - if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil { - visitErr = err - return - } - } + if nonCompletableFlag(flag) { + return + } + if _, ok := flag.Annotations[BashCompOneRequiredFlag]; ok { + format := " must_have_one_flag+=(\"--%s" + if flag.Value.Type() != "bool" { + format += "=" + } + format += cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name)) + + if len(flag.Shorthand) > 0 { + WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) } } }) - return visitErr } -func writeRequiredNouns(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil { - return err - } - sort.Sort(sort.StringSlice(cmd.ValidArgs)) +func writeRequiredNouns(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " must_have_one_noun=()\n") + sort.Strings(cmd.ValidArgs) for _, value := range cmd.ValidArgs { - if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil { - return err - } + // Remove any description that may be included following a tab character. + // Descriptions are not supported by bash completion. + value = strings.SplitN(value, "\t", 2)[0] + WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) + } + if cmd.ValidArgsFunction != nil { + WriteStringAndCheck(buf, " has_completion_function=1\n") } - return nil } -func writeArgAliases(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil { - return err +func writeCmdAliases(buf io.StringWriter, cmd *Command) { + if len(cmd.Aliases) == 0 { + return } - sort.Sort(sort.StringSlice(cmd.ArgAliases)) + + sort.Strings(cmd.Aliases) + + WriteStringAndCheck(buf, fmt.Sprint(` if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then`, "\n")) + for _, value := range cmd.Aliases { + WriteStringAndCheck(buf, fmt.Sprintf(" command_aliases+=(%q)\n", value)) + WriteStringAndCheck(buf, fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name())) + } + WriteStringAndCheck(buf, ` fi`) + WriteStringAndCheck(buf, "\n") +} +func writeArgAliases(buf io.StringWriter, cmd *Command) { + WriteStringAndCheck(buf, " noun_aliases=()\n") + sort.Strings(cmd.ArgAliases) for _, value := range cmd.ArgAliases { - if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil { - return err - } + WriteStringAndCheck(buf, fmt.Sprintf(" noun_aliases+=(%q)\n", value)) } - return nil } -func gen(cmd *Command, w io.Writer) error { +func gen(buf io.StringWriter, cmd *Command) { for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c == cmd.helpCommand { + if !c.IsAvailableCommand() && c != cmd.helpCommand { continue } - if err := gen(c, w); err != nil { - return err - } + gen(buf, c) } commandName := cmd.CommandPath() - commandName = strings.Replace(commandName, " ", "_", -1) - commandName = strings.Replace(commandName, ":", "__", -1) - if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil { - return err - } - if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil { - return err - } - if err := writeCommands(cmd, w); err != nil { - return err - } - if err := writeFlags(cmd, w); err != nil { - return err - } - if err := writeRequiredFlag(cmd, w); err != nil { - return err - } - if err := writeRequiredNouns(cmd, w); err != nil { - return err - } - if err := writeArgAliases(cmd, w); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "}\n\n"); err != nil { - return err - } - return nil -} + commandName = strings.ReplaceAll(commandName, " ", "_") + commandName = strings.ReplaceAll(commandName, ":", "__") -func (cmd *Command) GenBashCompletion(w io.Writer) error { - if err := preamble(w, cmd.Name()); err != nil { - return err - } - if len(cmd.BashCompletionFunction) > 0 { - if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil { - return err - } - } - if err := gen(cmd, w); err != nil { - return err + if cmd.Root() == cmd { + WriteStringAndCheck(buf, fmt.Sprintf("_%s_root_command()\n{\n", commandName)) + } else { + WriteStringAndCheck(buf, fmt.Sprintf("_%s()\n{\n", commandName)) } - return postscript(w, cmd.Name()) -} -func (cmd *Command) GenBashCompletionFile(filename string) error { - outFile, err := os.Create(filename) - if err != nil { - return err - } - defer outFile.Close() + WriteStringAndCheck(buf, fmt.Sprintf(" last_command=%q\n", commandName)) + WriteStringAndCheck(buf, "\n") + WriteStringAndCheck(buf, " command_aliases=()\n") + WriteStringAndCheck(buf, "\n") - return cmd.GenBashCompletion(outFile) + writeCommands(buf, cmd) + writeFlags(buf, cmd) + writeRequiredFlag(buf, cmd) + writeRequiredNouns(buf, cmd) + writeArgAliases(buf, cmd) + WriteStringAndCheck(buf, "}\n\n") } -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists. -func (cmd *Command) MarkFlagRequired(name string) error { - return MarkFlagRequired(cmd.Flags(), name) -} - -// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists. -func (cmd *Command) MarkPersistentFlagRequired(name string) error { - return MarkFlagRequired(cmd.PersistentFlags(), name) -} - -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists. -func MarkFlagRequired(flags *pflag.FlagSet, name string) error { - return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) -} - -// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.Flags(), name, extensions...) -} +// GenBashCompletion generates bash completion file and writes to the passed writer. +func (c *Command) GenBashCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + writePreamble(buf, c.Name()) + if len(c.BashCompletionFunction) > 0 { + buf.WriteString(c.BashCompletionFunction + "\n") + } + gen(buf, c) + writePostscript(buf, c.Name()) -// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. -// Generated bash autocompletion will call the bash function f for the flag. -func (cmd *Command) MarkFlagCustom(name string, f string) error { - return MarkFlagCustom(cmd.Flags(), name, f) + _, err := buf.WriteTo(w) + return err } -// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.PersistentFlags(), name, extensions...) +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 } -// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { - return flags.SetAnnotation(name, BashCompFilenameExt, extensions) -} +// GenBashCompletionFile generates bash completion file. +func (c *Command) GenBashCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() -// MarkFlagCustom adds the BashCompCustom annotation to the named flag in the flag set, if it exists. -// Generated bash autocompletion will call the bash function f for the flag. -func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { - return flags.SetAnnotation(name, BashCompCustom, []string{f}) + return c.GenBashCompletion(outFile) } diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md deleted file mode 100644 index 84d5b012f..000000000 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ /dev/null @@ -1,206 +0,0 @@ -# Generating Bash Completions For Your Own cobra.Command - -Generating bash completions from a cobra command is incredibly easy. An actual program which does so for the kubernetes kubectl binary is as follows: - -```go -package main - -import ( - "io/ioutil" - "os" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd" -) - -func main() { - kubectl := cmd.NewFactory(nil).NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) - kubectl.GenBashCompletionFile("out.sh") -} -``` - -That will get you completions of subcommands and flags. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. - -## Creating your own custom functions - -Some more actual code that works in kubernetes: - -```bash -const ( - bash_completion_func = `__kubectl_parse_get() -{ - local kubectl_output out - if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then - out=($(echo "${kubectl_output}" | awk '{print $1}')) - COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_get_resource() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 - fi - __kubectl_parse_get ${nouns[${#nouns[@]} -1]} - if [[ $? -eq 0 ]]; then - return 0 - fi -} - -__custom_func() { - case ${last_command} in - kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) - __kubectl_get_resource - return - ;; - *) - ;; - esac -} -`) -``` - -And then I set that in my command definition: - -```go -cmds := &cobra.Command{ - Use: "kubectl", - Short: "kubectl controls the Kubernetes cluster manager", - Long: `kubectl controls the Kubernetes cluster manager. - -Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, - Run: runHelp, - BashCompletionFunction: bash_completion_func, -} -``` - -The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__custom_func()` to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! - -## Have the completions code complete your 'nouns' - -In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like: - -```go -validArgs []string = { "pod", "node", "service", "replicationcontroller" } - -cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", - Short: "Display one or many resources", - Long: get_long, - Example: get_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunGet(f, out, cmd, args) - util.CheckErr(err) - }, - ValidArgs: validArgs, -} -``` - -Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like - -```bash -# kubectl get [tab][tab] -node pod replicationcontroller service -``` - -## Plural form and shortcuts for nouns - -If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`: - -```go` -argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } - -cmd := &cobra.Command{ - ... - ValidArgs: validArgs, - ArgAliases: argAliases -} -``` - -The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion aglorithm if entered manually, e.g. in: - -```bash -# kubectl get rc [tab][tab] -backend frontend database -``` - -Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns -in this example again instead of the replication controllers. - -## Mark flags as required - -Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy. - -```go -cmd.MarkFlagRequired("pod") -cmd.MarkFlagRequired("container") -``` - -and you'll get something like - -```bash -# kubectl exec [tab][tab][tab] --c --container= -p --pod= -``` - -# Specify valid filename extensions for flags that take a filename - -In this example we use --filename= and expect to get a json or yaml file as the argument. To make this easier we annotate the --filename flag with valid filename extensions. - -```go - annotations := []string{"json", "yaml", "yml"} - annotation := make(map[string][]string) - annotation[cobra.BashCompFilenameExt] = annotations - - flag := &pflag.Flag{ - Name: "filename", - Shorthand: "f", - Usage: usage, - Value: value, - DefValue: value.String(), - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -Now when you run a command with this filename flag you'll get something like - -```bash -# kubectl create -f -test/ example/ rpmbuild/ -hello.yml test.json -``` - -So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. - -# Specifiy custom flag completion - -Similar to the filename completion and filtering usingn cobra.BashCompFilenameExt, you can specifiy -a custom flag completion function with cobra.BashCompCustom: - -```go - annotation := make(map[string][]string) - annotation[cobra.BashCompFilenameExt] = []string{"__kubectl_get_namespaces"} - - flag := &pflag.Flag{ - Name: "namespace", - Usage: usage, - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction` -value, e.g.: - -```bash -__kubectl_get_namespaces() -{ - local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - local kubectl_out - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) - fi -} -``` diff --git a/vendor/github.com/spf13/cobra/bash_completionsV2.go b/vendor/github.com/spf13/cobra/bash_completionsV2.go new file mode 100644 index 000000000..1cce5c329 --- /dev/null +++ b/vendor/github.com/spf13/cobra/bash_completionsV2.go @@ -0,0 +1,396 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" +) + +func (c *Command) genBashCompletion(w io.Writer, includeDesc bool) error { + buf := new(bytes.Buffer) + genBashComp(buf, c.Name(), includeDesc) + _, err := buf.WriteTo(w) + return err +} + +func genBashComp(buf io.StringWriter, name string, includeDesc bool) { + compCmd := ShellCompRequestCmd + if !includeDesc { + compCmd = ShellCompNoDescRequestCmd + } + + WriteStringAndCheck(buf, fmt.Sprintf(`# bash completion V2 for %-36[1]s -*- shell-script -*- + +__%[1]s_debug() +{ + if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then + echo "$*" >> "${BASH_COMP_DEBUG_FILE}" + fi +} + +# Macs have bash3 for which the bash-completion package doesn't include +# _init_completion. This is a minimal version of that function. +__%[1]s_init_completion() +{ + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} + +# This function calls the %[1]s program to obtain the completion +# results and the directive. It fills the 'out' and 'directive' vars. +__%[1]s_get_completion_results() { + local requestComp lastParam lastChar args + + # Prepare the command to request completions for the program. + # Calling ${words[0]} instead of directly %[1]s allows handling aliases + args=("${words[@]:1}") + requestComp="${words[0]} %[2]s ${args[*]}" + + lastParam=${words[$((${#words[@]}-1))]} + lastChar=${lastParam:$((${#lastParam}-1)):1} + __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}" + + if [[ -z ${cur} && ${lastChar} != = ]]; then + # If the last parameter is complete (there is a space following it) + # We add an extra empty parameter so we can indicate this to the go method. + __%[1]s_debug "Adding extra empty parameter" + requestComp="${requestComp} ''" + fi + + # When completing a flag with an = (e.g., %[1]s -n=) + # bash focuses on the part after the =, so we need to remove + # the flag part from $cur + if [[ ${cur} == -*=* ]]; then + cur="${cur#*=}" + fi + + __%[1]s_debug "Calling ${requestComp}" + # Use eval to handle any environment variables and such + out=$(eval "${requestComp}" 2>/dev/null) + + # Extract the directive integer at the very end of the output following a colon (:) + directive=${out##*:} + # Remove the directive + out=${out%%:*} + if [[ ${directive} == "${out}" ]]; then + # There is not directive specified + directive=0 + fi + __%[1]s_debug "The completion directive is: ${directive}" + __%[1]s_debug "The completions are: ${out}" +} + +__%[1]s_process_completion_results() { + local shellCompDirectiveError=%[3]d + local shellCompDirectiveNoSpace=%[4]d + local shellCompDirectiveNoFileComp=%[5]d + local shellCompDirectiveFilterFileExt=%[6]d + local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d + + if (((directive & shellCompDirectiveError) != 0)); then + # Error code. No completion. + __%[1]s_debug "Received error from custom completion go code" + return + else + if (((directive & shellCompDirectiveNoSpace) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then + __%[1]s_debug "Activating no space" + compopt -o nospace + else + __%[1]s_debug "No space directive not supported in this version of bash" + fi + fi + if (((directive & shellCompDirectiveKeepOrder) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then + # no sort isn't supported for bash less than < 4.4 + if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then + __%[1]s_debug "No sort directive not supported in this version of bash" + else + __%[1]s_debug "Activating keep order" + compopt -o nosort + fi + else + __%[1]s_debug "No sort directive not supported in this version of bash" + fi + fi + if (((directive & shellCompDirectiveNoFileComp) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then + __%[1]s_debug "Activating no file completion" + compopt +o default + else + __%[1]s_debug "No file completion directive not supported in this version of bash" + fi + fi + fi + + # Separate activeHelp from normal completions + local completions=() + local activeHelp=() + __%[1]s_extract_activeHelp + + if (((directive & shellCompDirectiveFilterFileExt) != 0)); then + # File extension filtering + local fullFilter filter filteringCmd + + # Do not use quotes around the $completions variable or else newline + # characters will be kept. + for filter in ${completions[*]}; do + fullFilter+="$filter|" + done + + filteringCmd="_filedir $fullFilter" + __%[1]s_debug "File filtering command: $filteringCmd" + $filteringCmd + elif (((directive & shellCompDirectiveFilterDirs) != 0)); then + # File completion for directories only + + local subdir + subdir=${completions[0]} + if [[ -n $subdir ]]; then + __%[1]s_debug "Listing directories in $subdir" + pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return + else + __%[1]s_debug "Listing directories in ." + _filedir -d + fi + else + __%[1]s_handle_completion_types + fi + + __%[1]s_handle_special_char "$cur" : + __%[1]s_handle_special_char "$cur" = + + # Print the activeHelp statements before we finish + if ((${#activeHelp[*]} != 0)); then + printf "\n"; + printf "%%s\n" "${activeHelp[@]}" + printf "\n" + + # The prompt format is only available from bash 4.4. + # We test if it is available before using it. + if (x=${PS1@P}) 2> /dev/null; then + printf "%%s" "${PS1@P}${COMP_LINE[@]}" + else + # Can't print the prompt. Just print the + # text the user had typed, it is workable enough. + printf "%%s" "${COMP_LINE[@]}" + fi + fi +} + +# Separate activeHelp lines from real completions. +# Fills the $activeHelp and $completions arrays. +__%[1]s_extract_activeHelp() { + local activeHelpMarker="%[9]s" + local endIndex=${#activeHelpMarker} + + while IFS='' read -r comp; do + if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then + comp=${comp:endIndex} + __%[1]s_debug "ActiveHelp found: $comp" + if [[ -n $comp ]]; then + activeHelp+=("$comp") + fi + else + # Not an activeHelp line but a normal completion + completions+=("$comp") + fi + done <<<"${out}" +} + +__%[1]s_handle_completion_types() { + __%[1]s_debug "__%[1]s_handle_completion_types: COMP_TYPE is $COMP_TYPE" + + case $COMP_TYPE in + 37|42) + # Type: menu-complete/menu-complete-backward and insert-completions + # If the user requested inserting one completion at a time, or all + # completions at once on the command-line we must remove the descriptions. + # https://github.com/spf13/cobra/issues/1508 + local tab=$'\t' comp + while IFS='' read -r comp; do + [[ -z $comp ]] && continue + # Strip any description + comp=${comp%%%%$tab*} + # Only consider the completions that match + if [[ $comp == "$cur"* ]]; then + COMPREPLY+=("$comp") + fi + done < <(printf "%%s\n" "${completions[@]}") + ;; + + *) + # Type: complete (normal completion) + __%[1]s_handle_standard_completion_case + ;; + esac +} + +__%[1]s_handle_standard_completion_case() { + local tab=$'\t' comp + + # Short circuit to optimize if we don't have descriptions + if [[ "${completions[*]}" != *$tab* ]]; then + IFS=$'\n' read -ra COMPREPLY -d '' < <(compgen -W "${completions[*]}" -- "$cur") + return 0 + fi + + local longest=0 + local compline + # Look for the longest completion so that we can format things nicely + while IFS='' read -r compline; do + [[ -z $compline ]] && continue + # Strip any description before checking the length + comp=${compline%%%%$tab*} + # Only consider the completions that match + [[ $comp == "$cur"* ]] || continue + COMPREPLY+=("$compline") + if ((${#comp}>longest)); then + longest=${#comp} + fi + done < <(printf "%%s\n" "${completions[@]}") + + # If there is a single completion left, remove the description text + if ((${#COMPREPLY[*]} == 1)); then + __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}" + comp="${COMPREPLY[0]%%%%$tab*}" + __%[1]s_debug "Removed description from single completion, which is now: ${comp}" + COMPREPLY[0]=$comp + else # Format the descriptions + __%[1]s_format_comp_descriptions $longest + fi +} + +__%[1]s_handle_special_char() +{ + local comp="$1" + local char=$2 + if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then + local word=${comp%%"${comp##*${char}}"} + local idx=${#COMPREPLY[*]} + while ((--idx >= 0)); do + COMPREPLY[idx]=${COMPREPLY[idx]#"$word"} + done + fi +} + +__%[1]s_format_comp_descriptions() +{ + local tab=$'\t' + local comp desc maxdesclength + local longest=$1 + + local i ci + for ci in ${!COMPREPLY[*]}; do + comp=${COMPREPLY[ci]} + # Properly format the description string which follows a tab character if there is one + if [[ "$comp" == *$tab* ]]; then + __%[1]s_debug "Original comp: $comp" + desc=${comp#*$tab} + comp=${comp%%%%$tab*} + + # $COLUMNS stores the current shell width. + # Remove an extra 4 because we add 2 spaces and 2 parentheses. + maxdesclength=$(( COLUMNS - longest - 4 )) + + # Make sure we can fit a description of at least 8 characters + # if we are to align the descriptions. + if ((maxdesclength > 8)); then + # Add the proper number of spaces to align the descriptions + for ((i = ${#comp} ; i < longest ; i++)); do + comp+=" " + done + else + # Don't pad the descriptions so we can fit more text after the completion + maxdesclength=$(( COLUMNS - ${#comp} - 4 )) + fi + + # If there is enough space for any description text, + # truncate the descriptions that are too long for the shell width + if ((maxdesclength > 0)); then + if ((${#desc} > maxdesclength)); then + desc=${desc:0:$(( maxdesclength - 1 ))} + desc+="…" + fi + comp+=" ($desc)" + fi + COMPREPLY[ci]=$comp + __%[1]s_debug "Final comp: $comp" + fi + done +} + +__start_%[1]s() +{ + local cur prev words cword split + + COMPREPLY=() + + # Call _init_completion from the bash-completion package + # to prepare the arguments properly + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -n =: || return + else + __%[1]s_init_completion -n =: || return + fi + + __%[1]s_debug + __%[1]s_debug "========= starting completion logic ==========" + __%[1]s_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword" + + # The user could have moved the cursor backwards on the command-line. + # We need to trigger completion from the $cword location, so we need + # to truncate the command-line ($words) up to the $cword location. + words=("${words[@]:0:$cword+1}") + __%[1]s_debug "Truncated words[*]: ${words[*]}," + + local out directive + __%[1]s_get_completion_results + __%[1]s_process_completion_results +} + +if [[ $(type -t compopt) = "builtin" ]]; then + complete -o default -F __start_%[1]s %[1]s +else + complete -o default -o nospace -F __start_%[1]s %[1]s +fi + +# ex: ts=4 sw=4 et filetype=sh +`, name, compCmd, + ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, + activeHelpMarker)) +} + +// GenBashCompletionFileV2 generates Bash completion version 2. +func (c *Command) GenBashCompletionFileV2(filename string, includeDesc bool) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenBashCompletionV2(outFile, includeDesc) +} + +// GenBashCompletionV2 generates Bash completion file version 2 +// and writes it to the passed writer. +func (c *Command) GenBashCompletionV2(w io.Writer, includeDesc bool) error { + return c.genBashCompletion(w, includeDesc) +} diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index 0c4e2e5de..e0b0947b0 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -1,9 +1,10 @@ -// Copyright © 2013 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -19,52 +20,97 @@ package cobra import ( "fmt" "io" + "os" "reflect" "strconv" "strings" "text/template" + "time" "unicode" ) var templateFuncs = template.FuncMap{ - "trim": strings.TrimSpace, - "trimRightSpace": trimRightSpace, - "appendIfNotPresent": appendIfNotPresent, - "rpad": rpad, - "gt": Gt, - "eq": Eq, + "trim": strings.TrimSpace, + "trimRightSpace": trimRightSpace, + "trimTrailingWhitespaces": trimRightSpace, + "appendIfNotPresent": appendIfNotPresent, + "rpad": rpad, + "gt": Gt, + "eq": Eq, } var initializers []func() +var finalizers []func() + +const ( + defaultPrefixMatching = false + defaultCommandSorting = true + defaultCaseInsensitive = false + defaultTraverseRunHooks = false +) + +// EnablePrefixMatching allows setting automatic prefix matching. Automatic prefix matching can be a dangerous thing +// to automatically enable in CLI tools. +// Set this to true to enable it. +var EnablePrefixMatching = defaultPrefixMatching + +// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. +// To disable sorting, set it to false. +var EnableCommandSorting = defaultCommandSorting + +// EnableCaseInsensitive allows case-insensitive commands names. (case sensitive by default) +var EnableCaseInsensitive = defaultCaseInsensitive + +// EnableTraverseRunHooks executes persistent pre-run and post-run hooks from all parents. +// By default this is disabled, which means only the first run hook to be found is executed. +var EnableTraverseRunHooks = defaultTraverseRunHooks -// automatic prefix matching can be a dangerous thing to automatically enable in CLI tools. -// Set this to true to enable it -var EnablePrefixMatching = false +// MousetrapHelpText enables an information splash screen on Windows +// if the CLI is started from explorer.exe. +// To disable the mousetrap, just set this variable to blank string (""). +// Works only on Microsoft Windows. +var MousetrapHelpText = `This is a command line tool. -//AddTemplateFunc adds a template function that's available to Usage and Help -//template generation. +You need to open cmd.exe and run it from there. +` + +// MousetrapDisplayDuration controls how long the MousetrapHelpText message is displayed on Windows +// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed. +// To disable the mousetrap, just set MousetrapHelpText to blank string (""). +// Works only on Microsoft Windows. +var MousetrapDisplayDuration = 5 * time.Second + +// AddTemplateFunc adds a template function that's available to Usage and Help +// template generation. func AddTemplateFunc(name string, tmplFunc interface{}) { templateFuncs[name] = tmplFunc } -//AddTemplateFuncs adds multiple template functions availalble to Usage and -//Help template generation. +// AddTemplateFuncs adds multiple template functions that are available to Usage and +// Help template generation. func AddTemplateFuncs(tmplFuncs template.FuncMap) { for k, v := range tmplFuncs { templateFuncs[k] = v } } -//OnInitialize takes a series of func() arguments and appends them to a slice of func(). +// OnInitialize sets the passed functions to be run when each command's +// Execute method is called. func OnInitialize(y ...func()) { - for _, x := range y { - initializers = append(initializers, x) - } + initializers = append(initializers, y...) } -//Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, -//Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as -//ints and then compared. +// OnFinalize sets the passed functions to be run when each command's +// Execute method is terminated. +func OnFinalize(y ...func()) { + finalizers = append(finalizers, y...) +} + +// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, +// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as +// ints and then compared. func Gt(a interface{}, b interface{}) bool { var left, right int64 av := reflect.ValueOf(a) @@ -92,7 +138,9 @@ func Gt(a interface{}, b interface{}) bool { return left > right } -//Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. +// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. func Eq(a interface{}, b interface{}) bool { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) @@ -112,7 +160,9 @@ func trimRightSpace(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) } -// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s +// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s. func appendIfNotPresent(s, stringToAppend string) string { if strings.Contains(s, stringToAppend) { return s @@ -120,10 +170,10 @@ func appendIfNotPresent(s, stringToAppend string) string { return s + " " + stringToAppend } -//rpad adds padding to the right of a string +// rpad adds padding to the right of a string. func rpad(s string, padding int) string { - template := fmt.Sprintf("%%-%ds", padding) - return fmt.Sprintf(template, s) + formattedString := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(formattedString, s) } // tmpl executes the given template text on data, writing the result to w. @@ -134,7 +184,7 @@ func tmpl(w io.Writer, text string, data interface{}) error { return t.Execute(w, data) } -// ld compares two strings and returns the levenshtein distance between them +// ld compares two strings and returns the levenshtein distance between them. func ld(s, t string, ignoreCase bool) int { if ignoreCase { s = strings.ToLower(s) @@ -143,8 +193,6 @@ func ld(s, t string, ignoreCase bool) int { d := make([][]int, len(s)+1) for i := range d { d[i] = make([]int, len(t)+1) - } - for i := range d { d[i][0] = i } for j := range d[0] { @@ -169,3 +217,26 @@ func ld(s, t string, ignoreCase bool) int { } return d[len(s)][len(t)] } + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +// CheckErr prints the msg with the prefix 'Error:' and exits with error code 1. If the msg is nil, it does nothing. +func CheckErr(msg interface{}) { + if msg != nil { + fmt.Fprintln(os.Stderr, "Error:", msg) + os.Exit(1) + } +} + +// WriteStringAndCheck writes a string into a buffer, and checks if the error is not nil. +func WriteStringAndCheck(b io.StringWriter, s string) { + _, err := b.WriteString(s) + CheckErr(err) +} diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index b92c95cbb..54748fc67 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -1,9 +1,10 @@ -// Copyright © 2013 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -11,172 +12,355 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. -//In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. +// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. +// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. package cobra import ( "bytes" + "context" + "errors" "fmt" "io" "os" "path/filepath" + "sort" "strings" flag "github.com/spf13/pflag" ) +const ( + FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" + CommandDisplayNameAnnotation = "cobra_annotation_command_display_name" +) + +// FParseErrWhitelist configures Flag parse errors to be ignored +type FParseErrWhitelist flag.ParseErrorsWhitelist + +// Group Structure to manage groups for commands +type Group struct { + ID string + Title string +} + // Command is just that, a command for your application. -// eg. 'go run' ... 'run' is the command. Cobra requires +// E.g. 'go run ...' - 'run' is the command. Cobra requires // you to define the usage and description as part of your command // definition to ensure usability. type Command struct { - // Name is the command name, usually the executable's name. - name string - // The one-line usage message. + // Use is the one-line usage message. + // Recommended syntax is as follows: + // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. + // ... indicates that you can specify multiple values for the previous argument. + // | indicates mutually exclusive information. You can use the argument to the left of the separator or the + // argument to the right of the separator. You cannot use both arguments in a single use of the command. + // { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are + // optional, they are enclosed in brackets ([ ]). + // Example: add [-F file | -D dir]... [-f format] profile Use string - // An array of aliases that can be used instead of the first word in Use. + + // Aliases is an array of aliases that can be used instead of the first word in Use. Aliases []string - // An array of command names for which this command will be suggested - similar to aliases but only suggests. + + // SuggestFor is an array of command names for which this command will be suggested - + // similar to aliases but only suggests. SuggestFor []string - // The short description shown in the 'help' output. + + // Short is the short description shown in the 'help' output. Short string - // The long message shown in the 'help ' output. + + // The group id under which this subcommand is grouped in the 'help' output of its parent. + GroupID string + + // Long is the long message shown in the 'help ' output. Long string - // Examples of how to use the command + + // Example is examples of how to use the command. Example string - // List of all valid non-flag arguments that are accepted in bash completions + + // ValidArgs is list of all valid non-flag arguments that are accepted in shell completions ValidArgs []string - // List of aliases for ValidArgs. These are not suggested to the user in the bash - // completion, but accepted if entered manually. + // ValidArgsFunction is an optional function that provides valid non-flag arguments for shell completion. + // It is a dynamic version of using ValidArgs. + // Only one of ValidArgs and ValidArgsFunction can be used for a command. + ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + + // Expected arguments + Args PositionalArgs + + // ArgAliases is List of aliases for ValidArgs. + // These are not suggested to the user in the shell completion, + // but accepted if entered manually. ArgAliases []string - // Custom functions used by the bash autocompletion generator + + // BashCompletionFunction is custom bash functions used by the legacy bash autocompletion generator. + // For portability with other shells, it is recommended to instead use ValidArgsFunction BashCompletionFunction string - // Is this command deprecated and should print this string when used? + + // Deprecated defines, if this command is deprecated and should print this string when used. Deprecated string - // Is this command hidden and should NOT show up in the list of available commands? - Hidden bool - // Full set of flags - flags *flag.FlagSet - // Set of flags childrens of this command will inherit - pflags *flag.FlagSet - // Flags that are declared specifically by this command (not inherited). - lflags *flag.FlagSet - // SilenceErrors is an option to quiet errors down stream - SilenceErrors bool - // Silence Usage is an option to silence usage when an error occurs. - SilenceUsage bool + + // Annotations are key/value pairs that can be used by applications to identify or + // group commands or set special options. + Annotations map[string]string + + // Version defines the version for this command. If this value is non-empty and the command does not + // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + // will print content of the "Version" variable. A shorthand "v" flag will also be added if the + // command does not define one. + Version string + // The *Run functions are executed in the following order: // * PersistentPreRun() // * PreRun() // * Run() // * PostRun() // * PersistentPostRun() - // All functions get the same args, the arguments after the command name - // PersistentPreRun: children of this command will inherit and execute + // All functions get the same args, the arguments after the command name. + // The *PreRun and *PostRun functions will only be executed if the Run function of the current + // command has been declared. + // + // PersistentPreRun: children of this command will inherit and execute. PersistentPreRun func(cmd *Command, args []string) - // PersistentPreRunE: PersistentPreRun but returns an error + // PersistentPreRunE: PersistentPreRun but returns an error. PersistentPreRunE func(cmd *Command, args []string) error // PreRun: children of this command will not inherit. PreRun func(cmd *Command, args []string) - // PreRunE: PreRun but returns an error + // PreRunE: PreRun but returns an error. PreRunE func(cmd *Command, args []string) error - // Run: Typically the actual work function. Most commands will only implement this + // Run: Typically the actual work function. Most commands will only implement this. Run func(cmd *Command, args []string) - // RunE: Run but returns an error + // RunE: Run but returns an error. RunE func(cmd *Command, args []string) error // PostRun: run after the Run command. PostRun func(cmd *Command, args []string) - // PostRunE: PostRun but returns an error + // PostRunE: PostRun but returns an error. PostRunE func(cmd *Command, args []string) error - // PersistentPostRun: children of this command will inherit and execute after PostRun + // PersistentPostRun: children of this command will inherit and execute after PostRun. PersistentPostRun func(cmd *Command, args []string) - // PersistentPostRunE: PersistentPostRun but returns an error + // PersistentPostRunE: PersistentPostRun but returns an error. PersistentPostRunE func(cmd *Command, args []string) error - // DisableAutoGenTag remove - DisableAutoGenTag bool - // Commands is the list of commands supported by this program. + + // groups for subcommands + commandgroups []*Group + + // args is actual args parsed from flags. + args []string + // flagErrorBuf contains all error messages from pflag. + flagErrorBuf *bytes.Buffer + // flags is full set of flags. + flags *flag.FlagSet + // pflags contains persistent flags. + pflags *flag.FlagSet + // lflags contains local flags. + // This field does not represent internal state, it's used as a cache to optimise LocalFlags function call + lflags *flag.FlagSet + // iflags contains inherited flags. + // This field does not represent internal state, it's used as a cache to optimise InheritedFlags function call + iflags *flag.FlagSet + // parentsPflags is all persistent flags of cmd's parents. + parentsPflags *flag.FlagSet + // globNormFunc is the global normalization function + // that we can use on every pflag set and children commands + globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + + // usageFunc is usage func defined by user. + usageFunc func(*Command) error + // usageTemplate is usage template defined by user. + usageTemplate string + // flagErrorFunc is func defined by user and it's called when the parsing of + // flags returns an error. + flagErrorFunc func(*Command, error) error + // helpTemplate is help template defined by user. + helpTemplate string + // helpFunc is help func defined by user. + helpFunc func(*Command, []string) + // helpCommand is command with usage 'help'. If it's not defined by user, + // cobra uses default help command. + helpCommand *Command + // helpCommandGroupID is the group id for the helpCommand + helpCommandGroupID string + + // completionCommandGroupID is the group id for the completion command + completionCommandGroupID string + + // versionTemplate is the version template defined by user. + versionTemplate string + + // errPrefix is the error message prefix defined by user. + errPrefix string + + // inReader is a reader defined by the user that replaces stdin + inReader io.Reader + // outWriter is a writer defined by the user that replaces stdout + outWriter io.Writer + // errWriter is a writer defined by the user that replaces stderr + errWriter io.Writer + + // FParseErrWhitelist flag parse errors to be ignored + FParseErrWhitelist FParseErrWhitelist + + // CompletionOptions is a set of options to control the handling of shell completion + CompletionOptions CompletionOptions + + // commandsAreSorted defines, if command slice are sorted or not. + commandsAreSorted bool + // commandCalledAs is the name or alias value used to call this command. + commandCalledAs struct { + name string + called bool + } + + ctx context.Context + + // commands is the list of commands supported by this program. commands []*Command - // Parent Command for this command + // parent is a parent command for this command. parent *Command - // max lengths of commands' string lengths for use in padding + // Max lengths of commands' string lengths for use in padding. commandsMaxUseLen int commandsMaxCommandPathLen int commandsMaxNameLen int - flagErrorBuf *bytes.Buffer + // TraverseChildren parses flags on all parents before executing child command. + TraverseChildren bool - args []string // actual args parsed from flags - output *io.Writer // nil means stderr; use Out() method instead - usageFunc func(*Command) error // Usage can be defined by application - usageTemplate string // Can be defined by Application - helpTemplate string // Can be defined by Application - helpFunc func(*Command, []string) // Help can be defined by application - helpCommand *Command // The help command - // The global normalization function that we can use on every pFlag set and children commands - globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + Hidden bool + + // SilenceErrors is an option to quiet errors down stream. + SilenceErrors bool - // Disable the suggestions based on Levenshtein distance that go along with 'unknown command' messages + // SilenceUsage is an option to silence usage when an error occurs. + SilenceUsage bool + + // DisableFlagParsing disables the flag parsing. + // If this is true all flags will be passed to the command as arguments. + DisableFlagParsing bool + + // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") + // will be printed by generating docs for this command. + DisableAutoGenTag bool + + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + + // DisableSuggestions disables the suggestions based on Levenshtein distance + // that go along with 'unknown command' messages. DisableSuggestions bool - // If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0 + + // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + // Must be > 0. SuggestionsMinimumDistance int } -// os.Args[1:] by default, if desired, can be overridden +// Context returns underlying command context. If command was executed +// with ExecuteContext or the context was set with SetContext, the +// previously set context will be returned. Otherwise, nil is returned. +// +// Notice that a call to Execute and ExecuteC will replace a nil context of +// a command with a context.Background, so a background context will be +// returned by Context after one of these functions has been called. +func (c *Command) Context() context.Context { + return c.ctx +} + +// SetContext sets context for the command. This context will be overwritten by +// Command.ExecuteContext or Command.ExecuteContextC. +func (c *Command) SetContext(ctx context.Context) { + c.ctx = ctx +} + +// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden // particularly useful when testing. func (c *Command) SetArgs(a []string) { c.args = a } -func (c *Command) getOut(def io.Writer) io.Writer { - if c.output != nil { - return *c.output - } - - if c.HasParent() { - return c.parent.Out() - } - return def +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +// Deprecated: Use SetOut and/or SetErr instead +func (c *Command) SetOutput(output io.Writer) { + c.outWriter = output + c.errWriter = output } -func (c *Command) Out() io.Writer { - return c.getOut(os.Stderr) +// SetOut sets the destination for usage messages. +// If newOut is nil, os.Stdout is used. +func (c *Command) SetOut(newOut io.Writer) { + c.outWriter = newOut } -func (c *Command) getOutOrStdout() io.Writer { - return c.getOut(os.Stdout) +// SetErr sets the destination for error messages. +// If newErr is nil, os.Stderr is used. +func (c *Command) SetErr(newErr io.Writer) { + c.errWriter = newErr } -// SetOutput sets the destination for usage and error messages. -// If output is nil, os.Stderr is used. -func (c *Command) SetOutput(output io.Writer) { - c.output = &output +// SetIn sets the source for input data +// If newIn is nil, os.Stdin is used. +func (c *Command) SetIn(newIn io.Reader) { + c.inReader = newIn } -// Usage can be defined by application +// SetUsageFunc sets usage function. Usage can be defined by application. func (c *Command) SetUsageFunc(f func(*Command) error) { c.usageFunc = f } -// Can be defined by Application +// SetUsageTemplate sets usage template. Can be defined by Application. func (c *Command) SetUsageTemplate(s string) { c.usageTemplate = s } -// Can be defined by Application +// SetFlagErrorFunc sets a function to generate an error when flag parsing +// fails. +func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { + c.flagErrorFunc = f +} + +// SetHelpFunc sets help function. Can be defined by Application. func (c *Command) SetHelpFunc(f func(*Command, []string)) { c.helpFunc = f } +// SetHelpCommand sets help command. func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } -// Can be defined by Application +// SetHelpCommandGroupID sets the group id of the help command. +func (c *Command) SetHelpCommandGroupID(groupID string) { + if c.helpCommand != nil { + c.helpCommand.GroupID = groupID + } + // helpCommandGroupID is used if no helpCommand is defined by the user + c.helpCommandGroupID = groupID +} + +// SetCompletionCommandGroupID sets the group id of the completion command. +func (c *Command) SetCompletionCommandGroupID(groupID string) { + // completionCommandGroupID is used if no completion command is defined by the user + c.Root().completionCommandGroupID = groupID +} + +// SetHelpTemplate sets help template to be used. Application can use it to set custom template. func (c *Command) SetHelpTemplate(s string) { c.helpTemplate = s } +// SetVersionTemplate sets version template to be used. Application can use it to set custom template. +func (c *Command) SetVersionTemplate(s string) { + c.versionTemplate = s +} + +// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. +func (c *Command) SetErrPrefix(s string) { + c.errPrefix = s +} + // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // The user should not have a cyclic dependency on commands. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { @@ -189,43 +373,148 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string } } +// OutOrStdout returns output to stdout. +func (c *Command) OutOrStdout() io.Writer { + return c.getOut(os.Stdout) +} + +// OutOrStderr returns output to stderr +func (c *Command) OutOrStderr() io.Writer { + return c.getOut(os.Stderr) +} + +// ErrOrStderr returns output to stderr +func (c *Command) ErrOrStderr() io.Writer { + return c.getErr(os.Stderr) +} + +// InOrStdin returns input to stdin +func (c *Command) InOrStdin() io.Reader { + return c.getIn(os.Stdin) +} + +func (c *Command) getOut(def io.Writer) io.Writer { + if c.outWriter != nil { + return c.outWriter + } + if c.HasParent() { + return c.parent.getOut(def) + } + return def +} + +func (c *Command) getErr(def io.Writer) io.Writer { + if c.errWriter != nil { + return c.errWriter + } + if c.HasParent() { + return c.parent.getErr(def) + } + return def +} + +func (c *Command) getIn(def io.Reader) io.Reader { + if c.inReader != nil { + return c.inReader + } + if c.HasParent() { + return c.parent.getIn(def) + } + return def +} + +// UsageFunc returns either the function set by SetUsageFunc for this command +// or a parent, or it returns a default usage function. func (c *Command) UsageFunc() (f func(*Command) error) { if c.usageFunc != nil { return c.usageFunc } - if c.HasParent() { - return c.parent.UsageFunc() + return c.Parent().UsageFunc() } return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) + c.mergePersistentFlags() + err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c) if err != nil { - fmt.Print(err) + c.PrintErrln(err) } return err } } +// Usage puts out the usage for the command. +// Used when a user provides invalid input. +// Can be defined by user by overriding UsageFunc. +func (c *Command) Usage() error { + return c.UsageFunc()(c) +} + // HelpFunc returns either the function set by SetHelpFunc for this command -// or a parent, or it returns a function which calls c.Help() +// or a parent, or it returns a function with default help behavior. func (c *Command) HelpFunc() func(*Command, []string) { - cmd := c - for cmd != nil { - if cmd.helpFunc != nil { - return cmd.helpFunc - } - cmd = cmd.parent + if c.helpFunc != nil { + return c.helpFunc + } + if c.HasParent() { + return c.Parent().HelpFunc() } - return func(*Command, []string) { - err := c.Help() + return func(c *Command, a []string) { + c.mergePersistentFlags() + // The help should be sent to stdout + // See https://github.com/spf13/cobra/issues/1002 + err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) if err != nil { - c.Println(err) + c.PrintErrln(err) } } } +// Help puts out the help for the command. +// Used when a user calls help [command]. +// Can be defined by user by overriding HelpFunc. +func (c *Command) Help() error { + c.HelpFunc()(c, []string{}) + return nil +} + +// UsageString returns usage string. +func (c *Command) UsageString() string { + // Storing normal writers + tmpOutput := c.outWriter + tmpErr := c.errWriter + + bb := new(bytes.Buffer) + c.outWriter = bb + c.errWriter = bb + + CheckErr(c.Usage()) + + // Setting things back to normal + c.outWriter = tmpOutput + c.errWriter = tmpErr + + return bb.String() +} + +// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this +// command or a parent, or it returns a function which returns the original +// error. +func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { + if c.flagErrorFunc != nil { + return c.flagErrorFunc + } + + if c.HasParent() { + return c.parent.FlagErrorFunc() + } + return func(c *Command, err error) error { + return err + } +} + var minUsagePadding = 25 +// UsagePadding return padding for the usage. func (c *Command) UsagePadding() int { if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen { return minUsagePadding @@ -235,7 +524,7 @@ func (c *Command) UsagePadding() int { var minCommandPathPadding = 11 -// +// CommandPathPadding return padding for the command path. func (c *Command) CommandPathPadding() int { if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen { return minCommandPathPadding @@ -245,6 +534,7 @@ func (c *Command) CommandPathPadding() int { var minNamePadding = 11 +// NamePadding returns padding for the name. func (c *Command) NamePadding() int { if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen { return minNamePadding @@ -252,6 +542,7 @@ func (c *Command) NamePadding() int { return c.parent.commandsMaxNameLen } +// UsageTemplate returns usage template for the command. func (c *Command) UsageTemplate() string { if c.usageTemplate != "" { return c.usageTemplate @@ -261,32 +552,38 @@ func (c *Command) UsageTemplate() string { return c.parent.UsageTemplate() } return `Usage:{{if .Runnable}} - {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}} - {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} Aliases: - {{.NameAndAliases}} -{{end}}{{if .HasExample}} + {{.NameAndAliases}}{{end}}{{if .HasExample}} Examples: -{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}} +{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}} + +Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}} -Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}} +{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}} + +Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} Flags: -{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}} +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} Global Flags: -{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}} +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} -Additional help topics:{{range .Commands}}{{if .IsHelpCommand}} - {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }} +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} ` } +// HelpTemplate return help template for the command. func (c *Command) HelpTemplate() string { if c.helpTemplate != "" { return c.helpTemplate @@ -295,72 +592,88 @@ func (c *Command) HelpTemplate() string { if c.HasParent() { return c.parent.HelpTemplate() } - return `{{with or .Long .Short }}{{. | trim}} + return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` } -// Really only used when casting a command to a commander -func (c *Command) resetChildrensParents() { - for _, x := range c.commands { - x.parent = c +// VersionTemplate return version template for the command. +func (c *Command) VersionTemplate() string { + if c.versionTemplate != "" { + return c.versionTemplate + } + + if c.HasParent() { + return c.parent.VersionTemplate() + } + return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} +` +} + +// ErrPrefix return error message prefix for the command +func (c *Command) ErrPrefix() string { + if c.errPrefix != "" { + return c.errPrefix + } + + if c.HasParent() { + return c.parent.ErrPrefix() } + return "Error:" } -// Test if the named flag is a boolean flag. -func isBooleanFlag(name string, f *flag.FlagSet) bool { - flag := f.Lookup(name) +func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { + flag := fs.Lookup(name) if flag == nil { return false } - return flag.Value.Type() == "bool" + return flag.NoOptDefVal != "" } -// Test if the named flag is a boolean flag. -func isBooleanShortFlag(name string, f *flag.FlagSet) bool { - result := false - f.VisitAll(func(f *flag.Flag) { - if f.Shorthand == name && f.Value.Type() == "bool" { - result = true - } - }) - return result +func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool { + if len(name) == 0 { + return false + } + + flag := fs.ShorthandLookup(name[:1]) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" } func stripFlags(args []string, c *Command) []string { - if len(args) < 1 { + if len(args) == 0 { return args } c.mergePersistentFlags() commands := []string{} - - inQuote := false - inFlag := false - for _, y := range args { - if !inQuote { - switch { - case strings.HasPrefix(y, "\""): - inQuote = true - case strings.Contains(y, "=\""): - inQuote = true - case strings.HasPrefix(y, "--") && !strings.Contains(y, "="): - // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' - inFlag = !isBooleanFlag(y[2:], c.Flags()) - case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()): - inFlag = true - case inFlag: - inFlag = false - case y == "": - // strip empty commands, as the go tests expect this to be ok.... - case !strings.HasPrefix(y, "-"): - commands = append(commands, y) - inFlag = false + flags := c.Flags() + +Loop: + for len(args) > 0 { + s := args[0] + args = args[1:] + switch { + case s == "--": + // "--" terminates the flags + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + // If '--flag arg' then + // delete arg from args. + fallthrough // (do the same as below) + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // If '-f arg' then + // delete 'arg' from args or break the loop if len(args) <= 1. + if len(args) <= 1 { + break Loop + } else { + args = args[1:] + continue } - } - - if strings.HasSuffix(y, "\"") && !strings.HasSuffix(y, "\\\"") { - inQuote = false + case s != "" && !strings.HasPrefix(s, "-"): + commands = append(commands, s) } } @@ -369,25 +682,50 @@ func stripFlags(args []string, c *Command) []string { // argsMinusFirstX removes only the first x from args. Otherwise, commands that look like // openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). -func argsMinusFirstX(args []string, x string) []string { - for i, y := range args { - if x == y { - ret := []string{} - ret = append(ret, args[:i]...) - ret = append(ret, args[i+1:]...) - return ret +// Special care needs to be taken not to remove a flag value. +func (c *Command) argsMinusFirstX(args []string, x string) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + flags := c.Flags() + +Loop: + for pos := 0; pos < len(args); pos++ { + s := args[pos] + switch { + case s == "--": + // -- means we have reached the end of the parseable args. Break out of the loop now. + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + fallthrough + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip + // over the next arg, because that is the value of this flag. + pos++ + continue + case !strings.HasPrefix(s, "-"): + // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, + // return the args, excluding the one at this position. + if s == x { + ret := make([]string, 0, len(args)-1) + ret = append(ret, args[:pos]...) + ret = append(ret, args[pos+1:]...) + return ret + } } } return args } -// find the target command given the args and command tree +func isFlagArg(arg string) bool { + return ((len(arg) >= 3 && arg[0:2] == "--") || + (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) +} + +// Find the target command given the args and command tree // Meant to be run on the highest node. Only searches down. func (c *Command) Find(args []string) (*Command, []string, error) { - if c == nil { - return nil, nil, fmt.Errorf("Called find() on a nil Command") - } - var innerfind func(*Command, []string) (*Command, []string) innerfind = func(c *Command, innerArgs []string) (*Command, []string) { @@ -396,59 +734,103 @@ func (c *Command) Find(args []string) (*Command, []string, error) { return c, innerArgs } nextSubCmd := argsWOflags[0] - matches := make([]*Command, 0) - for _, cmd := range c.commands { - if cmd.Name() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) - } - if EnablePrefixMatching { - if strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match - matches = append(matches, cmd) - } - for _, x := range cmd.Aliases { - if strings.HasPrefix(x, nextSubCmd) { - matches = append(matches, cmd) - } - } - } - } - // only accept a single prefix match - multiple matches would be ambiguous - if len(matches) == 1 { - return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0])) + cmd := c.findNext(nextSubCmd) + if cmd != nil { + return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd)) } - return c, innerArgs } commandFound, a := innerfind(c, args) - argsWOflags := stripFlags(a, commandFound) + if commandFound.Args == nil { + return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound)) + } + return commandFound, a, nil +} - // no subcommand, always take args - if !commandFound.HasSubCommands() { - return commandFound, a, nil +func (c *Command) findSuggestions(arg string) string { + if c.DisableSuggestions { + return "" + } + if c.SuggestionsMinimumDistance <= 0 { + c.SuggestionsMinimumDistance = 2 + } + var sb strings.Builder + if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { + sb.WriteString("\n\nDid you mean this?\n") + for _, s := range suggestions { + _, _ = fmt.Fprintf(&sb, "\t%v\n", s) + } } + return sb.String() +} - // root command with subcommands, do subcommand checking - if commandFound == c && len(argsWOflags) > 0 { - suggestionsString := "" - if !c.DisableSuggestions { - if c.SuggestionsMinimumDistance <= 0 { - c.SuggestionsMinimumDistance = 2 - } - if suggestions := c.SuggestionsFor(argsWOflags[0]); len(suggestions) > 0 { - suggestionsString += "\n\nDid you mean this?\n" - for _, s := range suggestions { - suggestionsString += fmt.Sprintf("\t%v\n", s) - } - } +func (c *Command) findNext(next string) *Command { + matches := make([]*Command, 0) + for _, cmd := range c.commands { + if commandNameMatches(cmd.Name(), next) || cmd.HasAlias(next) { + cmd.commandCalledAs.name = next + return cmd + } + if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { + matches = append(matches, cmd) } - return commandFound, a, fmt.Errorf("unknown command %q for %q%s", argsWOflags[0], commandFound.CommandPath(), suggestionsString) } - return commandFound, a, nil + if len(matches) == 1 { + // Temporarily disable gosec G602, which produces a false positive. + // See https://github.com/securego/gosec/issues/1005. + return matches[0] // #nosec G602 + } + + return nil +} + +// Traverse the command tree to find the command, and parse args for +// each parent. +func (c *Command) Traverse(args []string) (*Command, []string, error) { + flags := []string{} + inFlag := false + + for i, arg := range args { + switch { + // A long flag with a space separated value + case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="): + // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' + inFlag = !hasNoOptDefVal(arg[2:], c.Flags()) + flags = append(flags, arg) + continue + // A short flag with a space separated value + case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()): + inFlag = true + flags = append(flags, arg) + continue + // The value for a flag + case inFlag: + inFlag = false + flags = append(flags, arg) + continue + // A flag without a value, or with an `=` separated value + case isFlagArg(arg): + flags = append(flags, arg) + continue + } + + cmd := c.findNext(arg) + if cmd == nil { + return c, args, nil + } + + if err := c.ParseFlags(flags); err != nil { + return nil, args, err + } + return cmd.Traverse(args[i+1:]) + } + return c, args, nil } +// SuggestionsFor provides suggestions for the typedName. func (c *Command) SuggestionsFor(typedName string) []string { suggestions := []string{} for _, cmd := range c.commands { @@ -469,84 +851,119 @@ func (c *Command) SuggestionsFor(typedName string) []string { return suggestions } +// VisitParents visits all parents of the command and invokes fn on each parent. func (c *Command) VisitParents(fn func(*Command)) { - var traverse func(*Command) *Command - - traverse = func(x *Command) *Command { - if x != c { - fn(x) - } - if x.HasParent() { - return traverse(x.parent) - } - return x + if c.HasParent() { + fn(c.Parent()) + c.Parent().VisitParents(fn) } - traverse(c) } +// Root finds root command. func (c *Command) Root() *Command { - var findRoot func(*Command) *Command - - findRoot = func(x *Command) *Command { - if x.HasParent() { - return findRoot(x.parent) - } - return x + if c.HasParent() { + return c.Parent().Root() } - - return findRoot(c) + return c } -// ArgsLenAtDash will return the length of f.Args at the moment when a -- was -// found during arg parsing. This allows your program to know which args were -// before the -- and which came after. (Description from -// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash). +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. func (c *Command) ArgsLenAtDash() int { return c.Flags().ArgsLenAtDash() } func (c *Command) execute(a []string) (err error) { if c == nil { - return fmt.Errorf("Called Execute() on a nil Command") + return fmt.Errorf("called Execute() on a nil Command") } if len(c.Deprecated) > 0 { c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) } - // initialize help flag as the last point possible to allow for user + // initialize help and version flag at the last point possible to allow for user // overriding - c.initHelpFlag() + c.InitDefaultHelpFlag() + c.InitDefaultVersionFlag() err = c.ParseFlags(a) if err != nil { - return err + return c.FlagErrorFunc()(c, err) } - // If help is called, regardless of other flags, return we want help + + // If help is called, regardless of other flags, return we want help. // Also say we need help if the command isn't runnable. helpVal, err := c.Flags().GetBool("help") if err != nil { // should be impossible to get here as we always declare a help - // flag in initHelpFlag() + // flag in InitDefaultHelpFlag() c.Println("\"help\" flag declared as non-bool. Please correct your code") return err } - if helpVal || !c.Runnable() { + + if helpVal { + return flag.ErrHelp + } + + // for back-compat, only add version flag behavior if version is defined + if c.Version != "" { + versionVal, err := c.Flags().GetBool("version") + if err != nil { + c.Println("\"version\" flag declared as non-bool. Please correct your code") + return err + } + if versionVal { + err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } + } + + if !c.Runnable() { return flag.ErrHelp } c.preRun() + + defer c.postRun() + argWoFlags := c.Flags().Args() + if c.DisableFlagParsing { + argWoFlags = a + } + if err := c.ValidateArgs(argWoFlags); err != nil { + return err + } + + parents := make([]*Command, 0, 5) for p := c; p != nil; p = p.Parent() { + if EnableTraverseRunHooks { + // When EnableTraverseRunHooks is set: + // - Execute all persistent pre-runs from the root parent till this command. + // - Execute all persistent post-runs from this command till the root parent. + parents = append([]*Command{p}, parents...) + } else { + // Otherwise, execute only the first found persistent hook. + parents = append(parents, p) + } + } + for _, p := range parents { if p.PersistentPreRunE != nil { if err := p.PersistentPreRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPreRun != nil { p.PersistentPreRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } if c.PreRunE != nil { @@ -557,6 +974,13 @@ func (c *Command) execute(a []string) (err error) { c.PreRun(c, argWoFlags) } + if err := c.ValidateRequiredFlags(); err != nil { + return err + } + if err := c.ValidateFlagGroups(); err != nil { + return err + } + if c.RunE != nil { if err := c.RunE(c, argWoFlags); err != nil { return err @@ -576,10 +1000,14 @@ func (c *Command) execute(a []string) (err error) { if err := p.PersistentPostRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPostRun != nil { p.PersistentPostRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } @@ -592,18 +1020,21 @@ func (c *Command) preRun() { } } -func (c *Command) errorMsgFromParse() string { - s := c.flagErrorBuf.String() - - x := strings.Split(s, "\n") - - if len(x) > 0 { - return x[0] +func (c *Command) postRun() { + for _, x := range finalizers { + x() } - return "" } -// Call execute to use the args (os.Args[1:] by default) +// ExecuteContext is the same as Execute(), but sets the ctx on the command. +// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs +// functions. +func (c *Command) ExecuteContext(ctx context.Context) error { + c.ctx = ctx + return c.Execute() +} + +// Execute uses the args (os.Args[1:] by default) // and run through the command tree finding appropriate matches // for commands and then corresponding flags. func (c *Command) Execute() error { @@ -611,7 +1042,19 @@ func (c *Command) Execute() error { return err } +// ExecuteContextC is the same as ExecuteC(), but sets the ctx on the command. +// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs +// functions. +func (c *Command) ExecuteContextC(ctx context.Context) (*Command, error) { + c.ctx = ctx + return c.ExecuteC() +} + +// ExecuteC executes the command. func (c *Command) ExecuteC() (cmd *Command, err error) { + if c.ctx == nil { + c.ctx = context.Background() + } // Regardless of what command execute is called on, run on Root only if c.HasParent() { @@ -623,99 +1066,239 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { preExecHookFn(c) } - // initialize help as the last point possible to allow for user - // overriding - c.initHelpCmd() + // initialize help at the last point to allow for user overriding + c.InitDefaultHelpCmd() + // initialize completion at the last point to allow for user overriding + c.InitDefaultCompletionCmd() + + // Now that all commands have been created, let's make sure all groups + // are properly created also + c.checkCommandGroups() - var args []string + args := c.args // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155 if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" { args = os.Args[1:] - } else { - args = c.args } - cmd, flags, err := c.Find(args) + // initialize the hidden command to be used for shell completion + c.initCompleteCmd(args) + + var flags []string + if c.TraverseChildren { + cmd, flags, err = c.Traverse(args) + } else { + cmd, flags, err = c.Find(args) + } if err != nil { // If found parse to a subcommand and then failed, talk about the subcommand if cmd != nil { c = cmd } if !c.SilenceErrors { - c.Println("Error:", err.Error()) - c.Printf("Run '%v --help' for usage.\n", c.CommandPath()) + c.PrintErrln(c.ErrPrefix(), err.Error()) + c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err } + + cmd.commandCalledAs.called = true + if cmd.commandCalledAs.name == "" { + cmd.commandCalledAs.name = cmd.Name() + } + + // We have to pass global context to children command + // if context is present on the parent command. + if cmd.ctx == nil { + cmd.ctx = c.ctx + } + err = cmd.execute(flags) if err != nil { // Always show help if requested, even if SilenceErrors is in // effect - if err == flag.ErrHelp { + if errors.Is(err, flag.ErrHelp) { cmd.HelpFunc()(cmd, args) return cmd, nil } - // If root command has SilentErrors flagged, + // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.Println("Error:", err.Error()) + c.PrintErrln(cmd.ErrPrefix(), err.Error()) } - // If root command has SilentUsage flagged, + // If root command has SilenceUsage flagged, // all subcommands should respect it if !cmd.SilenceUsage && !c.SilenceUsage { c.Println(cmd.UsageString()) } - return cmd, err } - return cmd, nil + return cmd, err } -func (c *Command) initHelpFlag() { - if c.Flags().Lookup("help") == nil { - c.Flags().BoolP("help", "h", false, "help for "+c.Name()) +func (c *Command) ValidateArgs(args []string) error { + if c.Args == nil { + return ArbitraryArgs(c, args) } + return c.Args(c, args) } -func (c *Command) initHelpCmd() { - if c.helpCommand == nil { - if !c.HasSubCommands() { +// ValidateRequiredFlags validates all required flags are present and returns an error otherwise +func (c *Command) ValidateRequiredFlags() error { + if c.DisableFlagParsing { + return nil + } + + flags := c.Flags() + missingFlagNames := []string{} + flags.VisitAll(func(pflag *flag.Flag) { + requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag] + if !found { return } + if (requiredAnnotation[0] == "true") && !pflag.Changed { + missingFlagNames = append(missingFlagNames, pflag.Name) + } + }) + + if len(missingFlagNames) > 0 { + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) + } + return nil +} + +// checkCommandGroups checks if a command has been added to a group that does not exists. +// If so, we panic because it indicates a coding error that should be corrected. +func (c *Command) checkCommandGroups() { + for _, sub := range c.commands { + // if Group is not defined let the developer know right away + if sub.GroupID != "" && !c.ContainsGroup(sub.GroupID) { + panic(fmt.Sprintf("group id '%s' is not defined for subcommand '%s'", sub.GroupID, sub.CommandPath())) + } + + sub.checkCommandGroups() + } +} + +// InitDefaultHelpFlag adds default help flag to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help flag, it will do nothing. +func (c *Command) InitDefaultHelpFlag() { + c.mergePersistentFlags() + if c.Flags().Lookup("help") == nil { + usage := "help for " + name := c.displayName() + if name == "" { + usage += "this command" + } else { + usage += name + } + c.Flags().BoolP("help", "h", false, usage) + _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"}) + } +} + +// InitDefaultVersionFlag adds default version flag to c. +// It is called automatically by executing the c. +// If c already has a version flag, it will do nothing. +// If c.Version is empty, it will do nothing. +func (c *Command) InitDefaultVersionFlag() { + if c.Version == "" { + return + } + + c.mergePersistentFlags() + if c.Flags().Lookup("version") == nil { + usage := "version for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + if c.Flags().ShorthandLookup("v") == nil { + c.Flags().BoolP("version", "v", false, usage) + } else { + c.Flags().Bool("version", false, usage) + } + _ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"}) + } +} + +// InitDefaultHelpCmd adds default help command to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help command or c has no subcommands, it will do nothing. +func (c *Command) InitDefaultHelpCmd() { + if !c.HasSubCommands() { + return + } + if c.helpCommand == nil { c.helpCommand = &Command{ Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - PersistentPreRun: func(cmd *Command, args []string) {}, - PersistentPostRun: func(cmd *Command, args []string) {}, - +Simply type ` + c.displayName() + ` help [path to command] for full details.`, + ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + var completions []string + cmd, _, e := c.Root().Find(args) + if e != nil { + return nil, ShellCompDirectiveNoFileComp + } + if cmd == nil { + // Root help command. + cmd = c.Root() + } + for _, subCmd := range cmd.Commands() { + if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand { + if strings.HasPrefix(subCmd.Name(), toComplete) { + completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short)) + } + } + } + return completions, ShellCompDirectiveNoFileComp + }, Run: func(c *Command, args []string) { cmd, _, e := c.Root().Find(args) if cmd == nil || e != nil { - c.Printf("Unknown help topic %#q.", args) - c.Root().Usage() + c.Printf("Unknown help topic %#q\n", args) + CheckErr(c.Root().Usage()) } else { - helpFunc := cmd.HelpFunc() - helpFunc(cmd, args) + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown + CheckErr(cmd.Help()) } }, + GroupID: c.helpCommandGroupID, } } + c.RemoveCommand(c.helpCommand) c.AddCommand(c.helpCommand) } -// Used for testing +// ResetCommands delete parent, subcommand and help command from c. func (c *Command) ResetCommands() { + c.parent = nil c.commands = nil c.helpCommand = nil + c.parentsPflags = nil } -//Commands returns a slice of child commands. +// Sorts commands by their names. +type commandSorterByName []*Command + +func (c commandSorterByName) Len() int { return len(c) } +func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() } + +// Commands returns a sorted slice of child commands. func (c *Command) Commands() []*Command { + // do not sort commands if it already sorted or sorting was disabled + if EnableCommandSorting && !c.commandsAreSorted { + sort.Sort(commandSorterByName(c.commands)) + c.commandsAreSorted = true + } return c.commands } @@ -744,7 +1327,38 @@ func (c *Command) AddCommand(cmds ...*Command) { x.SetGlobalNormalizationFunc(c.globNormFunc) } c.commands = append(c.commands, x) + c.commandsAreSorted = false + } +} + +// Groups returns a slice of child command groups. +func (c *Command) Groups() []*Group { + return c.commandgroups +} + +// AllChildCommandsHaveGroup returns if all subcommands are assigned to a group +func (c *Command) AllChildCommandsHaveGroup() bool { + for _, sub := range c.commands { + if (sub.IsAvailableCommand() || sub == c.helpCommand) && sub.GroupID == "" { + return false + } + } + return true +} + +// ContainsGroup return if groupID exists in the list of command groups. +func (c *Command) ContainsGroup(groupID string) bool { + for _, x := range c.commandgroups { + if x.ID == groupID { + return true + } } + return false +} + +// AddGroup adds one or more command groups to this parent command. +func (c *Command) AddGroup(groups ...*Group) { + c.commandgroups = append(c.commandgroups, groups...) } // RemoveCommand removes one or more commands from a parent command. @@ -781,72 +1395,71 @@ main: } } -// Print is a convenience method to Print to the defined output +// Print is a convenience method to Print to the defined output, fallback to Stderr if not set. func (c *Command) Print(i ...interface{}) { - fmt.Fprint(c.Out(), i...) + fmt.Fprint(c.OutOrStderr(), i...) } -// Println is a convenience method to Println to the defined output +// Println is a convenience method to Println to the defined output, fallback to Stderr if not set. func (c *Command) Println(i ...interface{}) { - str := fmt.Sprintln(i...) - c.Print(str) + c.Print(fmt.Sprintln(i...)) } -// Printf is a convenience method to Printf to the defined output +// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. func (c *Command) Printf(format string, i ...interface{}) { - str := fmt.Sprintf(format, i...) - c.Print(str) + c.Print(fmt.Sprintf(format, i...)) } -// Output the usage for the command -// Used when a user provides invalid input -// Can be defined by user by overriding UsageFunc -func (c *Command) Usage() error { - c.mergePersistentFlags() - err := c.UsageFunc()(c) - return err +// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErr(i ...interface{}) { + fmt.Fprint(c.ErrOrStderr(), i...) } -// Output the help for the command -// Used when a user calls help [command] -// by the default HelpFunc in the commander -func (c *Command) Help() error { - c.mergePersistentFlags() - err := tmpl(c.getOutOrStdout(), c.HelpTemplate(), c) - return err +// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErrln(i ...interface{}) { + c.PrintErr(fmt.Sprintln(i...)) } -func (c *Command) UsageString() string { - tmpOutput := c.output - bb := new(bytes.Buffer) - c.SetOutput(bb) - c.Usage() - c.output = tmpOutput - return bb.String() +// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set. +func (c *Command) PrintErrf(format string, i ...interface{}) { + c.PrintErr(fmt.Sprintf(format, i...)) } // CommandPath returns the full path to this command. func (c *Command) CommandPath() string { - str := c.Name() - x := c - for x.HasParent() { - str = x.parent.Name() + " " + str - x = x.parent + if c.HasParent() { + return c.Parent().CommandPath() + " " + c.Name() } - return str + return c.displayName() } -//The full usage for a given command (including parents) +func (c *Command) displayName() string { + if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok { + return displayName + } + return c.Name() +} + +// UseLine puts out the full usage for a given command (including parents). func (c *Command) UseLine() string { - str := "" + var useline string + use := strings.Replace(c.Use, c.Name(), c.displayName(), 1) if c.HasParent() { - str = c.parent.CommandPath() + " " + useline = c.parent.CommandPath() + " " + use + } else { + useline = use + } + if c.DisableFlagsInUseLine { + return useline } - return str + c.Use + if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { + useline += " [flags]" + } + return useline } -// For use in determining which flags have been assigned to which commands -// and which persist +// DebugFlags used to determine which flags have been assigned to which commands +// and which persist. func (c *Command) DebugFlags() { c.Println("DebugFlags called on", c.Name()) var debugflags func(*Command) @@ -857,12 +1470,8 @@ func (c *Command) DebugFlags() { } if x.HasFlags() { x.flags.VisitAll(func(f *flag.Flag) { - if x.HasPersistentFlags() { - if x.persistentFlag(f.Name) == nil { - c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") - } else { - c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") - } + if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") } else { c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") } @@ -892,9 +1501,6 @@ func (c *Command) DebugFlags() { // Name returns the command's name: the first word in the use line. func (c *Command) Name() string { - if c.name != "" { - return c.name - } name := c.Use i := strings.Index(name, " ") if i >= 0 { @@ -906,33 +1512,60 @@ func (c *Command) Name() string { // HasAlias determines if a given string is an alias of the command. func (c *Command) HasAlias(s string) bool { for _, a := range c.Aliases { - if a == s { + if commandNameMatches(a, s) { return true } } return false } +// CalledAs returns the command name or alias that was used to invoke +// this command or an empty string if the command has not been called. +func (c *Command) CalledAs() string { + if c.commandCalledAs.called { + return c.commandCalledAs.name + } + return "" +} + +// hasNameOrAliasPrefix returns true if the Name or any of aliases start +// with prefix +func (c *Command) hasNameOrAliasPrefix(prefix string) bool { + if strings.HasPrefix(c.Name(), prefix) { + c.commandCalledAs.name = c.Name() + return true + } + for _, alias := range c.Aliases { + if strings.HasPrefix(alias, prefix) { + c.commandCalledAs.name = alias + return true + } + } + return false +} + +// NameAndAliases returns a list of the command name and all aliases func (c *Command) NameAndAliases() string { return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") } +// HasExample determines if the command has example. func (c *Command) HasExample() bool { return len(c.Example) > 0 } -// Runnable determines if the command is itself runnable +// Runnable determines if the command is itself runnable. func (c *Command) Runnable() bool { return c.Run != nil || c.RunE != nil } -// HasSubCommands determines if the command has children commands +// HasSubCommands determines if the command has children commands. func (c *Command) HasSubCommands() bool { return len(c.commands) > 0 } // IsAvailableCommand determines if a command is available as a non-help command -// (this includes all non deprecated/hidden commands) +// (this includes all non deprecated/hidden commands). func (c *Command) IsAvailableCommand() bool { if len(c.Deprecated) != 0 || c.Hidden { return false @@ -949,11 +1582,12 @@ func (c *Command) IsAvailableCommand() bool { return false } -// IsHelpCommand determines if a command is a 'help' command; a help command is -// determined by the fact that it is NOT runnable/hidden/deprecated, and has no -// sub commands that are runnable/hidden/deprecated -func (c *Command) IsHelpCommand() bool { - +// IsAdditionalHelpTopicCommand determines if a command is an additional +// help topic command; additional help topic command is determined by the +// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that +// are runnable/hidden/deprecated. +// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. +func (c *Command) IsAdditionalHelpTopicCommand() bool { // if a command is runnable, deprecated, or hidden it is not a 'help' command if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden { return false @@ -961,7 +1595,7 @@ func (c *Command) IsHelpCommand() bool { // if any non-help sub commands are found, the command is not a 'help' command for _, sub := range c.commands { - if !sub.IsHelpCommand() { + if !sub.IsAdditionalHelpTopicCommand() { return false } } @@ -970,14 +1604,13 @@ func (c *Command) IsHelpCommand() bool { return true } -// HasHelpSubCommands determines if a command has any avilable 'help' sub commands +// HasHelpSubCommands determines if a command has any available 'help' sub commands // that need to be shown in the usage/help default template under 'additional help -// topics' +// topics'. func (c *Command) HasHelpSubCommands() bool { - // return true on the first found available 'help' sub command for _, sub := range c.commands { - if sub.IsHelpCommand() { + if sub.IsAdditionalHelpTopicCommand() { return true } } @@ -987,9 +1620,8 @@ func (c *Command) HasHelpSubCommands() bool { } // HasAvailableSubCommands determines if a command has available sub commands that -// need to be shown in the usage/help default template under 'available commands' +// need to be shown in the usage/help default template under 'available commands'. func (c *Command) HasAvailableSubCommands() bool { - // return true on the first found available (non deprecated/help/hidden) // sub command for _, sub := range c.commands { @@ -998,89 +1630,113 @@ func (c *Command) HasAvailableSubCommands() bool { } } - // the command either has no sub comamnds, or no available (non deprecated/help/hidden) + // the command either has no sub commands, or no available (non deprecated/help/hidden) // sub commands return false } -// Determine if the command is a child command +// HasParent determines if the command is a child command. func (c *Command) HasParent() bool { return c.parent != nil } -// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists +// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { return c.globNormFunc } -// Get the complete FlagSet that applies to this command (local and persistent declared here and by all parents) +// Flags returns the complete FlagSet that applies +// to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } c.flags.SetOutput(c.flagErrorBuf) } + return c.flags } -// Get the local FlagSet specifically set in the current command +// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. +func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { + persistentFlags := c.PersistentFlags() + + out := flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.LocalFlags().VisitAll(func(f *flag.Flag) { + if persistentFlags.Lookup(f.Name) == nil { + out.AddFlag(f) + } + }) + return out +} + +// LocalFlags returns the local FlagSet specifically set in the current command. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() - local := flag.NewFlagSet(c.Name(), flag.ContinueOnError) - c.lflags.VisitAll(func(f *flag.Flag) { - local.AddFlag(f) - }) - if !c.HasParent() { - flag.CommandLine.VisitAll(func(f *flag.Flag) { - if local.Lookup(f.Name) == nil { - local.AddFlag(f) - } - }) + if c.lflags == nil { + c.lflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.lflags.SetOutput(c.flagErrorBuf) + } + c.lflags.SortFlags = c.Flags().SortFlags + if c.globNormFunc != nil { + c.lflags.SetNormalizeFunc(c.globNormFunc) } - return local + + addToLocal := func(f *flag.Flag) { + // Add the flag if it is not a parent PFlag, or it shadows a parent PFlag + if c.lflags.Lookup(f.Name) == nil && f != c.parentsPflags.Lookup(f.Name) { + c.lflags.AddFlag(f) + } + } + c.Flags().VisitAll(addToLocal) + c.PersistentFlags().VisitAll(addToLocal) + return c.lflags } -// All Flags which were inherited from parents commands +// InheritedFlags returns all flags which were inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) InheritedFlags() *flag.FlagSet { c.mergePersistentFlags() - inherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError) - local := c.LocalFlags() - - var rmerge func(x *Command) - - rmerge = func(x *Command) { - if x.HasPersistentFlags() { - x.PersistentFlags().VisitAll(func(f *flag.Flag) { - if inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { - inherited.AddFlag(f) - } - }) - } - if x.HasParent() { - rmerge(x.parent) + if c.iflags == nil { + c.iflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) } + c.iflags.SetOutput(c.flagErrorBuf) } - if c.HasParent() { - rmerge(c.parent) + local := c.LocalFlags() + if c.globNormFunc != nil { + c.iflags.SetNormalizeFunc(c.globNormFunc) } - return inherited + c.parentsPflags.VisitAll(func(f *flag.Flag) { + if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { + c.iflags.AddFlag(f) + } + }) + return c.iflags } -// All Flags which were not inherited from parent commands +// NonInheritedFlags returns all flags which were not inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) NonInheritedFlags() *flag.FlagSet { return c.LocalFlags() } -// Get the Persistent FlagSet specifically set in the current command +// PersistentFlags returns the persistent FlagSet specifically set in the current command. func (c *Command) PersistentFlags() *flag.FlagSet { if c.pflags == nil { - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1089,60 +1745,64 @@ func (c *Command) PersistentFlags() *flag.FlagSet { return c.pflags } -// For use in testing +// ResetFlags deletes all flags from command. func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.flags.SetOutput(c.flagErrorBuf) - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) + + c.lflags = nil + c.iflags = nil + c.parentsPflags = nil } -// Does the command contain any flags (local plus persistent from the entire structure) +// HasFlags checks if the command contains any flags (local plus persistent from the entire structure). func (c *Command) HasFlags() bool { return c.Flags().HasFlags() } -// Does the command contain persistent flags +// HasPersistentFlags checks if the command contains persistent flags. func (c *Command) HasPersistentFlags() bool { return c.PersistentFlags().HasFlags() } -// Does the command has flags specifically declared locally +// HasLocalFlags checks if the command has flags specifically declared locally. func (c *Command) HasLocalFlags() bool { return c.LocalFlags().HasFlags() } -// Does the command have flags inherited from its parent command +// HasInheritedFlags checks if the command has flags inherited from its parent command. func (c *Command) HasInheritedFlags() bool { return c.InheritedFlags().HasFlags() } -// Does the command contain any flags (local plus persistent from the entire -// structure) which are not hidden or deprecated +// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire +// structure) which are not hidden or deprecated. func (c *Command) HasAvailableFlags() bool { return c.Flags().HasAvailableFlags() } -// Does the command contain persistent flags which are not hidden or deprecated +// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. func (c *Command) HasAvailablePersistentFlags() bool { return c.PersistentFlags().HasAvailableFlags() } -// Does the command has flags specifically declared locally which are not hidden -// or deprecated +// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden +// or deprecated. func (c *Command) HasAvailableLocalFlags() bool { return c.LocalFlags().HasAvailableFlags() } -// Does the command have flags inherited from its parent command which are -// not hidden or deprecated +// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are +// not hidden or deprecated. func (c *Command) HasAvailableInheritedFlags() bool { return c.InheritedFlags().HasAvailableFlags() } -// Flag climbs up the command tree looking for matching flag +// Flag climbs up the command tree looking for matching flag. func (c *Command) Flag(name string) (flag *flag.Flag) { flag = c.Flags().Lookup(name) @@ -1153,65 +1813,84 @@ func (c *Command) Flag(name string) (flag *flag.Flag) { return } -// recursively find matching persistent flag +// Recursively find matching persistent flag. func (c *Command) persistentFlag(name string) (flag *flag.Flag) { if c.HasPersistentFlags() { flag = c.PersistentFlags().Lookup(name) } - if flag == nil && c.HasParent() { - flag = c.parent.persistentFlag(name) + if flag == nil { + c.updateParentsPflags() + flag = c.parentsPflags.Lookup(name) } return } -// ParseFlags parses persistent flag tree & local flags -func (c *Command) ParseFlags(args []string) (err error) { +// ParseFlags parses persistent flag tree and local flags. +func (c *Command) ParseFlags(args []string) error { + if c.DisableFlagParsing { + return nil + } + + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + beforeErrorBufLen := c.flagErrorBuf.Len() c.mergePersistentFlags() - err = c.Flags().Parse(args) - return + + // do it here after merging all flags and just before parse + c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist) + + err := c.Flags().Parse(args) + // Print warnings if they occurred (e.g. deprecated flag messages). + if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil { + c.Print(c.flagErrorBuf.String()) + } + + return err } -// Parent returns a commands parent command +// Parent returns a commands parent command. func (c *Command) Parent() *Command { return c.parent } +// mergePersistentFlags merges c.PersistentFlags() to c.Flags() +// and adds missing persistent flags of all parents. func (c *Command) mergePersistentFlags() { - var rmerge func(x *Command) + c.updateParentsPflags() + c.Flags().AddFlagSet(c.PersistentFlags()) + c.Flags().AddFlagSet(c.parentsPflags) +} - // Save the set of local flags - if c.lflags == nil { - c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) - if c.flagErrorBuf == nil { - c.flagErrorBuf = new(bytes.Buffer) - } - c.lflags.SetOutput(c.flagErrorBuf) - addtolocal := func(f *flag.Flag) { - c.lflags.AddFlag(f) - } - c.Flags().VisitAll(addtolocal) - c.PersistentFlags().VisitAll(addtolocal) - } - rmerge = func(x *Command) { - if !x.HasParent() { - flag.CommandLine.VisitAll(func(f *flag.Flag) { - if x.PersistentFlags().Lookup(f.Name) == nil { - x.PersistentFlags().AddFlag(f) - } - }) - } - if x.HasPersistentFlags() { - x.PersistentFlags().VisitAll(func(f *flag.Flag) { - if c.Flags().Lookup(f.Name) == nil { - c.Flags().AddFlag(f) - } - }) - } - if x.HasParent() { - rmerge(x.parent) - } +// updateParentsPflags updates c.parentsPflags by adding +// new persistent flags of all parents. +// If c.parentsPflags == nil, it makes new. +func (c *Command) updateParentsPflags() { + if c.parentsPflags == nil { + c.parentsPflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) + c.parentsPflags.SetOutput(c.flagErrorBuf) + c.parentsPflags.SortFlags = false + } + + if c.globNormFunc != nil { + c.parentsPflags.SetNormalizeFunc(c.globNormFunc) + } + + c.Root().PersistentFlags().AddFlagSet(flag.CommandLine) + + c.VisitParents(func(parent *Command) { + c.parentsPflags.AddFlagSet(parent.PersistentFlags()) + }) +} + +// commandNameMatches checks if two command names are equal +// taking into account case sensitivity according to +// EnableCaseInsensitive global configuration. +func commandNameMatches(s string, t string) bool { + if EnableCaseInsensitive { + return strings.EqualFold(s, t) } - rmerge(c) + return s == t } diff --git a/vendor/github.com/spf13/cobra/command_notwin.go b/vendor/github.com/spf13/cobra/command_notwin.go index 6159c1cc1..307f0c127 100644 --- a/vendor/github.com/spf13/cobra/command_notwin.go +++ b/vendor/github.com/spf13/cobra/command_notwin.go @@ -1,3 +1,18 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !windows // +build !windows package cobra diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go index 4b0eaa1b6..adbef395c 100644 --- a/vendor/github.com/spf13/cobra/command_win.go +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -1,8 +1,24 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows // +build windows package cobra import ( + "fmt" "os" "time" @@ -11,16 +27,15 @@ import ( var preExecHookFn = preExecHook -// enables an information splash screen on Windows if the CLI is started from explorer.exe. -var MousetrapHelpText string = `This is a command line tool - -You need to open cmd.exe and run it from there. -` - func preExecHook(c *Command) { - if mousetrap.StartedByExplorer() { + if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { c.Print(MousetrapHelpText) - time.Sleep(5 * time.Second) + if MousetrapDisplayDuration > 0 { + time.Sleep(MousetrapDisplayDuration) + } else { + c.Println("Press return to continue...") + fmt.Scanln() + } os.Exit(1) } } diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go new file mode 100644 index 000000000..c0c08b057 --- /dev/null +++ b/vendor/github.com/spf13/cobra/completions.go @@ -0,0 +1,939 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "fmt" + "os" + "regexp" + "strconv" + "strings" + "sync" + + "github.com/spf13/pflag" +) + +const ( + // ShellCompRequestCmd is the name of the hidden command that is used to request + // completion results from the program. It is used by the shell completion scripts. + ShellCompRequestCmd = "__complete" + // ShellCompNoDescRequestCmd is the name of the hidden command that is used to request + // completion results without their description. It is used by the shell completion scripts. + ShellCompNoDescRequestCmd = "__completeNoDesc" +) + +// Global map of flag completion functions. Make sure to use flagCompletionMutex before you try to read and write from it. +var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){} + +// lock for reading and writing from flagCompletionFunctions +var flagCompletionMutex = &sync.RWMutex{} + +// ShellCompDirective is a bit map representing the different behaviors the shell +// can be instructed to have once completions have been provided. +type ShellCompDirective int + +type flagCompError struct { + subCommand string + flagName string +} + +func (e *flagCompError) Error() string { + return "Subcommand '" + e.subCommand + "' does not support flag '" + e.flagName + "'" +} + +const ( + // ShellCompDirectiveError indicates an error occurred and completions should be ignored. + ShellCompDirectiveError ShellCompDirective = 1 << iota + + // ShellCompDirectiveNoSpace indicates that the shell should not add a space + // after the completion even if there is a single completion provided. + ShellCompDirectiveNoSpace + + // ShellCompDirectiveNoFileComp indicates that the shell should not provide + // file completion even when no completion is provided. + ShellCompDirectiveNoFileComp + + // ShellCompDirectiveFilterFileExt indicates that the provided completions + // should be used as file extension filters. + // For flags, using Command.MarkFlagFilename() and Command.MarkPersistentFlagFilename() + // is a shortcut to using this directive explicitly. The BashCompFilenameExt + // annotation can also be used to obtain the same behavior for flags. + ShellCompDirectiveFilterFileExt + + // ShellCompDirectiveFilterDirs indicates that only directory names should + // be provided in file completion. To request directory names within another + // directory, the returned completions should specify the directory within + // which to search. The BashCompSubdirsInDir annotation can be used to + // obtain the same behavior but only for flags. + ShellCompDirectiveFilterDirs + + // ShellCompDirectiveKeepOrder indicates that the shell should preserve the order + // in which the completions are provided + ShellCompDirectiveKeepOrder + + // =========================================================================== + + // All directives using iota should be above this one. + // For internal use. + shellCompDirectiveMaxValue + + // ShellCompDirectiveDefault indicates to let the shell perform its default + // behavior after completions have been provided. + // This one must be last to avoid messing up the iota count. + ShellCompDirectiveDefault ShellCompDirective = 0 +) + +const ( + // Constants for the completion command + compCmdName = "completion" + compCmdNoDescFlagName = "no-descriptions" + compCmdNoDescFlagDesc = "disable completion descriptions" + compCmdNoDescFlagDefault = false +) + +// CompletionOptions are the options to control shell completion +type CompletionOptions struct { + // DisableDefaultCmd prevents Cobra from creating a default 'completion' command + DisableDefaultCmd bool + // DisableNoDescFlag prevents Cobra from creating the '--no-descriptions' flag + // for shells that support completion descriptions + DisableNoDescFlag bool + // DisableDescriptions turns off all completion descriptions for shells + // that support them + DisableDescriptions bool + // HiddenDefaultCmd makes the default 'completion' command hidden + HiddenDefaultCmd bool +} + +// NoFileCompletions can be used to disable file completion for commands that should +// not trigger file completions. +func NoFileCompletions(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + return nil, ShellCompDirectiveNoFileComp +} + +// FixedCompletions can be used to create a completion function which always +// returns the same results. +func FixedCompletions(choices []string, directive ShellCompDirective) func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + return func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) { + return choices, directive + } +} + +// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag. +func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error { + flag := c.Flag(flagName) + if flag == nil { + return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName) + } + flagCompletionMutex.Lock() + defer flagCompletionMutex.Unlock() + + if _, exists := flagCompletionFunctions[flag]; exists { + return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName) + } + flagCompletionFunctions[flag] = f + return nil +} + +// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. +func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) { + flag := c.Flag(flagName) + if flag == nil { + return nil, false + } + + flagCompletionMutex.RLock() + defer flagCompletionMutex.RUnlock() + + completionFunc, exists := flagCompletionFunctions[flag] + return completionFunc, exists +} + +// Returns a string listing the different directive enabled in the specified parameter +func (d ShellCompDirective) string() string { + var directives []string + if d&ShellCompDirectiveError != 0 { + directives = append(directives, "ShellCompDirectiveError") + } + if d&ShellCompDirectiveNoSpace != 0 { + directives = append(directives, "ShellCompDirectiveNoSpace") + } + if d&ShellCompDirectiveNoFileComp != 0 { + directives = append(directives, "ShellCompDirectiveNoFileComp") + } + if d&ShellCompDirectiveFilterFileExt != 0 { + directives = append(directives, "ShellCompDirectiveFilterFileExt") + } + if d&ShellCompDirectiveFilterDirs != 0 { + directives = append(directives, "ShellCompDirectiveFilterDirs") + } + if d&ShellCompDirectiveKeepOrder != 0 { + directives = append(directives, "ShellCompDirectiveKeepOrder") + } + if len(directives) == 0 { + directives = append(directives, "ShellCompDirectiveDefault") + } + + if d >= shellCompDirectiveMaxValue { + return fmt.Sprintf("ERROR: unexpected ShellCompDirective value: %d", d) + } + return strings.Join(directives, ", ") +} + +// initCompleteCmd adds a special hidden command that can be used to request custom completions. +func (c *Command) initCompleteCmd(args []string) { + completeCmd := &Command{ + Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd), + Aliases: []string{ShellCompNoDescRequestCmd}, + DisableFlagsInUseLine: true, + Hidden: true, + DisableFlagParsing: true, + Args: MinimumNArgs(1), + Short: "Request shell completion choices for the specified command-line", + Long: fmt.Sprintf("%[2]s is a special command that is used by the shell completion logic\n%[1]s", + "to request completion choices for the specified command-line.", ShellCompRequestCmd), + Run: func(cmd *Command, args []string) { + finalCmd, completions, directive, err := cmd.getCompletions(args) + if err != nil { + CompErrorln(err.Error()) + // Keep going for multiple reasons: + // 1- There could be some valid completions even though there was an error + // 2- Even without completions, we need to print the directive + } + + noDescriptions := cmd.CalledAs() == ShellCompNoDescRequestCmd + if !noDescriptions { + if doDescriptions, err := strconv.ParseBool(getEnvConfig(cmd, configEnvVarSuffixDescriptions)); err == nil { + noDescriptions = !doDescriptions + } + } + noActiveHelp := GetActiveHelpConfig(finalCmd) == activeHelpGlobalDisable + out := finalCmd.OutOrStdout() + for _, comp := range completions { + if noActiveHelp && strings.HasPrefix(comp, activeHelpMarker) { + // Remove all activeHelp entries if it's disabled. + continue + } + if noDescriptions { + // Remove any description that may be included following a tab character. + comp = strings.SplitN(comp, "\t", 2)[0] + } + + // Make sure we only write the first line to the output. + // This is needed if a description contains a linebreak. + // Otherwise the shell scripts will interpret the other lines as new flags + // and could therefore provide a wrong completion. + comp = strings.SplitN(comp, "\n", 2)[0] + + // Finally trim the completion. This is especially important to get rid + // of a trailing tab when there are no description following it. + // For example, a sub-command without a description should not be completed + // with a tab at the end (or else zsh will show a -- following it + // although there is no description). + comp = strings.TrimSpace(comp) + + // Print each possible completion to the output for the completion script to consume. + fmt.Fprintln(out, comp) + } + + // As the last printout, print the completion directive for the completion script to parse. + // The directive integer must be that last character following a single colon (:). + // The completion script expects : + fmt.Fprintf(out, ":%d\n", directive) + + // Print some helpful info to stderr for the user to understand. + // Output from stderr must be ignored by the completion script. + fmt.Fprintf(finalCmd.ErrOrStderr(), "Completion ended with directive: %s\n", directive.string()) + }, + } + c.AddCommand(completeCmd) + subCmd, _, err := c.Find(args) + if err != nil || subCmd.Name() != ShellCompRequestCmd { + // Only create this special command if it is actually being called. + // This reduces possible side-effects of creating such a command; + // for example, having this command would cause problems to a + // cobra program that only consists of the root command, since this + // command would cause the root command to suddenly have a subcommand. + c.RemoveCommand(completeCmd) + } +} + +func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) { + // The last argument, which is not completely typed by the user, + // should not be part of the list of arguments + toComplete := args[len(args)-1] + trimmedArgs := args[:len(args)-1] + + var finalCmd *Command + var finalArgs []string + var err error + // Find the real command for which completion must be performed + // check if we need to traverse here to parse local flags on parent commands + if c.Root().TraverseChildren { + finalCmd, finalArgs, err = c.Root().Traverse(trimmedArgs) + } else { + // For Root commands that don't specify any value for their Args fields, when we call + // Find(), if those Root commands don't have any sub-commands, they will accept arguments. + // However, because we have added the __complete sub-command in the current code path, the + // call to Find() -> legacyArgs() will return an error if there are any arguments. + // To avoid this, we first remove the __complete command to get back to having no sub-commands. + rootCmd := c.Root() + if len(rootCmd.Commands()) == 1 { + rootCmd.RemoveCommand(c) + } + + finalCmd, finalArgs, err = rootCmd.Find(trimmedArgs) + } + if err != nil { + // Unable to find the real command. E.g., someInvalidCmd + return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs) + } + finalCmd.ctx = c.ctx + + // These flags are normally added when `execute()` is called on `finalCmd`, + // however, when doing completion, we don't call `finalCmd.execute()`. + // Let's add the --help and --version flag ourselves but only if the finalCmd + // has not disabled flag parsing; if flag parsing is disabled, it is up to the + // finalCmd itself to handle the completion of *all* flags. + if !finalCmd.DisableFlagParsing { + finalCmd.InitDefaultHelpFlag() + finalCmd.InitDefaultVersionFlag() + } + + // Check if we are doing flag value completion before parsing the flags. + // This is important because if we are completing a flag value, we need to also + // remove the flag name argument from the list of finalArgs or else the parsing + // could fail due to an invalid value (incomplete) for the flag. + flag, finalArgs, toComplete, flagErr := checkIfFlagCompletion(finalCmd, finalArgs, toComplete) + + // Check if interspersed is false or -- was set on a previous arg. + // This works by counting the arguments. Normally -- is not counted as arg but + // if -- was already set or interspersed is false and there is already one arg then + // the extra added -- is counted as arg. + flagCompletion := true + _ = finalCmd.ParseFlags(append(finalArgs, "--")) + newArgCount := finalCmd.Flags().NArg() + + // Parse the flags early so we can check if required flags are set + if err = finalCmd.ParseFlags(finalArgs); err != nil { + return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error()) + } + + realArgCount := finalCmd.Flags().NArg() + if newArgCount > realArgCount { + // don't do flag completion (see above) + flagCompletion = false + } + // Error while attempting to parse flags + if flagErr != nil { + // If error type is flagCompError and we don't want flagCompletion we should ignore the error + if _, ok := flagErr.(*flagCompError); !(ok && !flagCompletion) { + return finalCmd, []string{}, ShellCompDirectiveDefault, flagErr + } + } + + // Look for the --help or --version flags. If they are present, + // there should be no further completions. + if helpOrVersionFlagPresent(finalCmd) { + return finalCmd, []string{}, ShellCompDirectiveNoFileComp, nil + } + + // We only remove the flags from the arguments if DisableFlagParsing is not set. + // This is important for commands which have requested to do their own flag completion. + if !finalCmd.DisableFlagParsing { + finalArgs = finalCmd.Flags().Args() + } + + if flag != nil && flagCompletion { + // Check if we are completing a flag value subject to annotations + if validExts, present := flag.Annotations[BashCompFilenameExt]; present { + if len(validExts) != 0 { + // File completion filtered by extensions + return finalCmd, validExts, ShellCompDirectiveFilterFileExt, nil + } + + // The annotation requests simple file completion. There is no reason to do + // that since it is the default behavior anyway. Let's ignore this annotation + // in case the program also registered a completion function for this flag. + // Even though it is a mistake on the program's side, let's be nice when we can. + } + + if subDir, present := flag.Annotations[BashCompSubdirsInDir]; present { + if len(subDir) == 1 { + // Directory completion from within a directory + return finalCmd, subDir, ShellCompDirectiveFilterDirs, nil + } + // Directory completion + return finalCmd, []string{}, ShellCompDirectiveFilterDirs, nil + } + } + + var completions []string + var directive ShellCompDirective + + // Enforce flag groups before doing flag completions + finalCmd.enforceFlagGroupsForCompletion() + + // Note that we want to perform flagname completion even if finalCmd.DisableFlagParsing==true; + // doing this allows for completion of persistent flag names even for commands that disable flag parsing. + // + // When doing completion of a flag name, as soon as an argument starts with + // a '-' we know it is a flag. We cannot use isFlagArg() here as it requires + // the flag name to be complete + if flag == nil && len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") && flagCompletion { + // First check for required flags + completions = completeRequireFlags(finalCmd, toComplete) + + // If we have not found any required flags, only then can we show regular flags + if len(completions) == 0 { + doCompleteFlags := func(flag *pflag.Flag) { + if !flag.Changed || + strings.Contains(flag.Value.Type(), "Slice") || + strings.Contains(flag.Value.Type(), "Array") { + // If the flag is not already present, or if it can be specified multiple times (Array or Slice) + // we suggest it as a completion + completions = append(completions, getFlagNameCompletions(flag, toComplete)...) + } + } + + // We cannot use finalCmd.Flags() because we may not have called ParsedFlags() for commands + // that have set DisableFlagParsing; it is ParseFlags() that merges the inherited and + // non-inherited flags. + finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { + doCompleteFlags(flag) + }) + // Try to complete non-inherited flags even if DisableFlagParsing==true. + // This allows programs to tell Cobra about flags for completion even + // if the actual parsing of flags is not done by Cobra. + // For instance, Helm uses this to provide flag name completion for + // some of its plugins. + finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { + doCompleteFlags(flag) + }) + } + + directive = ShellCompDirectiveNoFileComp + if len(completions) == 1 && strings.HasSuffix(completions[0], "=") { + // If there is a single completion, the shell usually adds a space + // after the completion. We don't want that if the flag ends with an = + directive = ShellCompDirectiveNoSpace + } + + if !finalCmd.DisableFlagParsing { + // If DisableFlagParsing==false, we have completed the flags as known by Cobra; + // we can return what we found. + // If DisableFlagParsing==true, Cobra may not be aware of all flags, so we + // let the logic continue to see if ValidArgsFunction needs to be called. + return finalCmd, completions, directive, nil + } + } else { + directive = ShellCompDirectiveDefault + if flag == nil { + foundLocalNonPersistentFlag := false + // If TraverseChildren is true on the root command we don't check for + // local flags because we can use a local flag on a parent command + if !finalCmd.Root().TraverseChildren { + // Check if there are any local, non-persistent flags on the command-line + localNonPersistentFlags := finalCmd.LocalNonPersistentFlags() + finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { + if localNonPersistentFlags.Lookup(flag.Name) != nil && flag.Changed { + foundLocalNonPersistentFlag = true + } + }) + } + + // Complete subcommand names, including the help command + if len(finalArgs) == 0 && !foundLocalNonPersistentFlag { + // We only complete sub-commands if: + // - there are no arguments on the command-line and + // - there are no local, non-persistent flags on the command-line or TraverseChildren is true + for _, subCmd := range finalCmd.Commands() { + if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand { + if strings.HasPrefix(subCmd.Name(), toComplete) { + completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short)) + } + directive = ShellCompDirectiveNoFileComp + } + } + } + + // Complete required flags even without the '-' prefix + completions = append(completions, completeRequireFlags(finalCmd, toComplete)...) + + // Always complete ValidArgs, even if we are completing a subcommand name. + // This is for commands that have both subcommands and ValidArgs. + if len(finalCmd.ValidArgs) > 0 { + if len(finalArgs) == 0 { + // ValidArgs are only for the first argument + for _, validArg := range finalCmd.ValidArgs { + if strings.HasPrefix(validArg, toComplete) { + completions = append(completions, validArg) + } + } + directive = ShellCompDirectiveNoFileComp + + // If no completions were found within commands or ValidArgs, + // see if there are any ArgAliases that should be completed. + if len(completions) == 0 { + for _, argAlias := range finalCmd.ArgAliases { + if strings.HasPrefix(argAlias, toComplete) { + completions = append(completions, argAlias) + } + } + } + } + + // If there are ValidArgs specified (even if they don't match), we stop completion. + // Only one of ValidArgs or ValidArgsFunction can be used for a single command. + return finalCmd, completions, directive, nil + } + + // Let the logic continue so as to add any ValidArgsFunction completions, + // even if we already found sub-commands. + // This is for commands that have subcommands but also specify a ValidArgsFunction. + } + } + + // Find the completion function for the flag or command + var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) + if flag != nil && flagCompletion { + flagCompletionMutex.RLock() + completionFn = flagCompletionFunctions[flag] + flagCompletionMutex.RUnlock() + } else { + completionFn = finalCmd.ValidArgsFunction + } + if completionFn != nil { + // Go custom completion defined for this flag or command. + // Call the registered completion function to get the completions. + var comps []string + comps, directive = completionFn(finalCmd, finalArgs, toComplete) + completions = append(completions, comps...) + } + + return finalCmd, completions, directive, nil +} + +func helpOrVersionFlagPresent(cmd *Command) bool { + if versionFlag := cmd.Flags().Lookup("version"); versionFlag != nil && + len(versionFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && versionFlag.Changed { + return true + } + if helpFlag := cmd.Flags().Lookup("help"); helpFlag != nil && + len(helpFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && helpFlag.Changed { + return true + } + return false +} + +func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string { + if nonCompletableFlag(flag) { + return []string{} + } + + var completions []string + flagName := "--" + flag.Name + if strings.HasPrefix(flagName, toComplete) { + // Flag without the = + completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage)) + + // Why suggest both long forms: --flag and --flag= ? + // This forces the user to *always* have to type either an = or a space after the flag name. + // Let's be nice and avoid making users have to do that. + // Since boolean flags and shortname flags don't show the = form, let's go that route and never show it. + // The = form will still work, we just won't suggest it. + // This also makes the list of suggested flags shorter as we avoid all the = forms. + // + // if len(flag.NoOptDefVal) == 0 { + // // Flag requires a value, so it can be suffixed with = + // flagName += "=" + // completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage)) + // } + } + + flagName = "-" + flag.Shorthand + if len(flag.Shorthand) > 0 && strings.HasPrefix(flagName, toComplete) { + completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage)) + } + + return completions +} + +func completeRequireFlags(finalCmd *Command, toComplete string) []string { + var completions []string + + doCompleteRequiredFlags := func(flag *pflag.Flag) { + if _, present := flag.Annotations[BashCompOneRequiredFlag]; present { + if !flag.Changed { + // If the flag is not already present, we suggest it as a completion + completions = append(completions, getFlagNameCompletions(flag, toComplete)...) + } + } + } + + // We cannot use finalCmd.Flags() because we may not have called ParsedFlags() for commands + // that have set DisableFlagParsing; it is ParseFlags() that merges the inherited and + // non-inherited flags. + finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { + doCompleteRequiredFlags(flag) + }) + finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { + doCompleteRequiredFlags(flag) + }) + + return completions +} + +func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*pflag.Flag, []string, string, error) { + if finalCmd.DisableFlagParsing { + // We only do flag completion if we are allowed to parse flags + // This is important for commands which have requested to do their own flag completion. + return nil, args, lastArg, nil + } + + var flagName string + trimmedArgs := args + flagWithEqual := false + orgLastArg := lastArg + + // When doing completion of a flag name, as soon as an argument starts with + // a '-' we know it is a flag. We cannot use isFlagArg() here as that function + // requires the flag name to be complete + if len(lastArg) > 0 && lastArg[0] == '-' { + if index := strings.Index(lastArg, "="); index >= 0 { + // Flag with an = + if strings.HasPrefix(lastArg[:index], "--") { + // Flag has full name + flagName = lastArg[2:index] + } else { + // Flag is shorthand + // We have to get the last shorthand flag name + // e.g. `-asd` => d to provide the correct completion + // https://github.com/spf13/cobra/issues/1257 + flagName = lastArg[index-1 : index] + } + lastArg = lastArg[index+1:] + flagWithEqual = true + } else { + // Normal flag completion + return nil, args, lastArg, nil + } + } + + if len(flagName) == 0 { + if len(args) > 0 { + prevArg := args[len(args)-1] + if isFlagArg(prevArg) { + // Only consider the case where the flag does not contain an =. + // If the flag contains an = it means it has already been fully processed, + // so we don't need to deal with it here. + if index := strings.Index(prevArg, "="); index < 0 { + if strings.HasPrefix(prevArg, "--") { + // Flag has full name + flagName = prevArg[2:] + } else { + // Flag is shorthand + // We have to get the last shorthand flag name + // e.g. `-asd` => d to provide the correct completion + // https://github.com/spf13/cobra/issues/1257 + flagName = prevArg[len(prevArg)-1:] + } + // Remove the uncompleted flag or else there could be an error created + // for an invalid value for that flag + trimmedArgs = args[:len(args)-1] + } + } + } + } + + if len(flagName) == 0 { + // Not doing flag completion + return nil, trimmedArgs, lastArg, nil + } + + flag := findFlag(finalCmd, flagName) + if flag == nil { + // Flag not supported by this command, the interspersed option might be set so return the original args + return nil, args, orgLastArg, &flagCompError{subCommand: finalCmd.Name(), flagName: flagName} + } + + if !flagWithEqual { + if len(flag.NoOptDefVal) != 0 { + // We had assumed dealing with a two-word flag but the flag is a boolean flag. + // In that case, there is no value following it, so we are not really doing flag completion. + // Reset everything to do noun completion. + trimmedArgs = args + flag = nil + } + } + + return flag, trimmedArgs, lastArg, nil +} + +// InitDefaultCompletionCmd adds a default 'completion' command to c. +// This function will do nothing if any of the following is true: +// 1- the feature has been explicitly disabled by the program, +// 2- c has no subcommands (to avoid creating one), +// 3- c already has a 'completion' command provided by the program. +func (c *Command) InitDefaultCompletionCmd() { + if c.CompletionOptions.DisableDefaultCmd || !c.HasSubCommands() { + return + } + + for _, cmd := range c.commands { + if cmd.Name() == compCmdName || cmd.HasAlias(compCmdName) { + // A completion command is already available + return + } + } + + haveNoDescFlag := !c.CompletionOptions.DisableNoDescFlag && !c.CompletionOptions.DisableDescriptions + + completionCmd := &Command{ + Use: compCmdName, + Short: "Generate the autocompletion script for the specified shell", + Long: fmt.Sprintf(`Generate the autocompletion script for %[1]s for the specified shell. +See each sub-command's help for details on how to use the generated script. +`, c.Root().Name()), + Args: NoArgs, + ValidArgsFunction: NoFileCompletions, + Hidden: c.CompletionOptions.HiddenDefaultCmd, + GroupID: c.completionCommandGroupID, + } + c.AddCommand(completionCmd) + + out := c.OutOrStdout() + noDesc := c.CompletionOptions.DisableDescriptions + shortDesc := "Generate the autocompletion script for %s" + bash := &Command{ + Use: "bash", + Short: fmt.Sprintf(shortDesc, "bash"), + Long: fmt.Sprintf(`Generate the autocompletion script for the bash shell. + +This script depends on the 'bash-completion' package. +If it is not installed already, you can install it via your OS's package manager. + +To load completions in your current shell session: + + source <(%[1]s completion bash) + +To load completions for every new session, execute once: + +#### Linux: + + %[1]s completion bash > /etc/bash_completion.d/%[1]s + +#### macOS: + + %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s + +You will need to start a new shell for this setup to take effect. +`, c.Root().Name()), + Args: NoArgs, + DisableFlagsInUseLine: true, + ValidArgsFunction: NoFileCompletions, + RunE: func(cmd *Command, args []string) error { + return cmd.Root().GenBashCompletionV2(out, !noDesc) + }, + } + if haveNoDescFlag { + bash.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc) + } + + zsh := &Command{ + Use: "zsh", + Short: fmt.Sprintf(shortDesc, "zsh"), + Long: fmt.Sprintf(`Generate the autocompletion script for the zsh shell. + +If shell completion is not already enabled in your environment you will need +to enable it. You can execute the following once: + + echo "autoload -U compinit; compinit" >> ~/.zshrc + +To load completions in your current shell session: + + source <(%[1]s completion zsh) + +To load completions for every new session, execute once: + +#### Linux: + + %[1]s completion zsh > "${fpath[1]}/_%[1]s" + +#### macOS: + + %[1]s completion zsh > $(brew --prefix)/share/zsh/site-functions/_%[1]s + +You will need to start a new shell for this setup to take effect. +`, c.Root().Name()), + Args: NoArgs, + ValidArgsFunction: NoFileCompletions, + RunE: func(cmd *Command, args []string) error { + if noDesc { + return cmd.Root().GenZshCompletionNoDesc(out) + } + return cmd.Root().GenZshCompletion(out) + }, + } + if haveNoDescFlag { + zsh.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc) + } + + fish := &Command{ + Use: "fish", + Short: fmt.Sprintf(shortDesc, "fish"), + Long: fmt.Sprintf(`Generate the autocompletion script for the fish shell. + +To load completions in your current shell session: + + %[1]s completion fish | source + +To load completions for every new session, execute once: + + %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish + +You will need to start a new shell for this setup to take effect. +`, c.Root().Name()), + Args: NoArgs, + ValidArgsFunction: NoFileCompletions, + RunE: func(cmd *Command, args []string) error { + return cmd.Root().GenFishCompletion(out, !noDesc) + }, + } + if haveNoDescFlag { + fish.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc) + } + + powershell := &Command{ + Use: "powershell", + Short: fmt.Sprintf(shortDesc, "powershell"), + Long: fmt.Sprintf(`Generate the autocompletion script for powershell. + +To load completions in your current shell session: + + %[1]s completion powershell | Out-String | Invoke-Expression + +To load completions for every new session, add the output of the above command +to your powershell profile. +`, c.Root().Name()), + Args: NoArgs, + ValidArgsFunction: NoFileCompletions, + RunE: func(cmd *Command, args []string) error { + if noDesc { + return cmd.Root().GenPowerShellCompletion(out) + } + return cmd.Root().GenPowerShellCompletionWithDesc(out) + + }, + } + if haveNoDescFlag { + powershell.Flags().BoolVar(&noDesc, compCmdNoDescFlagName, compCmdNoDescFlagDefault, compCmdNoDescFlagDesc) + } + + completionCmd.AddCommand(bash, zsh, fish, powershell) +} + +func findFlag(cmd *Command, name string) *pflag.Flag { + flagSet := cmd.Flags() + if len(name) == 1 { + // First convert the short flag into a long flag + // as the cmd.Flag() search only accepts long flags + if short := flagSet.ShorthandLookup(name); short != nil { + name = short.Name + } else { + set := cmd.InheritedFlags() + if short = set.ShorthandLookup(name); short != nil { + name = short.Name + } else { + return nil + } + } + } + return cmd.Flag(name) +} + +// CompDebug prints the specified string to the same file as where the +// completion script prints its logs. +// Note that completion printouts should never be on stdout as they would +// be wrongly interpreted as actual completion choices by the completion script. +func CompDebug(msg string, printToStdErr bool) { + msg = fmt.Sprintf("[Debug] %s", msg) + + // Such logs are only printed when the user has set the environment + // variable BASH_COMP_DEBUG_FILE to the path of some file to be used. + if path := os.Getenv("BASH_COMP_DEBUG_FILE"); path != "" { + f, err := os.OpenFile(path, + os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err == nil { + defer f.Close() + WriteStringAndCheck(f, msg) + } + } + + if printToStdErr { + // Must print to stderr for this not to be read by the completion script. + fmt.Fprint(os.Stderr, msg) + } +} + +// CompDebugln prints the specified string with a newline at the end +// to the same file as where the completion script prints its logs. +// Such logs are only printed when the user has set the environment +// variable BASH_COMP_DEBUG_FILE to the path of some file to be used. +func CompDebugln(msg string, printToStdErr bool) { + CompDebug(fmt.Sprintf("%s\n", msg), printToStdErr) +} + +// CompError prints the specified completion message to stderr. +func CompError(msg string) { + msg = fmt.Sprintf("[Error] %s", msg) + CompDebug(msg, true) +} + +// CompErrorln prints the specified completion message to stderr with a newline at the end. +func CompErrorln(msg string) { + CompError(fmt.Sprintf("%s\n", msg)) +} + +// These values should not be changed: users will be using them explicitly. +const ( + configEnvVarGlobalPrefix = "COBRA" + configEnvVarSuffixDescriptions = "COMPLETION_DESCRIPTIONS" +) + +var configEnvVarPrefixSubstRegexp = regexp.MustCompile(`[^A-Z0-9_]`) + +// configEnvVar returns the name of the program-specific configuration environment +// variable. It has the format _ where is the name of the +// root command in upper case, with all non-ASCII-alphanumeric characters replaced by `_`. +func configEnvVar(name, suffix string) string { + // This format should not be changed: users will be using it explicitly. + v := strings.ToUpper(fmt.Sprintf("%s_%s", name, suffix)) + v = configEnvVarPrefixSubstRegexp.ReplaceAllString(v, "_") + return v +} + +// getEnvConfig returns the value of the configuration environment variable +// _ where is the name of the root command in upper +// case, with all non-ASCII-alphanumeric characters replaced by `_`. +// If the value is empty or not set, the value of the environment variable +// COBRA_ is returned instead. +func getEnvConfig(cmd *Command, suffix string) string { + v := os.Getenv(configEnvVar(cmd.Root().Name(), suffix)) + if v == "" { + v = os.Getenv(configEnvVar(configEnvVarGlobalPrefix, suffix)) + } + return v +} diff --git a/vendor/github.com/spf13/cobra/fish_completions.go b/vendor/github.com/spf13/cobra/fish_completions.go new file mode 100644 index 000000000..12d61b691 --- /dev/null +++ b/vendor/github.com/spf13/cobra/fish_completions.go @@ -0,0 +1,292 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" +) + +func genFishComp(buf io.StringWriter, name string, includeDesc bool) { + // Variables should not contain a '-' or ':' character + nameForVar := name + nameForVar = strings.ReplaceAll(nameForVar, "-", "_") + nameForVar = strings.ReplaceAll(nameForVar, ":", "_") + + compCmd := ShellCompRequestCmd + if !includeDesc { + compCmd = ShellCompNoDescRequestCmd + } + WriteStringAndCheck(buf, fmt.Sprintf("# fish completion for %-36s -*- shell-script -*-\n", name)) + WriteStringAndCheck(buf, fmt.Sprintf(` +function __%[1]s_debug + set -l file "$BASH_COMP_DEBUG_FILE" + if test -n "$file" + echo "$argv" >> $file + end +end + +function __%[1]s_perform_completion + __%[1]s_debug "Starting __%[1]s_perform_completion" + + # Extract all args except the last one + set -l args (commandline -opc) + # Extract the last arg and escape it in case it is a space + set -l lastArg (string escape -- (commandline -ct)) + + __%[1]s_debug "args: $args" + __%[1]s_debug "last arg: $lastArg" + + # Disable ActiveHelp which is not supported for fish shell + set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg" + + __%[1]s_debug "Calling $requestComp" + set -l results (eval $requestComp 2> /dev/null) + + # Some programs may output extra empty lines after the directive. + # Let's ignore them or else it will break completion. + # Ref: https://github.com/spf13/cobra/issues/1279 + for line in $results[-1..1] + if test (string trim -- $line) = "" + # Found an empty line, remove it + set results $results[1..-2] + else + # Found non-empty line, we have our proper output + break + end + end + + set -l comps $results[1..-2] + set -l directiveLine $results[-1] + + # For Fish, when completing a flag with an = (e.g., -n=) + # completions must be prefixed with the flag + set -l flagPrefix (string match -r -- '-.*=' "$lastArg") + + __%[1]s_debug "Comps: $comps" + __%[1]s_debug "DirectiveLine: $directiveLine" + __%[1]s_debug "flagPrefix: $flagPrefix" + + for comp in $comps + printf "%%s%%s\n" "$flagPrefix" "$comp" + end + + printf "%%s\n" "$directiveLine" +end + +# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result +function __%[1]s_perform_completion_once + __%[1]s_debug "Starting __%[1]s_perform_completion_once" + + if test -n "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion" + return 0 + end + + set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion) + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "No completions, probably due to a failure" + return 1 + end + + __%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result" + return 0 +end + +# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run +function __%[1]s_clear_perform_completion_once_result + __%[1]s_debug "" + __%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable ==========" + set --erase __%[1]s_perform_completion_once_result + __%[1]s_debug "Successfully erased the variable __%[1]s_perform_completion_once_result" +end + +function __%[1]s_requires_order_preservation + __%[1]s_debug "" + __%[1]s_debug "========= checking if order preservation is required ==========" + + __%[1]s_perform_completion_once + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Error determining if order preservation is required" + return 1 + end + + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + __%[1]s_debug "Directive is: $directive" + + set -l shellCompDirectiveKeepOrder %[9]d + set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2) + __%[1]s_debug "Keeporder is: $keeporder" + + if test $keeporder -ne 0 + __%[1]s_debug "This does require order preservation" + return 0 + end + + __%[1]s_debug "This doesn't require order preservation" + return 1 +end + + +# This function does two things: +# - Obtain the completions and store them in the global __%[1]s_comp_results +# - Return false if file completion should be performed +function __%[1]s_prepare_completions + __%[1]s_debug "" + __%[1]s_debug "========= starting completion logic ==========" + + # Start fresh + set --erase __%[1]s_comp_results + + __%[1]s_perform_completion_once + __%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result" + + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "No completion, probably due to a failure" + # Might as well do file completion, in case it helps + return 1 + end + + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2] + + __%[1]s_debug "Completions are: $__%[1]s_comp_results" + __%[1]s_debug "Directive is: $directive" + + set -l shellCompDirectiveError %[4]d + set -l shellCompDirectiveNoSpace %[5]d + set -l shellCompDirectiveNoFileComp %[6]d + set -l shellCompDirectiveFilterFileExt %[7]d + set -l shellCompDirectiveFilterDirs %[8]d + + if test -z "$directive" + set directive 0 + end + + set -l compErr (math (math --scale 0 $directive / $shellCompDirectiveError) %% 2) + if test $compErr -eq 1 + __%[1]s_debug "Received error directive: aborting." + # Might as well do file completion, in case it helps + return 1 + end + + set -l filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) %% 2) + set -l dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) %% 2) + if test $filefilter -eq 1; or test $dirfilter -eq 1 + __%[1]s_debug "File extension filtering or directory filtering not supported" + # Do full file completion instead + return 1 + end + + set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) %% 2) + set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) %% 2) + + __%[1]s_debug "nospace: $nospace, nofiles: $nofiles" + + # If we want to prevent a space, or if file completion is NOT disabled, + # we need to count the number of valid completions. + # To do so, we will filter on prefix as the completions we have received + # may not already be filtered so as to allow fish to match on different + # criteria than the prefix. + if test $nospace -ne 0; or test $nofiles -eq 0 + set -l prefix (commandline -t | string escape --style=regex) + __%[1]s_debug "prefix: $prefix" + + set -l completions (string match -r -- "^$prefix.*" $__%[1]s_comp_results) + set --global __%[1]s_comp_results $completions + __%[1]s_debug "Filtered completions are: $__%[1]s_comp_results" + + # Important not to quote the variable for count to work + set -l numComps (count $__%[1]s_comp_results) + __%[1]s_debug "numComps: $numComps" + + if test $numComps -eq 1; and test $nospace -ne 0 + # We must first split on \t to get rid of the descriptions to be + # able to check what the actual completion will be. + # We don't need descriptions anyway since there is only a single + # real completion which the shell will expand immediately. + set -l split (string split --max 1 \t $__%[1]s_comp_results[1]) + + # Fish won't add a space if the completion ends with any + # of the following characters: @=/:., + set -l lastChar (string sub -s -1 -- $split) + if not string match -r -q "[@=/:.,]" -- "$lastChar" + # In other cases, to support the "nospace" directive we trick the shell + # by outputting an extra, longer completion. + __%[1]s_debug "Adding second completion to perform nospace directive" + set --global __%[1]s_comp_results $split[1] $split[1]. + __%[1]s_debug "Completions are now: $__%[1]s_comp_results" + end + end + + if test $numComps -eq 0; and test $nofiles -eq 0 + # To be consistent with bash and zsh, we only trigger file + # completion when there are no other completions + __%[1]s_debug "Requesting file completion" + return 1 + end + end + + return 0 +end + +# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves +# so we can properly delete any completions provided by another script. +# Only do this if the program can be found, or else fish may print some errors; besides, +# the existing completions will only be loaded if the program can be found. +if type -q "%[2]s" + # The space after the program name is essential to trigger completion for the program + # and not completion of the program name itself. + # Also, we use '> /dev/null 2>&1' since '&>' is not supported in older versions of fish. + complete --do-complete "%[2]s " > /dev/null 2>&1 +end + +# Remove any pre-existing completions for the program since we will be handling all of them. +complete -c %[2]s -e + +# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global +complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result' +# The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results +# which provides the program's completion choices. +# If this doesn't require order preservation, we don't use the -k flag +complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' +# otherwise we use the -k flag +complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' +`, nameForVar, name, compCmd, + ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) +} + +// GenFishCompletion generates fish completion file and writes to the passed writer. +func (c *Command) GenFishCompletion(w io.Writer, includeDesc bool) error { + buf := new(bytes.Buffer) + genFishComp(buf, c.Name(), includeDesc) + _, err := buf.WriteTo(w) + return err +} + +// GenFishCompletionFile generates fish completion file. +func (c *Command) GenFishCompletionFile(filename string, includeDesc bool) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenFishCompletion(outFile, includeDesc) +} diff --git a/vendor/github.com/spf13/cobra/flag_groups.go b/vendor/github.com/spf13/cobra/flag_groups.go new file mode 100644 index 000000000..560612fd3 --- /dev/null +++ b/vendor/github.com/spf13/cobra/flag_groups.go @@ -0,0 +1,290 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "fmt" + "sort" + "strings" + + flag "github.com/spf13/pflag" +) + +const ( + requiredAsGroupAnnotation = "cobra_annotation_required_if_others_set" + oneRequiredAnnotation = "cobra_annotation_one_required" + mutuallyExclusiveAnnotation = "cobra_annotation_mutually_exclusive" +) + +// MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors +// if the command is invoked with a subset (but not all) of the given flags. +func (c *Command) MarkFlagsRequiredTogether(flagNames ...string) { + c.mergePersistentFlags() + for _, v := range flagNames { + f := c.Flags().Lookup(v) + if f == nil { + panic(fmt.Sprintf("Failed to find flag %q and mark it as being required in a flag group", v)) + } + if err := c.Flags().SetAnnotation(v, requiredAsGroupAnnotation, append(f.Annotations[requiredAsGroupAnnotation], strings.Join(flagNames, " "))); err != nil { + // Only errs if the flag isn't found. + panic(err) + } + } +} + +// MarkFlagsOneRequired marks the given flags with annotations so that Cobra errors +// if the command is invoked without at least one flag from the given set of flags. +func (c *Command) MarkFlagsOneRequired(flagNames ...string) { + c.mergePersistentFlags() + for _, v := range flagNames { + f := c.Flags().Lookup(v) + if f == nil { + panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a one-required flag group", v)) + } + if err := c.Flags().SetAnnotation(v, oneRequiredAnnotation, append(f.Annotations[oneRequiredAnnotation], strings.Join(flagNames, " "))); err != nil { + // Only errs if the flag isn't found. + panic(err) + } + } +} + +// MarkFlagsMutuallyExclusive marks the given flags with annotations so that Cobra errors +// if the command is invoked with more than one flag from the given set of flags. +func (c *Command) MarkFlagsMutuallyExclusive(flagNames ...string) { + c.mergePersistentFlags() + for _, v := range flagNames { + f := c.Flags().Lookup(v) + if f == nil { + panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a mutually exclusive flag group", v)) + } + // Each time this is called is a single new entry; this allows it to be a member of multiple groups if needed. + if err := c.Flags().SetAnnotation(v, mutuallyExclusiveAnnotation, append(f.Annotations[mutuallyExclusiveAnnotation], strings.Join(flagNames, " "))); err != nil { + panic(err) + } + } +} + +// ValidateFlagGroups validates the mutuallyExclusive/oneRequired/requiredAsGroup logic and returns the +// first error encountered. +func (c *Command) ValidateFlagGroups() error { + if c.DisableFlagParsing { + return nil + } + + flags := c.Flags() + + // groupStatus format is the list of flags as a unique ID, + // then a map of each flag name and whether it is set or not. + groupStatus := map[string]map[string]bool{} + oneRequiredGroupStatus := map[string]map[string]bool{} + mutuallyExclusiveGroupStatus := map[string]map[string]bool{} + flags.VisitAll(func(pflag *flag.Flag) { + processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus) + processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus) + processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus) + }) + + if err := validateRequiredFlagGroups(groupStatus); err != nil { + return err + } + if err := validateOneRequiredFlagGroups(oneRequiredGroupStatus); err != nil { + return err + } + if err := validateExclusiveFlagGroups(mutuallyExclusiveGroupStatus); err != nil { + return err + } + return nil +} + +func hasAllFlags(fs *flag.FlagSet, flagnames ...string) bool { + for _, fname := range flagnames { + f := fs.Lookup(fname) + if f == nil { + return false + } + } + return true +} + +func processFlagForGroupAnnotation(flags *flag.FlagSet, pflag *flag.Flag, annotation string, groupStatus map[string]map[string]bool) { + groupInfo, found := pflag.Annotations[annotation] + if found { + for _, group := range groupInfo { + if groupStatus[group] == nil { + flagnames := strings.Split(group, " ") + + // Only consider this flag group at all if all the flags are defined. + if !hasAllFlags(flags, flagnames...) { + continue + } + + groupStatus[group] = make(map[string]bool, len(flagnames)) + for _, name := range flagnames { + groupStatus[group][name] = false + } + } + + groupStatus[group][pflag.Name] = pflag.Changed + } + } +} + +func validateRequiredFlagGroups(data map[string]map[string]bool) error { + keys := sortedKeys(data) + for _, flagList := range keys { + flagnameAndStatus := data[flagList] + + unset := []string{} + for flagname, isSet := range flagnameAndStatus { + if !isSet { + unset = append(unset, flagname) + } + } + if len(unset) == len(flagnameAndStatus) || len(unset) == 0 { + continue + } + + // Sort values, so they can be tested/scripted against consistently. + sort.Strings(unset) + return fmt.Errorf("if any flags in the group [%v] are set they must all be set; missing %v", flagList, unset) + } + + return nil +} + +func validateOneRequiredFlagGroups(data map[string]map[string]bool) error { + keys := sortedKeys(data) + for _, flagList := range keys { + flagnameAndStatus := data[flagList] + var set []string + for flagname, isSet := range flagnameAndStatus { + if isSet { + set = append(set, flagname) + } + } + if len(set) >= 1 { + continue + } + + // Sort values, so they can be tested/scripted against consistently. + sort.Strings(set) + return fmt.Errorf("at least one of the flags in the group [%v] is required", flagList) + } + return nil +} + +func validateExclusiveFlagGroups(data map[string]map[string]bool) error { + keys := sortedKeys(data) + for _, flagList := range keys { + flagnameAndStatus := data[flagList] + var set []string + for flagname, isSet := range flagnameAndStatus { + if isSet { + set = append(set, flagname) + } + } + if len(set) == 0 || len(set) == 1 { + continue + } + + // Sort values, so they can be tested/scripted against consistently. + sort.Strings(set) + return fmt.Errorf("if any flags in the group [%v] are set none of the others can be; %v were all set", flagList, set) + } + return nil +} + +func sortedKeys(m map[string]map[string]bool) []string { + keys := make([]string, len(m)) + i := 0 + for k := range m { + keys[i] = k + i++ + } + sort.Strings(keys) + return keys +} + +// enforceFlagGroupsForCompletion will do the following: +// - when a flag in a group is present, other flags in the group will be marked required +// - when none of the flags in a one-required group are present, all flags in the group will be marked required +// - when a flag in a mutually exclusive group is present, other flags in the group will be marked as hidden +// This allows the standard completion logic to behave appropriately for flag groups +func (c *Command) enforceFlagGroupsForCompletion() { + if c.DisableFlagParsing { + return + } + + flags := c.Flags() + groupStatus := map[string]map[string]bool{} + oneRequiredGroupStatus := map[string]map[string]bool{} + mutuallyExclusiveGroupStatus := map[string]map[string]bool{} + c.Flags().VisitAll(func(pflag *flag.Flag) { + processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus) + processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus) + processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus) + }) + + // If a flag that is part of a group is present, we make all the other flags + // of that group required so that the shell completion suggests them automatically + for flagList, flagnameAndStatus := range groupStatus { + for _, isSet := range flagnameAndStatus { + if isSet { + // One of the flags of the group is set, mark the other ones as required + for _, fName := range strings.Split(flagList, " ") { + _ = c.MarkFlagRequired(fName) + } + } + } + } + + // If none of the flags of a one-required group are present, we make all the flags + // of that group required so that the shell completion suggests them automatically + for flagList, flagnameAndStatus := range oneRequiredGroupStatus { + isSet := false + + for _, isSet = range flagnameAndStatus { + if isSet { + break + } + } + + // None of the flags of the group are set, mark all flags in the group + // as required + if !isSet { + for _, fName := range strings.Split(flagList, " ") { + _ = c.MarkFlagRequired(fName) + } + } + } + + // If a flag that is mutually exclusive to others is present, we hide the other + // flags of that group so the shell completion does not suggest them + for flagList, flagnameAndStatus := range mutuallyExclusiveGroupStatus { + for flagName, isSet := range flagnameAndStatus { + if isSet { + // One of the flags of the mutually exclusive group is set, mark the other ones as hidden + // Don't mark the flag that is already set as hidden because it may be an + // array or slice flag and therefore must continue being suggested + for _, fName := range strings.Split(flagList, " ") { + if fName != flagName { + flag := c.Flags().Lookup(fName) + flag.Hidden = true + } + } + } + } + } +} diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go new file mode 100644 index 000000000..a830b7bca --- /dev/null +++ b/vendor/github.com/spf13/cobra/powershell_completions.go @@ -0,0 +1,325 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The generated scripts require PowerShell v5.0+ (which comes Windows 10, but +// can be downloaded separately for windows 7 or 8.1). + +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" +) + +func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) { + // Variables should not contain a '-' or ':' character + nameForVar := name + nameForVar = strings.ReplaceAll(nameForVar, "-", "_") + nameForVar = strings.ReplaceAll(nameForVar, ":", "_") + + compCmd := ShellCompRequestCmd + if !includeDesc { + compCmd = ShellCompNoDescRequestCmd + } + WriteStringAndCheck(buf, fmt.Sprintf(`# powershell completion for %-36[1]s -*- shell-script -*- + +function __%[1]s_debug { + if ($env:BASH_COMP_DEBUG_FILE) { + "$args" | Out-File -Append -FilePath "$env:BASH_COMP_DEBUG_FILE" + } +} + +filter __%[1]s_escapeStringWithSpecialChars { +`+" $_ -replace '\\s|#|@|\\$|;|,|''|\\{|\\}|\\(|\\)|\"|`|\\||<|>|&','`$&'"+` +} + +[scriptblock]${__%[2]sCompleterBlock} = { + param( + $WordToComplete, + $CommandAst, + $CursorPosition + ) + + # Get the current command line and convert into a string + $Command = $CommandAst.CommandElements + $Command = "$Command" + + __%[1]s_debug "" + __%[1]s_debug "========= starting completion logic ==========" + __%[1]s_debug "WordToComplete: $WordToComplete Command: $Command CursorPosition: $CursorPosition" + + # The user could have moved the cursor backwards on the command-line. + # We need to trigger completion from the $CursorPosition location, so we need + # to truncate the command-line ($Command) up to the $CursorPosition location. + # Make sure the $Command is longer then the $CursorPosition before we truncate. + # This happens because the $Command does not include the last space. + if ($Command.Length -gt $CursorPosition) { + $Command=$Command.Substring(0,$CursorPosition) + } + __%[1]s_debug "Truncated command: $Command" + + $ShellCompDirectiveError=%[4]d + $ShellCompDirectiveNoSpace=%[5]d + $ShellCompDirectiveNoFileComp=%[6]d + $ShellCompDirectiveFilterFileExt=%[7]d + $ShellCompDirectiveFilterDirs=%[8]d + $ShellCompDirectiveKeepOrder=%[9]d + + # Prepare the command to request completions for the program. + # Split the command at the first space to separate the program and arguments. + $Program,$Arguments = $Command.Split(" ",2) + + $RequestComp="$Program %[3]s $Arguments" + __%[1]s_debug "RequestComp: $RequestComp" + + # we cannot use $WordToComplete because it + # has the wrong values if the cursor was moved + # so use the last argument + if ($WordToComplete -ne "" ) { + $WordToComplete = $Arguments.Split(" ")[-1] + } + __%[1]s_debug "New WordToComplete: $WordToComplete" + + + # Check for flag with equal sign + $IsEqualFlag = ($WordToComplete -Like "--*=*" ) + if ( $IsEqualFlag ) { + __%[1]s_debug "Completing equal sign flag" + # Remove the flag part + $Flag,$WordToComplete = $WordToComplete.Split("=",2) + } + + if ( $WordToComplete -eq "" -And ( -Not $IsEqualFlag )) { + # If the last parameter is complete (there is a space following it) + # We add an extra empty parameter so we can indicate this to the go method. + __%[1]s_debug "Adding extra empty parameter" + # PowerShell 7.2+ changed the way how the arguments are passed to executables, + # so for pre-7.2 or when Legacy argument passing is enabled we need to use +`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+` + if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or + ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or + (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and + $PSNativeCommandArgumentPassing -eq 'Legacy')) { +`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + } else { + $RequestComp="$RequestComp" + ' ""' + } + } + + __%[1]s_debug "Calling $RequestComp" + # First disable ActiveHelp which is not supported for Powershell + ${env:%[10]s}=0 + + #call the command store the output in $out and redirect stderr and stdout to null + # $Out is an array contains each line per element + Invoke-Expression -OutVariable out "$RequestComp" 2>&1 | Out-Null + + # get directive from last line + [int]$Directive = $Out[-1].TrimStart(':') + if ($Directive -eq "") { + # There is no directive specified + $Directive = 0 + } + __%[1]s_debug "The completion directive is: $Directive" + + # remove directive (last element) from out + $Out = $Out | Where-Object { $_ -ne $Out[-1] } + __%[1]s_debug "The completions are: $Out" + + if (($Directive -band $ShellCompDirectiveError) -ne 0 ) { + # Error code. No completion. + __%[1]s_debug "Received error from custom completion go code" + return + } + + $Longest = 0 + [Array]$Values = $Out | ForEach-Object { + #Split the output in name and description +`+" $Name, $Description = $_.Split(\"`t\",2)"+` + __%[1]s_debug "Name: $Name Description: $Description" + + # Look for the longest completion so that we can format things nicely + if ($Longest -lt $Name.Length) { + $Longest = $Name.Length + } + + # Set the description to a one space string if there is none set. + # This is needed because the CompletionResult does not accept an empty string as argument + if (-Not $Description) { + $Description = " " + } + @{Name="$Name";Description="$Description"} + } + + + $Space = " " + if (($Directive -band $ShellCompDirectiveNoSpace) -ne 0 ) { + # remove the space here + __%[1]s_debug "ShellCompDirectiveNoSpace is called" + $Space = "" + } + + if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or + (($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) { + __%[1]s_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported" + + # return here to prevent the completion of the extensions + return + } + + $Values = $Values | Where-Object { + # filter the result + $_.Name -like "$WordToComplete*" + + # Join the flag back if we have an equal sign flag + if ( $IsEqualFlag ) { + __%[1]s_debug "Join the equal sign flag back to the completion value" + $_.Name = $Flag + "=" + $_.Name + } + } + + # we sort the values in ascending order by name if keep order isn't passed + if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) { + $Values = $Values | Sort-Object -Property Name + } + + if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { + __%[1]s_debug "ShellCompDirectiveNoFileComp is called" + + if ($Values.Length -eq 0) { + # Just print an empty string here so the + # shell does not start to complete paths. + # We cannot use CompletionResult here because + # it does not accept an empty string as argument. + "" + return + } + } + + # Get the current mode + $Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function + __%[1]s_debug "Mode: $Mode" + + $Values | ForEach-Object { + + # store temporary because switch will overwrite $_ + $comp = $_ + + # PowerShell supports three different completion modes + # - TabCompleteNext (default windows style - on each key press the next option is displayed) + # - Complete (works like bash) + # - MenuComplete (works like zsh) + # You set the mode with Set-PSReadLineKeyHandler -Key Tab -Function + + # CompletionResult Arguments: + # 1) CompletionText text to be used as the auto completion result + # 2) ListItemText text to be displayed in the suggestion list + # 3) ResultType type of completion result + # 4) ToolTip text for the tooltip with details about the object + + switch ($Mode) { + + # bash like + "Complete" { + + if ($Values.Length -eq 1) { + __%[1]s_debug "Only one completion left" + + # insert space after value + [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + + } else { + # Add the proper number of spaces to align the descriptions + while($comp.Name.Length -lt $Longest) { + $comp.Name = $comp.Name + " " + } + + # Check for empty description and only add parentheses if needed + if ($($comp.Description) -eq " " ) { + $Description = "" + } else { + $Description = " ($($comp.Description))" + } + + [System.Management.Automation.CompletionResult]::new("$($comp.Name)$Description", "$($comp.Name)$Description", 'ParameterValue', "$($comp.Description)") + } + } + + # zsh like + "MenuComplete" { + # insert space after value + # MenuComplete will automatically show the ToolTip of + # the highlighted value at the bottom of the suggestions. + [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + } + + # TabCompleteNext and in case we get something unknown + Default { + # Like MenuComplete but we don't want to add a space here because + # the user need to press space anyway to get the completion. + # Description will not be shown because that's not possible with TabCompleteNext + [System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)") + } + } + + } +} + +Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock ${__%[2]sCompleterBlock} +`, name, nameForVar, compCmd, + ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) +} + +func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error { + buf := new(bytes.Buffer) + genPowerShellComp(buf, c.Name(), includeDesc) + _, err := buf.WriteTo(w) + return err +} + +func (c *Command) genPowerShellCompletionFile(filename string, includeDesc bool) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.genPowerShellCompletion(outFile, includeDesc) +} + +// GenPowerShellCompletionFile generates powershell completion file without descriptions. +func (c *Command) GenPowerShellCompletionFile(filename string) error { + return c.genPowerShellCompletionFile(filename, false) +} + +// GenPowerShellCompletion generates powershell completion file without descriptions +// and writes it to the passed writer. +func (c *Command) GenPowerShellCompletion(w io.Writer) error { + return c.genPowerShellCompletion(w, false) +} + +// GenPowerShellCompletionFileWithDesc generates powershell completion file with descriptions. +func (c *Command) GenPowerShellCompletionFileWithDesc(filename string) error { + return c.genPowerShellCompletionFile(filename, true) +} + +// GenPowerShellCompletionWithDesc generates powershell completion file with descriptions +// and writes it to the passed writer. +func (c *Command) GenPowerShellCompletionWithDesc(w io.Writer) error { + return c.genPowerShellCompletion(w, true) +} diff --git a/vendor/github.com/spf13/cobra/shell_completions.go b/vendor/github.com/spf13/cobra/shell_completions.go new file mode 100644 index 000000000..b035742d3 --- /dev/null +++ b/vendor/github.com/spf13/cobra/shell_completions.go @@ -0,0 +1,98 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "github.com/spf13/pflag" +) + +// MarkFlagRequired instructs the various shell completion implementations to +// prioritize the named flag when performing completion, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkFlagRequired(name string) error { + return MarkFlagRequired(c.Flags(), name) +} + +// MarkPersistentFlagRequired instructs the various shell completion implementations to +// prioritize the named persistent flag when performing completion, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkPersistentFlagRequired(name string) error { + return MarkFlagRequired(c.PersistentFlags(), name) +} + +// MarkFlagRequired instructs the various shell completion implementations to +// prioritize the named flag when performing completion, +// and causes your command to report an error if invoked without the flag. +func MarkFlagRequired(flags *pflag.FlagSet, name string) error { + return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) +} + +// MarkFlagFilename instructs the various shell completion implementations to +// limit completions for the named flag to the specified file extensions. +func (c *Command) MarkFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.Flags(), name, extensions...) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. +// The bash completion script will call the bash function f for the flag. +// +// This will only work for bash completion. +// It is recommended to instead use c.RegisterFlagCompletionFunc(...) which allows +// to register a Go function which will work across all shells. +func (c *Command) MarkFlagCustom(name string, f string) error { + return MarkFlagCustom(c.Flags(), name, f) +} + +// MarkPersistentFlagFilename instructs the various shell completion +// implementations to limit completions for the named persistent flag to the +// specified file extensions. +func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.PersistentFlags(), name, extensions...) +} + +// MarkFlagFilename instructs the various shell completion implementations to +// limit completions for the named flag to the specified file extensions. +func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { + return flags.SetAnnotation(name, BashCompFilenameExt, extensions) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. +// The bash completion script will call the bash function f for the flag. +// +// This will only work for bash completion. +// It is recommended to instead use c.RegisterFlagCompletionFunc(...) which allows +// to register a Go function which will work across all shells. +func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { + return flags.SetAnnotation(name, BashCompCustom, []string{f}) +} + +// MarkFlagDirname instructs the various shell completion implementations to +// limit completions for the named flag to directory names. +func (c *Command) MarkFlagDirname(name string) error { + return MarkFlagDirname(c.Flags(), name) +} + +// MarkPersistentFlagDirname instructs the various shell completion +// implementations to limit completions for the named persistent flag to +// directory names. +func (c *Command) MarkPersistentFlagDirname(name string) error { + return MarkFlagDirname(c.PersistentFlags(), name) +} + +// MarkFlagDirname instructs the various shell completion implementations to +// limit completions for the named flag to directory names. +func MarkFlagDirname(flags *pflag.FlagSet, name string) error { + return flags.SetAnnotation(name, BashCompSubdirsInDir, []string{}) +} diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go new file mode 100644 index 000000000..1856e4c7f --- /dev/null +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -0,0 +1,308 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// GenZshCompletionFile generates zsh completion file including descriptions. +func (c *Command) GenZshCompletionFile(filename string) error { + return c.genZshCompletionFile(filename, true) +} + +// GenZshCompletion generates zsh completion file including descriptions +// and writes it to the passed writer. +func (c *Command) GenZshCompletion(w io.Writer) error { + return c.genZshCompletion(w, true) +} + +// GenZshCompletionFileNoDesc generates zsh completion file without descriptions. +func (c *Command) GenZshCompletionFileNoDesc(filename string) error { + return c.genZshCompletionFile(filename, false) +} + +// GenZshCompletionNoDesc generates zsh completion file without descriptions +// and writes it to the passed writer. +func (c *Command) GenZshCompletionNoDesc(w io.Writer) error { + return c.genZshCompletion(w, false) +} + +// MarkZshCompPositionalArgumentFile only worked for zsh and its behavior was +// not consistent with Bash completion. It has therefore been disabled. +// Instead, when no other completion is specified, file completion is done by +// default for every argument. One can disable file completion on a per-argument +// basis by using ValidArgsFunction and ShellCompDirectiveNoFileComp. +// To achieve file extension filtering, one can use ValidArgsFunction and +// ShellCompDirectiveFilterFileExt. +// +// Deprecated +func (c *Command) MarkZshCompPositionalArgumentFile(argPosition int, patterns ...string) error { + return nil +} + +// MarkZshCompPositionalArgumentWords only worked for zsh. It has therefore +// been disabled. +// To achieve the same behavior across all shells, one can use +// ValidArgs (for the first argument only) or ValidArgsFunction for +// any argument (can include the first one also). +// +// Deprecated +func (c *Command) MarkZshCompPositionalArgumentWords(argPosition int, words ...string) error { + return nil +} + +func (c *Command) genZshCompletionFile(filename string, includeDesc bool) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.genZshCompletion(outFile, includeDesc) +} + +func (c *Command) genZshCompletion(w io.Writer, includeDesc bool) error { + buf := new(bytes.Buffer) + genZshComp(buf, c.Name(), includeDesc) + _, err := buf.WriteTo(w) + return err +} + +func genZshComp(buf io.StringWriter, name string, includeDesc bool) { + compCmd := ShellCompRequestCmd + if !includeDesc { + compCmd = ShellCompNoDescRequestCmd + } + WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s +compdef _%[1]s %[1]s + +# zsh completion for %-36[1]s -*- shell-script -*- + +__%[1]s_debug() +{ + local file="$BASH_COMP_DEBUG_FILE" + if [[ -n ${file} ]]; then + echo "$*" >> "${file}" + fi +} + +_%[1]s() +{ + local shellCompDirectiveError=%[3]d + local shellCompDirectiveNoSpace=%[4]d + local shellCompDirectiveNoFileComp=%[5]d + local shellCompDirectiveFilterFileExt=%[6]d + local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d + + local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder + local -a completions + + __%[1]s_debug "\n========= starting completion logic ==========" + __%[1]s_debug "CURRENT: ${CURRENT}, words[*]: ${words[*]}" + + # The user could have moved the cursor backwards on the command-line. + # We need to trigger completion from the $CURRENT location, so we need + # to truncate the command-line ($words) up to the $CURRENT location. + # (We cannot use $CURSOR as its value does not work when a command is an alias.) + words=("${=words[1,CURRENT]}") + __%[1]s_debug "Truncated words[*]: ${words[*]}," + + lastParam=${words[-1]} + lastChar=${lastParam[-1]} + __%[1]s_debug "lastParam: ${lastParam}, lastChar: ${lastChar}" + + # For zsh, when completing a flag with an = (e.g., %[1]s -n=) + # completions must be prefixed with the flag + setopt local_options BASH_REMATCH + if [[ "${lastParam}" =~ '-.*=' ]]; then + # We are dealing with a flag with an = + flagPrefix="-P ${BASH_REMATCH}" + fi + + # Prepare the command to obtain completions + requestComp="${words[1]} %[2]s ${words[2,-1]}" + if [ "${lastChar}" = "" ]; then + # If the last parameter is complete (there is a space following it) + # We add an extra empty parameter so we can indicate this to the go completion code. + __%[1]s_debug "Adding extra empty parameter" + requestComp="${requestComp} \"\"" + fi + + __%[1]s_debug "About to call: eval ${requestComp}" + + # Use eval to handle any environment variables and such + out=$(eval ${requestComp} 2>/dev/null) + __%[1]s_debug "completion output: ${out}" + + # Extract the directive integer following a : from the last line + local lastLine + while IFS='\n' read -r line; do + lastLine=${line} + done < <(printf "%%s\n" "${out[@]}") + __%[1]s_debug "last line: ${lastLine}" + + if [ "${lastLine[1]}" = : ]; then + directive=${lastLine[2,-1]} + # Remove the directive including the : and the newline + local suffix + (( suffix=${#lastLine}+2)) + out=${out[1,-$suffix]} + else + # There is no directive specified. Leave $out as is. + __%[1]s_debug "No directive found. Setting do default" + directive=0 + fi + + __%[1]s_debug "directive: ${directive}" + __%[1]s_debug "completions: ${out}" + __%[1]s_debug "flagPrefix: ${flagPrefix}" + + if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then + __%[1]s_debug "Completion received error. Ignoring completions." + return + fi + + local activeHelpMarker="%[9]s" + local endIndex=${#activeHelpMarker} + local startIndex=$((${#activeHelpMarker}+1)) + local hasActiveHelp=0 + while IFS='\n' read -r comp; do + # Check if this is an activeHelp statement (i.e., prefixed with $activeHelpMarker) + if [ "${comp[1,$endIndex]}" = "$activeHelpMarker" ];then + __%[1]s_debug "ActiveHelp found: $comp" + comp="${comp[$startIndex,-1]}" + if [ -n "$comp" ]; then + compadd -x "${comp}" + __%[1]s_debug "ActiveHelp will need delimiter" + hasActiveHelp=1 + fi + + continue + fi + + if [ -n "$comp" ]; then + # If requested, completions are returned with a description. + # The description is preceded by a TAB character. + # For zsh's _describe, we need to use a : instead of a TAB. + # We first need to escape any : as part of the completion itself. + comp=${comp//:/\\:} + + local tab="$(printf '\t')" + comp=${comp//$tab/:} + + __%[1]s_debug "Adding completion: ${comp}" + completions+=${comp} + lastComp=$comp + fi + done < <(printf "%%s\n" "${out[@]}") + + # Add a delimiter after the activeHelp statements, but only if: + # - there are completions following the activeHelp statements, or + # - file completion will be performed (so there will be choices after the activeHelp) + if [ $hasActiveHelp -eq 1 ]; then + if [ ${#completions} -ne 0 ] || [ $((directive & shellCompDirectiveNoFileComp)) -eq 0 ]; then + __%[1]s_debug "Adding activeHelp delimiter" + compadd -x "--" + hasActiveHelp=0 + fi + fi + + if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then + __%[1]s_debug "Activating nospace." + noSpace="-S ''" + fi + + if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then + __%[1]s_debug "Activating keep order." + keepOrder="-V" + fi + + if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then + # File extension filtering + local filteringCmd + filteringCmd='_files' + for filter in ${completions[@]}; do + if [ ${filter[1]} != '*' ]; then + # zsh requires a glob pattern to do file filtering + filter="\*.$filter" + fi + filteringCmd+=" -g $filter" + done + filteringCmd+=" ${flagPrefix}" + + __%[1]s_debug "File filtering command: $filteringCmd" + _arguments '*:filename:'"$filteringCmd" + elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then + # File completion for directories only + local subdir + subdir="${completions[1]}" + if [ -n "$subdir" ]; then + __%[1]s_debug "Listing directories in $subdir" + pushd "${subdir}" >/dev/null 2>&1 + else + __%[1]s_debug "Listing directories in ." + fi + + local result + _arguments '*:dirname:_files -/'" ${flagPrefix}" + result=$? + if [ -n "$subdir" ]; then + popd >/dev/null 2>&1 + fi + return $result + else + __%[1]s_debug "Calling _describe" + if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then + __%[1]s_debug "_describe found some completions" + + # Return the success of having called _describe + return 0 + else + __%[1]s_debug "_describe did not find completions." + __%[1]s_debug "Checking if we should do file completion." + if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then + __%[1]s_debug "deactivating file completion" + + # We must return an error code here to let zsh know that there were no + # completions found by _describe; this is what will trigger other + # matching algorithms to attempt to find completions. + # For example zsh can match letters in the middle of words. + return 1 + else + # Perform file completion + __%[1]s_debug "Activating file completion" + + # We must return the result of this command, so it must be the + # last command, or else we must store its result to return it. + _arguments '*:filename:_files'" ${flagPrefix}" + fi + fi + fi +} + +# don't run the completion function when being source-ed or eval-ed +if [ "$funcstack[1]" = "_%[1]s" ]; then + _%[1]s +fi +`, name, compCmd, + ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, + activeHelpMarker)) +} diff --git a/vendor/github.com/spf13/jwalterweatherman/.gitignore b/vendor/github.com/spf13/jwalterweatherman/.gitignore index 00268614f..a71f88af8 100644 --- a/vendor/github.com/spf13/jwalterweatherman/.gitignore +++ b/vendor/github.com/spf13/jwalterweatherman/.gitignore @@ -20,3 +20,5 @@ _cgo_export.* _testmain.go *.exe +*.bench +go.sum \ No newline at end of file diff --git a/vendor/github.com/spf13/jwalterweatherman/README.md b/vendor/github.com/spf13/jwalterweatherman/README.md index c6f327c1d..932a23fc6 100644 --- a/vendor/github.com/spf13/jwalterweatherman/README.md +++ b/vendor/github.com/spf13/jwalterweatherman/README.md @@ -18,7 +18,7 @@ provides a few advantages over using the standard log library alone. I really wanted a very straightforward library that could seamlessly do the following things. -1. Replace all the println, printf, etc statements thought my code with +1. Replace all the println, printf, etc statements thoughout my code with something more useful 2. Allow the user to easily control what levels are printed to stdout 3. Allow the user to easily control what levels are logged @@ -44,7 +44,7 @@ Available Loggers are: * FATAL These each are loggers based on the log standard library and follow the -standard usage. Eg.. +standard usage. Eg. ```go import ( @@ -79,6 +79,13 @@ standard usage. Eg.. ``` +NOTE: You can also use the library in a non-global setting by creating an instance of a Notebook: + +```go +notepad = jww.NewNotepad(jww.LevelInfo, jww.LevelTrace, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) +notepad.WARN.Println("Some warning"") +``` + _Why 7 levels?_ Maybe you think that 7 levels are too much for any application... and you @@ -118,35 +125,15 @@ verbosity. Note that JWW's own internal output uses log levels as well, so set the log level before making any other calls if you want to see what it's up to. -### Using a temp log file - -JWW conveniently creates a temporary file and sets the log Handle to -a io.Writer created for it. You should call this early in your application -initialization routine as it will only log calls made after it is executed. -When this option is used, the library will fmt.Println where to find the -log file. - -```go - import ( - jww "github.com/spf13/jwalterweatherman" - ) - - jww.UseTempLogFile("YourAppName") - -``` ### Setting a log file -JWW can log to any file you provide a path to (provided it’s writable). -Will only append to this file. +JWW can log to any `io.Writer`: ```go - import ( - jww "github.com/spf13/jwalterweatherman" - ) - jww.SetLogFile("/path/to/logfile") + jww.SetLogOutput(customWriter) ``` @@ -157,5 +144,5 @@ This is an early release. I’ve been using it for a while and this is the third interface I’ve tried. I like this one pretty well, but no guarantees that it won’t change a bit. -I wrote this for use in [hugo](http://hugo.spf13.com). If you are looking +I wrote this for use in [hugo](https://gohugo.io). If you are looking for a static website engine that’s super fast please checkout Hugo. diff --git a/vendor/github.com/spf13/jwalterweatherman/default_notepad.go b/vendor/github.com/spf13/jwalterweatherman/default_notepad.go new file mode 100644 index 000000000..a018c15c4 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/default_notepad.go @@ -0,0 +1,111 @@ +// Copyright © 2016 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "io" + "io/ioutil" + "log" + "os" +) + +var ( + TRACE *log.Logger + DEBUG *log.Logger + INFO *log.Logger + WARN *log.Logger + ERROR *log.Logger + CRITICAL *log.Logger + FATAL *log.Logger + + LOG *log.Logger + FEEDBACK *Feedback + + defaultNotepad *Notepad +) + +func reloadDefaultNotepad() { + TRACE = defaultNotepad.TRACE + DEBUG = defaultNotepad.DEBUG + INFO = defaultNotepad.INFO + WARN = defaultNotepad.WARN + ERROR = defaultNotepad.ERROR + CRITICAL = defaultNotepad.CRITICAL + FATAL = defaultNotepad.FATAL + + LOG = defaultNotepad.LOG + FEEDBACK = defaultNotepad.FEEDBACK +} + +func init() { + defaultNotepad = NewNotepad(LevelError, LevelWarn, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) + reloadDefaultNotepad() +} + +// SetLogThreshold set the log threshold for the default notepad. Trace by default. +func SetLogThreshold(threshold Threshold) { + defaultNotepad.SetLogThreshold(threshold) + reloadDefaultNotepad() +} + +// SetLogOutput set the log output for the default notepad. Discarded by default. +func SetLogOutput(handle io.Writer) { + defaultNotepad.SetLogOutput(handle) + reloadDefaultNotepad() +} + +// SetStdoutThreshold set the standard output threshold for the default notepad. +// Info by default. +func SetStdoutThreshold(threshold Threshold) { + defaultNotepad.SetStdoutThreshold(threshold) + reloadDefaultNotepad() +} + +// SetStdoutOutput set the stdout output for the default notepad. Default is stdout. +func SetStdoutOutput(handle io.Writer) { + defaultNotepad.outHandle = handle + defaultNotepad.init() + reloadDefaultNotepad() +} + +// SetPrefix set the prefix for the default logger. Empty by default. +func SetPrefix(prefix string) { + defaultNotepad.SetPrefix(prefix) + reloadDefaultNotepad() +} + +// SetFlags set the flags for the default logger. "log.Ldate | log.Ltime" by default. +func SetFlags(flags int) { + defaultNotepad.SetFlags(flags) + reloadDefaultNotepad() +} + +// SetLogListeners configures the default logger with one or more log listeners. +func SetLogListeners(l ...LogListener) { + defaultNotepad.logListeners = l + defaultNotepad.init() + reloadDefaultNotepad() +} + +// Level returns the current global log threshold. +func LogThreshold() Threshold { + return defaultNotepad.logThreshold +} + +// Level returns the current global output threshold. +func StdoutThreshold() Threshold { + return defaultNotepad.stdoutThreshold +} + +// GetStdoutThreshold returns the defined Treshold for the log logger. +func GetLogThreshold() Threshold { + return defaultNotepad.GetLogThreshold() +} + +// GetStdoutThreshold returns the Treshold for the stdout logger. +func GetStdoutThreshold() Threshold { + return defaultNotepad.GetStdoutThreshold() +} diff --git a/vendor/github.com/spf13/jwalterweatherman/log_counter.go b/vendor/github.com/spf13/jwalterweatherman/log_counter.go new file mode 100644 index 000000000..41285f3dc --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/log_counter.go @@ -0,0 +1,46 @@ +// Copyright © 2016 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "io" + "sync/atomic" +) + +// Counter is an io.Writer that increments a counter on Write. +type Counter struct { + count uint64 +} + +func (c *Counter) incr() { + atomic.AddUint64(&c.count, 1) +} + +// Reset resets the counter. +func (c *Counter) Reset() { + atomic.StoreUint64(&c.count, 0) +} + +// Count returns the current count. +func (c *Counter) Count() uint64 { + return atomic.LoadUint64(&c.count) +} + +func (c *Counter) Write(p []byte) (n int, err error) { + c.incr() + return len(p), nil +} + +// LogCounter creates a LogListener that counts log statements >= the given threshold. +func LogCounter(counter *Counter, t1 Threshold) LogListener { + return func(t2 Threshold) io.Writer { + if t2 < t1 { + // Not interested in this threshold. + return nil + } + return counter + } +} diff --git a/vendor/github.com/spf13/jwalterweatherman/notepad.go b/vendor/github.com/spf13/jwalterweatherman/notepad.go new file mode 100644 index 000000000..cc7957bf7 --- /dev/null +++ b/vendor/github.com/spf13/jwalterweatherman/notepad.go @@ -0,0 +1,225 @@ +// Copyright © 2016 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package jwalterweatherman + +import ( + "fmt" + "io" + "io/ioutil" + "log" +) + +type Threshold int + +func (t Threshold) String() string { + return prefixes[t] +} + +const ( + LevelTrace Threshold = iota + LevelDebug + LevelInfo + LevelWarn + LevelError + LevelCritical + LevelFatal +) + +var prefixes map[Threshold]string = map[Threshold]string{ + LevelTrace: "TRACE", + LevelDebug: "DEBUG", + LevelInfo: "INFO", + LevelWarn: "WARN", + LevelError: "ERROR", + LevelCritical: "CRITICAL", + LevelFatal: "FATAL", +} + +// Notepad is where you leave a note! +type Notepad struct { + TRACE *log.Logger + DEBUG *log.Logger + INFO *log.Logger + WARN *log.Logger + ERROR *log.Logger + CRITICAL *log.Logger + FATAL *log.Logger + + LOG *log.Logger + FEEDBACK *Feedback + + loggers [7]**log.Logger + logHandle io.Writer + outHandle io.Writer + logThreshold Threshold + stdoutThreshold Threshold + prefix string + flags int + + logListeners []LogListener +} + +// A LogListener can ble supplied to a Notepad to listen on log writes for a given +// threshold. This can be used to capture log events in unit tests and similar. +// Note that this function will be invoked once for each log threshold. If +// the given threshold is not of interest to you, return nil. +// Note that these listeners will receive log events for a given threshold, even +// if the current configuration says not to log it. That way you can count ERRORs even +// if you don't print them to the console. +type LogListener func(t Threshold) io.Writer + +// NewNotepad creates a new Notepad. +func NewNotepad( + outThreshold Threshold, + logThreshold Threshold, + outHandle, logHandle io.Writer, + prefix string, flags int, + logListeners ...LogListener, +) *Notepad { + + n := &Notepad{logListeners: logListeners} + + n.loggers = [7]**log.Logger{&n.TRACE, &n.DEBUG, &n.INFO, &n.WARN, &n.ERROR, &n.CRITICAL, &n.FATAL} + n.outHandle = outHandle + n.logHandle = logHandle + n.stdoutThreshold = outThreshold + n.logThreshold = logThreshold + + if len(prefix) != 0 { + n.prefix = "[" + prefix + "] " + } else { + n.prefix = "" + } + + n.flags = flags + + n.LOG = log.New(n.logHandle, + "LOG: ", + n.flags) + n.FEEDBACK = &Feedback{out: log.New(outHandle, "", 0), log: n.LOG} + + n.init() + return n +} + +// init creates the loggers for each level depending on the notepad thresholds. +func (n *Notepad) init() { + logAndOut := io.MultiWriter(n.outHandle, n.logHandle) + + for t, logger := range n.loggers { + threshold := Threshold(t) + prefix := n.prefix + threshold.String() + " " + + switch { + case threshold >= n.logThreshold && threshold >= n.stdoutThreshold: + *logger = log.New(n.createLogWriters(threshold, logAndOut), prefix, n.flags) + + case threshold >= n.logThreshold: + *logger = log.New(n.createLogWriters(threshold, n.logHandle), prefix, n.flags) + + case threshold >= n.stdoutThreshold: + *logger = log.New(n.createLogWriters(threshold, n.outHandle), prefix, n.flags) + + default: + *logger = log.New(n.createLogWriters(threshold, ioutil.Discard), prefix, n.flags) + } + } +} + +func (n *Notepad) createLogWriters(t Threshold, handle io.Writer) io.Writer { + if len(n.logListeners) == 0 { + return handle + } + writers := []io.Writer{handle} + for _, l := range n.logListeners { + w := l(t) + if w != nil { + writers = append(writers, w) + } + } + + if len(writers) == 1 { + return handle + } + + return io.MultiWriter(writers...) +} + +// SetLogThreshold changes the threshold above which messages are written to the +// log file. +func (n *Notepad) SetLogThreshold(threshold Threshold) { + n.logThreshold = threshold + n.init() +} + +// SetLogOutput changes the file where log messages are written. +func (n *Notepad) SetLogOutput(handle io.Writer) { + n.logHandle = handle + n.init() +} + +// GetStdoutThreshold returns the defined Treshold for the log logger. +func (n *Notepad) GetLogThreshold() Threshold { + return n.logThreshold +} + +// SetStdoutThreshold changes the threshold above which messages are written to the +// standard output. +func (n *Notepad) SetStdoutThreshold(threshold Threshold) { + n.stdoutThreshold = threshold + n.init() +} + +// GetStdoutThreshold returns the Treshold for the stdout logger. +func (n *Notepad) GetStdoutThreshold() Threshold { + return n.stdoutThreshold +} + +// SetPrefix changes the prefix used by the notepad. Prefixes are displayed between +// brackets at the beginning of the line. An empty prefix won't be displayed at all. +func (n *Notepad) SetPrefix(prefix string) { + if len(prefix) != 0 { + n.prefix = "[" + prefix + "] " + } else { + n.prefix = "" + } + n.init() +} + +// SetFlags choose which flags the logger will display (after prefix and message +// level). See the package log for more informations on this. +func (n *Notepad) SetFlags(flags int) { + n.flags = flags + n.init() +} + +// Feedback writes plainly to the outHandle while +// logging with the standard extra information (date, file, etc). +type Feedback struct { + out *log.Logger + log *log.Logger +} + +func (fb *Feedback) Println(v ...interface{}) { + fb.output(fmt.Sprintln(v...)) +} + +func (fb *Feedback) Printf(format string, v ...interface{}) { + fb.output(fmt.Sprintf(format, v...)) +} + +func (fb *Feedback) Print(v ...interface{}) { + fb.output(fmt.Sprint(v...)) +} + +func (fb *Feedback) output(s string) { + if fb.out != nil { + fb.out.Output(2, s) + } + if fb.log != nil { + fb.log.Output(2, s) + } +} diff --git a/vendor/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go b/vendor/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go deleted file mode 100644 index b64ed469c..000000000 --- a/vendor/github.com/spf13/jwalterweatherman/thatswhyyoualwaysleaveanote.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright © 2016 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package jwalterweatherman - -import ( - "fmt" - "io" - "io/ioutil" - "log" - "os" - "sync/atomic" -) - -// Level describes the chosen log level between -// debug and critical. -type Level int - -type NotePad struct { - Handle io.Writer - Level Level - Prefix string - Logger **log.Logger - counter uint64 -} - -func (n *NotePad) incr() { - atomic.AddUint64(&n.counter, 1) -} - -func (n *NotePad) resetCounter() { - atomic.StoreUint64(&n.counter, 0) -} - -func (n *NotePad) getCount() uint64 { - return atomic.LoadUint64(&n.counter) -} - -type countingWriter struct { - incrFunc func() -} - -func (cw *countingWriter) Write(p []byte) (n int, err error) { - cw.incrFunc() - - return 0, nil -} - -// Feedback is special. It writes plainly to the output while -// logging with the standard extra information (date, file, etc) -// Only Println and Printf are currently provided for this -type Feedback struct{} - -const ( - LevelTrace Level = iota - LevelDebug - LevelInfo - LevelWarn - LevelError - LevelCritical - LevelFatal - DefaultLogThreshold = LevelWarn - DefaultStdoutThreshold = LevelError -) - -var ( - TRACE *log.Logger - DEBUG *log.Logger - INFO *log.Logger - WARN *log.Logger - ERROR *log.Logger - CRITICAL *log.Logger - FATAL *log.Logger - LOG *log.Logger - FEEDBACK Feedback - LogHandle io.Writer = ioutil.Discard - OutHandle io.Writer = os.Stdout - BothHandle io.Writer = io.MultiWriter(LogHandle, OutHandle) - NotePads []*NotePad = []*NotePad{trace, debug, info, warn, err, critical, fatal} - - trace *NotePad = &NotePad{Level: LevelTrace, Handle: os.Stdout, Logger: &TRACE, Prefix: "TRACE: "} - debug *NotePad = &NotePad{Level: LevelDebug, Handle: os.Stdout, Logger: &DEBUG, Prefix: "DEBUG: "} - info *NotePad = &NotePad{Level: LevelInfo, Handle: os.Stdout, Logger: &INFO, Prefix: "INFO: "} - warn *NotePad = &NotePad{Level: LevelWarn, Handle: os.Stdout, Logger: &WARN, Prefix: "WARN: "} - err *NotePad = &NotePad{Level: LevelError, Handle: os.Stdout, Logger: &ERROR, Prefix: "ERROR: "} - critical *NotePad = &NotePad{Level: LevelCritical, Handle: os.Stdout, Logger: &CRITICAL, Prefix: "CRITICAL: "} - fatal *NotePad = &NotePad{Level: LevelFatal, Handle: os.Stdout, Logger: &FATAL, Prefix: "FATAL: "} - logThreshold Level = DefaultLogThreshold - outputThreshold Level = DefaultStdoutThreshold -) - -const ( - DATE = log.Ldate - TIME = log.Ltime - SFILE = log.Lshortfile - LFILE = log.Llongfile - MSEC = log.Lmicroseconds -) - -var logFlags = DATE | TIME | SFILE - -func init() { - SetStdoutThreshold(DefaultStdoutThreshold) -} - -// initialize will setup the jWalterWeatherman standard approach of providing the user -// some feedback and logging a potentially different amount based on independent log and output thresholds. -// By default the output has a lower threshold than logged -// Don't use if you have manually set the Handles of the different levels as it will overwrite them. -func initialize() { - BothHandle = io.MultiWriter(LogHandle, OutHandle) - - for _, n := range NotePads { - if n.Level < outputThreshold && n.Level < logThreshold { - n.Handle = ioutil.Discard - } else if n.Level >= outputThreshold && n.Level >= logThreshold { - n.Handle = BothHandle - } else if n.Level >= outputThreshold && n.Level < logThreshold { - n.Handle = OutHandle - } else { - n.Handle = LogHandle - } - } - - for _, n := range NotePads { - n.Handle = io.MultiWriter(n.Handle, &countingWriter{n.incr}) - *n.Logger = log.New(n.Handle, n.Prefix, logFlags) - } - - LOG = log.New(LogHandle, - "LOG: ", - logFlags) -} - -// Set the log Flags (Available flag: DATE, TIME, SFILE, LFILE and MSEC) -func SetLogFlag(flags int) { - logFlags = flags - initialize() -} - -// Level returns the current global log threshold. -func LogThreshold() Level { - return logThreshold -} - -// Level returns the current global output threshold. -func StdoutThreshold() Level { - return outputThreshold -} - -// Ensures that the level provided is within the bounds of available levels -func levelCheck(level Level) Level { - switch { - case level <= LevelTrace: - return LevelTrace - case level >= LevelFatal: - return LevelFatal - default: - return level - } -} - -// Establishes a threshold where anything matching or above will be logged -func SetLogThreshold(level Level) { - logThreshold = levelCheck(level) - initialize() -} - -// Establishes a threshold where anything matching or above will be output -func SetStdoutThreshold(level Level) { - outputThreshold = levelCheck(level) - initialize() -} - -// Conveniently Sets the Log Handle to a io.writer created for the file behind the given filepath -// Will only append to this file -func SetLogFile(path string) { - file, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) - if err != nil { - CRITICAL.Println("Failed to open log file:", path, err) - os.Exit(-1) - } - - INFO.Println("Logging to", file.Name()) - - LogHandle = file - initialize() -} - -// Conveniently Creates a temporary file and sets the Log Handle to a io.writer created for it -func UseTempLogFile(prefix string) { - file, err := ioutil.TempFile(os.TempDir(), prefix) - if err != nil { - CRITICAL.Println(err) - } - - INFO.Println("Logging to", file.Name()) - - LogHandle = file - initialize() -} - -// LogCountForLevel returns the number of log invocations for a given level. -func LogCountForLevel(l Level) uint64 { - for _, np := range NotePads { - if np.Level == l { - return np.getCount() - } - } - return 0 -} - -// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations -// greater than or equal to a given level threshold. -func LogCountForLevelsGreaterThanorEqualTo(threshold Level) uint64 { - var cnt uint64 - for _, np := range NotePads { - if np.Level >= threshold { - cnt += np.getCount() - } - } - return cnt -} - -// ResetLogCounters resets the invocation counters for all levels. -func ResetLogCounters() { - for _, np := range NotePads { - np.resetCounter() - } -} - -// Disables logging for the entire JWW system -func DiscardLogging() { - LogHandle = ioutil.Discard - initialize() -} - -// Feedback is special. It writes plainly to the output while -// logging with the standard extra information (date, file, etc) -// Only Println and Printf are currently provided for this -func (fb *Feedback) Println(v ...interface{}) { - s := fmt.Sprintln(v...) - fmt.Print(s) - LOG.Output(2, s) -} - -// Feedback is special. It writes plainly to the output while -// logging with the standard extra information (date, file, etc) -// Only Println and Printf are currently provided for this -func (fb *Feedback) Printf(format string, v ...interface{}) { - s := fmt.Sprintf(format, v...) - fmt.Print(s) - LOG.Output(2, s) -} diff --git a/vendor/github.com/tdewolff/minify/v2/.gitignore b/vendor/github.com/tdewolff/minify/v2/.gitignore index c9ea38dbc..e2cf6cf8e 100644 --- a/vendor/github.com/tdewolff/minify/v2/.gitignore +++ b/vendor/github.com/tdewolff/minify/v2/.gitignore @@ -23,8 +23,10 @@ bindings/js/example/node_modules bindings/js/example/test.min.html bindings/py/go.mod bindings/py/go.sum -bindings/py/minify.h -bindings/py/minify.so -bindings/py/tdewolff_minify.egg-info +bindings/py/**/*.h +bindings/py/**/*.so +bindings/py/**/*.egg-info bindings/py/example/example.min.html bindings/py/dist +bindings/py/build +bindings/py/**/*.pyc diff --git a/vendor/github.com/tdewolff/minify/v2/README.md b/vendor/github.com/tdewolff/minify/v2/README.md index d2bfff407..81d91b8ed 100644 --- a/vendor/github.com/tdewolff/minify/v2/README.md +++ b/vendor/github.com/tdewolff/minify/v2/README.md @@ -1,27 +1,30 @@ -# Minify [![API reference](https://img.shields.io/badge/godoc-reference-5272B4)](https://pkg.go.dev/github.com/tdewolff/minify/v2?tab=doc) [![Go Report Card](https://goreportcard.com/badge/github.com/tdewolff/minify)](https://goreportcard.com/report/github.com/tdewolff/minify) [![codecov](https://codecov.io/gh/tdewolff/minify/branch/master/graph/badge.svg?token=Cr7r2EKPj2)](https://codecov.io/gh/tdewolff/minify) [![Donate](https://img.shields.io/badge/patreon-donate-DFB317)](https://www.patreon.com/tdewolff) +# Minify [![API reference](https://img.shields.io/badge/godoc-reference-5272B4)](https://pkg.go.dev/github.com/tdewolff/minify/v2?tab=doc) [![Go Report Card](https://goreportcard.com/badge/github.com/tdewolff/minify)](https://goreportcard.com/report/github.com/tdewolff/minify) [![codecov](https://codecov.io/gh/tdewolff/minify/branch/master/graph/badge.svg?token=Cr7r2EKPj2)](https://codecov.io/gh/tdewolff/minify) **[Online demo](https://go.tacodewolff.nl/minify)** if you need to minify files *now*. **[Binaries](https://github.com/tdewolff/minify/releases) of CLI for various platforms.** See [CLI](https://github.com/tdewolff/minify/tree/master/cmd/minify) for more installation instructions. +**[Windows binary from scoop](https://scoop.sh/#/apps?q=minify)** install with `scoop install main/minify` + **[Python bindings](https://pypi.org/project/tdewolff-minify/)** install with `pip install tdewolff-minify` **[JavaScript bindings](https://www.npmjs.com/package/@tdewolff/minify)** install with `npm i @tdewolff/minify` +**[.NET bindings](https://github.com/JKamsker/NMinify)** install with `Install-Package NMinify` or `dotnet add package NMinify`, thanks to Jonas Kamsker for the port + --- *Did you know that the shortest valid piece of HTML5 is `x`? See for yourself at the [W3C Validator](http://validator.w3.org/)!* -Minify is a minifier package written in [Go][1]. It provides HTML5, CSS3, JS, JSON, SVG and XML minifiers and an interface to implement any other minifier. Minification is the process of removing bytes from a file (such as whitespace) without changing its output and therefore shrinking its size and speeding up transmission over the internet and possibly parsing. The implemented minifiers are designed for high performance. +Minify is a minifier package written in [Go][1]. It provides HTML5, CSS3, JS, JSON, SVG and XML minifiers and an interface to implement any other minifier. Minification is the process of removing bytes from a file (such as whitespace) without changing its output and therefore shrinking its size and speeding up transmission over the internet and possibly parsing. The implemented minifiers are designed for high performance (see https://github.com/privatenumber/minification-benchmarks where this library is (one of) the fastest JS minifiers). The core functionality associates mimetypes with minification functions, allowing embedded resources (like CSS or JS within HTML files) to be minified as well. Users can add new implementations that are triggered based on a mimetype (or pattern), or redirect to an external command (like ClosureCompiler, UglifyCSS, ...). ### Sponsors +I'm actively looking for support in the form of donations or sponsorships to keep developing this library and highly appreciate any gesture. Please see the Sponsors button in GitHub for ways to contribute, or contact me directly. [![SiteGround](https://www.siteground.com/img/downloads/siteground-logo-black-transparent-vector.svg)](https://www.siteground.com/) -Please see https://www.patreon.com/tdewolff for ways to contribute, otherwise please contact me directly! - #### Table of Contents - [Minify](#minify) @@ -77,7 +80,7 @@ Minifiers or bindings to minifiers exist in almost all programming languages. So This minifier proves to be that fast and extensive minifier that can handle HTML and any other filetype it may contain (CSS, JS, ...). It is usually orders of magnitude faster than existing minifiers. ## Installation -Make sure you have [Git](https://git-scm.com/) and [Go](https://golang.org/dl/) (1.13 or higher) installed, run +Make sure you have [Git](https://git-scm.com/) and [Go](https://golang.org/dl/) (1.18 or higher) installed, run ``` mkdir Project cd Project @@ -196,12 +199,13 @@ The HTML5 minifier uses these minifications: Options: -- `KeepConditionalComments` preserve all IE conditional comments such as `` and ``, see https://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx#syntax +- `KeepSpecialComments` preserve all special comments, including Server Side Includes such as `` and IE conditional comments such as `` and ``, see https://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx#syntax - `KeepDefaultAttrVals` preserve default attribute values such as `