@@ -308,18 +308,30 @@ private function white()
308308
309309 private function error ($ m )
310310 {
311- $ i =0 ;
312311 $ col =0 ;
312+ $ colBytes = 0 ;
313313 $ line =1 ;
314- for ($ i = $ this ->at -1 ; $ i > 0 && @$ this ->text [$ i ] !== "\n" ; $ i --, $ col ++) {
314+
315+ $ i = $ this ->at ;
316+ while ($ i > 0 ) {
317+ $ ch = mb_substr (mb_strcut ($ this ->text , $ i - 1 ), 0 , 1 );
318+ $ i -= strlen ($ ch );
319+
320+ if ($ ch === "\n" ) {
321+ break ;
322+ }
323+
324+ $ col ++;
325+ $ colBytes += strlen ($ ch );
315326 }
327+
316328 for (; $ i > 0 ;
317329 $ i --) {
318330 if ($ this ->text [$ i ] === "\n" ) {
319331 $ line ++;
320332 }
321333 }
322- throw new HJSONException ("$ m at line $ line, $ col >>> " . mb_substr ($ this ->text , $ this ->at - $ col , 20 ) ." ... " );
334+ throw new HJSONException ("$ m at line $ line, $ col >>> " . mb_substr (mb_strcut ( $ this ->text , $ this ->at - $ colBytes ), 0 , 20 ) ." ... " );
323335 }
324336
325337 private function next ($ c = false )
@@ -332,15 +344,19 @@ private function next($c = false)
332344
333345 // Get the next character. When there are no more characters,
334346 // return the empty string.
335- $ this ->ch = (mb_strlen ($ this ->text ) > $ this ->at ) ? $ this ->text [ $ this ->at ] : null ;
336- $ this ->at ++ ;
347+ $ this ->ch = (strlen ($ this ->text ) > $ this ->at ) ? mb_substr ( mb_strcut ( $ this ->text , $ this ->at ), 0 , 1 ) : null ;
348+ $ this ->at += strlen ( $ this -> ch ) ;
337349 return $ this ->ch ;
338350 }
339351
340352 private function peek ($ offs )
341353 {
342354 // range check is not required
343- return $ this ->text [$ this ->at + $ offs ];
355+ if ($ offs >= 0 ) {
356+ return mb_substr (mb_strcut ($ this ->text , $ this ->at ), $ offs , 1 );
357+ } else {
358+ return mb_substr (mb_strcut ($ this ->text , 0 , $ this ->at ), $ offs , 1 );
359+ }
344360 }
345361
346362 private function skipIndent ($ indent )
0 commit comments