Skip to content

Commit

Permalink
[text] Apple quotes plist characters differently from GNUStep.
Browse files Browse the repository at this point in the history
Add another quotable table, and choose the right one based on format.
  • Loading branch information
DHowett committed Dec 13, 2013
1 parent 8da3321 commit bff50a2
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
25 changes: 18 additions & 7 deletions text.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
type textPlistGenerator struct {
writer io.Writer
format int

quotableTable *[4]uint64
}

var (
Expand All @@ -25,7 +27,7 @@ func (p *textPlistGenerator) generateDocument(pval *plistValue) {
p.writePlistValue(pval)
}

func plistQuotedString(str string) string {
func (p *textPlistGenerator) plistQuotedString(str string) string {
if str == "" {
return `""`
}
Expand All @@ -46,7 +48,7 @@ func plistQuotedString(str string) string {
s += us
} else {
c := uint8(r)
if quotable[c/64]&(1<<(c%64)) > 0 {
if (*p.quotableTable)[c/64]&(1<<(c%64)) > 0 {
quot = true
}

Expand Down Expand Up @@ -87,7 +89,7 @@ func (p *textPlistGenerator) writePlistValue(pval *plistValue) {
dict := pval.value.(*dictionary)
dict.populateArrays()
for i, k := range dict.keys {
io.WriteString(p.writer, plistQuotedString(k)+`=`)
io.WriteString(p.writer, p.plistQuotedString(k)+`=`)
p.writePlistValue(dict.values[i])
p.writer.Write([]byte(`;`))
}
Expand All @@ -101,7 +103,7 @@ func (p *textPlistGenerator) writePlistValue(pval *plistValue) {
}
p.writer.Write([]byte(`)`))
case String:
io.WriteString(p.writer, plistQuotedString(pval.value.(string)))
io.WriteString(p.writer, p.plistQuotedString(pval.value.(string)))
case Integer:
if p.format == GNUStepFormat {
p.writer.Write([]byte(`<*I`))
Expand Down Expand Up @@ -148,13 +150,21 @@ func (p *textPlistGenerator) writePlistValue(pval *plistValue) {
io.WriteString(p.writer, pval.value.(time.Time).In(time.UTC).Format(textPlistTimeLayout))
p.writer.Write([]byte(`>`))
} else {
io.WriteString(p.writer, plistQuotedString(pval.value.(time.Time).In(time.UTC).Format(textPlistTimeLayout)))
io.WriteString(p.writer, p.plistQuotedString(pval.value.(time.Time).In(time.UTC).Format(textPlistTimeLayout)))
}
}
}

func newTextPlistGenerator(w io.Writer, format int) *textPlistGenerator {
return &textPlistGenerator{w, format}
table := &osQuotable
if format == GNUStepFormat {
table = &gsQuotable
}
return &textPlistGenerator{
writer: w,
format: format,
quotableTable: table,
}
}

type byteReader interface {
Expand Down Expand Up @@ -274,7 +284,8 @@ func (p *textPlistParser) parseUnquotedString() *plistValue {
panic(err)
}
// if we encounter a character that must be quoted, we're done.
if quotable[c/64]&(1<<(c%64)) > 0 {
// the GNUStep quote table is more lax here, so we use it instead of the OpenStep one.
if gsQuotable[c/64]&(1<<(c%64)) > 0 {
p.reader.UnreadByte()
break
}
Expand Down
10 changes: 9 additions & 1 deletion text_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ package plist
// Bitmap of characters that must be inside a quoted string
// when written to an old-style property list
// Low bits represent lower characters, and each uint64 represents 64 characters.
var quotable = [4]uint64{
var gsQuotable = [4]uint64{
0x78001385ffffffff,
0xa800000138000000,
0xffffffffffffffff,
0xffffffffffffffff,
}

// 7f instead of 3f in the top line: CFOldStylePlist.c says . is valid, but they quote it.
var osQuotable = [4]uint64{
0xf4007f6fffffffff,
0xf8000001f8000001,
0xffffffffffffffff,
0xffffffffffffffff,
}

var whitespace = [4]uint64{
0x0000000100003f00,
0x0000000000000000,
Expand Down

0 comments on commit bff50a2

Please sign in to comment.