Розширення набору стандартних функцій і класів Delphi, HTML, XML, DHTML, Інтернет-технології, статті

У даній статті описується бібліотека функцій і класів AcedUtils, яка містить реалізацію поширених структур даних і алгоритмів мовою Delphiдля платформи Win32. Код бібліотеки написаний і протестований на Borland Delphi 7.


Передмова


При розробці функцій і класів, що складають бібліотеку AcedUtils, основна увага приділялася оптимізації коду за швидкодією. Очевидно, при правильному підході, програми, написані на мові Delphi і скомпільовані в “рідний” код, можуть працювати не повільніше, ніж аналогічні програми на C + + чи C #. Треба тільки розуміти, що секрет досягнення максимальної продуктивності полягає не стільки в оптимізації машинного коду, асемблерних вставках і т.п., скільки у використанні відповідних алгоритмів. Наприклад, якщо стоїть завдання пошуку деякого значення в масиві елементів, можна піти кількома шляхами. Найпростіший шлях – послідовний перебір елементів і порівняння їх з потрібним значенням. Для масиву, що містить всього кілька елементів, цей метод може виявитися найефективнішим. Якщо масив містить багато елементів, краще заздалегідь відсортувати його, а потім використовувати бінарний пошук, який незрівнянно швидше послідовного перебору елементів. Якщо число елементів масиву вимірюється десятками тисяч і пошук в ньому виконується часто, має сенс пожертвувати зайвою пам’яттю для організації хешірованное списку. Час пошуку в хеше не залежить від розміру масиву. Але й хешірованних список має свої недоліки, як, наприклад, неможливість послідовної індексації елементів. Функції і класи з AcedUtils представляють собою готовий інструментарій, що включає поширені алгоритми роботи з даними. Розробник може випробувати різні варіанти і вибрати з них той, який краще підходить для даної конкретної задачі.


В останніх версіях бібліотеки додані класи для роботи зі збалансованими бінарними деревами (червоно-чорними деревами), двосторонніми чергами (деками), пріоритетними чергами. Додані функції, реалізують ефективні алгоритми сортування і пошуку елементів набору даних (інтроспективної сортування, часткову сортування, сортування з збереженням відносного порядку проходження рівних елементів), різні перестановочне алгоритми, функції для злиття впорядкованих наборів елементів, а також для роботи з купою.


Коротко розглянемо призначення модулів у складі AcedUtils.



Тепер докладніше розглянемо функціональність основних модулів AcedUtils.


Модуль AcedMemory


Цей модуль призначений для заміни стандартного менеджера пам’яті Delphiальтернативним механізмом розподілу пам’яті. Метою розробки нового менеджера пам’яті було прагнення оптимізувати роботу з невеликими блоками пам’яті, які виникають при організації зберігання даних у вигляді об’єктної бази, коли кожен запис представляється примірником відповідного класу. Під оптимізацією мається на увазі, по-перше, підвищення швидкості при виділенні / звільнення блоків пам’яті, по-друге, вирішення проблеми фрагментації вільних блоків. Починаючи з версії 1.09, менеджер пам’яті відслідковує спроби повторного звільнення блоків пам’яті і генерує виняток. Розглянемо докладніше принцип роботи AcedMemory.


Пам’ять запитується у операційної системи викликом VirtualAlloc блоками розміром 2МБ, які в даному контексті називаються регіонами. Кожен регіон складається з 32 блоків розміром 64кБ. Кожен такий блок призначений для фрагментів пам’яті певного розміру. Наприклад, один блок може містити 4 фрагмента по 16Кб, інший – 1024 фрагмента по 64 байта і т.д. Коли з прикладної програми викликається функція GetMem, розмір виділених фрагментів пам’яті округляється вгору до найближчого числа, рівного 2 в ступені N, де N може бути від 3 до 16. Коли всі фрагменти пам’яті потрібного розміру в складі блоку зайняті, в регіоні виділяється наступний блок під фрагменти пам’яті потрібного розміру. Якщо всі 32 блоку в складі регіону зайняті, створюється новий регіон розміром 2МБ. Адреса кожного фрагмента пам’яті (до 64кБ) кратний його розміром, що позитивно впливає на продуктивність. На відміну від стандартного менеджера пам’яті, розмір виділених фрагментів не зберігається в пам’яті з негативним зсувом, а обчислюється, при необхідності, за адресою фрагмента. Коли потрібно виділити фрагмент пам’яті розміром більше 64кБ, цей розмір округляється вгору до числа, кратного 4096 байт, а потім викликається функція VirtualAlloc для запиту відповідного блоку пам’яті у операційної системи.


Для підключення AcedMemory до проекту, посилання на цей модуль необхідно додати в розділ uses файлу проекту, причому AcedMemory повинен стояти першим у цьому розділі. Стандартні модулі Forms, Classes та інші повинні перебувати в списку uses, після AcedMemory. Якщо цього не зробити, при завершенні програми виникне помилка. Це відбувається через те, що в розділі finalization модуля Classes побічно викликається функція FreeMem для звільнення деяких блоків пам’яті, виділених в процесі роботи програми. Модулі фіналізуються в порядку, зворотному їх перерахування у розділі uses файлу проекту. Щоб менеджер пам’яті AcedMemory був ще активний на момент виклику розділу finalization модуля Classes, посилання на AcedMemory повинна знаходитися в списку uses файлу проекту перед модулем Classes і будь-якими іншими модулями, використовують Classes, такими, як модуль Forms.


Окрім, власне, механізму для виділення / звільнення пам’яті, в модулі AcedMemory є декілька допоміжних функцій: G_GetMemSize повертає розмір блоку пам’яті, адреса якої передано як параметр; функція G_GetTotalMemAllocated повертає загальний обсяг пам’яті, виділений прикладної програмі. Виклик цієї функції не призводить до тривалого перерахунку розмірів всіх виділених блоків. Замість цього просто повертається значення внутрішнього лічильника пам’яті. Функція G_GetTotalMemCommitted повертає загальний розмір фізичної пам’яті, виділеної програмі операційною системою. Це число не враховує пам’ять, виділену в “купі” для службових структур модуля AcedMemory, а також пам’ять, розподілену засобами, відмінними від менеджера пам’яті.


Модуль AcedBinary


У цьому модулі зібрано велику кількість функцій для роботи з бінарними даними, представленими масивами байт, слів, подвійних слів, бітовими рядками, окремими значеннями типу LongWord. Детальний їх опис можна знайти у вихідному коді модуля. У деяких функціях використовуються інструкції MMX, для виконання яких потрібен процесор не нижче Pentium-MMX або Pentium II. Коротко розглянемо основні групи функцій.


