Difference between revisions of "Ru:KeyValues (SourceMod Scripting)"

From AlliedModders Wiki
Jump to: navigation, search
(New page: KeyValues are simple, tree-based structures used for storing nested sections containing key/value pairs. Detailed information on KeyValues can be seen at the [http://developer.valvesoftwa...)
 
(Deletion)
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
KeyValues are simple, tree-based structures used for storing nested sections containing key/value pairsDetailed information on KeyValues can be seen at the [http://developer.valvesoftware.com/wiki/KeyValues_class Valve Developer Wiki].   
+
KeyValues это простая древовидная структура используемая для хранения вложенных разделов состоящих из пар ключ/значениеДетальная информация про KeyValues может быть найдена на [http://developer.valvesoftware.com/wiki/KeyValues_class Valve Developer Wiki].   
  
All KeyValues specific functions in this document are from <tt>public/include/keyvalues.inc</tt>.
+
Все KeyValues функции в этом документе находятся в <tt>public/include/keyvalues.inc</tt>.
  
=Introduction=
+
=Введение=
KeyValues consist of a ''nodes'', or ''sections'', which contain pairs of keys and valuesA section looks like this:
+
KeyValues состоит из ''узлов'' и ''разделов'', которые содержат пары ключей и значенийРазделы выглядят примерно так:
<pre>"section"
+
<pre>"раздел"
 
{
 
{
"key" "value"
+
"ключ" "значение"
 
}</pre>
 
}</pre>
  
The <tt>"section"</tt> string denotes the section's nameThe <tt>"key"</tt> string is the key name, and the <tt>"value"</tt>" string is the value.
+
Сторка <tt>"раздел"</tt> является именем разделаСтрока <tt>"ключ"</tt> это имя ключа и строка <tt>"значение"</tt>" является значением.
  
KeyValues structures are created with <tt>CreateKeyValues()</tt>.  The Handle must be freed when finished in order to avoid a memory leak.
+
KeyValues структуры создаются с помощью <tt>CreateKeyValues()</tt>.  Handle должен быть освобожден после завершения работы для устранения утечки памяти.
  
=Files=
+
=Файлы=
KeyValues can be exported and imported via KeyValues filesThese files always consist of a root node and any number of sub-keys or sub-sectionsFor example, a file might look like this:
+
KeyValues могут быть экспортированы и импортированы с помощью KeyValues файловЭти файлы всегда состоят из главного узла и множества под-ключей или подразделовНапример файл может выглядеть вот так:
 
<pre>"MyFile"
 
<pre>"MyFile"
 
{
 
{
Line 24: Line 24:
 
}</pre>
 
}</pre>
  
In this example, <tt>STEAM_0:0:7</tt> is a section under <tt>MyFile</tt>, the root node.   
+
В этом примере <tt>STEAM_0:0:7</tt> это раздел под главным узлом <tt>MyFile</tt>.   
  
To load KeyValues from a file, use <tt>FileToKeyValues</tt>  To save KeyValues to a file, use <tt>KeyValuesFromFile</tt>.  For both cases, you must already have a Handle to a KeyValues structure.
+
Для загрузки KeyValues из файла используйте <tt>FileToKeyValues</tt>. Для сохранения KeyValues в файл используйте <tt>KeyValuesFromFile</tt>.  Для обоих случае вы всегда должны иметь Handle ссылающийся на KeyValues структуру.
  
=Traversal=
+
=Перемещение=
SourceMod provides natives for traversing over a KeyValues structureHowever, it is important to understand how this traversal worksInternally, SourceMod keeps track of two pieces of information:
+
SourceMod обеспечивает нативное перемещение по KeyValues структуреОднако очень важно понимать как происходит это перемещениеВнутренне, SourceMod отслеживает из двух частей информации:
*The root node
+
*Главный узел
*A traversal stack
+
*Стек перемещения
  
Since a KeyValues structure is inherently recursive (it's a tree), the ''traversal stack'' is used to save a history of each ''traversal'' made (a traversal being a recursive dive into the tree, where the current nesting level deepens by one section).  The ''top'' of this stack is where all operations take place.   
+
Поскольку структура KeyValues изначально рекурсивная (это дерево), ''стек перемещения'' используется для сохранения истории каждого ''перемещения'' (перемещение начинается рекурсивно погружаться в дерево, где текущий уровень вложенности углубляется на одну секцию).  ''верх'' этого стека где все операции имеют место..   
  
For example, <tt>KvJumpToKey</tt> will attempt to find a sub-key under the current sectionIf it succeeds, the position in the tree has changed by moving down one level, and thus this position is pushed onto the traversal stackNow, operations such as <tt>KvGetString</tt> will use this new position.
+
Например, <tt>KvJumpToKey</tt> будет пытаться найтим под-ключ под текущим разделомПри успехе позиция в дереве изменяется перемещением вниз на один уровень, и, следовательно, эта позиция помещается в стек перемещенияТеперь операции такие как <tt>KvGetString</tt> будут использовать эту новую позицию.
  
There are natives which change the position but do not change the traversal stackFor example, <tt>KvGotoNextKey</tt> will change the current section being viewed, but there are no push/pop operations to the traversal stackThis is because the nesting level did not change; it advances to the next section at the same level, rather than finding a section a level deeper.
+
Это нативные изменяют положение, но не меняют стек перемещенияНапример, <tt>KvGotoNextKey</tt> будет менять текущий раздел перед просмотром, но это не является push/pop операциями для стека перемещенияЭто потому, что уровень вложенности не изменился; он проходит в следующий раздел на том же уровне, скорее чем найти секцию уровнем глубже.
  
More traversal natives:
+
Больше нативных перемещений:
*<tt>KvGotoFirstSubKey</tt> - Finds the first sub-section under the current sectionThis pushes the section onto the traversal stack.
+
*<tt>KvGotoFirstSubKey</tt> - Находит первый подраздел ниже текущей позицииЭто помещает раздел на стек перемещения.
*<tt>KvGoBack</tt> - Pops the traversal stack (moves up one level).
+
*<tt>KvGoBack</tt> - Берет из стека перемещения (поднимается на уровень выше).
*<tt>KvRewind</tt> - Clears the traversal stack so the current position is the root node.
+
*<tt>KvRewind</tt> - Стирает из стека перемещения текущую позицию в главном узле.
  
==Basic Lookup==
+
==Основной Просмотр==
Let's take our <tt>MyFile</tt> example from aboveHow could we retrieve the name "crab" given the Steam ID?
+
Давайте возьмем наш пример <tt>MyFile</tt>.  Как мы можем получить имя "crab" учитывая Steam ID?
  
 
<pawn>bool:GetNameFromSteamID(const String:steamid[], String:name[], maxlength)
 
<pawn>bool:GetNameFromSteamID(const String:steamid[], String:name[], maxlength)
Line 60: Line 60:
 
}</pawn>
 
}</pawn>
  
'''Note:''' <tt>KvJumpToKey</tt> is a traversal native that changes the nesting level of the traversal stackHowever, <tt>CloseHandle</tt> will not accidentally close only the current level of the KeyValues structureIt will close the entire thing.
+
'''Обратите внимание:''' <tt>KvJumpToKey</tt> является нативным перемещением, что изменения уровней вложенности стека перемещенияОднако <tt>CloseHandle</tt> не будет случайно закрывать текущий уровень структуры KeyValues.  Это закроет всю вещь.
  
==Iterative Lookup==
+
==Повторяющийся Просмотр==
Let's modify our previous example to use iterationThis has the same functionality, but demonstrates how to browse over many sections.
+
Давайте модифицируер предыдущий пример для использования повторовЭто имеет ту же функциональность, но демонстрирует, как для просмотра в течение многих разделах.
  
 
<pawn>bool:GetNameFromSteamID(const String:steamid[], String:name[], maxlength)
 
<pawn>bool:GetNameFromSteamID(const String:steamid[], String:name[], maxlength)
Line 91: Line 91:
 
}</pawn>
 
}</pawn>
  
'''Note:''' In this example, note that <tt>KvGotoNextKey</tt> is an iterative function, not a traversal oneSince it does not change the nesting level, we don't need to call <tt>KvGoBack</tt> to return and continue iterating.
+
'''Обратите внимание:''' В этом примере отметим что <tt>KvGotoNextKey</tt> является итеративной функции, не однократное перемещениеТак как это не меняет уровень вложенности, мы не должны вызывать <tt>KvGoBack</tt> для возврата и продолжения итерации.
  
==Full Traversal==
+
==Полное Перемещение==
Let's say we wanted to browse every section of a KeyValues fileAn example of this might look like:
+
Например мы хотим просмотреть каждую секцию файла KeyValues.  Пример как это может выглядеть:
 
<pawn>BrowseKeyValues(Handle:kv)
 
<pawn>BrowseKeyValues(Handle:kv)
 
{
 
{
Line 107: Line 107:
 
}</pawn>
 
}</pawn>
  
This function will browse an entire KeyValues structureNote that every successful call to <tt>KvGotoFirstSubKey</tt> is paired with a call to <tt>KvGoBack</tt>.  This is because the former pushes onto the traversal stackWe must pop the position off so we can continue browsing from our old position.
+
Эта функция будет просматривать всю структуру KeyValues.  Обратите внимаеие, что каждый успешный вызов <tt>KvGotoFirstSubKey</tt> сопровождается вызовом <tt>KvGoBack</tt>.  Это потому, что первый помещается в стек перемещенияМы должны взять позицию для того, чтоб могли продолжить просмотр с нашей старой позиции.
  
=Deletion=
+
=Удаление=
There are two ways to delete sections from a KeyValues structure:
+
Есть два пути для удаления секции из структуры KeyValues:
*<tt>KvDeleteKey</tt> - Safely removes a named sub-section and any of its child sections/keys.
+
*<tt>KvDeleteKey</tt> - Безопасное удаление имени подраздела и все дочерние секции/ключи.
*<tt>KvDeleteThis</tt> - Safely removes the current position if possible.
+
*<tt>KvDeleteThis</tt> - Безопасное удаление текущей позиции, если это возможно.
  
==Simple Deletion==
+
==Простое Удаление==
First, let's use our "basic lookup" example to delete a Steam ID section:
+
Для начала используем наш пример "базовый просмотр" для удаления секции Steam ID:
 
<pawn>RemoveSteamID(const String:steamid[])
 
<pawn>RemoveSteamID(const String:steamid[])
 
{
 
{
Line 130: Line 130:
 
}</pawn>
 
}</pawn>
  
'''Note:''' We called <tt>KvRewind</tt> so the file would be dumped from the root position, instead of the current one.   
+
'''Обратите внимание:''' Мы вызвали <tt>KvRewind</tt> так файл будет сбрасываться с корневой позиции, вместо текущей.   
  
==Iterative Deletion==
+
==Повторяющееся Удаление==
Likewise, let's show how our earlier iterative example could be adapted for deleting a sectionFor this we can use <tt>KvDeleteThis</tt>, which deletes the current position from the previous position in the traversal stack.
+
Кроме того давайте покажем как ранее повторяющийся пример может быть адаптирован для удаления разделаДля этого мы используем <tt>KvDeleteThis</tt>, который удаляет текущую позицию из предыдущей позиции в стеке перемещения.
  
 
<pawn>RemoveSteamID(const String:steamid[])
 
<pawn>RemoveSteamID(const String:steamid[])
Line 160: Line 160:
 
}</pawn>
 
}</pawn>
  
