@@ -747,22 +747,57 @@ protected function processLine()
747
747
$ this ->emit ('data ' , array ($ line ));
748
748
}
749
749
750
- protected function strlen ($ str )
750
+ private function strlen ($ str )
751
751
{
752
- return mb_strlen ($ str , $ this ->encoding );
752
+ // prefer mb_strlen() if available
753
+ if (function_exists ('mb_strlen ' )) {
754
+ return mb_strlen ($ str , $ this ->encoding );
755
+ }
756
+
757
+ // otherwise replace all unicode chars with dots and count dots
758
+ return strlen (preg_replace ('/./us ' , '. ' , $ str ));
753
759
}
754
760
755
- protected function substr ($ str , $ start = 0 , $ len = null )
761
+ private function substr ($ str , $ start = 0 , $ len = null )
756
762
{
757
763
if ($ len === null ) {
758
764
$ len = $ this ->strlen ($ str ) - $ start ;
759
765
}
760
- return (string )mb_substr ($ str , $ start , $ len , $ this ->encoding );
766
+
767
+ // prefer mb_substr() if available
768
+ if (function_exists ('mb_substr ' )) {
769
+ return (string )mb_substr ($ str , $ start , $ len , $ this ->encoding );
770
+ }
771
+
772
+ // otherwise build array with all unicode chars and slice array
773
+ preg_match_all ('/./us ' , $ str , $ matches );
774
+
775
+ return implode ('' , array_slice ($ matches [0 ], $ start , $ len ));
761
776
}
762
777
763
- private function strwidth ($ str )
764
- {
765
- return mb_strwidth ($ str , $ this ->encoding );
778
+ /** @internal */
779
+ public function strwidth ($ str )
780
+ {
781
+ // prefer mb_strwidth() if available
782
+ if (function_exists ('mb_strwidth ' )) {
783
+ return mb_strwidth ($ str , $ this ->encoding );
784
+ }
785
+
786
+ // otherwise replace each double-width unicode graphemes with two dots, all others with single dot and count number of dots
787
+ // mbstring's list of double-width graphemes is *very* long: https://3v4l.org/GEg3u
788
+ // let's use symfony's list from https://github.com/symfony/polyfill-mbstring/blob/e79d363049d1c2128f133a2667e4f4190904f7f4/Mbstring.php#L523
789
+ // which looks like they originally came from http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
790
+ return strlen (preg_replace (
791
+ array (
792
+ '/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u ' ,
793
+ '/./us ' ,
794
+ ),
795
+ array (
796
+ '.. ' ,
797
+ '. ' ,
798
+ ),
799
+ $ str
800
+ ));
766
801
}
767
802
768
803
/** @internal */
0 commit comments