field.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package ini
  2. import (
  3. "encoding"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. )
  9. // Types to look for ("Marshaler"/"Unmarshaler" interface)
  10. var (
  11. marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
  12. unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem()
  13. textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
  14. textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
  15. )
  16. // INIDecoderError is returned on decoding error
  17. type INIDecoderError struct {
  18. msg string
  19. err error
  20. f *field
  21. }
  22. // Error returns an formatted string of the INIDecoderError
  23. func (i *INIDecoderError) Error() string {
  24. return fmt.Sprintf(
  25. "INI Decoder Error: %s. %s. Field %s, namespace: %s",
  26. i.msg, i.err.Error(), i.f.t.Name(), i.f.ns,
  27. )
  28. }
  29. // INIEncoderError is returned on encoding error
  30. type INIEncoderError struct {
  31. msg string
  32. err error
  33. f *field
  34. }
  35. // Error returns an formatted string of the INIEncoderError
  36. func (i *INIEncoderError) Error() string {
  37. return fmt.Sprintf(
  38. "INI Encoder Error: %s. Field: %s, namespace: %s",
  39. i.msg, i.err.Error(), i.f.t.Name(), i.f.ns,
  40. )
  41. }
  42. // decoder and encoder methods
  43. type decodeFn func([]byte) error
  44. type encodeFn func() ([]byte, error)
  45. type field struct {
  46. ns string
  47. t reflect.Type
  48. v reflect.Value
  49. p interface{}
  50. // decoder or encoder method (will be changed when a cache for "elements" is implemented)
  51. fn interface{} // Use setFn to set this!
  52. }
  53. func newField(v reflect.Value, p interface{}, i int) *field {
  54. f := &field{
  55. t: v.Type(),
  56. v: v,
  57. p: nil,
  58. }
  59. if p != nil {
  60. switch p.(type) {
  61. case reflect.Type:
  62. f.p = p.(reflect.Type).Field(i)
  63. case reflect.Value:
  64. f.p = p.(reflect.Value).Type().Field(i)
  65. }
  66. }
  67. return f
  68. }
  69. // implements checks if the field implements the type t, or a pointer method to type t
  70. func (f *field) implements(t reflect.Type) bool {
  71. return (f.t.Implements(t) || (f.t.Kind() != reflect.Ptr && reflect.PtrTo(f.t).Implements(t)))
  72. }
  73. // setNS determines the namespace for the field
  74. func (f *field) setNS(ns string) string {
  75. if f.p == nil {
  76. f.ns = ns + "." + f.t.Name()
  77. return f.ns
  78. }
  79. if tag := f.p.(reflect.StructField).Tag.Get("ini"); len(tag) != 0 {
  80. f.ns = ns + "." + tag
  81. return f.ns
  82. }
  83. f.ns = ns + "." + f.p.(reflect.StructField).Name
  84. return f.ns
  85. }
  86. // setFN sets the function
  87. func (f *field) setFn(fn interface{}) {
  88. f.fn = fn
  89. }
  90. // decode returns the decoder-method (do not call f.fn, for future changes!)
  91. func (f *field) decode(b []byte) error {
  92. return f.fn.(decodeFn)(b)
  93. }
  94. // encode returns the decoder-method (do not call f.fn directly, for future changes!)
  95. func (f *field) encode() ([]byte, error) {
  96. return f.fn.(encodeFn)()
  97. }
  98. /**
  99. DECODER METHODS
  100. **/
  101. func (f *field) valid() error {
  102. if f.v.CanAddr() {
  103. return nil
  104. }
  105. return fmt.Errorf("Field '%s' not addressable", f.ns)
  106. }
  107. func (f *field) uintDecoder(b []byte) error {
  108. if err := f.valid(); err != nil {
  109. return &INIDecoderError{
  110. msg: "Unsigned integer decoder",
  111. err: err,
  112. f: f,
  113. }
  114. }
  115. i, err := strconv.ParseUint(string(b), 10, 64)
  116. if err != nil {
  117. return &INIDecoderError{
  118. msg: "Unsigned integer decoder",
  119. err: err,
  120. f: f,
  121. }
  122. }
  123. f.v.SetUint(i)
  124. return nil
  125. }
  126. func (f *field) intDecoder(b []byte) error {
  127. if err := f.valid(); err != nil {
  128. return &INIDecoderError{
  129. msg: "Integer decoder",
  130. err: err,
  131. f: f,
  132. }
  133. }
  134. i, err := strconv.ParseInt(string(b), 10, 64)
  135. if err != nil {
  136. return &INIDecoderError{
  137. msg: "Integer decoder",
  138. err: err,
  139. f: f,
  140. }
  141. }
  142. f.v.SetInt(i)
  143. return nil
  144. }
  145. func (f *field) float32Decoder(b []byte) error {
  146. if err := f.valid(); err != nil {
  147. return &INIDecoderError{
  148. msg: "Float (32) decoder",
  149. err: err,
  150. f: f,
  151. }
  152. }
  153. i, err := strconv.ParseFloat(string(b), 32)
  154. if err != nil {
  155. return &INIDecoderError{
  156. msg: "Float (32) decoder",
  157. err: err,
  158. f: f,
  159. }
  160. }
  161. f.v.SetFloat(i)
  162. return nil
  163. }
  164. func (f *field) float64Decoder(b []byte) error {
  165. if err := f.valid(); err != nil {
  166. return &INIDecoderError{
  167. msg: "Float (64) decoder",
  168. err: err,
  169. f: f,
  170. }
  171. }
  172. i, err := strconv.ParseFloat(string(b), 64)
  173. if err != nil {
  174. return &INIDecoderError{
  175. msg: "Float (64) decoder",
  176. err: err,
  177. f: f,
  178. }
  179. }
  180. f.v.SetFloat(i)
  181. return nil
  182. }
  183. func (f *field) strDecoder(b []byte) error {
  184. if err := f.valid(); err != nil {
  185. return &INIDecoderError{
  186. msg: "String decoder",
  187. err: err,
  188. f: f,
  189. }
  190. }
  191. f.v.SetString(string(b))
  192. return nil
  193. }
  194. func (f *field) boolDecoder(b []byte) error {
  195. if err := f.valid(); err != nil {
  196. return &INIDecoderError{
  197. msg: "Boolean decoder",
  198. err: err,
  199. f: f,
  200. }
  201. }
  202. f.v.SetBool(true)
  203. return nil
  204. }
  205. func (f *field) unmarshalerDecoder(b []byte) error {
  206. if err := f.valid(); err != nil {
  207. return &INIDecoderError{
  208. msg: "Unmarshaler decoder",
  209. err: err,
  210. f: f,
  211. }
  212. }
  213. v := f.v
  214. if v.Kind() != reflect.Ptr && v.Type().Name() != "" {
  215. v = v.Addr()
  216. }
  217. if v.IsNil() {
  218. v.Set(reflect.New(v.Type().Elem()))
  219. }
  220. if i, ok := v.Interface().(Unmarshaler); ok {
  221. if err := i.UnmarshalINI(b); err != nil {
  222. return &INIDecoderError{
  223. msg: "UnmarshalINI decoder",
  224. err: err,
  225. f: f,
  226. }
  227. }
  228. return nil
  229. }
  230. if i, ok := v.Interface().(encoding.TextUnmarshaler); ok {
  231. if err := i.UnmarshalText(b); err != nil {
  232. return &INIDecoderError{
  233. msg: "UnmarshalText decoder",
  234. err: err,
  235. f: f,
  236. }
  237. }
  238. return nil
  239. }
  240. return fmt.Errorf("Cannot load Unmarshaler")
  241. }
  242. /**
  243. ENCODER METHODS
  244. **/
  245. func (f *field) nskey() string {
  246. return f.ns[strings.LastIndexByte(f.ns, '.')+1:]
  247. }
  248. func (f *field) uintEncoder() ([]byte, error) {
  249. i := strconv.FormatUint(f.v.Uint(), 10)
  250. return []byte(f.nskey() + " = " + i), nil
  251. }
  252. func (f *field) intEncoder() ([]byte, error) {
  253. i := strconv.FormatInt(f.v.Int(), 10)
  254. return []byte(f.nskey() + " = " + i), nil
  255. }
  256. func (f *field) float32Encoder() ([]byte, error) {
  257. i := strconv.FormatFloat(f.v.Float(), 'G', -1, 32)
  258. return []byte(f.nskey() + " = " + i), nil
  259. }
  260. func (f *field) float64Encoder() ([]byte, error) {
  261. i := strconv.FormatFloat(f.v.Float(), 'G', -1, 64)
  262. return []byte(f.nskey() + " = " + i), nil
  263. }
  264. func (f *field) strEncoder() ([]byte, error) {
  265. str := strings.Replace(f.v.String(), "\n", "\\\n", -1)
  266. return []byte(f.nskey() + " = " + str), nil
  267. }
  268. func (f *field) boolEncoder() ([]byte, error) {
  269. if f.v.Bool() {
  270. return []byte(f.nskey()), nil
  271. }
  272. return nil, nil
  273. }
  274. func (f *field) structEncoder() ([]byte, error) {
  275. split := strings.SplitN(f.ns, ".", 3)
  276. if len(split) == 2 {
  277. return nil, nil
  278. }
  279. if len(split) != 3 {
  280. return nil, &INIEncoderError{
  281. msg: "Struct encoder",
  282. err: fmt.Errorf("Invalid namespace"),
  283. f: f,
  284. }
  285. }
  286. return []byte("\n[" + split[2] + "]"), nil
  287. }
  288. func (f *field) marshalerDecoder() ([]byte, error) {
  289. if err := f.valid(); err != nil {
  290. return nil, &INIEncoderError{
  291. msg: "Unmarshaler decoder",
  292. err: err,
  293. f: f,
  294. }
  295. }
  296. v := f.v
  297. if v.Kind() != reflect.Ptr && v.Type().Name() != "" {
  298. v = v.Addr()
  299. }
  300. if v.IsNil() {
  301. v.Set(reflect.New(v.Type().Elem()))
  302. }
  303. if i, ok := v.Interface().(Marshaler); ok {
  304. b, err := i.MarshalINI()
  305. if err != nil {
  306. return nil, err
  307. }
  308. if b == nil {
  309. return nil, nil
  310. }
  311. return append([]byte(f.nskey()+" = "), b...), nil
  312. }
  313. if i, ok := v.Interface().(encoding.TextMarshaler); ok {
  314. b, err := i.MarshalText()
  315. if err != nil {
  316. return nil, err
  317. }
  318. if b == nil {
  319. return nil, nil
  320. }
  321. return append([]byte(f.nskey()+" = "), b...), nil
  322. }
  323. return nil, fmt.Errorf("Cannot load Marshaler")
  324. }