Changeset - r18710:759428ffd8c8
[Not reviewed]
master
0 2 0
rubidium - 12 years ago 2011-12-17 13:33:36
rubidium@openttd.org
(svn r23568) -Codechange: only allocate the buffer for writing when it is really needed
2 files changed with 83 insertions and 75 deletions:
0 comments (0 inline, 0 general)
src/strgen/strgen.cpp
Show inline comments
 
@@ -71,9 +71,6 @@ static LanguagePackHeader _lang; ///< He
 
#define HASH_SIZE 32767
 
static uint16 _hash_head[HASH_SIZE];
 

	
 
/** The buffer for writing a single string. */
 
typedef SmallVector<byte, 256> Buffer;
 
Buffer _put_buf;
 
static int _next_string_id;
 

	
 
static uint32 _hash;
 
@@ -168,33 +165,42 @@ void NORETURN CDECL error(const char *s,
 
	throw std::exception();
 
}
 

	
 
static void PutByte(byte c)
 
{
 
	*_put_buf.Append() = c;
 
}
 

	
 
/** The buffer for writing a single string. */
 
struct Buffer : SmallVector<byte, 256> {
 
	/**
 
	 * Conveniance method for adding a byte.
 
	 * @param value The value to add.
 
	 */
 
	void AppendByte(byte value)
 
	{
 
		*this->Append() = value;
 
	}
 

	
 
static void PutUtf8(uint32 value)
 
{
 
	if (value < 0x80) {
 
		PutByte(value);
 
	} else if (value < 0x800) {
 
		PutByte(0xC0 + GB(value,  6, 5));
 
		PutByte(0x80 + GB(value,  0, 6));
 
	} else if (value < 0x10000) {
 
		PutByte(0xE0 + GB(value, 12, 4));
 
		PutByte(0x80 + GB(value,  6, 6));
 
		PutByte(0x80 + GB(value,  0, 6));
 
	} else if (value < 0x110000) {
 
		PutByte(0xF0 + GB(value, 18, 3));
 
		PutByte(0x80 + GB(value, 12, 6));
 
		PutByte(0x80 + GB(value,  6, 6));
 
		PutByte(0x80 + GB(value,  0, 6));
 
	} else {
 
		strgen_warning("Invalid unicode value U+0x%X", value);
 
	/**
 
	 * Add an Unicode character encoded in UTF-8 to the buffer.
 
	 * @param value The character to add.
 
	 */
 
	void AppendUtf8(uint32 value)
 
	{
 
		if (value < 0x80) {
 
			*this->Append() = value;
 
		} else if (value < 0x800) {
 
			*this->Append() = 0xC0 + GB(value,  6, 5);
 
			*this->Append() = 0x80 + GB(value,  0, 6);
 
		} else if (value < 0x10000) {
 
			*this->Append() = 0xE0 + GB(value, 12, 4);
 
			*this->Append() = 0x80 + GB(value,  6, 6);
 
			*this->Append() = 0x80 + GB(value,  0, 6);
 
		} else if (value < 0x110000) {
 
			*this->Append() = 0xF0 + GB(value, 18, 3);
 
			*this->Append() = 0x80 + GB(value, 12, 6);
 
			*this->Append() = 0x80 + GB(value,  6, 6);
 
			*this->Append() = 0x80 + GB(value,  0, 6);
 
		} else {
 
			strgen_warning("Invalid unicode value U+0x%X", value);
 
		}
 
	}
 
}
 

	
 
};
 

	
 
size_t Utf8Validate(const char *s)
 
{
 
@@ -221,10 +227,10 @@ size_t Utf8Validate(const char *s)
 
}
 

	
 

	
 
static void EmitSingleChar(char *buf, int value)
 
static void EmitSingleChar(Buffer *buffer, char *buf, int value)
 
{
 
	if (*buf != '\0') strgen_warning("Ignoring trailing letters in command");
 
	PutUtf8(value);
 
	buffer->AppendUtf8(value);
 
}
 

	
 

	
 
@@ -300,17 +306,17 @@ char *ParseWord(char **buf)
 
/* Forward declaration */
 
static int TranslateArgumentIdx(int arg, int offset = 0);
 

	
 
static void EmitWordList(const char * const *words, uint nw)
 
static void EmitWordList(Buffer *buffer, const char * const *words, uint nw)
 
{
 
	PutByte(nw);
 
	for (uint i = 0; i < nw; i++) PutByte(strlen(words[i]) + 1);
 
	buffer->AppendByte(nw);
 
	for (uint i = 0; i < nw; i++) buffer->AppendByte(strlen(words[i]) + 1);
 
	for (uint i = 0; i < nw; i++) {
 
		for (uint j = 0; words[i][j] != '\0'; j++) PutByte(words[i][j]);
 
		PutByte(0);
 
		for (uint j = 0; words[i][j] != '\0'; j++) buffer->AppendByte(words[i][j]);
 
		buffer->AppendByte(0);
 
	}
 
}
 

	
 
static void EmitPlural(char *buf, int value)
 
static void EmitPlural(Buffer *buffer, char *buf, int value)
 
{
 
	int argidx = _cur_argidx;
 
	int offset = 0;
 
@@ -346,14 +352,14 @@ static void EmitPlural(char *buf, int va
 
		}
 
	}
 

	
 