==Full Deletion==
+
==Полное Удаление==
Lastly, let's take a look at how we would delete all (or some) keys.  <tt>KvDeleteThis</tt> has the special property that it can act as an automatic iteratorWhen it deletes a key, it automatically attempts to advance to the next one, as <tt>KvGotoNextKey</tt> wouldIf it can't find any more keys, it simply pops the traversal stack.   
+
Наконец давайте посмотрим как удалить все (или некоторые) ключи.  <tt>KvDeleteThis</tt> как особое свойство которое может действовать в качестве автоматического итератораКогда удаляется ключ автоматически переходим к следующему, как если бы вызвали <tt>KvGotoNextKey</tt>.  Если больше нет ключей просто берет стек перемещения.   
  
An example of deleting all SteamIDs that have blank names:
+
Пример удаление всех SteamID-ов содержащие пустые имена:
 
<pawn>DeleteAll(Handle:kv)
 
<pawn>DeleteAll(Handle:kv)
 
{
 
{
Line 187: Line 187:
 
}</pawn>
 
}</pawn>
  
While at first this loop looks infinite, it is notIf <tt>KvDeleteThis</tt> fails to find a subsequent key, it will break out of the loopSimilarly, if <tt>KvGotoNextKey</tt> fails, the loop will end.
+
Хотя это и выглядет как бесконечный цикл, это не такКак только <tt>KvDeleteThis</tt> вернет неудачу при нахождении ключа, произойдет разрыв цеклаАналогично, если <tt>KvGotoNextKey</tt> вернет неудачу, цикл закончится.
  