Перша група об’єднує функції для обміну значень змінних і кілька функцій для роботи з числами типу LongWord. Вона включає процедури G_Swap32, G_Swap16, G_ Swap8, що обмінюють значення двох змінних відповідного розміру (в бітах), процедуру G_BSwap, яка звертає порядок проходження байт у значенні типу LongWord, функції G_Log2, G_Gcd, G_ Lcm, що повертають, відповідно, логарифм числа за основи 2, найбільший спільний дільник двох чисел і найменше спільне кратне двох чисел. Функції G_CeilPowerOfTwo, G_FloorPowerOfTwo округлюють подвійне слово до найближчої ступеня числа 2 вгору або вниз, відповідно.


До другої групи належать функції, що працюють з масивами байт, слів і подвійних слів. Наприклад, коли необхідно заповнити нулями масив байт, стане в нагоді процедура G_ZeroMem. Якщо потрібно скопіювати вміст одного блоку пам’яті в інший і заздалегідь відомо, що ці блоки пам’яті не перекриваються, замість стандартної процедури Move краще скористатися процедурою G_ CopyMem з AcedBinary, яка виконає то ж дію значно швидше. Якщо блоки пам’яті можуть перекриваються, потрібно використовувати процедуру G_MoveMem. В цьому випадку при роботі з масивами подвійних слів можна трохи підвищити швидкодію, якщо викликати, відповідно, процедури G_ CopyLongs і G_MoveLongs. Крім того, може бути корисна процедура G_ FillLongs для заповнення масиву подвійних слів певним значенням або процедура G_ GenerateLongs, заповнює такий масив зростаючою або спадною послідовністю цілих чисел. Коли потрібно знайти число типу Word або Integer в несортовані масиві, замість організації циклу з перебором елементів масиву краще викликати функцію G_ Scan_Word або G_Scan_Integer. Ці функції використовують спеціальні машинні інструкції для швидкого пошуку значення в масиві двох-або четирехбайтний елементів. Аналогічні функції є для пошуку елемента з кінця масиву (G_ ScanBackward …), пошуку значення, що відрізняється від заданого (G_ScanOther …), заміни одних значень іншими (G_Replace …) і т.д.


В AcedBinary є група функцій для роботи з відсортованими масивами елементів типу Integer, Word, LongWord, яка включає функції для, власне, сортування масиву за збільшенням (G_Sort …), виконання бінарного пошуку (G_BinarySearch …). Сортовані масиви можна розглядати як множини і застосовувати до них відповідні операції. Наприклад, масив унікальних елементів типу Integer – це одне з можливих подань безлічі: [-2147483648 .. 2147483647]. Функція G_SetUnion_ Integer формує з двох таких масивів новий масив, що складається з елементів, які присутні хоча б в одному з вихідних масивів; G_SetIntersection_ Integer повертає масив, що складається тільки з тих елементів, які присутні в обох масивах; G_SetDifference_Integer повертає масив елементів, які присутні в першому, але відсутні в другому масиві; G_SetSymmetricDiffference_ Integer формує масив з елементів, які присутні тільки в одному з вихідних масивів. Є ще дві інформаційні функції для роботи зі множинами: G_ SetIntersectsWith_Integer повертає True, якщо в двох масивах є які-небудь спільні елементи, тобто перетин двох множин не є порожнім безліччю; інша функція – G_ SetContainedIn_Integer повертає True, якщо всі елементи першого масиву присутні в другому масиві, тобто першого безлічі є підмножиною другого. Аналогічні функції є для масивів елементів типу Word і LongWord. Ці функції можуть використовуватися спільно з класами TIntegerList і TWordList, визначеними в модулі AcedContainers.


Наступна група функцій в AcedBinary призначена для роботи з бітами в складі подвійного слова, тобто значення типу LongWord. Ця група включає функцію G_ReverseBits (звертає порядок проходження біт); G_BitTest32, G_BitSet32, G_ BitReset32, G_BitToggle32 (використовуються для перевірки, установки, скидання або інвертування одного біта у складі подвійного слова). Є також функції для підрахунку числа встановлених і скинутих біт, пошуку першого або останнього біта із заданим станом і інші.


Остання група функцій аналогічна щойно розглянутої, але ці функції працюють з битами в складі бітової рядка. Наприклад, функція G_BitSet встановлює в одиницю біт з заданим індексом в бітової рядку, адресується першим параметром цієї функції; функція G_ToggleBits інвертує всі біти в заданому діапазоні бітової рядка; G_CountOfFreeBits повертає число нульових бітів в заданому діапазоні бітової рядку; G_ SetBitScanForward повертає індекс першого встановленого, тобто одиничного, біта в складі бітової рядка. Ці та інші функції використовуються класом TBitList з модуля AcedContainers для ефективної роботи з даними, представленими у вигляді упакованого набору значень типу Boolean.


Модуль AcedStreams в Delphi   


Містить класи, призначені для роботи з бінарним потоком даних. Бінарний потік в даному контексті – це просто масив байт в пам’яті, розмір якого динамічно зростає у міру додавання нових даних. Після того, як всі дані поміщені в потік, його вміст може бути перетворено в масив, рядок в кодуванні Base64, збережено у файлі або в іншому потоці типу TStream. При цьому може бути виконано стиснення даних методом LZ + Huffman, шифрування методом RC6 і захист цифровий сигнатурою SHA-256. Для перевірки цілісності даних разом з ними в потік поміщається значення контрольної суми Адлера. Бінарний потік створюється за допомогою екземпляра класу TBinaryWriter. Стандартні класи в складі VCL орієнтовані на роботу з потоком типу TStream. Щоб вирішити цю проблему в модулі AcedStreams передбачений клас TStreamWriter, який є нащадком стандартного класу TStream і, одночасно, є оболонкою над TBinaryWriter. Таким чином, можна, наприклад, зберегти зображення типу TGraphic в потоці TBinaryWriter. Для цього потрібно створити екземпляр TStreamWriter, передавши в його конструктор посилання на TBinaryWriter. Потім цей екземпляр TStreamWriter передати як параметр в метод TGraphic.SaveToStream. Крім класів TBinaryWriter, TStreamWriter, в модулі AcedStreams є відповідні їм класи TBinaryReader, TStreamReader, призначені для читання даних з бінарного потоку.


