flatten.go
func flattenScalars(
	output []interface{},
	input []interface{},
	missingKeyName func() interface{},
) []interface{} {
	for len(input) > 0 {
		var needsFixing bool

		if isOdd(len(input)) {
			needsFixing = true
		} else {
			// check for non-string in an even position
			for i := 0; i < len(input); i += 2 {
				switch input[i].(type) {
				case string, missingKeyT:
					break
				default:
					needsFixing = true
				}
			}
		}

		if !needsFixing {
			output = append(output, input...)
			input = nil
			continue
		}

		// Build a classification of items in the array. This will be used
		// to determine the most likely position of missing key(s).
		// TODO(jpj): this could be allocated from a sync.Pool
		type classificationT byte
		const (
			stringKey classificationT = iota
			stringPossibleKey
			stringValue
			errorVar
			otherType
		)
		classifications := make([]classificationT, len(input))

		for i := 0; i < len(input); i++ {
			switch v := input[i].(type) {
			case string:
				if _, ok := knownKeys[v]; ok {
					classifications[i] = stringKey
				} else if possibleKeyRE.MatchString(v) {
					classifications[i] = stringPossibleKey
				} else {
					classifications[i] = stringValue
				}
			case missingKeyT:
				classifications[i] = stringKey
			default:
				classifications[i] = otherType
			}
		}

		if len(input) == 1 {
			// Only one parameter, give it a key name. If it is a string it might
			// be the 'msg' parameter.
			output = append(output, missingKeyName())
			output = append(output, input[0])
			input = nil
			continue
		}

		// Function to insert a key before an item that is either unlikely
		// or impossible to be a key. Returns true if something was inserted.
		// Note that this function assumes that there are at least two items
		// in the slice, which is guaranteed at this point.
		insertKeyFromBack := func(c classificationT) bool {
			// Start at the second last item
			for i := len(input) - 2; i > 0; i -= 2 {
				if classifications[i] == c {
					if isEven(len(input)) {
						input = insertKeyAt(input, i, missingKeyName())
					} else {
						input = insertKeyAt(input, i+1, missingKeyName())
					}
					return true
				}
			}
			return false
		}
		if insertKeyFromBack(otherType) {
			continue
		}
		if insertKeyFromBack(errorVar) {
			continue
		}
		if insertKeyFromBack(stringValue) {
			continue
		}
		insertKeyFromFront := func(c classificationT) bool {
			for i := 0; i < len(input); i += 2 {
				if classifications[i] == c {
					input = insertKeyAt(input, i, missingKeyName())
					return true
				}
			}
			return false
		}
		if insertKeyFromFront(otherType) {
			continue
		}
		if insertKeyFromFront(errorVar) {
			continue
		}
		if insertKeyFromFront(stringValue) {
			continue
		}
		if insertKeyFromFront(stringPossibleKey) {
			continue
		}
		input = insertKeyAt(input, 0, missingKeyName())
	}
	return output
}
func flattenScalars(
	output []interface{},
	input []interface{},
	missingKeyName func() interface{},
) []interface{} {
	for len(input) > 0 {
		var needsFixing bool

		if isOdd(len(input)) {
			needsFixing = true
		} else {
			// check for non-string in an even position
			for i := 0; i < len(input); i += 2 {
				switch input[i].(type) {
				case string, missingKeyT:
					break
				default:
					needsFixing = true
				}
			}
		}

		if !needsFixing {
			output = append(output, input...)
			input = nil
			continue
		}

		// Build a classification of items in the array. This will be used
		// to determine the most likely position of missing key(s).
		// TODO(jpj): this could be allocated from a sync.Pool
		type classificationT byte
		const (
			stringKey classificationT = iota
			stringPossibleKey
			stringValue
			errorVar
			otherType
		)
		classifications := make([]classificationT, len(input))

		for i := 0; i < len(input); i++ {
			switch v := input[i].(type) {
			case string:
				if _, ok := knownKeys[v]; ok {
					classifications[i] = stringKey
				} else if possibleKeyRE.MatchString(v) {
					classifications[i] = stringPossibleKey
				} else {
					classifications[i] = stringValue
				}
			case missingKeyT:
				classifications[i] = stringKey
			default:
				classifications[i] = otherType
			}
		}

		if len(input) == 1 {
			// Only one parameter, give it a key name. If it is a string it might
			// be the 'msg' parameter.
			output = append(output, missingKeyName())
			output = append(output, input[0])
			input = nil
			continue
		}

		// Function to insert a key before an item that is either unlikely
		// or impossible to be a key. Returns true if something was inserted.
		// Note that this function assumes that there are at least two items
		// in the slice, which is guaranteed at this point.
		insertKeyFromBack := func(c classificationT) bool {
			// Start at the second last item
			for i := len(input) - 2; i > 0; i -= 2 {
				if classifications[i] == c {
					if isEven(len(input)) {
						input = insertKeyAt(input, i, missingKeyName())
					} else {
						input = insertKeyAt(input, i+1, missingKeyName())
					}
					return true
				}
			}
			return false
		}
		if insertKeyFromBack(otherType) {
			continue
		}
		if insertKeyFromBack(errorVar) {
			continue
		}
		if insertKeyFromBack(stringValue) {
			continue
		}
		insertKeyFromFront := func(c classificationT) bool {
			for i := 0; i < len(input); i += 2 {
				if classifications[i] == c {
					input = insertKeyAt(input, i, missingKeyName())
					return true
				}
			}
			return false
		}
		if insertKeyFromFront(otherType) {
			continue
		}
		if insertKeyFromFront(errorVar) {
			continue
		}
		if insertKeyFromFront(stringValue) {
			continue
		}
		if insertKeyFromFront(stringPossibleKey) {
			continue
		}
		input = insertKeyAt(input, 0, missingKeyName())
	}
	return output
}
func flattenScalars ( output [ ] interface { } , input [ ] interface { } , missingKeyName func ( ) interface { } , ) [ ] interface { } { for len ( input ) > 0 { var needsFixing bool if isOdd ( len ( input ) ) { needsFixing = true } else { // check for non-string in an even position for i := 0 ; i < len ( input ) ; i += 2 { switch input [ i ] . ( type ) { case string , missingKeyT : break default : needsFixing = true } } } if ! needsFixing { output = append ( output , input ... ) input = nil continue } // Build a classification of items in the array. This will be used // to determine the most likely position of missing key(s). // TODO(jpj): this could be allocated from a sync.Pool type classificationT byte const ( stringKey classificationT = iota stringPossibleKey stringValue errorVar otherType ) classifications := make ( [ ] classificationT , len ( input ) ) for i := 0 ; i < len ( input ) ; i ++ { switch v := input [ i ] . ( type ) { case string : if _ , ok := knownKeys [ v ] ; ok { classifications [ i ] = stringKey } else if possibleKeyRE . MatchString ( v ) { classifications [ i ] = stringPossibleKey } else { classifications [ i ] = stringValue } case missingKeyT : classifications [ i ] = stringKey default : classifications [ i ] = otherType } } if len ( input ) == 1 { // Only one parameter, give it a key name. If it is a string it might // be the 'msg' parameter. output = append ( output , missingKeyName ( ) ) output = append ( output , input [ 0 ] ) input = nil continue } // Function to insert a key before an item that is either unlikely // or impossible to be a key. Returns true if something was inserted. // Note that this function assumes that there are at least two items // in the slice, which is guaranteed at this point. insertKeyFromBack := func ( c classificationT ) bool { // Start at the second last item for i := len ( input ) - 2 ; i > 0 ; i -= 2 { if classifications [ i ] == c { if isEven ( len ( input ) ) { input = insertKeyAt ( input , i , missingKeyName ( ) ) } else { input = insertKeyAt ( input , i + 1 , missingKeyName ( ) ) } return true } } return false } if insertKeyFromBack ( otherType ) { continue } if insertKeyFromBack ( errorVar ) { continue } if insertKeyFromBack ( stringValue ) { continue } insertKeyFromFront := func ( c classificationT ) bool { for i := 0 ; i < len ( input ) ; i += 2 { if classifications [ i ] == c { input = insertKeyAt ( input , i , missingKeyName ( ) ) return true } } return false } if insertKeyFromFront ( otherType ) { continue } if insertKeyFromFront ( errorVar ) { continue } if insertKeyFromFront ( stringValue ) { continue } if insertKeyFromFront ( stringPossibleKey ) { continue } input = insertKeyAt ( input , 0 , missingKeyName ( ) ) } return output }
// flattenScalars adjusts a list of items, none of which are keyvalsers.
//
// Ideally the list will have an even number of items, with strings in the
// even indices. If it doesn't, this function will fix it.
flattenScalars adjusts a list of items none of which are keyvalsers . Ideally the list will have an even number of items with strings in the even indices . If it doesn t this function will fix it .