vendor/gopkg.in/ini.v1/parser.go
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
   129 	line := string(in)
   129 	line := string(in)
   130 
   130 
   131 	// Check if key name surrounded by quotes.
   131 	// Check if key name surrounded by quotes.
   132 	var keyQuote string
   132 	var keyQuote string
   133 	if line[0] == '"' {
   133 	if line[0] == '"' {
   134 		if len(line) > 6 && string(line[0:3]) == `"""` {
   134 		if len(line) > 6 && line[0:3] == `"""` {
   135 			keyQuote = `"""`
   135 			keyQuote = `"""`
   136 		} else {
   136 		} else {
   137 			keyQuote = `"`
   137 			keyQuote = `"`
   138 		}
   138 		}
   139 	} else if line[0] == '`' {
   139 	} else if line[0] == '`' {
   162 
   162 
   163 	endIdx = strings.IndexAny(line, delimiters)
   163 	endIdx = strings.IndexAny(line, delimiters)
   164 	if endIdx < 0 {
   164 	if endIdx < 0 {
   165 		return "", -1, ErrDelimiterNotFound{line}
   165 		return "", -1, ErrDelimiterNotFound{line}
   166 	}
   166 	}
       
   167 	if endIdx == 0 {
       
   168 		return "", -1, ErrEmptyKeyName{line}
       
   169 	}
       
   170 
   167 	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
   171 	return strings.TrimSpace(line[0:endIdx]), endIdx + 1, nil
   168 }
   172 }
   169 
   173 
   170 func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
   174 func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
   171 	for {
   175 	for {
   230 		}
   234 		}
   231 		return "", nil
   235 		return "", nil
   232 	}
   236 	}
   233 
   237 
   234 	var valQuote string
   238 	var valQuote string
   235 	if len(line) > 3 && string(line[0:3]) == `"""` {
   239 	if len(line) > 3 && line[0:3] == `"""` {
   236 		valQuote = `"""`
   240 		valQuote = `"""`
   237 	} else if line[0] == '`' {
   241 	} else if line[0] == '`' {
   238 		valQuote = "`"
   242 		valQuote = "`"
   239 	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
   243 	} else if p.options.UnescapeValueDoubleQuotes && line[0] == '"' {
   240 		valQuote = `"`
   244 		valQuote = `"`
   287 	// Trim single and double quotes
   291 	// Trim single and double quotes
   288 	if (hasSurroundedQuote(line, '\'') ||
   292 	if (hasSurroundedQuote(line, '\'') ||
   289 		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
   293 		hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
   290 		line = line[1 : len(line)-1]
   294 		line = line[1 : len(line)-1]
   291 	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
   295 	} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
   292 		if strings.Contains(line, `\;`) {
   296 		line = strings.ReplaceAll(line, `\;`, ";")
   293 			line = strings.Replace(line, `\;`, ";", -1)
   297 		line = strings.ReplaceAll(line, `\#`, "#")
   294 		}
       
   295 		if strings.Contains(line, `\#`) {
       
   296 			line = strings.Replace(line, `\#`, "#", -1)
       
   297 		}
       
   298 	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
   298 	} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
   299 		return p.readPythonMultilines(line, bufferSize)
   299 		return p.readPythonMultilines(line, bufferSize)
   300 	}
   300 	}
   301 
   301 
   302 	return line, nil
   302 	return line, nil
   304 
   304 
   305 func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
   305 func (p *parser) readPythonMultilines(line string, bufferSize int) (string, error) {
   306 	parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
   306 	parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
   307 	peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
   307 	peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
   308 
   308 
   309 	indentSize := 0
       
   310 	for {
   309 	for {
   311 		peekData, peekErr := peekBuffer.ReadBytes('\n')
   310 		peekData, peekErr := peekBuffer.ReadBytes('\n')
   312 		if peekErr != nil {
   311 		if peekErr != nil && peekErr != io.EOF {
   313 			if peekErr == io.EOF {
       
   314 				p.debug("readPythonMultilines: io.EOF, peekData: %q, line: %q", string(peekData), line)
       
   315 				return line, nil
       
   316 			}
       
   317 
       
   318 			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
   312 			p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
   319 			return "", peekErr
   313 			return "", peekErr
   320 		}
   314 		}
   321 
   315 
   322 		p.debug("readPythonMultilines: parsing %q", string(peekData))
   316 		p.debug("readPythonMultilines: parsing %q", string(peekData))
   331 		if len(peekMatches) != 3 {
   325 		if len(peekMatches) != 3 {
   332 			p.debug("readPythonMultilines: end of value, got: %q", line)
   326 			p.debug("readPythonMultilines: end of value, got: %q", line)
   333 			return line, nil
   327 			return line, nil
   334 		}
   328 		}
   335 
   329 
   336 		// Determine indent size and line prefix.
       
   337 		currentIndentSize := len(peekMatches[1])
       
   338 		if indentSize < 1 {
       
   339 			indentSize = currentIndentSize
       
   340 			p.debug("readPythonMultilines: indent size is %d", indentSize)
       
   341 		}
       
   342 
       
   343 		// Make sure each line is indented at least as far as first line.
       
   344 		if currentIndentSize < indentSize {
       
   345 			p.debug("readPythonMultilines: end of value, current indent: %d, expected indent: %d, line: %q", currentIndentSize, indentSize, line)
       
   346 			return line, nil
       
   347 		}
       
   348 
       
   349 		// Advance the parser reader (buffer) in-sync with the peek buffer.
   330 		// Advance the parser reader (buffer) in-sync with the peek buffer.
   350 		_, err := p.buf.Discard(len(peekData))
   331 		_, err := p.buf.Discard(len(peekData))
   351 		if err != nil {
   332 		if err != nil {
   352 			p.debug("readPythonMultilines: failed to skip to the end, returning error")
   333 			p.debug("readPythonMultilines: failed to skip to the end, returning error")
   353 			return "", err
   334 			return "", err
   354 		}
   335 		}
   355 
   336 
   356 		// Handle indented empty line.
   337 		line += "\n" + peekMatches[0]
   357 		line += "\n" + peekMatches[1][indentSize:] + peekMatches[2]
       
   358 	}
   338 	}
   359 }
   339 }
   360 
   340 
   361 // parse parses data through an io.Reader.
   341 // parse parses data through an io.Reader.
   362 func (f *File) parse(reader io.Reader) (err error) {
   342 func (f *File) parse(reader io.Reader) (err error) {
   463 			section.Comment = strings.TrimSpace(p.comment.String())
   443 			section.Comment = strings.TrimSpace(p.comment.String())
   464 
   444 
   465 			// Reset auto-counter and comments
   445 			// Reset auto-counter and comments
   466 			p.comment.Reset()
   446 			p.comment.Reset()
   467 			p.count = 1
   447 			p.count = 1
       
   448 			// Nested values can't span sections
       
   449 			isLastValueEmpty = false
   468 
   450 
   469 			inUnparseableSection = false
   451 			inUnparseableSection = false
   470 			for i := range f.options.UnparseableSections {
   452 			for i := range f.options.UnparseableSections {
   471 				if f.options.UnparseableSections[i] == name ||
   453 				if f.options.UnparseableSections[i] == name ||
   472 					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) {
   454 					((f.options.Insensitive || f.options.InsensitiveSections) && strings.EqualFold(f.options.UnparseableSections[i], name)) {
   483 			continue
   465 			continue
   484 		}
   466 		}
   485 
   467 
   486 		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
   468 		kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
   487 		if err != nil {
   469 		if err != nil {
       
   470 			switch {
   488 			// Treat as boolean key when desired, and whole line is key name.
   471 			// Treat as boolean key when desired, and whole line is key name.
   489 			if IsErrDelimiterNotFound(err) {
   472 			case IsErrDelimiterNotFound(err):
   490 				switch {
   473 				switch {
   491 				case f.options.AllowBooleanKeys:
   474 				case f.options.AllowBooleanKeys:
   492 					kname, err := p.readValue(line, parserBufferSize)
   475 					kname, err := p.readValue(line, parserBufferSize)
   493 					if err != nil {
   476 					if err != nil {
   494 						return err
   477 						return err
   502 					continue
   485 					continue
   503 
   486 
   504 				case f.options.SkipUnrecognizableLines:
   487 				case f.options.SkipUnrecognizableLines:
   505 					continue
   488 					continue
   506 				}
   489 				}
       
   490 			case IsErrEmptyKeyName(err) && f.options.SkipUnrecognizableLines:
       
   491 				continue
   507 			}
   492 			}
   508 			return err
   493 			return err
   509 		}
   494 		}
   510 
   495 
   511 		// Auto increment.
   496 		// Auto increment.