Коли потрібно прочитати дані з потоку TBinaryReader, перш за все потрібно завантажити вихідний масив з даними в пам’ять. Для цього використовується один з наступних методів: LoadFromArray (завантажує дані з масиву байт, посилання на який передана в якості параметра), LoadFromBase64 (завантажує дані з рядка в кодуванні Base64), LoadFromFile (завантажує дані з файлу, який був попередньо відкритий і встановлено в позицію, відповідну початку блоку даних), LoadFromStream (завантажує дані з потоку типу TStream). Всі методи LoadFrom … приймають як параметр посилання на 256-бітний ключ EncryptionKey. Якщо в цьому параметрі переданий покажчик на ключ, відмінний від nil, при завантаженні даних виконується їх дешифрування з вказаним ключем і перевірка цілісності даних за збереженим в потоці значенням цифровий сигнатури SHA-256. У класі TBinaryReader є методи для читання з потоку значень різного типу, включаючи String, Integer, TDateTime і т.д., а також метод Read, що копіює заданий число байт з бінарного потоку в певну область пам’яті. Якщо дані бінарного потоку повинні бути лічені деяким стандартним класом, що працює тільки з потоками типу TStream, таким як клас TBitmap, потрібно створити екземпляр класу TStreamReader, передавши в його конструктор посилання на відповідний примірник TBinaryReader. Після цього дані можуть бути завантажені методом TBitmap. LoadFromStream з передачею в нього посилання на створений екземпляр TStreamReader.


Клас TBinaryWriter використовується для приміщення даних в бінарний потік, організований у вигляді динамічного масиву. Дані записуються в потік методами WriteString, WriteInteger, WriteDateTime і т.п. Крім того, метод Write дозволяє скопіювати в потік вміст довільної області пам’яті. Коли всі необхідні дані поміщені в бінарний потік, можна викликати один з наступних методів: SaveToArray (Представляє дані потоку, можливо, стислі і зашифровані, у вигляді масиву байт), SaveToBase64 (представляє дані у вигляді рядка в кодуванні Base64), SaveToFile (зберігає дані у файлі, дескриптор якого передано в якості параметра), SaveToStream (зберігає дані в потоці типу TStream). Всі методи SaveTo … приймають параметр CompressionMode, який встановлює режим стиснення бінарних даних перед приміщенням їх у вихідний масив (див. перелік констант, що вибирають режим стиснення, в описі модуля AcedCompression). Методи SaveTo … беруть також параметр EncryptionKey. Якщо він не дорівнює значенню nil, то повинен містити посилання на 256-бітний ключ, тобто масив з 32 байт. У цьому випадку дані бінарного потоку шифруються методом RC6 з вказаним ключем. Крім того, для них обчислюється значення цифровий сигнатури SHA-256, яка також записується в вихідний масив і використовується в подальшому при розшифровці даних для перевірки їх цілісності. Ключ шифру передається параметром типу PSHA256Digest. Цей тип є свого роду підказкою, що в якості ключа для шифрування методом RC6 зручно використовувати значення односторонньої функції SHA-256, розраховане для ключового масиву байт або рядки символів, вводиться користувачем з клавіатури в якості пароля.


Модуль AcedStrings


AcedStrings містить набір функцій, призначених для роботи з рядками типу AnsiString. Крім того, в цьому модулі визначений клас TStringBuilder, що є аналогом класів StringBuilder з. NET і Java. Розглянемо докладніше, що корисного є в цьому модулі.


В AcedStrings знаходяться функції, що реалізують швидке порівняння рядків з урахуванням або без урахування регістра символів. Порівняння виконується на більше-менше або на одно – не одно. При порівнянні можуть враховуватися всі символи або тільки певне число початкових символів рядка. Наступна група об’єднує функції, використовувані для перетворення рядків і окремих символів до верхнього або нижнього регістру. Далі слідують функції, які полегшують роботу з рядками, збереженими в кодуванні MS-DOS. Вони дозволяють швидко міняти кодування рядків з DOS на Windows і назад. В процесі перетворення використовуються масиви перекодування ToOemChars і ToAnsiChars, визначені в кінці інтерфейсного розділу модуля. Ці масиви за замовчуванням відповідають кодуванні “Кирилиця Win1251”. Однак, використовуючи невелику програму, текст якої наведено в вигляді коментаря в модулі AcedStrings, можна сформувати відповідні таблиці для будь-якої іншої кодування символів. Є також можливість динамічного формування таблиць перекодування в момент запуску програми на комп’ютері кінцевого користувача в залежності від поточних регіональних налаштувань. Цей режим включається при визначенні символу USE_DYNAMIC_TABLES в коді модуля AcedStrings.


Наступна група містить функції пошуку, заміни, видалення підрядків і окремих символів. Тут знаходяться функції швидкого пошуку підрядків з урахуванням і без урахування регістра символів. Пошук виконується з початку (Функції G_PosStr / G_ PosText) або з кінця рядка (функції G_ LastPosStr / G_LastPosText). Для пошуку окремих символів служать функції G_ CharPos і G_LastCharPos. Функція G_Paste замінює фрагмент рядка певної довжини, починаючи з вказаного символу, іншим фрагментом. Функції: G_ ReplaceStr, G_ReplaceText, G_ReplaceChar, G_ReplaceChars, G_ ReplaceCharsWithOneChar використовуються для заміни всіх входжень підрядка або деякого символу в рядку інший підрядком або символом. Функції: G_Delete, G_CutLeft, G_ CutRight, G_DeleteStr, G_DeleteText, G_ DeleteChar, G_DeleteChars, G_KeepChars використовуються для видалення з рядка фрагментів, підрядків або окремих символів. Функції: G_Compact, G_ Trim, G_TrimLeft, G_TrimRight видаляють з рядка пробіли і керуючі символи.


Далі слідують функції для роботи з маскою. Під маскою тут розуміється шаблон, подібний тому, який використовується при пошуку файлів на диску, як, наприклад, “rpt?? W?. Xls” або “*. Tmp”. Функція G_ApplyMask форматує рядок символів за допомогою маски, а G_ExtractWithMask, навпаки, витягує дані з рядка по масці; G_ ValidateMask використовується для перевірки того, що рядок задовольняє заданій масці; функції G_ ValidateWildStr і G_ ValidateWildText виконують перевірку відповідності рядка заданим шаблоном, який може містити спеціальні символи, які передбачають заміну їх будь-якою кількістю довільних символів, тобто аналогічні символу “*” в шаблоні для пошуку файлів.


