From 5b38e00ade51d6b5f058b80eb936d73ddff3a730 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Thu, 31 Jan 2013 19:14:14 +0100 Subject: [PATCH] Expose some methods on strings to Nasal --- src/Scripting/CMakeLists.txt | 2 + src/Scripting/NasalString.cxx | 133 ++++++++++++++++++++++++++++++++++ src/Scripting/NasalString.hxx | 27 +++++++ src/Scripting/NasalSys.cxx | 10 ++- src/Scripting/NasalSys.hxx | 3 +- 5 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 src/Scripting/NasalString.cxx create mode 100644 src/Scripting/NasalString.hxx diff --git a/src/Scripting/CMakeLists.txt b/src/Scripting/CMakeLists.txt index 57ef20827..de71090b1 100644 --- a/src/Scripting/CMakeLists.txt +++ b/src/Scripting/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES NasalCanvas.cxx NasalClipboard.cxx NasalCondition.cxx + NasalString.cxx ) set(HEADERS @@ -15,6 +16,7 @@ set(HEADERS NasalCanvas.hxx NasalClipboard.hxx NasalCondition.hxx + NasalString.hxx ) if(WIN32) diff --git a/src/Scripting/NasalString.cxx b/src/Scripting/NasalString.cxx new file mode 100644 index 000000000..df29b862b --- /dev/null +++ b/src/Scripting/NasalString.cxx @@ -0,0 +1,133 @@ +// Add (std::string) like methods to Nasal strings +// +// Copyright (C) 2013 Thomas Geymayer +// +// 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. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "NasalString.hxx" + +#include +#include +#include +#include + +/** + * Compare (sub)string with other string + * + * compare(s) + * compare(pos, len, s) + */ +static naRef f_compare(naContext c, naRef me, int argc, naRef* args) +{ + nasal::CallContext ctx(c, argc, args); + nasal::String str = nasal::from_nasal(c, me), + rhs = ctx.requireArg(argc > 1 ? 2 : 0); + size_t pos = argc > 1 ? ctx.requireArg(1) : 0; + size_t len = argc > 1 ? ctx.requireArg(2) : 0; + + if( len == 0 ) + len = nasal::String::npos; + + return naNum( str.compare(pos, len, rhs) ); +} + +/** + * Check whether string starts with other string + */ +static naRef f_starts_with(naContext c, naRef me, int argc, naRef* args) +{ + nasal::CallContext ctx(c, argc, args); + nasal::String str = nasal::from_nasal(c, me), + rhs = ctx.requireArg(0); + + return naNum( str.starts_with(rhs) ); +} + +/** + * Helper to convert size_t position/npos to Nasal conventions (-1 == npos) + */ +naRef pos_to_nasal(size_t pos) +{ + if( pos == nasal::String::npos ) + return naNum(-1); + else + return naNum(pos); +} + +/** + * Find first occurrence of single character + * + * find(c, pos = 0) + */ +static naRef f_find(naContext c, naRef me, int argc, naRef* args) +{ + nasal::CallContext ctx(c, argc, args); + nasal::String str = nasal::from_nasal(c, me), + find = ctx.requireArg(0); + size_t pos = ctx.getArg(1, 0); + + if( find.size() != 1 ) + naRuntimeError(c, "string::find: single character expected"); + + return pos_to_nasal( str.find(*find.c_str(), pos) ); +} + +/** + * Find first character of a string occurring in this string + * + * find_first_of(search, pos = 0) + */ +static naRef f_find_first_of(naContext c, naRef me, int argc, naRef* args) +{ + nasal::CallContext ctx(c, argc, args); + nasal::String str = nasal::from_nasal(c, me), + find = ctx.requireArg(0); + size_t pos = ctx.getArg(1, 0); + + return pos_to_nasal( str.find_first_of(find, pos) ); +} + +/** + * Find first character of this string not occurring in the other string + * + * find_first_not_of(search, pos = 0) + */ +static naRef f_find_first_not_of(naContext c, naRef me, int argc, naRef* args) +{ + nasal::CallContext ctx(c, argc, args); + nasal::String str = nasal::from_nasal(c, me), + find = ctx.requireArg(0); + size_t pos = ctx.getArg(1, 0); + + return pos_to_nasal( str.find_first_not_of(find, pos) ); +} + +//------------------------------------------------------------------------------ +naRef initNasalString(naRef globals, naRef string, naContext c, naRef gcSave) +{ + nasal::Hash string_module(string, c); + + string_module.set("compare", f_compare); + string_module.set("starts_with", f_starts_with); + string_module.set("find", f_find); + string_module.set("find_first_of", f_find_first_of); + string_module.set("find_first_not_of", f_find_first_not_of); + + return naNil(); +} diff --git a/src/Scripting/NasalString.hxx b/src/Scripting/NasalString.hxx new file mode 100644 index 000000000..80d6474d5 --- /dev/null +++ b/src/Scripting/NasalString.hxx @@ -0,0 +1,27 @@ +// Add (std::string) like methods to Nasal strings +// +// Copyright (C) 2013 Thomas Geymayer +// +// 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. + +#ifndef SCRIPTING_NASAL_STRING_HXX +#define SCRIPTING_NASAL_STRING_HXX + +#include + +naRef initNasalString(naRef globals, naRef string, naContext c, naRef gcSave); + +#endif // of SCRIPTING_NASAL_STRING_HXX + diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index ff94e2ee6..ef6440d3d 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -29,6 +29,7 @@ #include "NasalCanvas.hxx" #include "NasalClipboard.hxx" #include "NasalCondition.hxx" +#include "NasalString.hxx" #include
#include
@@ -100,6 +101,7 @@ FGNasalSys::FGNasalSys() nasalSys = this; _context = 0; _globals = naNil(); + _string = naNil(); _gcHash = naNil(); _nextGCKey = 0; // Any value will do _callCount = 0; @@ -154,6 +156,7 @@ FGNasalSys::~FGNasalSys() naFreeContext(_context); _globals = naNil(); + _string = naNil(); } bool FGNasalSys::parseAndRun(const char* sourceCode) @@ -547,8 +550,6 @@ void FGNasalSys::init() hashset(_globals, funcs[i].name, naNewFunc(_context, naNewCCode(_context, funcs[i].func))); - - // And our SGPropertyNode wrapper hashset(_globals, "props", genPropsModule()); @@ -558,6 +559,11 @@ void FGNasalSys::init() _gcHash = naNewHash(_context); hashset(_globals, "__gcsave", _gcHash); + // Add string methods + _string = naInit_string(_context); + naSave(_context, _string); + initNasalString(_globals, _string, _context, _gcHash); + initNasalPositioned(_globals, _context, _gcHash); NasalClipboard::init(this); initNasalCanvas(_globals, _context, _gcHash); diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index 543484499..83efde6e4 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -186,7 +186,8 @@ private: naRef genPropsModule(); naContext _context; - naRef _globals; + naRef _globals, + _string; SGPropertyNode_ptr _cmdArg; -- 2.39.5