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 }