func configFromReaderWithConfig(reader io.Reader, cfg *CfgParseParams) (*logConfig, error) {
	config, err := unmarshalConfig(reader)
	if err != nil {
		return nil, err
	}
	if config.name != seelogConfigId {
		return nil, errors.New("Root xml tag must be '" + seelogConfigId + "'")
	}
	err = checkUnexpectedAttribute(
		config,
		minLevelId,
		maxLevelId,
		levelsId,
		loggerTypeFromStringAttr,
		asyncLoggerIntervalAttr,
		adaptLoggerMinIntervalAttr,
		adaptLoggerMaxIntervalAttr,
		adaptLoggerCriticalMsgCountAttr,
	)
	if err != nil {
		return nil, err
	}
	err = checkExpectedElements(config, optionalElement(outputsId), optionalElement(formatsId), optionalElement(exceptionsId))
	if err != nil {
		return nil, err
	}
	constraints, err := getConstraints(config)
	if err != nil {
		return nil, err
	}
	exceptions, err := getExceptions(config)
	if err != nil {
		return nil, err
	}
	err = checkDistinctExceptions(exceptions)
	if err != nil {
		return nil, err
	}
	formats, err := getFormats(config)
	if err != nil {
		return nil, err
	}
	dispatcher, err := getOutputsTree(config, formats, cfg)
	if err != nil {
		if dispatcher != nil {
			dispatcher.Close()
		}
		return nil, err
	}
	loggerType, logData, err := getloggerTypeFromStringData(config)
	if err != nil {
		return nil, err
	}
	return newConfig(constraints, exceptions, dispatcher, loggerType, logData, cfg)
}
configFromReader parses data from a given reader.
Returns parsed config which can be used to create logger in case no errors occured.
Returns error if format is incorrect or anything happened.
package seelog
import (
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
)
const (
	seelogConfigId                   = "seelog"
	outputsId                        = "outputs"
	formatsId                        = "formats"
	minLevelId                       = "minlevel"
	maxLevelId                       = "maxlevel"
	levelsId                         = "levels"
	exceptionsId                     = "exceptions"
	exceptionId                      = "exception"
	funcPatternId                    = "funcpattern"
	filePatternId                    = "filepattern"
	formatId                         = "format"
	formatAttrId                     = "format"
	formatKeyAttrId                  = "id"
	outputFormatId                   = "formatid"
	pathId                           = "path"
	fileWriterId                     = "file"
	smtpWriterId                     = "smtp"
	senderaddressId                  = "senderaddress"
	senderNameId                     = "sendername"
	recipientId                      = "recipient"
	addressId                        = "address"
	hostNameId                       = "hostname"
	hostPortId                       = "hostport"
	userNameId                       = "username"
	userPassId                       = "password"
	cACertDirpathId                  = "cacertdirpath"
	splitterDispatcherId             = "splitter"
	consoleWriterId                  = "console"
	customReceiverId                 = "custom"
	customNameAttrId                 = "name"
	customNameDataAttrPrefix         = "data-"
	filterDispatcherId               = "filter"
	filterLevelsAttrId               = "levels"
	rollingfileWriterId              = "rollingfile"
	rollingFileTypeAttr              = "type"
	rollingFilePathAttr              = "filename"
	rollingFileMaxSizeAttr           = "maxsize"
	rollingFileMaxRollsAttr          = "maxrolls"
	rollingFileDataPatternAttr       = "datepattern"
	rollingFileArchiveAttr           = "archivetype"
	rollingFileArchivePathAttr       = "archivepath"
	bufferedWriterId                 = "buffered"
	bufferedSizeAttr                 = "size"
	bufferedFlushPeriodAttr          = "flushperiod"
	loggerTypeFromStringAttr         = "type"
	asyncLoggerIntervalAttr          = "asyncinterval"
	adaptLoggerMinIntervalAttr       = "mininterval"
	adaptLoggerMaxIntervalAttr       = "maxinterval"
	adaptLoggerCriticalMsgCountAttr  = "critmsgcount"
	predefinedPrefix                 = "std:"
	connWriterId                     = "conn"
	connWriterAddrAttr               = "addr"
	connWriterNetAttr                = "net"
	connWriterReconnectOnMsgAttr     = "reconnectonmsg"
	connWriterUseTLSAttr             = "tls"
	connWriterInsecureSkipVerifyAttr = "insecureskipverify"
)
type CustomReceiverProducer func(CustomReceiverInitArgs) (CustomReceiver, error)
type CfgParseParams struct {
	CustomReceiverProducers map[string]CustomReceiverProducer
}
func (cfg *CfgParseParams) String() string {
	return fmt.Sprintf("CfgParams: {custom_recs=%d}", len(cfg.CustomReceiverProducers))
}
type elementMapEntry struct {
	constructor func(node *xmlNode, formatFromParent *formatter, formats map[string]*formatter, cfg *CfgParseParams) (interface{}, error)
}
var elementMap map[string]elementMapEntry
var predefinedFormats map[string]*formatter
func init() {
	elementMap = map[string]elementMapEntry{
		fileWriterId:         {createfileWriter},
		splitterDispatcherId: {createSplitter},
		customReceiverId:     {createCustomReceiver},
		filterDispatcherId:   {createFilter},
		consoleWriterId:      {createConsoleWriter},
		rollingfileWriterId:  {createRollingFileWriter},
		bufferedWriterId:     {createbufferedWriter},
		smtpWriterId:         {createSmtpWriter},
		connWriterId:         {createconnWriter},
	}
	err := fillPredefinedFormats()
	if err != nil {
		panic(fmt.Sprintf("Seelog couldn't start: predefined formats creation failed. Error: %s", err.Error()))
	}
}
func fillPredefinedFormats() error {
	predefinedFormatsWithoutPrefix := map[string]string{
		"xml-debug":       `<time>%Ns</time><lev>%Lev</lev><msg>%Msg</msg><path>%RelFile</path><func>%Func</func><line>%Line</line>`,
		"xml-debug-short": `<t>%Ns</t><l>%l</l><m>%Msg</m><p>%RelFile</p><f>%Func</f>`,
		"xml":             `<time>%Ns</time><lev>%Lev</lev><msg>%Msg</msg>`,
		"xml-short":       `<t>%Ns</t><l>%l</l><m>%Msg</m>`,
		"json-debug":       `{"time":%Ns,"lev":"%Lev","msg":"%Msg","path":"%RelFile","func":"%Func","line":"%Line"}`,
		"json-debug-short": `{"t":%Ns,"l":"%Lev","m":"%Msg","p":"%RelFile","f":"%Func"}`,
		"json":             `{"time":%Ns,"lev":"%Lev","msg":"%Msg"}`,
		"json-short":       `{"t":%Ns,"l":"%Lev","m":"%Msg"}`,
		"debug":       `[%LEVEL] %RelFile:%Func.%Line %Date %Time %Msg%n`,
		"debug-short": `[%LEVEL] %Date %Time %Msg%n`,
		"fast":        `%Ns %l %Msg%n`,
	}
	predefinedFormats = make(map[string]*formatter)
	for formatKey, format := range predefinedFormatsWithoutPrefix {
		formatter, err := newFormatter(format)
		if err != nil {
			return err
		}
		predefinedFormats[predefinedPrefix+formatKey] = formatter
	}
	return nil
}
func configFromReader(reader io.Reader) (*logConfig, error) {
	return configFromReaderWithConfig(reader, nil)
}