diff options
Diffstat (limited to 'engines/wintermute/base/scriptables/script_ext_string.cpp')
| -rw-r--r-- | engines/wintermute/base/scriptables/script_ext_string.cpp | 436 | 
1 files changed, 436 insertions, 0 deletions
diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp new file mode 100644 index 0000000000..9bcfe28bbf --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_string.cpp @@ -0,0 +1,436 @@ +/* ScummVM - Graphic Adventure Engine
 + *
 + * ScummVM is the legal property of its developers, whose names
 + * are too numerous to list here. Please refer to the COPYRIGHT
 + * file distributed with this source distribution.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 +
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 +
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + */
 +
 +/*
 + * This file is based on WME Lite.
 + * http://dead-code.org/redir.php?target=wmelite
 + * Copyright (c) 2011 Jan Nedoma
 + */
 +
 +#include "engines/wintermute/base/base_game.h"
 +#include "engines/wintermute/base/scriptables/script_stack.h"
 +#include "engines/wintermute/base/scriptables/script_value.h"
 +#include "engines/wintermute/utils/utils.h"
 +#include "engines/wintermute/base/scriptables/script_ext_string.h"
 +#include "engines/wintermute/base/scriptables/script_ext_array.h"
 +#include "engines/wintermute/utils/string_util.h"
 +#include "common/tokenizer.h"
 +
 +namespace Wintermute {
 +
 +IMPLEMENT_PERSISTENT(SXString, false)
 +
 +BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack) {
 +	return new SXString(inGame, stack);
 +}
 +
 +//////////////////////////////////////////////////////////////////////////
 +SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
 +	_string = NULL;
 +	_capacity = 0;
 +
 +	stack->correctParams(1);
 +	ScValue *val = stack->pop();
 +
 +	if (val->isInt()) {
 +		_capacity = MAX(0, val->getInt());
 +		if (_capacity > 0) {
 +			_string = new char[_capacity];
 +			memset(_string, 0, _capacity);
 +		}
 +	} else {
 +		setStringVal(val->getString());
 +	}
 +
 +	if (_capacity == 0) {
 +		setStringVal("");
 +	}
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +SXString::~SXString() {
 +	if (_string) {
 +		delete[] _string;
 +	}
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +void SXString::setStringVal(const char *val) {
 +	int len = strlen(val);
 +	if (len >= _capacity) {
 +		_capacity = len + 1;
 +		delete[] _string;
 +		_string = NULL;
 +		_string = new char[_capacity];
 +		memset(_string, 0, _capacity);
 +	}
 +	strcpy(_string, val);
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +const char *SXString::scToString() {
 +	if (_string) {
 +		return _string;
 +	} else {
 +		return "[null string]";
 +	}
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +void SXString::scSetString(const char *val) {
 +	setStringVal(val);
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
 +	//////////////////////////////////////////////////////////////////////////
 +	// Substring
 +	//////////////////////////////////////////////////////////////////////////
 +	if (strcmp(name, "Substring") == 0) {
 +		stack->correctParams(2);
 +		int start = stack->pop()->getInt();
 +		int end   = stack->pop()->getInt();
 +
 +		if (end < start) {
 +			BaseUtils::swap(&start, &end);
 +		}
 +
 +		//try {
 +		WideString str;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			str = StringUtil::utf8ToWide(_string);
 +		} else {
 +			str = StringUtil::ansiToWide(_string);
 +		}
 +
 +		//WideString subStr = str.substr(start, end - start + 1);
 +		WideString subStr(str.c_str() + start, end - start + 1);
 +
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
 +		} else {
 +			stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
 +		}
 +		//  } catch (std::exception &) {
 +		//      stack->pushNULL();
 +		//  }
 +
 +		return STATUS_OK;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////
 +	// Substr
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "Substr") == 0) {
 +		stack->correctParams(2);
 +		int start = stack->pop()->getInt();
 +
 +		ScValue *val = stack->pop();
 +		int len = val->getInt();
 +
 +		if (!val->isNULL() && len <= 0) {
 +			stack->pushString("");
 +			return STATUS_OK;
 +		}
 +
 +		if (val->isNULL()) {
 +			len = strlen(_string) - start;
 +		}
 +
 +//		try {
 +		WideString str;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			str = StringUtil::utf8ToWide(_string);
 +		} else {
 +			str = StringUtil::ansiToWide(_string);
 +		}
 +
 +//			WideString subStr = str.substr(start, len);
 +		WideString subStr(str.c_str() + start, len);
 +
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
 +		} else {
 +			stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
 +		}
 +//		} catch (std::exception &) {
 +//			stack->pushNULL();
 +//		}
 +
 +		return STATUS_OK;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////
 +	// ToUpperCase
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "ToUpperCase") == 0) {
 +		stack->correctParams(0);
 +
 +		WideString str;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			str = StringUtil::utf8ToWide(_string);
 +		} else {
 +			str = StringUtil::ansiToWide(_string);
 +		}
 +
 +		str.toUppercase();
 +
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			stack->pushString(StringUtil::wideToUtf8(str).c_str());
 +		} else {
 +			stack->pushString(StringUtil::wideToAnsi(str).c_str());
 +		}
 +
 +		return STATUS_OK;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////
 +	// ToLowerCase
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "ToLowerCase") == 0) {
 +		stack->correctParams(0);
 +
 +		WideString str;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			str = StringUtil::utf8ToWide(_string);
 +		} else {
 +			str = StringUtil::ansiToWide(_string);
 +		}
 +
 +		str.toLowercase();
 +
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			stack->pushString(StringUtil::wideToUtf8(str).c_str());
 +		} else {
 +			stack->pushString(StringUtil::wideToAnsi(str).c_str());
 +		}
 +
 +		return STATUS_OK;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////
 +	// IndexOf
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "IndexOf") == 0) {
 +		stack->correctParams(2);
 +
 +		const char *strToFind = stack->pop()->getString();
 +		int index = stack->pop()->getInt();
 +
 +		WideString str;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			str = StringUtil::utf8ToWide(_string);
 +		} else {
 +			str = StringUtil::ansiToWide(_string);
 +		}
 +
 +		WideString toFind;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			toFind = StringUtil::utf8ToWide(strToFind);
 +		} else {
 +			toFind = StringUtil::ansiToWide(strToFind);
 +		}
 +
 +		int indexOf = StringUtil::indexOf(str, toFind, index);
 +		stack->pushInt(indexOf);
 +
 +		return STATUS_OK;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////
 +	// Split
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "Split") == 0) {
 +		stack->correctParams(1);
 +		ScValue *val = stack->pop();
 +		char separators[MAX_PATH_LENGTH] = ",";
 +		if (!val->isNULL()) {
 +			strcpy(separators, val->getString());
 +		}
 +
 +		SXArray *array = new SXArray(_gameRef);
 +		if (!array) {
 +			stack->pushNULL();
 +			return STATUS_OK;
 +		}
 +
 +
 +		WideString str;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			str = StringUtil::utf8ToWide(_string);
 +		} else {
 +			str = StringUtil::ansiToWide(_string);
 +		}
 +
 +		WideString delims;
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			delims = StringUtil::utf8ToWide(separators);
 +		} else {
 +			delims = StringUtil::ansiToWide(separators);
 +		}
 +
 +		Common::Array<WideString> parts;
 +
 +
 +
 +		Common::StringTokenizer tokenizer(str, delims);
 +		while (!tokenizer.empty()) {
 +			Common::String str2 = tokenizer.nextToken();
 +			parts.push_back(str2);
 +		}
 +		// TODO: Clean this up
 +		/*do {
 +		    pos = StringUtil::IndexOf(Common::String(str.c_str() + start), delims, start);
 +		    //pos = str.find_first_of(delims, start);
 +		    if (pos == start) {
 +		        start = pos + 1;
 +		    } else if (pos == str.size()) {
 +		        parts.push_back(Common::String(str.c_str() + start));
 +		        break;
 +		    } else {
 +		        parts.push_back(Common::String(str.c_str() + start, pos - start));
 +		        start = pos + 1;
 +		    }
 +		    //start = str.find_first_not_of(delims, start);
 +		    start = StringUtil::LastIndexOf(Common::String(str.c_str() + start), delims, start) + 1;
 +
 +		} while (pos != str.size());*/
 +
 +		for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) {
 +			WideString &part = (*it);
 +
 +			if (_gameRef->_textEncoding == TEXT_UTF8) {
 +				val = new ScValue(_gameRef,  StringUtil::wideToUtf8(part).c_str());
 +			} else {
 +				val = new ScValue(_gameRef,  StringUtil::wideToAnsi(part).c_str());
 +			}
 +
 +			array->push(val);
 +			delete val;
 +			val = NULL;
 +		}
 +
 +		stack->pushNative(array, false);
 +		return STATUS_OK;
 +	} else {
 +		return STATUS_FAILED;
 +	}
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +ScValue *SXString::scGetProperty(const char *name) {
 +	_scValue->setNULL();
 +
 +	//////////////////////////////////////////////////////////////////////////
 +	// Type (RO)
 +	//////////////////////////////////////////////////////////////////////////
 +	if (strcmp(name, "Type") == 0) {
 +		_scValue->setString("string");
 +		return _scValue;
 +	}
 +	//////////////////////////////////////////////////////////////////////////
 +	// Length (RO)
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "Length") == 0) {
 +		if (_gameRef->_textEncoding == TEXT_UTF8) {
 +			WideString wstr = StringUtil::utf8ToWide(_string);
 +			_scValue->setInt(wstr.size());
 +		} else {
 +			_scValue->setInt(strlen(_string));
 +		}
 +
 +		return _scValue;
 +	}
 +	//////////////////////////////////////////////////////////////////////////
 +	// Capacity
 +	//////////////////////////////////////////////////////////////////////////
 +	else if (strcmp(name, "Capacity") == 0) {
 +		_scValue->setInt(_capacity);
 +		return _scValue;
 +	} else {
 +		return _scValue;
 +	}
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +bool SXString::scSetProperty(const char *name, ScValue *value) {
 +	//////////////////////////////////////////////////////////////////////////
 +	// Capacity
 +	//////////////////////////////////////////////////////////////////////////
 +	if (strcmp(name, "Capacity") == 0) {
 +		int32 newCap = (uint32)value->getInt();
 +		if (newCap < (int32)(strlen(_string) + 1)) {
 +			_gameRef->LOG(0, "Warning: cannot lower string capacity");
 +		} else if (newCap != _capacity) {
 +			char *newStr = new char[newCap];
 +			if (newStr) {
 +				memset(newStr, 0, newCap);
 +				strcpy(newStr, _string);
 +				delete[] _string;
 +				_string = newStr;
 +				_capacity = newCap;
 +			}
 +		}
 +		return STATUS_OK;
 +	} else {
 +		return STATUS_FAILED;
 +	}
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +bool SXString::persist(BasePersistenceManager *persistMgr) {
 +
 +	BaseScriptable::persist(persistMgr);
 +
 +	persistMgr->transfer(TMEMBER(_capacity));
 +
 +	if (persistMgr->getIsSaving()) {
 +		if (_capacity > 0) {
 +			persistMgr->putBytes((byte *)_string, _capacity);
 +		}
 +	} else {
 +		if (_capacity > 0) {
 +			_string = new char[_capacity];
 +			persistMgr->getBytes((byte *)_string, _capacity);
 +		} else {
 +			_string = NULL;
 +		}
 +	}
 +
 +	return STATUS_OK;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////////
 +int SXString::scCompare(BaseScriptable *val) {
 +	return strcmp(_string, ((SXString *)val)->_string);
 +}
 +
 +} // end of namespace Wintermute
  | 
