Найти глобальный атом из частичной строки
Я могу создать Глобальный Атом, используя GlobalAddAtom
и я могу найти этот атом снова, используя GlobalFindAtom
если я уже знаю строку, связанную с атомом. Но есть ли способ найти все атомы, чья связанная строка соответствует данной частичной строке?
Например, допустим, у меня есть атом, строка которого "Hello, World!" Как я могу позже найти этот атом, выполнив поиск "Hello"?
2 ответа
К сожалению, описываемое вами поведение невозможно для таблиц Atom. Это связано с тем, что таблицы Atom в Windows в основном являются хэш-таблицами, а процесс отображения обрабатывает строки целиком, а не по частям.
Конечно, это звучит так, как будто это возможно, как указано в документации MSDN:
Приложения могут также использовать таблицы локальных атомов для экономии времени при поиске конкретной строки. Чтобы выполнить поиск, приложению нужно только поместить строку поиска в таблицу атомов и сравнить полученный атом с атомами в соответствующих структурах. Сравнение атомов обычно быстрее, чем сравнение строк.
Однако они имеют в виду точные совпадения. Это ограничение, вероятно, устарело по сравнению с тем, что возможно с ресурсами, доступными в настоящее время для программного обеспечения. Тем не менее, Atoms были доступны еще в Win16, и в то время это средство позволяло приложениям эффективно управлять строковыми данными в минимальном объеме памяти. Атомы по-прежнему используются в настоящее время для управления именами классов окон и все еще обеспечивают приличные преимущества в уменьшении занимаемой площади нескольких хранимых копий строк.
Если вам необходимо эффективно хранить строковые данные и иметь возможность сканирования путем частичных начальных совпадений, дерево суффиксов, вероятно, удовлетворит или превысит ваши потребности.
Это на самом деле можно сделать, но только путем сканирования их всех. В LINQPad 5 это можно сделать за 0,025 секунды на моем компьютере, поэтому это довольно быстро. Вот пример реализации:
void Main()
{
const string atomPrefix = "Hello";
const int bufferSize = 1024;
ushort smallestAtomIndex = 0XC000;
var buffer = new StringBuilder(bufferSize);
var results = new List<string>();
for (ushort atomIndex = smallestAtomIndex; atomIndex < ushort.MaxValue; atomIndex++)
{
var resultLength = GlobalGetAtomName(atomIndex, buffer, bufferSize);
if (buffer.ToString().StartsWith(atomPrefix))
{
results.Add($"{buffer} - {atomIndex}");
}
buffer.Clear();
}
results.Dump();
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint GlobalGetAtomName(ushort atom, StringBuilder buffer, int size);