	PutUtf8(SCC_PLURAL_LIST);
 
	PutByte(_lang.plural_form);
 
	PutByte(TranslateArgumentIdx(argidx, offset));
 
	EmitWordList(words, nw);
 
	buffer->AppendUtf8(SCC_PLURAL_LIST);
 
	buffer->AppendByte(_lang.plural_form);
 
	buffer->AppendByte(TranslateArgumentIdx(argidx, offset));
 
	EmitWordList(buffer, words, nw);
 
}
 

	
 

	
 
static void EmitGender(char *buf, int value)
 
static void EmitGender(Buffer *buffer, char *buf, int value)
 
{
 
	int argidx = _cur_argidx;
 
	int offset = 0;
 
@@ -367,8 +373,8 @@ static void EmitGender(char *buf, int va
 
		if (nw >= MAX_NUM_GENDERS) error("G argument '%s' invalid", buf);
 

	
 
		/* now nw contains the gender index */
 
		PutUtf8(SCC_GENDER_INDEX);
 
		PutByte(nw);
 
		buffer->AppendUtf8(SCC_GENDER_INDEX);
 
		buffer->AppendByte(nw);
 
	} else {
 
		const char *words[MAX_NUM_GENDERS];
 

	
 
@@ -388,9 +394,9 @@ static void EmitGender(char *buf, int va
 
		if (nw != _lang.num_genders) error("Bad # of arguments for gender command");
 

	
 
		assert(IsInsideBS(cmd->value, SCC_CONTROL_START, UINT8_MAX));
 
		PutUtf8(SCC_GENDER_LIST);
 
		PutByte(TranslateArgumentIdx(argidx, offset));
 
		EmitWordList(words, nw);
 
		buffer->AppendUtf8(SCC_GENDER_LIST);
 
		buffer->AppendByte(TranslateArgumentIdx(argidx, offset));
 
		EmitWordList(buffer, words, nw);
 
	}
 
}
 

	
 
@@ -1054,21 +1060,21 @@ static int TranslateArgumentIdx(int argi
 
	return sum + offset;
 
}
 

	
 
static void PutArgidxCommand()
 
static void PutArgidxCommand(Buffer *buffer)
 
{
 
	PutUtf8(SCC_ARG_INDEX);
 
	PutByte(TranslateArgumentIdx(_cur_argidx));
 
	buffer->AppendUtf8(SCC_ARG_INDEX);
 
	buffer->AppendByte(TranslateArgumentIdx(_cur_argidx));
 
}
 

	
 

	
 
static void PutCommandString(const char *str)
 
static void PutCommandString(Buffer *buffer, const char *str)
 
{
 
	_cur_argidx = 0;
 

	
 
	while (*str != '\0') {
 
		/* Process characters as they are until we encounter a { */
 
		if (*str != '{') {
 
			PutByte(*str++);
 
			buffer->AppendByte(*str++);
 
			continue;
 
		}
 

	
 
@@ -1079,8 +1085,8 @@ static void PutCommandString(const char 
 
		if (cs == NULL) break;
 

	
 
		if (casei != -1) {
 
			PutUtf8(SCC_SET_CASE); // {SET_CASE}
 
			PutByte(casei);
 
			buffer->AppendUtf8(SCC_SET_CASE); // {SET_CASE}
 
			buffer->AppendByte(casei);
 
		}
 

	
 
		/* For params that consume values, we need to handle the argindex properly */
 
@@ -1088,7 +1094,7 @@ static void PutCommandString(const char 
 
			/* Check if we need to output a move-param command */
 
			if (argno != -1 && argno != _cur_argidx) {
 
				_cur_argidx = argno;
 
				PutArgidxCommand();
 
				PutArgidxCommand(buffer);
 
			}
 

	
 
			/* Output the one from the master string... it's always accurate. */
 
@@ -1098,7 +1104,7 @@ static void PutCommandString(const char 
 
			}
 
		}
 

	
 
		cs->proc(param, cs->value);
 
		cs->proc(buffer, param, cs->value);
 
	}
 
}
 

	
 
@@ -1169,6 +1175,7 @@ struct LanguageWriter {
 
		_lang.winlangid = TO_LE16(_lang.winlangid);
 

	
 
		this->WriteHeader(&_lang);
 
		Buffer buffer;
 

	
 
		for (int i = 0; i != 32; i++) {
 
			for (uint j = 0; j != in_use[i]; j++) {
 
@@ -1192,7 +1199,7 @@ struct LanguageWriter {
 
					}
 
					if ((_show_todo & 1) != 0) {
 
						const char *s = "<TODO> ";
 
						while (*s != '\0') PutByte(*s++);
 
						while (*s != '\0') buffer.AppendByte(*s++);
 
					}
 
				}
 

	
 
@@ -1217,33 +1224,33 @@ struct LanguageWriter {
 
					 * It has this format
 
					 * <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
 
					 * Each LEN is printed using 2 bytes in big endian order. */
 
					PutUtf8(SCC_SWITCH_CASE);
 
					buffer.AppendUtf8(SCC_SWITCH_CASE);
 
					/* Count the number of cases */
 
					for (num = 0, c = casep; c; c = c->next) num++;
 
					PutByte(num);
 
					buffer.AppendByte(num);
 

	
 
					/* Write each case */
 
					for (c = casep; c != NULL; c = c->next) {
 
						PutByte(c->caseidx);
 
						buffer.AppendByte(c->caseidx);
 
						/* Make some space for the 16-bit length */
 
						size_t pos = _put_buf.Length();
 
						PutByte(0);
 
						PutByte(0);
 
						size_t pos = buffer.Length();
 
						buffer.AppendByte(0);
 
						buffer.AppendByte(0);
 
						/* Write string */
 
						PutCommandString(c->string);
 
						PutByte(0); // terminate with a zero
 
						PutCommandString(&buffer, c->string);
 
						buffer.AppendByte(0); // terminate with a zero
 
						/* Fill in the length */
 
						size_t size = _put_buf.Length() - (pos + 2);
 
						_put_buf[pos + 0] = GB(size, 8, 8);
 
						_put_buf[pos + 1] = GB(size, 0, 8);
 
						size_t size = buffer.Length() - (pos + 2);
 
						buffer[pos + 0] = GB(size, 8, 8);
 
						buffer[pos + 1] = GB(size, 0, 8);
 
					}
 
				}
 

	
 
				if (cmdp != NULL) PutCommandString(cmdp);
 
				if (cmdp != NULL) PutCommandString(&buffer, cmdp);
 

	
 
				this->WriteLength(_put_buf.Length());
 
				this->Write(_put_buf.Begin(), _put_buf.Length());
 
				_put_buf.Clear();
 
				this->WriteLength(buffer.Length());
 
				this->Write(buffer.Begin(), buffer.Length());
 
				buffer.Clear();
 
			}
 
		}
 
	}
src/table/strgen_tables.h
Show inline comments
 
@@ -19,7 +19,8 @@ enum CmdFlags {
 
};
 
DECLARE_ENUM_AS_BIT_SET(CmdFlags)
 

	
 
typedef void (*ParseCmdProc)(char *buf, int value);
 
struct Buffer;
 
typedef void (*ParseCmdProc)(Buffer *buffer, char *buf, int value);
 

	
 
struct CmdStruct {
 
	const char *cmd;
 
@@ -29,9 +30,9 @@ struct CmdStruct {
 
	CmdFlags flags;
 
};
 

	
 
static void EmitSingleChar(char *buf, int value);
 
static void EmitPlural(char *buf, int value);
 
static void EmitGender(char *buf, int value);
 
static void EmitSingleChar(Buffer *buffer, char *buf, int value);
 
static void EmitPlural(Buffer *buffer, char *buf, int value);
 
static void EmitGender(Buffer *buffer, char *buf, int value);
 

	
 
static const CmdStruct _cmd_structs[] = {
 
	/* Font size */
0 comments (0 inline, 0 general)