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";
set(HEADERS
Ghost.hxx
NasalHash.hxx
+ NasalString.hxx
from_nasal_detail.hxx
from_nasal.hxx
nasal_traits.hxx
set(SOURCES
NasalHash.cxx
+ NasalString.cxx
from_nasal.cxx
to_nasal.cxx
)
--- /dev/null
+// 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
--- /dev/null
+///@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_ */
#include "Ghost.hxx"
#include "NasalHash.hxx"
+#include "NasalString.hxx"
#include <boost/shared_ptr.hpp>
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);
#include "from_nasal_detail.hxx"
#include "NasalHash.hxx"
+#include "NasalString.hxx"
#include <simgear/misc/sg_path.hxx>
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
namespace nasal
{
class Hash;
+ class String;
/**
* Thrown when converting a type from/to Nasal has failed
*/
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
*/
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);
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);
*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;
+}