[mapguide-commits] r7627 - sandbox/jng/node/Oem/SWIGEx/Source/Modules

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jun 18 07:37:13 PDT 2013


Author: jng
Date: 2013-06-18 07:37:13 -0700 (Tue, 18 Jun 2013)
New Revision: 7627

Modified:
   sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
Log:
This submission allows the generated NodeJS binding to do basic parameter and return value marshalling for its proxy class methods and also generates a (currently empty) hook function which will apply the necessary JS prototype inheritance chains.

Modified: sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
===================================================================
--- sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx	2013-06-17 04:48:27 UTC (rev 7626)
+++ sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx	2013-06-18 14:37:13 UTC (rev 7627)
@@ -1,9 +1,14 @@
 #include "swigmod.h"
 #include <vector>
+#include <sstream>
 
 #define EXPORTS_VAR "exports"
 #define CLASS_EXPORT_VAR "tpl"
 #define CLASS_PROXY_CTOR_NAME "New"
+#define BASE_CLASS_FUNC_TEMPLATE_VAR "baseCls"
+#define WRAPPED_PTR_VAR "wrappedPtr"
+#define FUNC_RET_VAR "retVal"
+#define ARGS_VAR "args"
 
 class Indenter
 {
@@ -24,11 +29,18 @@
     String* m_namespace;
     String* m_currentClassName;
     File* m_fOutputFile;
+    std::vector<std::string> m_classFwdDecls;
     std::vector<std::string> m_classDecls;
+    std::vector<std::string> m_classMethodDecls;
     std::vector<std::string> m_classExportCalls;
+    std::vector<std::string> m_classInheritCalls;
     std::vector<std::string> m_classMemberExportCalls;
+    std::vector<std::string> m_classSetupCalls;
     std::string m_currentFragment;
     std::string m_currentExportFragment;
+    std::string m_currentInheritFragment;
+    std::string m_currentMethodFragment;
+    std::string m_currentClassSetupFragment;
     int m_indentationLevels;
     
 public:
@@ -95,8 +107,25 @@
         writeToFile("#include \"WebSupport.h\"\n");
         writeToFile("#include \"HttpHandler.h\"\n\n\n");
 
+        // Due to C++ being sensitive to order of types declared (we are outputting this all into one big .cpp file)
+        // We have to output the generated code in chunks, as shown below
+        //
+        //
+
         Language::top(n);
+        writeToFile("//=====================================\n");
+        writeToFile("//Forward declarations\n");
+        writeToFile("//=====================================\n");
+        for (std::vector<std::string>::iterator it = m_classFwdDecls.begin(); it != m_classFwdDecls.end(); it++)
+        {
+            std::string call = (*it);
+            writeToFile(call);
+            writeToFile("\n");
+        }
 
+        writeToFile("//=====================================\n");
+        writeToFile("//Proxy class definitions\n");
+        writeToFile("//=====================================\n");
         for (std::vector<std::string>::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
         {
             std::string call = (*it);
@@ -104,6 +133,26 @@
             writeToFile("\n");
         }
 
+        writeToFile("//=====================================\n");
+        writeToFile("//Proxy class method definitions\n");
+        writeToFile("//=====================================\n");
+        for (std::vector<std::string>::iterator it = m_classMethodDecls.begin(); it != m_classMethodDecls.end(); it++)
+        {
+            std::string call = (*it);
+            writeToFile(call);
+            writeToFile("\n");
+        }
+
+        writeToFile("//=====================================\n");
+        writeToFile("//Proxy class setup methods\n");
+        writeToFile("//=====================================\n");
+        for (std::vector<std::string>::iterator it = m_classSetupCalls.begin(); it != m_classSetupCalls.end(); it++)
+        {
+            std::string call = (*it);
+            writeToFile(call);
+            writeToFile("\n");
+        }
+
         writeToFile(NewStringf("extern \"C\" void init(v8::Handle<v8::Object> %s) {\n", EXPORTS_VAR));
         {
             Indenter ind(m_indentationLevels);
@@ -113,6 +162,13 @@
                 writeToFile(call);
                 writeToFile("\n");
             }
+
+            for (std::vector<std::string>::iterator it = m_classInheritCalls.begin(); it != m_classInheritCalls.end(); it++)
+            {
+                std::string call = (*it);
+                writeToFile(call);
+                writeToFile("\n");
+            }
         }
         writeToFile("}\n");
         writeToFile(NewStringf("NODE_MODULE(%s, init)\n", modName));
@@ -131,7 +187,7 @@
         if (Strstr(name, entry))
         {
             writeToFile(NewStringf("//Global Function: %s\n", name));
-            writeToFile(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& args) {\n", name));
+            writeToFile(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", name, ARGS_VAR));
             {
                 Indenter ind(m_indentationLevels);
                 //writeToFile("v8::HandleScope scope;\n");
@@ -144,7 +200,7 @@
         {
             String* ovName = getOverloadedName(n);
             writeToCurrentClassFragment(NewStringf("//ctor Function Wrapper: %s\n", name));
-            writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& args) {\n", ovName));
+            writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", ovName, ARGS_VAR));
             {
                 Indenter ind(m_indentationLevels);
                 //writeToCurrentClassFragment("v8::HandleScope scope;\n");
@@ -156,7 +212,7 @@
         else if (Strstr(name, dtorPrefix))
         {
             writeToCurrentClassFragment(NewStringf("//dtor Function Wrapper: %s\n", name));
-            writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& args) {\n", name));
+            writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", name, ARGS_VAR));
             {
                 Indenter ind(m_indentationLevels);
                 //writeToCurrentClassFragment("v8::HandleScope scope;\n");
@@ -169,23 +225,74 @@
         return SWIG_OK;
     }
 
-    void writeTabs() 
+    void writeTabsToCurrentClassSetupFragment() 
     {
         if (m_indentationLevels > 0)
         {
             for (int i = 0; i < m_indentationLevels; i++)
             {
-                Printf(m_fOutputFile, "\t");
+                m_currentClassSetupFragment += "\t";
             }
         }
     }
 
-    void writeTabsToCurrentFragment() 
+    void writeToCurrentClassSetupFragment(String* str, bool bDelete = true)
     {
+        writeTabsToCurrentClassSetupFragment();
+        m_currentClassSetupFragment += Char(str);
+        if (bDelete)
+            Delete(str);
+    }
+
+    void writeToCurrentClassSetupFragment(const std::string& str)
+    {
+        writeTabsToCurrentClassSetupFragment();
+        m_currentClassSetupFragment += str;
+    }
+
+    void writeToCurrentClassSetupFragment(const char* str)
+    {
+        writeTabsToCurrentClassSetupFragment();
+        m_currentClassSetupFragment += str;
+    }
+
+    void writeTabsToCurrentMethodFragment() 
+    {
         if (m_indentationLevels > 0)
         {
             for (int i = 0; i < m_indentationLevels; i++)
             {
+                m_currentMethodFragment += "\t";
+            }
+        }
+    }
+
+    void writeToCurrentMethodFragment(String* str, bool bDelete = true)
+    {
+        writeTabsToCurrentMethodFragment();
+        m_currentMethodFragment += Char(str);
+        if (bDelete)
+            Delete(str);
+    }
+
+    void writeToCurrentMethodFragment(const std::string& str)
+    {
+        writeTabsToCurrentMethodFragment();
+        m_currentMethodFragment += str;
+    }
+
+    void writeToCurrentMethodFragment(const char* str)
+    {
+        writeTabsToCurrentMethodFragment();
+        m_currentMethodFragment += str;
+    }
+
+    void writeTabsToCurrentClassFragment() 
+    {
+        if (m_indentationLevels > 0)
+        {
+            for (int i = 0; i < m_indentationLevels; i++)
+            {
                 m_currentFragment += "\t";
             }
         }
@@ -193,7 +300,7 @@
 
     void writeToCurrentClassFragment(String* str, bool bDelete = true)
     {
-        writeTabsToCurrentFragment();
+        writeTabsToCurrentClassFragment();
         m_currentFragment += Char(str);
         if (bDelete)
             Delete(str);
@@ -201,19 +308,30 @@
 
     void writeToCurrentClassFragment(const std::string& str)
     {
-        writeTabsToCurrentFragment();
+        writeTabsToCurrentClassFragment();
         m_currentFragment += str;
     }
 
     void writeToCurrentClassFragment(const char* str)
     {
-        writeTabsToCurrentFragment();
+        writeTabsToCurrentClassFragment();
         m_currentFragment += str;
     }
+
+    void writeTabsToFile() 
+    {
+        if (m_indentationLevels > 0)
+        {
+            for (int i = 0; i < m_indentationLevels; i++)
+            {
+                Printf(m_fOutputFile, "\t");
+            }
+        }
+    }
     
     void writeToFile(String* str, bool bDelete = true)
     {
-        writeTabs();
+        writeTabsToFile();
         Printf(m_fOutputFile, "%s", str);
         if (bDelete)
             Delete(str);
@@ -221,13 +339,13 @@
 
     void writeToFile(const std::string& str)
     {
-        writeTabs();
+        writeTabsToFile();
         Printf(m_fOutputFile, str.c_str());
     }
 
     void writeToFile(const char* str)
     {
-        writeTabs();
+        writeTabsToFile();
         Printf(m_fOutputFile, str);
     }
 
@@ -248,7 +366,9 @@
     virtual int classHandler(Node* n)
     {
         m_classMemberExportCalls.clear();
+        m_currentClassSetupFragment = std::string();
         m_currentFragment = std::string();
+        m_currentInheritFragment = std::string();
         m_currentExportFragment = std::string();
         m_currentClassName = NewString(Getattr(n,"sym:name"));
 
@@ -261,16 +381,27 @@
 
             std::string proxyClsName;
             setProxyClassName(m_currentClassName, proxyClsName);
+            
+            std::string fwdDecl = "class ";
+            fwdDecl += proxyClsName;
+            fwdDecl += ";";
+            m_classFwdDecls.push_back(fwdDecl);
+
             std::string clsHead = "class "; 
             clsHead += proxyClsName;
             clsHead += " : node::ObjectWrap\n";
             
             //Export call
             m_currentExportFragment += proxyClsName;
-            m_currentExportFragment += "::Export(";
+            m_currentExportFragment += "_Export(";
             m_currentExportFragment += EXPORTS_VAR;
             m_currentExportFragment += ");";
 
+            m_currentInheritFragment += proxyClsName;
+            m_currentInheritFragment += "_ApplyInheritanceChain(";
+            m_currentInheritFragment += EXPORTS_VAR;
+            m_currentInheritFragment += ");";
+
             //Unmanaged pointer member
             writeToCurrentClassFragment(clsHead);
             writeToCurrentClassFragment("{\n");
@@ -345,7 +476,7 @@
             //Proxy Constructor
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& args) {\n", CLASS_PROXY_CTOR_NAME));
+                writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", CLASS_PROXY_CTOR_NAME, ARGS_VAR));
                 {
                     Indenter ind2(m_indentationLevels);
                     writeToCurrentClassFragment("//TODO: Parse arguments and determine which actual native constructor to invoke\n");
@@ -357,12 +488,12 @@
             //node/v8 export function
             {
                 Indenter ind(m_indentationLevels);
-                writeToCurrentClassFragment(NewStringf("static void Export(v8::Handle<v8::Object> %s)\n", EXPORTS_VAR));
-                writeToCurrentClassFragment("{\n");
+                writeToCurrentClassSetupFragment(NewStringf("static void %s_Export(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
+                writeToCurrentClassSetupFragment("{\n");
                 {
                     Indenter ind2(m_indentationLevels);
-                    writeToCurrentClassFragment(NewStringf("v8::Local<v8::FunctionTemplate> %s = v8::FunctionTemplate::New(%s::%s);\n", CLASS_EXPORT_VAR, proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME));
-                    writeToCurrentClassFragment(NewStringf("%s->SetClassName(v8::String::NewSymbol(\"%s\"));\n", CLASS_EXPORT_VAR, m_currentClassName));
+                    writeToCurrentClassSetupFragment(NewStringf("v8::Local<v8::FunctionTemplate> %s = v8::FunctionTemplate::New(%s::%s);\n", CLASS_EXPORT_VAR, proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME));
+                    writeToCurrentClassSetupFragment(NewStringf("%s->SetClassName(v8::String::NewSymbol(\"%s\"));\n", CLASS_EXPORT_VAR, m_currentClassName));
 
                     std::string ctorReg = "v8::Persistent<v8::Function> constructor = v8::Persistent<v8::Function>::New(";
                     ctorReg += CLASS_EXPORT_VAR;
@@ -379,13 +510,25 @@
 
                     for (std::vector<std::string>::iterator it = m_classMemberExportCalls.begin(); it != m_classMemberExportCalls.end(); it++)
                     {
-                        writeToCurrentClassFragment((*it));
-                        writeToCurrentClassFragment("\n");
+                        writeToCurrentClassSetupFragment((*it));
+                        writeToCurrentClassSetupFragment("\n");
                     }
                 }
-                writeToCurrentClassFragment("}\n");
+                writeToCurrentClassSetupFragment("}\n");
             }
 
+            //node/v8 inheritance hook
+            {
+                Indenter ind(m_indentationLevels);
+                writeToCurrentClassSetupFragment(NewStringf("static void %s_ApplyInheritanceChain(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
+                writeToCurrentClassSetupFragment("{\n");
+                {
+                    Indenter ind2(m_indentationLevels);
+                    writeToCurrentClassSetupFragment("//TODO: Apply prototype inheritance chain\n");
+                }
+                writeToCurrentClassSetupFragment("}\n");
+            }
+
             writeToCurrentClassFragment("};");
 
             Delete(m_currentClassName);
@@ -393,6 +536,8 @@
 
             m_classDecls.push_back(m_currentFragment);
             m_classExportCalls.push_back(m_currentExportFragment);
+            m_classInheritCalls.push_back(m_currentInheritFragment);
+            m_classSetupCalls.push_back(m_currentClassSetupFragment);
 
         }
         return SWIG_OK;
@@ -409,73 +554,330 @@
         return SWIG_OK;
     }
 
-    void emitNativeClassMethodCall(Node* n)
-    {
-        //proxy - The wrapped proxy object pointer
-        //wrappedPtr - The native MapGuide object pointer
-        writeToCurrentClassFragment("//TODO: Do your thing\n");
-    }
-
     virtual int memberfunctionHandler(Node* n)
     {
         String* name = Getattr(n, "sym:name");
+        SwigType *retType  = Getattr(n,"type");
+        SwigType *retTypeUnprefixed = SwigType_base(retType);
         String* overloaded_name = Copy(getOverloadedName(n));
         String* overloaded_name_qualified = Swig_name_member(m_currentClassName, overloaded_name);
+        ParmList *parms  = Getattr(n,"parms");
 
         std::string proxyClsName;
         setProxyClassName(m_currentClassName, proxyClsName);
         
-        writeToCurrentClassFragment(NewStringf("//\tMember Function: %s::%s\n", m_currentClassName, overloaded_name));
-        writeToCurrentClassFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& args) {\n", overloaded_name_qualified));
+        bool isMgPointer = !SwigType_issimple(retType);
+        bool isVoid = (Strcmp(retType, "void") == 0);
+
+        m_currentMethodFragment = std::string();
+
+        //Proxy method is encoded as ClassName_SwigQualifiedMethodName
+
+        writeToCurrentMethodFragment(NewStringf("//\tMember Function: %s::%s\n", m_currentClassName, overloaded_name));
+        writeToCurrentMethodFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", overloaded_name_qualified, ARGS_VAR));
         {
             Indenter ind(m_indentationLevels);
+
+            std::string wrappedPtrCall;
+            writeToCurrentMethodFragment(NewStringf("//Return type - %s (pointer? %s)\n", retType, (isMgPointer ? "true" : "false")));
+            
+            if (isVoid)
+            {
+                writeToCurrentMethodFragment("//Function is void and does not return a value\n");
+            }
+            else
+            {
+                if (isMgPointer)
+                {
+                    writeToCurrentMethodFragment(NewStringf("Ptr<%s> %s;\n", retTypeUnprefixed, FUNC_RET_VAR));
+                }
+                else
+                {
+                    writeToCurrentMethodFragment(NewStringf("%s %s;\n", retType, FUNC_RET_VAR));
+                }
+            }
+
+            if (!isVoid)
+            {
+                wrappedPtrCall += FUNC_RET_VAR;
+                wrappedPtrCall += " = ";
+            }
+            wrappedPtrCall += WRAPPED_PTR_VAR;
+            wrappedPtrCall += "->";
+            
             if (isCurrentClassMgObject())
-                writeToCurrentClassFragment(NewStringf("%s* wrappedPtr = NULL;\n", m_currentClassName));
+                writeToCurrentMethodFragment(NewStringf("%s* %s = NULL;\n", m_currentClassName, WRAPPED_PTR_VAR));
             else
-                writeToCurrentClassFragment(NewStringf("Ptr<%s> wrappedPtr;\n", m_currentClassName));
-            writeToCurrentClassFragment("MG_TRY()\n");
-            writeToCurrentClassFragment(NewStringf("%s* proxy = ObjectWrap::Unwrap<%s>(args.This());\n", proxyClsName.c_str(), proxyClsName.c_str()));
-            writeToCurrentClassFragment("wrappedPtr = proxy->GetInternalPointer();\n");
-            emitNativeClassMethodCall(n);
-            writeToCurrentClassFragment(NewStringf("MG_CATCH(L\"%s::%s\")\n", proxyClsName.c_str(), overloaded_name_qualified));
-            writeToCurrentClassFragment("if (mgException != NULL) {\n");
+                writeToCurrentMethodFragment(NewStringf("Ptr<%s> %s;\n", m_currentClassName, WRAPPED_PTR_VAR));
+            writeToCurrentMethodFragment("MG_TRY()\n");
+            
+            if (parms)
             {
+                std::string funcCallArgsStr;
+                getFunctionArgumentAssignmentCode(parms, funcCallArgsStr);
+                wrappedPtrCall += Char(name);
+                wrappedPtrCall += "(";
+                wrappedPtrCall += funcCallArgsStr;
+                wrappedPtrCall += ");\n";
+            }
+            else
+            {
+                writeToCurrentMethodFragment("//Function has no arguments\n");
+                wrappedPtrCall += Char(name);
+                wrappedPtrCall += "();\n";
+            }
+            
+            writeToCurrentMethodFragment(NewStringf("%s* proxy = node::ObjectWrap::Unwrap<%s>(%s.This());\n", proxyClsName.c_str(), proxyClsName.c_str(), ARGS_VAR));
+            writeToCurrentMethodFragment(NewStringf("%s = proxy->GetInternalPointer();\n", WRAPPED_PTR_VAR));
+            
+            //Here's the actual call
+            writeToCurrentMethodFragment("//Do your thing\n");
+            writeToCurrentMethodFragment(wrappedPtrCall);
+            writeToCurrentMethodFragment("\n");
+
+            writeToCurrentMethodFragment(NewStringf("MG_CATCH(L\"%s::%s\")\n", proxyClsName.c_str(), overloaded_name_qualified));
+            writeToCurrentMethodFragment("if (mgException != NULL)\n");
+            writeToCurrentMethodFragment("{\n");
+            {
                 Indenter ind2(m_indentationLevels);
-                writeToCurrentClassFragment("//NOTE: Unlike previous iterations of the MapGuide API, MgException::GetDetails() finally gives us *everything*\n");
-                writeToCurrentClassFragment("STRING details = mgException->GetDetails();\n");
-                writeToCurrentClassFragment("std::string mbDetails = MgUtil::WideCharToMultiByte(details);\n");
-                writeToCurrentClassFragment("v8::Local<v8::Value> v8ex = v8::Exception::Error(v8::String::New(mbDetails.c_str()));\n");
-                writeToCurrentClassFragment("//Release our MgException before throwing the v8 one\n");
-                writeToCurrentClassFragment("mgException = NULL;\n");
+                writeToCurrentMethodFragment("//NOTE: Unlike previous iterations of the MapGuide API, MgException::GetDetails() finally gives us *everything*\n");
+                writeToCurrentMethodFragment("STRING details = mgException->GetDetails();\n");
+                writeToCurrentMethodFragment("std::string mbDetails = MgUtil::WideCharToMultiByte(details);\n");
+                writeToCurrentMethodFragment("v8::Local<v8::Value> v8ex = v8::Exception::Error(v8::String::New(mbDetails.c_str()));\n");
+                writeToCurrentMethodFragment("//Release our MgException before throwing the v8 one\n");
+                writeToCurrentMethodFragment("mgException = NULL;\n");
                 if (isCurrentClassMgObject())
-                    writeToCurrentClassFragment("if (wrappedPtr) { ((MgDisposable*)wrappedPtr)->Release(); wrappedPtr = NULL; }\n");
-                writeToCurrentClassFragment("return v8::ThrowException(v8ex);\n");
+                    writeToCurrentMethodFragment(NewStringf("if (%s) { ((MgDisposable*)%s)->Release(); %s = NULL; }\n", WRAPPED_PTR_VAR, WRAPPED_PTR_VAR, WRAPPED_PTR_VAR));
+                writeToCurrentMethodFragment("return v8::ThrowException(v8ex);\n");
             }
-            writeToCurrentClassFragment("}\n");
+            writeToCurrentMethodFragment("}\n");
             if (isCurrentClassMgObject())
-                writeToCurrentClassFragment("if (wrappedPtr) { ((MgDisposable*)wrappedPtr)->Release(); wrappedPtr = NULL; }\n");
-            //writeToCurrentClassFragment("v8::HandleScope scope;\n");
-            //writeToCurrentClassFragment("return scope.Close();\n");
-            writeToCurrentClassFragment("return v8::Undefined();\n");
+                writeToCurrentMethodFragment(NewStringf("if (%s) { ((MgDisposable*)%s)->Release(); %s = NULL; }\n", WRAPPED_PTR_VAR, WRAPPED_PTR_VAR, WRAPPED_PTR_VAR));
+            //writeToCurrentMethodFragment("v8::HandleScope scope;\n");
+            //writeToCurrentMethodFragment("return scope.Close();\n");
+
+            writeToCurrentMethodFragment("\n");
+            writeToCurrentMethodFragment("//Return value to javascript\n");
+            if (isVoid)
+            {
+                writeToCurrentMethodFragment("return v8::Undefined();\n");
+            }
+            else
+            {
+                if (isMgPointer) //Stub
+                {
+                    writeToCurrentMethodFragment("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"TODO: Case not handled yet: Returning objects\")));\n");
+                }
+                else
+                {
+                    std::string scopeCloseCall;
+                    std::string preCloseCallCode;
+                    writeToCurrentMethodFragment("v8::HandleScope scope;\n");
+                    if (isMgPointer)
+                    {
+                         
+                    }
+                    else
+                    {
+                        getScopeCloseCallForBasicType(retType, scopeCloseCall, preCloseCallCode);
+                    }
+                    if (!preCloseCallCode.empty())
+                        writeToCurrentMethodFragment(preCloseCallCode);
+                    writeToCurrentMethodFragment(NewStringf("return scope.Close(%s);\n", scopeCloseCall.c_str()));
+                }
+            }
         }
-        writeToCurrentClassFragment("}\n");
+        writeToCurrentMethodFragment("}\n");
 
         String* regCall = NewStringf(
-            "%s->PrototypeTemplate()->Set(v8::String::NewSymbol(\"%s\"), v8::FunctionTemplate::New(%s::%s)->GetFunction());\n",
+            "%s->PrototypeTemplate()->Set(v8::String::NewSymbol(\"%s\"), v8::FunctionTemplate::New(%s)->GetFunction());\n",
             CLASS_EXPORT_VAR,
             overloaded_name,
-            proxyClsName.c_str(),
             overloaded_name_qualified);
         std::string sRegCall;
         sRegCall += Char(regCall);
 
         m_classMemberExportCalls.push_back(sRegCall);
+        m_classMethodDecls.push_back(m_currentMethodFragment);
         
         Delete(regCall);
         Delete(overloaded_name);
         return SWIG_OK;
     }
 
+    void getFunctionArgumentAssignmentCode(ParmList* parms, std::string& nativeMethodArgsString)
+    {
+        int argNo = 0;
+        Parm *p;
+        for (p = parms; p; p = nextSibling(p)) 
+        {
+            SwigType *type  = Getattr(p,"type");
+            SwigType *typeUnprefixed = SwigType_base(type);
+            String   *name  = Getattr(p,"name");
+            //String   *value = Getattr(p,"value");
+
+            bool isArgMgPointer = !SwigType_issimple(type);
+            
+            writeToCurrentMethodFragment("//Argument\n");
+            writeToCurrentMethodFragment(NewStringf("// Name - %s\n", name));
+            writeToCurrentMethodFragment(NewStringf("// Type - %s\n", type));
+            //writeToCurrentMethodFragment(NewStringf("// Value - %s\n", value));
+            
+            //Before we extract values from v8::Arguments, do basic checks on primitive
+            //types
+            if (isArgMgPointer)
+            {
+                writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsObject()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not an object\")));\n", argNo, (argNo + 1), name, type));
+            }
+            else
+            {
+                //Write definition check
+                writeToCurrentMethodFragment(NewStringf("if (args[%d]->IsUndefined()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is undefined\")));\n", argNo, (argNo + 1), name, type));
+                //Then type check
+                if (Strcmp(type, "BYTE") == 0 ||
+                    Strcmp(type, "INT8") == 0 ||
+                    Strcmp(type, "INT16") == 0 ||
+                    Strcmp(type, "INT32") == 0 ||
+                    Strcmp(type, "STATUS") == 0 ||                    //Huh?
+                    Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
+                    Strcmp(type, "MgSiteInfo::MgPortType") == 0 ||    //Huh? I thought MapGuide API doesn't expose enums!
+                    Strcmp(type, "int") == 0 ||
+                    Strcmp(type, "UINT32") == 0 ||
+                    Strcmp(type, "INT64") == 0 ||
+                    Strcmp(type, "long") == 0 ||
+                    Strcmp(type, "long long") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsInt32()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", argNo, (argNo + 1), name, type));
+                }
+                else if (Strcmp(type, "double") == 0 ||
+                         Strcmp(type, "float") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsNumber()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", argNo, (argNo + 1), name, type));
+                }
+                else if (Strcmp(type, "STRINGPARAM") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsString()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a string\")));\n", argNo, (argNo + 1), name, type));
+                }
+                else if (Strcmp(type, "bool") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsBoolean()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a boolean\")));\n", argNo, (argNo + 1), name, type));
+                }
+            }
+
+            if (isArgMgPointer)
+            {
+                std::string proxyClsName;
+                setProxyClassName(typeUnprefixed, proxyClsName);
+                writeToCurrentMethodFragment(NewStringf("Ptr<%s> arg%d = NULL;\n", typeUnprefixed, argNo));
+                writeToCurrentMethodFragment(NewStringf("%s* proxyArg%d = NULL;\n", proxyClsName.c_str(), argNo));
+                writeToCurrentMethodFragment(NewStringf("if (!args[%d]->IsUndefined())\n", argNo));
+                writeToCurrentMethodFragment("{\n");
+                {
+                    Indenter ind(m_indentationLevels);
+                    writeToCurrentMethodFragment(NewStringf("proxyArg%d = node::ObjectWrap::Unwrap<%s>(args[%d]->ToObject());\n", argNo, proxyClsName.c_str(), argNo));
+                    writeToCurrentMethodFragment(NewStringf("arg%d = proxyArg%d->GetInternalPointer();\n", argNo, argNo));
+                }
+                writeToCurrentMethodFragment("}\n");
+            }
+            else
+            {
+                //Then type check
+                if (Strcmp(type, "BYTE") == 0 ||
+                    Strcmp(type, "INT8") == 0 ||
+                    Strcmp(type, "INT16") == 0 ||
+                    Strcmp(type, "INT32") == 0 ||
+                    Strcmp(type, "STATUS") == 0 ||                    //Huh?
+                    Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
+                    Strcmp(type, "MgSiteInfo::MgPortType") == 0 ||    //Huh? I thought MapGuide API doesn't expose enums!
+                    Strcmp(type, "int") == 0 ||
+                    Strcmp(type, "UINT32") == 0 ||
+                    Strcmp(type, "INT64") == 0 ||
+                    Strcmp(type, "long") == 0 ||
+                    Strcmp(type, "long long") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("%s arg%d = (%s)args[%d]->IntegerValue();\n", type, argNo, type, argNo));
+                }
+                else if (Strcmp(type, "double") == 0 ||
+                         Strcmp(type, "float") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("%s arg%d = (%s)args[%d]->NumberValue();\n", type, argNo, type, argNo));
+                }
+                else if (Strcmp(type, "BYTE_ARRAY_OUT") == 0)
+                {
+                    //writeToCurrentMethodFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
+                    //writeToCurrentMethodFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
+                    //writeToCurrentMethodFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
+                    writeToCurrentMethodFragment("//TODO: Case not handled: BYTE_ARRAY_OUT\n");
+                    writeToCurrentMethodFragment(NewStringf("BYTE_ARRAY_OUT arg%d = NULL;\n", argNo));
+                }
+                else if (Strcmp(type, "STRINGPARAM") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("v8::String::Utf8Value mbArg%d(args[%d]->ToString());\n", argNo, argNo));
+                    writeToCurrentMethodFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(std::string(*mbArg%d));\n", argNo, argNo));
+                }
+                else if (Strcmp(type, "bool") == 0)
+                {
+                    writeToCurrentMethodFragment(NewStringf("%s arg%d = args[%d]->BooleanValue();\n", type, argNo, argNo));
+                }
+            }
+            
+            writeToCurrentMethodFragment("\n");
+
+            if (!nativeMethodArgsString.empty())
+                nativeMethodArgsString += ", ";
+
+            nativeMethodArgsString += "arg";
+            
+            std::stringstream out;
+            out << argNo;
+            nativeMethodArgsString += out.str();
+
+            argNo++;
+        }
+    }
+
+    void getScopeCloseCallForBasicType(SwigType* type, std::string& str, std::string& preCloseCallCode)
+    {
+        std::string invocation = "(";
+        invocation += FUNC_RET_VAR;
+        invocation += ")";
+        if (Strcmp(type, "BYTE") == 0 ||
+            Strcmp(type, "INT8") == 0 ||
+            Strcmp(type, "INT16") == 0 ||
+            Strcmp(type, "INT32") == 0 ||
+            Strcmp(type, "STATUS") == 0 ||                    //Huh?
+            Strcmp(type, "MgSiteInfo::MgSiteStatus") == 0 ||  //Huh? I thought MapGuide API doesn't expose enums!
+            Strcmp(type, "int") == 0 ||
+            Strcmp(type, "UINT32") == 0 ||
+            Strcmp(type, "INT64") == 0 ||
+            Strcmp(type, "long") == 0 ||
+            Strcmp(type, "long long") == 0)
+        {
+            str += "v8::Integer::New";
+            str += invocation;
+        }
+        else if (Strcmp(type, "double") == 0 ||
+                 Strcmp(type, "float") == 0)
+        {
+            str += "v8::Number::New";
+            str += invocation;
+        }
+        else if (Strcmp(type, "STRING") == 0)
+        {
+            preCloseCallCode += "std::string mbRetVal = MgUtil::WideCharToMultiByte(";
+            preCloseCallCode += FUNC_RET_VAR;
+            preCloseCallCode += ");\n";
+
+            str += "v8::String::New(";
+            str += "mbRetVal.c_str())";
+        }
+        else if (Strcmp(type, "bool") == 0)
+        {
+            str += "v8::Boolean::New";
+            str += invocation;
+        }
+    }
+
     virtual int membervariableHandler(Node* n)
     {
         String* name = Getattr(n, "sym:name");



More information about the mapguide-commits mailing list