[[Category:SourceMod Scripting]]
+
[[Category:Ru:SourceMod Scripting]]
[[Category:Russian]]
 

Latest revision as of 00:23, 25 December 2010

KeyValues это простая древовидная структура используемая для хранения вложенных разделов состоящих из пар ключ/значение. Детальная информация про KeyValues может быть найдена на Valve Developer Wiki.

Все KeyValues функции в этом документе находятся в public/include/keyvalues.inc.

Введение

KeyValues состоит из узлов и разделов, которые содержат пары ключей и значений. Разделы выглядят примерно так:

"раздел"
{
	"ключ"	"значение"
}

Сторка "раздел" является именем раздела. Строка "ключ" это имя ключа и строка "значение"" является значением.

KeyValues структуры создаются с помощью CreateKeyValues(). Handle должен быть освобожден после завершения работы для устранения утечки памяти.

Файлы

KeyValues могут быть экспортированы и импортированы с помощью KeyValues файлов. Эти файлы всегда состоят из главного узла и множества под-ключей или подразделов. Например файл может выглядеть вот так:

"MyFile"
{
	"STEAM_0:0:7"
	{
		"name"		"crab"
	}
}

В этом примере STEAM_0:0:7 это раздел под главным узлом MyFile.

Для загрузки KeyValues из файла используйте FileToKeyValues. Для сохранения KeyValues в файл используйте KeyValuesFromFile. Для обоих случае вы всегда должны иметь Handle ссылающийся на KeyValues структуру.