Крім перерахованих, в AcedStrings входять функції: G_CountOfChar, G_CountOfChars для підрахунку числа входжень одного або декількох символів в рядок; G_IsEmpty для перевірки того, що рядок є порожній або містить тільки прогалини і керуючі символи; G_PadLeft, G_PadRight, G_ Center для доповнення рядка, відповідно, ліворуч, праворуч або з обох сторін зазначеним символом до необхідної довжини; функція G_Duplicate формує рядок, що складається з декількох копій іншого рядка; G_StrReverse звертає порядок символів у рядку.


Якщо для управління пам’яттю в проекті використовується менеджер пам’яті AcedMemory і в тексті модуля AcedStrings визначено символ USE_ ACED_MEMORY, стають доступні функції G_NewStr, G_Append, G_ AppendLine, G_Insert. Вони можуть використовуватися в якості альтернативи класу TStringBuilder для того, щоб ефективно змінювати і доповнювати рядки типу AnsiString на місці, без зайвого перерозподілу пам’яті. Наприклад, формування довгою рядки в циклі за допомогою функції G_Append виконується значно швидше простий конкатенації рядків. Однак, цей спосіб все ж менш ефективний, ніж використання класу TStringBuilder, тому що при кожній зміні рядка витрачається додатковий час на визначення розміру області пам’яті, виділеної під рядок. Функції типу G_Append, G_Insert краще застосовувати для внесення невеликого числа змін в довгий рядок, коли створення спеціального екземпляра класу TStringBuilder невиправдано.


Клас TStringBuilder


Цей клас призначений для динамічного створення рядка з окремих фрагментів і зміни рядки довільної довжини. В принципі, можна змінювати і доповнювати звичайну рядок типу AnsiString. Однак при кожному додаток такого рядка відбувається виділення пам’яті під новий рядок і копіювання в неї даних. Перерозподіл пам’яті – це досить повільна операція, незалежно від використовуваного менеджера пам’яті. У примірнику TStringBuilder рядок, по можливості, змінюється на місці, без зайвої перетасовки пам’яті. Наприклад, якщо необхідно сформувати рядок з елементів деякого списку, то замість того, щоб по черзі додавати рядки до змінної типу String, краще створити екземпляр класу TStringBuilder, додати кожен рядок зі списку методом Append, а потім перетворити результат до типу String викликом методу ToString класу TStringBuilder.


У класі TStringBuilder реалізовані основні методи для внесення змін та доповнення рядка. Зокрема, метод Append додає до цьому рядку інший рядок, фрагмент рядки, один або кілька повторюваних символів, десяткове або шістнадцяткове представлення числа; метод Insert вставляє підрядок в зазначену позицію; метод Delete видаляє фрагмент рядка; метод Reverse звертає порядок символів у всій рядку або в окремому фрагменті; метод Clear очищує рядок. Ще є методи для створення копії примірника класу TStringBuilder (метод Clone), перетворення рядка або її фрагмента до типу AnsiString (Метод ToString), заповнення фрагмента рядка зазначеним символом (метод Fill), додавання в кінець рядка символів перекладу рядка (метод AppendLine) та інші. Властивість Chars класу TStringBuilder дозволяє працювати з рядком як зі звичайним масивом символів.


Модуль AcedCommon


В AcedCommon зібрані різноманітні функції, в тому числі, для форматування дати і часу, перетворення числа в рядок і рядки в число, записи числових та грошових сум прописом, заміни символів рядка шістнадцятковим кодами цих символів і, навпаки, заміни кодів символами, кодування байтових масивів і рядків в Base64 і зворотного їх перетворення. Крім того, тут знаходяться функції для обчислення контрольної суми Адлера і CRC32, роботи з лічильниками, таймером високого дозволу, а також кілька допоміжних функцій.


Форматування дати і часу


На початку модуля AcedCommon оголошені константні масиви, що містять назви місяців і днів тижня, записаних по-російськи і по-англійськи. Для форматування дати використовується функція G_FormatDate. Вона повертає дату представлену короткої числовий формою або повною формою, яка містить назву місяця і слово “року”. Рядок-результат може включати також повне або коротка назва дня тижня або, взагалі, складатися тільки з дня тижня без дати. Функція G_ SplitDate дозволяє виділити з дати день місяця як числове значення, а сам місяць і рік представити у вигляді рядка. Для форматування часу використовується функція G_ FormatTime, яка перетворює час у рядок за правилами російської мови з можливим зазначенням числа секунд і мілісекунд.


Операції з числами типу Double і Currency


Наступна група об’єднує функції для роботи із значеннями типу Double і Currency. Зокрема, процедури G_Inc, G_Dec, G_ Mult, G_Div приймають в якості першого параметра посилання на змінну типу Double або Currency і, відповідно, складають, віднімають, множать або ділять її значення на число, передане другим параметром. Ці процедури покликані компенсувати собою відсутність у мові Delphi операцій “+ =”, “/ =” і т.п. з C-подібних мов. Функцію G_ToDouble необхідно викликати для приведення значення типу Currency до типу Double, т.к. звичайний спосіб приведення: “Double (Currency)” не спрацьовує через помилку в компіляторі. Функція G_ThousandsToDouble перетворює значення типу Currency до типу Double, одночасно ділить його на 1000 і округлює до 3-х знаків після коми.


Контрольна сума Адлера і CRC-32


Дана група функцій призначена для обчислення контрольних сум, що використовуються при перевірці цілісності даних. Контрольна сума являє собою число типу LongWord, яке залежить від усього вихідного масиву даних. При зміні хоча б одного біта даних, значення контрольної суми змінюється. Це значення може, наприклад, передаватися разом з даними по мережі, а потім перераховуватися на приймальному кінці і порівнюватися з вихідним значенням контрольної суми. Якщо обидва значення рівні, то з великою ймовірністю можна стверджувати, що дані передані без помилок. Тут маються на увазі випадкові помилки при передачі, а не навмисне спотворення даних. Для надійного захисту даних від будь-якого виду втручання замість контрольної суми потрібно використовувати цифрову сигнатуру, таку як SHA-256 (див. опис модуля AcedCrypto). Правда, значення односторонньої функції SHA-256 розраховується повільніше, ніж контрольна сума типу CRC-32.


