示例#1
0
 template<class Position> BOOST_DISPATCH_FORCE_INLINE
 reference operator()(Position const& pos)
 {
   return block_(pos);
 }
示例#2
0
/**
	Writes a Lua object to a text file.
**/
static void
WriteObject(Script& script, FILE* file, const char* name,
						Script::Object value, unsigned int indentLevel)
{
	// If there is nothing in the variable, then don't write it.
	if (value.IsNil())
		return;

	// If the variable is user data or a function, then don't write it.
	if (value.IsUserData()	||	value.IsFunction())
	{
		return;
	}

	// Indent the line the number of spaces for the current indentation level.
	const unsigned int INDENT_SIZE = 4;
	const unsigned int indentSpaces = indentLevel * INDENT_SIZE;
	IndentFile(file, indentSpaces);
	
	// If the object has a name, write it out.
	if (name)
		fprintf(file, "%s = ", name);

	// If the object's value is a number, write it as a number.
	if (value.IsNumber())
		fprintf(file, "%.16g", value.GetNumber());

	// Or if the object's value is a string, write it as a quoted string.
	else if (value.IsString())
		fprintf(file, "\"%s\"", value.GetString());

	// Otherwise, see if the object's value is a table.
	else if (value.IsTable())
	{
		// Write the table header.
		fputs("\n", file);
		IndentFile(file, indentSpaces);
		fputs("{\n", file);

		// Rename, just for ease of reading.
		Script::Object table = value;

		// upperIndex is the upper index value of a sequential numerical array
		// items.
		int upperIndex = 1;
		bool wroteSemi = false;
		bool hasSequential = false;

		// Block to search for array items.
		{
			// Pop the stack state when done.
			Script::AutoBlock block (script);

			// Grab index 1 and index 2 of the table.
			Script::Object value1 = table.GetByIndex(1);
			Script::Object value2 = table.GetByIndex(2);

			// If they both exist, then there is a sequential list.
			if (!value1.IsNil()	&&	!value2.IsNil())
			{
				// Cycle through the list.
				bool firstSequential = true;
				for (; ; ++upperIndex)
				{
					// Restore the stack state each iteration.
					Script::AutoBlock block_ (script);

					// Try retrieving the table entry at upperIndex.
					Script::Object value = table.GetByIndex(upperIndex);

					// If it doesn't exist, then exit the loop.
					if (value.IsNil())
						break;

					// Only add the comma and return if not on the first item.
					if (!firstSequential)
						fputs(",\n", file);
					
					// Write the object as an unnamed entry.
					WriteObject(script, file, NULL, value, indentLevel + 1);

					// We've definitely passed the first item now.
					firstSequential = false;
				}
			}
		}

		// Did we find any sequential table values?
		if (upperIndex > 1)
		{
			hasSequential = true;
		}
		
		// Cycle through the table.
		int i;
		script.PushNil();
		while ((i = script.Next(table.GetStackIndex())) != 0)
		{
			char keyName[255];

			// Retrieve the table entry's key and value.
			Script::Object key = script.GetObject(script.GetTop() - 1);
			Script::Object value = script.GetObject(script.GetTop());

			// Is the key a number?
			if (key.IsNumber())
			{
				// Yes, were there sequential array items in this table?
				if (hasSequential)
				{
					// Is the array item's key an integer?
					float realNum = key.GetNumber();
					int intNum = (int)realNum;
					if (realNum == (float)intNum)
					{
						// Yes.	Is it between 1 and upperIndex?
						if (intNum >= 1	&&	intNum < upperIndex)
						{
							// We already wrote it as part of the sequential
							// list.
							script.Pop();
							continue;
						}
					}
				}

				// Build the table entry name for the number.
				sprintf(keyName, "[%.16g]", key.GetNumber());
			}
			else
			{
				// Build the table entry name for the string key name.
				strcpy(keyName, key.GetString());
			}

			// If we wrote a sequential list, the value we're about to write
			// is not nil, and we haven't written the semicolon to separate
			// the sequential table entries from the keyed table entries...
			if (hasSequential	&&	!value.IsNil()	&&	!wroteSemi)
			{
				// Then add a comma (for good measure) and the semicolon.
				fputs(", ;\n", file);
				wroteSemi = true;
			}

			// Write the table entry.
			WriteObject(script, file, keyName, value, indentLevel + 1);

			// Add a comma after the table entry.
			fputs(",\n", file);

			// Go to the next item.
			script.Pop();
		}

		// If we wrote a sequential list and haven't written a semicolon, then
		// there were no keyed table entries.	Just write the final comma.
		if (hasSequential	&&	!wroteSemi)
		{
			fputs(",\n", file);
		}
		
		// Indent, with the intent of closing up the table.
		IndentFile(file, indentSpaces);

		// If the indentation level is 0, then we're at the root position.
		if (indentLevel == 0)
		{
			// Add a couple extra returns for readability's sake.
			fputs("}\n\n", file);
		}
		else
		{
			// Close the table.	The comma is written when WriteObject()
			// returns from the recursive call.
			fputs("}", file);
		}
	}

	// If the indentation level is at the root, then add a return to separate
	// the lines.
	if (indentLevel == 0)
	{
		fputs("\n", file);
	}
}