vendor/gopkg.in/ini.v1/struct.go
changeset 256 6d9efbef00a9
parent 251 1c52a0eeb952
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
   256 			field.Set(reflect.ValueOf(timeVal))
   256 			field.Set(reflect.ValueOf(timeVal))
   257 		}
   257 		}
   258 	case reflect.Slice:
   258 	case reflect.Slice:
   259 		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
   259 		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
   260 	default:
   260 	default:
   261 		return fmt.Errorf("unsupported type '%s'", t)
   261 		return fmt.Errorf("unsupported type %q", t)
   262 	}
   262 	}
   263 	return nil
   263 	return nil
   264 }
   264 }
   265 
   265 
   266 func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool) {
   266 func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool, allowNonUnique bool, extends bool) {
   267 	opts := strings.SplitN(tag, ",", 3)
   267 	opts := strings.SplitN(tag, ",", 5)
   268 	rawName = opts[0]
   268 	rawName = opts[0]
   269 	if len(opts) > 1 {
   269 	for _, opt := range opts[1:] {
   270 		omitEmpty = opts[1] == "omitempty"
   270 		omitEmpty = omitEmpty || (opt == "omitempty")
   271 	}
   271 		allowShadow = allowShadow || (opt == "allowshadow")
   272 	if len(opts) > 2 {
   272 		allowNonUnique = allowNonUnique || (opt == "nonunique")
   273 		allowShadow = opts[2] == "allowshadow"
   273 		extends = extends || (opt == "extends")
   274 	}
   274 	}
   275 	return rawName, omitEmpty, allowShadow
   275 	return rawName, omitEmpty, allowShadow, allowNonUnique, extends
   276 }
   276 }
   277 
   277 
   278 func (s *Section) mapTo(val reflect.Value, isStrict bool) error {
   278 // mapToField maps the given value to the matching field of the given section.
       
   279 // The sectionIndex is the index (if non unique sections are enabled) to which the value should be added.
       
   280 func (s *Section) mapToField(val reflect.Value, isStrict bool, sectionIndex int, sectionName string) error {
   279 	if val.Kind() == reflect.Ptr {
   281 	if val.Kind() == reflect.Ptr {
   280 		val = val.Elem()
   282 		val = val.Elem()
   281 	}
   283 	}
   282 	typ := val.Type()
   284 	typ := val.Type()
   283 
   285 
   288 		tag := tpField.Tag.Get("ini")
   290 		tag := tpField.Tag.Get("ini")
   289 		if tag == "-" {
   291 		if tag == "-" {
   290 			continue
   292 			continue
   291 		}
   293 		}
   292 
   294 
   293 		rawName, _, allowShadow := parseTagOptions(tag)
   295 		rawName, _, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
   294 		fieldName := s.parseFieldName(tpField.Name, rawName)
   296 		fieldName := s.parseFieldName(tpField.Name, rawName)
   295 		if len(fieldName) == 0 || !field.CanSet() {
   297 		if len(fieldName) == 0 || !field.CanSet() {
   296 			continue
   298 			continue
   297 		}
   299 		}
   298 
   300 
   299 		isStruct := tpField.Type.Kind() == reflect.Struct
   301 		isStruct := tpField.Type.Kind() == reflect.Struct
   300 		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
   302 		isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
   301 		isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
   303 		isAnonymousPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
   302 		if isAnonymous {
   304 		if isAnonymousPtr {
   303 			field.Set(reflect.New(tpField.Type.Elem()))
   305 			field.Set(reflect.New(tpField.Type.Elem()))
   304 		}
   306 		}
   305 
   307 
   306 		if isAnonymous || isStruct || isStructPtr {
   308 		if extends && (isAnonymousPtr || (isStruct && tpField.Anonymous)) {
   307 			if sec, err := s.f.GetSection(fieldName); err == nil {
   309 			if isStructPtr && field.IsNil() {
       
   310 				field.Set(reflect.New(tpField.Type.Elem()))
       
   311 			}
       
   312 			fieldSection := s
       
   313 			if rawName != "" {
       
   314 				sectionName = s.name + s.f.options.ChildSectionDelimiter + rawName
       
   315 				if secs, err := s.f.SectionsByName(sectionName); err == nil && sectionIndex < len(secs) {
       
   316 					fieldSection = secs[sectionIndex]
       
   317 				}
       
   318 			}
       
   319 			if err := fieldSection.mapToField(field, isStrict, sectionIndex, sectionName); err != nil {
       
   320 				return fmt.Errorf("map to field %q: %v", fieldName, err)
       
   321 			}
       
   322 		} else if isAnonymousPtr || isStruct || isStructPtr {
       
   323 			if secs, err := s.f.SectionsByName(fieldName); err == nil {
       
   324 				if len(secs) <= sectionIndex {
       
   325 					return fmt.Errorf("there are not enough sections (%d <= %d) for the field %q", len(secs), sectionIndex, fieldName)
       
   326 				}
   308 				// Only set the field to non-nil struct value if we have a section for it.
   327 				// Only set the field to non-nil struct value if we have a section for it.
   309 				// Otherwise, we end up with a non-nil struct ptr even though there is no data.
   328 				// Otherwise, we end up with a non-nil struct ptr even though there is no data.
   310 				if isStructPtr && field.IsNil() {
   329 				if isStructPtr && field.IsNil() {
   311 					field.Set(reflect.New(tpField.Type.Elem()))
   330 					field.Set(reflect.New(tpField.Type.Elem()))
   312 				}
   331 				}
   313 				if err = sec.mapTo(field, isStrict); err != nil {
   332 				if err = secs[sectionIndex].mapToField(field, isStrict, sectionIndex, fieldName); err != nil {
   314 					return fmt.Errorf("error mapping field %q: %v", fieldName, err)
   333 					return fmt.Errorf("map to field %q: %v", fieldName, err)
   315 				}
   334 				}
   316 				continue
   335 				continue
   317 			}
   336 			}
   318 		}
   337 		}
       
   338 
       
   339 		// Map non-unique sections
       
   340 		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
       
   341 			newField, err := s.mapToSlice(fieldName, field, isStrict)
       
   342 			if err != nil {
       
   343 				return fmt.Errorf("map to slice %q: %v", fieldName, err)
       
   344 			}
       
   345 
       
   346 			field.Set(newField)
       
   347 			continue
       
   348 		}
       
   349 
   319 		if key, err := s.GetKey(fieldName); err == nil {
   350 		if key, err := s.GetKey(fieldName); err == nil {
   320 			delim := parseDelim(tpField.Tag.Get("delim"))
   351 			delim := parseDelim(tpField.Tag.Get("delim"))
   321 			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
   352 			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
   322 				return fmt.Errorf("error mapping field %q: %v", fieldName, err)
   353 				return fmt.Errorf("set field %q: %v", fieldName, err)
   323 			}
   354 			}
   324 		}
   355 		}
   325 	}
   356 	}
   326 	return nil
   357 	return nil
   327 }
   358 }
   328 
   359 
   329 // MapTo maps section to given struct.
   360 // mapToSlice maps all sections with the same name and returns the new value.
   330 func (s *Section) MapTo(v interface{}) error {
   361 // The type of the Value must be a slice.
       
   362 func (s *Section) mapToSlice(secName string, val reflect.Value, isStrict bool) (reflect.Value, error) {
       
   363 	secs, err := s.f.SectionsByName(secName)
       
   364 	if err != nil {
       
   365 		return reflect.Value{}, err
       
   366 	}
       
   367 
       
   368 	typ := val.Type().Elem()
       
   369 	for i, sec := range secs {
       
   370 		elem := reflect.New(typ)
       
   371 		if err = sec.mapToField(elem, isStrict, i, sec.name); err != nil {
       
   372 			return reflect.Value{}, fmt.Errorf("map to field from section %q: %v", secName, err)
       
   373 		}
       
   374 
       
   375 		val = reflect.Append(val, elem.Elem())
       
   376 	}
       
   377 	return val, nil
       
   378 }
       
   379 
       
   380 // mapTo maps a section to object v.
       
   381 func (s *Section) mapTo(v interface{}, isStrict bool) error {
   331 	typ := reflect.TypeOf(v)
   382 	typ := reflect.TypeOf(v)
   332 	val := reflect.ValueOf(v)
   383 	val := reflect.ValueOf(v)
   333 	if typ.Kind() == reflect.Ptr {
   384 	if typ.Kind() == reflect.Ptr {
   334 		typ = typ.Elem()
   385 		typ = typ.Elem()
   335 		val = val.Elem()
   386 		val = val.Elem()
   336 	} else {
   387 	} else {
   337 		return errors.New("cannot map to non-pointer struct")
   388 		return errors.New("not a pointer to a struct")
   338 	}
   389 	}
   339 
   390 
   340 	return s.mapTo(val, false)
   391 	if typ.Kind() == reflect.Slice {
       
   392 		newField, err := s.mapToSlice(s.name, val, isStrict)
       
   393 		if err != nil {
       
   394 			return err
       
   395 		}
       
   396 
       
   397 		val.Set(newField)
       
   398 		return nil
       
   399 	}
       
   400 
       
   401 	return s.mapToField(val, isStrict, 0, s.name)
       
   402 }
       
   403 
       
   404 // MapTo maps section to given struct.
       
   405 func (s *Section) MapTo(v interface{}) error {
       
   406 	return s.mapTo(v, false)
   341 }
   407 }
   342 
   408 
   343 // StrictMapTo maps section to given struct in strict mode,
   409 // StrictMapTo maps section to given struct in strict mode,
   344 // which returns all possible error including value parsing error.
   410 // which returns all possible error including value parsing error.
   345 func (s *Section) StrictMapTo(v interface{}) error {
   411 func (s *Section) StrictMapTo(v interface{}) error {
   346 	typ := reflect.TypeOf(v)
   412 	return s.mapTo(v, true)
   347 	val := reflect.ValueOf(v)
       
   348 	if typ.Kind() == reflect.Ptr {
       
   349 		typ = typ.Elem()
       
   350 		val = val.Elem()
       
   351 	} else {
       
   352 		return errors.New("cannot map to non-pointer struct")
       
   353 	}
       
   354 
       
   355 	return s.mapTo(val, true)
       
   356 }
   413 }
   357 
   414 
   358 // MapTo maps file to given struct.
   415 // MapTo maps file to given struct.
   359 func (f *File) MapTo(v interface{}) error {
   416 func (f *File) MapTo(v interface{}) error {
   360 	return f.Section("").MapTo(v)
   417 	return f.Section("").MapTo(v)
   428 			}
   485 			}
   429 
   486 
   430 			if i == 0 {
   487 			if i == 0 {
   431 				keyWithShadows = newKey(key.s, key.name, val)
   488 				keyWithShadows = newKey(key.s, key.name, val)
   432 			} else {
   489 			} else {
   433 				keyWithShadows.AddShadow(val)
   490 				_ = keyWithShadows.AddShadow(val)
   434 			}
   491 			}
   435 		}
   492 		}
   436 		key = keyWithShadows
   493 		*key = *keyWithShadows
   437 		return nil
   494 		return nil
   438 	}
   495 	}
   439 
   496 
   440 	var buf bytes.Buffer
   497 	var buf bytes.Buffer
   441 	for i := 0; i < field.Len(); i++ {
   498 	for i := 0; i < field.Len(); i++ {
   481 	case reflect.Ptr:
   538 	case reflect.Ptr:
   482 		if !field.IsNil() {
   539 		if !field.IsNil() {
   483 			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
   540 			return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
   484 		}
   541 		}
   485 	default:
   542 	default:
   486 		return fmt.Errorf("unsupported type '%s'", t)
   543 		return fmt.Errorf("unsupported type %q", t)
   487 	}
   544 	}
   488 	return nil
   545 	return nil
   489 }
   546 }
   490 
   547 
   491 // CR: copied from encoding/json/encode.go with modifications of time.Time support.
   548 // CR: copied from encoding/json/encode.go with modifications of time.Time support.
   521 		val = val.Elem()
   578 		val = val.Elem()
   522 	}
   579 	}
   523 	typ := val.Type()
   580 	typ := val.Type()
   524 
   581 
   525 	for i := 0; i < typ.NumField(); i++ {
   582 	for i := 0; i < typ.NumField(); i++ {
       
   583 		if !val.Field(i).CanInterface() {
       
   584 			continue
       
   585 		}
       
   586 
   526 		field := val.Field(i)
   587 		field := val.Field(i)
   527 		tpField := typ.Field(i)
   588 		tpField := typ.Field(i)
   528 
   589 
   529 		tag := tpField.Tag.Get("ini")
   590 		tag := tpField.Tag.Get("ini")
   530 		if tag == "-" {
   591 		if tag == "-" {
   531 			continue
   592 			continue
   532 		}
   593 		}
   533 
   594 
   534 		rawName, omitEmpty, allowShadow := parseTagOptions(tag)
   595 		rawName, omitEmpty, allowShadow, allowNonUnique, extends := parseTagOptions(tag)
   535 		if omitEmpty && isEmptyValue(field) {
   596 		if omitEmpty && isEmptyValue(field) {
   536 			continue
   597 			continue
   537 		}
   598 		}
   538 
   599 
   539 		if r, ok := field.Interface().(StructReflector); ok {
   600 		if r, ok := field.Interface().(StructReflector); ok {
   543 		fieldName := s.parseFieldName(tpField.Name, rawName)
   604 		fieldName := s.parseFieldName(tpField.Name, rawName)
   544 		if len(fieldName) == 0 || !field.CanSet() {
   605 		if len(fieldName) == 0 || !field.CanSet() {
   545 			continue
   606 			continue
   546 		}
   607 		}
   547 
   608 
   548 		if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
   609 		if extends && tpField.Anonymous && (tpField.Type.Kind() == reflect.Ptr || tpField.Type.Kind() == reflect.Struct) {
       
   610 			if err := s.reflectFrom(field); err != nil {
       
   611 				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
       
   612 			}
       
   613 			continue
       
   614 		}
       
   615 
       
   616 		if (tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct) ||
   549 			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
   617 			(tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
   550 			// Note: The only error here is section doesn't exist.
   618 			// Note: The only error here is section doesn't exist.
   551 			sec, err := s.f.GetSection(fieldName)
   619 			sec, err := s.f.GetSection(fieldName)
   552 			if err != nil {
   620 			if err != nil {
   553 				// Note: fieldName can never be empty here, ignore error.
   621 				// Note: fieldName can never be empty here, ignore error.
   558 			if len(sec.Comment) == 0 {
   626 			if len(sec.Comment) == 0 {
   559 				sec.Comment = tpField.Tag.Get("comment")
   627 				sec.Comment = tpField.Tag.Get("comment")
   560 			}
   628 			}
   561 
   629 
   562 			if err = sec.reflectFrom(field); err != nil {
   630 			if err = sec.reflectFrom(field); err != nil {
   563 				return fmt.Errorf("error reflecting field %q: %v", fieldName, err)
   631 				return fmt.Errorf("reflect from field %q: %v", fieldName, err)
   564 			}
   632 			}
   565 			continue
   633 			continue
   566 		}
   634 		}
   567 
   635 
       
   636 		if allowNonUnique && tpField.Type.Kind() == reflect.Slice {
       
   637 			slice := field.Slice(0, field.Len())
       
   638 			if field.Len() == 0 {
       
   639 				return nil
       
   640 			}
       
   641 			sliceOf := field.Type().Elem().Kind()
       
   642 
       
   643 			for i := 0; i < field.Len(); i++ {
       
   644 				if sliceOf != reflect.Struct && sliceOf != reflect.Ptr {
       
   645 					return fmt.Errorf("field %q is not a slice of pointer or struct", fieldName)
       
   646 				}
       
   647 
       
   648 				sec, err := s.f.NewSection(fieldName)
       
   649 				if err != nil {
       
   650 					return err
       
   651 				}
       
   652 
       
   653 				// Add comment from comment tag
       
   654 				if len(sec.Comment) == 0 {
       
   655 					sec.Comment = tpField.Tag.Get("comment")
       
   656 				}
       
   657 
       
   658 				if err := sec.reflectFrom(slice.Index(i)); err != nil {
       
   659 					return fmt.Errorf("reflect from field %q: %v", fieldName, err)
       
   660 				}
       
   661 			}
       
   662 			continue
       
   663 		}
       
   664 
       
   665 		// Note: Same reason as section.
   568 		key, err := s.GetKey(fieldName)
   666 		key, err := s.GetKey(fieldName)
   569 		if err != nil {
   667 		if err != nil {
   570 			key, _ = s.NewKey(fieldName, "")
   668 			key, _ = s.NewKey(fieldName, "")
   571 		}
   669 		}
   572 
   670 
   575 			key.Comment = tpField.Tag.Get("comment")
   673 			key.Comment = tpField.Tag.Get("comment")
   576 		}
   674 		}
   577 
   675 
   578 		delim := parseDelim(tpField.Tag.Get("delim"))
   676 		delim := parseDelim(tpField.Tag.Get("delim"))
   579 		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil {
   677 		if err = reflectWithProperType(tpField.Type, key, field, delim, allowShadow); err != nil {
   580 			return fmt.Errorf("error reflecting field %q: %v", fieldName, err)
   678 			return fmt.Errorf("reflect field %q: %v", fieldName, err)
   581 		}
   679 		}
   582 
   680 
   583 	}
   681 	}
   584 	return nil
   682 	return nil
   585 }
   683 }
   586 
   684 
   587 // ReflectFrom reflects secion from given struct.
   685 // ReflectFrom reflects section from given struct. It overwrites existing ones.
   588 func (s *Section) ReflectFrom(v interface{}) error {
   686 func (s *Section) ReflectFrom(v interface{}) error {
   589 	typ := reflect.TypeOf(v)
   687 	typ := reflect.TypeOf(v)
   590 	val := reflect.ValueOf(v)
   688 	val := reflect.ValueOf(v)
       
   689 
       
   690 	if s.name != DefaultSection && s.f.options.AllowNonUniqueSections &&
       
   691 		(typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr) {
       
   692 		// Clear sections to make sure none exists before adding the new ones
       
   693 		s.f.DeleteSection(s.name)
       
   694 
       
   695 		if typ.Kind() == reflect.Ptr {
       
   696 			sec, err := s.f.NewSection(s.name)
       
   697 			if err != nil {
       
   698 				return err
       
   699 			}
       
   700 			return sec.reflectFrom(val.Elem())
       
   701 		}
       
   702 
       
   703 		slice := val.Slice(0, val.Len())
       
   704 		sliceOf := val.Type().Elem().Kind()
       
   705 		if sliceOf != reflect.Ptr {
       
   706 			return fmt.Errorf("not a slice of pointers")
       
   707 		}
       
   708 
       
   709 		for i := 0; i < slice.Len(); i++ {
       
   710 			sec, err := s.f.NewSection(s.name)
       
   711 			if err != nil {
       
   712 				return err
       
   713 			}
       
   714 
       
   715 			err = sec.reflectFrom(slice.Index(i))
       
   716 			if err != nil {
       
   717 				return fmt.Errorf("reflect from %dth field: %v", i, err)
       
   718 			}
       
   719 		}
       
   720 
       
   721 		return nil
       
   722 	}
       
   723 
   591 	if typ.Kind() == reflect.Ptr {
   724 	if typ.Kind() == reflect.Ptr {
   592 		typ = typ.Elem()
       
   593 		val = val.Elem()
   725 		val = val.Elem()
   594 	} else {
   726 	} else {
   595 		return errors.New("cannot reflect from non-pointer struct")
   727 		return errors.New("not a pointer to a struct")
   596 	}
   728 	}
   597 
   729 
   598 	return s.reflectFrom(val)
   730 	return s.reflectFrom(val)
   599 }
   731 }
   600 
   732