Nasal String wrapper and allow adding methods to string objects.
- Add nasal::String for wrapping Nasal string data and accessing string methods (which eg. could be exposed to Nasal) - Allow adding functions from C/C++ which are callable on Nasal strings.
This commit is contained in:
parent
53b9fd2110
commit
e7f9486aa1
@ -441,14 +441,17 @@ static const char* getMember_r(naContext ctx, naRef obj, naRef field, naRef* out
|
||||
naRef p;
|
||||
struct VecRec* pv;
|
||||
if(--count < 0) return "too many parents";
|
||||
if(!IS_HASH(obj) && !IS_GHOST(obj)) return "non-objects have no members";
|
||||
|
||||
|
||||
if (IS_GHOST(obj)) {
|
||||
if (ghostGetMember(ctx, obj, field, out)) return "";
|
||||
if(!ghostGetMember(ctx, obj, globals->parentsRef, &p)) return 0;
|
||||
} else {
|
||||
} else if (IS_HASH(obj)) {
|
||||
if(naHash_get(obj, field, out)) return "";
|
||||
if(!naHash_get(obj, globals->parentsRef, &p)) return 0;
|
||||
} else if (IS_STR(obj) ) {
|
||||
return getMember_r(ctx, getStringMethods(ctx), field, out, count);
|
||||
} else {
|
||||
return "non-objects have no members";
|
||||
}
|
||||
|
||||
if(!IS_VEC(p)) return "object \"parents\" field not vector";
|
||||
|
@ -3,6 +3,7 @@ include (SimGearComponent)
|
||||
set(HEADERS
|
||||
Ghost.hxx
|
||||
NasalHash.hxx
|
||||
NasalString.hxx
|
||||
from_nasal_detail.hxx
|
||||
from_nasal.hxx
|
||||
nasal_traits.hxx
|
||||
@ -11,6 +12,7 @@ set(HEADERS
|
||||
|
||||
set(SOURCES
|
||||
NasalHash.cxx
|
||||
NasalString.cxx
|
||||
from_nasal.cxx
|
||||
to_nasal.cxx
|
||||
)
|
||||
|
180
simgear/nasal/cppbind/NasalString.cxx
Normal file
180
simgear/nasal/cppbind/NasalString.cxx
Normal file
@ -0,0 +1,180 @@
|
||||
// Wrapper class for Nasal strings
|
||||
//
|
||||
// Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
#include "NasalString.hxx"
|
||||
#include "to_nasal.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace nasal
|
||||
{
|
||||
|
||||
/**
|
||||
* Predicate (eg. for std::find_if) returning true if no character of the
|
||||
* stored string given by the range [begin, end) matches.
|
||||
*/
|
||||
struct no_match:
|
||||
public std::unary_function<const char, bool>
|
||||
{
|
||||
no_match(const char* begin, const char* end):
|
||||
_begin(begin),
|
||||
_end(end)
|
||||
{}
|
||||
|
||||
bool operator()(const char c) const
|
||||
{
|
||||
return std::find(_begin, _end, c) == _end;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* _begin;
|
||||
const char* _end;
|
||||
};
|
||||
|
||||
//template<typename Iterator>
|
||||
//Iterator
|
||||
//rfind_first_of( Iterator rbegin_src, Iterator rend_src,
|
||||
// Iterator begin_find, Iterator end_find )
|
||||
//{
|
||||
// for(; rbegin_src != rend_src; --rbegin_src)
|
||||
// {
|
||||
// for(Iterator chr = begin_find; chr != end_find; ++chr)
|
||||
// {
|
||||
// if( *rbegin_src == *chr )
|
||||
// return rbegin_src;
|
||||
// }
|
||||
// }
|
||||
// return rend_src;
|
||||
//}
|
||||
|
||||
|
||||
const size_t String::npos = static_cast<size_t>(-1);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
String::String(naContext c, const char* str):
|
||||
_str( to_nasal(c, str) )
|
||||
{
|
||||
assert( naIsString(_str) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
String::String(naRef str):
|
||||
_str(str)
|
||||
{
|
||||
assert( naIsString(_str) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char* String::c_str() const
|
||||
{
|
||||
return naStr_data(_str);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char* String::begin() const
|
||||
{
|
||||
return c_str();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char* String::end() const
|
||||
{
|
||||
return c_str() + size();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
size_t String::size() const
|
||||
{
|
||||
return naStr_len(_str);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
size_t String::length() const
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool String::empty() const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int String::compare(size_t pos, size_t len, const String& rhs) const
|
||||
{
|
||||
if( pos >= size() )
|
||||
throw std::out_of_range("nasal::String::compare: pos");
|
||||
|
||||
return memcmp( begin() + pos,
|
||||
rhs.begin(),
|
||||
std::min(rhs.size(), std::min(size() - pos, len)) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool String::starts_with(const String& rhs) const
|
||||
{
|
||||
return rhs.size() <= size() && compare(0, npos, rhs) == 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
size_t String::find(const char c, size_t pos) const
|
||||
{
|
||||
if( pos >= size() )
|
||||
return npos;
|
||||
|
||||
const char* result = std::find(begin() + pos, end(), c);
|
||||
|
||||
return result != end() ? result - begin() : npos;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
size_t String::find_first_of(const String& chr, size_t pos) const
|
||||
{
|
||||
if( pos >= size() )
|
||||
return npos;
|
||||
|
||||
const char* result = std::find_first_of( begin() + pos, end(),
|
||||
chr.begin(), chr.end() );
|
||||
|
||||
return result != end() ? result - begin() : npos;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
size_t String::find_first_not_of(const String& chr, size_t pos) const
|
||||
{
|
||||
if( pos >= size() )
|
||||
return npos;
|
||||
|
||||
const char* result = std::find_if( begin() + pos, end(),
|
||||
no_match(chr.begin(), chr.end()) );
|
||||
|
||||
return result != end() ? result - begin() : npos;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const naRef String::get_naRef() const
|
||||
{
|
||||
return _str;
|
||||
}
|
||||
|
||||
} // namespace nasal
|
80
simgear/nasal/cppbind/NasalString.hxx
Normal file
80
simgear/nasal/cppbind/NasalString.hxx
Normal file
@ -0,0 +1,80 @@
|
||||
///@file Wrapper class for Nasal strings
|
||||
//
|
||||
// Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
#ifndef SG_NASAL_STRING_HXX_
|
||||
#define SG_NASAL_STRING_HXX_
|
||||
|
||||
#include "from_nasal.hxx"
|
||||
#include "to_nasal.hxx"
|
||||
|
||||
namespace nasal
|
||||
{
|
||||
|
||||
/**
|
||||
* A Nasal String
|
||||
*/
|
||||
class String
|
||||
{
|
||||
public:
|
||||
|
||||
static const size_t npos;
|
||||
|
||||
/**
|
||||
* Create a new Nasal String
|
||||
*
|
||||
* @param c Nasal context for creating the string
|
||||
* @param str String data
|
||||
*/
|
||||
String(naContext c, const char* str);
|
||||
|
||||
/**
|
||||
* Initialize from an existing Nasal String
|
||||
*
|
||||
* @param str Existing Nasal String
|
||||
*/
|
||||
String(naRef string);
|
||||
|
||||
const char* c_str() const;
|
||||
const char* begin() const;
|
||||
const char* end() const;
|
||||
|
||||
size_t size() const;
|
||||
size_t length() const;
|
||||
bool empty() const;
|
||||
|
||||
int compare(size_t pos, size_t len, const String& rhs) const;
|
||||
bool starts_with(const String& rhs) const;
|
||||
|
||||
size_t find(const char c, size_t pos = 0) const;
|
||||
size_t find_first_of(const String& chr, size_t pos = 0) const;
|
||||
size_t find_first_not_of(const String& chr, size_t pos = 0) const;
|
||||
|
||||
/**
|
||||
* Get Nasal representation of String
|
||||
*/
|
||||
const naRef get_naRef() const;
|
||||
|
||||
protected:
|
||||
|
||||
naRef _str;
|
||||
|
||||
};
|
||||
|
||||
} // namespace nasal
|
||||
|
||||
#endif /* SG_NASAL_STRING_HXX_ */
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "Ghost.hxx"
|
||||
#include "NasalHash.hxx"
|
||||
#include "NasalString.hxx"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
@ -111,6 +112,27 @@ int main(int argc, char* argv[])
|
||||
Hash mod = hash.createHash("mod");
|
||||
mod.set("parent", hash);
|
||||
|
||||
String string( to_nasal(c, "Test") );
|
||||
VERIFY( from_nasal<std::string>(c, string.get_naRef()) == "Test" );
|
||||
VERIFY( string.c_str() == std::string("Test") );
|
||||
VERIFY( string.starts_with(string) );
|
||||
VERIFY( string.starts_with(String(c, "T")) );
|
||||
VERIFY( string.starts_with(String(c, "Te")) );
|
||||
VERIFY( string.starts_with(String(c, "Tes")) );
|
||||
VERIFY( string.starts_with(String(c, "Test")) );
|
||||
VERIFY( !string.starts_with(String(c, "Test1")) );
|
||||
VERIFY( !string.starts_with(String(c, "bb")) );
|
||||
VERIFY( !string.starts_with(String(c, "bbasdasdafasd")) );
|
||||
VERIFY( string.find('e') == 1 );
|
||||
VERIFY( string.find('9') == String::npos );
|
||||
VERIFY( string.find_first_of(String(c, "st")) == 2 );
|
||||
VERIFY( string.find_first_of(String(c, "st"), 3) == 3 );
|
||||
VERIFY( string.find_first_of(String(c, "xyz")) == String::npos );
|
||||
VERIFY( string.find_first_not_of(String(c, "Tst")) == 1 );
|
||||
VERIFY( string.find_first_not_of(String(c, "Tse"), 2) == 3 );
|
||||
VERIFY( string.find_first_not_of(String(c, "abc")) == 0 );
|
||||
VERIFY( string.find_first_not_of(String(c, "abc"), 20) == String::npos );
|
||||
|
||||
Ghost<BasePtr>::init("BasePtr")
|
||||
.method<&Base::member>("member")
|
||||
.member("str", &Base::getString, &Base::setString);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "from_nasal_detail.hxx"
|
||||
#include "NasalHash.hxx"
|
||||
#include "NasalString.hxx"
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
@ -70,4 +71,13 @@ namespace nasal
|
||||
return Hash(ref, c);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
String from_nasal_helper(naContext c, naRef ref, String*)
|
||||
{
|
||||
if( !naIsString(ref) )
|
||||
throw bad_nasal_cast("Not a string");
|
||||
|
||||
return String(ref);
|
||||
}
|
||||
|
||||
} // namespace nasal
|
||||
|
@ -36,6 +36,7 @@ class SGPath;
|
||||
namespace nasal
|
||||
{
|
||||
class Hash;
|
||||
class String;
|
||||
|
||||
/**
|
||||
* Thrown when converting a type from/to Nasal has failed
|
||||
@ -87,6 +88,11 @@ namespace nasal
|
||||
*/
|
||||
Hash from_nasal_helper(naContext c, naRef ref, Hash*);
|
||||
|
||||
/**
|
||||
* Convert a Nasal string to a nasal::String
|
||||
*/
|
||||
String from_nasal_helper(naContext c, naRef ref, String*);
|
||||
|
||||
/**
|
||||
* Convert a Nasal number to a C++ numeric type
|
||||
*/
|
||||
|
@ -119,6 +119,9 @@ naRef naInit_readline(naContext c);
|
||||
naRef naInit_gtk(naContext ctx);
|
||||
naRef naInit_cairo(naContext ctx);
|
||||
|
||||
// Returns a hash which can be used to add methods callable on strings
|
||||
naRef naInit_string(naContext c);
|
||||
|
||||
// Context stack inspection, frame zero is the "top"
|
||||
int naStackDepth(naContext ctx);
|
||||
int naGetLine(naContext ctx, int frame);
|
||||
@ -159,6 +162,7 @@ naRef naStr_fromdata(naRef dst, const char* data, int len);
|
||||
naRef naStr_concat(naRef dest, naRef s1, naRef s2);
|
||||
naRef naStr_substr(naRef dest, naRef str, int start, int len);
|
||||
naRef naInternSymbol(naRef sym);
|
||||
naRef getStringMethods(naContext c);
|
||||
|
||||
// Vector utilities:
|
||||
int naVec_size(naRef v);
|
||||
|
@ -320,3 +320,27 @@ static int fromnum(double val, unsigned char* s)
|
||||
*ptr = 0;
|
||||
return ptr - s;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static naRef string_methods;
|
||||
static int init = 0; // As we can't use naNil() for static initialization we
|
||||
// need a separate variable for saving whether we have
|
||||
// already initialized.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
naRef naInit_string(naContext c)
|
||||
{
|
||||
string_methods = naNewHash(c);
|
||||
init = 1;
|
||||
return string_methods;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
naRef getStringMethods(naContext c)
|
||||
{
|
||||
if( !init )
|
||||
return naNil();
|
||||
|
||||
return string_methods;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user