Skip to content

Commit f5917f6

Browse files
committed
СтрШаблон: вынесено создание Regexp; класс исключений; мелочи
1 parent 8c8f083 commit f5917f6

File tree

1 file changed

+63
-18
lines changed

1 file changed

+63
-18
lines changed

src/OneScript.StandardLibrary/StringOperations.cs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,34 @@ This Source Code Form is subject to the terms of the
55
at http://mozilla.org/MPL/2.0/.
66
----------------------------------------------------------*/
77

8-
using System;
9-
using System.Linq;
108
using OneScript.Commons;
119
using OneScript.Contexts;
1210
using OneScript.Contexts.Enums;
1311
using OneScript.Exceptions;
1412
using OneScript.Execution;
13+
using OneScript.Localization;
1514
using OneScript.StandardLibrary.Collections;
1615
using ScriptEngine.Machine;
1716
using ScriptEngine.Machine.Contexts;
17+
using System;
18+
using System.Linq;
1819

1920
namespace OneScript.StandardLibrary
2021
{
2122
[GlobalContext(Category = "Операции со строками")]
2223
public class StringOperations : GlobalContextBase<StringOperations>
2324
{
25+
private static readonly System.Text.RegularExpressions.Regex _templateRe
26+
= new System.Text.RegularExpressions.Regex(@"(%%)|%(\d+)|%\((\d+)\)|%");
27+
2428
/// <summary>
2529
/// Получает строку на языке, заданном во втором параметре (коды языков в соответствии с ISO 639-1)
2630
/// или на текущем языке системы.
2731
/// </summary>
2832
/// <param name="src">Строка на нескольких языках</param>
2933
/// <param name="lang">Код языка (если не указан, возвращает вариант для текущего языка системы,
30-
/// если вариант не найден, то возвращает вариант для английского языка, если не задан вариант для английского языка,
31-
/// то возвращает первый вариант из списка)</param>
34+
/// если вариант не найден, то возвращает вариант для английского языка,
35+
/// если не задан вариант для английского языка, то возвращает первый вариант из списка)</param>
3236
[ContextMethod("НСтр", "NStr")]
3337
public string NStr(string src, string lang = null)
3438
{
@@ -39,7 +43,8 @@ public string NStr(string src, string lang = null)
3943
/// Определяет, что строка начинается с указанной подстроки.
4044
/// </summary>
4145
/// <param name="inputString">Строка, начало которой проверяется на совпадение с подстрокой поиска.</param>
42-
/// <param name="searchString">Строка, содержащая предполагаемое начало строки. В случае если переданное значение является пустой строкой генерируется исключительная ситуация.</param>
46+
/// <param name="searchString">Строка, содержащая предполагаемое начало строки.
47+
/// В случае, если переданное значение является пустой строкой, генерируется исключительная ситуация.</param>
4348
[ContextMethod("СтрНачинаетсяС", "StrStartsWith")]
4449
public bool StrStartsWith(string inputString, string searchString)
4550
{
@@ -51,7 +56,7 @@ public bool StrStartsWith(string inputString, string searchString)
5156
{
5257
result = inputString.StartsWith(searchString);
5358
}
54-
else throw new RuntimeException("Ошибка при вызове метода контекста (СтрНачинаетсяС): Недопустимое значение параметра (параметр номер '2')");
59+
else throw StringOpException.StrStartsWith();
5560
}
5661

5762
return result;
@@ -61,7 +66,8 @@ public bool StrStartsWith(string inputString, string searchString)
6166
/// Определяет, заканчивается ли строка указанной подстрокой.
6267
/// </summary>
6368
/// <param name="inputString">Строка, окончание которой проверяется на совпадение с подстрокой поиска.</param>
64-
/// <param name="searchString">Строка, содержащая предполагаемое окончание строки. В случае если переданное значение является пустой строкой генерируется исключительная ситуация.</param>
69+
/// <param name="searchString">Строка, содержащая предполагаемое окончание строки.
70+
/// В случае, если переданное значение является пустой строкой, генерируется исключительная ситуация.</param>
6571
[ContextMethod("СтрЗаканчиваетсяНа", "StrEndsWith")]
6672
public bool StrEndsWith(string inputString, string searchString)
6773
{
@@ -73,7 +79,7 @@ public bool StrEndsWith(string inputString, string searchString)
7379
{
7480
result = inputString.EndsWith(searchString);
7581
}
76-
else throw new RuntimeException("Ошибка при вызове метода контекста (СтрЗаканчиваетсяНа): Недопустимое значение параметра (параметр номер '2')");
82+
else throw StringOpException.StrEndsWith();
7783
}
7884

7985
return result;
@@ -84,7 +90,8 @@ public bool StrEndsWith(string inputString, string searchString)
8490
/// </summary>
8591
/// <param name="inputString">Разделяемая строка.</param>
8692
/// <param name="stringDelimiter">Строка символов, каждый из которых является индивидуальным разделителем.</param>
87-
/// <param name="includeEmpty">Указывает необходимость включать в результат пустые строки, которые могут образоваться в результате разделения исходной строки. Значение по умолчанию: Истина. </param>
93+
/// <param name="includeEmpty">Указывает необходимость включать в результат пустые строки,
94+
/// которые могут образоваться в результате разделения исходной строки. Значение по умолчанию: Истина. </param>
8895
[ContextMethod("СтрРазделить", "StrSplit")]
8996
public ArrayImpl StrSplit(string inputString, string stringDelimiter, bool? includeEmpty = true)
9097
{
@@ -94,12 +101,14 @@ public ArrayImpl StrSplit(string inputString, string stringDelimiter, bool? incl
94101

95102
if(!string.IsNullOrEmpty(inputString))
96103
{
97-
arrParsed = inputString.Split(stringDelimiter?.ToCharArray(), (bool) includeEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
104+
arrParsed = inputString.Split(stringDelimiter?.ToCharArray(),
105+
(bool)includeEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
98106
}
99107
else
100108
{
101-
arrParsed = (bool) includeEmpty ? new string[] { string.Empty } : new string[0];
109+
arrParsed = (bool)includeEmpty ? new string[] { string.Empty } : Array.Empty<string>();
102110
}
111+
103112
return new ArrayImpl(arrParsed.Select(x => ValueFactory.Create(x)));
104113
}
105114

@@ -149,7 +158,7 @@ public int StrFind(string haystack, string needle, SearchDirection direction = S
149158

150159
bool fromBegin = direction == SearchDirection.FromBegin;
151160

152-
if(startPos == 0)
161+
if (startPos == 0)
153162
{
154163
startPos = fromBegin ? 1 : len;
155164
}
@@ -215,9 +224,8 @@ public string StrTemplate(string template,
215224
.SkipWhile(x => x == null)
216225
.Count();
217226

218-
var re = new System.Text.RegularExpressions.Regex(@"(%%)|%(\d+)|%\((\d+)\)|%");
219227
int maxNumber = 0;
220-
var result = re.Replace(srcFormat, (m) =>
228+
var result = _templateRe.Replace(srcFormat, (m) =>
221229
{
222230
if (m.Groups[1].Success)
223231
return "%";
@@ -227,7 +235,7 @@ public string StrTemplate(string template,
227235
var number = int.Parse(m.Groups[2].Success ? m.Groups[2].Value : m.Groups[3].Value);
228236

229237
if (number < 1 || number > 10)
230-
throw new RuntimeException($"Ошибка синтаксиса шаблона в позиции {m.Index+2}: недопустимый номер подстановки");
238+
throw StringOpException.TemplateSubst(m.Index + 2, number);
231239

232240
//FIXME: отключено, т.к. платформа игнорирует ошибку с недостаточным числом параметров
233241
//if (number > passedArgsCount)
@@ -239,7 +247,7 @@ public string StrTemplate(string template,
239247
return arguments[10-number] ?? "";
240248
}
241249

242-
throw new RuntimeException("Ошибка синтаксиса шаблона в позиции " + (m.Index + 2));
250+
throw StringOpException.TemplateSyntax(m.Index + 2);
243251
});
244252

245253
if (passedArgsCount > maxNumber)
@@ -252,9 +260,9 @@ public static IAttachableContext CreateInstance()
252260
{
253261
return new StringOperations();
254262
}
255-
256263
}
257264

265+
258266
[EnumerationType("НаправлениеПоиска", "SearchDirection")]
259267
public enum SearchDirection
260268
{
@@ -264,5 +272,42 @@ public enum SearchDirection
264272
FromEnd
265273
}
266274

267-
275+
276+
public class StringOpException : RuntimeException
277+
{
278+
public StringOpException(BilingualString message, Exception innerException) : base(message,
279+
innerException)
280+
{}
281+
282+
public StringOpException(BilingualString message) : base(message)
283+
{}
284+
285+
public static StringOpException StrStartsWith()
286+
{
287+
return new StringOpException(new BilingualString(
288+
"Error calling context method (StrStartsWith): Invalid parameter number '2' value",
289+
"Ошибка при вызове метода контекста (СтрНачинаетсяС): Недопустимое значение параметра номер '2'"));
290+
}
291+
public static StringOpException StrEndsWith()
292+
{
293+
return new StringOpException(new BilingualString(
294+
"Error calling context method (StrEndsWith): Invalid parameter number '2' value",
295+
"Ошибка при вызове метода контекста (СтрЗаканчиваетсяНа): Недопустимое значение параметра номер '2'"));
296+
}
297+
298+
public static StringOpException TemplateSyntax(int pos)
299+
{
300+
return new StringOpException(new BilingualString(
301+
$"Ошибка синтаксиса шаблона в позиции {pos}",
302+
$"Template syntax error at position {pos}"));
303+
}
304+
305+
public static StringOpException TemplateSubst(int pos, int num)
306+
{
307+
return new StringOpException(new BilingualString(
308+
$"Ошибка синтаксиса шаблона в позиции {pos}. Недопустимый номер подстановки: '{num}'",
309+
$"Template syntax error at position {pos}. Invalid substitution number: '{num}'"));
310+
}
311+
}
312+
268313
}

0 commit comments

Comments
 (0)