_wS_
|
Дата: Воскресенье, 13.05.2012, 18:49:44 | Сообщение # 1 |
|
Класс: StringMap (adt_trie.inc) https://sm.alliedmods.net/new-api/adt_trie/StringMap
Позволяет хранить разные типы данных по уникальным ключам-строкам, например, "zx". Ключ "zx" и "Zx" это разные ключи. Символы в имени ключа могут быть любыми, SourceMod запустит цикл по каждому из них, чтобы преобразовать ключ-строку в unsigned int хэш.
Для хранения строк StringMap подходит лучше, чем ArrayList, т.к. хранит строку такой, какая она есть. ArrayList же каждому элементу выделяет одинаковое количество байтов. Поиск в StringMap работает намного быстрее, чем в ArrayList.
Создать StringMap объект. Уничтожьте, если больше не нужен: delete map
Код StringMap map = new StringMap();
Создать точно такой же StringMap объект-копию, который никак не связан с оригиналом. Требуется SourceMod 1.11+
Код StringMap map_clone = map.Clone();
Добавить/изменить значение. Если replace false и key уже существует, то значение перезаписано не будет и вернёт false. Значением может быть int/bool/float/Handle.
Код bool map.SetValue(const char[] key, any value, bool replace=true);
Добавить/изменить массив. Можно использовать и структуры (enum struct).
Код bool map.SetArray(const char[] key, const any[] array, int num_items, bool replace=true);
Добавить/изменить строку:
Код bool map.SetString(const char[] key, const char[] value, bool replace=true);
Получить данные. size = сколько байтов записано в буфер. Например, для строки "t" вернёт 1, а для "т" 2.
Код bool map.GetValue(const char[] key, any &value); bool map.GetArray(const char[] key, any[] array, int max_size, int &size=0); bool map.GetString(const char[] key, char[] value, int max_size, int &size=0);
Удалить ключ:
Код bool map.Remove(const char[] key);
Удалить все ключи:
Получить количество всех ключей:
Получить список всех ключей (их имена). Этот список (snapshot) никак не связан с map, и его нужно уничтожить (delete), когда он не нужен. Если удалить ключ из map, или уничтожить map, то snapshot остаётся прежним.
Код StringMapSnapshot snapshot = map.Snapshot();
Количество ключей в snapshot:
Возвращает размер буфера, необходимый для хранения данного ключа (длина ключа + 1). char[] buffer = new char[размер]; index - позиция ключа от 0 до snapshot.Length - 1
Код int snapshot.KeyBufferSize(int index);
Получить имя ключа по его позиции (index). По идее ключи упорядочены в случайном порядке и не стоит ожидать какого-то конкретного порядка. Возвращает количество байтов, записанных в буфер.
Код int snapshot.GetKey(int index, char[] buffer, int maxlength);
Примеры:
Код enum struct Test { int number; char name[4]; }
public void OnPluginStart() { StringMap map = new StringMap(); // Записываем данные: map.SetValue("hp", 150); if (!map.SetValue("hp", 200, false)) { PrintToServer("Ключ \"hp\" уже существует"); } map.SetArray("rgb", {255, 100, 200}, 3); Test t; t.number = 12345; strcopy(t.name, sizeof(t.name), "Cat"); map.SetArray("test", t, sizeof(t)); map.SetString("game", "CS:S"); // Получаем записанные данные: int hp; if (map.GetValue("hp", hp)) { PrintToServer("hp = %d", hp); // hp = 150 } int rgb[3]; if (map.GetArray("rgb", rgb, sizeof(rgb))) { PrintToServer("rgb = %d %d %d", rgb[0], rgb[1], rgb[2]); // rgb = 255 100 200 } t.number = 0; t.name[0] = 0; if (map.GetArray("test", t, sizeof(t))) { PrintToServer("Test::number = %d, Test::name = %s", t.number, t.name); // Test::number = 12345, Test::name = Cat } // Если нужно получить не весь элемент, а определённое кол-во первых ячеек: any a[1]; if (map.GetArray("test", a, sizeof(a))) { PrintToServer("Test::number = %d", a[0]); // Test::number = 12345 } int bytes; char game[16]; if (map.GetString("game", game, sizeof(game), bytes)) { PrintToServer("game = %s, bytes = %d", game, bytes); // game = CS:S, bytes = 4 } PrintToServer("Ключей в map: %d", map.Size); // Ключей в map: 4 if (map.Remove("hp")) { PrintToServer("Ключ \"hp\" удалён. Осталось ключей: %d", map.Size); // Ключ "hp" удалён. Осталось ключей: 3 } StringMapSnapshot snapshot = map.Snapshot(); if (snapshot) { int snapshotLength = snapshot.Length; PrintToServer("snapshot.Length = %d", snapshotLength); // snapshot.Length = 3 for (int index = 0, keyBufferSize; index < snapshotLength; index++) { keyBufferSize = snapshot.KeyBufferSize(index); char[] key = new char[keyBufferSize]; bytes = snapshot.GetKey(index, key, keyBufferSize); PrintToServer("Ключ: \"%s\", keyBufferSize: %d, bytes = %d.", key, keyBufferSize, bytes);
// Ключ: "test", keyBufferSize: 5, bytes = 4. // Ключ: "game", keyBufferSize: 5, bytes = 4. // Ключ: "rgb" , keyBufferSize: 4, bytes = 3. } // Не забываем уничтожать. delete snapshot; } // Раз map уже совсем не нужен, уничтожаем. delete map; }
Если map содержит ключи с разными типами данных, то в StringMapSnapshot можно столкнуться с проблемой. SourceMod API не позволяет определить тип данных, у нас есть только имя ключа. Если попытаться получить/перезаписать один тип данных на другой, то скорее всего будет ошибка. Поэтому, нужно или имена ключей сравнивать, или где-то хранить инфу о типе, или использовать несколько StringMap под каждый тип.
Сообщение отредактировал _wS_ - Вторник, 14.12.2021, 05:43:33 |
|
| |