Функція G_Adler32 обчислює контрольну суму Адлера масиву байт відповідно до RFC 1950. Ця контрольна сума застосовується бібліотекою стиснення zlib. Вона виходить швидше, ніж CRC-32, але, як видно, є трохи менше надійною. Функції G_ CRC32 і G_NextCRC32 повертають значення контрольної суми CRC-32 зазначеної області пам’яті. Друга функція відрізняється від першої тим, що вона використовується для поетапного розрахунку контрольної суми масиву, представленого у вигляді декількох фрагментів. Наприклад, якщо довгий масив передається по мережі у вигляді кількох пакетів, функція G_NextCRC32, що викликається послідовно для кожного пакета даних, обчислить в результаті контрольну суму цілого масиву. Пара функцій G_ CRC32_Str і G_ CRC32_Text може використовуватися при хешування рядків. Перша функція повертає значення типу LongWord, яке залежить від всіх символів рядка з урахуванням їх регістру. Друга функція повертає значення, яке залежить від всіх символів рядка, але не залежить від їх регістра, тобто це значення буде однаковим для рядків, які відрізняються тільки регістром символів.


Перетворення числа в рядок і рядки в число


В AcedCommon є кілька функцій для перетворення цілого числа в рядок, що містить його десяткове або шістнадцяткове подання (функції G_ IntToStr, G_UIntToHex та ін.) G_HexToUInt повертає число типу LongWord, шістнадцяткова запис якого передана параметром типу String. Функції G_Between … використовуються для перевірки того, що число, записане у вигляді рядка, лежить в потрібному діапазоні. Функції G_StrTo … виконують перетворення рядка в число, типу Integer, LongWord, Int64, Extended або Currency. У випадку помилки ці функції не генерують виняток, а повертають значення False. Ще є функція G_ModDiv10, яка ділить значення var-параметра на 10 і повертає залишок від ділення як результат функції. Вона може бути корисна при перетворенні в рядок довгих чисел.


Функції G_NumToStr і G_NumToRub використовуються для запису числових та грошових сум прописом по-російськи. Різні особливості запису чисел прописом налаштовуються відповідними параметрами форматування. Наприклад, виклик G_NumToStr (54321, S, nfFemale) поверне у змінній S рядок: “п’ятьдесят чотири тисячі триста двадцять один”, а виклик G_NumToRub (3.2, ruFull, ruNumShort) поверне рядок: “Три рубля 20 коп.”.


Робота з кодуванням Base64 і шістнадцятковим кодами


У цьому ж модулі знаходяться функції для роботи з кодуванням Base64, що представляють рядок символів або масив байт у вигляді нового рядка, не містить пробілів, керуючих символів і символів в національній кодуванні. Функція G_Base64 Encode виконує кодування рядка символів або масиву байт в Base64. Результат повертається у вигляді рядка типу AnsiString. Зворотне перетворення виконується функцією G_Base64 Decode, яка відновлює вихідний масив байт або рядок символів з рядка в кодуванні Base64. Крім того, тут знаходяться функції, що дозволяють представити рядок символів у вигляді рядка шістнадцятиричних кодів символів. Функція G_ StrToCodes повертає рядок, в якій кожен символ вихідного рядка, переданої параметром, замінений відповідним шістнадцятковим кодом. Наприклад, виклик G_ StrToCodes (“ABC”) поверне рядок: “414243”. Функція G_CodesToStr використовується для зворотного перетворення: G_ CodesToStr (“414242”) поверне рядок “ABC”.


Функції для виміру часових інтервалів


Коли в програмі потрібно відміряти тимчасові інтервали, можна скористатися стандартною функцією GetTickCount з модуля Windows, яка повертає число мілісекунд, що минув з моменту завантаження операційної системи. Оскільки це значення виражається числом типу LongWord, з часом воно може переповнитися і піти на наступний “коло”. Функція G_TickCountSince з модуля AcedCommon враховує цю особливість і повертає число мілісекунд, що минув з того моменту, як функція GetTickCount повернула значення Tick, передане в якості параметра в G_TickCountSince. Хоча GetTickCount повертає число мілісекунд, точність цієї функції не перевищує 0.1 секунди. Коли потрібно відміряти інтервал з точністю до однієї мілісекунди можна скористатися таймером високого дозволу. Отримати поточне значення таймера можна викликом функції G_QueryPC, яка повертає значення, отримане викликом системної функції QueryPerformanceCounter. По різниці значень таймера можна визначити тривалість тимчасового інтервалу за допомогою функції G_GetTimeInterval. Крім того, за допомогою функції G_GetPC_ Delta можна, навпаки, обчислити різницю значень таймера, відповідну тимчасового інтервалу певної тривалості.


До виміру часових інтервалів за допомогою таймера високого дозволу має сенс вдаватися, тільки коли потрібна висока точність. В інших випадках краще викликати функції GetTickCount і G_TickCountSince, тому що вони використовують менше ресурсів системи. У модулі AcedCommon є також функція G_ RDTSC, зчитує значення 64-розрядного лічильника, який збільшується на кожному такті процесора. В деяких випадках ця функція може замінити собою таймер високого дозволу. Крім того, вона може бути корисна при ініціалізації генератора псевдовипадкових чисел.


Інші функції


Функція G_SwitchToApplication переводить на передній план запущений екземпляр програми, до якого належить вікно з вказаним ім’ям класу. Зазвичай ця функція застосовується для запобігання повторного запуску програми, щоб замість запуску нового екземпляра вивести на передній план запущений раніше примірник програми. Крім того, її можна використовувати, наприклад, для перемикання на інше завдання при організації програми у вигляді декількох незалежних процесів. Функція G_SelectMenu використовується для імітації вибору користувачем заданого пункту або підпункту меню поточного вікна. При цьому у функцію вікна надсилаються події, що імітують натискання користувачем клавіші виклику меню, клавіш зі стрілками вправо і вниз, клавіші Enter, в послідовності, необхідної для вибору потрібного пункту меню. При цьому глибина розкритого підпункту може бути будь-хто. Функції G_ToggleKey і G_ IsToggled керують станом клавіш: Num Lock, Caps Lock, Scroll Lock. Перша функція дозволяє змінити стан будь-якої з цих клавіш, друга – зчитує поточний стан відповідної клавіші. Остання функція G_ODS поміщає повідомлення в Event Log (журнал, що викликається з відладчика в середовищі Delphiпо Ctrl + Alt + V).


Модуль AcedCompression