Перемещение

SourceMod обеспечивает нативное перемещение по KeyValues структуре. Однако очень важно понимать как происходит это перемещение. Внутренне, SourceMod отслеживает из двух частей информации:

  • Главный узел
  • Стек перемещения

Поскольку структура KeyValues изначально рекурсивная (это дерево), стек перемещения используется для сохранения истории каждого перемещения (перемещение начинается рекурсивно погружаться в дерево, где текущий уровень вложенности углубляется на одну секцию). верх этого стека где все операции имеют место..

Например, KvJumpToKey будет пытаться найтим под-ключ под текущим разделом. При успехе позиция в дереве изменяется перемещением вниз на один уровень, и, следовательно, эта позиция помещается в стек перемещения. Теперь операции такие как KvGetString будут использовать эту новую позицию.

Это нативные изменяют положение, но не меняют стек перемещения. Например, KvGotoNextKey будет менять текущий раздел перед просмотром, но это не является push/pop операциями для стека перемещения. Это потому, что уровень вложенности не изменился; он проходит в следующий раздел на том же уровне, скорее чем найти секцию уровнем глубже.

Больше нативных перемещений:

  • KvGotoFirstSubKey - Находит первый подраздел ниже текущей позиции. Это помещает раздел на стек перемещения.
  • KvGoBack - Берет из стека перемещения (поднимается на уровень выше).
  • KvRewind - Стирает из стека перемещения текущую позицию в главном узле.

Основной Просмотр

Давайте возьмем наш пример MyFile. Как мы можем получить имя "crab" учитывая Steam ID?

bool:GetNameFromSteamID(const String:steamid[], String:name[], maxlength)
{
	new Handle:kv = CreateKeyValues("MyFile");
	FileToKeyValues(kv, "myfile.txt");
	if (!KvJumpToKey(kv, steamid))
	{
		return false;
	}
	KvGetString(kv, "name", name, maxlength);
	CloseHandle(kv);
	return true;
}

Обратите внимание: KvJumpToKey является нативным перемещением, что изменения уровней вложенности стека перемещения. Однако CloseHandle не будет случайно закрывать текущий уровень структуры KeyValues. Это закроет всю вещь.

Повторяющийся Просмотр

Давайте модифицируер предыдущий пример для использования повторов. Это имеет ту же функциональность, но демонстрирует, как для просмотра в течение многих разделах.

