@@ -2855,6 +2855,36 @@ if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) &&
28552855 return input;
28562856}
28572857
2858+ /+ +
2859+ Strips leading characters as specified in second argument.
2860+
2861+ Params:
2862+ input = string or $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
2863+ of characters
2864+ chars = list of chars to strip
2865+
2866+ Returns: $(D input) stripped of extra characters.
2867+
2868+ Postconditions: $(D input) and the returned value
2869+ will share the same tail (see $(REF sameTail, std,array)).
2870+
2871+ See_Also:
2872+ Generic stripping on ranges: $(REF _stripLeft, std, algorithm, mutation)
2873+ +/
2874+ auto stripLeft (Range )(Range input, string chars)
2875+ if (isForwardRange! Range && isSomeChar! (ElementEncodingType! Range ) &&
2876+ ! isInfinite! Range && ! isConvertibleToString! Range )
2877+ {
2878+ while (! input.empty)
2879+ {
2880+ auto c = input.front;
2881+ if (indexOf(chars, c) == - 1 )
2882+ break ;
2883+ input.popFront();
2884+ }
2885+ return input;
2886+ }
2887+
28582888// /
28592889@safe pure unittest
28602890{
@@ -2870,10 +2900,24 @@ if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) &&
28702900 assert (stripLeft([paraSep] ~ " hello world" ~ paraSep) ==
28712901 " hello world" ~ [paraSep]);
28722902
2903+ assert (stripLeft(" hello world " , " " ) ==
2904+ " hello world " );
2905+ assert (stripLeft(" xxxxxhello world " , " x" ) ==
2906+ " hello world " );
2907+ assert (stripLeft(" xxxyy hello world " , " xy " ) ==
2908+ " hello world " );
2909+
28732910 import std.array : array;
2874- import std.utf : byChar;
2911+ import std.utf : byChar, byWchar, byDchar ;
28752912 assert (stripLeft(" hello world " w.byChar).array ==
28762913 " hello world " );
2914+
2915+ assert (stripLeft(" xxxyy hello world " w.byChar, " xy " ).array ==
2916+ " hello world " );
2917+
2918+ assert (stripLeft(" \u2028\u2020 hello world\u2028 " w.byWchar, " \u2028 " ).array == " \u2020 hello world\u2028 " );
2919+ assert (stripLeft(" \U00010001 hello world" w.byWchar, " " ).array == " \U00010001 hello world" w);
2920+ assert (stripLeft(" \U00010001 xyhello world" d.byDchar, " \U00010001 xy" ).array == " hello world" d);
28772921}
28782922
28792923auto stripLeft (Range )(auto ref Range str)
@@ -2882,6 +2926,12 @@ if (isConvertibleToString!Range)
28822926 return stripLeft! (StringTypeOf! Range )(str);
28832927}
28842928
2929+ auto stripLeft (Range )(auto ref Range str, string chars)
2930+ if (isConvertibleToString! Range )
2931+ {
2932+ return stripLeft! (StringTypeOf! Range )(str, chars);
2933+ }
2934+
28852935@safe pure unittest
28862936{
28872937 assert (testAliasedString! stripLeft(" hello" ));
@@ -2995,6 +3045,53 @@ if (isSomeString!Range ||
29953045 }
29963046}
29973047
3048+ /+ +
3049+ Strips trailing characters as specified in second argument.
3050+
3051+ Params:
3052+ str = string or random access range of characters
3053+ chars = list of chars to strip
3054+
3055+ Returns:
3056+ slice of $(D str) stripped of trailing extra characters.
3057+
3058+ See_Also:
3059+ Generic stripping on ranges: $(REF _stripRight, std, algorithm, mutation)
3060+ +/
3061+ auto stripRight (Range )(Range str, string chars)
3062+ if (isSomeString! Range ||
3063+ isRandomAccessRange! Range && hasLength! Range && hasSlicing! Range &&
3064+ ! isConvertibleToString! Range &&
3065+ isSomeChar! (ElementEncodingType! Range ))
3066+ {
3067+ alias C = Unqual! (ElementEncodingType! (typeof (str)));
3068+
3069+ static if (isSomeString! (typeof (str)))
3070+ {
3071+ import std.utf : codeLength;
3072+
3073+ foreach_reverse (i, dchar c; str)
3074+ {
3075+ if (indexOf(chars, c) == - 1 )
3076+ return str[0 .. i + codeLength! C(c)];
3077+ }
3078+
3079+ return str[0 .. 0 ];
3080+ }
3081+ else
3082+ {
3083+ size_t i = str.length;
3084+ while (i-- )
3085+ {
3086+ if (indexOf(chars, str[i]) != - 1 )
3087+ continue ;
3088+ break ;
3089+ }
3090+
3091+ return str[0 .. i + 1 ];
3092+ }
3093+ }
3094+
29983095// /
29993096@safe pure
30003097unittest
@@ -3010,6 +3107,13 @@ unittest
30103107 [lineSep] ~ " hello world" );
30113108 assert (stripRight([paraSep] ~ " hello world" ~ paraSep) ==
30123109 [paraSep] ~ " hello world" );
3110+
3111+ assert (stripRight(" hello world " , " x" ) ==
3112+ " hello world " );
3113+ assert (stripRight(" hello world " , " " ) ==
3114+ " hello world" );
3115+ assert (stripRight(" hello worldxy " , " xy " ) ==
3116+ " hello world" );
30133117}
30143118
30153119auto stripRight (Range )(auto ref Range str)
@@ -3018,6 +3122,12 @@ if (isConvertibleToString!Range)
30183122 return stripRight! (StringTypeOf! Range )(str);
30193123}
30203124
3125+ auto stripRight (Range )(auto ref Range str, string chars)
3126+ if (isConvertibleToString! Range )
3127+ {
3128+ return stripRight! (StringTypeOf! Range )(str, chars);
3129+ }
3130+
30213131@safe pure unittest
30223132{
30233133 assert (testAliasedString! stripRight(" hello " ));
@@ -3045,6 +3155,11 @@ if (isConvertibleToString!Range)
30453155 cast (void ) stripRight (" a\x80 " .byUTF! char ).array;
30463156 wstring ws = [' a' , cast (wchar ) 0xDC00 ];
30473157 cast (void ) stripRight (ws.byUTF! wchar ).array;
3158+
3159+ assert (stripRight(" hello world xyz " .byChar, " xyz " ).array == " hello world" );
3160+ assert (stripRight(" \u2028 hello world\u2020\u2028 " w.byWchar, " \u2028 " ).array == " \u2028 hello world\u2020 " );
3161+ assert (stripRight(" hello world\U00010001 " w.byWchar, " " ).array == " hello world\U00010001 " w);
3162+ assert (stripRight(" hello world\U00010001 xy" d.byDchar, " \U00010001 xy" ).array == " hello world" d);
30483163}
30493164
30503165
@@ -3070,6 +3185,29 @@ if (isSomeString!Range ||
30703185 return stripRight (stripLeft(str));
30713186}
30723187
3188+ /+ +
3189+ Strips both leading and trailing extra characters as specified in the
3190+ second argument.
3191+
3192+ Params:
3193+ str = string or random access range of characters
3194+ chars = list of chars to strip
3195+
3196+ Returns:
3197+ slice of $(D str) stripped of leading and trailing extra characters.
3198+
3199+ See_Also:
3200+ Generic stripping on ranges: $(REF _strip, std, algorithm, mutation)
3201+ +/
3202+ auto strip (Range )(Range str, string chars)
3203+ if (isSomeString! Range ||
3204+ isRandomAccessRange! Range && hasLength! Range && hasSlicing! Range &&
3205+ ! isConvertibleToString! Range &&
3206+ isSomeChar! (ElementEncodingType! Range ))
3207+ {
3208+ return stripRight (stripLeft(str, chars), chars);
3209+ }
3210+
30733211// /
30743212@safe pure unittest
30753213{
@@ -3084,6 +3222,12 @@ if (isSomeString!Range ||
30843222 " hello world" );
30853223 assert (strip([paraSep] ~ " hello world" ~ [paraSep]) ==
30863224 " hello world" );
3225+ assert (strip(" hello world " , " x" ) ==
3226+ " hello world " );
3227+ assert (strip(" hello world " , " " ) ==
3228+ " hello world" );
3229+ assert (strip(" xyxyhello worldxyxy " , " xy " ) ==
3230+ " hello world" );
30873231}
30883232
30893233auto strip (Range )(auto ref Range str)
@@ -3092,6 +3236,12 @@ if (isConvertibleToString!Range)
30923236 return strip! (StringTypeOf! Range )(str);
30933237}
30943238
3239+ auto strip (Range )(auto ref Range str, string chars)
3240+ if (isConvertibleToString! Range )
3241+ {
3242+ return strip! (StringTypeOf! Range )(str, chars);
3243+ }
3244+
30953245@safe pure unittest
30963246{
30973247 assert (testAliasedString! strip(" hello world " ));
0 commit comments