cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bhigg...@apache.org
Subject [08/38] BB10: Add stock WebWorks Native Extension generated by Momentics.
Date Wed, 30 Jul 2014 19:06:25 GMT
http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/public/json_writer.cpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/public/json_writer.cpp b/src/blackberry10/native/public/json_writer.cpp
new file mode 100644
index 0000000..cdf4188
--- /dev/null
+++ b/src/blackberry10/native/public/json_writer.cpp
@@ -0,0 +1,829 @@
+#include <json/writer.h>
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool isControlCharacter(char ch)
+{
+   return ch > 0 && ch <= 0x1F;
+}
+
+static bool containsControlCharacter( const char* str )
+{
+   while ( *str ) 
+   {
+      if ( isControlCharacter( *(str++) ) )
+         return true;
+   }
+   return false;
+}
+static void uintToString( unsigned int value, 
+                          char *&current )
+{
+   *--current = 0;
+   do
+   {
+      *--current = (value % 10) + '0';
+      value /= 10;
+   }
+   while ( value != 0 );
+}
+
+std::string valueToString( Int value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   bool isNegative = value < 0;
+   if ( isNegative )
+      value = -value;
+   uintToString( UInt(value), current );
+   if ( isNegative )
+      *--current = '-';
+   assert( current >= buffer );
+   return current;
+}
+
+
+std::string valueToString( UInt value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   uintToString( value, current );
+   assert( current >= buffer );
+   return current;
+}
+
+std::string valueToString( double value )
+{
+   char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. 
+   sprintf_s(buffer, sizeof(buffer), "%#.16g", value); 
+#else	
+   sprintf(buffer, "%#.16g", value); 
+#endif
+   char* ch = buffer + strlen(buffer) - 1;
+   if (*ch != '0') return buffer; // nothing to truncate, so save time
+   while(ch > buffer && *ch == '0'){
+     --ch;
+   }
+   char* last_nonzero = ch;
+   while(ch >= buffer){
+     switch(*ch){
+     case '0':
+     case '1':
+     case '2':
+     case '3':
+     case '4':
+     case '5':
+     case '6':
+     case '7':
+     case '8':
+     case '9':
+       --ch;
+       continue;
+     case '.':
+       // Truncate zeroes to save bytes in output, but keep one.
+       *(last_nonzero+2) = '\0';
+       return buffer;
+     default:
+       return buffer;
+     }
+   }
+   return buffer;
+}
+
+
+std::string valueToString( bool value )
+{
+   return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+   // Not sure how to handle unicode...
+   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
+      return std::string("\"") + value + "\"";
+   // We have to walk value and escape any special characters.
+   // Appending to std::string is not efficient, but this should be rare.
+   // (Note: forward slashes are *not* rare, but I am not escaping them.)
+   unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
+   std::string result;
+   result.reserve(maxsize); // to avoid lots of mallocs
+   result += "\"";
+   for (const char* c=value; *c != 0; ++c)
+   {
+      switch(*c)
+      {
+         case '\"':
+            result += "\\\"";
+            break;
+         case '\\':
+            result += "\\\\";
+            break;
+         case '\b':
+            result += "\\b";
+            break;
+         case '\f':
+            result += "\\f";
+            break;
+         case '\n':
+            result += "\\n";
+            break;
+         case '\r':
+            result += "\\r";
+            break;
+         case '\t':
+            result += "\\t";
+            break;
+         //case '/':
+            // Even though \/ is considered a legal escape in JSON, a bare
+            // slash is also legal, so I see no reason to escape it.
+            // (I hope I am not misunderstanding something.
+            // blep notes: actually escaping \/ may be useful in javascript to avoid </ 
+            // sequence.
+            // Should add a flag to allow this compatibility mode and prevent this 
+            // sequence from occurring.
+         default:
+            if ( isControlCharacter( *c ) )
+            {
+               std::ostringstream oss;
+               oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+               result += oss.str();
+            }
+            else
+            {
+               result += *c;
+            }
+            break;
+      }
+   }
+   result += "\"";
+   return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+   : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void 
+FastWriter::enableYAMLCompatibility()
+{
+   yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string 
+FastWriter::write( const Value &root )
+{
+   document_ = "";
+   writeValue( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+FastWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      document_ += "null";
+      break;
+   case intValue:
+      document_ += valueToString( value.asInt() );
+      break;
+   case uintValue:
+      document_ += valueToString( value.asUInt() );
+      break;
+   case realValue:
+      document_ += valueToString( value.asDouble() );
+      break;
+   case stringValue:
+      document_ += valueToQuotedString( value.asCString() );
+      break;
+   case booleanValue:
+      document_ += valueToString( value.asBool() );
+      break;
+   case arrayValue:
+      {
+         document_ += "[";
+         int size = value.size();
+         for ( int index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ",";
+            writeValue( value[index] );
+         }
+         document_ += "]";
+      }
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         document_ += "{";
+         for ( Value::Members::iterator it = members.begin(); 
+               it != members.end(); 
+               ++it )
+         {
+            const std::string &name = *it;
+            if ( it != members.begin() )
+               document_ += ",";
+            document_ += valueToQuotedString( name.c_str() );
+            document_ += yamlCompatiblityEnabled_ ? ": " 
+                                                  : ":";
+            writeValue( value[name] );
+         }
+         document_ += "}";
+      }
+      break;
+   }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+   : rightMargin_( 74 )
+   , indentSize_( 3 )
+{
+}
+
+
+std::string 
+StyledWriter::write( const Value &root )
+{
+   document_ = "";
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+StyledWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               document_ += " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               document_ += ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+               writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            document_ += ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         document_ += "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ", ";
+            document_ += childValues_[index];
+         }
+         document_ += " ]";
+      }
+   }
+}
+
+
+bool 
+StyledWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      document_ += value;
+}
+
+
+void 
+StyledWriter::writeIndent()
+{
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         document_ += '\n';
+   }
+   document_ += indentString_;
+}
+
+
+void 
+StyledWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   document_ += value;
+}
+
+
+void 
+StyledWriter::indent()
+{
+   indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void 
+StyledWriter::unindent()
+{
+   assert( int(indentString_.size()) >= indentSize_ );
+   indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void 
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   document_ += normalizeEOL( root.getComment( commentBefore ) );
+   document_ += "\n";
+}
+
+
+void 
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      document_ += "\n";
+      document_ += normalizeEOL( root.getComment( commentAfter ) );
+      document_ += "\n";
+   }
+}
+
+
+bool 
+StyledWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+   : document_(NULL)
+   , rightMargin_( 74 )
+   , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+   document_ = &out;
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   *document_ << "\n";
+   document_ = NULL; // Forget the stream, for safety.
+}
+
+
+void 
+StyledStreamWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               *document_ << " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               *document_ << ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+	       writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            *document_ << ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         *document_ << "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               *document_ << ", ";
+            *document_ << childValues_[index];
+         }
+         *document_ << " ]";
+      }
+   }
+}
+
+
+bool 
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledStreamWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::writeIndent()
+{
+  /*
+    Some comments in this method would have been nice. ;-)
+
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         *document_ << '\n';
+   }
+  */
+   *document_ << '\n' << indentString_;
+}
+
+
+void 
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::indent()
+{
+   indentString_ += indentation_;
+}
+
+
+void 
+StyledStreamWriter::unindent()
+{
+   assert( indentString_.size() >= indentation_.size() );
+   indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void 
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   *document_ << normalizeEOL( root.getComment( commentBefore ) );
+   *document_ << "\n";
+}
+
+
+void 
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      *document_ << "\n";
+      *document_ << normalizeEOL( root.getComment( commentAfter ) );
+      *document_ << "\n";
+   }
+}
+
+
+bool 
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+   Json::StyledStreamWriter writer;
+   writer.write(sout, root);
+   return sout;
+}
+
+
+} // namespace Json

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/public/plugin.cpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/public/plugin.cpp b/src/blackberry10/native/public/plugin.cpp
new file mode 100644
index 0000000..6906275
--- /dev/null
+++ b/src/blackberry10/native/public/plugin.cpp
@@ -0,0 +1,320 @@
+#include "plugin.h"
+#include "tokenizer.h"
+
+#ifdef _WINDOWS
+#include <windows.h>
+BOOL APIENTRY DllMain( HANDLE hModule,
+                       DWORD ul_reason_for_call,
+                       LPVOID lpReserved )
+{
+    return TRUE;
+}
+#else
+#include <errno.h>
+#include <string.h>
+
+extern int errno;
+#endif
+
+SendPluginEv SendPluginEvent;
+
+string g_GetSysErrMsg( void )
+{
+    string strError = "Unknown";
+    // Problem loading
+#ifdef _WINDOWS
+    int nErrorCode = GetLastError();
+    LPTSTR s;
+    if ( ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    NULL, nErrorCode, 0, ( LPTSTR ) &s, 0, NULL ) )
+    {
+        strError = s;
+    }
+    else
+    {
+        char szBuf[ 20 ];
+        _snprintf_s( szBuf, _countof(szBuf), 19, "%d", nErrorCode );
+        strError = szBuf;
+    }
+#else
+    char szError[80];
+    if ( strerror_r( errno, szError, sizeof(szError)  ) )
+    {
+        strError = "no description found";
+    }
+    else
+    {
+        strError = szError;
+    }
+#endif
+    return strError;
+}
+
+void g_sleep( unsigned int mseconds )
+{
+#ifdef _WINDOWS
+    Sleep( mseconds );
+#else
+    usleep( mseconds * 1000 );
+#endif
+}
+
+string& g_trim( string& str )
+{
+    // Whitespace characters
+    char whspc[] = " \t\r\n\v\f";
+
+    // Whack off first part
+    size_t pos = str.find_first_not_of( whspc );
+
+    if ( pos != string::npos )
+        str.replace( 0, pos, "" );
+
+    // Whack off trailing stuff
+    pos = str.find_last_not_of( whspc );
+
+    if ( pos != string::npos )
+        str.replace( pos + 1, str.length() - pos, "" );
+
+    return str;
+}
+
+void g_tokenize( const string& str, const string& delimiters, vector<string>& tokens )
+{
+    tokenize( str, tokens, delimiters );
+}
+
+char* SetEventFunc( SendPluginEv funcPtr )
+{
+    static char * szObjList = onGetObjList();
+    SendPluginEvent = funcPtr;
+    return szObjList;
+}
+
+
+const int nMAXSIZE = 512;
+char* g_pszRetVal = NULL;
+
+//-----------------------------------------------------------
+// Map from an object Id to an object instance
+//-----------------------------------------------------------
+typedef std::map<string, JSExt*> StringToJExt_T;
+
+//-----------------------------------------------------------
+// Map from a browser context to an id mapping
+//-----------------------------------------------------------
+typedef std::map<void*, StringToJExt_T*> VoidToMap_T;
+
+VoidToMap_T g_context2Map;
+
+class GlobalSharedModule
+{
+
+public:
+    GlobalSharedModule( void )
+    {
+        g_pszRetVal = new char[ nMAXSIZE ];
+    }
+
+    ~GlobalSharedModule()
+    {
+        delete [] g_pszRetVal;
+
+        VoidToMap_T::iterator posMaps;
+
+        for ( posMaps = g_context2Map.begin(); posMaps != g_context2Map.end(); ++posMaps )
+        {
+            StringToJExt_T& id2Obj = *posMaps->second;
+            StringToJExt_T::iterator posMap;
+
+            for ( posMap = id2Obj.begin(); posMap != id2Obj.end(); ++posMap )
+            {
+                JSExt* pJSExt = posMap->second;
+
+                if ( pJSExt->CanDelete() )
+                {
+                    delete pJSExt;
+                }
+            }
+
+            id2Obj.erase( id2Obj.begin(), id2Obj.end() );
+        }
+
+        g_context2Map.erase( g_context2Map.begin(), g_context2Map.end() );
+    }
+};
+
+GlobalSharedModule g_sharedModule;
+
+char* g_str2global( const string& strRetVal )
+{
+    int nLen = strRetVal.size();
+
+    if ( nLen >= nMAXSIZE )
+    {
+        delete [] g_pszRetVal;
+        g_pszRetVal = new char[ nLen + 1 ];
+    }
+
+    else
+    {
+        // To minimaize the number of memory reallocations, the assumption
+        // is that in most times this will be the case
+        delete [] g_pszRetVal;
+        g_pszRetVal = new char[ nMAXSIZE ];
+    }
+
+    strcpy( g_pszRetVal, strRetVal.c_str() );
+    return g_pszRetVal;
+}
+
+bool g_unregisterObject( const string& strObjId, void* pContext )
+{
+    // Called by the plugin extension implementation
+    // if the extension handles the deletion of its object
+
+    StringToJExt_T * pID2Obj = NULL;
+
+    VoidToMap_T::iterator iter = g_context2Map.find( pContext );
+
+    if ( iter != g_context2Map.end() )
+    {
+        pID2Obj = iter->second;
+    }
+    else
+    {
+        return false;
+    }
+
+    StringToJExt_T& mapID2Obj = *pID2Obj;
+
+    StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+    if ( r == mapID2Obj.end() )
+    {
+        return false;
+    }
+
+    mapID2Obj.erase( strObjId );
+    return true;
+}
+
+char* InvokeFunction( const char* szCommand, void* pContext )
+{
+    StringToJExt_T * pID2Obj = NULL;
+
+    VoidToMap_T::iterator iter = g_context2Map.find( pContext );
+
+    if ( iter != g_context2Map.end() )
+    {
+        pID2Obj = iter->second;
+    }
+    else
+    {
+        pID2Obj = new StringToJExt_T;
+        g_context2Map[ pContext ] = pID2Obj;
+    }
+
+    StringToJExt_T& mapID2Obj = *pID2Obj;
+
+    string strFullCommand = szCommand;
+    vector<string> arParams;
+    g_tokenize( strFullCommand, " ", arParams );
+    string strCommand = arParams[ 0 ];
+    string strRetVal = szERROR;
+
+    if ( strCommand == szCREATE )
+    {
+        string strClassName = arParams[ 1 ];
+        string strObjId = arParams[ 2 ];
+
+        StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+        if ( r != mapID2Obj.end() )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Object already exists.";
+            return g_str2global( strRetVal );
+        }
+
+        JSExt* pJSExt = onCreateObject( strClassName, strObjId );
+
+        if ( pJSExt == NULL )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Unknown object type ";
+            strRetVal += strClassName;
+            return g_str2global( strRetVal );
+        }
+
+        pJSExt->m_pContext = pContext;
+        mapID2Obj[ strObjId ] = pJSExt;
+
+        strRetVal = szOK;
+        strRetVal += strObjId;
+        return g_str2global( strRetVal );
+    }
+    else
+    if ( strCommand == szINVOKE )
+    {
+        string strObjId = arParams[ 1 ];
+        string strMethod = arParams[ 2 ];
+
+        StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+        if ( r == mapID2Obj.end() )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :No object found for id.";
+            return g_str2global( strRetVal );
+        }
+
+        JSExt* pJSExt = r->second;
+
+        size_t nLoc = strFullCommand.find( strObjId );
+
+        if ( nLoc == string::npos )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Internal InvokeMethod error.";
+            return g_str2global( strRetVal );
+        }
+
+        if ( strMethod == szDISPOSE )
+        {
+            StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+            if ( r == mapID2Obj.end() )
+            {
+                strRetVal = szERROR;
+                strRetVal += strObjId;
+                return g_str2global( strRetVal );
+            }
+
+            JSExt * pJSExt = mapID2Obj[ strObjId ];
+
+            if ( pJSExt->CanDelete() )
+            {
+                delete pJSExt;
+            }
+
+            mapID2Obj.erase( strObjId );
+            strRetVal = szOK;
+            strRetVal += strObjId;
+            return g_str2global( strRetVal );
+        }
+
+        size_t nSuffixLoc = nLoc + strObjId.size();
+        string strInvoke = strFullCommand.substr( nSuffixLoc );
+        strInvoke = g_trim( strInvoke );
+        strRetVal = pJSExt->InvokeMethod( strInvoke );
+        return g_str2global( strRetVal );
+    }
+
+    strRetVal += " :Unknown command ";
+    strRetVal += strCommand;
+    return g_str2global( strRetVal );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/public/plugin.h
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/public/plugin.h b/src/blackberry10/native/public/plugin.h
new file mode 100644
index 0000000..4ef7116
--- /dev/null
+++ b/src/blackberry10/native/public/plugin.h
@@ -0,0 +1,70 @@
+#ifndef _PLUGIN_H
+#define _PLUGIN_H
+
+#include <map>
+#include <string>
+#include <vector>
+#include <unistd.h>
+//#include "tokenizer.h"
+
+using namespace std;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//%% Functions exported by this DLL
+//%% Should always be only SetEventFunc and InvokeFunction
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// g++ requires extern "C" otherwise the names of SetEventFunc and InvokeFunction
+// are mangled C++ style. MS Visual Studio doesn't seem to care though.
+extern "C"
+{
+    typedef void (*SendPluginEv)( const char* szEvent, void* pContext );
+    char* SetEventFunc(SendPluginEv funcPtr);
+    char* InvokeFunction( const char* szCommand, void* pContext );
+}
+
+// JNEXT Framework function of the form:
+// typedef void (*SendPluginEv)( const char* szEvent );
+// used to notify JavaScript of an asynchronous event
+extern SendPluginEv SendPluginEvent;
+
+/////////////////////////////////////////////////////////////////////////
+// Constants and methods common to all JNEXT extensions types
+/////////////////////////////////////////////////////////////////////////
+#define szERROR         "Error "
+#define szOK            "Ok "
+
+#define szDISPOSE       "Dispose"
+#define szINVOKE        "InvokeMethod"
+#define szCREATE        "CreateObj"
+
+/////////////////////////////////////////////////////////////////////////
+// Utility functions
+/////////////////////////////////////////////////////////////////////////
+string& g_trim( string& str );
+void g_tokenize(const string& str,const string& delimiters, vector<string>& tokens);
+char* g_str2static( const string& strRetVal );
+void g_sleep( unsigned int mseconds );
+bool g_unregisterObject( const string& strObjId, void* pContext );
+
+
+/////////////////////////////////////////////////////////////////////////
+// Abstract extension object
+/////////////////////////////////////////////////////////////////////////
+class JSExt
+{
+public:
+    virtual ~JSExt() {};
+    virtual string InvokeMethod( const string& strCommand ) = 0;
+    virtual bool CanDelete( void ) = 0;
+    virtual void TryDelete( void ) {}
+public:
+    void* m_pContext;
+};
+
+/////////////////////////////////////////////////////////////////////////
+// Callback functions to be implemented by the plugin implementation
+/////////////////////////////////////////////////////////////////////////
+extern char* onGetObjList( void );
+extern JSExt* onCreateObject( const string& strClassName, const string& strObjId );
+
+#endif

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/public/tokenizer.cpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/public/tokenizer.cpp b/src/blackberry10/native/public/tokenizer.cpp
new file mode 100644
index 0000000..4a39573
--- /dev/null
+++ b/src/blackberry10/native/public/tokenizer.cpp
@@ -0,0 +1,222 @@
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+you must not claim that you wrote the original software.
+If you use this software in a product, an acknowledgment
+in the product documentation would be appreciated but is
+not required.
+
+2. Altered source versions must be plainly marked as such,
+and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/
+
+/********************************************************************
+	created:	2006-01-28
+	filename: 	tokenizer.cpp
+	author:		J�rg Wiedenmann
+	
+	purpose:	A tokenizer function which provides a very
+				customizable way of breaking up strings.
+
+	history:	2006-01-28, Original version
+				2006-03-04, Fixed a small parsing bug, thanks Elias.
+*********************************************************************/
+
+#include "tokenizer.h"
+
+using namespace std;
+
+void tokenize ( const string& str, vector<string>& result,
+			   const string& delimiters, const string& delimiters_preserve,
+			   const string& quote, const string& esc )
+{
+	// clear the vector
+	if ( false == result.empty() )
+	{
+		result.clear();
+	}
+
+	string::size_type pos = 0; // the current position (char) in the string
+	char ch = 0; // buffer for the current character
+	char delimiter = 0;	// the buffer for the delimiter char which
+							// will be added to the tokens if the delimiter
+							// is preserved
+	char current_quote = 0; // the char of the current open quote
+	bool quoted = false; // indicator if there is an open quote
+	string token;  // string buffer for the token
+	bool token_complete = false; // indicates if the current token is
+								 // read to be added to the result vector
+	string::size_type len = str.length();  // length of the input-string
+
+	// for every char in the input-string
+	while ( len > pos )
+	{
+		// get the character of the string and reset the delimiter buffer
+		ch = str.at(pos);
+		delimiter = 0;
+
+		// assume ch isn't a delimiter
+		bool add_char = true;
+
+		// check ...
+
+		// ... if the delimiter is an escaped character
+		bool escaped = false; // indicates if the next char is protected
+		if ( false == esc.empty() ) // check if esc-chars are  provided
+		{
+			if ( string::npos != esc.find_first_of(ch) )
+			{
+				// get the escaped char
+				++pos;
+				if ( pos < len ) // if there are more chars left
+				{
+					// get the next one
+					ch = str.at(pos);
+
+					// add the escaped character to the token
+					add_char = true;
+				}
+				else // cannot get any more characters
+				{
+					// don't add the esc-char
+					add_char = false;
+				}
+
+				// ignore the remaining delimiter checks
+				escaped = true;
+			}
+		}
+
+		// ... if the delimiter is a quote
+		if ( false == quote.empty() && false == escaped )
+		{
+			// if quote chars are provided and the char isn't protected
+			if ( string::npos != quote.find_first_of(ch) )
+			{
+				// if not quoted, set state to open quote and set
+				// the quote character
+				if ( false == quoted )
+				{
+					quoted = true;
+					current_quote = ch;
+
+					// don't add the quote-char to the token
+					add_char = false;
+				}
+				else // if quote is open already
+				{
+					// check if it is the matching character to close it
+					if ( current_quote == ch )
+					{
+						// close quote and reset the quote character
+						quoted = false;
+						current_quote = 0;
+
+						// don't add the quote-char to the token
+						add_char = false;
+					}
+				} // else
+			}
+		}
+
+		// ... if the delimiter isn't preserved
+		if ( false == delimiters.empty() && false == escaped &&
+			 false == quoted )
+		{
+			// if a delimiter is provided and the char isn't protected by
+			// quote or escape char
+			if ( string::npos != delimiters.find_first_of(ch) )
+			{
+				// if ch is a delimiter and the token string isn't empty
+				// the token is complete
+				if ( false == token.empty() ) // BUGFIX: 2006-03-04
+				{
+					token_complete = true;
+				}
+
+				// don't add the delimiter to the token
+				add_char = false;
+			}
+		}
+
+		// ... if the delimiter is preserved - add it as a token
+		bool add_delimiter = false;
+		if ( false == delimiters_preserve.empty() && false == escaped &&
+			 false == quoted )
+		{
+			// if a delimiter which will be preserved is provided and the
+			// char isn't protected by quote or escape char
+			if ( string::npos != delimiters_preserve.find_first_of(ch) )
+			{
+				// if ch is a delimiter and the token string isn't empty
+				// the token is complete
+				if ( false == token.empty() ) // BUGFIX: 2006-03-04
+				{
+					token_complete = true;
+				}
+
+				// don't add the delimiter to the token
+				add_char = false;
+
+				// add the delimiter
+				delimiter = ch;
+				add_delimiter = true;
+			}
+		}
+
+
+		// add the character to the token
+		if ( true == add_char )
+		{
+			// add the current char
+			token.push_back( ch );
+		}
+
+		// add the token if it is complete
+		if ( true == token_complete && false == token.empty() )
+		{
+			// add the token string
+			result.push_back( token );
+
+			// clear the contents
+			token.clear();
+
+			// build the next token
+			token_complete = false;
+		}
+
+		// add the delimiter
+		if ( true == add_delimiter )
+		{
+			// the next token is the delimiter
+			string delim_token;
+			delim_token.push_back( delimiter );
+			result.push_back( delim_token );
+
+			// REMOVED: 2006-03-04, Bugfix
+		}
+
+		// repeat for the next character
+		++pos;
+	} // while
+
+	// add the final token
+	if ( false == token.empty() )
+	{
+		result.push_back( token );
+	}
+}

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/public/tokenizer.h
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/public/tokenizer.h b/src/blackberry10/native/public/tokenizer.h
new file mode 100644
index 0000000..75f567c
--- /dev/null
+++ b/src/blackberry10/native/public/tokenizer.h
@@ -0,0 +1,55 @@
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+	you must not claim that you wrote the original software.
+	If you use this software in a product, an acknowledgment
+	in the product documentation would be appreciated but is
+	not required.
+
+2. Altered source versions must be plainly marked as such,
+	and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/
+
+/********************************************************************
+	created:	2006-01-28
+	filename: 	tokenizer.cpp
+	author:		J�rg Wiedenmann
+
+	purpose:	A tokenizer function which provides a very
+				customizable way of breaking up strings.
+*********************************************************************/
+
+#include <vector>
+#include <string>
+using namespace std;
+
+// Function to break up a string into tokens
+//
+// Parameters:
+//-----------
+// str = the input string that will be tokenized
+// result = the tokens for str
+// delimiters = the delimiter characters
+// delimiters preserve = same as above, but the delimiter characters
+//		will be put into the result as a token
+// quote = characters to protect the enclosed characters
+// esc = characters to protect a single character
+//
+
+void tokenize ( const string& str, vector<string>& result,
+			const string& delimiters, const string& delimiters_preserve = "",
+			const string& quote = "\"", const string& esc = "\\" );

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/readme.txt
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/readme.txt b/src/blackberry10/native/readme.txt
new file mode 100644
index 0000000..ca4246f
--- /dev/null
+++ b/src/blackberry10/native/readme.txt
@@ -0,0 +1,406 @@
+Template for BlackBerry 10 Cordova Plugins
+==========================================
+
+BlackBerry 10 Cordova Plugins create a bridge between JavaScript code in an HTML5 application and C/C++ and/or Qt code in the plugin, allowing access to native libraries, which are not part of the HTML5 specification. The BlackBerry 10 Plugins included with the Cordova SDK also follow the same or similar format as shown in this template.
+
+Plugins offer a JavaScript API which communicates through an interface to native methods. This interface can send and receive data through strings, or data that can be represented as a string such as JSON and Base64.
+
+This template includes examples for communicating in several ways:
+
+1. A function that returns a string from a native method.
+2. A function that sends a string to, and gets another back, from a native method.
+3. A function that calls a native method with a JSON object input, and provides a callback function, which is fired by a native method, and receives JSON data.
+4. Defining a property that is linked to native methods when retrieved or set.
+5. Starting and Stopping a native thread, with a callback function that receives events from the native thread.
+
+## Building and Testing the Sample
+
+The included sample is the default Cordova Hello World application created by the "cordova create" command. It is ready to run on your simulator simply by calling "cordova run" in the sample directory. It has been altered to include a div in "index.html" for displaying the test data, and a set of test functions in "js/index.js" to excercise the template API and display some results.
+
+To use the plugin in another project, that's been created with Cordova, run "cordova plugin add <path to this Template folder>/plugin"
+
+Then you can call the methods with the namespace "community.templateplugin", and that should appear in WebInspector as an Object so you can see what APIs are available. The example APIs included will be detailed later in this guide.
+
+## Starting a Plugin from the Template
+
+Copy the Template folder to a location on your computer to start working with it.
+
+### Momentics NDK setup
+
+You can either import the project from the Template folder, or use the New Project Wizard in Momentics to create a starter project.
+
+#### Using the New Project Wizard
+
+1. Open the Momentics IDE. Navigate to the workbench and from the program menu select File -> New -> New BlackBerry Project.
+2. Choose Native Extension from the Project Type list, then select BlackBerry WebWorks, and click Next.
+3. Change the project name to "Template" and click Finish.
+4. Right click your project again and select Build Configurations -> Manage..., then click New.
+5. Enter "device" for the name and choose to copy settings from Device-Release.
+6. Repeat to create a configuration named "simulator", and choose to copy settings from Simulator-Debug.
+7. You will need to copy the device and simulator folders to the "/plugin/src/blackberry10/native" directory where you copied the Template, each time you build. You can configure a post build command if you'd like, in the project properties.
+
+#### Importing the Template
+
+1. Open the Momentics IDE. Navigate to the workbench and from the program menu
+select File -> Import and choose "Existing Projects into Workspace".
+2. Choose "Select root directory: " and browse to the "/plugin/src/blackberry10/native" directory where you copied the Template. Select the Template project in the Projects list and uncheck "Copy projects into workspace". Click Finish.
+3. Follow these next steps to build the template plugin to be sure the setup is working.
+
+#### How to build your native Plugin
+
+1. Right click your project and select the Clean Project option.
+2. Right click your project again and select Build Configurations -> Build Selected... .
+3. A window will appear that shows all the available build configurations
+for the project. Select "device" and "simulator" and click ok.
+4. You should see the shared libraries (libTemplate.so files) generated in the folders for each Build Configuration that you selected.
+
+### Using the Plugin in an Application
+
+To use the plugin in another project, that's been created with Cordova, run "cordova plugin add <path to this Template folder>/plugin".
+That will copy the plugin into the project, and update the www/config.xml file to include the feature as below:
+
+
+<feature name="community.templateplugin" value="community.templateplugin" />
+
+
+All the methods in the plugin will be prefixed by that feature name, so a method called "test()" supplied in the "community.templateplugin" plugin will be called in JavaScript like so:
+
+
+community.templateplugin.test();
+
+
+Depending on the plugin, these methods can also have return values, take arguments, or supply callback methods.
+
+To remove the plugin, run "cordova plugin rm community.templateplugin"
+
+### Modifying the Template Plugin
+
+#### Namespace
+Choose a namespace for your application that is concise and descriptive. Use community.pluginname as the general format. Change all the occurences of the name in plugin/plugin.xml. Update the "ID variable in client.js to match the namespace.
+
+#### JNEXT plugin files
+index.js and the template_js.cpp/hpp files are linked by the name of the library and the name of the class in the library. Change the Class Name from TemplateJS to something that matches the new plugin's role. Change the project name in the NDK as well. Then you will need to update the references in index.js to match the new values:
+
+Find self.init = function () {}, and change "libTemplate" to the new project name, but keep the "lib" prefix. Then change the reference to "TemplateJS" to use the new Class Name.
+
+
+self.init = function () {
+	if (!JNEXT.require("libTemplate")) {
+		return false;
+	}
+
+	self.m_id = JNEXT.createObject("libTemplate.TemplateJS");
+
+	//...
+};
+
+#### Update .js files
+There are many other places where "template" is used in file names and methods in the JavaScript files. These can be changed to better reflect the new plugin API. Note carefully where index.js calls the JNEXT.Template object so that you don't break the chain.
+
+#### Change NDK files
+In the files template_ndk.hpp and template_ndk.cpp, there are plenty of uses of "Template" and "template" which can be changed to match the new plugin.
+
+#### Rebuild 
+When making changes, rebuild regularly so you don't make a really hard to find typo.
+
+Follow the steps above to:
+1. Build the native portion, and
+2. Use the plugin in your test app.
+
+## Architecture of a Plugin
+
+Plugins are organized into several files, each with a specific role.
+
+1. plugin.xml - defines the namespace of the plugin lists the files that need to be included.
+2. client.js - the client file defines the API that can be called by an application. It calls to functions in index.js using the Cordova framework. It also connects callback functions to the events that fire them.
+3. index.js - This is the main controller of the plugin. It receives calls from the client.js through Cordova, and calls the appropriate methods in the included JNEXT object, which does the communication to the Native side of JNEXT.
+4. template_js.hpp - C++ header for the JNEXT code. You should rarely have to edit this aside from renaming.
+6. template_js.cpp - C++ code for the JNEXT plugin. Besides renaming, the primary editing of this will be to edit the InvokeMethod function to call the appropriate methods in template_ndk.cpp, given the command and callbackId sent in from index.js and the Template object.
+7. template_ndk.hpp - C++ header for the native code. Where you will need to list method signatures for the extenion methods called from the template_js.cpp file, and any private methods or variables.
+8. template_ndk.cpp - C++ native code. All the main native code will go here typically. 
+
+## Communication end to end
+
+Plugin methods can be synchronous or asynchronous, send arguments, receive return values, and provide callback methods.
+
+In client.js we define the _ID variable for the name of the plugin, and the exec method from Cordova which will do the communication:
+
+
+var _self = {},
+	_ID = "community.templateplugin",
+	exec = cordova.require("cordova/exec");
+
+
+The basic format of all cordova client-side calls is 
+
+
+exec(success, fail, pluginId, method, args);
+
+
+In most cases, we'll define success and fail inline.
+
+#### Synchronous Methods
+
+a simple Synchronous method call looks like this, in client.js:
+
+
+_self.testInput = function (input) {
+	var result,
+		success = function (data, response) {
+			result = data;
+		},
+		fail = function (data, response) {
+			console.log("Error: " + data);
+		};
+	exec(success, fail, _ID, "test", { input: input });
+	return result;
+};
+
+
+In index.js, the client-side call maps to 
+
+
+test: function (success, fail, args, env) {
+	var result = new PluginResult(args, env);
+	args = JSON.parse(decodeURIComponent(args["input"]));
+	result.ok(template.getInstance().testInput(result.callbackId, args), false);
+},
+
+Where the success and fail callbacks were sent in from client.js, and args is an object passed in to the exec method, but it has been converted by JSON.stringify() and encoded as a URIcomponent, so you must call 
+
+
+JSON.parse(decodeURIComponent(args["input"]));
+
+
+To communicate through Cordova, a new PluginResult is created, and we fire the result.ok method, and pass in the result of the appropriate JNEXT function. In order to handle times where there is a callback, we will always include the callbackId when sending in arguments. So, the method in the JNEXT.Template object looks like the following:
+
+
+self.testInput = function (callbackId, input) {
+	return JNEXT.invoke(self.m_id, "testStringInput " + callbackId + " " + input);
+};
+
+Note: If input is a JSON object, we need to convert it to a string first with JSON.stringify(input).
+
+Now the communication passes into the native layer. JNEXT.invoke eventually calls into:
+
+
+string TemplateJS::InvokeMethod(const string& command) {
+	// format must be: "command callbackId params"
+	size_t commandIndex = command.find_first_of(" ");
+	std::string strCommand = command.substr(0, commandIndex);
+	size_t callbackIndex = command.find_first_of(" ", commandIndex + 1);
+	std::string callbackId = command.substr(commandIndex + 1, callbackIndex - commandIndex - 1);
+	std::string arg = command.substr(callbackIndex + 1, command.length());
+	// ...
+	} else if (strCommand == "testStringInput") {
+		return m_pTemplateController->templateTestString(arg);
+	}
+	//...
+}
+
+
+The method name and callbackId are stripped off the front of the command sent in, and the rest is sent in as an argument for the appropriate method. Note the use of the pointer to the TemplateNDK object, so we separate our regular native code from the JNEXT code.
+
+Finally, we call the native method that contains the functionality we are providing to our WebWorks application, and in this example, it takes in the arguments, appends them to a string and returns the result to WebWorks.
+
+
+// Take in input and return a value
+std::string TemplateNDK::templateTestString(const std::string& inputString) {
+	return "Template Test Function, got: " + inputString;
+}
+
+
+If the input is a JSON object, we need to parse it first, as shown here:
+
+
+// Parse the arg string as JSON
+Json::Reader reader;
+Json::Value root;
+bool parse = reader.parse(inputString, root);
+
+
+To return JSON, use 
+
+
+Json::FastWriter writer;
+Json::Value root;
+root["result"] = "result value";
+return writer.write(root);
+
+
+#### Asynchronous Methods
+
+An Asynchronous method will typically provide a callback function to receive the results of a method, but this is not necessarily the case for all situations. The sequence is much the same as that of Synchronous Methods with these differences:
+
+Asynchronous method call, with both input and a callback function:
+
+
+_self.testAsync = function (input, callback) {
+	var success = function (data, response) {
+			var json = JSON.parse(data);
+			callback(json);
+		},
+		fail = function (data, response) {
+			console.log("Error: " + data);
+		};
+	exec(success, fail, _ID, "testAsync", { input: input });
+};
+
+
+In index.js we're going to keep a record of the PluginResult so we can call the callback on it later. And right now, we'll call into JNEXT for the native code, but return noResult(true) right now. The true value tells Cordova to keep our callback around.
+
+
+testAsync: function (success, fail, args, env) {
+	var result = new PluginResult(args, env);
+	resultObjs[result.callbackId] = result;
+	args = JSON.parse(decodeURIComponent(args["input"]));
+	template.getInstance().testAsync(result.callbackId, args);
+	result.noResult(true);
+},
+
+
+Now the code proceeds as for Synchronous events, until the template_ndk.cpp method, where instead of returning the result directly, the NotifyEvent method is used instead, but we'll be passing in the callbackId as well this time instead of ignoring it. The callbackId is what we'll use to communicate back through JNEXT:
+
+
+// Asynchronous callback with JSON data input and output
+void TemplateNDK::templateTestAsync(const std::string& callbackId, const std::string& inputString) {
+	// Parse the arg string as JSON
+	Json::FastWriter writer;
+	Json::Reader reader;
+	Json::Value root;
+	bool parse = reader.parse(inputString, root);
+
+	if (!parse) {
+		Json::Value error;
+		error["result"] = "Cannot parse JSON object";
+		m_pParent->NotifyEvent(callbackId + " " + writer.write(error));
+	} else {
+		root["result"] = root["value1"].asInt() + root["value2"].asInt();
+		m_pParent->NotifyEvent(callbackId + " " + writer.write(root));
+	}
+}
+
+
+This event passes through the JNEXT plugin and is received on the onEvent(strData) method of the JNEXT.Template object. In the case of a standard asynchronous one-time event, we'll lookup the result and call callbackOk(data, false) so the callback is removed from Cordova, and we'll delete our record as well. However, if we need to keep that callback around for further events, we'll need some way of tracking that. In this example, there is only one callback that we need to keep around ever. :
+
+
+// Fired by the Event framework (used by asynchronous callbacks)
+self.onEvent = function (strData) {
+	var arData = strData.split(" "),
+		callbackId = arData[0],
+		result = resultObjs[callbackId],
+		data = arData.slice(1, arData.length).join(" ");
+
+	if (result) {
+        if (callbackId != threadCallback) {
+            result.callbackOk(data, false);
+            delete resultObjs[callbackId];
+        } else {
+        	result.callbackOk(data, true);
+        }
+    }
+	...
+};
+
+
+result.callbackOk(data, false) will call the success method that we registered at the beginning of the flow, in client.js.
+
+#### Callbacks for multiple events
+
+The Asynchronous methods above use one-time callbacks to receive their results. Sometimes it is important to receive multiple events on a callback, such as when listening to a thread or longer process.
+
+This is done as above, simply retaining our PluginResult registry until we don't need it any longer, and if necessary, we can return a value immediately but also keep the callback as so:
+
+
+startThread: function (success, fail, args, env) {
+	var result = new PluginResult(args, env);
+	if (!threadCallback) {
+		threadCallback = result.callbackId;
+		resultObjs[result.callbackId] = result;
+		result.ok(template.getInstance().startThread(result.callbackId), true);
+	} else {
+		result.error(template.getInstance().startThread(result.callbackId), false);
+	}
+},
+
+At the native layer, the NotifyEvent method can be called multiple times and be received by the callback in this way. The same success method will get called for the immediate result, and all the subsequent callbacks.
+
+#### Defining Properties
+
+Properties can be defined on the plugin so that code like:
+
+
+community.templateplugin.templateProperty;
+
+
+returns a value, and it can be set by the following code:
+
+
+community.templateplugin.templateProperty = value;
+
+
+The following code defines a property called templateProperty, backed by the plugin method of the same name for setting or retrieving the value. The getter or setter could be removed to restrict what the property responds to.
+
+
+Object.defineProperty(_self, "templateProperty", {
+	get: function () {
+		var result,
+			success = function (data, response) {
+				result = data;
+			},
+			fail = function (data, response) {
+				console.log("Error: " + data);
+			};
+		exec(success, fail, _ID, "templateProperty", null);
+		return result;
+	},
+	set: function (arg) {
+		var result,
+			success = function (data, response) {
+				result = data;
+			},
+			fail = function (data, response) {
+				console.log("Error: " + data);
+			};
+		exec(success, fail, _ID, "templateProperty", {"value": arg });
+		return result;
+	}
+});
+
+
+The property calls are the same as synchronous calls, but are adapted to handle both input and no input on the same function in index.js:
+
+
+templateProperty: function (success, fail, args, env) {
+	var result = new PluginResult(args, env);
+	var value;
+	if (args && args["value"]) {
+        value = JSON.parse(decodeURIComponent(args["value"]));
+		template.getInstance().templateProperty(result.callbackId, value);
+        result.noResult(false);
+    } else {
+        result.ok(template.getInstance().templateProperty(), false);
+    }
+},
+
+
+## Debugging
+
+Debugging plugins is difficult, but there are some ways that can be effective. If you open WebInspector to the "first" WebView, instead of the second, you will be able to see and interact with the index.js code and the inner parts of the extension. Opening a tab on the "second" WebView, where you normally would, at the same time will allow you to inspect the whole flow of calls within JavaScript.
+
+Simple JavaScript alerts also work in the plugin files and this can be invaluable to check the value of some data being passed around. Since plugins deal with strings, it's easy to check.
+
+### Common Issues
+If you are getting a message saying the application can not load your .so file, it's nearly always a linking problem. Your code may build in the IDE, but not actually link on the device. Make sure you've included all your dependencies and includes properly, on the build that you have loaded. Also, make sure that you've loaded the device build on a device, and the simulator on a simulator.
+
+If your application launches but quickly freezes and then is closed, you may be using a BPS API but haven't called
+
+
+bps_initialize();
+
+
+It is required for things like LED, Vibration, Audio and many others. See [more information here](http://developer.blackberry.com/native/reference/bb10/com.qnx.doc.bps.lib_ref/com.qnx.doc.bps.lib_ref/topic/bps_initialize.html).
+
+## Disclaimer
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/src/template_js.cpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/src/template_js.cpp b/src/blackberry10/native/src/template_js.cpp
new file mode 100644
index 0000000..c4de122
--- /dev/null
+++ b/src/blackberry10/native/src/template_js.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2013 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include "../public/tokenizer.h"
+#include "template_js.hpp"
+#include "template_ndk.hpp"
+
+using namespace std;
+
+/**
+ * Default constructor.
+ */
+TemplateJS::TemplateJS(const std::string& id) :
+		m_id(id) {
+	m_pTemplateController = new webworks::TemplateNDK(this);
+}
+
+/**
+ * TemplateJS destructor.
+ */
+TemplateJS::~TemplateJS() {
+	if (m_pTemplateController)
+		delete m_pTemplateController;
+}
+
+/**
+ * This method returns the list of objects implemented by this native
+ * extension.
+ */
+char* onGetObjList() {
+	static char name[] = "TemplateJS";
+	return name;
+}
+
+/**
+ * This method is used by JNext to instantiate the TemplateJS object when
+ * an object is created on the JavaScript server side.
+ */
+JSExt* onCreateObject(const string& className, const string& id) {
+	if (className == "TemplateJS") {
+		return new TemplateJS(id);
+	}
+
+	return NULL;
+}
+
+/**
+ * Method used by JNext to determine if the object can be deleted.
+ */
+bool TemplateJS::CanDelete() {
+	return true;
+}
+
+/**
+ * It will be called from JNext JavaScript side with passed string.
+ * This method implements the interface for the JavaScript to native binding
+ * for invoking native code. This method is triggered when JNext.invoke is
+ * called on the JavaScript side with this native objects id.
+ */
+string TemplateJS::InvokeMethod(const string& command) {
+	// format must be: "command callbackId params"
+	size_t commandIndex = command.find_first_of(" ");
+	std::string strCommand = command.substr(0, commandIndex);
+	size_t callbackIndex = command.find_first_of(" ", commandIndex + 1);
+	std::string callbackId = command.substr(commandIndex + 1, callbackIndex - commandIndex - 1);
+	std::string arg = command.substr(callbackIndex + 1, command.length());
+
+	// based on the command given, run the appropriate method in template_ndk.cpp
+	if (strCommand == "testString") {
+		return m_pTemplateController->templateTestString();
+	} else if (strCommand == "testStringInput") {
+		return m_pTemplateController->templateTestString(arg);
+	} else if (strCommand == "templateProperty") {
+		// if arg exists we are setting property
+		if (arg != strCommand) {
+			m_pTemplateController->setTemplateProperty(arg);
+		} else {
+			return m_pTemplateController->getTemplateProperty();
+		}
+	} else if (strCommand == "testAsync") {
+		m_pTemplateController->templateTestAsync(callbackId, arg);
+	} else if (strCommand == "templateStartThread") {
+		return m_pTemplateController->templateStartThread(callbackId);
+	} else if (strCommand == "templateStopThread") {
+		return m_pTemplateController->templateStopThread();
+	}
+
+	strCommand.append(";");
+	strCommand.append(command);
+	return strCommand;
+}
+
+// Notifies JavaScript of an event
+void TemplateJS::NotifyEvent(const std::string& event) {
+	std::string eventString = m_id + " ";
+	eventString.append(event);
+	SendPluginEvent(eventString.c_str(), m_pContext);
+}

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/src/template_js.hpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/src/template_js.hpp b/src/blackberry10/native/src/template_js.hpp
new file mode 100644
index 0000000..00d6ceb
--- /dev/null
+++ b/src/blackberry10/native/src/template_js.hpp
@@ -0,0 +1,39 @@
+/*
+* Copyright 2013 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef TemplateJS_HPP_
+#define TemplateJS_HPP_
+
+#include <string>
+#include "../public/plugin.h"
+#include "template_ndk.hpp"
+
+class TemplateJS: public JSExt {
+
+public:
+    explicit TemplateJS(const std::string& id);
+    virtual ~TemplateJS();
+    virtual bool CanDelete();
+    virtual std::string InvokeMethod(const std::string& command);
+    void NotifyEvent(const std::string& event);
+
+private:
+    std::string m_id;
+    // Definition of a pointer to the actual native extension code
+    webworks::TemplateNDK *m_pTemplateController;
+};
+
+#endif /* TemplateJS_HPP_ */

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/src/template_ndk.cpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/src/template_ndk.cpp b/src/blackberry10/native/src/template_ndk.cpp
new file mode 100644
index 0000000..142645e
--- /dev/null
+++ b/src/blackberry10/native/src/template_ndk.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2013 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <sstream>
+#include <json/reader.h>
+#include <json/writer.h>
+#include <pthread.h>
+#include "template_ndk.hpp"
+#include "template_js.hpp"
+
+namespace webworks {
+
+TemplateNDK::TemplateNDK(TemplateJS *parent) {
+	m_pParent = parent;
+	templateProperty = 50;
+	templateThreadCount = 1;
+	m_thread = 0;
+	pthread_cond_t cond  = PTHREAD_COND_INITIALIZER;
+	pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+	threadHalt = true;
+}
+
+TemplateNDK::~TemplateNDK() {
+}
+
+// These methods are the true native code we intend to reach from WebWorks
+std::string TemplateNDK::templateTestString() {
+	return "Template Test Function";
+}
+
+// Take in input and return a value
+std::string TemplateNDK::templateTestString(const std::string& inputString) {
+	return "Template Test Function, got: " + inputString;
+}
+
+// Get an integer property
+std::string TemplateNDK::getTemplateProperty() {
+	stringstream ss;
+	ss << templateProperty;
+	return ss.str();
+}
+
+// set an integer property
+void TemplateNDK::setTemplateProperty(const std::string& inputString) {
+	templateProperty = (int) strtoul(inputString.c_str(), NULL, 10);
+}
+
+// Asynchronous callback with JSON data input and output
+void TemplateNDK::templateTestAsync(const std::string& callbackId, const std::string& inputString) {
+	// Parse the arg string as JSON
+	Json::FastWriter writer;
+	Json::Reader reader;
+	Json::Value root;
+	bool parse = reader.parse(inputString, root);
+
+	if (!parse) {
+		Json::Value error;
+		error["result"] = "Cannot parse JSON object";
+		m_pParent->NotifyEvent(callbackId + " " + writer.write(error));
+	} else {
+		root["result"] = root["value1"].asInt() + root["value2"].asInt();
+		m_pParent->NotifyEvent(callbackId + " " + writer.write(root));
+	}
+}
+
+// Thread functions
+// The following functions are for controlling a Thread in the extension
+
+// The actual thread (must appear before the startThread method)
+// Loops and runs the callback method
+void* TemplateThread(void* parent) {
+	TemplateNDK *pParent = static_cast<TemplateNDK *>(parent);
+
+	// Loop calls the callback function and continues until stop is set
+	while (!pParent->isThreadHalt()) {
+		sleep(1);
+		pParent->templateThreadCallback();
+	}
+
+	return NULL;
+}
+
+// Starts the thread and returns a message on status
+std::string TemplateNDK::templateStartThread(const std::string& callbackId) {
+	if (!m_thread) {
+		int rc;
+	    rc = pthread_mutex_lock(&mutex);
+	    threadHalt = false;
+	    rc = pthread_cond_signal(&cond);
+	    rc = pthread_mutex_unlock(&mutex);
+
+		pthread_attr_t thread_attr;
+		pthread_attr_init(&thread_attr);
+		pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+
+		pthread_create(&m_thread, &thread_attr, TemplateThread,
+				static_cast<void *>(this));
+		pthread_attr_destroy(&thread_attr);
+		threadCallbackId = callbackId;
+		return "Thread Started";
+	} else {
+		return "Thread Running";
+	}
+}
+
+// Sets the stop value
+std::string TemplateNDK::templateStopThread() {
+	int rc;
+	// Request thread to set prevent sleep to false and terminate
+	rc = pthread_mutex_lock(&mutex);
+	threadHalt = true;
+	rc = pthread_cond_signal(&cond);
+	rc = pthread_mutex_unlock(&mutex);
+
+    // Wait for the thread to terminate.
+    void *exit_status;
+    rc = pthread_join(m_thread, &exit_status) ;
+
+	// Clean conditional variable and mutex
+	pthread_cond_destroy(&cond);
+	pthread_mutex_destroy(&mutex);
+
+	m_thread = 0;
+	threadHalt = true;
+	return "Thread stopped";
+}
+
+// The callback method that sends an event through JNEXT
+void TemplateNDK::templateThreadCallback() {
+	Json::FastWriter writer;
+	Json::Value root;
+	root["threadCount"] = templateThreadCount++;
+	m_pParent->NotifyEvent(threadCallbackId + " " + writer.write(root));
+}
+
+// getter for the stop value
+bool TemplateNDK::isThreadHalt() {
+	int rc;
+	bool isThreadHalt;
+	rc = pthread_mutex_lock(&mutex);
+	isThreadHalt = threadHalt;
+	rc = pthread_mutex_unlock(&mutex);
+	return isThreadHalt;
+}
+
+} /* namespace webworks */

http://git-wip-us.apache.org/repos/asf/cordova-plugin-globalization/blob/cd9819fb/src/blackberry10/native/src/template_ndk.hpp
----------------------------------------------------------------------
diff --git a/src/blackberry10/native/src/template_ndk.hpp b/src/blackberry10/native/src/template_ndk.hpp
new file mode 100644
index 0000000..9c798e5
--- /dev/null
+++ b/src/blackberry10/native/src/template_ndk.hpp
@@ -0,0 +1,64 @@
+/*
+* Copyright 2013 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef TEMPLATENDK_HPP_
+#define TEMPLATENDK_HPP_
+
+#include <string>
+#include <pthread.h>
+
+class TemplateJS;
+
+namespace webworks {
+
+class TemplateNDK {
+public:
+	explicit TemplateNDK(TemplateJS *parent = NULL);
+	virtual ~TemplateNDK();
+
+	// The extension methods are defined here
+	std::string templateTestString();
+
+	std::string templateTestString(const std::string& inputString);
+
+	std::string getTemplateProperty();
+
+	void setTemplateProperty(const std::string& inputString);
+
+	void templateTestAsync(const std::string& callbackId, const std::string& inputString);
+
+	std::string templateStartThread(const std::string& callbackId);
+
+	std::string templateStopThread();
+
+	bool isThreadHalt();
+
+	void templateThreadCallback();
+
+private:
+	TemplateJS *m_pParent;
+	int templateProperty;
+	int templateThreadCount;
+	bool threadHalt;
+	std::string threadCallbackId;
+	pthread_t m_thread;
+	pthread_cond_t cond;
+	pthread_mutex_t mutex;
+};
+
+} // namespace webworks
+
+#endif /* TEMPLATENDK_H_ */


Mime
View raw message