bool:GetNameFromSteamID(const String:steamid[], String:name[], maxlength)
{
	new Handle:kv = CreateKeyValues("MyFile");
	FileToKeyValues(kv, "myfile.txt");
 
	if (!KvGotoFirstSubKey(kv))
	{
		return false;
	}
 
	decl String:buffer[255];
	do
	{
		KvGetSectionName(kv, buffer, sizeof(buffer));
		if (StrEqual(buffer, steamid))
		{
			KvGetString(kv, "name", name, maxlength);
			CloseHandle(kv);
			return true;
		}
	} while (KvGotoNextKey(kv));
 
	CloseHandle(kv)
	return false
}

Обратите внимание: В этом примере отметим что KvGotoNextKey является итеративной функции, не однократное перемещение. Так как это не меняет уровень вложенности, мы не должны вызывать KvGoBack для возврата и продолжения итерации.

Полное Перемещение

Например мы хотим просмотреть каждую секцию файла KeyValues. Пример как это может выглядеть:

BrowseKeyValues(Handle:kv)
{
	do
	{
		if (KvGotoFirstSubKey(kv))
		{
			BrowseKeyValues(kv);
			KvGoBack(kv);
		}
	} while (KvGotoNextKey(kv));
}

Эта функция будет просматривать всю структуру KeyValues. Обратите внимаеие, что каждый успешный вызов KvGotoFirstSubKey сопровождается вызовом KvGoBack. Это потому, что первый помещается в стек перемещения. Мы должны взять позицию для того, чтоб могли продолжить просмотр с нашей старой позиции.

Удаление

Есть два пути для удаления секции из структуры KeyValues:

  • KvDeleteKey - Безопасное удаление имени подраздела и все дочерние секции/ключи.
  • KvDeleteThis - Безопасное удаление текущей позиции, если это возможно.

Простое Удаление

Для начала используем наш пример "базовый просмотр" для удаления секции Steam ID:

RemoveSteamID(const String:steamid[])
{
	new Handle:kv = CreateKeyValues("MyFile")
	FileToKeyValues(kv, "myfile.txt")
	if (!KvGotoFirstSubKey(kv))
	{
		return
	}
	KvDeleteKey(kv, steamid)
	KvRewind(kv)
	KeyValuesToFile(kv, "myfile.txt")
	CloseHandle(kv)
}

Обратите внимание: Мы вызвали KvRewind так файл будет сбрасываться с корневой позиции, вместо текущей.

Повторяющееся Удаление

Кроме того давайте покажем как ранее повторяющийся пример может быть адаптирован для удаления раздела. Для этого мы используем KvDeleteThis, который удаляет текущую позицию из предыдущей позиции в стеке перемещения.

RemoveSteamID(const String:steamid[])
{
	new Handle:kv = CreateKeyValues("MyFile")
	FileToKeyValues(kv, "myfile.txt")
 
	if (!KvGotoFirstSubKey(kv))
	{
		return
	}
 
	decl String:buffer[255]
	do
	{
		KvGetSectionName(kv, buffer, sizeof(buffer))
		if (StrEqual(buffer, steamid))
		{
			KvDeleteThis(kv)
			CloseHandle(kv)
			return
		}
	} while (KvGotoNextKey(kv))
 
	CloseHandle(kv)
}

Полное Удаление

Наконец давайте посмотрим как удалить все (или некоторые) ключи. KvDeleteThis как особое свойство которое может действовать в качестве автоматического итератора. Когда удаляется ключ автоматически переходим к следующему, как если бы вызвали KvGotoNextKey. Если больше нет ключей просто берет стек перемещения.

Пример удаление всех SteamID-ов содержащие пустые имена:

DeleteAll(Handle:kv)
{
	if (!KvGotoFirstSubKey(kv))
	{
		return
	}
 
	for (;;)
	{
		decl String:name[4]
		KvGetString(kv, name, sizeof(name))
		if (name[0] == '\0')
		{
			if (KvDeleteThis(kv) < 1)
			{
				break
			}
		} else if (!KvGotoNextKey(kv)) {
			break
		}	
	}
}

Хотя это и выглядет как бесконечный цикл, это не так. Как только KvDeleteThis вернет неудачу при нахождении ключа, произойдет разрыв цекла. Аналогично, если KvGotoNextKey вернет неудачу, цикл закончится.