У модулі AcedCompression знаходяться функції, призначені для стиснення бінарних даних методом Зеева-Лемпела з наступним перетворенням в код Хаффмана. Упаковка даних здійснюється функцією G_Deflate, яка приймає як параметр Mode одну з констант, що вибирають режим стиснення. Допустимі наступні режими:



Модуль AcedCrypto


Модуль об’єднує функції, використовувані для шифрування і верифікації даних, а також для генерації псевдовипадкових чисел.


Функції G_RC4 … призначені для шифрування даних методом RC4. Це широко поширений потоковий шифр. Можливо, по стійкості він поступається блоковим шифрам, типу Rijndael або CAST, але, зате, значно перевершує їх по продуктивності. Не так давно в цьому шифрі було виявлено кілька вразливостей, які стосуються алгоритму заповнення внутрішнього масиву ключів (key scheduling algorithm). Щоб уникнути пов’язаної з цим гіпотетичної небезпеки злому зашифрованих даних, компанія RCA, розробник даного шифру, рекомендує пропускати перші 256 байт вихідний псевдослучайной послідовності. Функції з модуля AcedCrypto написані з урахуванням цього зауваження. При правильному використанні метод RC4 є цілком надійним. Треба тільки пам’ятати основну особливість потокових шифрів – один і той же ключ не повинен застосовуватися для шифрування різних даних. Наприклад, ключ може обчислюватися за допомогою побітової операції xor двох чисел, одне з яких є постійним і розраховується як цифрова сигнатура пароля, що вводиться користувачем з клавіатури, а друге число є змінним і створюється генератором псевдовипадкових чисел перед кожним сеансом шифрування даних. Змінюване число може зберігатися в перших байтах зашифрованого потоку даних.


Наступний набір функцій з AcedCrypto – G_RC6 … призначений для шифрування даних методом RC6. Це блоковий шифр, розроблений компанією RCA. Нормальна довжина ключа для шифрування методом RC6 становить 256 біт (32 байти). В AcedCrypto є функції для ініціалізації процесу шифрування, завдання початкового вектора, шифрування і дешифрування 128-бітного блоку даних в режимі ECB (електронна кодова книга), шифрування і дешифрування довільного масиву байт в режимах CFB (зворотна завантаження шіфротекста) і OFB (зворотна завантаження вихідних даних) з розміром блоку 128 біт. У режимах CFB і OFB розмір шіфруемих і дешіфруемих фрагментів даних повинен збігатися або розмір цих фрагментів повинен бути кратний 16 байт. При використанні в якості ключа шифру пароля, що вводиться користувачем з клавіатури, потрібно передавати в функцію G_RC6Init в якості ключа не саму рядок, що містить введений пароль, а цифрову сигнатуру SHA-256, розраховану для рядка, введеної користувачем.


Далі в модулі AcedCrypto знаходяться функції, призначені для розрахунку значення односторонньої хеш-функції SHA-256 масиву байт. Цифрова сигнатура SHA-256 являє собою масив з 32 байт, який обчислюється за даними вихідного масиву байт таким чином, щоб, по-перше, неможливо було підібрати інший масив байт, для якого значення сигнатури співпало б з даною сигнатурою, і, по-друге, щоб за значенням цифрової сигнатури неможливо було відновити небудь значення з вихідного масиву байт. Алгоритм розрахунку SHA-256 реалізований відповідно до документа FIPS180-2. Не так давно була опублікована інформація про знаходження уразливості в алгоритмі хеш-функції SHA-1. У зв’язку з цим слід зазначити, що алгоритм SHA-256 багато в чому відрізняється від SHA-1 і про успішні атаки на SHA-256 до сих пір нічого не відомо. У модулі AcedCrypto є функції для розрахунку цифрової сигнатури для масиву байт і рядки символів. Крім того, можна розрахувати сигнатуру для масиву байт, представленого у вигляді декількох фрагментів. Це зручно, наприклад, при роботі з даними, організованими у вигляді потоку типу TStream.


Функції G_Random … реалізують генератор псевдовипадкових чисел типу Mersenne Twister, період якого можна вважати рівним нескінченності. Функція G_ RandomNext повертає число типу LongWord, рівномірно розподілене в інтервалі від 0 до $ FFFFFFFF; функція G_RandomUniform генерує псевдослучайную величину, рівномірно розподілену в інтервалі [0.0, 1.0]; G_ RandomGauss використовується для моделювання безперервної випадкової величини з нормальним законом розподілу. Функція G_RandomFill дозволяє заповнити область пам’яті псевдослучайной послідовністю байт. Функція G_RandomEncryptVector шифрує внутрішній вектор, який використовується при генерації псевдовипадкових чисел, методом RC6. Це відповідає перекладу генератора на нову числову послідовність. Слід зазначити, що сама по собі вихідна числова послідовність даного генератора не є криптографічно стійкою. Щоб перетворити її в криптографічно стійку, можна скористатися, наприклад, функцією G_SHA256 Transform.


Модуль AcedAlgorithm


Об’єднує функції для роботи з набором даних, представленим у вигляді масиву покажчиків. Такі масиви зручні для подання в пам’яті різних тимчасових списків, які можуть містити посилання на які зберігаються об’єкти типу TSerializableObject, покажчики на записи, використовувані в процесі групування даних при побудові звітів, і т.п. Працювати з масивами вказівників зручно за допомогою класу TArrayList з модуля AcedContainers. Але клас TArrayList містить методи для виконання тільки самих основних операцій з даними. Велике число інших операцій реалізується функціями з модуля AcedAlgorithm. Застосувати будь-які з цих функцій до даних, що містяться в наборі TArrayList, можна працюючи з властивостями ItemList і Count класу TArrayList. Розглянемо структуру модуля AcedAlgorithm.


На початку модуля розташовуються функції G_ Search і G_ SearchBackward для лінійного пошуку в масиві. Шукане значення Value передається в ці функції як покажчик. Крім того, одним із параметрів є адреса функції типу TMatchFunction, призначеної для зіставлення значення елементу масиву. Функція G_Search виробляє послідовний пошук, починаючи з перших елементів масиву, G_ SearchBackward – Пошук назад, починаючи з останніх елементів масиву. Функція G_ Replace знаходить в масиві всі елементи, рівні значенням Value, і замінює їх новим елементом, який передається як параметр функції. G_ CountOf підраховує кількість елементів, рівних згаданої значенням. Функція G_ RemoveCopy копіює в новий масив все елементи з вихідного масиву, крім тих, які дорівнюють значенню Value. Ще є функції для видалення суміжних дублікатів елементів. Далі слідують функції для пошуку мінімального і максимального елементів масиву. Функції G_SearchMin і G_SearchMax повертають сам мінімальний або максимальний елемент, а G_ IndexOfMin і G_ IndexOfMax – індекс мінімального чи максимального елемента. Коли потрібно знайти відразу і мінімум і максимум в масиві елементів, замість того, щоб викликати спочатку G_ SearchMin, а потім G_ SearchMax, краще скористатися функцією G_ SearchMinMax, яка оптимізована для такого випадку.


