Skip to content
классы на языке X++ для работы со строками и текстом (TextBuffer)
Java PowerShell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
ax2009
ax2012
ax4
.gitattributes
.gitignore
CHANGELOG.md
LICENSE
README.md
build.ps1

README.md

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)

You can’t perform that action at this time.