mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:32:25 -05:00 
			
		
		
		
	[chore]: Bump github.com/minio/minio-go/v7 from 7.0.72 to 7.0.73 (#3083)
This commit is contained in:
		
					parent
					
						
							
								ae349dd6a5
							
						
					
				
			
			
				commit
				
					
						43c480aec4
					
				
			
		
					 44 changed files with 3889 additions and 245 deletions
				
			
		
							
								
								
									
										9
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
										
									
									
									
								
							|  | @ -43,7 +43,7 @@ require ( | ||||||
| 	github.com/jackc/pgx/v5 v5.6.0 | 	github.com/jackc/pgx/v5 v5.6.0 | ||||||
| 	github.com/microcosm-cc/bluemonday v1.0.27 | 	github.com/microcosm-cc/bluemonday v1.0.27 | ||||||
| 	github.com/miekg/dns v1.1.61 | 	github.com/miekg/dns v1.1.61 | ||||||
| 	github.com/minio/minio-go/v7 v7.0.72 | 	github.com/minio/minio-go/v7 v7.0.73 | ||||||
| 	github.com/mitchellh/mapstructure v1.5.0 | 	github.com/mitchellh/mapstructure v1.5.0 | ||||||
| 	github.com/ncruces/go-sqlite3 v0.17.0 | 	github.com/ncruces/go-sqlite3 v0.17.0 | ||||||
| 	github.com/oklog/ulid v1.3.1 | 	github.com/oklog/ulid v1.3.1 | ||||||
|  | @ -119,6 +119,7 @@ require ( | ||||||
| 	github.com/gin-contrib/sse v0.1.0 // indirect | 	github.com/gin-contrib/sse v0.1.0 // indirect | ||||||
| 	github.com/go-errors/errors v1.4.1 // indirect | 	github.com/go-errors/errors v1.4.1 // indirect | ||||||
| 	github.com/go-fed/httpsig v1.1.0 // indirect | 	github.com/go-fed/httpsig v1.1.0 // indirect | ||||||
|  | 	github.com/go-ini/ini v1.67.0 // indirect | ||||||
| 	github.com/go-jose/go-jose/v4 v4.0.1 // indirect | 	github.com/go-jose/go-jose/v4 v4.0.1 // indirect | ||||||
| 	github.com/go-logr/logr v1.4.1 // indirect | 	github.com/go-logr/logr v1.4.1 // indirect | ||||||
| 	github.com/go-logr/stdr v1.2.2 // indirect | 	github.com/go-logr/stdr v1.2.2 // indirect | ||||||
|  | @ -137,7 +138,7 @@ require ( | ||||||
| 	github.com/go-playground/universal-translator v0.18.1 // indirect | 	github.com/go-playground/universal-translator v0.18.1 // indirect | ||||||
| 	github.com/go-playground/validator/v10 v10.20.0 // indirect | 	github.com/go-playground/validator/v10 v10.20.0 // indirect | ||||||
| 	github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 // indirect | 	github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 // indirect | ||||||
| 	github.com/goccy/go-json v0.10.2 // indirect | 	github.com/goccy/go-json v0.10.3 // indirect | ||||||
| 	github.com/godbus/dbus/v5 v5.0.4 // indirect | 	github.com/godbus/dbus/v5 v5.0.4 // indirect | ||||||
| 	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect | 	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect | ||||||
| 	github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect | 	github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect | ||||||
|  | @ -159,8 +160,8 @@ require ( | ||||||
| 	github.com/jinzhu/inflection v1.0.0 // indirect | 	github.com/jinzhu/inflection v1.0.0 // indirect | ||||||
| 	github.com/josharian/intern v1.0.0 // indirect | 	github.com/josharian/intern v1.0.0 // indirect | ||||||
| 	github.com/json-iterator/go v1.1.12 // indirect | 	github.com/json-iterator/go v1.1.12 // indirect | ||||||
| 	github.com/klauspost/compress v1.17.8 // indirect | 	github.com/klauspost/compress v1.17.9 // indirect | ||||||
| 	github.com/klauspost/cpuid/v2 v2.2.7 // indirect | 	github.com/klauspost/cpuid/v2 v2.2.8 // indirect | ||||||
| 	github.com/kr/pretty v0.3.1 // indirect | 	github.com/kr/pretty v0.3.1 // indirect | ||||||
| 	github.com/kr/text v0.2.0 // indirect | 	github.com/kr/text v0.2.0 // indirect | ||||||
| 	github.com/leodido/go-urn v1.4.0 // indirect | 	github.com/leodido/go-urn v1.4.0 // indirect | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								go.sum
									
										
									
									
									
								
							|  | @ -207,6 +207,8 @@ github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7 | ||||||
| github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | ||||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | ||||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | ||||||
|  | github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= | ||||||
|  | github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= | ||||||
| github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= | github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= | ||||||
| github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= | github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= | ||||||
| github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | ||||||
|  | @ -254,8 +256,8 @@ github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= | ||||||
| github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= | github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= | ||||||
| github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 h1:PSPmmucxGiFBtbQcttHTUc4LQ3P09AW+ldO2qspyKdY= | github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 h1:PSPmmucxGiFBtbQcttHTUc4LQ3P09AW+ldO2qspyKdY= | ||||||
| github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= | github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= | ||||||
| github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= | github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= | ||||||
| github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= | ||||||
| github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= | github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= | ||||||
| github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||||||
| github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= | github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= | ||||||
|  | @ -391,12 +393,12 @@ github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q | ||||||
| github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||||||
| github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | ||||||
| github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | ||||||
| github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= | github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= | ||||||
| github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= | github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= | ||||||
| github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||||
| github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||||
| github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= | github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= | ||||||
| github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= | github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= | ||||||
| github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | ||||||
| github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||||||
| github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= | ||||||
|  | @ -422,8 +424,8 @@ github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= | ||||||
| github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= | github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= | ||||||
| github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= | github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= | ||||||
| github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= | github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= | ||||||
| github.com/minio/minio-go/v7 v7.0.72 h1:ZSbxs2BfJensLyHdVOgHv+pfmvxYraaUy07ER04dWnA= | github.com/minio/minio-go/v7 v7.0.73 h1:qr2vi96Qm7kZ4v7LLebjte+MQh621fFWnv93p12htEo= | ||||||
| github.com/minio/minio-go/v7 v7.0.72/go.mod h1:4yBA8v80xGA30cfM3fz0DKYMXunWl/AV/6tWEs9ryzo= | github.com/minio/minio-go/v7 v7.0.73/go.mod h1:qydcVzV8Hqtj1VtEocfxbmVFa2siu6HGa+LDEPogjD8= | ||||||
| github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= | ||||||
| github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= | ||||||
| github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								vendor/github.com/go-ini/ini/.editorconfig
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/go-ini/ini/.editorconfig
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | # http://editorconfig.org | ||||||
|  | 
 | ||||||
|  | root = true | ||||||
|  | 
 | ||||||
|  | [*] | ||||||
|  | charset = utf-8 | ||||||
|  | end_of_line = lf | ||||||
|  | insert_final_newline = true | ||||||
|  | trim_trailing_whitespace = true | ||||||
|  | 
 | ||||||
|  | [*_test.go] | ||||||
|  | trim_trailing_whitespace = false | ||||||
							
								
								
									
										7
									
								
								vendor/github.com/go-ini/ini/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/go-ini/ini/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | testdata/conf_out.ini | ||||||
|  | ini.sublime-project | ||||||
|  | ini.sublime-workspace | ||||||
|  | testdata/conf_reflect.ini | ||||||
|  | .idea | ||||||
|  | /.vscode | ||||||
|  | .DS_Store | ||||||
							
								
								
									
										27
									
								
								vendor/github.com/go-ini/ini/.golangci.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/go-ini/ini/.golangci.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | linters-settings: | ||||||
|  |   staticcheck: | ||||||
|  |     checks: [ | ||||||
|  |       "all", | ||||||
|  |       "-SA1019" # There are valid use cases of strings.Title | ||||||
|  |     ] | ||||||
|  |   nakedret: | ||||||
|  |     max-func-lines: 0 # Disallow any unnamed return statement | ||||||
|  | 
 | ||||||
|  | linters: | ||||||
|  |   enable: | ||||||
|  |     - deadcode | ||||||
|  |     - errcheck | ||||||
|  |     - gosimple | ||||||
|  |     - govet | ||||||
|  |     - ineffassign | ||||||
|  |     - staticcheck | ||||||
|  |     - structcheck | ||||||
|  |     - typecheck | ||||||
|  |     - unused | ||||||
|  |     - varcheck | ||||||
|  |     - nakedret | ||||||
|  |     - gofmt | ||||||
|  |     - rowserrcheck | ||||||
|  |     - unconvert | ||||||
|  |     - goimports | ||||||
|  |     - unparam | ||||||
							
								
								
									
										191
									
								
								vendor/github.com/go-ini/ini/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-ini/ini/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,191 @@ | ||||||
|  | Apache License | ||||||
|  | Version 2.0, January 2004 | ||||||
|  | http://www.apache.org/licenses/ | ||||||
|  | 
 | ||||||
|  | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||||
|  | 
 | ||||||
|  | 1. Definitions. | ||||||
|  | 
 | ||||||
|  | "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: | ||||||
|  | 
 | ||||||
|  | You must give any other recipients of the Work or Derivative Works a copy of | ||||||
|  | this License; and | ||||||
|  | You must cause any modified files to carry prominent notices stating that You | ||||||
|  | changed the files; and | ||||||
|  | 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 | ||||||
|  | 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 2014 Unknwon | ||||||
|  | 
 | ||||||
|  |    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. | ||||||
							
								
								
									
										15
									
								
								vendor/github.com/go-ini/ini/Makefile
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/go-ini/ini/Makefile
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | .PHONY: build test bench vet coverage | ||||||
|  | 
 | ||||||
|  | build: vet bench | ||||||
|  | 
 | ||||||
|  | test: | ||||||
|  | 	go test -v -cover -race | ||||||
|  | 
 | ||||||
|  | bench: | ||||||
|  | 	go test -v -cover -test.bench=. -test.benchmem | ||||||
|  | 
 | ||||||
|  | vet: | ||||||
|  | 	go vet | ||||||
|  | 
 | ||||||
|  | coverage: | ||||||
|  | 	go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out | ||||||
							
								
								
									
										43
									
								
								vendor/github.com/go-ini/ini/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/go-ini/ini/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | ||||||
|  | # INI | ||||||
|  | 
 | ||||||
|  | [](https://github.com/go-ini/ini/actions?query=branch%3Amain) | ||||||
|  | [](https://codecov.io/gh/go-ini/ini) | ||||||
|  | [](https://pkg.go.dev/github.com/go-ini/ini?tab=doc) | ||||||
|  | [](https://sourcegraph.com/github.com/go-ini/ini) | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | Package ini provides INI file read and write functionality in Go. | ||||||
|  | 
 | ||||||
|  | ## Features | ||||||
|  | 
 | ||||||
|  | - Load from multiple data sources(file, `[]byte`, `io.Reader` and `io.ReadCloser`) with overwrites. | ||||||
|  | - Read with recursion values. | ||||||
|  | - Read with parent-child sections. | ||||||
|  | - Read with auto-increment key names. | ||||||
|  | - Read with multiple-line values. | ||||||
|  | - Read with tons of helper methods. | ||||||
|  | - Read and convert values to Go types. | ||||||
|  | - Read and **WRITE** comments of sections and keys. | ||||||
|  | - Manipulate sections, keys and comments with ease. | ||||||
|  | - Keep sections and keys in order as you parse and save. | ||||||
|  | 
 | ||||||
|  | ## Installation | ||||||
|  | 
 | ||||||
|  | The minimum requirement of Go is **1.13**. | ||||||
|  | 
 | ||||||
|  | ```sh | ||||||
|  | $ go get gopkg.in/ini.v1 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Please add `-u` flag to update in the future. | ||||||
|  | 
 | ||||||
|  | ## Getting Help | ||||||
|  | 
 | ||||||
|  | - [Getting Started](https://ini.unknwon.io/docs/intro/getting_started) | ||||||
|  | - [API Documentation](https://gowalker.org/gopkg.in/ini.v1) | ||||||
|  | - 中国大陆镜像:https://ini.unknwon.cn | ||||||
|  | 
 | ||||||
|  | ## License | ||||||
|  | 
 | ||||||
|  | This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. | ||||||
							
								
								
									
										16
									
								
								vendor/github.com/go-ini/ini/codecov.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/go-ini/ini/codecov.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | coverage: | ||||||
|  |   range: "60...95" | ||||||
|  |   status: | ||||||
|  |     project: | ||||||
|  |       default: | ||||||
|  |         threshold: 1% | ||||||
|  |         informational: true | ||||||
|  |     patch: | ||||||
|  |       defualt: | ||||||
|  |         only_pulls: true | ||||||
|  |         informational: true | ||||||
|  | 
 | ||||||
|  | comment: | ||||||
|  |   layout: 'diff' | ||||||
|  | 
 | ||||||
|  | github_checks: false | ||||||
							
								
								
									
										76
									
								
								vendor/github.com/go-ini/ini/data_source.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/go-ini/ini/data_source.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | ||||||
|  | // Copyright 2019 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	_ dataSource = (*sourceFile)(nil) | ||||||
|  | 	_ dataSource = (*sourceData)(nil) | ||||||
|  | 	_ dataSource = (*sourceReadCloser)(nil) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // dataSource is an interface that returns object which can be read and closed. | ||||||
|  | type dataSource interface { | ||||||
|  | 	ReadCloser() (io.ReadCloser, error) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // sourceFile represents an object that contains content on the local file system. | ||||||
|  | type sourceFile struct { | ||||||
|  | 	name string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) { | ||||||
|  | 	return os.Open(s.name) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // sourceData represents an object that contains content in memory. | ||||||
|  | type sourceData struct { | ||||||
|  | 	data []byte | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *sourceData) ReadCloser() (io.ReadCloser, error) { | ||||||
|  | 	return ioutil.NopCloser(bytes.NewReader(s.data)), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // sourceReadCloser represents an input stream with Close method. | ||||||
|  | type sourceReadCloser struct { | ||||||
|  | 	reader io.ReadCloser | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) { | ||||||
|  | 	return s.reader, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseDataSource(source interface{}) (dataSource, error) { | ||||||
|  | 	switch s := source.(type) { | ||||||
|  | 	case string: | ||||||
|  | 		return sourceFile{s}, nil | ||||||
|  | 	case []byte: | ||||||
|  | 		return &sourceData{s}, nil | ||||||
|  | 	case io.ReadCloser: | ||||||
|  | 		return &sourceReadCloser{s}, nil | ||||||
|  | 	case io.Reader: | ||||||
|  | 		return &sourceReadCloser{ioutil.NopCloser(s)}, nil | ||||||
|  | 	default: | ||||||
|  | 		return nil, fmt.Errorf("error parsing data source: unknown type %q", s) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								vendor/github.com/go-ini/ini/deprecated.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/go-ini/ini/deprecated.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | // Copyright 2019 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// Deprecated: Use "DefaultSection" instead. | ||||||
|  | 	DEFAULT_SECTION = DefaultSection | ||||||
|  | 	// Deprecated: AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE. | ||||||
|  | 	AllCapsUnderscore = SnackCase | ||||||
|  | ) | ||||||
							
								
								
									
										49
									
								
								vendor/github.com/go-ini/ini/error.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/go-ini/ini/error.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | // Copyright 2016 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // ErrDelimiterNotFound indicates the error type of no delimiter is found which there should be one. | ||||||
|  | type ErrDelimiterNotFound struct { | ||||||
|  | 	Line string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsErrDelimiterNotFound returns true if the given error is an instance of ErrDelimiterNotFound. | ||||||
|  | func IsErrDelimiterNotFound(err error) bool { | ||||||
|  | 	_, ok := err.(ErrDelimiterNotFound) | ||||||
|  | 	return ok | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (err ErrDelimiterNotFound) Error() string { | ||||||
|  | 	return fmt.Sprintf("key-value delimiter not found: %s", err.Line) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ErrEmptyKeyName indicates the error type of no key name is found which there should be one. | ||||||
|  | type ErrEmptyKeyName struct { | ||||||
|  | 	Line string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsErrEmptyKeyName returns true if the given error is an instance of ErrEmptyKeyName. | ||||||
|  | func IsErrEmptyKeyName(err error) bool { | ||||||
|  | 	_, ok := err.(ErrEmptyKeyName) | ||||||
|  | 	return ok | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (err ErrEmptyKeyName) Error() string { | ||||||
|  | 	return fmt.Sprintf("empty key name: %s", err.Line) | ||||||
|  | } | ||||||
							
								
								
									
										541
									
								
								vendor/github.com/go-ini/ini/file.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										541
									
								
								vendor/github.com/go-ini/ini/file.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,541 @@ | ||||||
|  | // Copyright 2017 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | 	"sync" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // File represents a combination of one or more INI files in memory. | ||||||
|  | type File struct { | ||||||
|  | 	options     LoadOptions | ||||||
|  | 	dataSources []dataSource | ||||||
|  | 
 | ||||||
|  | 	// Should make things safe, but sometimes doesn't matter. | ||||||
|  | 	BlockMode bool | ||||||
|  | 	lock      sync.RWMutex | ||||||
|  | 
 | ||||||
|  | 	// To keep data in order. | ||||||
|  | 	sectionList []string | ||||||
|  | 	// To keep track of the index of a section with same name. | ||||||
|  | 	// This meta list is only used with non-unique section names are allowed. | ||||||
|  | 	sectionIndexes []int | ||||||
|  | 
 | ||||||
|  | 	// Actual data is stored here. | ||||||
|  | 	sections map[string][]*Section | ||||||
|  | 
 | ||||||
|  | 	NameMapper | ||||||
|  | 	ValueMapper | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // newFile initializes File object with given data sources. | ||||||
|  | func newFile(dataSources []dataSource, opts LoadOptions) *File { | ||||||
|  | 	if len(opts.KeyValueDelimiters) == 0 { | ||||||
|  | 		opts.KeyValueDelimiters = "=:" | ||||||
|  | 	} | ||||||
|  | 	if len(opts.KeyValueDelimiterOnWrite) == 0 { | ||||||
|  | 		opts.KeyValueDelimiterOnWrite = "=" | ||||||
|  | 	} | ||||||
|  | 	if len(opts.ChildSectionDelimiter) == 0 { | ||||||
|  | 		opts.ChildSectionDelimiter = "." | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &File{ | ||||||
|  | 		BlockMode:   true, | ||||||
|  | 		dataSources: dataSources, | ||||||
|  | 		sections:    make(map[string][]*Section), | ||||||
|  | 		options:     opts, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Empty returns an empty file object. | ||||||
|  | func Empty(opts ...LoadOptions) *File { | ||||||
|  | 	var opt LoadOptions | ||||||
|  | 	if len(opts) > 0 { | ||||||
|  | 		opt = opts[0] | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Ignore error here, we are sure our data is good. | ||||||
|  | 	f, _ := LoadSources(opt, []byte("")) | ||||||
|  | 	return f | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewSection creates a new section. | ||||||
|  | func (f *File) NewSection(name string) (*Section, error) { | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		return nil, errors.New("empty section name") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (f.options.Insensitive || f.options.InsensitiveSections) && name != DefaultSection { | ||||||
|  | 		name = strings.ToLower(name) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if f.BlockMode { | ||||||
|  | 		f.lock.Lock() | ||||||
|  | 		defer f.lock.Unlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !f.options.AllowNonUniqueSections && inSlice(name, f.sectionList) { | ||||||
|  | 		return f.sections[name][0], nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	f.sectionList = append(f.sectionList, name) | ||||||
|  | 
 | ||||||
|  | 	// NOTE: Append to indexes must happen before appending to sections, | ||||||
|  | 	// otherwise index will have off-by-one problem. | ||||||
|  | 	f.sectionIndexes = append(f.sectionIndexes, len(f.sections[name])) | ||||||
|  | 
 | ||||||
|  | 	sec := newSection(f, name) | ||||||
|  | 	f.sections[name] = append(f.sections[name], sec) | ||||||
|  | 
 | ||||||
|  | 	return sec, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewRawSection creates a new section with an unparseable body. | ||||||
|  | func (f *File) NewRawSection(name, body string) (*Section, error) { | ||||||
|  | 	section, err := f.NewSection(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	section.isRawSection = true | ||||||
|  | 	section.rawBody = body | ||||||
|  | 	return section, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewSections creates a list of sections. | ||||||
|  | func (f *File) NewSections(names ...string) (err error) { | ||||||
|  | 	for _, name := range names { | ||||||
|  | 		if _, err = f.NewSection(name); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetSection returns section by given name. | ||||||
|  | func (f *File) GetSection(name string) (*Section, error) { | ||||||
|  | 	secs, err := f.SectionsByName(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return secs[0], err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // HasSection returns true if the file contains a section with given name. | ||||||
|  | func (f *File) HasSection(name string) bool { | ||||||
|  | 	section, _ := f.GetSection(name) | ||||||
|  | 	return section != nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SectionsByName returns all sections with given name. | ||||||
|  | func (f *File) SectionsByName(name string) ([]*Section, error) { | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		name = DefaultSection | ||||||
|  | 	} | ||||||
|  | 	if f.options.Insensitive || f.options.InsensitiveSections { | ||||||
|  | 		name = strings.ToLower(name) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if f.BlockMode { | ||||||
|  | 		f.lock.RLock() | ||||||
|  | 		defer f.lock.RUnlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	secs := f.sections[name] | ||||||
|  | 	if len(secs) == 0 { | ||||||
|  | 		return nil, fmt.Errorf("section %q does not exist", name) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return secs, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Section assumes named section exists and returns a zero-value when not. | ||||||
|  | func (f *File) Section(name string) *Section { | ||||||
|  | 	sec, err := f.GetSection(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		if name == "" { | ||||||
|  | 			name = DefaultSection | ||||||
|  | 		} | ||||||
|  | 		sec, _ = f.NewSection(name) | ||||||
|  | 		return sec | ||||||
|  | 	} | ||||||
|  | 	return sec | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SectionWithIndex assumes named section exists and returns a new section when not. | ||||||
|  | func (f *File) SectionWithIndex(name string, index int) *Section { | ||||||
|  | 	secs, err := f.SectionsByName(name) | ||||||
|  | 	if err != nil || len(secs) <= index { | ||||||
|  | 		// NOTE: It's OK here because the only possible error is empty section name, | ||||||
|  | 		// but if it's empty, this piece of code won't be executed. | ||||||
|  | 		newSec, _ := f.NewSection(name) | ||||||
|  | 		return newSec | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return secs[index] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Sections returns a list of Section stored in the current instance. | ||||||
|  | func (f *File) Sections() []*Section { | ||||||
|  | 	if f.BlockMode { | ||||||
|  | 		f.lock.RLock() | ||||||
|  | 		defer f.lock.RUnlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sections := make([]*Section, len(f.sectionList)) | ||||||
|  | 	for i, name := range f.sectionList { | ||||||
|  | 		sections[i] = f.sections[name][f.sectionIndexes[i]] | ||||||
|  | 	} | ||||||
|  | 	return sections | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ChildSections returns a list of child sections of given section name. | ||||||
|  | func (f *File) ChildSections(name string) []*Section { | ||||||
|  | 	return f.Section(name).ChildSections() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SectionStrings returns list of section names. | ||||||
|  | func (f *File) SectionStrings() []string { | ||||||
|  | 	list := make([]string, len(f.sectionList)) | ||||||
|  | 	copy(list, f.sectionList) | ||||||
|  | 	return list | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeleteSection deletes a section or all sections with given name. | ||||||
|  | func (f *File) DeleteSection(name string) { | ||||||
|  | 	secs, err := f.SectionsByName(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < len(secs); i++ { | ||||||
|  | 		// For non-unique sections, it is always needed to remove the first one so | ||||||
|  | 		// in the next iteration, the subsequent section continue having index 0. | ||||||
|  | 		// Ignoring the error as index 0 never returns an error. | ||||||
|  | 		_ = f.DeleteSectionWithIndex(name, 0) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeleteSectionWithIndex deletes a section with given name and index. | ||||||
|  | func (f *File) DeleteSectionWithIndex(name string, index int) error { | ||||||
|  | 	if !f.options.AllowNonUniqueSections && index != 0 { | ||||||
|  | 		return fmt.Errorf("delete section with non-zero index is only allowed when non-unique sections is enabled") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		name = DefaultSection | ||||||
|  | 	} | ||||||
|  | 	if f.options.Insensitive || f.options.InsensitiveSections { | ||||||
|  | 		name = strings.ToLower(name) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if f.BlockMode { | ||||||
|  | 		f.lock.Lock() | ||||||
|  | 		defer f.lock.Unlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Count occurrences of the sections | ||||||
|  | 	occurrences := 0 | ||||||
|  | 
 | ||||||
|  | 	sectionListCopy := make([]string, len(f.sectionList)) | ||||||
|  | 	copy(sectionListCopy, f.sectionList) | ||||||
|  | 
 | ||||||
|  | 	for i, s := range sectionListCopy { | ||||||
|  | 		if s != name { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if occurrences == index { | ||||||
|  | 			if len(f.sections[name]) <= 1 { | ||||||
|  | 				delete(f.sections, name) // The last one in the map | ||||||
|  | 			} else { | ||||||
|  | 				f.sections[name] = append(f.sections[name][:index], f.sections[name][index+1:]...) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Fix section lists | ||||||
|  | 			f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...) | ||||||
|  | 			f.sectionIndexes = append(f.sectionIndexes[:i], f.sectionIndexes[i+1:]...) | ||||||
|  | 
 | ||||||
|  | 		} else if occurrences > index { | ||||||
|  | 			// Fix the indices of all following sections with this name. | ||||||
|  | 			f.sectionIndexes[i-1]-- | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		occurrences++ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f *File) reload(s dataSource) error { | ||||||
|  | 	r, err := s.ReadCloser() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer r.Close() | ||||||
|  | 
 | ||||||
|  | 	return f.parse(r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Reload reloads and parses all data sources. | ||||||
|  | func (f *File) Reload() (err error) { | ||||||
|  | 	for _, s := range f.dataSources { | ||||||
|  | 		if err = f.reload(s); err != nil { | ||||||
|  | 			// In loose mode, we create an empty default section for nonexistent files. | ||||||
|  | 			if os.IsNotExist(err) && f.options.Loose { | ||||||
|  | 				_ = f.parse(bytes.NewBuffer(nil)) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		if f.options.ShortCircuit { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Append appends one or more data sources and reloads automatically. | ||||||
|  | func (f *File) Append(source interface{}, others ...interface{}) error { | ||||||
|  | 	ds, err := parseDataSource(source) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	f.dataSources = append(f.dataSources, ds) | ||||||
|  | 	for _, s := range others { | ||||||
|  | 		ds, err = parseDataSource(s) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		f.dataSources = append(f.dataSources, ds) | ||||||
|  | 	} | ||||||
|  | 	return f.Reload() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) { | ||||||
|  | 	equalSign := DefaultFormatLeft + f.options.KeyValueDelimiterOnWrite + DefaultFormatRight | ||||||
|  | 
 | ||||||
|  | 	if PrettyFormat || PrettyEqual { | ||||||
|  | 		equalSign = fmt.Sprintf(" %s ", f.options.KeyValueDelimiterOnWrite) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Use buffer to make sure target is safe until finish encoding. | ||||||
|  | 	buf := bytes.NewBuffer(nil) | ||||||
|  | 	lastSectionIdx := len(f.sectionList) - 1 | ||||||
|  | 	for i, sname := range f.sectionList { | ||||||
|  | 		sec := f.SectionWithIndex(sname, f.sectionIndexes[i]) | ||||||
|  | 		if len(sec.Comment) > 0 { | ||||||
|  | 			// Support multiline comments | ||||||
|  | 			lines := strings.Split(sec.Comment, LineBreak) | ||||||
|  | 			for i := range lines { | ||||||
|  | 				if lines[i][0] != '#' && lines[i][0] != ';' { | ||||||
|  | 					lines[i] = "; " + lines[i] | ||||||
|  | 				} else { | ||||||
|  | 					lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:]) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if _, err := buf.WriteString(lines[i] + LineBreak); err != nil { | ||||||
|  | 					return nil, err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if i > 0 || DefaultHeader || (i == 0 && strings.ToUpper(sec.name) != DefaultSection) { | ||||||
|  | 			if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			// Write nothing if default section is empty | ||||||
|  | 			if len(sec.keyList) == 0 { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		isLastSection := i == lastSectionIdx | ||||||
|  | 		if sec.isRawSection { | ||||||
|  | 			if _, err := buf.WriteString(sec.rawBody); err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if PrettySection && !isLastSection { | ||||||
|  | 				// Put a line between sections | ||||||
|  | 				if _, err := buf.WriteString(LineBreak); err != nil { | ||||||
|  | 					return nil, err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Count and generate alignment length and buffer spaces using the | ||||||
|  | 		// longest key. Keys may be modified if they contain certain characters so | ||||||
|  | 		// we need to take that into account in our calculation. | ||||||
|  | 		alignLength := 0 | ||||||
|  | 		if PrettyFormat { | ||||||
|  | 			for _, kname := range sec.keyList { | ||||||
|  | 				keyLength := len(kname) | ||||||
|  | 				// First case will surround key by ` and second by """ | ||||||
|  | 				if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) { | ||||||
|  | 					keyLength += 2 | ||||||
|  | 				} else if strings.Contains(kname, "`") { | ||||||
|  | 					keyLength += 6 | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if keyLength > alignLength { | ||||||
|  | 					alignLength = keyLength | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		alignSpaces := bytes.Repeat([]byte(" "), alignLength) | ||||||
|  | 
 | ||||||
|  | 	KeyList: | ||||||
|  | 		for _, kname := range sec.keyList { | ||||||
|  | 			key := sec.Key(kname) | ||||||
|  | 			if len(key.Comment) > 0 { | ||||||
|  | 				if len(indent) > 0 && sname != DefaultSection { | ||||||
|  | 					buf.WriteString(indent) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Support multiline comments | ||||||
|  | 				lines := strings.Split(key.Comment, LineBreak) | ||||||
|  | 				for i := range lines { | ||||||
|  | 					if lines[i][0] != '#' && lines[i][0] != ';' { | ||||||
|  | 						lines[i] = "; " + strings.TrimSpace(lines[i]) | ||||||
|  | 					} else { | ||||||
|  | 						lines[i] = lines[i][:1] + " " + strings.TrimSpace(lines[i][1:]) | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					if _, err := buf.WriteString(lines[i] + LineBreak); err != nil { | ||||||
|  | 						return nil, err | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if len(indent) > 0 && sname != DefaultSection { | ||||||
|  | 				buf.WriteString(indent) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			switch { | ||||||
|  | 			case key.isAutoIncrement: | ||||||
|  | 				kname = "-" | ||||||
|  | 			case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters): | ||||||
|  | 				kname = "`" + kname + "`" | ||||||
|  | 			case strings.Contains(kname, "`"): | ||||||
|  | 				kname = `"""` + kname + `"""` | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			writeKeyValue := func(val string) (bool, error) { | ||||||
|  | 				if _, err := buf.WriteString(kname); err != nil { | ||||||
|  | 					return false, err | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if key.isBooleanType { | ||||||
|  | 					buf.WriteString(LineBreak) | ||||||
|  | 					return true, nil | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Write out alignment spaces before "=" sign | ||||||
|  | 				if PrettyFormat { | ||||||
|  | 					buf.Write(alignSpaces[:alignLength-len(kname)]) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// In case key value contains "\n", "`", "\"", "#" or ";" | ||||||
|  | 				if strings.ContainsAny(val, "\n`") { | ||||||
|  | 					val = `"""` + val + `"""` | ||||||
|  | 				} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") { | ||||||
|  | 					val = "`" + val + "`" | ||||||
|  | 				} else if len(strings.TrimSpace(val)) != len(val) { | ||||||
|  | 					val = `"` + val + `"` | ||||||
|  | 				} | ||||||
|  | 				if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil { | ||||||
|  | 					return false, err | ||||||
|  | 				} | ||||||
|  | 				return false, nil | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			shadows := key.ValueWithShadows() | ||||||
|  | 			if len(shadows) == 0 { | ||||||
|  | 				if _, err := writeKeyValue(""); err != nil { | ||||||
|  | 					return nil, err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			for _, val := range shadows { | ||||||
|  | 				exitLoop, err := writeKeyValue(val) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return nil, err | ||||||
|  | 				} else if exitLoop { | ||||||
|  | 					continue KeyList | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			for _, val := range key.nestedValues { | ||||||
|  | 				if _, err := buf.WriteString(indent + "  " + val + LineBreak); err != nil { | ||||||
|  | 					return nil, err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if PrettySection && !isLastSection { | ||||||
|  | 			// Put a line between sections | ||||||
|  | 			if _, err := buf.WriteString(LineBreak); err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return buf, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // WriteToIndent writes content into io.Writer with given indention. | ||||||
|  | // If PrettyFormat has been set to be true, | ||||||
|  | // it will align "=" sign with spaces under each section. | ||||||
|  | func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) { | ||||||
|  | 	buf, err := f.writeToBuffer(indent) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return buf.WriteTo(w) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // WriteTo writes file content into io.Writer. | ||||||
|  | func (f *File) WriteTo(w io.Writer) (int64, error) { | ||||||
|  | 	return f.WriteToIndent(w, "") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SaveToIndent writes content to file system with given value indention. | ||||||
|  | func (f *File) SaveToIndent(filename, indent string) error { | ||||||
|  | 	// Note: Because we are truncating with os.Create, | ||||||
|  | 	// 	so it's safer to save to a temporary file location and rename after done. | ||||||
|  | 	buf, err := f.writeToBuffer(indent) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ioutil.WriteFile(filename, buf.Bytes(), 0666) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SaveTo writes content to file system. | ||||||
|  | func (f *File) SaveTo(filename string) error { | ||||||
|  | 	return f.SaveToIndent(filename, "") | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								vendor/github.com/go-ini/ini/helper.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/go-ini/ini/helper.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | // Copyright 2019 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | func inSlice(str string, s []string) bool { | ||||||
|  | 	for _, v := range s { | ||||||
|  | 		if str == v { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
							
								
								
									
										176
									
								
								vendor/github.com/go-ini/ini/ini.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								vendor/github.com/go-ini/ini/ini.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,176 @@ | ||||||
|  | // Copyright 2014 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini provides INI file read and write functionality in Go. | ||||||
|  | package ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 	"regexp" | ||||||
|  | 	"runtime" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	// Maximum allowed depth when recursively substituing variable names. | ||||||
|  | 	depthValues = 99 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// DefaultSection is the name of default section. You can use this var or the string literal. | ||||||
|  | 	// In most of cases, an empty string is all you need to access the section. | ||||||
|  | 	DefaultSection = "DEFAULT" | ||||||
|  | 
 | ||||||
|  | 	// LineBreak is the delimiter to determine or compose a new line. | ||||||
|  | 	// This variable will be changed to "\r\n" automatically on Windows at package init time. | ||||||
|  | 	LineBreak = "\n" | ||||||
|  | 
 | ||||||
|  | 	// Variable regexp pattern: %(variable)s | ||||||
|  | 	varPattern = regexp.MustCompile(`%\(([^)]+)\)s`) | ||||||
|  | 
 | ||||||
|  | 	// DefaultHeader explicitly writes default section header. | ||||||
|  | 	DefaultHeader = false | ||||||
|  | 
 | ||||||
|  | 	// PrettySection indicates whether to put a line between sections. | ||||||
|  | 	PrettySection = true | ||||||
|  | 	// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output | ||||||
|  | 	// or reduce all possible spaces for compact format. | ||||||
|  | 	PrettyFormat = true | ||||||
|  | 	// PrettyEqual places spaces around "=" sign even when PrettyFormat is false. | ||||||
|  | 	PrettyEqual = false | ||||||
|  | 	// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled. | ||||||
|  | 	DefaultFormatLeft = "" | ||||||
|  | 	// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled. | ||||||
|  | 	DefaultFormatRight = "" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	if runtime.GOOS == "windows" && !inTest { | ||||||
|  | 		LineBreak = "\r\n" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // LoadOptions contains all customized options used for load data source(s). | ||||||
|  | type LoadOptions struct { | ||||||
|  | 	// Loose indicates whether the parser should ignore nonexistent files or return error. | ||||||
|  | 	Loose bool | ||||||
|  | 	// Insensitive indicates whether the parser forces all section and key names to lowercase. | ||||||
|  | 	Insensitive bool | ||||||
|  | 	// InsensitiveSections indicates whether the parser forces all section to lowercase. | ||||||
|  | 	InsensitiveSections bool | ||||||
|  | 	// InsensitiveKeys indicates whether the parser forces all key names to lowercase. | ||||||
|  | 	InsensitiveKeys bool | ||||||
|  | 	// IgnoreContinuation indicates whether to ignore continuation lines while parsing. | ||||||
|  | 	IgnoreContinuation bool | ||||||
|  | 	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value. | ||||||
|  | 	IgnoreInlineComment bool | ||||||
|  | 	// SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs. | ||||||
|  | 	SkipUnrecognizableLines bool | ||||||
|  | 	// ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source. | ||||||
|  | 	ShortCircuit bool | ||||||
|  | 	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing. | ||||||
|  | 	// This type of keys are mostly used in my.cnf. | ||||||
|  | 	AllowBooleanKeys bool | ||||||
|  | 	// AllowShadows indicates whether to keep track of keys with same name under same section. | ||||||
|  | 	AllowShadows bool | ||||||
|  | 	// AllowNestedValues indicates whether to allow AWS-like nested values. | ||||||
|  | 	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values | ||||||
|  | 	AllowNestedValues bool | ||||||
|  | 	// AllowPythonMultilineValues indicates whether to allow Python-like multi-line values. | ||||||
|  | 	// Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure | ||||||
|  | 	// Relevant quote:  Values can also span multiple lines, as long as they are indented deeper | ||||||
|  | 	// than the first line of the value. | ||||||
|  | 	AllowPythonMultilineValues bool | ||||||
|  | 	// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value. | ||||||
|  | 	// Docs: https://docs.python.org/2/library/configparser.html | ||||||
|  | 	// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names. | ||||||
|  | 	// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment. | ||||||
|  | 	SpaceBeforeInlineComment bool | ||||||
|  | 	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format | ||||||
|  | 	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value" | ||||||
|  | 	UnescapeValueDoubleQuotes bool | ||||||
|  | 	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format | ||||||
|  | 	// when value is NOT surrounded by any quotes. | ||||||
|  | 	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all. | ||||||
|  | 	UnescapeValueCommentSymbols bool | ||||||
|  | 	// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise | ||||||
|  | 	// conform to key/value pairs. Specify the names of those blocks here. | ||||||
|  | 	UnparseableSections []string | ||||||
|  | 	// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:". | ||||||
|  | 	KeyValueDelimiters string | ||||||
|  | 	// KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=". | ||||||
|  | 	KeyValueDelimiterOnWrite string | ||||||
|  | 	// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".". | ||||||
|  | 	ChildSectionDelimiter string | ||||||
|  | 	// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes). | ||||||
|  | 	PreserveSurroundedQuote bool | ||||||
|  | 	// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values). | ||||||
|  | 	DebugFunc DebugFunc | ||||||
|  | 	// ReaderBufferSize is the buffer size of the reader in bytes. | ||||||
|  | 	ReaderBufferSize int | ||||||
|  | 	// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times. | ||||||
|  | 	AllowNonUniqueSections bool | ||||||
|  | 	// AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated. | ||||||
|  | 	AllowDuplicateShadowValues bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DebugFunc is the type of function called to log parse events. | ||||||
|  | type DebugFunc func(message string) | ||||||
|  | 
 | ||||||
|  | // LoadSources allows caller to apply customized options for loading from data source(s). | ||||||
|  | func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) { | ||||||
|  | 	sources := make([]dataSource, len(others)+1) | ||||||
|  | 	sources[0], err = parseDataSource(source) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	for i := range others { | ||||||
|  | 		sources[i+1], err = parseDataSource(others[i]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	f := newFile(sources, opts) | ||||||
|  | 	if err = f.Reload(); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return f, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Load loads and parses from INI data sources. | ||||||
|  | // Arguments can be mixed of file name with string type, or raw data in []byte. | ||||||
|  | // It will return error if list contains nonexistent files. | ||||||
|  | func Load(source interface{}, others ...interface{}) (*File, error) { | ||||||
|  | 	return LoadSources(LoadOptions{}, source, others...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // LooseLoad has exactly same functionality as Load function | ||||||
|  | // except it ignores nonexistent files instead of returning error. | ||||||
|  | func LooseLoad(source interface{}, others ...interface{}) (*File, error) { | ||||||
|  | 	return LoadSources(LoadOptions{Loose: true}, source, others...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InsensitiveLoad has exactly same functionality as Load function | ||||||
|  | // except it forces all section and key names to be lowercased. | ||||||
|  | func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) { | ||||||
|  | 	return LoadSources(LoadOptions{Insensitive: true}, source, others...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ShadowLoad has exactly same functionality as Load function | ||||||
|  | // except it allows have shadow keys. | ||||||
|  | func ShadowLoad(source interface{}, others ...interface{}) (*File, error) { | ||||||
|  | 	return LoadSources(LoadOptions{AllowShadows: true}, source, others...) | ||||||
|  | } | ||||||
							
								
								
									
										837
									
								
								vendor/github.com/go-ini/ini/key.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										837
									
								
								vendor/github.com/go-ini/ini/key.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,837 @@ | ||||||
|  | // Copyright 2014 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Key represents a key under a section. | ||||||
|  | type Key struct { | ||||||
|  | 	s               *Section | ||||||
|  | 	Comment         string | ||||||
|  | 	name            string | ||||||
|  | 	value           string | ||||||
|  | 	isAutoIncrement bool | ||||||
|  | 	isBooleanType   bool | ||||||
|  | 
 | ||||||
|  | 	isShadow bool | ||||||
|  | 	shadows  []*Key | ||||||
|  | 
 | ||||||
|  | 	nestedValues []string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // newKey simply return a key object with given values. | ||||||
|  | func newKey(s *Section, name, val string) *Key { | ||||||
|  | 	return &Key{ | ||||||
|  | 		s:     s, | ||||||
|  | 		name:  name, | ||||||
|  | 		value: val, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (k *Key) addShadow(val string) error { | ||||||
|  | 	if k.isShadow { | ||||||
|  | 		return errors.New("cannot add shadow to another shadow key") | ||||||
|  | 	} else if k.isAutoIncrement || k.isBooleanType { | ||||||
|  | 		return errors.New("cannot add shadow to auto-increment or boolean key") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !k.s.f.options.AllowDuplicateShadowValues { | ||||||
|  | 		// Deduplicate shadows based on their values. | ||||||
|  | 		if k.value == val { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		for i := range k.shadows { | ||||||
|  | 			if k.shadows[i].value == val { | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	shadow := newKey(k.s, k.name, val) | ||||||
|  | 	shadow.isShadow = true | ||||||
|  | 	k.shadows = append(k.shadows, shadow) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddShadow adds a new shadow key to itself. | ||||||
|  | func (k *Key) AddShadow(val string) error { | ||||||
|  | 	if !k.s.f.options.AllowShadows { | ||||||
|  | 		return errors.New("shadow key is not allowed") | ||||||
|  | 	} | ||||||
|  | 	return k.addShadow(val) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (k *Key) addNestedValue(val string) error { | ||||||
|  | 	if k.isAutoIncrement || k.isBooleanType { | ||||||
|  | 		return errors.New("cannot add nested value to auto-increment or boolean key") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	k.nestedValues = append(k.nestedValues, val) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddNestedValue adds a nested value to the key. | ||||||
|  | func (k *Key) AddNestedValue(val string) error { | ||||||
|  | 	if !k.s.f.options.AllowNestedValues { | ||||||
|  | 		return errors.New("nested value is not allowed") | ||||||
|  | 	} | ||||||
|  | 	return k.addNestedValue(val) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValueMapper represents a mapping function for values, e.g. os.ExpandEnv | ||||||
|  | type ValueMapper func(string) string | ||||||
|  | 
 | ||||||
|  | // Name returns name of key. | ||||||
|  | func (k *Key) Name() string { | ||||||
|  | 	return k.name | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Value returns raw value of key for performance purpose. | ||||||
|  | func (k *Key) Value() string { | ||||||
|  | 	return k.value | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValueWithShadows returns raw values of key and its shadows if any. Shadow | ||||||
|  | // keys with empty values are ignored from the returned list. | ||||||
|  | func (k *Key) ValueWithShadows() []string { | ||||||
|  | 	if len(k.shadows) == 0 { | ||||||
|  | 		if k.value == "" { | ||||||
|  | 			return []string{} | ||||||
|  | 		} | ||||||
|  | 		return []string{k.value} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	vals := make([]string, 0, len(k.shadows)+1) | ||||||
|  | 	if k.value != "" { | ||||||
|  | 		vals = append(vals, k.value) | ||||||
|  | 	} | ||||||
|  | 	for _, s := range k.shadows { | ||||||
|  | 		if s.value != "" { | ||||||
|  | 			vals = append(vals, s.value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NestedValues returns nested values stored in the key. | ||||||
|  | // It is possible returned value is nil if no nested values stored in the key. | ||||||
|  | func (k *Key) NestedValues() []string { | ||||||
|  | 	return k.nestedValues | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // transformValue takes a raw value and transforms to its final string. | ||||||
|  | func (k *Key) transformValue(val string) string { | ||||||
|  | 	if k.s.f.ValueMapper != nil { | ||||||
|  | 		val = k.s.f.ValueMapper(val) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Fail-fast if no indicate char found for recursive value | ||||||
|  | 	if !strings.Contains(val, "%") { | ||||||
|  | 		return val | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < depthValues; i++ { | ||||||
|  | 		vr := varPattern.FindString(val) | ||||||
|  | 		if len(vr) == 0 { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Take off leading '%(' and trailing ')s'. | ||||||
|  | 		noption := vr[2 : len(vr)-2] | ||||||
|  | 
 | ||||||
|  | 		// Search in the same section. | ||||||
|  | 		// If not found or found the key itself, then search again in default section. | ||||||
|  | 		nk, err := k.s.GetKey(noption) | ||||||
|  | 		if err != nil || k == nk { | ||||||
|  | 			nk, _ = k.s.f.Section("").GetKey(noption) | ||||||
|  | 			if nk == nil { | ||||||
|  | 				// Stop when no results found in the default section, | ||||||
|  | 				// and returns the value as-is. | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Substitute by new value and take off leading '%(' and trailing ')s'. | ||||||
|  | 		val = strings.Replace(val, vr, nk.value, -1) | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // String returns string representation of value. | ||||||
|  | func (k *Key) String() string { | ||||||
|  | 	return k.transformValue(k.value) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Validate accepts a validate function which can | ||||||
|  | // return modifed result as key value. | ||||||
|  | func (k *Key) Validate(fn func(string) string) string { | ||||||
|  | 	return fn(k.String()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseBool returns the boolean value represented by the string. | ||||||
|  | // | ||||||
|  | // It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On, | ||||||
|  | // 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off. | ||||||
|  | // Any other value returns an error. | ||||||
|  | func parseBool(str string) (value bool, err error) { | ||||||
|  | 	switch str { | ||||||
|  | 	case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On": | ||||||
|  | 		return true, nil | ||||||
|  | 	case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "n", "OFF", "off", "Off": | ||||||
|  | 		return false, nil | ||||||
|  | 	} | ||||||
|  | 	return false, fmt.Errorf("parsing \"%s\": invalid syntax", str) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Bool returns bool type value. | ||||||
|  | func (k *Key) Bool() (bool, error) { | ||||||
|  | 	return parseBool(k.String()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Float64 returns float64 type value. | ||||||
|  | func (k *Key) Float64() (float64, error) { | ||||||
|  | 	return strconv.ParseFloat(k.String(), 64) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Int returns int type value. | ||||||
|  | func (k *Key) Int() (int, error) { | ||||||
|  | 	v, err := strconv.ParseInt(k.String(), 0, 64) | ||||||
|  | 	return int(v), err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Int64 returns int64 type value. | ||||||
|  | func (k *Key) Int64() (int64, error) { | ||||||
|  | 	return strconv.ParseInt(k.String(), 0, 64) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Uint returns uint type valued. | ||||||
|  | func (k *Key) Uint() (uint, error) { | ||||||
|  | 	u, e := strconv.ParseUint(k.String(), 0, 64) | ||||||
|  | 	return uint(u), e | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Uint64 returns uint64 type value. | ||||||
|  | func (k *Key) Uint64() (uint64, error) { | ||||||
|  | 	return strconv.ParseUint(k.String(), 0, 64) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Duration returns time.Duration type value. | ||||||
|  | func (k *Key) Duration() (time.Duration, error) { | ||||||
|  | 	return time.ParseDuration(k.String()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TimeFormat parses with given format and returns time.Time type value. | ||||||
|  | func (k *Key) TimeFormat(format string) (time.Time, error) { | ||||||
|  | 	return time.Parse(format, k.String()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Time parses with RFC3339 format and returns time.Time type value. | ||||||
|  | func (k *Key) Time() (time.Time, error) { | ||||||
|  | 	return k.TimeFormat(time.RFC3339) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustString returns default value if key value is empty. | ||||||
|  | func (k *Key) MustString(defaultVal string) string { | ||||||
|  | 	val := k.String() | ||||||
|  | 	if len(val) == 0 { | ||||||
|  | 		k.value = defaultVal | ||||||
|  | 		return defaultVal | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustBool always returns value without error, | ||||||
|  | // it returns false if error occurs. | ||||||
|  | func (k *Key) MustBool(defaultVal ...bool) bool { | ||||||
|  | 	val, err := k.Bool() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = strconv.FormatBool(defaultVal[0]) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustFloat64 always returns value without error, | ||||||
|  | // it returns 0.0 if error occurs. | ||||||
|  | func (k *Key) MustFloat64(defaultVal ...float64) float64 { | ||||||
|  | 	val, err := k.Float64() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = strconv.FormatFloat(defaultVal[0], 'f', -1, 64) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustInt always returns value without error, | ||||||
|  | // it returns 0 if error occurs. | ||||||
|  | func (k *Key) MustInt(defaultVal ...int) int { | ||||||
|  | 	val, err := k.Int() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = strconv.FormatInt(int64(defaultVal[0]), 10) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustInt64 always returns value without error, | ||||||
|  | // it returns 0 if error occurs. | ||||||
|  | func (k *Key) MustInt64(defaultVal ...int64) int64 { | ||||||
|  | 	val, err := k.Int64() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = strconv.FormatInt(defaultVal[0], 10) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustUint always returns value without error, | ||||||
|  | // it returns 0 if error occurs. | ||||||
|  | func (k *Key) MustUint(defaultVal ...uint) uint { | ||||||
|  | 	val, err := k.Uint() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = strconv.FormatUint(uint64(defaultVal[0]), 10) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustUint64 always returns value without error, | ||||||
|  | // it returns 0 if error occurs. | ||||||
|  | func (k *Key) MustUint64(defaultVal ...uint64) uint64 { | ||||||
|  | 	val, err := k.Uint64() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = strconv.FormatUint(defaultVal[0], 10) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustDuration always returns value without error, | ||||||
|  | // it returns zero value if error occurs. | ||||||
|  | func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration { | ||||||
|  | 	val, err := k.Duration() | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = defaultVal[0].String() | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustTimeFormat always parses with given format and returns value without error, | ||||||
|  | // it returns zero value if error occurs. | ||||||
|  | func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { | ||||||
|  | 	val, err := k.TimeFormat(format) | ||||||
|  | 	if len(defaultVal) > 0 && err != nil { | ||||||
|  | 		k.value = defaultVal[0].Format(format) | ||||||
|  | 		return defaultVal[0] | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MustTime always parses with RFC3339 format and returns value without error, | ||||||
|  | // it returns zero value if error occurs. | ||||||
|  | func (k *Key) MustTime(defaultVal ...time.Time) time.Time { | ||||||
|  | 	return k.MustTimeFormat(time.RFC3339, defaultVal...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // In always returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) In(defaultVal string, candidates []string) string { | ||||||
|  | 	val := k.String() | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InFloat64 always returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { | ||||||
|  | 	val := k.MustFloat64() | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InInt always returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InInt(defaultVal int, candidates []int) int { | ||||||
|  | 	val := k.MustInt() | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InInt64 always returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { | ||||||
|  | 	val := k.MustInt64() | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InUint always returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InUint(defaultVal uint, candidates []uint) uint { | ||||||
|  | 	val := k.MustUint() | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InUint64 always returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 { | ||||||
|  | 	val := k.MustUint64() | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InTimeFormat always parses with given format and returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { | ||||||
|  | 	val := k.MustTimeFormat(format) | ||||||
|  | 	for _, cand := range candidates { | ||||||
|  | 		if val == cand { | ||||||
|  | 			return val | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return defaultVal | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // InTime always parses with RFC3339 format and returns value without error, | ||||||
|  | // it returns default value if error occurs or doesn't fit into candidates. | ||||||
|  | func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { | ||||||
|  | 	return k.InTimeFormat(time.RFC3339, defaultVal, candidates) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RangeFloat64 checks if value is in given range inclusively, | ||||||
|  | // and returns default value if it's not. | ||||||
|  | func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 { | ||||||
|  | 	val := k.MustFloat64() | ||||||
|  | 	if val < min || val > max { | ||||||
|  | 		return defaultVal | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RangeInt checks if value is in given range inclusively, | ||||||
|  | // and returns default value if it's not. | ||||||
|  | func (k *Key) RangeInt(defaultVal, min, max int) int { | ||||||
|  | 	val := k.MustInt() | ||||||
|  | 	if val < min || val > max { | ||||||
|  | 		return defaultVal | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RangeInt64 checks if value is in given range inclusively, | ||||||
|  | // and returns default value if it's not. | ||||||
|  | func (k *Key) RangeInt64(defaultVal, min, max int64) int64 { | ||||||
|  | 	val := k.MustInt64() | ||||||
|  | 	if val < min || val > max { | ||||||
|  | 		return defaultVal | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RangeTimeFormat checks if value with given format is in given range inclusively, | ||||||
|  | // and returns default value if it's not. | ||||||
|  | func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time { | ||||||
|  | 	val := k.MustTimeFormat(format) | ||||||
|  | 	if val.Unix() < min.Unix() || val.Unix() > max.Unix() { | ||||||
|  | 		return defaultVal | ||||||
|  | 	} | ||||||
|  | 	return val | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RangeTime checks if value with RFC3339 format is in given range inclusively, | ||||||
|  | // and returns default value if it's not. | ||||||
|  | func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time { | ||||||
|  | 	return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Strings returns list of string divided by given delimiter. | ||||||
|  | func (k *Key) Strings(delim string) []string { | ||||||
|  | 	str := k.String() | ||||||
|  | 	if len(str) == 0 { | ||||||
|  | 		return []string{} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	runes := []rune(str) | ||||||
|  | 	vals := make([]string, 0, 2) | ||||||
|  | 	var buf bytes.Buffer | ||||||
|  | 	escape := false | ||||||
|  | 	idx := 0 | ||||||
|  | 	for { | ||||||
|  | 		if escape { | ||||||
|  | 			escape = false | ||||||
|  | 			if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) { | ||||||
|  | 				buf.WriteRune('\\') | ||||||
|  | 			} | ||||||
|  | 			buf.WriteRune(runes[idx]) | ||||||
|  | 		} else { | ||||||
|  | 			if runes[idx] == '\\' { | ||||||
|  | 				escape = true | ||||||
|  | 			} else if strings.HasPrefix(string(runes[idx:]), delim) { | ||||||
|  | 				idx += len(delim) - 1 | ||||||
|  | 				vals = append(vals, strings.TrimSpace(buf.String())) | ||||||
|  | 				buf.Reset() | ||||||
|  | 			} else { | ||||||
|  | 				buf.WriteRune(runes[idx]) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		idx++ | ||||||
|  | 		if idx == len(runes) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if buf.Len() > 0 { | ||||||
|  | 		vals = append(vals, strings.TrimSpace(buf.String())) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StringsWithShadows returns list of string divided by given delimiter. | ||||||
|  | // Shadows will also be appended if any. | ||||||
|  | func (k *Key) StringsWithShadows(delim string) []string { | ||||||
|  | 	vals := k.ValueWithShadows() | ||||||
|  | 	results := make([]string, 0, len(vals)*2) | ||||||
|  | 	for i := range vals { | ||||||
|  | 		if len(vals) == 0 { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		results = append(results, strings.Split(vals[i], delim)...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for i := range results { | ||||||
|  | 		results[i] = k.transformValue(strings.TrimSpace(results[i])) | ||||||
|  | 	} | ||||||
|  | 	return results | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value. | ||||||
|  | func (k *Key) Float64s(delim string) []float64 { | ||||||
|  | 	vals, _ := k.parseFloat64s(k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value. | ||||||
|  | func (k *Key) Ints(delim string) []int { | ||||||
|  | 	vals, _ := k.parseInts(k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value. | ||||||
|  | func (k *Key) Int64s(delim string) []int64 { | ||||||
|  | 	vals, _ := k.parseInt64s(k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value. | ||||||
|  | func (k *Key) Uints(delim string) []uint { | ||||||
|  | 	vals, _ := k.parseUints(k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value. | ||||||
|  | func (k *Key) Uint64s(delim string) []uint64 { | ||||||
|  | 	vals, _ := k.parseUint64s(k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Bools returns list of bool divided by given delimiter. Any invalid input will be treated as zero value. | ||||||
|  | func (k *Key) Bools(delim string) []bool { | ||||||
|  | 	vals, _ := k.parseBools(k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TimesFormat parses with given format and returns list of time.Time divided by given delimiter. | ||||||
|  | // Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC). | ||||||
|  | func (k *Key) TimesFormat(format, delim string) []time.Time { | ||||||
|  | 	vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Times parses with RFC3339 format and returns list of time.Time divided by given delimiter. | ||||||
|  | // Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC). | ||||||
|  | func (k *Key) Times(delim string) []time.Time { | ||||||
|  | 	return k.TimesFormat(time.RFC3339, delim) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then | ||||||
|  | // it will not be included to result list. | ||||||
|  | func (k *Key) ValidFloat64s(delim string) []float64 { | ||||||
|  | 	vals, _ := k.parseFloat64s(k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will | ||||||
|  | // not be included to result list. | ||||||
|  | func (k *Key) ValidInts(delim string) []int { | ||||||
|  | 	vals, _ := k.parseInts(k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer, | ||||||
|  | // then it will not be included to result list. | ||||||
|  | func (k *Key) ValidInt64s(delim string) []int64 { | ||||||
|  | 	vals, _ := k.parseInt64s(k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer, | ||||||
|  | // then it will not be included to result list. | ||||||
|  | func (k *Key) ValidUints(delim string) []uint { | ||||||
|  | 	vals, _ := k.parseUints(k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned | ||||||
|  | // integer, then it will not be included to result list. | ||||||
|  | func (k *Key) ValidUint64s(delim string) []uint64 { | ||||||
|  | 	vals, _ := k.parseUint64s(k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidBools returns list of bool divided by given delimiter. If some value is not 64-bit unsigned | ||||||
|  | // integer, then it will not be included to result list. | ||||||
|  | func (k *Key) ValidBools(delim string) []bool { | ||||||
|  | 	vals, _ := k.parseBools(k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter. | ||||||
|  | func (k *Key) ValidTimesFormat(format, delim string) []time.Time { | ||||||
|  | 	vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false) | ||||||
|  | 	return vals | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter. | ||||||
|  | func (k *Key) ValidTimes(delim string) []time.Time { | ||||||
|  | 	return k.ValidTimesFormat(time.RFC3339, delim) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input. | ||||||
|  | func (k *Key) StrictFloat64s(delim string) ([]float64, error) { | ||||||
|  | 	return k.parseFloat64s(k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictInts returns list of int divided by given delimiter or error on first invalid input. | ||||||
|  | func (k *Key) StrictInts(delim string) ([]int, error) { | ||||||
|  | 	return k.parseInts(k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input. | ||||||
|  | func (k *Key) StrictInt64s(delim string) ([]int64, error) { | ||||||
|  | 	return k.parseInt64s(k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictUints returns list of uint divided by given delimiter or error on first invalid input. | ||||||
|  | func (k *Key) StrictUints(delim string) ([]uint, error) { | ||||||
|  | 	return k.parseUints(k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input. | ||||||
|  | func (k *Key) StrictUint64s(delim string) ([]uint64, error) { | ||||||
|  | 	return k.parseUint64s(k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictBools returns list of bool divided by given delimiter or error on first invalid input. | ||||||
|  | func (k *Key) StrictBools(delim string) ([]bool, error) { | ||||||
|  | 	return k.parseBools(k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter | ||||||
|  | // or error on first invalid input. | ||||||
|  | func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) { | ||||||
|  | 	return k.parseTimesFormat(format, k.Strings(delim), false, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter | ||||||
|  | // or error on first invalid input. | ||||||
|  | func (k *Key) StrictTimes(delim string) ([]time.Time, error) { | ||||||
|  | 	return k.StrictTimesFormat(time.RFC3339, delim) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseBools transforms strings to bools. | ||||||
|  | func (k *Key) parseBools(strs []string, addInvalid, returnOnInvalid bool) ([]bool, error) { | ||||||
|  | 	vals := make([]bool, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := parseBool(str) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, val.(bool)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseFloat64s transforms strings to float64s. | ||||||
|  | func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) { | ||||||
|  | 	vals := make([]float64, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := strconv.ParseFloat(str, 64) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, val.(float64)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseInts transforms strings to ints. | ||||||
|  | func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) { | ||||||
|  | 	vals := make([]int, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := strconv.ParseInt(str, 0, 64) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, int(val.(int64))) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseInt64s transforms strings to int64s. | ||||||
|  | func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) { | ||||||
|  | 	vals := make([]int64, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := strconv.ParseInt(str, 0, 64) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, val.(int64)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseUints transforms strings to uints. | ||||||
|  | func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) { | ||||||
|  | 	vals := make([]uint, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := strconv.ParseUint(str, 0, 64) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, uint(val.(uint64))) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parseUint64s transforms strings to uint64s. | ||||||
|  | func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) { | ||||||
|  | 	vals := make([]uint64, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := strconv.ParseUint(str, 0, 64) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, val.(uint64)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Parser func(str string) (interface{}, error) | ||||||
|  | 
 | ||||||
|  | // parseTimesFormat transforms strings to times in given format. | ||||||
|  | func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) { | ||||||
|  | 	vals := make([]time.Time, 0, len(strs)) | ||||||
|  | 	parser := func(str string) (interface{}, error) { | ||||||
|  | 		val, err := time.Parse(format, str) | ||||||
|  | 		return val, err | ||||||
|  | 	} | ||||||
|  | 	rawVals, err := k.doParse(strs, addInvalid, returnOnInvalid, parser) | ||||||
|  | 	if err == nil { | ||||||
|  | 		for _, val := range rawVals { | ||||||
|  | 			vals = append(vals, val.(time.Time)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // doParse transforms strings to different types | ||||||
|  | func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) { | ||||||
|  | 	vals := make([]interface{}, 0, len(strs)) | ||||||
|  | 	for _, str := range strs { | ||||||
|  | 		val, err := parser(str) | ||||||
|  | 		if err != nil && returnOnInvalid { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		if err == nil || addInvalid { | ||||||
|  | 			vals = append(vals, val) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return vals, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetValue changes key value. | ||||||
|  | func (k *Key) SetValue(v string) { | ||||||
|  | 	if k.s.f.BlockMode { | ||||||
|  | 		k.s.f.lock.Lock() | ||||||
|  | 		defer k.s.f.lock.Unlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	k.value = v | ||||||
|  | 	k.s.keysHash[k.name] = v | ||||||
|  | } | ||||||
							
								
								
									
										520
									
								
								vendor/github.com/go-ini/ini/parser.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										520
									
								
								vendor/github.com/go-ini/ini/parser.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,520 @@ | ||||||
|  | // Copyright 2015 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"bytes" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"regexp" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"unicode" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const minReaderBufferSize = 4096 | ||||||
|  | 
 | ||||||
|  | var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`) | ||||||
|  | 
 | ||||||
|  | type parserOptions struct { | ||||||
|  | 	IgnoreContinuation          bool | ||||||
|  | 	IgnoreInlineComment         bool | ||||||
|  | 	AllowPythonMultilineValues  bool | ||||||
|  | 	SpaceBeforeInlineComment    bool | ||||||
|  | 	UnescapeValueDoubleQuotes   bool | ||||||
|  | 	UnescapeValueCommentSymbols bool | ||||||
|  | 	PreserveSurroundedQuote     bool | ||||||
|  | 	DebugFunc                   DebugFunc | ||||||
|  | 	ReaderBufferSize            int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type parser struct { | ||||||
|  | 	buf     *bufio.Reader | ||||||
|  | 	options parserOptions | ||||||
|  | 
 | ||||||
|  | 	isEOF   bool | ||||||
|  | 	count   int | ||||||
|  | 	comment *bytes.Buffer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) debug(format string, args ...interface{}) { | ||||||
|  | 	if p.options.DebugFunc != nil { | ||||||
|  | 		p.options.DebugFunc(fmt.Sprintf(format, args...)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func newParser(r io.Reader, opts parserOptions) *parser { | ||||||
|  | 	size := opts.ReaderBufferSize | ||||||
|  | 	if size < minReaderBufferSize { | ||||||
|  | 		size = minReaderBufferSize | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &parser{ | ||||||
|  | 		buf:     bufio.NewReaderSize(r, size), | ||||||
|  | 		options: opts, | ||||||
|  | 		count:   1, | ||||||
|  | 		comment: &bytes.Buffer{}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format. | ||||||
|  | // http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding | ||||||
|  | func (p *parser) BOM() error { | ||||||
|  | 	mask, err := p.buf.Peek(2) | ||||||
|  | 	if err != nil && err != io.EOF { | ||||||
|  | 		return err | ||||||
|  | 	} else if len(mask) < 2 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch { | ||||||
|  | 	case mask[0] == 254 && mask[1] == 255: | ||||||
|  | 		fallthrough | ||||||
|  | 	case mask[0] == 255 && mask[1] == 254: | ||||||
|  | 		_, err = p.buf.Read(mask) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	case mask[0] == 239 && mask[1] == 187: | ||||||
|  | 		mask, err := p.buf.Peek(3) | ||||||
|  | 		if err != nil && err != io.EOF { | ||||||
|  | 			return err | ||||||
|  | 		} else if len(mask) < 3 { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		if mask[2] == 191 { | ||||||
|  | 			_, err = p.buf.Read(mask) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) readUntil(delim byte) ([]byte, error) { | ||||||
|  | 	data, err := p.buf.ReadBytes(delim) | ||||||
|  | 	if err != nil { | ||||||
|  | 		if err == io.EOF { | ||||||
|  | 			p.isEOF = true | ||||||
|  | 		} else { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return data, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func cleanComment(in []byte) ([]byte, bool) { | ||||||
|  | 	i := bytes.IndexAny(in, "#;") | ||||||
|  | 	if i == -1 { | ||||||
|  | 		return nil, false | ||||||
|  | 	} | ||||||
|  | 	return in[i:], true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func readKeyName(delimiters string, in []byte) (string, int, error) { | ||||||
|  | 	line := string(in) | ||||||
|  | 
 | ||||||
|  | 	// Check if key name surrounded by quotes. | ||||||
|  | 	var keyQuote string | ||||||
|  | 	if line[0] == '"' { | ||||||
|  | 		if len(line) > 6 && line[0:3] == `"""` { | ||||||
|  | 			keyQuote = `"""` | ||||||
|  | 		} else { | ||||||
|  | 			keyQuote = `"` | ||||||
|  | 		} | ||||||
|  | 	} else if line[0] == '`' { | ||||||
|  | 		keyQuote = "`" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Get out key name | ||||||
|  | 	var endIdx int | ||||||
|  | 	if len(keyQuote) > 0 { | ||||||
|  | 		startIdx := len(keyQuote) | ||||||
|  | 		// FIXME: fail case -> """"""name"""=value | ||||||
|  | 		pos := strings.Index(line[startIdx:], keyQuote) | ||||||
|  | 		if pos == -1 { | ||||||
|  | 			return "", -1, fmt.Errorf("missing closing key quote: %s", line) | ||||||
|  | 		} | ||||||
|  | 		pos += startIdx | ||||||
|  | 
 | ||||||
|  | 		// Find key-value delimiter | ||||||
|  | 		i := strings.IndexAny(line[pos+startIdx:], delimiters) | ||||||
|  | 		if i < 0 { | ||||||
|  | 			return "", -1, ErrDelimiterNotFound{line} | ||||||
|  | 		} | ||||||
|  | 		endIdx = pos + i | ||||||
|  | 		return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	endIdx = strings.IndexAny(line, delimiters) | ||||||
|  | 	if endIdx < 0 { | ||||||
|  | 		return "", -1, ErrDelimiterNotFound{line} | ||||||
|  | 	} | ||||||
|  | 	if endIdx == 0 { | ||||||
|  | 		return "", -1, ErrEmptyKeyName{line} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) readMultilines(line, val, valQuote string) (string, error) { | ||||||
|  | 	for { | ||||||
|  | 		data, err := p.readUntil('\n') | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		next := string(data) | ||||||
|  | 
 | ||||||
|  | 		pos := strings.LastIndex(next, valQuote) | ||||||
|  | 		if pos > -1 { | ||||||
|  | 			val += next[:pos] | ||||||
|  | 
 | ||||||
|  | 			comment, has := cleanComment([]byte(next[pos:])) | ||||||
|  | 			if has { | ||||||
|  | 				p.comment.Write(bytes.TrimSpace(comment)) | ||||||
|  | 			} | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		val += next | ||||||
|  | 		if p.isEOF { | ||||||
|  | 			return "", fmt.Errorf("missing closing key quote from %q to %q", line, next) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) readContinuationLines(val string) (string, error) { | ||||||
|  | 	for { | ||||||
|  | 		data, err := p.readUntil('\n') | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		next := strings.TrimSpace(string(data)) | ||||||
|  | 
 | ||||||
|  | 		if len(next) == 0 { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		val += next | ||||||
|  | 		if val[len(val)-1] != '\\' { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		val = val[:len(val)-1] | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // hasSurroundedQuote check if and only if the first and last characters | ||||||
|  | // are quotes \" or \'. | ||||||
|  | // It returns false if any other parts also contain same kind of quotes. | ||||||
|  | func hasSurroundedQuote(in string, quote byte) bool { | ||||||
|  | 	return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote && | ||||||
|  | 		strings.IndexByte(in[1:], quote) == len(in)-2 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) readValue(in []byte, bufferSize int) (string, error) { | ||||||
|  | 
 | ||||||
|  | 	line := strings.TrimLeftFunc(string(in), unicode.IsSpace) | ||||||
|  | 	if len(line) == 0 { | ||||||
|  | 		if p.options.AllowPythonMultilineValues && len(in) > 0 && in[len(in)-1] == '\n' { | ||||||
|  | 			return p.readPythonMultilines(line, bufferSize) | ||||||
|  | 		} | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var valQuote string | ||||||
|  | 	if len(line) > 3 && line[0:3] == `"""` { | ||||||
|  | 		valQuote = `"""` | ||||||
|  | 	} else if line[0] == '`' { | ||||||
|  | 		valQuote = "`" | ||||||
|  | 	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' { | ||||||
|  | 		valQuote = `"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(valQuote) > 0 { | ||||||
|  | 		startIdx := len(valQuote) | ||||||
|  | 		pos := strings.LastIndex(line[startIdx:], valQuote) | ||||||
|  | 		// Check for multi-line value | ||||||
|  | 		if pos == -1 { | ||||||
|  | 			return p.readMultilines(line, line[startIdx:], valQuote) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if p.options.UnescapeValueDoubleQuotes && valQuote == `"` { | ||||||
|  | 			return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil | ||||||
|  | 		} | ||||||
|  | 		return line[startIdx : pos+startIdx], nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lastChar := line[len(line)-1] | ||||||
|  | 	// Won't be able to reach here if value only contains whitespace | ||||||
|  | 	line = strings.TrimSpace(line) | ||||||
|  | 	trimmedLastChar := line[len(line)-1] | ||||||
|  | 
 | ||||||
|  | 	// Check continuation lines when desired | ||||||
|  | 	if !p.options.IgnoreContinuation && trimmedLastChar == '\\' { | ||||||
|  | 		return p.readContinuationLines(line[:len(line)-1]) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check if ignore inline comment | ||||||
|  | 	if !p.options.IgnoreInlineComment { | ||||||
|  | 		var i int | ||||||
|  | 		if p.options.SpaceBeforeInlineComment { | ||||||
|  | 			i = strings.Index(line, " #") | ||||||
|  | 			if i == -1 { | ||||||
|  | 				i = strings.Index(line, " ;") | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		} else { | ||||||
|  | 			i = strings.IndexAny(line, "#;") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if i > -1 { | ||||||
|  | 			p.comment.WriteString(line[i:]) | ||||||
|  | 			line = strings.TrimSpace(line[:i]) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Trim single and double quotes | ||||||
|  | 	if (hasSurroundedQuote(line, '\'') || | ||||||
|  | 		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote { | ||||||
|  | 		line = line[1 : len(line)-1] | ||||||
|  | 	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols { | ||||||
|  | 		line = strings.ReplaceAll(line, `\;`, ";") | ||||||
|  | 		line = strings.ReplaceAll(line, `\#`, "#") | ||||||
|  | 	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' { | ||||||
|  | 		return p.readPythonMultilines(line, bufferSize) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return line, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) { | ||||||
|  | 	parserBufferPeekResult, _ := p.buf.Peek(bufferSize) | ||||||
|  | 	peekBuffer := bytes.NewBuffer(parserBufferPeekResult) | ||||||
|  | 
 | ||||||
|  | 	for { | ||||||
|  | 		peekData, peekErr := peekBuffer.ReadBytes('\n') | ||||||
|  | 		if peekErr != nil && peekErr != io.EOF { | ||||||
|  | 			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr) | ||||||
|  | 			return "", peekErr | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		p.debug("readPythonMultilines: parsing %q", string(peekData)) | ||||||
|  | 
 | ||||||
|  | 		peekMatches := pythonMultiline.FindStringSubmatch(string(peekData)) | ||||||
|  | 		p.debug("readPythonMultilines: matched %d parts", len(peekMatches)) | ||||||
|  | 		for n, v := range peekMatches { | ||||||
|  | 			p.debug("   %d: %q", n, v) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Return if not a Python multiline value. | ||||||
|  | 		if len(peekMatches) != 3 { | ||||||
|  | 			p.debug("readPythonMultilines: end of value, got: %q", line) | ||||||
|  | 			return line, nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Advance the parser reader (buffer) in-sync with the peek buffer. | ||||||
|  | 		_, err := p.buf.Discard(len(peekData)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			p.debug("readPythonMultilines: failed to skip to the end, returning error") | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		line += "\n" + peekMatches[0] | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // parse parses data through an io.Reader. | ||||||
|  | func (f *File) parse(reader io.Reader) (err error) { | ||||||
|  | 	p := newParser(reader, parserOptions{ | ||||||
|  | 		IgnoreContinuation:          f.options.IgnoreContinuation, | ||||||
|  | 		IgnoreInlineComment:         f.options.IgnoreInlineComment, | ||||||
|  | 		AllowPythonMultilineValues:  f.options.AllowPythonMultilineValues, | ||||||
|  | 		SpaceBeforeInlineComment:    f.options.SpaceBeforeInlineComment, | ||||||
|  | 		UnescapeValueDoubleQuotes:   f.options.UnescapeValueDoubleQuotes, | ||||||
|  | 		UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols, | ||||||
|  | 		PreserveSurroundedQuote:     f.options.PreserveSurroundedQuote, | ||||||
|  | 		DebugFunc:                   f.options.DebugFunc, | ||||||
|  | 		ReaderBufferSize:            f.options.ReaderBufferSize, | ||||||
|  | 	}) | ||||||
|  | 	if err = p.BOM(); err != nil { | ||||||
|  | 		return fmt.Errorf("BOM: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Ignore error because default section name is never empty string. | ||||||
|  | 	name := DefaultSection | ||||||
|  | 	if f.options.Insensitive || f.options.InsensitiveSections { | ||||||
|  | 		name = strings.ToLower(DefaultSection) | ||||||
|  | 	} | ||||||
|  | 	section, _ := f.NewSection(name) | ||||||
|  | 
 | ||||||
|  | 	// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key | ||||||
|  | 	var isLastValueEmpty bool | ||||||
|  | 	var lastRegularKey *Key | ||||||
|  | 
 | ||||||
|  | 	var line []byte | ||||||
|  | 	var inUnparseableSection bool | ||||||
|  | 
 | ||||||
|  | 	// NOTE: Iterate and increase `currentPeekSize` until | ||||||
|  | 	// the size of the parser buffer is found. | ||||||
|  | 	// TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`. | ||||||
|  | 	parserBufferSize := 0 | ||||||
|  | 	// NOTE: Peek 4kb at a time. | ||||||
|  | 	currentPeekSize := minReaderBufferSize | ||||||
|  | 
 | ||||||
|  | 	if f.options.AllowPythonMultilineValues { | ||||||
|  | 		for { | ||||||
|  | 			peekBytes, _ := p.buf.Peek(currentPeekSize) | ||||||
|  | 			peekBytesLength := len(peekBytes) | ||||||
|  | 
 | ||||||
|  | 			if parserBufferSize >= peekBytesLength { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			currentPeekSize *= 2 | ||||||
|  | 			parserBufferSize = peekBytesLength | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for !p.isEOF { | ||||||
|  | 		line, err = p.readUntil('\n') | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if f.options.AllowNestedValues && | ||||||
|  | 			isLastValueEmpty && len(line) > 0 { | ||||||
|  | 			if line[0] == ' ' || line[0] == '\t' { | ||||||
|  | 				err = lastRegularKey.addNestedValue(string(bytes.TrimSpace(line))) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		line = bytes.TrimLeftFunc(line, unicode.IsSpace) | ||||||
|  | 		if len(line) == 0 { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Comments | ||||||
|  | 		if line[0] == '#' || line[0] == ';' { | ||||||
|  | 			// Note: we do not care ending line break, | ||||||
|  | 			// it is needed for adding second line, | ||||||
|  | 			// so just clean it once at the end when set to value. | ||||||
|  | 			p.comment.Write(line) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Section | ||||||
|  | 		if line[0] == '[' { | ||||||
|  | 			// Read to the next ']' (TODO: support quoted strings) | ||||||
|  | 			closeIdx := bytes.LastIndexByte(line, ']') | ||||||
|  | 			if closeIdx == -1 { | ||||||
|  | 				return fmt.Errorf("unclosed section: %s", line) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			name := string(line[1:closeIdx]) | ||||||
|  | 			section, err = f.NewSection(name) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			comment, has := cleanComment(line[closeIdx+1:]) | ||||||
|  | 			if has { | ||||||
|  | 				p.comment.Write(comment) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			section.Comment = strings.TrimSpace(p.comment.String()) | ||||||
|  | 
 | ||||||
|  | 			// Reset auto-counter and comments | ||||||
|  | 			p.comment.Reset() | ||||||
|  | 			p.count = 1 | ||||||
|  | 			// Nested values can't span sections | ||||||
|  | 			isLastValueEmpty = false | ||||||
|  | 
 | ||||||
|  | 			inUnparseableSection = false | ||||||
|  | 			for i := range f.options.UnparseableSections { | ||||||
|  | 				if f.options.UnparseableSections[i] == name || | ||||||
|  | 					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) { | ||||||
|  | 					inUnparseableSection = true | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if inUnparseableSection { | ||||||
|  | 			section.isRawSection = true | ||||||
|  | 			section.rawBody += string(line) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line) | ||||||
|  | 		if err != nil { | ||||||
|  | 			switch { | ||||||
|  | 			// Treat as boolean key when desired, and whole line is key name. | ||||||
|  | 			case IsErrDelimiterNotFound(err): | ||||||
|  | 				switch { | ||||||
|  | 				case f.options.AllowBooleanKeys: | ||||||
|  | 					kname, err := p.readValue(line, parserBufferSize) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return err | ||||||
|  | 					} | ||||||
|  | 					key, err := section.NewBooleanKey(kname) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return err | ||||||
|  | 					} | ||||||
|  | 					key.Comment = strings.TrimSpace(p.comment.String()) | ||||||
|  | 					p.comment.Reset() | ||||||
|  | 					continue | ||||||
|  | 
 | ||||||
|  | 				case f.options.SkipUnrecognizableLines: | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 			case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines: | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Auto increment. | ||||||
|  | 		isAutoIncr := false | ||||||
|  | 		if kname == "-" { | ||||||
|  | 			isAutoIncr = true | ||||||
|  | 			kname = "#" + strconv.Itoa(p.count) | ||||||
|  | 			p.count++ | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		value, err := p.readValue(line[offset:], parserBufferSize) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		isLastValueEmpty = len(value) == 0 | ||||||
|  | 
 | ||||||
|  | 		key, err := section.NewKey(kname, value) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		key.isAutoIncrement = isAutoIncr | ||||||
|  | 		key.Comment = strings.TrimSpace(p.comment.String()) | ||||||
|  | 		p.comment.Reset() | ||||||
|  | 		lastRegularKey = key | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										256
									
								
								vendor/github.com/go-ini/ini/section.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								vendor/github.com/go-ini/ini/section.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,256 @@ | ||||||
|  | // Copyright 2014 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Section represents a config section. | ||||||
|  | type Section struct { | ||||||
|  | 	f        *File | ||||||
|  | 	Comment  string | ||||||
|  | 	name     string | ||||||
|  | 	keys     map[string]*Key | ||||||
|  | 	keyList  []string | ||||||
|  | 	keysHash map[string]string | ||||||
|  | 
 | ||||||
|  | 	isRawSection bool | ||||||
|  | 	rawBody      string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func newSection(f *File, name string) *Section { | ||||||
|  | 	return &Section{ | ||||||
|  | 		f:        f, | ||||||
|  | 		name:     name, | ||||||
|  | 		keys:     make(map[string]*Key), | ||||||
|  | 		keyList:  make([]string, 0, 10), | ||||||
|  | 		keysHash: make(map[string]string), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Name returns name of Section. | ||||||
|  | func (s *Section) Name() string { | ||||||
|  | 	return s.name | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Body returns rawBody of Section if the section was marked as unparseable. | ||||||
|  | // It still follows the other rules of the INI format surrounding leading/trailing whitespace. | ||||||
|  | func (s *Section) Body() string { | ||||||
|  | 	return strings.TrimSpace(s.rawBody) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetBody updates body content only if section is raw. | ||||||
|  | func (s *Section) SetBody(body string) { | ||||||
|  | 	if !s.isRawSection { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	s.rawBody = body | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewKey creates a new key to given section. | ||||||
|  | func (s *Section) NewKey(name, val string) (*Key, error) { | ||||||
|  | 	if len(name) == 0 { | ||||||
|  | 		return nil, errors.New("error creating new key: empty key name") | ||||||
|  | 	} else if s.f.options.Insensitive || s.f.options.InsensitiveKeys { | ||||||
|  | 		name = strings.ToLower(name) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if s.f.BlockMode { | ||||||
|  | 		s.f.lock.Lock() | ||||||
|  | 		defer s.f.lock.Unlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if inSlice(name, s.keyList) { | ||||||
|  | 		if s.f.options.AllowShadows { | ||||||
|  | 			if err := s.keys[name].addShadow(val); err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			s.keys[name].value = val | ||||||
|  | 			s.keysHash[name] = val | ||||||
|  | 		} | ||||||
|  | 		return s.keys[name], nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	s.keyList = append(s.keyList, name) | ||||||
|  | 	s.keys[name] = newKey(s, name, val) | ||||||
|  | 	s.keysHash[name] = val | ||||||
|  | 	return s.keys[name], nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewBooleanKey creates a new boolean type key to given section. | ||||||
|  | func (s *Section) NewBooleanKey(name string) (*Key, error) { | ||||||
|  | 	key, err := s.NewKey(name, "true") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	key.isBooleanType = true | ||||||
|  | 	return key, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetKey returns key in section by given name. | ||||||
|  | func (s *Section) GetKey(name string) (*Key, error) { | ||||||
|  | 	if s.f.BlockMode { | ||||||
|  | 		s.f.lock.RLock() | ||||||
|  | 	} | ||||||
|  | 	if s.f.options.Insensitive || s.f.options.InsensitiveKeys { | ||||||
|  | 		name = strings.ToLower(name) | ||||||
|  | 	} | ||||||
|  | 	key := s.keys[name] | ||||||
|  | 	if s.f.BlockMode { | ||||||
|  | 		s.f.lock.RUnlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if key == nil { | ||||||
|  | 		// Check if it is a child-section. | ||||||
|  | 		sname := s.name | ||||||
|  | 		for { | ||||||
|  | 			if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 { | ||||||
|  | 				sname = sname[:i] | ||||||
|  | 				sec, err := s.f.GetSection(sname) | ||||||
|  | 				if err != nil { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 				return sec.GetKey(name) | ||||||
|  | 			} | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name) | ||||||
|  | 	} | ||||||
|  | 	return key, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // HasKey returns true if section contains a key with given name. | ||||||
|  | func (s *Section) HasKey(name string) bool { | ||||||
|  | 	key, _ := s.GetKey(name) | ||||||
|  | 	return key != nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Deprecated: Use "HasKey" instead. | ||||||
|  | func (s *Section) Haskey(name string) bool { | ||||||
|  | 	return s.HasKey(name) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // HasValue returns true if section contains given raw value. | ||||||
|  | func (s *Section) HasValue(value string) bool { | ||||||
|  | 	if s.f.BlockMode { | ||||||
|  | 		s.f.lock.RLock() | ||||||
|  | 		defer s.f.lock.RUnlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, k := range s.keys { | ||||||
|  | 		if value == k.value { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Key assumes named Key exists in section and returns a zero-value when not. | ||||||
|  | func (s *Section) Key(name string) *Key { | ||||||
|  | 	key, err := s.GetKey(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		// It's OK here because the only possible error is empty key name, | ||||||
|  | 		// but if it's empty, this piece of code won't be executed. | ||||||
|  | 		key, _ = s.NewKey(name, "") | ||||||
|  | 		return key | ||||||
|  | 	} | ||||||
|  | 	return key | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Keys returns list of keys of section. | ||||||
|  | func (s *Section) Keys() []*Key { | ||||||
|  | 	keys := make([]*Key, len(s.keyList)) | ||||||
|  | 	for i := range s.keyList { | ||||||
|  | 		keys[i] = s.Key(s.keyList[i]) | ||||||
|  | 	} | ||||||
|  | 	return keys | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ParentKeys returns list of keys of parent section. | ||||||
|  | func (s *Section) ParentKeys() []*Key { | ||||||
|  | 	var parentKeys []*Key | ||||||
|  | 	sname := s.name | ||||||
|  | 	for { | ||||||
|  | 		if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 { | ||||||
|  | 			sname = sname[:i] | ||||||
|  | 			sec, err := s.f.GetSection(sname) | ||||||
|  | 			if err != nil { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			parentKeys = append(parentKeys, sec.Keys()...) | ||||||
|  | 		} else { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 	return parentKeys | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // KeyStrings returns list of key names of section. | ||||||
|  | func (s *Section) KeyStrings() []string { | ||||||
|  | 	list := make([]string, len(s.keyList)) | ||||||
|  | 	copy(list, s.keyList) | ||||||
|  | 	return list | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // KeysHash returns keys hash consisting of names and values. | ||||||
|  | func (s *Section) KeysHash() map[string]string { | ||||||
|  | 	if s.f.BlockMode { | ||||||
|  | 		s.f.lock.RLock() | ||||||
|  | 		defer s.f.lock.RUnlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	hash := make(map[string]string, len(s.keysHash)) | ||||||
|  | 	for key, value := range s.keysHash { | ||||||
|  | 		hash[key] = value | ||||||
|  | 	} | ||||||
|  | 	return hash | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeleteKey deletes a key from section. | ||||||
|  | func (s *Section) DeleteKey(name string) { | ||||||
|  | 	if s.f.BlockMode { | ||||||
|  | 		s.f.lock.Lock() | ||||||
|  | 		defer s.f.lock.Unlock() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for i, k := range s.keyList { | ||||||
|  | 		if k == name { | ||||||
|  | 			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...) | ||||||
|  | 			delete(s.keys, name) | ||||||
|  | 			delete(s.keysHash, name) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ChildSections returns a list of child sections of current section. | ||||||
|  | // For example, "[parent.child1]" and "[parent.child12]" are child sections | ||||||
|  | // of section "[parent]". | ||||||
|  | func (s *Section) ChildSections() []*Section { | ||||||
|  | 	prefix := s.name + s.f.options.ChildSectionDelimiter | ||||||
|  | 	children := make([]*Section, 0, 3) | ||||||
|  | 	for _, name := range s.f.sectionList { | ||||||
|  | 		if strings.HasPrefix(name, prefix) { | ||||||
|  | 			children = append(children, s.f.sections[name]...) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return children | ||||||
|  | } | ||||||
							
								
								
									
										747
									
								
								vendor/github.com/go-ini/ini/struct.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										747
									
								
								vendor/github.com/go-ini/ini/struct.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,747 @@ | ||||||
|  | // Copyright 2014 Unknwon | ||||||
|  | // | ||||||
|  | // 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 ini | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | 	"unicode" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // NameMapper represents a ini tag name mapper. | ||||||
|  | type NameMapper func(string) string | ||||||
|  | 
 | ||||||
|  | // Built-in name getters. | ||||||
|  | var ( | ||||||
|  | 	// SnackCase converts to format SNACK_CASE. | ||||||
|  | 	SnackCase NameMapper = func(raw string) string { | ||||||
|  | 		newstr := make([]rune, 0, len(raw)) | ||||||
|  | 		for i, chr := range raw { | ||||||
|  | 			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { | ||||||
|  | 				if i > 0 { | ||||||
|  | 					newstr = append(newstr, '_') | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			newstr = append(newstr, unicode.ToUpper(chr)) | ||||||
|  | 		} | ||||||
|  | 		return string(newstr) | ||||||
|  | 	} | ||||||
|  | 	// TitleUnderscore converts to format title_underscore. | ||||||
|  | 	TitleUnderscore NameMapper = func(raw string) string { | ||||||
|  | 		newstr := make([]rune, 0, len(raw)) | ||||||
|  | 		for i, chr := range raw { | ||||||
|  | 			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { | ||||||
|  | 				if i > 0 { | ||||||
|  | 					newstr = append(newstr, '_') | ||||||
|  | 				} | ||||||
|  | 				chr -= 'A' - 'a' | ||||||
|  | 			} | ||||||
|  | 			newstr = append(newstr, chr) | ||||||
|  | 		} | ||||||
|  | 		return string(newstr) | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func (s *Section) parseFieldName(raw, actual string) string { | ||||||
|  | 	if len(actual) > 0 { | ||||||
|  | 		return actual | ||||||
|  | 	} | ||||||
|  | 	if s.f.NameMapper != nil { | ||||||
|  | 		return s.f.NameMapper(raw) | ||||||
|  | 	} | ||||||
|  | 	return raw | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseDelim(actual string) string { | ||||||
|  | 	if len(actual) > 0 { | ||||||
|  | 		return actual | ||||||
|  | 	} | ||||||
|  | 	return "," | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var reflectTime = reflect.TypeOf(time.Now()).Kind() | ||||||
|  | 
 | ||||||
|  | // setSliceWithProperType sets proper values to slice based on its type. | ||||||
|  | func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { | ||||||
|  | 	var strs []string | ||||||
|  | 	if allowShadow { | ||||||
|  | 		strs = key.StringsWithShadows(delim) | ||||||
|  | 	} else { | ||||||
|  | 		strs = key.Strings(delim) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	numVals := len(strs) | ||||||
|  | 	if numVals == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var vals interface{} | ||||||
|  | 	var err error | ||||||
|  | 
 | ||||||
|  | 	sliceOf := field.Type().Elem().Kind() | ||||||
|  | 	switch sliceOf { | ||||||
|  | 	case reflect.String: | ||||||
|  | 		vals = strs | ||||||
|  | 	case reflect.Int: | ||||||
|  | 		vals, err = key.parseInts(strs, true, false) | ||||||
|  | 	case reflect.Int64: | ||||||
|  | 		vals, err = key.parseInt64s(strs, true, false) | ||||||
|  | 	case reflect.Uint: | ||||||
|  | 		vals, err = key.parseUints(strs, true, false) | ||||||
|  | 	case reflect.Uint64: | ||||||
|  | 		vals, err = key.parseUint64s(strs, true, false) | ||||||
|  | 	case reflect.Float64: | ||||||
|  | 		vals, err = key.parseFloat64s(strs, true, false) | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		vals, err = key.parseBools(strs, true, false) | ||||||
|  | 	case reflectTime: | ||||||
|  | 		vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false) | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("unsupported type '[]%s'", sliceOf) | ||||||
|  | 	} | ||||||
|  | 	if err != nil && isStrict { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	slice := reflect.MakeSlice(field.Type(), numVals, numVals) | ||||||
|  | 	for i := 0; i < numVals; i++ { | ||||||
|  | 		switch sliceOf { | ||||||
|  | 		case reflect.String: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i])) | ||||||
|  | 		case reflect.Int: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i])) | ||||||
|  | 		case reflect.Int64: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i])) | ||||||
|  | 		case reflect.Uint: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i])) | ||||||
|  | 		case reflect.Uint64: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i])) | ||||||
|  | 		case reflect.Float64: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i])) | ||||||
|  | 		case reflect.Bool: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]bool)[i])) | ||||||
|  | 		case reflectTime: | ||||||
|  | 			slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i])) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	field.Set(slice) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func wrapStrictError(err error, isStrict bool) error { | ||||||
|  | 	if isStrict { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // setWithProperType sets proper value to field based on its type, | ||||||
|  | // but it does not return error for failing parsing, | ||||||
|  | // because we want to use default value that is already assigned to struct. | ||||||
|  | func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { | ||||||
|  | 	vt := t | ||||||
|  | 	isPtr := t.Kind() == reflect.Ptr | ||||||
|  | 	if isPtr { | ||||||
|  | 		vt = t.Elem() | ||||||
|  | 	} | ||||||
|  | 	switch vt.Kind() { | ||||||
|  | 	case reflect.String: | ||||||
|  | 		stringVal := key.String() | ||||||
|  | 		if isPtr { | ||||||
|  | 			field.Set(reflect.ValueOf(&stringVal)) | ||||||
|  | 		} else if len(stringVal) > 0 { | ||||||
|  | 			field.SetString(key.String()) | ||||||
|  | 		} | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		boolVal, err := key.Bool() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return wrapStrictError(err, isStrict) | ||||||
|  | 		} | ||||||
|  | 		if isPtr { | ||||||
|  | 			field.Set(reflect.ValueOf(&boolVal)) | ||||||
|  | 		} else { | ||||||
|  | 			field.SetBool(boolVal) | ||||||
|  | 		} | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		// ParseDuration will not return err for `0`, so check the type name | ||||||
|  | 		if vt.Name() == "Duration" { | ||||||
|  | 			durationVal, err := key.Duration() | ||||||
|  | 			if err != nil { | ||||||
|  | 				if intVal, err := key.Int64(); err == nil { | ||||||
|  | 					field.SetInt(intVal) | ||||||
|  | 					return nil | ||||||
|  | 				} | ||||||
|  | 				return wrapStrictError(err, isStrict) | ||||||
|  | 			} | ||||||
|  | 			if isPtr { | ||||||
|  | 				field.Set(reflect.ValueOf(&durationVal)) | ||||||
|  | 			} else if int64(durationVal) > 0 { | ||||||
|  | 				field.Set(reflect.ValueOf(durationVal)) | ||||||
|  | 			} | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		intVal, err := key.Int64() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return wrapStrictError(err, isStrict) | ||||||
|  | 		} | ||||||
|  | 		if isPtr { | ||||||
|  | 			pv := reflect.New(t.Elem()) | ||||||
|  | 			pv.Elem().SetInt(intVal) | ||||||
|  | 			field.Set(pv) | ||||||
|  | 		} else { | ||||||
|  | 			field.SetInt(intVal) | ||||||
|  | 		} | ||||||
|  | 	//	byte is an alias for uint8, so supporting uint8 breaks support for byte | ||||||
|  | 	case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||||
|  | 		durationVal, err := key.Duration() | ||||||
|  | 		// Skip zero value | ||||||
|  | 		if err == nil && uint64(durationVal) > 0 { | ||||||
|  | 			if isPtr { | ||||||
|  | 				field.Set(reflect.ValueOf(&durationVal)) | ||||||
|  | 			} else { | ||||||
|  | 				field.Set(reflect.ValueOf(durationVal)) | ||||||
|  | 			} | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		uintVal, err := key.Uint64() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return wrapStrictError(err, isStrict) | ||||||
|  | 		} | ||||||
|  | 		if isPtr { | ||||||
|  | 			pv := reflect.New(t.Elem()) | ||||||
|  | 			pv.Elem().SetUint(uintVal) | ||||||
|  | 			field.Set(pv) | ||||||
|  | 		} else { | ||||||
|  | 			field.SetUint(uintVal) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		floatVal, err := key.Float64() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return wrapStrictError(err, isStrict) | ||||||
|  | 		} | ||||||
|  | 		if isPtr { | ||||||
|  | 			pv := reflect.New(t.Elem()) | ||||||
|  | 			pv.Elem().SetFloat(floatVal) | ||||||
|  | 			field.Set(pv) | ||||||
|  | 		} else { | ||||||
|  | 			field.SetFloat(floatVal) | ||||||
|  | 		} | ||||||
|  | 	case reflectTime: | ||||||
|  | 		timeVal, err := key.Time() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return wrapStrictError(err, isStrict) | ||||||
|  | 		} | ||||||
|  | 		if isPtr { | ||||||
|  | 			field.Set(reflect.ValueOf(&timeVal)) | ||||||
|  | 		} else { | ||||||
|  | 			field.Set(reflect.ValueOf(timeVal)) | ||||||
|  | 		} | ||||||
|  | 	case reflect.Slice: | ||||||
|  | 		return setSliceWithProperType(key, field, delim, allowShadow, isStrict) | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("unsupported type %q", t) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) { | ||||||
|  | 	opts := strings.SplitN(tag, ",", 5) | ||||||
|  | 	rawName = opts[0] | ||||||
|  | 	for _, opt := range opts[1:] { | ||||||
|  | 		omitEmpty = omitEmpty || (opt == "omitempty") | ||||||
|  | 		allowShadow = allowShadow || (opt == "allowshadow") | ||||||
|  | 		allowNonUnique = allowNonUnique || (opt == "nonunique") | ||||||
|  | 		extends = extends || (opt == "extends") | ||||||
|  | 	} | ||||||
|  | 	return rawName, omitEmpty, allowShadow, allowNonUnique, extends | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // mapToField maps the given value to the matching field of the given section. | ||||||
|  | // The sectionIndex is the index (if non unique sections are enabled) to which the value should be added. | ||||||
|  | func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error { | ||||||
|  | 	if val.Kind() == reflect.Ptr { | ||||||
|  | 		val = val.Elem() | ||||||
|  | 	} | ||||||
|  | 	typ := val.Type() | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < typ.NumField(); i++ { | ||||||
|  | 		field := val.Field(i) | ||||||
|  | 		tpField := typ.Field(i) | ||||||
|  | 
 | ||||||
|  | 		tag := tpField.Tag.Get("ini") | ||||||
|  | 		if tag == "-" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag) | ||||||
|  | 		fieldName := s.parseFieldName(tpField.Name, rawName) | ||||||
|  | 		if len(fieldName) == 0 || !field.CanSet() { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		isStruct := tpField.Type.Kind() == reflect.Struct | ||||||
|  | 		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct | ||||||
|  | 		isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous | ||||||
|  | 		if isAnonymousPtr { | ||||||
|  | 			field.Set(reflect.New(tpField.Type.Elem())) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) { | ||||||
|  | 			if isStructPtr && field.IsNil() { | ||||||
|  | 				field.Set(reflect.New(tpField.Type.Elem())) | ||||||
|  | 			} | ||||||
|  | 			fieldSection := s | ||||||
|  | 			if rawName != "" { | ||||||
|  | 				sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName | ||||||
|  | 				if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) { | ||||||
|  | 					fieldSection = secs[sectionIndex] | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil { | ||||||
|  | 				return fmt.Errorf("map to field %q: %v", fieldName, err) | ||||||
|  | 			} | ||||||
|  | 		} else if isAnonymousPtr || isStruct || isStructPtr { | ||||||
|  | 			if secs, err := s.f.SectionsByName(fieldName); err == nil { | ||||||
|  | 				if len(secs) <= sectionIndex { | ||||||
|  | 					return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName) | ||||||
|  | 				} | ||||||
|  | 				// Only set the field to non-nil struct value if we have a section for it. | ||||||
|  | 				// Otherwise, we end up with a non-nil struct ptr even though there is no data. | ||||||
|  | 				if isStructPtr && field.IsNil() { | ||||||
|  | 					field.Set(reflect.New(tpField.Type.Elem())) | ||||||
|  | 				} | ||||||
|  | 				if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil { | ||||||
|  | 					return fmt.Errorf("map to field %q: %v", fieldName, err) | ||||||
|  | 				} | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Map non-unique sections | ||||||
|  | 		if allowNonUnique && tpField.Type.Kind() == reflect.Slice { | ||||||
|  | 			newField, err := s.mapToSlice(fieldName, field, isStrict) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("map to slice %q: %v", fieldName, err) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			field.Set(newField) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if key, err := s.GetKey(fieldName); err == nil { | ||||||
|  | 			delim := parseDelim(tpField.Tag.Get("delim")) | ||||||
|  | 			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil { | ||||||
|  | 				return fmt.Errorf("set field %q: %v", fieldName, err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // mapToSlice maps all sections with the same name and returns the new value. | ||||||
|  | // The type of the Value must be a slice. | ||||||
|  | func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) { | ||||||
|  | 	secs, err := s.f.SectionsByName(secName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return reflect.Value{}, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	typ := val.Type().Elem() | ||||||
|  | 	for i, sec := range secs { | ||||||
|  | 		elem := reflect.New(typ) | ||||||
|  | 		if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil { | ||||||
|  | 			return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		val = reflect.Append(val, elem.Elem()) | ||||||
|  | 	} | ||||||
|  | 	return val, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // mapTo maps a section to object v. | ||||||
|  | func (s *Section) mapTo(v interface{}, isStrict bool) error { | ||||||
|  | 	typ := reflect.TypeOf(v) | ||||||
|  | 	val := reflect.ValueOf(v) | ||||||
|  | 	if typ.Kind() == reflect.Ptr { | ||||||
|  | 		typ = typ.Elem() | ||||||
|  | 		val = val.Elem() | ||||||
|  | 	} else { | ||||||
|  | 		return errors.New("not a pointer to a struct") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if typ.Kind() == reflect.Slice { | ||||||
|  | 		newField, err := s.mapToSlice(s.name, val, isStrict) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		val.Set(newField) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return s.mapToField(val, isStrict, 0, s.name) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MapTo maps section to given struct. | ||||||
|  | func (s *Section) MapTo(v interface{}) error { | ||||||
|  | 	return s.mapTo(v, false) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictMapTo maps section to given struct in strict mode, | ||||||
|  | // which returns all possible error including value parsing error. | ||||||
|  | func (s *Section) StrictMapTo(v interface{}) error { | ||||||
|  | 	return s.mapTo(v, true) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MapTo maps file to given struct. | ||||||
|  | func (f *File) MapTo(v interface{}) error { | ||||||
|  | 	return f.Section("").MapTo(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictMapTo maps file to given struct in strict mode, | ||||||
|  | // which returns all possible error including value parsing error. | ||||||
|  | func (f *File) StrictMapTo(v interface{}) error { | ||||||
|  | 	return f.Section("").StrictMapTo(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MapToWithMapper maps data sources to given struct with name mapper. | ||||||
|  | func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { | ||||||
|  | 	cfg, err := Load(source, others...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	cfg.NameMapper = mapper | ||||||
|  | 	return cfg.MapTo(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode, | ||||||
|  | // which returns all possible error including value parsing error. | ||||||
|  | func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error { | ||||||
|  | 	cfg, err := Load(source, others...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	cfg.NameMapper = mapper | ||||||
|  | 	return cfg.StrictMapTo(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // MapTo maps data sources to given struct. | ||||||
|  | func MapTo(v, source interface{}, others ...interface{}) error { | ||||||
|  | 	return MapToWithMapper(v, nil, source, others...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StrictMapTo maps data sources to given struct in strict mode, | ||||||
|  | // which returns all possible error including value parsing error. | ||||||
|  | func StrictMapTo(v, source interface{}, others ...interface{}) error { | ||||||
|  | 	return StrictMapToWithMapper(v, nil, source, others...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // reflectSliceWithProperType does the opposite thing as setSliceWithProperType. | ||||||
|  | func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error { | ||||||
|  | 	slice := field.Slice(0, field.Len()) | ||||||
|  | 	if field.Len() == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	sliceOf := field.Type().Elem().Kind() | ||||||
|  | 
 | ||||||
|  | 	if allowShadow { | ||||||
|  | 		var keyWithShadows *Key | ||||||
|  | 		for i := 0; i < field.Len(); i++ { | ||||||
|  | 			var val string | ||||||
|  | 			switch sliceOf { | ||||||
|  | 			case reflect.String: | ||||||
|  | 				val = slice.Index(i).String() | ||||||
|  | 			case reflect.Int, reflect.Int64: | ||||||
|  | 				val = fmt.Sprint(slice.Index(i).Int()) | ||||||
|  | 			case reflect.Uint, reflect.Uint64: | ||||||
|  | 				val = fmt.Sprint(slice.Index(i).Uint()) | ||||||
|  | 			case reflect.Float64: | ||||||
|  | 				val = fmt.Sprint(slice.Index(i).Float()) | ||||||
|  | 			case reflect.Bool: | ||||||
|  | 				val = fmt.Sprint(slice.Index(i).Bool()) | ||||||
|  | 			case reflectTime: | ||||||
|  | 				val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339) | ||||||
|  | 			default: | ||||||
|  | 				return fmt.Errorf("unsupported type '[]%s'", sliceOf) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if i == 0 { | ||||||
|  | 				keyWithShadows = newKey(key.s, key.name, val) | ||||||
|  | 			} else { | ||||||
|  | 				_ = keyWithShadows.AddShadow(val) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		*key = *keyWithShadows | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var buf bytes.Buffer | ||||||
|  | 	for i := 0; i < field.Len(); i++ { | ||||||
|  | 		switch sliceOf { | ||||||
|  | 		case reflect.String: | ||||||
|  | 			buf.WriteString(slice.Index(i).String()) | ||||||
|  | 		case reflect.Int, reflect.Int64: | ||||||
|  | 			buf.WriteString(fmt.Sprint(slice.Index(i).Int())) | ||||||
|  | 		case reflect.Uint, reflect.Uint64: | ||||||
|  | 			buf.WriteString(fmt.Sprint(slice.Index(i).Uint())) | ||||||
|  | 		case reflect.Float64: | ||||||
|  | 			buf.WriteString(fmt.Sprint(slice.Index(i).Float())) | ||||||
|  | 		case reflect.Bool: | ||||||
|  | 			buf.WriteString(fmt.Sprint(slice.Index(i).Bool())) | ||||||
|  | 		case reflectTime: | ||||||
|  | 			buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339)) | ||||||
|  | 		default: | ||||||
|  | 			return fmt.Errorf("unsupported type '[]%s'", sliceOf) | ||||||
|  | 		} | ||||||
|  | 		buf.WriteString(delim) | ||||||
|  | 	} | ||||||
|  | 	key.SetValue(buf.String()[:buf.Len()-len(delim)]) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // reflectWithProperType does the opposite thing as setWithProperType. | ||||||
|  | func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error { | ||||||
|  | 	switch t.Kind() { | ||||||
|  | 	case reflect.String: | ||||||
|  | 		key.SetValue(field.String()) | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		key.SetValue(fmt.Sprint(field.Bool())) | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		key.SetValue(fmt.Sprint(field.Int())) | ||||||
|  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||||
|  | 		key.SetValue(fmt.Sprint(field.Uint())) | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		key.SetValue(fmt.Sprint(field.Float())) | ||||||
|  | 	case reflectTime: | ||||||
|  | 		key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339))) | ||||||
|  | 	case reflect.Slice: | ||||||
|  | 		return reflectSliceWithProperType(key, field, delim, allowShadow) | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		if !field.IsNil() { | ||||||
|  | 			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow) | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("unsupported type %q", t) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // CR: copied from encoding/json/encode.go with modifications of time.Time support. | ||||||
|  | // TODO: add more test coverage. | ||||||
|  | func isEmptyValue(v reflect.Value) bool { | ||||||
|  | 	switch v.Kind() { | ||||||
|  | 	case reflect.Array, reflect.Map, reflect.Slice, reflect.String: | ||||||
|  | 		return v.Len() == 0 | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		return !v.Bool() | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		return v.Int() == 0 | ||||||
|  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||||||
|  | 		return v.Uint() == 0 | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		return v.Float() == 0 | ||||||
|  | 	case reflect.Interface, reflect.Ptr: | ||||||
|  | 		return v.IsNil() | ||||||
|  | 	case reflectTime: | ||||||
|  | 		t, ok := v.Interface().(time.Time) | ||||||
|  | 		return ok && t.IsZero() | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // StructReflector is the interface implemented by struct types that can extract themselves into INI objects. | ||||||
|  | type StructReflector interface { | ||||||
|  | 	ReflectINIStruct(*File) error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *Section) reflectFrom(val reflect.Value) error { | ||||||
|  | 	if val.Kind() == reflect.Ptr { | ||||||
|  | 		val = val.Elem() | ||||||
|  | 	} | ||||||
|  | 	typ := val.Type() | ||||||
|  | 
 | ||||||
|  | 	for i := 0; i < typ.NumField(); i++ { | ||||||
|  | 		if !val.Field(i).CanInterface() { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		field := val.Field(i) | ||||||
|  | 		tpField := typ.Field(i) | ||||||
|  | 
 | ||||||
|  | 		tag := tpField.Tag.Get("ini") | ||||||
|  | 		if tag == "-" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag) | ||||||
|  | 		if omitEmpty && isEmptyValue(field) { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if r, ok := field.Interface().(StructReflector); ok { | ||||||
|  | 			return r.ReflectINIStruct(s.f) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fieldName := s.parseFieldName(tpField.Name, rawName) | ||||||
|  | 		if len(fieldName) == 0 || !field.CanSet() { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) { | ||||||
|  | 			if err := s.reflectFrom(field); err != nil { | ||||||
|  | 				return fmt.Errorf("reflect from field %q: %v", fieldName, err) | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) || | ||||||
|  | 			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") { | ||||||
|  | 			// Note: The only error here is section doesn't exist. | ||||||
|  | 			sec, err := s.f.GetSection(fieldName) | ||||||
|  | 			if err != nil { | ||||||
|  | 				// Note: fieldName can never be empty here, ignore error. | ||||||
|  | 				sec, _ = s.f.NewSection(fieldName) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Add comment from comment tag | ||||||
|  | 			if len(sec.Comment) == 0 { | ||||||
|  | 				sec.Comment = tpField.Tag.Get("comment") | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if err = sec.reflectFrom(field); err != nil { | ||||||
|  | 				return fmt.Errorf("reflect from field %q: %v", fieldName, err) | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if allowNonUnique && tpField.Type.Kind() == reflect.Slice { | ||||||
|  | 			slice := field.Slice(0, field.Len()) | ||||||
|  | 			if field.Len() == 0 { | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
|  | 			sliceOf := field.Type().Elem().Kind() | ||||||
|  | 
 | ||||||
|  | 			for i := 0; i < field.Len(); i++ { | ||||||
|  | 				if sliceOf != reflect.Struct && sliceOf != reflect.Ptr { | ||||||
|  | 					return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				sec, err := s.f.NewSection(fieldName) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Add comment from comment tag | ||||||
|  | 				if len(sec.Comment) == 0 { | ||||||
|  | 					sec.Comment = tpField.Tag.Get("comment") | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if err := sec.reflectFrom(slice.Index(i)); err != nil { | ||||||
|  | 					return fmt.Errorf("reflect from field %q: %v", fieldName, err) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Note: Same reason as section. | ||||||
|  | 		key, err := s.GetKey(fieldName) | ||||||
|  | 		if err != nil { | ||||||
|  | 			key, _ = s.NewKey(fieldName, "") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Add comment from comment tag | ||||||
|  | 		if len(key.Comment) == 0 { | ||||||
|  | 			key.Comment = tpField.Tag.Get("comment") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		delim := parseDelim(tpField.Tag.Get("delim")) | ||||||
|  | 		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil { | ||||||
|  | 			return fmt.Errorf("reflect field %q: %v", fieldName, err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ReflectFrom reflects section from given struct. It overwrites existing ones. | ||||||
|  | func (s *Section) ReflectFrom(v interface{}) error { | ||||||
|  | 	typ := reflect.TypeOf(v) | ||||||
|  | 	val := reflect.ValueOf(v) | ||||||
|  | 
 | ||||||
|  | 	if s.name != DefaultSection && s.f.options.AllowNonUniqueSections && | ||||||
|  | 		(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) { | ||||||
|  | 		// Clear sections to make sure none exists before adding the new ones | ||||||
|  | 		s.f.DeleteSection(s.name) | ||||||
|  | 
 | ||||||
|  | 		if typ.Kind() == reflect.Ptr { | ||||||
|  | 			sec, err := s.f.NewSection(s.name) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			return sec.reflectFrom(val.Elem()) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		slice := val.Slice(0, val.Len()) | ||||||
|  | 		sliceOf := val.Type().Elem().Kind() | ||||||
|  | 		if sliceOf != reflect.Ptr { | ||||||
|  | 			return fmt.Errorf("not a slice of pointers") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for i := 0; i < slice.Len(); i++ { | ||||||
|  | 			sec, err := s.f.NewSection(s.name) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			err = sec.reflectFrom(slice.Index(i)) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("reflect from %dth field: %v", i, err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if typ.Kind() == reflect.Ptr { | ||||||
|  | 		val = val.Elem() | ||||||
|  | 	} else { | ||||||
|  | 		return errors.New("not a pointer to a struct") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return s.reflectFrom(val) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ReflectFrom reflects file from given struct. | ||||||
|  | func (f *File) ReflectFrom(v interface{}) error { | ||||||
|  | 	return f.Section("").ReflectFrom(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ReflectFromWithMapper reflects data sources from given struct with name mapper. | ||||||
|  | func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error { | ||||||
|  | 	cfg.NameMapper = mapper | ||||||
|  | 	return cfg.ReflectFrom(v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ReflectFrom reflects data sources from given struct. | ||||||
|  | func ReflectFrom(cfg *File, v interface{}) error { | ||||||
|  | 	return ReflectFromWithMapper(cfg, v, nil) | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								vendor/github.com/goccy/go-json/.golangci.yml
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/goccy/go-json/.golangci.yml
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -56,6 +56,9 @@ linters: | ||||||
|     - cyclop |     - cyclop | ||||||
|     - containedctx |     - containedctx | ||||||
|     - revive |     - revive | ||||||
|  |     - nosnakecase | ||||||
|  |     - exhaustruct | ||||||
|  |     - depguard | ||||||
| 
 | 
 | ||||||
| issues: | issues: | ||||||
|   exclude-rules: |   exclude-rules: | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/goccy/go-json/Makefile
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/goccy/go-json/Makefile
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -30,7 +30,7 @@ golangci-lint: | $(BIN_DIR) | ||||||
| 		GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
 | 		GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
 | ||||||
| 		cd $$GOLANGCI_LINT_TMP_DIR; \
 | 		cd $$GOLANGCI_LINT_TMP_DIR; \
 | ||||||
| 		go mod init tmp; \
 | 		go mod init tmp; \
 | ||||||
| 		GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0; \
 | 		GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2; \
 | ||||||
| 		rm -rf $$GOLANGCI_LINT_TMP_DIR; \
 | 		rm -rf $$GOLANGCI_LINT_TMP_DIR; \
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								vendor/github.com/goccy/go-json/encode.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/goccy/go-json/encode.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -52,7 +52,7 @@ func (e *Encoder) EncodeContext(ctx context.Context, v interface{}, optFuncs ... | ||||||
| 	rctx.Option.Flag |= encoder.ContextOption | 	rctx.Option.Flag |= encoder.ContextOption | ||||||
| 	rctx.Option.Context = ctx | 	rctx.Option.Context = ctx | ||||||
| 
 | 
 | ||||||
| 	err := e.encodeWithOption(rctx, v, optFuncs...) | 	err := e.encodeWithOption(rctx, v, optFuncs...) //nolint: contextcheck | ||||||
| 
 | 
 | ||||||
| 	encoder.ReleaseRuntimeContext(rctx) | 	encoder.ReleaseRuntimeContext(rctx) | ||||||
| 	return err | 	return err | ||||||
|  | @ -120,7 +120,7 @@ func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOption | ||||||
| 		optFunc(rctx.Option) | 		optFunc(rctx.Option) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	buf, err := encode(rctx, v) | 	buf, err := encode(rctx, v) //nolint: contextcheck | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		encoder.ReleaseRuntimeContext(rctx) | 		encoder.ReleaseRuntimeContext(rctx) | ||||||
| 		return nil, err | 		return nil, err | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								vendor/github.com/goccy/go-json/internal/decoder/ptr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/goccy/go-json/internal/decoder/ptr.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -85,6 +85,7 @@ func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P | ||||||
| 	} | 	} | ||||||
| 	c, err := d.dec.Decode(ctx, cursor, depth, newptr) | 	c, err := d.dec.Decode(ctx, cursor, depth, newptr) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | 		*(*unsafe.Pointer)(p) = nil | ||||||
| 		return 0, err | 		return 0, err | ||||||
| 	} | 	} | ||||||
| 	cursor = c | 	cursor = c | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -147,7 +147,7 @@ func (d *unmarshalTextDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int | ||||||
| 	return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path") | 	return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func unquoteBytes(s []byte) (t []byte, ok bool) { | func unquoteBytes(s []byte) (t []byte, ok bool) { //nolint: nonamedreturns | ||||||
| 	length := len(s) | 	length := len(s) | ||||||
| 	if length < 2 || s[0] != '"' || s[length-1] != '"' { | 	if length < 2 || s[0] != '"' || s[length-1] != '"' { | ||||||
| 		return | 		return | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/goccy/go-json/internal/encoder/compact.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/goccy/go-json/internal/encoder/compact.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -213,8 +213,8 @@ func compactString(dst, src []byte, cursor int64, escape bool) ([]byte, int64, e | ||||||
| 				dst = append(dst, src[start:cursor]...) | 				dst = append(dst, src[start:cursor]...) | ||||||
| 				dst = append(dst, `\u202`...) | 				dst = append(dst, `\u202`...) | ||||||
| 				dst = append(dst, hex[src[cursor+2]&0xF]) | 				dst = append(dst, hex[src[cursor+2]&0xF]) | ||||||
| 				cursor += 2 |  | ||||||
| 				start = cursor + 3 | 				start = cursor + 3 | ||||||
|  | 				cursor += 2 | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		switch c { | 		switch c { | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/goccy/go-json/internal/encoder/compiler.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/goccy/go-json/internal/encoder/compiler.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -480,7 +480,7 @@ func (c *Compiler) mapCode(typ *runtime.Type) (*MapCode, error) { | ||||||
| 
 | 
 | ||||||
| func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) { | func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) { | ||||||
| 	switch { | 	switch { | ||||||
| 	case c.isPtrMarshalJSONType(typ): | 	case c.implementsMarshalJSONType(typ) || c.implementsMarshalJSONType(runtime.PtrTo(typ)): | ||||||
| 		return c.marshalJSONCode(typ) | 		return c.marshalJSONCode(typ) | ||||||
| 	case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType): | 	case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType): | ||||||
| 		return c.marshalTextCode(typ) | 		return c.marshalTextCode(typ) | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								vendor/github.com/goccy/go-json/internal/encoder/int.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/goccy/go-json/internal/encoder/int.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,27 @@ | ||||||
|  | // This files's processing codes are inspired by https://github.com/segmentio/encoding. | ||||||
|  | // The license notation is as follows. | ||||||
|  | // | ||||||
|  | // # MIT License | ||||||
|  | // | ||||||
|  | // Copyright (c) 2019 Segment.io, Inc. | ||||||
|  | // | ||||||
|  | // 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. | ||||||
| package encoder | package encoder | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								vendor/github.com/goccy/go-json/internal/encoder/string.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/goccy/go-json/internal/encoder/string.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,27 @@ | ||||||
|  | // This files's string processing codes are inspired by https://github.com/segmentio/encoding. | ||||||
|  | // The license notation is as follows. | ||||||
|  | // | ||||||
|  | // # MIT License | ||||||
|  | // | ||||||
|  | // Copyright (c) 2019 Segment.io, Inc. | ||||||
|  | // | ||||||
|  | // 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. | ||||||
| package encoder | package encoder | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								vendor/github.com/goccy/go-json/internal/runtime/rtype.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/goccy/go-json/internal/runtime/rtype.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -252,7 +252,6 @@ func IfaceIndir(*Type) bool | ||||||
| //go:noescape | //go:noescape | ||||||
| func RType2Type(t *Type) reflect.Type | func RType2Type(t *Type) reflect.Type | ||||||
| 
 | 
 | ||||||
| //go:nolint structcheck |  | ||||||
| type emptyInterface struct { | type emptyInterface struct { | ||||||
| 	_   *Type | 	_   *Type | ||||||
| 	ptr unsafe.Pointer | 	ptr unsafe.Pointer | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								vendor/github.com/goccy/go-json/json.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/goccy/go-json/json.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -166,7 +166,6 @@ type UnmarshalerContext interface { | ||||||
| // JSON cannot represent cyclic data structures and Marshal does not | // JSON cannot represent cyclic data structures and Marshal does not | ||||||
| // handle them. Passing cyclic structures to Marshal will result in | // handle them. Passing cyclic structures to Marshal will result in | ||||||
| // an infinite recursion. | // an infinite recursion. | ||||||
| // |  | ||||||
| func Marshal(v interface{}) ([]byte, error) { | func Marshal(v interface{}) ([]byte, error) { | ||||||
| 	return MarshalWithOption(v) | 	return MarshalWithOption(v) | ||||||
| } | } | ||||||
|  | @ -264,14 +263,13 @@ func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...E | ||||||
| // | // | ||||||
| // The JSON null value unmarshals into an interface, map, pointer, or slice | // The JSON null value unmarshals into an interface, map, pointer, or slice | ||||||
| // by setting that Go value to nil. Because null is often used in JSON to mean | // by setting that Go value to nil. Because null is often used in JSON to mean | ||||||
| // ``not present,'' unmarshaling a JSON null into any other Go type has no effect | // “not present,” unmarshaling a JSON null into any other Go type has no effect | ||||||
| // on the value and produces no error. | // on the value and produces no error. | ||||||
| // | // | ||||||
| // When unmarshaling quoted strings, invalid UTF-8 or | // When unmarshaling quoted strings, invalid UTF-8 or | ||||||
| // invalid UTF-16 surrogate pairs are not treated as an error. | // invalid UTF-16 surrogate pairs are not treated as an error. | ||||||
| // Instead, they are replaced by the Unicode replacement | // Instead, they are replaced by the Unicode replacement | ||||||
| // character U+FFFD. | // character U+FFFD. | ||||||
| // |  | ||||||
| func Unmarshal(data []byte, v interface{}) error { | func Unmarshal(data []byte, v interface{}) error { | ||||||
| 	return unmarshal(data, v) | 	return unmarshal(data, v) | ||||||
| } | } | ||||||
|  | @ -299,7 +297,6 @@ func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) | ||||||
| //	Number, for JSON numbers | //	Number, for JSON numbers | ||||||
| //	string, for JSON string literals | //	string, for JSON string literals | ||||||
| //	nil, for JSON null | //	nil, for JSON null | ||||||
| // |  | ||||||
| type Token = json.Token | type Token = json.Token | ||||||
| 
 | 
 | ||||||
| // A Number represents a JSON number literal. | // A Number represents a JSON number literal. | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/klauspost/compress/s2/decode_arm64.s
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/klauspost/compress/s2/decode_arm64.s
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -60,7 +60,7 @@ | ||||||
| // | // | ||||||
| // The d variable is implicitly R_DST - R_DBASE,  and len(dst)-d is R_DEND - R_DST. | // The d variable is implicitly R_DST - R_DBASE,  and len(dst)-d is R_DEND - R_DST. | ||||||
| // The s variable is implicitly R_SRC - R_SBASE, and len(src)-s is R_SEND - R_SRC. | // The s variable is implicitly R_SRC - R_SBASE, and len(src)-s is R_SEND - R_SRC. | ||||||
| TEXT ·s2Decode(SB), NOSPLIT, $56-64 | TEXT ·s2Decode(SB), NOSPLIT, $56-56 | ||||||
| 	// Initialize R_SRC, R_DST and R_DBASE-R_SEND. | 	// Initialize R_SRC, R_DST and R_DBASE-R_SEND. | ||||||
| 	MOVD dst_base+0(FP), R_DBASE | 	MOVD dst_base+0(FP), R_DBASE | ||||||
| 	MOVD dst_len+8(FP), R_DLEN | 	MOVD dst_len+8(FP), R_DLEN | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								vendor/github.com/klauspost/compress/s2/index.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/klauspost/compress/s2/index.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -17,6 +17,8 @@ const ( | ||||||
| 	S2IndexHeader   = "s2idx\x00" | 	S2IndexHeader   = "s2idx\x00" | ||||||
| 	S2IndexTrailer  = "\x00xdi2s" | 	S2IndexTrailer  = "\x00xdi2s" | ||||||
| 	maxIndexEntries = 1 << 16 | 	maxIndexEntries = 1 << 16 | ||||||
|  | 	// If distance is less than this, we do not add the entry. | ||||||
|  | 	minIndexDist = 1 << 20 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Index represents an S2/Snappy index. | // Index represents an S2/Snappy index. | ||||||
|  | @ -72,6 +74,10 @@ func (i *Index) add(compressedOffset, uncompressedOffset int64) error { | ||||||
| 		if latest.compressedOffset > compressedOffset { | 		if latest.compressedOffset > compressedOffset { | ||||||
| 			return fmt.Errorf("internal error: Earlier compressed received (%d > %d)", latest.uncompressedOffset, uncompressedOffset) | 			return fmt.Errorf("internal error: Earlier compressed received (%d > %d)", latest.uncompressedOffset, uncompressedOffset) | ||||||
| 		} | 		} | ||||||
|  | 		if latest.uncompressedOffset+minIndexDist > uncompressedOffset { | ||||||
|  | 			// Only add entry if distance is large enough. | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	i.info = append(i.info, struct { | 	i.info = append(i.info, struct { | ||||||
| 		compressedOffset   int64 | 		compressedOffset   int64 | ||||||
|  | @ -122,7 +128,7 @@ func (i *Index) Find(offset int64) (compressedOff, uncompressedOff int64, err er | ||||||
| 
 | 
 | ||||||
| // reduce to stay below maxIndexEntries | // reduce to stay below maxIndexEntries | ||||||
| func (i *Index) reduce() { | func (i *Index) reduce() { | ||||||
| 	if len(i.info) < maxIndexEntries && i.estBlockUncomp >= 1<<20 { | 	if len(i.info) < maxIndexEntries && i.estBlockUncomp >= minIndexDist { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -132,7 +138,7 @@ func (i *Index) reduce() { | ||||||
| 	j := 0 | 	j := 0 | ||||||
| 
 | 
 | ||||||
| 	// Each block should be at least 1MB, but don't reduce below 1000 entries. | 	// Each block should be at least 1MB, but don't reduce below 1000 entries. | ||||||
| 	for i.estBlockUncomp*(int64(removeN)+1) < 1<<20 && len(i.info)/(removeN+1) > 1000 { | 	for i.estBlockUncomp*(int64(removeN)+1) < minIndexDist && len(i.info)/(removeN+1) > 1000 { | ||||||
| 		removeN++ | 		removeN++ | ||||||
| 	} | 	} | ||||||
| 	for idx := 0; idx < len(src); idx++ { | 	for idx := 0; idx < len(src); idx++ { | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								vendor/github.com/klauspost/compress/s2/s2.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/klauspost/compress/s2/s2.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -109,7 +109,11 @@ const ( | ||||||
| 	chunkTypeStreamIdentifier = 0xff | 	chunkTypeStreamIdentifier = 0xff | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var crcTable = crc32.MakeTable(crc32.Castagnoli) | var ( | ||||||
|  | 	crcTable              = crc32.MakeTable(crc32.Castagnoli) | ||||||
|  | 	magicChunkSnappyBytes = []byte(magicChunkSnappy) // Can be passed to functions where it escapes. | ||||||
|  | 	magicChunkBytes       = []byte(magicChunk)       // Can be passed to functions where it escapes. | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // crc implements the checksum specified in section 3 of | // crc implements the checksum specified in section 3 of | ||||||
| // https://github.com/google/snappy/blob/master/framing_format.txt | // https://github.com/google/snappy/blob/master/framing_format.txt | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								vendor/github.com/klauspost/compress/s2/writer.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/klauspost/compress/s2/writer.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -239,6 +239,9 @@ func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if n2 == 0 { | 		if n2 == 0 { | ||||||
|  | 			if cap(inbuf) >= w.obufLen { | ||||||
|  | 				w.buffers.Put(inbuf) | ||||||
|  | 			} | ||||||
| 			break | 			break | ||||||
| 		} | 		} | ||||||
| 		n += int64(n2) | 		n += int64(n2) | ||||||
|  | @ -314,9 +317,9 @@ func (w *Writer) AddSkippableBlock(id uint8, data []byte) (err error) { | ||||||
| 		hWriter := make(chan result) | 		hWriter := make(chan result) | ||||||
| 		w.output <- hWriter | 		w.output <- hWriter | ||||||
| 		if w.snappy { | 		if w.snappy { | ||||||
| 			hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunkSnappy)} | 			hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} | ||||||
| 		} else { | 		} else { | ||||||
| 			hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunk)} | 			hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -370,9 +373,9 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) { | ||||||
| 		hWriter := make(chan result) | 		hWriter := make(chan result) | ||||||
| 		w.output <- hWriter | 		w.output <- hWriter | ||||||
| 		if w.snappy { | 		if w.snappy { | ||||||
| 			hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunkSnappy)} | 			hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} | ||||||
| 		} else { | 		} else { | ||||||
| 			hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunk)} | 			hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -478,9 +481,9 @@ func (w *Writer) write(p []byte) (nRet int, errRet error) { | ||||||
| 			hWriter := make(chan result) | 			hWriter := make(chan result) | ||||||
| 			w.output <- hWriter | 			w.output <- hWriter | ||||||
| 			if w.snappy { | 			if w.snappy { | ||||||
| 				hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunkSnappy)} | 				hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} | ||||||
| 			} else { | 			} else { | ||||||
| 				hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunk)} | 				hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -560,6 +563,9 @@ func (w *Writer) writeFull(inbuf []byte) (errRet error) { | ||||||
| 
 | 
 | ||||||
| 	if w.concurrency == 1 { | 	if w.concurrency == 1 { | ||||||
| 		_, err := w.writeSync(inbuf[obufHeaderLen:]) | 		_, err := w.writeSync(inbuf[obufHeaderLen:]) | ||||||
|  | 		if cap(inbuf) >= w.obufLen { | ||||||
|  | 			w.buffers.Put(inbuf) | ||||||
|  | 		} | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -569,9 +575,9 @@ func (w *Writer) writeFull(inbuf []byte) (errRet error) { | ||||||
| 		hWriter := make(chan result) | 		hWriter := make(chan result) | ||||||
| 		w.output <- hWriter | 		w.output <- hWriter | ||||||
| 		if w.snappy { | 		if w.snappy { | ||||||
| 			hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunkSnappy)} | 			hWriter <- result{startOffset: w.uncompWritten, b: magicChunkSnappyBytes} | ||||||
| 		} else { | 		} else { | ||||||
| 			hWriter <- result{startOffset: w.uncompWritten, b: []byte(magicChunk)} | 			hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -637,9 +643,9 @@ func (w *Writer) writeSync(p []byte) (nRet int, errRet error) { | ||||||
| 		var n int | 		var n int | ||||||
| 		var err error | 		var err error | ||||||
| 		if w.snappy { | 		if w.snappy { | ||||||
| 			n, err = w.writer.Write([]byte(magicChunkSnappy)) | 			n, err = w.writer.Write(magicChunkSnappyBytes) | ||||||
| 		} else { | 		} else { | ||||||
| 			n, err = w.writer.Write([]byte(magicChunk)) | 			n, err = w.writer.Write(magicChunkBytes) | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return 0, w.err(err) | 			return 0, w.err(err) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								vendor/github.com/klauspost/cpuid/v2/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/klauspost/cpuid/v2/README.md
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -310,6 +310,7 @@ Exit Code 1 | ||||||
| | AVXSLOW            | Indicates the CPU performs 2 128 bit operations instead of one                                                                                                                     | | | AVXSLOW            | Indicates the CPU performs 2 128 bit operations instead of one                                                                                                                     | | ||||||
| | AVXVNNI            | AVX (VEX encoded) VNNI neural network instructions                                                                                                                                 | | | AVXVNNI            | AVX (VEX encoded) VNNI neural network instructions                                                                                                                                 | | ||||||
| | AVXVNNIINT8        | AVX-VNNI-INT8 instructions                                                                                                                                                         | | | AVXVNNIINT8        | AVX-VNNI-INT8 instructions                                                                                                                                                         | | ||||||
|  | | AVXVNNIINT16       | AVX-VNNI-INT16 instructions                                                                                                                                                        | | ||||||
| | BHI_CTRL           | Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598                                                                    | | | BHI_CTRL           | Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598                                                                    | | ||||||
| | BMI1               | Bit Manipulation Instruction Set 1                                                                                                                                                 | | | BMI1               | Bit Manipulation Instruction Set 1                                                                                                                                                 | | ||||||
| | BMI2               | Bit Manipulation Instruction Set 2                                                                                                                                                 | | | BMI2               | Bit Manipulation Instruction Set 2                                                                                                                                                 | | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/klauspost/cpuid/v2/cpuid.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/klauspost/cpuid/v2/cpuid.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -104,6 +104,7 @@ const ( | ||||||
| 	AVXSLOW                              // Indicates the CPU performs 2 128 bit operations instead of one | 	AVXSLOW                              // Indicates the CPU performs 2 128 bit operations instead of one | ||||||
| 	AVXVNNI                              // AVX (VEX encoded) VNNI neural network instructions | 	AVXVNNI                              // AVX (VEX encoded) VNNI neural network instructions | ||||||
| 	AVXVNNIINT8                          // AVX-VNNI-INT8 instructions | 	AVXVNNIINT8                          // AVX-VNNI-INT8 instructions | ||||||
|  | 	AVXVNNIINT16                         // AVX-VNNI-INT16 instructions | ||||||
| 	BHI_CTRL                             // Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598 | 	BHI_CTRL                             // Branch History Injection and Intra-mode Branch Target Injection / CVE-2022-0001, CVE-2022-0002 / INTEL-SA-00598 | ||||||
| 	BMI1                                 // Bit Manipulation Instruction Set 1 | 	BMI1                                 // Bit Manipulation Instruction Set 1 | ||||||
| 	BMI2                                 // Bit Manipulation Instruction Set 2 | 	BMI2                                 // Bit Manipulation Instruction Set 2 | ||||||
|  | @ -1242,6 +1243,7 @@ func support() flagSet { | ||||||
| 		// CPUID.(EAX=7, ECX=1).EDX | 		// CPUID.(EAX=7, ECX=1).EDX | ||||||
| 		fs.setIf(edx1&(1<<4) != 0, AVXVNNIINT8) | 		fs.setIf(edx1&(1<<4) != 0, AVXVNNIINT8) | ||||||
| 		fs.setIf(edx1&(1<<5) != 0, AVXNECONVERT) | 		fs.setIf(edx1&(1<<5) != 0, AVXNECONVERT) | ||||||
|  | 		fs.setIf(edx1&(1<<10) != 0, AVXVNNIINT16) | ||||||
| 		fs.setIf(edx1&(1<<14) != 0, PREFETCHI) | 		fs.setIf(edx1&(1<<14) != 0, PREFETCHI) | ||||||
| 		fs.setIf(edx1&(1<<19) != 0, AVX10) | 		fs.setIf(edx1&(1<<19) != 0, AVX10) | ||||||
| 		fs.setIf(edx1&(1<<21) != 0, APX_F) | 		fs.setIf(edx1&(1<<21) != 0, APX_F) | ||||||
|  |  | ||||||
							
								
								
									
										369
									
								
								vendor/github.com/klauspost/cpuid/v2/featureid_string.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										369
									
								
								vendor/github.com/klauspost/cpuid/v2/featureid_string.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -44,194 +44,195 @@ func _() { | ||||||
| 	_ = x[AVXSLOW-34] | 	_ = x[AVXSLOW-34] | ||||||
| 	_ = x[AVXVNNI-35] | 	_ = x[AVXVNNI-35] | ||||||
| 	_ = x[AVXVNNIINT8-36] | 	_ = x[AVXVNNIINT8-36] | ||||||
| 	_ = x[BHI_CTRL-37] | 	_ = x[AVXVNNIINT16-37] | ||||||
| 	_ = x[BMI1-38] | 	_ = x[BHI_CTRL-38] | ||||||
| 	_ = x[BMI2-39] | 	_ = x[BMI1-39] | ||||||
| 	_ = x[CETIBT-40] | 	_ = x[BMI2-40] | ||||||
| 	_ = x[CETSS-41] | 	_ = x[CETIBT-41] | ||||||
| 	_ = x[CLDEMOTE-42] | 	_ = x[CETSS-42] | ||||||
| 	_ = x[CLMUL-43] | 	_ = x[CLDEMOTE-43] | ||||||
| 	_ = x[CLZERO-44] | 	_ = x[CLMUL-44] | ||||||
| 	_ = x[CMOV-45] | 	_ = x[CLZERO-45] | ||||||
| 	_ = x[CMPCCXADD-46] | 	_ = x[CMOV-46] | ||||||
| 	_ = x[CMPSB_SCADBS_SHORT-47] | 	_ = x[CMPCCXADD-47] | ||||||
| 	_ = x[CMPXCHG8-48] | 	_ = x[CMPSB_SCADBS_SHORT-48] | ||||||
| 	_ = x[CPBOOST-49] | 	_ = x[CMPXCHG8-49] | ||||||
| 	_ = x[CPPC-50] | 	_ = x[CPBOOST-50] | ||||||
| 	_ = x[CX16-51] | 	_ = x[CPPC-51] | ||||||
| 	_ = x[EFER_LMSLE_UNS-52] | 	_ = x[CX16-52] | ||||||
| 	_ = x[ENQCMD-53] | 	_ = x[EFER_LMSLE_UNS-53] | ||||||
| 	_ = x[ERMS-54] | 	_ = x[ENQCMD-54] | ||||||
| 	_ = x[F16C-55] | 	_ = x[ERMS-55] | ||||||
| 	_ = x[FLUSH_L1D-56] | 	_ = x[F16C-56] | ||||||
| 	_ = x[FMA3-57] | 	_ = x[FLUSH_L1D-57] | ||||||
| 	_ = x[FMA4-58] | 	_ = x[FMA3-58] | ||||||
| 	_ = x[FP128-59] | 	_ = x[FMA4-59] | ||||||
| 	_ = x[FP256-60] | 	_ = x[FP128-60] | ||||||
| 	_ = x[FSRM-61] | 	_ = x[FP256-61] | ||||||
| 	_ = x[FXSR-62] | 	_ = x[FSRM-62] | ||||||
| 	_ = x[FXSROPT-63] | 	_ = x[FXSR-63] | ||||||
| 	_ = x[GFNI-64] | 	_ = x[FXSROPT-64] | ||||||
| 	_ = x[HLE-65] | 	_ = x[GFNI-65] | ||||||
| 	_ = x[HRESET-66] | 	_ = x[HLE-66] | ||||||
| 	_ = x[HTT-67] | 	_ = x[HRESET-67] | ||||||
| 	_ = x[HWA-68] | 	_ = x[HTT-68] | ||||||
| 	_ = x[HYBRID_CPU-69] | 	_ = x[HWA-69] | ||||||
| 	_ = x[HYPERVISOR-70] | 	_ = x[HYBRID_CPU-70] | ||||||
| 	_ = x[IA32_ARCH_CAP-71] | 	_ = x[HYPERVISOR-71] | ||||||
| 	_ = x[IA32_CORE_CAP-72] | 	_ = x[IA32_ARCH_CAP-72] | ||||||
| 	_ = x[IBPB-73] | 	_ = x[IA32_CORE_CAP-73] | ||||||
| 	_ = x[IBPB_BRTYPE-74] | 	_ = x[IBPB-74] | ||||||
| 	_ = x[IBRS-75] | 	_ = x[IBPB_BRTYPE-75] | ||||||
| 	_ = x[IBRS_PREFERRED-76] | 	_ = x[IBRS-76] | ||||||
| 	_ = x[IBRS_PROVIDES_SMP-77] | 	_ = x[IBRS_PREFERRED-77] | ||||||
| 	_ = x[IBS-78] | 	_ = x[IBRS_PROVIDES_SMP-78] | ||||||
| 	_ = x[IBSBRNTRGT-79] | 	_ = x[IBS-79] | ||||||
| 	_ = x[IBSFETCHSAM-80] | 	_ = x[IBSBRNTRGT-80] | ||||||
| 	_ = x[IBSFFV-81] | 	_ = x[IBSFETCHSAM-81] | ||||||
| 	_ = x[IBSOPCNT-82] | 	_ = x[IBSFFV-82] | ||||||
| 	_ = x[IBSOPCNTEXT-83] | 	_ = x[IBSOPCNT-83] | ||||||
| 	_ = x[IBSOPSAM-84] | 	_ = x[IBSOPCNTEXT-84] | ||||||
| 	_ = x[IBSRDWROPCNT-85] | 	_ = x[IBSOPSAM-85] | ||||||
| 	_ = x[IBSRIPINVALIDCHK-86] | 	_ = x[IBSRDWROPCNT-86] | ||||||
| 	_ = x[IBS_FETCH_CTLX-87] | 	_ = x[IBSRIPINVALIDCHK-87] | ||||||
| 	_ = x[IBS_OPDATA4-88] | 	_ = x[IBS_FETCH_CTLX-88] | ||||||
| 	_ = x[IBS_OPFUSE-89] | 	_ = x[IBS_OPDATA4-89] | ||||||
| 	_ = x[IBS_PREVENTHOST-90] | 	_ = x[IBS_OPFUSE-90] | ||||||
| 	_ = x[IBS_ZEN4-91] | 	_ = x[IBS_PREVENTHOST-91] | ||||||
| 	_ = x[IDPRED_CTRL-92] | 	_ = x[IBS_ZEN4-92] | ||||||
| 	_ = x[INT_WBINVD-93] | 	_ = x[IDPRED_CTRL-93] | ||||||
| 	_ = x[INVLPGB-94] | 	_ = x[INT_WBINVD-94] | ||||||
| 	_ = x[KEYLOCKER-95] | 	_ = x[INVLPGB-95] | ||||||
| 	_ = x[KEYLOCKERW-96] | 	_ = x[KEYLOCKER-96] | ||||||
| 	_ = x[LAHF-97] | 	_ = x[KEYLOCKERW-97] | ||||||
| 	_ = x[LAM-98] | 	_ = x[LAHF-98] | ||||||
| 	_ = x[LBRVIRT-99] | 	_ = x[LAM-99] | ||||||
| 	_ = x[LZCNT-100] | 	_ = x[LBRVIRT-100] | ||||||
| 	_ = x[MCAOVERFLOW-101] | 	_ = x[LZCNT-101] | ||||||
| 	_ = x[MCDT_NO-102] | 	_ = x[MCAOVERFLOW-102] | ||||||
| 	_ = x[MCOMMIT-103] | 	_ = x[MCDT_NO-103] | ||||||
| 	_ = x[MD_CLEAR-104] | 	_ = x[MCOMMIT-104] | ||||||
| 	_ = x[MMX-105] | 	_ = x[MD_CLEAR-105] | ||||||
| 	_ = x[MMXEXT-106] | 	_ = x[MMX-106] | ||||||
| 	_ = x[MOVBE-107] | 	_ = x[MMXEXT-107] | ||||||
| 	_ = x[MOVDIR64B-108] | 	_ = x[MOVBE-108] | ||||||
| 	_ = x[MOVDIRI-109] | 	_ = x[MOVDIR64B-109] | ||||||
| 	_ = x[MOVSB_ZL-110] | 	_ = x[MOVDIRI-110] | ||||||
| 	_ = x[MOVU-111] | 	_ = x[MOVSB_ZL-111] | ||||||
| 	_ = x[MPX-112] | 	_ = x[MOVU-112] | ||||||
| 	_ = x[MSRIRC-113] | 	_ = x[MPX-113] | ||||||
| 	_ = x[MSRLIST-114] | 	_ = x[MSRIRC-114] | ||||||
| 	_ = x[MSR_PAGEFLUSH-115] | 	_ = x[MSRLIST-115] | ||||||
| 	_ = x[NRIPS-116] | 	_ = x[MSR_PAGEFLUSH-116] | ||||||
| 	_ = x[NX-117] | 	_ = x[NRIPS-117] | ||||||
| 	_ = x[OSXSAVE-118] | 	_ = x[NX-118] | ||||||
| 	_ = x[PCONFIG-119] | 	_ = x[OSXSAVE-119] | ||||||
| 	_ = x[POPCNT-120] | 	_ = x[PCONFIG-120] | ||||||
| 	_ = x[PPIN-121] | 	_ = x[POPCNT-121] | ||||||
| 	_ = x[PREFETCHI-122] | 	_ = x[PPIN-122] | ||||||
| 	_ = x[PSFD-123] | 	_ = x[PREFETCHI-123] | ||||||
| 	_ = x[RDPRU-124] | 	_ = x[PSFD-124] | ||||||
| 	_ = x[RDRAND-125] | 	_ = x[RDPRU-125] | ||||||
| 	_ = x[RDSEED-126] | 	_ = x[RDRAND-126] | ||||||
| 	_ = x[RDTSCP-127] | 	_ = x[RDSEED-127] | ||||||
| 	_ = x[RRSBA_CTRL-128] | 	_ = x[RDTSCP-128] | ||||||
| 	_ = x[RTM-129] | 	_ = x[RRSBA_CTRL-129] | ||||||
| 	_ = x[RTM_ALWAYS_ABORT-130] | 	_ = x[RTM-130] | ||||||
| 	_ = x[SBPB-131] | 	_ = x[RTM_ALWAYS_ABORT-131] | ||||||
| 	_ = x[SERIALIZE-132] | 	_ = x[SBPB-132] | ||||||
| 	_ = x[SEV-133] | 	_ = x[SERIALIZE-133] | ||||||
| 	_ = x[SEV_64BIT-134] | 	_ = x[SEV-134] | ||||||
| 	_ = x[SEV_ALTERNATIVE-135] | 	_ = x[SEV_64BIT-135] | ||||||
| 	_ = x[SEV_DEBUGSWAP-136] | 	_ = x[SEV_ALTERNATIVE-136] | ||||||
| 	_ = x[SEV_ES-137] | 	_ = x[SEV_DEBUGSWAP-137] | ||||||
| 	_ = x[SEV_RESTRICTED-138] | 	_ = x[SEV_ES-138] | ||||||
| 	_ = x[SEV_SNP-139] | 	_ = x[SEV_RESTRICTED-139] | ||||||
| 	_ = x[SGX-140] | 	_ = x[SEV_SNP-140] | ||||||
| 	_ = x[SGXLC-141] | 	_ = x[SGX-141] | ||||||
| 	_ = x[SHA-142] | 	_ = x[SGXLC-142] | ||||||
| 	_ = x[SME-143] | 	_ = x[SHA-143] | ||||||
| 	_ = x[SME_COHERENT-144] | 	_ = x[SME-144] | ||||||
| 	_ = x[SPEC_CTRL_SSBD-145] | 	_ = x[SME_COHERENT-145] | ||||||
| 	_ = x[SRBDS_CTRL-146] | 	_ = x[SPEC_CTRL_SSBD-146] | ||||||
| 	_ = x[SRSO_MSR_FIX-147] | 	_ = x[SRBDS_CTRL-147] | ||||||
| 	_ = x[SRSO_NO-148] | 	_ = x[SRSO_MSR_FIX-148] | ||||||
| 	_ = x[SRSO_USER_KERNEL_NO-149] | 	_ = x[SRSO_NO-149] | ||||||
| 	_ = x[SSE-150] | 	_ = x[SRSO_USER_KERNEL_NO-150] | ||||||
| 	_ = x[SSE2-151] | 	_ = x[SSE-151] | ||||||
| 	_ = x[SSE3-152] | 	_ = x[SSE2-152] | ||||||
| 	_ = x[SSE4-153] | 	_ = x[SSE3-153] | ||||||
| 	_ = x[SSE42-154] | 	_ = x[SSE4-154] | ||||||
| 	_ = x[SSE4A-155] | 	_ = x[SSE42-155] | ||||||
| 	_ = x[SSSE3-156] | 	_ = x[SSE4A-156] | ||||||
| 	_ = x[STIBP-157] | 	_ = x[SSSE3-157] | ||||||
| 	_ = x[STIBP_ALWAYSON-158] | 	_ = x[STIBP-158] | ||||||
| 	_ = x[STOSB_SHORT-159] | 	_ = x[STIBP_ALWAYSON-159] | ||||||
| 	_ = x[SUCCOR-160] | 	_ = x[STOSB_SHORT-160] | ||||||
| 	_ = x[SVM-161] | 	_ = x[SUCCOR-161] | ||||||
| 	_ = x[SVMDA-162] | 	_ = x[SVM-162] | ||||||
| 	_ = x[SVMFBASID-163] | 	_ = x[SVMDA-163] | ||||||
| 	_ = x[SVML-164] | 	_ = x[SVMFBASID-164] | ||||||
| 	_ = x[SVMNP-165] | 	_ = x[SVML-165] | ||||||
| 	_ = x[SVMPF-166] | 	_ = x[SVMNP-166] | ||||||
| 	_ = x[SVMPFT-167] | 	_ = x[SVMPF-167] | ||||||
| 	_ = x[SYSCALL-168] | 	_ = x[SVMPFT-168] | ||||||
| 	_ = x[SYSEE-169] | 	_ = x[SYSCALL-169] | ||||||
| 	_ = x[TBM-170] | 	_ = x[SYSEE-170] | ||||||
| 	_ = x[TDX_GUEST-171] | 	_ = x[TBM-171] | ||||||
| 	_ = x[TLB_FLUSH_NESTED-172] | 	_ = x[TDX_GUEST-172] | ||||||
| 	_ = x[TME-173] | 	_ = x[TLB_FLUSH_NESTED-173] | ||||||
| 	_ = x[TOPEXT-174] | 	_ = x[TME-174] | ||||||
| 	_ = x[TSCRATEMSR-175] | 	_ = x[TOPEXT-175] | ||||||
| 	_ = x[TSXLDTRK-176] | 	_ = x[TSCRATEMSR-176] | ||||||
| 	_ = x[VAES-177] | 	_ = x[TSXLDTRK-177] | ||||||
| 	_ = x[VMCBCLEAN-178] | 	_ = x[VAES-178] | ||||||
| 	_ = x[VMPL-179] | 	_ = x[VMCBCLEAN-179] | ||||||
| 	_ = x[VMSA_REGPROT-180] | 	_ = x[VMPL-180] | ||||||
| 	_ = x[VMX-181] | 	_ = x[VMSA_REGPROT-181] | ||||||
| 	_ = x[VPCLMULQDQ-182] | 	_ = x[VMX-182] | ||||||
| 	_ = x[VTE-183] | 	_ = x[VPCLMULQDQ-183] | ||||||
| 	_ = x[WAITPKG-184] | 	_ = x[VTE-184] | ||||||
| 	_ = x[WBNOINVD-185] | 	_ = x[WAITPKG-185] | ||||||
| 	_ = x[WRMSRNS-186] | 	_ = x[WBNOINVD-186] | ||||||
| 	_ = x[X87-187] | 	_ = x[WRMSRNS-187] | ||||||
| 	_ = x[XGETBV1-188] | 	_ = x[X87-188] | ||||||
| 	_ = x[XOP-189] | 	_ = x[XGETBV1-189] | ||||||
| 	_ = x[XSAVE-190] | 	_ = x[XOP-190] | ||||||
| 	_ = x[XSAVEC-191] | 	_ = x[XSAVE-191] | ||||||
| 	_ = x[XSAVEOPT-192] | 	_ = x[XSAVEC-192] | ||||||
| 	_ = x[XSAVES-193] | 	_ = x[XSAVEOPT-193] | ||||||
| 	_ = x[AESARM-194] | 	_ = x[XSAVES-194] | ||||||
| 	_ = x[ARMCPUID-195] | 	_ = x[AESARM-195] | ||||||
| 	_ = x[ASIMD-196] | 	_ = x[ARMCPUID-196] | ||||||
| 	_ = x[ASIMDDP-197] | 	_ = x[ASIMD-197] | ||||||
| 	_ = x[ASIMDHP-198] | 	_ = x[ASIMDDP-198] | ||||||
| 	_ = x[ASIMDRDM-199] | 	_ = x[ASIMDHP-199] | ||||||
| 	_ = x[ATOMICS-200] | 	_ = x[ASIMDRDM-200] | ||||||
| 	_ = x[CRC32-201] | 	_ = x[ATOMICS-201] | ||||||
| 	_ = x[DCPOP-202] | 	_ = x[CRC32-202] | ||||||
| 	_ = x[EVTSTRM-203] | 	_ = x[DCPOP-203] | ||||||
| 	_ = x[FCMA-204] | 	_ = x[EVTSTRM-204] | ||||||
| 	_ = x[FP-205] | 	_ = x[FCMA-205] | ||||||
| 	_ = x[FPHP-206] | 	_ = x[FP-206] | ||||||
| 	_ = x[GPA-207] | 	_ = x[FPHP-207] | ||||||
| 	_ = x[JSCVT-208] | 	_ = x[GPA-208] | ||||||
| 	_ = x[LRCPC-209] | 	_ = x[JSCVT-209] | ||||||
| 	_ = x[PMULL-210] | 	_ = x[LRCPC-210] | ||||||
| 	_ = x[SHA1-211] | 	_ = x[PMULL-211] | ||||||
| 	_ = x[SHA2-212] | 	_ = x[SHA1-212] | ||||||
| 	_ = x[SHA3-213] | 	_ = x[SHA2-213] | ||||||
| 	_ = x[SHA512-214] | 	_ = x[SHA3-214] | ||||||
| 	_ = x[SM3-215] | 	_ = x[SHA512-215] | ||||||
| 	_ = x[SM4-216] | 	_ = x[SM3-216] | ||||||
| 	_ = x[SVE-217] | 	_ = x[SM4-217] | ||||||
| 	_ = x[lastID-218] | 	_ = x[SVE-218] | ||||||
|  | 	_ = x[lastID-219] | ||||||
| 	_ = x[firstID-0] | 	_ = x[firstID-0] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID" | const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8AVXVNNIINT16BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBPB_BRTYPEIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSBPBSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSRSO_MSR_FIXSRSO_NOSRSO_USER_KERNEL_NOSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID" | ||||||
| 
 | 
 | ||||||
| var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 67, 70, 75, 84, 93, 102, 106, 116, 128, 136, 144, 152, 160, 167, 177, 187, 195, 205, 216, 224, 234, 252, 267, 274, 286, 293, 300, 311, 319, 323, 327, 333, 338, 346, 351, 357, 361, 370, 388, 396, 403, 407, 411, 425, 431, 435, 439, 448, 452, 456, 461, 466, 470, 474, 481, 485, 488, 494, 497, 500, 510, 520, 533, 546, 550, 561, 565, 579, 596, 599, 609, 620, 626, 634, 645, 653, 665, 681, 695, 706, 716, 731, 739, 750, 760, 767, 776, 786, 790, 793, 800, 805, 816, 823, 830, 838, 841, 847, 852, 861, 868, 876, 880, 883, 889, 896, 909, 914, 916, 923, 930, 936, 940, 949, 953, 958, 964, 970, 976, 986, 989, 1005, 1009, 1018, 1021, 1030, 1045, 1058, 1064, 1078, 1085, 1088, 1093, 1096, 1099, 1111, 1125, 1135, 1147, 1154, 1173, 1176, 1180, 1184, 1188, 1193, 1198, 1203, 1208, 1222, 1233, 1239, 1242, 1247, 1256, 1260, 1265, 1270, 1276, 1283, 1288, 1291, 1300, 1316, 1319, 1325, 1335, 1343, 1347, 1356, 1360, 1372, 1375, 1385, 1388, 1395, 1403, 1410, 1413, 1420, 1423, 1428, 1434, 1442, 1448, 1454, 1462, 1467, 1474, 1481, 1489, 1496, 1501, 1506, 1513, 1517, 1519, 1523, 1526, 1531, 1536, 1541, 1545, 1549, 1553, 1559, 1562, 1565, 1568, 1574} | var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 67, 70, 75, 84, 93, 102, 106, 116, 128, 136, 144, 152, 160, 167, 177, 187, 195, 205, 216, 224, 234, 252, 267, 274, 286, 293, 300, 311, 323, 331, 335, 339, 345, 350, 358, 363, 369, 373, 382, 400, 408, 415, 419, 423, 437, 443, 447, 451, 460, 464, 468, 473, 478, 482, 486, 493, 497, 500, 506, 509, 512, 522, 532, 545, 558, 562, 573, 577, 591, 608, 611, 621, 632, 638, 646, 657, 665, 677, 693, 707, 718, 728, 743, 751, 762, 772, 779, 788, 798, 802, 805, 812, 817, 828, 835, 842, 850, 853, 859, 864, 873, 880, 888, 892, 895, 901, 908, 921, 926, 928, 935, 942, 948, 952, 961, 965, 970, 976, 982, 988, 998, 1001, 1017, 1021, 1030, 1033, 1042, 1057, 1070, 1076, 1090, 1097, 1100, 1105, 1108, 1111, 1123, 1137, 1147, 1159, 1166, 1185, 1188, 1192, 1196, 1200, 1205, 1210, 1215, 1220, 1234, 1245, 1251, 1254, 1259, 1268, 1272, 1277, 1282, 1288, 1295, 1300, 1303, 1312, 1328, 1331, 1337, 1347, 1355, 1359, 1368, 1372, 1384, 1387, 1397, 1400, 1407, 1415, 1422, 1425, 1432, 1435, 1440, 1446, 1454, 1460, 1466, 1474, 1479, 1486, 1493, 1501, 1508, 1513, 1518, 1525, 1529, 1531, 1535, 1538, 1543, 1548, 1553, 1557, 1561, 1565, 1571, 1574, 1577, 1580, 1586} | ||||||
| 
 | 
 | ||||||
| func (i FeatureID) String() string { | func (i FeatureID) String() string { | ||||||
| 	if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) { | 	if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) { | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								vendor/github.com/minio/minio-go/v7/api-put-object-streaming.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/minio/minio-go/v7/api-put-object-streaming.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -637,7 +637,9 @@ func (c *Client) putObjectMultipartStreamParallel(ctx context.Context, bucketNam | ||||||
| 	// Sort all completed parts. | 	// Sort all completed parts. | ||||||
| 	sort.Sort(completedParts(complMultipartUpload.Parts)) | 	sort.Sort(completedParts(complMultipartUpload.Parts)) | ||||||
| 
 | 
 | ||||||
| 	opts = PutObjectOptions{} | 	opts = PutObjectOptions{ | ||||||
|  | 		ServerSideEncryption: opts.ServerSideEncryption, | ||||||
|  | 	} | ||||||
| 	if len(crcBytes) > 0 { | 	if len(crcBytes) > 0 { | ||||||
| 		// Add hash of hashes. | 		// Add hash of hashes. | ||||||
| 		crc.Reset() | 		crc.Reset() | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								vendor/github.com/minio/minio-go/v7/api-put-object.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/minio/minio-go/v7/api-put-object.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -464,7 +464,9 @@ func (c *Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketNam | ||||||
| 	// Sort all completed parts. | 	// Sort all completed parts. | ||||||
| 	sort.Sort(completedParts(complMultipartUpload.Parts)) | 	sort.Sort(completedParts(complMultipartUpload.Parts)) | ||||||
| 
 | 
 | ||||||
| 	opts = PutObjectOptions{} | 	opts = PutObjectOptions{ | ||||||
|  | 		ServerSideEncryption: opts.ServerSideEncryption, | ||||||
|  | 	} | ||||||
| 	if len(crcBytes) > 0 { | 	if len(crcBytes) > 0 { | ||||||
| 		// Add hash of hashes. | 		// Add hash of hashes. | ||||||
| 		crc.Reset() | 		crc.Reset() | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/minio/minio-go/v7/api.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/minio/minio-go/v7/api.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -129,7 +129,7 @@ type Options struct { | ||||||
| // Global constants. | // Global constants. | ||||||
| const ( | const ( | ||||||
| 	libraryName    = "minio-go" | 	libraryName    = "minio-go" | ||||||
| 	libraryVersion = "v7.0.72" | 	libraryVersion = "v7.0.73" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // User Agent should always following the below style. | // User Agent should always following the below style. | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/minio/minio-go/v7/pkg/credentials/file_aws_credentials.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/minio/minio-go/v7/pkg/credentials/file_aws_credentials.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -26,7 +26,7 @@ import ( | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	ini "gopkg.in/ini.v1" | 	"github.com/go-ini/ini" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // A externalProcessCredentials stores the output of a credential_process | // A externalProcessCredentials stores the output of a credential_process | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								vendor/github.com/minio/minio-go/v7/pkg/replication/replication.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/minio/minio-go/v7/pkg/replication/replication.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -406,6 +406,9 @@ func (c *Config) EditRule(opts Options) error { | ||||||
| 			return fmt.Errorf("priority must be unique. Replication configuration already has a rule with this priority") | 			return fmt.Errorf("priority must be unique. Replication configuration already has a rule with this priority") | ||||||
| 		} | 		} | ||||||
| 		if rule.Destination.Bucket != newRule.Destination.Bucket && rule.ID == newRule.ID { | 		if rule.Destination.Bucket != newRule.Destination.Bucket && rule.ID == newRule.ID { | ||||||
|  | 			if c.Role == newRule.Destination.Bucket { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
| 			return fmt.Errorf("invalid destination bucket for this rule") | 			return fmt.Errorf("invalid destination bucket for this rule") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								vendor/github.com/minio/minio-go/v7/s3-endpoints.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/minio/minio-go/v7/s3-endpoints.go
									
										
									
										generated
									
									
										vendored
									
									
								
							|  | @ -44,6 +44,10 @@ var awsS3EndpointMap = map[string]awsS3Endpoint{ | ||||||
| 		"s3.ca-central-1.amazonaws.com", | 		"s3.ca-central-1.amazonaws.com", | ||||||
| 		"s3.dualstack.ca-central-1.amazonaws.com", | 		"s3.dualstack.ca-central-1.amazonaws.com", | ||||||
| 	}, | 	}, | ||||||
|  | 	"ca-west-1": { | ||||||
|  | 		"s3.ca-west-1.amazonaws.com", | ||||||
|  | 		"s3.dualstack.ca-west-1.amazonaws.com", | ||||||
|  | 	}, | ||||||
| 	"eu-west-1": { | 	"eu-west-1": { | ||||||
| 		"s3.eu-west-1.amazonaws.com", | 		"s3.eu-west-1.amazonaws.com", | ||||||
| 		"s3.dualstack.eu-west-1.amazonaws.com", | 		"s3.dualstack.eu-west-1.amazonaws.com", | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								vendor/modules.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/modules.txt
									
										
									
									
										vendored
									
									
								
							|  | @ -238,6 +238,9 @@ github.com/go-errors/errors | ||||||
| # github.com/go-fed/httpsig v1.1.0 | # github.com/go-fed/httpsig v1.1.0 | ||||||
| ## explicit; go 1.13 | ## explicit; go 1.13 | ||||||
| github.com/go-fed/httpsig | github.com/go-fed/httpsig | ||||||
|  | # github.com/go-ini/ini v1.67.0 | ||||||
|  | ## explicit | ||||||
|  | github.com/go-ini/ini | ||||||
| # github.com/go-jose/go-jose/v4 v4.0.1 | # github.com/go-jose/go-jose/v4 v4.0.1 | ||||||
| ## explicit; go 1.21 | ## explicit; go 1.21 | ||||||
| github.com/go-jose/go-jose/v4 | github.com/go-jose/go-jose/v4 | ||||||
|  | @ -322,8 +325,8 @@ github.com/go-swagger/go-swagger/generator | ||||||
| # github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 | # github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 | ||||||
| ## explicit | ## explicit | ||||||
| github.com/go-xmlfmt/xmlfmt | github.com/go-xmlfmt/xmlfmt | ||||||
| # github.com/goccy/go-json v0.10.2 | # github.com/goccy/go-json v0.10.3 | ||||||
| ## explicit; go 1.12 | ## explicit; go 1.19 | ||||||
| github.com/goccy/go-json | github.com/goccy/go-json | ||||||
| github.com/goccy/go-json/internal/decoder | github.com/goccy/go-json/internal/decoder | ||||||
| github.com/goccy/go-json/internal/encoder | github.com/goccy/go-json/internal/encoder | ||||||
|  | @ -450,11 +453,11 @@ github.com/josharian/intern | ||||||
| # github.com/json-iterator/go v1.1.12 | # github.com/json-iterator/go v1.1.12 | ||||||
| ## explicit; go 1.12 | ## explicit; go 1.12 | ||||||
| github.com/json-iterator/go | github.com/json-iterator/go | ||||||
| # github.com/klauspost/compress v1.17.8 | # github.com/klauspost/compress v1.17.9 | ||||||
| ## explicit; go 1.20 | ## explicit; go 1.20 | ||||||
| github.com/klauspost/compress/internal/race | github.com/klauspost/compress/internal/race | ||||||
| github.com/klauspost/compress/s2 | github.com/klauspost/compress/s2 | ||||||
| # github.com/klauspost/cpuid/v2 v2.2.7 | # github.com/klauspost/cpuid/v2 v2.2.8 | ||||||
| ## explicit; go 1.15 | ## explicit; go 1.15 | ||||||
| github.com/klauspost/cpuid/v2 | github.com/klauspost/cpuid/v2 | ||||||
| # github.com/kr/pretty v0.3.1 | # github.com/kr/pretty v0.3.1 | ||||||
|  | @ -488,7 +491,7 @@ github.com/miekg/dns | ||||||
| # github.com/minio/md5-simd v1.1.2 | # github.com/minio/md5-simd v1.1.2 | ||||||
| ## explicit; go 1.14 | ## explicit; go 1.14 | ||||||
| github.com/minio/md5-simd | github.com/minio/md5-simd | ||||||
| # github.com/minio/minio-go/v7 v7.0.72 | # github.com/minio/minio-go/v7 v7.0.73 | ||||||
| ## explicit; go 1.21 | ## explicit; go 1.21 | ||||||
| github.com/minio/minio-go/v7 | github.com/minio/minio-go/v7 | ||||||
| github.com/minio/minio-go/v7/pkg/credentials | github.com/minio/minio-go/v7/pkg/credentials | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue