github.com/RevenueMonster/sqlike@v1.0.6/jsonb/string.go (about)

     1  package jsonb
     2  
     3  import (
     4  	"github.com/RevenueMonster/sqlike/util"
     5  )
     6  
     7  // ReadRawString :
     8  func (r *Reader) ReadRawString() (string, error) {
     9  	c := r.nextToken()
    10  	if c == 'n' {
    11  		if err := r.unreadByte().ReadNull(); err != nil {
    12  			return "", err
    13  		}
    14  		return "null", nil
    15  	}
    16  
    17  	if c != '"' {
    18  		return "", ErrInvalidJSON{
    19  			callback: "ReadString",
    20  			message:  "expect start with \"",
    21  		}
    22  	}
    23  
    24  	for i := r.pos; i < r.len; i++ {
    25  		c = r.b[i]
    26  		if c == '"' {
    27  			str := string(r.b[r.pos:i])
    28  			r.pos = i + 1
    29  			return str, nil
    30  		}
    31  	}
    32  
    33  	return "", ErrInvalidJSON{
    34  		callback: "ReadString",
    35  		message:  "expect end with \"",
    36  	}
    37  }
    38  
    39  // ReadString :
    40  func (r *Reader) ReadString() (string, error) {
    41  	c := r.nextToken()
    42  	if c == 'n' {
    43  		if err := r.unreadByte().ReadNull(); err != nil {
    44  			return "", err
    45  		}
    46  		return "", nil
    47  	}
    48  
    49  	if c != '"' {
    50  		return "", ErrInvalidJSON{
    51  			callback: "ReadString",
    52  			message:  "expect start with \"",
    53  		}
    54  	}
    55  
    56  	blr := util.AcquireString()
    57  	defer util.ReleaseString(blr)
    58  
    59  	for i := r.pos; i < r.len; {
    60  		c = r.b[i]
    61  		if c == '"' {
    62  			r.pos = i + 1
    63  			break
    64  		}
    65  
    66  		if c == '\\' {
    67  			switch r.b[i+1] {
    68  			case '"':
    69  				blr.WriteRune('"')
    70  				i += 2
    71  			case '\\':
    72  				blr.WriteRune('\\')
    73  				i += 2
    74  			case 'b':
    75  				blr.WriteRune('\b')
    76  				i += 2
    77  			case 'f':
    78  				blr.WriteRune('\f')
    79  				i += 2
    80  			case 'n':
    81  				blr.WriteRune('\n')
    82  				i += 2
    83  			case 'r':
    84  				blr.WriteRune('\r')
    85  				i += 2
    86  			case 't':
    87  				blr.WriteRune('\t')
    88  				i += 2
    89  			case '/':
    90  				blr.WriteRune('/')
    91  				i += 2
    92  			case 'u':
    93  				// TODO: unicode
    94  				blr.WriteRune('u')
    95  				i += 2
    96  			default:
    97  				blr.WriteByte(c)
    98  			}
    99  			continue
   100  		}
   101  
   102  		blr.WriteByte(c)
   103  		i++
   104  	}
   105  
   106  	if c != '"' {
   107  		return "", ErrInvalidJSON{
   108  			callback: "ReadEscapeString",
   109  			message:  "expect end with \"",
   110  		}
   111  	}
   112  
   113  	return blr.String(), nil
   114  }
   115  
   116  // skipString :
   117  func (r *Reader) skipString() error {
   118  	c := r.nextToken()
   119  	if c == 'n' {
   120  		return r.unreadByte().ReadNull()
   121  	}
   122  
   123  	if c != '"' {
   124  		return ErrInvalidJSON{
   125  			callback: "skipString",
   126  			message:  "expect start with \"",
   127  		}
   128  	}
   129  
   130  	for i := r.pos; i < r.len; {
   131  		c = r.b[i]
   132  
   133  		if c == '"' {
   134  			r.pos = i + 1
   135  			break
   136  		}
   137  
   138  		if c == '\\' {
   139  			switch r.b[i+1] {
   140  			case '"':
   141  				i += 2
   142  			case '\\':
   143  				i += 2
   144  			case 'b':
   145  				i += 2
   146  			case 'f':
   147  				i += 2
   148  			case 'n':
   149  				i += 2
   150  			case 'r':
   151  				i += 2
   152  			case 't':
   153  				i += 2
   154  			case '/':
   155  				i += 2
   156  			case 'u':
   157  				i += 2
   158  			}
   159  			continue
   160  		}
   161  		i++
   162  	}
   163  
   164  	if c != '"' {
   165  		return ErrInvalidJSON{
   166  			callback: "skipString",
   167  			message:  "expect end with \"",
   168  		}
   169  	}
   170  
   171  	return nil
   172  }
   173  
   174  var escapeCharMap = map[byte][]byte{
   175  	'\t': []byte(`\t`),
   176  	'\n': []byte(`\n`),
   177  	'\r': []byte(`\r`),
   178  	'"':  []byte(`\"`),
   179  	'\\': []byte(`\\`),
   180  	'\b': []byte(`\b`),
   181  }
   182  
   183  func escapeString(w *Writer, str string) {
   184  	length := len(str)
   185  	for i := 0; i < length; i++ {
   186  		b := str[0]
   187  		str = str[1:]
   188  		if x, ok := escapeCharMap[b]; ok {
   189  			w.Write(x)
   190  			continue
   191  		}
   192  		w.WriteByte(b)
   193  	}
   194  }