@@ -127,13 +127,7 @@ proc parseHook*(s: string, i: var int, v: var SomeFloat) =
127127 i += chars
128128 v = f
129129
130- proc parseHook * (s: string , i: var int , v: var string ) =
131- # # Parse string.
132- eatSpace (s, i)
133- if i + 3 < s.len and s[i+ 0 ] == 'n' and s[i+ 1 ] == 'u' and s[i+ 2 ] == 'l' and s[i+ 3 ] == 'l' :
134- i += 4
135- return
136- eatChar (s, i, '"' )
130+ proc parseStringSlow (s: string , i: var int , v: var string ) =
137131 while i < s.len:
138132 let c = s[i]
139133 case c
@@ -161,6 +155,85 @@ proc parseHook*(s: string, i: var int, v: var string) =
161155 inc i
162156 eatChar (s, i, '"' )
163157
158+ proc parseStringFast (s: string , i: var int , v: var string ) =
159+ # It appears to be faster to scan the string once, then allocate exact chars,
160+ # and then scan the string again populating it.
161+ var
162+ j = i
163+ ll = 0
164+ while j < s.len:
165+ let c = s[j]
166+ case c
167+ of '"' :
168+ break
169+ of '\\ ' :
170+ inc j
171+ let c = s[j]
172+ case c
173+ of 'u' :
174+ inc j
175+ let u = parseHexInt (s[j ..< j + 4 ])
176+ j += 3
177+ ll += Rune (u).toUTF8 ().len
178+ else :
179+ inc ll
180+ else :
181+ inc ll
182+ inc j
183+
184+ if ll > 0 :
185+ v = newString (ll)
186+ var
187+ at = 0
188+ ss = cast [ptr UncheckedArray [char ]](v[0 ].addr )
189+ template add (ss: ptr UncheckedArray [char ], c: char ) =
190+ ss[at] = c
191+ inc at
192+ while i < s.len:
193+ let c = s[i]
194+ case c
195+ of '"' :
196+ break
197+ of '\\ ' :
198+ inc i
199+ let c = s[i]
200+ case c
201+ of '"' , '\\ ' , '/' : ss.add (c)
202+ of 'b' : ss.add '\b '
203+ of 'f' : ss.add '\f '
204+ of 'n' : ss.add '\n '
205+ of 'r' : ss.add '\r '
206+ of 't' : ss.add '\t '
207+ of 'u' :
208+ inc i
209+ let u = parseHexInt (s[i ..< i + 4 ])
210+ i += 3
211+ for c in Rune (u).toUTF8 ():
212+ ss.add (c)
213+ else :
214+ ss.add (c)
215+ else :
216+ ss.add (c)
217+ inc i
218+
219+ eatChar (s, i, '"' )
220+
221+ proc parseHook * (s: string , i: var int , v: var string ) =
222+ # # Parse string.
223+ eatSpace (s, i)
224+ if i + 3 < s.len and s[i+ 0 ] == 'n' and s[i+ 1 ] == 'u' and s[i+ 2 ] == 'l' and s[i+ 3 ] == 'l' :
225+ i += 4
226+ return
227+ eatChar (s, i, '"' )
228+
229+ when nimvm :
230+ parseStringSlow (s, i, v)
231+ else :
232+ when defined (js):
233+ parseStringSlow (s, i, v)
234+ else :
235+ parseStringFast (s, i, v)
236+
164237proc parseHook * (s: string , i: var int , v: var char ) =
165238 var str: string
166239 s.parseHook (i, str)
0 commit comments