/SysString

классы на языке X++ для работы со строками и текстом (TextBuffer)

Primary LanguageJavaMIT LicenseMIT

SysString

SysString – это классы на языке X++ для работы со строками и текстом (TextBuffer) в Microsoft Dynamics AX 2009, Microsoft Dynamics AX 2012 и Axapta 4.0.

Класс String

Класс String — отдельный класс, который содержит статические методы для работы со строками.

Класс SysText

Класс SysText расширяет (extends) класс TextBuffer и содержит статические методы для работы с содержимым текстового буфера.

Методы

trimIdent

Аксапта позволяет использовать raw-литералы для строк. Однако внутри raw-литерала оступы никак не учитываются. А хотелось бы. Особенно для SQL-команд, которые потом приходится видеть в SQL Management Studio.

Детальное описание проблемы можно найти в JEP 355: Text Blocks, а краткую спецификацию в описании функции trimIdent для Kotlin.

Метод trimIdent:

  • удаляет первую и последнюю пробельные строки (пустая строка или строка, состоящая только из пробелов)
  • вычисляет минимальный отступ у оставшихся строк, не учитывая пробельные строки внутри
  • удаляет минимальный отступ у всех строк
  • пробельные строки преобразует в пустые строки

Например:

str withoutIndent = String::trimIdent(@"
            ABC
            123
            456
        ");
;
info(withoutIndent); // ABC\n123\n456

Примечание: Метод трактует символы табуляции как значимые символы, а не как пробелы

Еще пример:

// Create the SQL Server Instead Of Trigger
createTriggerSQL = String::trimIdent(@"
            CREATE TRIGGER [dbo].[ShipCarrierStagingInsTrig] ON [dbo].[%1] INSTEAD OF INSERT AS
            BEGIN
                DECLARE @RecId AS bigint
                SELECT @RecId = max(RecId) FROM %1 WITH (UPDLOCK, HOLDLOCK)
                IF @RecId IS NULL BEGIN  SELECT @RecId = 0  END
                INSERT INTO %1
                    (%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,
                        %12,%13,%14,%15,%16,%17,%18,%19)
                select
                    %2,%3,ISNULL(%4,''),getdate(),
                    case
                        when ISNULL(%6,0.0) != 0.0 then %6
                        else
                            cast(
                                case
                                    when %20 is null then '0.0'
                                    when %20 = '' then '0.0'
                                    else %20
                                end
                            as numeric(28,12))
                    end,
                    ....
            END
            ");

calcIdent

Вспомогательная функция, которая используется в trimIdent. Вычисляет отступ в многострочном тексте.

Примечание: Метод трактует символы табуляции как значимые символы, а не как пробелы

changeIdent

Вспомогательная функция, которая используется в trimIdent. Увеличивает или уменьшает отступ на указанное число пробелов у строк в textBuffer. Не изменяет количество строк.

Примечание: Метод трактует символы табуляции как значимые символы, а не как пробелы

ChangeLog

Направления для развития

Методы в классе String

Ранее представленный проект SysGlobal также содержит дополнительные функции для работы со строками. Однако некоторые разработчики посетовали, что внутренним регламентом им запрещено модифицировать стандартные framework-классы вообще и класс Global в частности. Поэтому в данном проекте функции добавлены в класс String, а не в Global (хотя trimIdent очень просится в Global).

В дальнейшем я планирую перенести строковые функции в класс String, а также добавить другие вспомогательные функции типа drop, hexDump и т.п., которые полезны, но были явно лишними в Global.

Но также буду рад услышать ваши предложения какие функции были бы полезными в классе String.

Статические методы или методы инстанса в классе SysText

Крепко думал перед публикацией проекта, решил остановиться на статических методах.

Буду рад услышать ваши замечания и доводы в пользу методов инстанса.

TextBuffer::find или [String::Regexp]

Крепко думал и решил оставить только встроенную в Аксапту функциональность для работы с регулярными выражениями (см. методы calcIdent и changeIdent). Буду рад услышать ваши замечания и доводы в пользу .net-регулярных выражений.

Когда будете измерять производительность, примите во внимание, что Аксапта "работает" с .net версии 3.5, а не с современными версиями .net. Да, современные библиотеки .net во многом подменяют функции старых библиотек. Но вполне возможна ситуация, когда на компьютере с Аксаптой современные библиотеки просто не установлены.

Также рассматривал возможность вообще обойтись без регулярных выражений, но вариант с перебором получился слишком медленным.

Буду рад услышать ваши предложения как сделать код быстрее вообще без регулярных выражений.

Копирование текста в методе SysText::trimIdent

Сейчас в методе SysText::trimIdent происходит копирование текста из исходного TextBuffer в промежуточный.

Поскольку аксаптовский TextBuffer является аналогом дот-нетовского StringBuilder, то в момент копирования происходит долгая сборка сегментов текста в TextBuffer и выделение потенциально большого и непрерывного куска в памяти. Конечно, эта операция потенциально ускоряет textBuffer.subStr, которые происходят позже. Но все равно хотелось бы избавиться от этого копирования, а просто передавать начало и конец сегмента в метод changeIdent.

Буду рад услышать ваши предложения и замечания.

Помощь проекту

Буду признателен за ваши замечания, предложения и советы по проекту как в разделе Issues, так и в виде письма на адрес mazzy@mazzy.ru

Мазуркин Сергей (mazzy)