13
13
14
14
namespace MySQLCLRFunctions
15
15
{
16
+ /*
17
+ *
18
+ * Naming conventions for regex parameters
19
+ * - find is for flat string
20
+ * - regexmatchpattern when a matching process
21
+ * - regexcapturepattern when it has to capture something
22
+ * - match is a noun, what was matched to the pattern
23
+ */
16
24
public static class StringTransform
17
25
{
18
26
/***************************************************************************************************************************************************************************************************
@@ -51,10 +59,10 @@ private static void FillRowWithCapStrs(Object matchObject, out SqlString match,
51
59
*
52
60
**************************************************************************************************************************************************************************************/
53
61
[ SqlFunction ( DataAccess = DataAccessKind . None , IsDeterministic = true , IsPrecise = true , FillRowMethodName = "FillRowWithStrPieces" ) ]
54
- public static IEnumerable Pieces ( String stringtosplitintopieces , String regexsplitterpattern )
62
+ public static IEnumerable Pieces ( String stringtosplitintopieces , String regexmatchpattern )
55
63
{
56
64
returnpieceorderno = 1 ;
57
- string [ ] stringpieces = Regex . Split ( stringtosplitintopieces , regexsplitterpattern , RegexOptions . IgnoreCase , TimeSpan . FromSeconds ( 2 ) ) ;
65
+ string [ ] stringpieces = Regex . Split ( stringtosplitintopieces , regexmatchpattern , RegexOptions . IgnoreCase , TimeSpan . FromSeconds ( 2 ) ) ;
58
66
return stringpieces ;
59
67
}
60
68
@@ -65,21 +73,111 @@ private static void FillRowWithStrPieces(Object obj, out SqlString piece, out Sq
65
73
pieceorderNo = returnpieceorderno ++ ;
66
74
}
67
75
76
+
77
+ // Extensions for internal use and simpler Fluent design, but not for SQL to call
78
+ internal static string ReplaceMatchExt ( this string input , string regexmatchpattern , string replacement )
79
+ {
80
+ return ReplaceMatch ( input , regexmatchpattern , replacement ) ;
81
+ }
82
+
83
+ /***************************************************************************************************************************************************************************************************
84
+ *
85
+ * ReplaceMatch Similar to REPLACE in SQL Server, except it has .NET regex
86
+ *
87
+ * Note parameter naming convention: find is for flat string, regexmatchpattern when a matching process, regexcapturepattern when it has to capture something
88
+ **************************************************************************************************************************************************************************************/
68
89
[ SqlFunction ( DataAccess = DataAccessKind . None , IsDeterministic = true , IsPrecise = true ) ]
90
+ public static string ReplaceMatch ( string input , string regexmatchpattern , string replacement )
91
+ {
92
+ return Regex . Replace ( input , regexmatchpattern , replacement ) ;
93
+ }
94
+
95
+ // Extensions for internal use and simpler Fluent design, but not for SQL to call
96
+ internal unsafe static string ReplaceRecursiveExt ( this string input , string find , string replacement )
97
+ {
98
+ return ReplaceRecursive ( input , find , replacement ) ;
99
+ }
100
+
101
+ unsafe public static string ReplaceRecursive ( string input , string find , string replacement )
102
+ {
103
+ if ( find == replacement ) return input ;
104
+ if ( replacement . Contains ( find ) )
105
+ {
106
+ throw new ArgumentOutOfRangeException ( nameof ( replacement ) , "the replacement string contains the sought string, so recursion would cause a blowup." ) ;
107
+ }
108
+
109
+ if ( find . Length != replacement . Length )
110
+ {
111
+ StringBuilder sb = new StringBuilder ( input ) ;
112
+ while ( true )
113
+ {
114
+ int formersize = sb . Length ;
115
+ sb . Replace ( find , replacement ) ;
116
+ int newsize = sb . Length ;
117
+ if ( formersize == newsize )
118
+ {
119
+ return sb . ToString ( ) ;
120
+ }
121
+ }
122
+ }
123
+ else if ( find . Length == replacement . Length )
124
+ {
125
+ int findlen = find . Length ;
126
+ var findchars = find . ToCharArray ( ) ;
127
+ int len = input . Length ;
128
+ fixed ( char * pointer = input )
129
+ {
130
+ // Add one to each of the characters.
131
+ for ( int i = 0 ; i <= len - findlen ; i ++ )
132
+ {
133
+ int j2 = 0 ;
134
+ for ( int j = i ; j < len ; j ++ )
135
+ {
136
+ if ( pointer [ j + j2 ] != findchars [ j2 ] ) goto outerloop ;
137
+ j2 ++ ;
138
+ if ( j2 == findlen )
139
+ {
140
+ // Replace!!!!!!!!
141
+
142
+ pointer [ j ] = findchars [ 0 ] ;
143
+ }
144
+ }
145
+ outerloop :
146
+ ;
147
+ }
148
+ // Return the mutated string.
149
+ return new string ( pointer ) ;
150
+ }
151
+ }
152
+
153
+ return input ;
154
+ }
155
+
69
156
/***************************************************************************************************************************************************************************************************
70
157
*
71
158
* Trim repeating bunches of character off right of string
72
159
*
73
160
* - Created for trimming "1.3930000000" off floating point number in sql which REFUSES to round.
74
161
*
75
162
**************************************************************************************************************************************************************************************/
163
+ [ SqlFunction ( DataAccess = DataAccessKind . None , IsDeterministic = true , IsPrecise = true ) ]
76
164
public static string RTrimChar ( string input , string trimAllOccFromRight )
77
165
{
78
166
if ( input == null ) return null ;
79
167
if ( string . IsNullOrWhiteSpace ( input ) ) return input ;
80
168
return input . TrimEnd ( trimAllOccFromRight . ToCharArray ( ) ) ;
81
169
}
82
170
171
+ [ SqlFunction ( DataAccess = DataAccessKind . None , IsDeterministic = true , IsPrecise = true ) ]
172
+ public static string RTrimN ( string input , int howmanycharactersoffend )
173
+ {
174
+ if ( input == null ) return null ;
175
+ if ( string . IsNullOrWhiteSpace ( input ) || howmanycharactersoffend == 0 ) return input ;
176
+ if ( input . Length <= howmanycharactersoffend ) return string . Empty ;
177
+ if ( howmanycharactersoffend < 0 ) throw new ArgumentOutOfRangeException ( nameof ( howmanycharactersoffend ) , howmanycharactersoffend , "Cannot have negate remove characters." ) ;
178
+ return input . Substring ( 0 , input . Length - howmanycharactersoffend ) ;
179
+ }
180
+
83
181
[ SqlFunction ( DataAccess = DataAccessKind . None , IsDeterministic = true , IsPrecise = true ) ]
84
182
public static string LPad ( string input , int padToLen )
85
183
{
@@ -113,15 +211,19 @@ public static string BlankOut(string input, string blankanyofthese, string sep)
113
211
}
114
212
return input ;
115
213
}
214
+ /***************************************************************************************************************************************************************************************************
215
+ *
216
+ * Title Like "UPPER" in SQL Server, as opposed to ToUpper in C#/.NET
217
+ *
218
+ **************************************************************************************************************************************************************************************/
116
219
[ SqlFunction ( DataAccess = DataAccessKind . None , IsDeterministic = true , IsPrecise = true ) ]
117
- public static string RemoveSQLServerNameDelimiters ( string input )
220
+ public static string Title ( string input )
118
221
{
119
- if ( string . IsNullOrWhiteSpace ( input ) ) return input ;
120
- if ( string . IsNullOrEmpty ( input ) ) return input ;
121
-
122
- input = input . Trim ( ) . Trim ( new char [ ] { '[' , ']' } ) . Replace ( "]]" , "]" ) ;
123
- return input ;
222
+ return Regex . Replace ( input , @"\b[a-z]\w+" , delegate ( Match match )
223
+ {
224
+ string v = match . ToString ( ) ;
225
+ return char . ToUpper ( v [ 0 ] ) + v . Substring ( 1 ) ;
226
+ } ) ;
124
227
}
125
-
126
228
}
127
229
}
0 commit comments