kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/util/encoding/rdf/rdf.go (about) 1 /* 2 * Copyright 2015 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package rdf implements encoding of RDF triples, as described in 18 // http://www.w3.org/TR/2014/REC-n-triples-20140225/. 19 package rdf // import "kythe.io/kythe/go/util/encoding/rdf" 20 21 import ( 22 "bytes" 23 "fmt" 24 "io" 25 "unicode" 26 ) 27 28 // A Triple represents a single RDF triple. 29 type Triple struct { 30 Subject, Predicate, Object string 31 } 32 33 // encodeTo appends the encoding of t to buf. 34 func (t *Triple) encodeTo(buf *bytes.Buffer) { 35 quoteTo(buf, t.Subject) 36 buf.WriteByte(' ') 37 quoteTo(buf, t.Predicate) 38 buf.WriteByte(' ') 39 quoteTo(buf, t.Object) 40 buf.WriteString(" .") 41 } 42 43 // Encode writes a string encoding of t as an RDF triple to w. 44 func (t *Triple) Encode(w io.Writer) error { 45 var buf bytes.Buffer 46 t.encodeTo(&buf) 47 _, err := w.Write(buf.Bytes()) 48 return err 49 } 50 51 // String returns a string encoding of t as an RDF triple. 52 func (t *Triple) String() string { 53 var buf bytes.Buffer 54 t.encodeTo(&buf) 55 return buf.String() 56 } 57 58 // ctrlMap gives shortcut escape sequences for common control characters. 59 var ctrlMap = map[rune]string{ 60 '\t': `\t`, 61 '\b': `\b`, 62 '\n': `\n`, 63 '\r': `\r`, 64 '\f': `\f`, 65 } 66 67 // Quote produces a quote-bounded string from s, following the TURTLE escaping 68 // rules http://www.w3.org/TR/2014/REC-turtle-20140225/#sec-escapes. 69 func Quote(s string) string { 70 var buf bytes.Buffer 71 quoteTo(&buf, s) 72 return buf.String() 73 } 74 75 func quoteTo(buf *bytes.Buffer, s string) { 76 buf.Grow(2 + len(s)) 77 buf.WriteByte('"') 78 for i, c := range s { 79 switch { 80 case unicode.IsControl(c): 81 if s, ok := ctrlMap[c]; ok { 82 buf.WriteString(s) 83 } else { 84 fmt.Fprintf(buf, "\\u%04x", c) 85 } 86 case c == '"', c == '\\', c == '\'': 87 buf.WriteByte('\\') 88 buf.WriteRune(c) 89 case c <= unicode.MaxASCII: 90 buf.WriteRune(c) 91 case c == unicode.ReplacementChar: 92 // In correctly-encoded UTF-8, we should never see a replacement 93 // char. Some text in the wild has valid Unicode characters that 94 // aren't UTF-8, and this case lets us be more forgiving of those. 95 fmt.Fprintf(buf, "\\u%04x", s[i]) 96 case c <= 0xffff: 97 fmt.Fprintf(buf, "\\u%04x", c) 98 default: 99 fmt.Fprintf(buf, "\\U%08x", c) 100 } 101 } 102 buf.WriteByte('"') 103 }