///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004-2007 by The Allacrost Project
// All Rights Reserved
//
// This code is licensed under the GNU GPL version 2. It is free software
// and you may modify it and/or redistribute it under the terms of this license.
// See http://www.gnu.org/copyleft/gpl.html for details.
///////////////////////////////////////////////////////////////////////////////
/** ****************************************************************************
*** \file script_write.h
*** \author Daniel Steuernol - steu@allacrost.org,
*** Tyler Olsen - roots@allacrost.org
*** \brief Header file for the WriteScriptDescriptor class.
*** ***************************************************************************/
#ifndef __SCRIPT_WRITE_HEADER__
#define __SCRIPT_WRITE_HEADER__
#include "utils.h"
#include "defs.h"
#include "script.h"
namespace hoa_script {
/** ****************************************************************************
*** \brief Provides a simplistic interface for writing data to a new Lua file
***
*** This class does not actually involve Lua in any way. Rather, it provides an
*** interface with which to write a Lua file from scratch. One area of the code
*** base which uses this class graciously is the Allacrost editor when it saves
*** new map files. Be cautious when using this class, as it can overwrite
*** existing Lua files. This class is primarily for writing data, not
*** code, although it is indeed possible to write script code using this class.
***
*** \note With the exception of the open/close file functions, all methods of
*** this class assume that the file is open and do not check otherwise. If you
*** try to invoke these functions with an unopened file, you will generate a
*** segmentation fault.
***
*** \note Except where noted in the function's comments, all methods
*** automatically insert a new line into the file after they write their
*** requested contents.
***
*** \todo Implement the WriteUString methods that will automatically insert the
*** gettext call to retrieve the translated value of the string.
***
*** \todo Allow the user to automatically compile the newly written file and
*** possibly also delete the plain text version when this is done.
*** ***************************************************************************/
class WriteScriptDescriptor : public ScriptDescriptor {
friend class GameScript;
public:
~WriteScriptDescriptor();
/** \name File Access Functions
*** \note These are derived from ScriptDescriptor, refer to the comments for these
*** methods in the header file for that class.
**/
//@{
bool OpenFile(const std::string& file_name);
bool OpenFile();
void CloseFile();
//@}
/** \name Comment Write Functions
*** \brief Writes comments into a Lua file
*** \param comment The comment to write to the file.
**/
//@{
//! \brief Inserts a blank line into the text.
void InsertNewLine();
/** \brief Writes a string of text and prepends it with a comment.
*** This is equivalent to the `// comment` in C++.
**/
void WriteComment(const std::string& comment);
//! \brief After this function is invoked, all other data written will be a comment
void BeginCommentBlock();
//! \brief Ends a comment block.
void EndCommentBlock();
/** \brief Writes an unaltered string to the file
*** \param comment The string of text to write to the file
*** \param new_line If true, automatically appends a new line (enabled by default)
*** \note Typically, you should really try to avoid using this function unless you know
*** what you are doing. It is, however, safe to use it between the beginning and end of a
*** comment block (just don't write the syntax that ends the block, which is `--]]`).
**/
void WriteLine(const std::string& comment, bool new_line = true);
//@}
/** \name Variable Write Functions
*** \brief These functions will write a single variable and its value to a Lua file.
*** \param *key The name of the Lua variable to write.
*** \param value The value of the new global variable to write.
*** \note If no write tables are open when these calls are made, the variables become global
*** in the Lua file. Otherwise, they become keys of the most recently opened table.
**/
//@{
void WriteBool(const std::string& key, bool value);
void WriteBool(const int32 key, bool value);
void WriteInt(const std::string& key, int32 value)
{ _WriteData(key, value); }
void WriteInt(const int32 key, int32 value)
{ _WriteData(key, value); }
void WriteUInt(const std::string& key, uint32 value)
{ _WriteData(key, value); }
void WriteUInt(const int32 key, uint32 value)
{ _WriteData(key, value); }
void WriteFloat(const std::string& key, float value)
{ _WriteData(key, value); }
void WriteFloat(const int32 key, float value)
{ _WriteData(key, value); }
void WriteString(const std::string& key, const std::string& value);
void WriteString(const int32 key, const std::string& value);
/** The WriteUString functions actually take standard strings, not ustrings, for their value.
*** What these methods do is write the string to the Lua file with the gettext translation
*** code attached so that when the value is retrieved, the appropriate string translation
*** is returned from gettext instead of the actual base string contained in the file.
**/
void WriteUString(const std::string& key, const std::string& value);
void WriteUString(const int32 key, const std::string& value);
//@}
/** \name Vector Write Functions
*** \brief These functions write a vector of data to a Lua file.
*** \param key The name of the table to use in the Lua file to represent the data.
*** \param &vect A reference to the vector of elements to write.
**/
//@{
void WriteBoolVector(const std::string &key, std::vector &vect);
void WriteBoolVector(const int32 key, std::vector &vect);
void WriteIntVector(const std::string &key, std::vector &vect)
{ _WriteDataVector(key, vect); }
void WriteIntVector(const int32 key, std::vector &vect)
{ _WriteDataVector(key, vect); }
void WriteUIntVector(const std::string &key, std::vector &vect)
{ _WriteDataVector(key, vect); }
void WriteUIntVector(const int32 key, std::vector &vect)
{ _WriteDataVector(key, vect); }
void WriteFloatVector(const std::string &key, std::vector &vect)
{ _WriteDataVector(key, vect); }
void WriteFloatVector(const int32 key, std::vector &vect)
{ _WriteDataVector(key, vect); }
void WriteStringVector(const std::string &key, std::vector &vect);
void WriteStringVector(const int32 key, std::vector &vect);
void WriteUStringVector(const std::string &key, std::vector &vect);
void WriteUStringVector(const int32 key, std::vector &vect);
//@}
/** \brief Write out the namespace header
*** \param the name of the namespace for this lua file.
**/
void WriteNamespace(const std::string &ns);
/** \name Table Write Functions
*** \brief These functions write the beginning and ends of Lua tables
*** \param key The name of the table to write.
*** \note If you begin a new table and then begin another when you haven't ended the first one, the
*** new table will become a key to the first. A table will only become global when there are no other
*** write tables open.
**/
//@{
void BeginTable(const std::string &key);
void BeginTable(int32 key);
void EndTable();
//@}
private:
//! \brief The output file stream to write to for when the file is opened in write mode.
std::ofstream _outfile;
//! \brief Set to true after a comment block begins and false after the comment block ends
bool _inside_comment_block;
/** \name Variable Write Templates
*** \brief These template functions are called by the public WriteTYPE functions of this class.
*** \param key The name or numeric identifier of the Lua variable to write.
*** \param value The value to write for the new variable
*** \note The integer keys are only valid for variables stored in a table, not for global variables.
**/
//@{
template void _WriteData(const std::string& key, T value);
template void _WriteData(const int32 key, T value);
//@}
/** \name Vector Read Templates
*** \brief These template functions are called by the public ReadTYPEVector functions of this class.
*** \param key The name or numeric identifier of the Lua variable to access.
*** \param vect A reference to the vector where the read variables should be store
*** \note Integer keys are only valid for variables stored in a table, not for global variables.
**/
//@{
template void _WriteDataVector(const std::string& key, std::vector &vect);
template void _WriteDataVector(const int32 key, std::vector &vect);
//@}
//! \brief Writes the pathname of all open tables (i.e., table1[table2][table3])
void _WriteTablePath();
}; // class WriteScriptDescriptor : public ScriptDescriptor
//-----------------------------------------------------------------------------
// Template Function Definitions
//-----------------------------------------------------------------------------
template void WriteScriptDescriptor::_WriteData(const std::string &key, T value) {
if (_open_tables.size() == 0) {
_outfile << key << " = " << value << std::endl;
}
else {
_WriteTablePath();
_outfile << '.' << key << " = " << value << std::endl;
}
}
template void WriteScriptDescriptor::_WriteData(const int32 key, T value) {
if (_open_tables.empty()) {
_error_messages << "* WriteScriptDescriptor::_WriteData() failed because there were no "
<< "tables open when attempting to write the key/value: [" << key << "] = " << value << std::endl;
return;
}
_WriteTablePath();
_outfile << '[' << key << ']' << " = " << value << std::endl;
}
template void WriteScriptDescriptor::_WriteDataVector(const std::string& key, std::vector &vect) {
if (vect.empty()) {
_error_messages << "* WriteScriptDescriptor::_WriteDataVector() failed because "
<< "the vector argument was empty for key name: " << key << std::endl;
return;
}
if (_open_tables.size() == 0) {
_outfile << key << " = { ";
}
else {
_WriteTablePath();
if (hoa_utils::IsStringNumeric(key))
_outfile << "[" << key << "] = { ";
else
_outfile << '.' << key << " = { ";
}
_outfile << vect[0];
for (uint32 i = 1; i < vect.size(); i++) {
_outfile << ", " << vect[i];
}
_outfile << " }" << std::endl;
}
template void WriteScriptDescriptor::_WriteDataVector(const int32 key, std::vector& vect) {
if (_open_tables.empty()) {
_error_messages << "* WriteScriptDescriptor::_WriteDataVector() failed because there were no "
<< "tables open when attempting for key name: " << key << std::endl;
return;
}
_WriteTablePath();
_outfile << '[' << key << "] = { ";
_outfile << vect[0];
for (uint32 i = 1; i < vect.size(); i++) {
_outfile << ", " << vect[i];
}
_outfile << " }" << std::endl;
}
} // namespace hoa_script
#endif // __SCRIPT_WRITE_HEADER_