1 module des.stdx..string; 2 3 public import std..string; 4 5 import std.array; 6 import std.algorithm; 7 import std.traits; 8 import std.range; 9 10 import des.ts; 11 import des.stdx.type : getTypedArray; 12 13 public import des.stdx.pformat; 14 15 /// 16 string toSnakeCase( in string str, bool ignore_first=true ) @property pure @trusted 17 { 18 string[] buf; 19 buf ~= ""; 20 foreach( i, ch; str ) 21 { 22 if( [ch].toUpper == [ch] ) buf ~= ""; 23 buf[$-1] ~= [ch].toLower; 24 } 25 if( buf[0].length == 0 && ignore_first ) 26 buf = buf[1..$]; 27 return buf.join("_"); 28 } 29 30 /// 31 unittest 32 { 33 assertEq( "SomeVar".toSnakeCase, "some_var" ); 34 assertEq( "SomeVar".toSnakeCase(false), "_some_var" ); 35 36 assertEq( "someVar".toSnakeCase, "some_var" ); 37 assertEq( "someVar".toSnakeCase(false), "some_var" ); 38 39 assertEq( "ARB".toSnakeCase, "a_r_b" ); 40 assertEq( "ARB".toSnakeCase(false), "_a_r_b" ); 41 42 // not alphabetic chars in upper case looks like lower, func separate by them 43 assertEq( "A.B.r.A".toSnakeCase, "a_._b_.r_._a" ); 44 assertEq( "A_B_r_A".toSnakeCase, "a___b__r___a" ); 45 } 46 47 /// 48 string toCamelCaseBySep( in string str, string sep="_", bool first_capitalize=true ) pure @trusted 49 { 50 auto arr = array( filter!"a.length > 0"( str.split(sep) ) ); 51 string[] ret; 52 foreach( i, v; arr ) 53 { 54 auto bb = v.capitalize; 55 if( i == 0 && !first_capitalize ) 56 bb = v.toLower; 57 ret ~= bb; 58 } 59 return ret.join(""); 60 } 61 62 /// 63 unittest 64 { 65 assertEq( toCamelCaseBySep( "single-precision-constant", "-", false ), "singlePrecisionConstant" ); 66 assertEq( toCamelCaseBySep( "one.two.three", ".", true ), "OneTwoThree" ); 67 assertEq( toCamelCaseBySep( "one..three", ".", true ), "OneThree" ); 68 assertEq( toCamelCaseBySep( "one/three", "/" ), "OneThree" ); 69 assertEq( toCamelCaseBySep( "one_.three", ".", false ), "one_Three" ); 70 71 // `_` in upper case looks equals as lower case 72 assertEq( toCamelCaseBySep( "one._three", ".", true ), "One_three" ); 73 } 74 75 /// 76 string toCamelCase( in string str, bool first_capitalize=true ) @property pure @trusted 77 { return toCamelCaseBySep( str, "_", first_capitalize ); } 78 79 /// 80 unittest 81 { 82 assertEq( "some_class".toCamelCase, "SomeClass" ); 83 assertEq( "_some_class".toCamelCase, "SomeClass" ); 84 assertEq( "some_func".toCamelCase(false), "someFunc" ); 85 assertEq( "_some_func".toCamelCase(false), "someFunc" ); 86 assertEq( "a_r_b".toCamelCase, "ARB" ); 87 assertEq( toCamelCase( "program_build" ), "ProgramBuild" ); 88 assertEq( toCamelCase( "program__build" ), "ProgramBuild" ); 89 90 assertEq( toCamelCase( "program__build", false ), toCamelCaseBySep( "program__build", "_", false ) ); 91 } 92 93 /// copy chars to string 94 string toDString( const(char*) c_str ) nothrow pure @trusted 95 { 96 if( c_str is null ) return ""; 97 char *ch = cast(char*)c_str; 98 size_t n; 99 while( *ch++ != '\0' ) n++; 100 return getTypedArray!char( n, c_str ).idup; 101 } 102 103 /// 104 unittest 105 { 106 auto c = [ 'a', 'b', 'c', '\0', 'd', 'e' ]; 107 assertEq( toDString( c.ptr ), "abc" ); 108 } 109 110 /// ditto 111 string toDStringFix(size_t S)( const(char[S]) c_buf ) nothrow pure @trusted 112 { 113 size_t n; 114 foreach( c; c_buf ) 115 { 116 if( c == '\0' ) break; 117 n++; 118 } 119 return getTypedArray!char( n, c_buf.ptr ).idup; 120 } 121 122 /// 123 unittest 124 { 125 char[6] c = [ 'a', 'b', 'c', '\0', 'd', 'e' ]; 126 assertEq( toDStringFix(c), "abc" ); 127 }