Наступні функції призначені для переупорядочивания елементів масиву за різними критеріями. Функція G_ Rotate переміщує всі елементи масиву, починаючи з зазначеного індексу, і до кінця масиву, в початок масиву, а елементи з початку до зазначеного індексу – в кінець масиву. G_ RotateCopy аналогічна G_Rotate, але зберігає результат у новому масиві і виконується трохи швидше, ніж G_ Rotate. Функція G_PartitionStrict переміщає всі елементи масиву, менші заданого значення, в початок масиву. Інші елементи переміщуються в кінець масиву. G_PartitionUnstrict відрізняється від G_PartitionStrict тільки умовою (“менше або дорівнює “замість” менше “) переміщення елементів в початок масиву. Є також аналоги цих функцій з приставкою Stable (G_StablePartitionStrict і G_StablePartitionUnstrict). Вони відрізняються тим, що при переміщенні елементів зберігається їх відносний порядок до і після значення Value. Функція G_SelectTop переміщує N мінімальних елементів в початок масиву. Інші елементи переміщуються в кінець масиву. Ця функція працює подібно алгоритму Nth_element з STL. Функція G_ StableSelectTop виконує ту саму дію, але без порушення відносного порядку елементів в лівій і правій частинах масиву, тобто до і після N-го елемента. При невеликому обсязі даних “stable” і “nonstable” варіанти функцій майже не відрізняються за швидкістю роботи, але для підтримки відносної порядку елементів припадає задіяти додаткову пам’ять в розмірі, що займає вихідним масивом покажчиків. Функція G_ RandomShuffle перемішує масив покажчиків за допомогою генератора псевдовипадкових чисел.


Далі слідують функції для сортування масиву за зростанням значень елементів. Елементи масиву порівнюються між собою за допомогою функції типу TCompareFunction, адреса якої передається як параметр в усі процедури сортування. Найшвидша сортування великого обсягу даних виконується процедурою G_ Sort, що реалізує метод інтроспективної сортування. Даний алгоритм є модифікацією алгоритму швидкого сортування, яка передбачає вибір для кожного діапазону середнього значення з трьох варіантів: початок, середина і кінець діапазону. Крім того, якщо підбираються вихідні дані, критичні для алгоритму швидкого сортування, і його складність досягає O (N2), Функція G_Sort замінює швидку сортування пірамідальної, складність якої завжди O (N * Log (N)). Коли потрібно відсортувати дані без зміни відносного порядку рівних елементів, стане в нагоді функція G_ StableSort, що реалізує метод сортування злиттям. На відміну від інтроспективної сортування, даний метод вимагає виділення додаткової пам’яті розміром, рівним розміром сортованого масиву покажчиків. Якщо потрібно відсортувати не весь масив, а тільки перші (найменші) N елементів, можна скористатися функцією G_ PartialSort або G_ PartialSortCopy, заснованими на алгоритмі пірамідальної сортування. Перевірити, чи є масив відсортованим за зростанням можна за допомогою функції G_IsSorted.


В AcedAlgorithm є функції для бінарного пошуку елементів у масиві, відсортованому за зростанням шуканого ознаки. Функція G_ BinarySearch повертає індекс елемента, значення якого дорівнює заданому. G_ SearchFirstGreater (G_ SearchFirstGreaterOrEqual) повертає індекс першого елемента масиву, значення якого більше (більше або дорівнює) згаданої значенням. G_SearchLastLesser (G_ SearchLastLesserOrEqual) повертає індекс останнього елемента в відсортованому масиві, значення якого менше (менше або дорівнює) шуканого значення. Також є функції для злиття сортованих масивів елементів. Перша з них – G_Merge створює з двох відсортованих масивів новий масив, що складається з усіх елементів вихідних масивів, який також є відсортованим за зростанням. Інші функції об’єднують масиви подібно до того, як різні логічні операції застосовуються до множинам. Наприклад, функція G_SetIntersection зберігає у вихідному масиві перетин вихідних масивів, тобто тільки ті елементи, які присутні в обох вихідних масивах.


Остання група функцій у цьому модулі призначена для роботи з купою. Купа є бінарне дерево у вигляді послідовної колекції елементів. Причому значення кожного вузла такого бінарного дерева більше або дорівнює значенням його дочірніх вузлів. Куча має такі властивості: перший елемент купи завжди є максимальним елементів в масиві, додавання і видалення елементів купи виконується з логарифмічною складністю. На основі куп можуть створюватися пріоритетні черги елементів. Крім того, механізм куп лежить в основі алгоритмів пірамідальної і часткової сортування елементів масиву. Процедура G_ MakeHeap змінювати порядок масив так, щоб він представляв собою купу. G_ PushHeap поміщає значення в купу. G_PopHeap витягує значення з купи. G_SortHeap сортує елементи купи за зростанням, тобто перетворює купу в звичайний сортований масив. Функція G_IsHeap перевіряє, чи є масив елементів купою.


Модуль AcedContainers


Містить класи, які є контейнерами даних.


Бітова рядок TBitList


Надає методи і властивості для роботи з рядком біт, яку можна представити як упакований набір елементів типу Boolean. Спочатку, при створенні екземпляра класу TBitList викликом конструктора Create, все біти рядка встановлюються в 0 (False) або 1 (True), залежно від значення, переданого в параметрі InitValue конструктора. Метод Load використовується для завантаження бітової рядки з бінарного потоку типу TBinaryReader, довільної області пам’яті або іншого екземпляра класу TBitList. Крім того, дані можуть бути завантажені з ключа реєстру Windows. Для збереження даних в бінарному потоці типу TBinaryWriter або в реєстрі Windows призначений метод Save. Завантажити бітову рядок зі звичайної рядка, що складається з символів “0” і “1”, можна за допомогою методу FromString. Навпаки, щоб представити бітову рядок у вигляді звичайної рядки, треба скористатися функцією ToString.


