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  }