yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
b118451e3
master
1 2#include "slang-name-convention-util.h" 3 4#include "../core/slang-char-util.h" 5#include "../core/slang-string-util.h" 6 7namespace Slang 8{ 9 10/* static */ NameConvention NameConventionUtil ::inferConventionFromText ( 11const UnownedStringSlice & slice ) 12{ 13// If no chars, or first char isn't alpha we don't know what it is 14if (slice .getLength () <=0 || !CharUtil ::isAlpha (slice [0 ])) 15 { 16return NameConvention ::Invalid ; 17 } 18 19typedef int Flags ; 20struct Flag 21 { 22enum Enum :Flags 23 { 24Underscore = 0x1 , 25Dash = 0x2 , 26Upper = 0x4 , 27Lower = 0x8 , 28 }; 29 }; 30 31Flags flags = 0 ; 32 33for (const char c :slice ) 34 { 35switch (c ) 36 { 37case '-' : 38flags |=Flag ::Dash ; 39break ; 40case '_' : 41flags |=Flag ::Underscore ; 42break ; 43default : 44 { 45if (CharUtil ::isLower (c )) 46 { 47flags |=Flag ::Lower ; 48 } 49else if (CharUtil ::isUpper (c )) 50 { 51flags |=Flag ::Upper ; 52 } 53else if (CharUtil ::isDigit (c )) 54 { 55// Is okay as long as not first char (which we already tested is alpha) 56 } 57else 58 { 59// Don't know what this style is 60return NameConvention ::Invalid ; 61 } 62 } 63 } 64 } 65 66// Use flags to determine what convention is used 67switch (flags ) 68 { 69// We'll assume it's lower camel. 70case Flag ::Lower : 71return NameConvention ::LowerCamel ; 72// We'll assume it's upper snake. It almost certainly isn't camel, and snake is more usual 73// than kabab. 74case Flag ::Upper : 75return NameConvention ::UpperSnake ; 76case Flag ::Upper |Flag ::Lower : 77 { 78// Looks like camel, choose the right case based on first char 79return CharUtil ::isUpper (slice [0 ]) ?NameConvention ::UpperCamel 80 :NameConvention ::LowerCamel ; 81 } 82case Flag ::Lower |Flag ::Dash : 83return NameConvention ::LowerKabab ; 84case Flag ::Upper |Flag ::Dash : 85return NameConvention ::UpperKabab ; 86case Flag ::Lower |Flag ::Underscore : 87return NameConvention ::LowerSnake ; 88case Flag ::Upper |Flag ::Underscore : 89return NameConvention ::UpperSnake ; 90default : 91break ; 92 } 93 94// Don't know what this style is 95return NameConvention ::Invalid ; 96} 97 98/* static */ NameStyle NameConventionUtil ::inferStyleFromText (const UnownedStringSlice & slice ) 99{ 100for (const char c :slice ) 101 { 102switch (c ) 103 { 104case '-' : 105return NameStyle ::Kabab ; 106case '_' : 107return NameStyle ::Snake ; 108default : 109break ; 110 } 111 } 112return NameStyle ::Camel ; 113} 114 115/* static */ void NameConventionUtil ::split ( 116NameStyle style , 117const UnownedStringSlice & slice , 118List < UnownedStringSlice >& out ) 119{ 120switch (style ) 121 { 122case NameStyle ::Kabab : 123 { 124StringUtil ::split (slice ,'-' ,out ); 125break ; 126 } 127case NameStyle ::Snake : 128 { 129StringUtil ::split (slice ,'_' ,out ); 130break ; 131 } 132case NameStyle ::Camel : 133 { 134typedef CharUtil ::Flags CharFlags ; 135typedef CharUtil ::Flag CharFlag ; 136 137CharFlags prevFlags = 0 ; 138const char * const end = slice .end (); 139 140const char * start = slice .begin (); 141for (const char * cur = start ;cur < end ;++ cur ) 142 { 143const char c = * cur ; 144const CharUtil ::Flags flags = CharUtil ::getFlags (c ); 145 146if (flags & CharFlag ::Upper ) 147 { 148if (prevFlags & CharFlag ::Lower ) 149 { 150// If we go from lower to upper, we have a transition 151out .add (UnownedStringSlice (start ,cur )); 152start = cur ; 153 } 154else if ((prevFlags & CharFlag ::Upper )&& cur + 1 < end ) 155 { 156// This works with capital or uncapitalized acronyms, but if we have two 157// capitalized acronyms following each other - it can't split. 158// 159// For example 160// "IAABBSystem" -> "IAABB", "System" 161// 162// If it only accepted lower case acronyms the logic could be changed such 163// that the following could be produced "IAabbSystem" -> "I", "Aabb", 164// "System" 165// 166// Since Slang source largely goes with upper case acronyms, we work with 167// the heuristic here.. 168 169if (CharUtil ::isLower (cur [1 ])) 170 { 171out .add (UnownedStringSlice (start ,cur )); 172start = cur ; 173 } 174 } 175 } 176 177prevFlags = flags ; 178 } 179 180// Add any end section 181if (start < end ) 182 { 183out .add (UnownedStringSlice (start ,end )); 184 } 185break ; 186 } 187case NameStyle ::Unknown : 188 { 189out .add (slice ); 190break ; 191 } 192 } 193} 194 195void NameConventionUtil ::split (const UnownedStringSlice & slice ,List < UnownedStringSlice >& out ) 196{ 197split (inferStyleFromText (slice ),slice ,out ); 198} 199 200/* static */ void NameConventionUtil ::join ( 201const UnownedStringSlice * slices , 202Index slicesCount , 203NameConvention convention , 204char joinChar , 205StringBuilder & out ) 206{ 207if (slicesCount <=0 ) 208 { 209return ; 210 } 211 212Index totalSize = slicesCount - 1 ; 213for (Index i = 0 ;i < slicesCount ;++ i ) 214 { 215totalSize += slices [i ].getLength (); 216 } 217 218char * const dstStart = out .prepareForAppend (totalSize ); 219char * dst = dstStart ; 220 221const bool upper = isUpper (convention ); 222 223for (Index i = 0 ;i < slicesCount ;++ i ) 224 { 225const UnownedStringSlice & slice = slices [i ]; 226const Index count = slice .getLength (); 227const char * const src = slice .begin (); 228 229if (i > 0 ) 230 { 231* dst ++ = joinChar ; 232 } 233 234if (upper ) 235 { 236for (Index j = 0 ;j < count ;++ j ) 237 { 238dst [j ]= CharUtil ::toUpper (src [j ]); 239 } 240 } 241else 242 { 243for (Index j = 0 ;j < count ;++ j ) 244 { 245dst [j ]= CharUtil ::toLower (src [j ]); 246 } 247 } 248 249dst += count ; 250 } 251 252SLANG_ASSERT (dstStart + totalSize == dst ); 253out .appendInPlace (dstStart ,totalSize ); 254} 255 256/* static */ void NameConventionUtil ::join ( 257const UnownedStringSlice * slices , 258Index slicesCount , 259NameConvention convention , 260StringBuilder & out ) 261{ 262const auto style = getNameStyle (convention ); 263 264switch (style ) 265 { 266case NameStyle ::Kabab : 267return join (slices ,slicesCount ,convention ,'-' ,out ); 268case NameStyle ::Snake : 269return join (slices ,slicesCount ,convention ,'_' ,out ); 270case NameStyle ::Camel : 271 { 272Index totalSize = 0 ; 273 274for (Index i = 0 ;i < slicesCount ;++ i ) 275 { 276totalSize += slices [i ].getLength (); 277 } 278 279char * const dstStart = out .prepareForAppend (totalSize ); 280char * dst = dstStart ; 281 282for (Index i = 0 ;i < slicesCount ;++ i ) 283 { 284const UnownedStringSlice & slice = slices [i ]; 285Index count = slice .getLength (); 286const char * src = slice .begin (); 287 288Int j = 0 ; 289 290if (count > 0 && !(i == 0 && isLower (convention ))) 291 { 292// Capitalize first letter of each word, unless on first word and 'lower' 293dst [j ]= CharUtil ::toUpper (src [j ]); 294j ++ ; 295 } 296 297for (;j < count ;++ j ) 298 { 299dst [j ]= CharUtil ::toLower (src [j ]); 300 } 301 302dst += count ; 303 } 304 305SLANG_ASSERT (dstStart + totalSize == dst ); 306out .appendInPlace (dstStart ,totalSize ); 307break ; 308 } 309 } 310} 311 312/* static */ void NameConventionUtil ::convert ( 313NameStyle fromStyle , 314const UnownedStringSlice & slice , 315NameConvention toConvention , 316StringBuilder & out ) 317{ 318// Split into slices 319List < UnownedStringSlice > slices ; 320split (fromStyle ,slice ,slices ); 321 322// Join the slices in the toConvention 323join (slices .getBuffer (),slices .getCount (),toConvention ,out ); 324} 325 326/* static */ void NameConventionUtil ::convert ( 327const UnownedStringSlice & slice , 328NameConvention toConvention , 329StringBuilder & out ) 330{ 331convert (inferStyleFromText (slice ),slice ,toConvention ,out ); 332} 333 334}// namespace Slang