До окремих елементів бітової рядки можна звернутися за допомогою властивості Bits. Змінити стан окремих бітів можна також методами SetBit, ResetBit і ToggleBit. Загальне число елементів повертається і встановлюється властивістю Count. Функція Contains перевіряє наявність в бітової рядку елемента з вказаним значенням (True або False). Методи IndexOf, LastIndexOf використовуються для пошуку, відповідно, вперед і назад першого встановленого або скинутого біта, починаючи з зазначеного індексу. Функція CountOf підраховує загальну кількість встановлених або скинутих біт в масиві. Метод SetAll встановлює всі біти в значення 0 або 1. Якщо два примірники класу TBitList містять однакове число елементів, до них можна застосувати різні логічні операції. Наприклад, метод AndBits виконує операцію логічного множення елементів двох списків. В результаті, встановленими виявляться тільки біти, які були встановлені в обох списках, а всі інші біти будуть встановлені в 0. Аналогічні методи передбачені для виконання операцій: OR, XOR, NOT, AND NOT. Функція Equals використовується для перевірки рівності вмісту двох екземплярів класу TBitList. Функція Clone повертає копію примірника TBitList.


Класи TIntegerList, TWordList


Ці класи призначені для роботи зі списком значень типу Integer або Word, відповідно. Класи повністю аналогічні одна одній, тому розглянемо тільки перший з них – TIntegerList. Список значень може бути підібране або непідібране. Це залежить від властивості MaintainSorted. Якщо воно дорівнює True, при виконанні операцій додавання і видалення елементи списку гарантовано розташовуються в порядку зростання значень. Якщо властивість MaintainSorted одно False, нові елементи додаються в кінець списку, незалежно від їх значень. В цьому випадку допустимо використовувати метод Insert для вставки одного або декількох елементів у довільне місце списку. Крім того, можна використовувати метод UnorderedRemoveAt для швидкого видалення елементів списку. При виклику даного методу видаляється елемент заміщується останнім елементом списку, після чого властивість Count зменшується на 1. Таким чином, видалення елемента відбувається без зсуву всіх наступних за ним елементів списку. Коли MaintainSorted одно True, при виклику методів Insert і UnorderedRemoveAt виникає виняток, тому що довільна вставка і unordered-видалення можуть порушити порядок сортування елементів.


Для пошуку значень в списку застосовується метод IndexOf, який повертає індекс знайденого елементу або -1, якщо шуканий елемент відсутній. Коли елементи списку розсортовані, використовується швидкий алгоритм бінарного пошуку, в іншому випадку – лінійний пошук за допомогою функції G_Scan_ Integer з модуля AcedBinary. Іноді буває зручніше не підтримувати список весь час в відсортованому вигляді, так як це уповільнює процес вставки і видалення елементів. Натомість перед початком пошуку можна викликати метод EnsureSorted. Тоді, якщо список не був відсортований, він сортується, а потім виконується швидкий бінарний пошук. Природно, це має сенс робити, тільки якщо пошук виконується багаторазово, тому що сама сортування займає більше часу, ніж лінійний пошук.


Аналогічно класу TBitList, в TIntegerList є методи для завантаження списку з бінарного потоку типу TBinaryReader, з довільної області пам’яті, з реєстру Windows або з іншого екземпляра класу TIntegerList. Список може бути збережений в бінарному потоці TBinaryWriter або в реєстрі Windows. Крім того, список може бути завантажений з рядка, що містить дані в кодуванні Base64, і може бути збережений у вигляді рядка в кодуванні Base64. Нові елементи зазвичай додаються в список методами Add або AddIfNotExists, коли необхідно уникнути дублювання значень в списку. Щоб видалити елемент зі списку за індексом, викликається метод RemoveAt, а щоб видалити всі елементи з певним значенням – метод Remove. При видаленні значень методами Remove і RemoveAt порядок залишаються в списку елементів не змінюється. Список повністю очищається при виклику методу Clear. Функція Equals дозволяє поелементно порівняти два списки, а функція Clone повертає копію даного екземпляра класу TIntegerList.


Коли властивість MaintainSorted одно False, примірник TIntegerList можна використовувати як стека. Значення поміщаються в стек (в кінець списку) методом Add, а витягуються з стека (з кінця списку) методом PopBack відповідно до правила: “першим увійшов – останнім вийшов”. Отримати останнє значення, поміщене в стек, без його видалення можна методом PeekBack. Звернутися до окремих елементів списку можна через властивість ItemList, яке повертає покажчик на масив елементів типу Integer. Число використовуваних елементів в цьому масиві визначається властивістю Count. Кількість елементів, під яке розподілена пам’ять у внутрішньому масиві, зчитується і встановлюється властивістю Capacity. Початкове значення цієї властивості передається як параметр в конструктор класу TIntegerList.


При описі модуля AcedBinary були розглянуті функції, що дозволяють працювати з масивами чисел типу Integer як з множинами, зокрема, застосовувати до них різні логічні операції. Ці операції можна виробляти і з примірниками класу TIntegerList. Наприклад, нехай є два відсортованих списку значень типу Integer List1 і List2, з яких необхідно отримати третій список List3, що містить значення, присутні в першому списку, але відсутні у другому. Це відповідає операції віднімання множин. Можна створити новий екземпляр класу TIntegerList для зберігання списку-результату List3, передавши в його конструктор число елементів першого списку, тому що це число відповідає максимальній довжині вихідного масиву для випадку, коли два вихідних безлічі не мають перетину. Операція віднімання множин та заповнення списку List3 виконується одним рядком коду:


List3.Count := G_SetDifference_Integer(List1.ItemList, List1.Count, List2.ItemList, List2.Count, List3.ItemList).


Список покажчиків TArrayList


TArrayList є аналогом класу ArrayList з. NET Framework. Він являє собою динамічний масив покажчиків. У конструктор класу передається передбачуване число елементів, яке буде додано в список. Елементи можна завантажити методом Load з іншого екземпляра класу TArrayList або з довільної області пам’яті. Окремі елементи додаються методом Add в кінець списку або методом Insert в довільне місце списку. Для видалення одного або кількох елементів за індексом використовується метод RemoveAt. Метод UnorderedRemoveAt дозволяє швидко видалити елемент зі списку, замінивши його останнім елементом списку і зменшивши на 1 значення властивості Count. Він може застосовуватися, коли порядок елементів не має значення. Для повного очищення списку призначений метод Clear. Аналогічно класам TIntegerList, TWordList, в класі TArrayList є методи для роботи зі списком як з стеком. Метод PopBack повертає посл

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*