@@ -527,78 +527,90 @@ func parseName(line *string) (*types.Name, error) {
527527 return & nameObj , nil
528528}
529529
530+ func insertKey (d types.Dict , key string , val types.Object , usesHexCodes bool ) (bool , error ) {
531+ var duplicateKeyErr bool
532+
533+ if ! usesHexCodes {
534+ if strings .IndexByte (key , '#' ) < 0 {
535+ // Avoid expensive "DecodeName".
536+ if _ , found := d [key ]; ! found {
537+ d [key ] = val
538+ } else {
539+ duplicateKeyErr = true
540+ }
541+ } else {
542+ duplicateKeyErr = d .Insert (key , val )
543+ usesHexCodes = true
544+ }
545+ } else {
546+ duplicateKeyErr = d .Insert (key , val )
547+ }
548+
549+ if duplicateKeyErr {
550+ // for now we digest duplicate keys.
551+ // TODO
552+ // if !validationRelaxed {
553+ // return false, errDictionaryDuplicateKey
554+ // }
555+ // if log.CLIEnabled() {
556+ // log.CLI.Printf("ParseDict: digesting duplicate key\n")
557+ // }
558+ _ = duplicateKeyErr
559+ }
560+
561+ if log .ParseEnabled () {
562+ log .Parse .Printf ("ParseDict: dict[%s]=%v\n " , key , val )
563+ }
564+
565+ return usesHexCodes , nil
566+ }
567+
530568func processDictKeys (line * string , relaxed bool ) (types.Dict , error ) {
531569 l := * line
532570 var eol bool
533- var hasNames bool
571+ var usesHexCodes bool
534572 d := types .NewDict ()
535573 for ! strings .HasPrefix (l , ">>" ) {
536- key , err := parseName (& l )
574+ keyName , err := parseName (& l )
537575 if err != nil {
538576 return nil , err
539577 }
540578 if log .ParseEnabled () {
541- log .Parse .Printf ("ParseDict: key = %s\n " , key )
579+ log .Parse .Printf ("ParseDict: key = %s\n " , keyName )
542580 }
543581
544- // position to first non whitespace after key
582+ // Position to first non whitespace after key.
545583 l , eol = trimLeftSpace (l , relaxed )
546584
547585 if len (l ) == 0 {
548586 if log .ParseEnabled () {
549587 log .Parse .Println ("ParseDict: only whitespace after key" )
550588 }
551- // only whitespace after key
589+ // Only whitespace after key.
552590 return nil , errDictionaryNotTerminated
553591 }
554592
555- // Fix for #252:
556- // For dicts with kv pairs terminated by eol we accept a missing value as an empty string.
593+ var val types. Object
594+
557595 if eol {
558- obj := types .StringLiteral ("" )
559- if log .ParseEnabled () {
560- log .Parse .Printf ("ParseDict: dict[%s]=%v\n " , key , obj )
561- }
562- stringKey := string (* key )
563- if ! hasNames {
564- // Avoid expensive "DecodeName" on existing keys in "Insert".
565- if _ , found := d [stringKey ]; found {
566- return nil , errDictionaryDuplicateKey
567- }
568- d [stringKey ] = obj
569- hasNames = strings .IndexByte (stringKey , '#' ) >= 0
570- } else {
571- if ok := d .Insert (stringKey , obj ); ! ok {
572- return nil , errDictionaryDuplicateKey
573- }
596+ // #252: For dicts with kv pairs terminated by eol we accept a missing value as an empty string.
597+ val = types .StringLiteral ("" )
598+ } else {
599+ if val , err = ParseObject (& l ); err != nil {
600+ return nil , err
574601 }
575- continue
576- }
577-
578- obj , err := ParseObject (& l )
579- if err != nil {
580- return nil , err
581602 }
582603
583604 // Specifying the null object as the value of a dictionary entry (7.3.7, "Dictionary Objects")
584- // hall be equivalent to omitting the entry entirely.
585- if obj != nil {
586- stringKey := string (* key )
587- if ! hasNames {
588- // Avoid expensive "DecodeName" on existing keys in "Insert".
589- if _ , found := d [stringKey ]; ! found {
590- d [stringKey ] = obj
591- hasNames = strings .IndexByte (stringKey , '#' ) >= 0
592- }
593- } else {
594- d .Insert (stringKey , obj )
605+ // shall be equivalent to omitting the entry entirely.
606+ if val != nil {
607+ detectedHexCodes , err := insertKey (d , string (* keyName ), val , usesHexCodes )
608+ if err != nil {
609+ return nil , err
595610 }
596- if log . ParseEnabled () {
597- log . Parse . Printf ( "ParseDict: dict[%s]=%v \n " , key , obj )
611+ if ! usesHexCodes && detectedHexCodes {
612+ usesHexCodes = true
598613 }
599- // if ok := d.Insert(string(*key), obj); !ok {
600- // return nil, errDictionaryDuplicateKey
601- // }
602614 }
603615
604616 // We are positioned on the char behind the last parsed dict value.
0 commit comments