[mapguide-commits] r7632 - sandbox/jng/node/Oem/SWIGEx/Source/Modules
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Jun 19 08:04:24 PDT 2013
Author: jng
Date: 2013-06-19 08:04:24 -0700 (Wed, 19 Jun 2013)
New Revision: 7632
Modified:
sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
Log:
This submission includes:
* Native class constructor overload resolution (currently naively based on argument number count checking)
* Refactor the argument setup into reusable classes
* Implement codegen to return JS wrappers for methods that return MapGuide pointers (doesn't properly handle inheritance yet)
Modified: sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx
===================================================================
--- sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx 2013-06-19 06:59:08 UTC (rev 7631)
+++ sandbox/jng/node/Oem/SWIGEx/Source/Modules/nodejs.cxx 2013-06-19 15:04:24 UTC (rev 7632)
@@ -1,5 +1,6 @@
#include "swigmod.h"
#include <vector>
+#include <map>
#include <sstream>
#define EXPORTS_VAR "exports"
@@ -113,6 +114,47 @@
}
};
+class ArgInfo
+{
+public:
+ ArgInfo(std::string sName, std::string sType, int iOffset, bool bMgPointer)
+ {
+ name = sName;
+ type = sType;
+ isMgPointer = bMgPointer;
+ offset = iOffset;
+ }
+
+ std::string name;
+ std::string type;
+ bool isMgPointer;
+ int offset;
+};
+
+class FunctionCallSetup
+{
+private:
+ std::string m_funcArgsStr;
+ std::vector<ArgInfo> m_args;
+public:
+ FunctionCallSetup()
+ {
+ }
+
+ void setFunctionArgumentString(std::string str) { m_funcArgsStr = str; }
+ const char* getFunctionArgumentString() const { return m_funcArgsStr.c_str(); }
+
+ const std::vector<ArgInfo>& getArgs() const { return m_args; }
+
+ void addArg(std::string sName, std::string sType, int argOffset, bool bMgPointer)
+ {
+ ArgInfo ai(sName, sType, argOffset, bMgPointer);
+ m_args.push_back(ai);
+ }
+};
+
+typedef std::map<std::string, std::string> StringMap;
+
class NODEJS : public Language
{
private:
@@ -120,25 +162,28 @@
String* m_currentClassName;
File* m_fOutputFile;
std::vector<std::string> m_classFwdDecls;
- std::vector<std::string> m_classDecls;
+ StringMap 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;
+ StringMap m_ctorSetupCode;
std::string m_currentFragment;
std::string m_currentExportFragment;
std::string m_currentInheritFragment;
std::string m_currentMethodFragment;
std::string m_currentClassSetupFragment;
int m_indentationLevels;
-
+ bool m_bInsertDebuggingCode;
+
public:
NODEJS() :
m_namespace(NULL),
m_currentClassName(NULL),
m_fOutputFile(NULL),
- m_indentationLevels(0)
+ m_indentationLevels(0),
+ m_bInsertDebuggingCode(true)
{ }
virtual void main(int argc, char* argv[])
@@ -203,24 +248,28 @@
//
Language::top(n);
+
writeToFile("//=====================================\n");
- writeToFile("//Forward declarations\n");
+ writeToFile("//Proxy class definitions\n");
writeToFile("//=====================================\n");
- for (std::vector<std::string>::iterator it = m_classFwdDecls.begin(); it != m_classFwdDecls.end(); it++)
+ for (StringMap::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
{
- std::string call = (*it);
+ std::string call = it->second;
writeToFile(call);
writeToFile("\n");
}
writeToFile("//=====================================\n");
- writeToFile("//Proxy class definitions\n");
+ writeToFile("//v8 persistent Proxy class constructors\n");
writeToFile("//=====================================\n");
- for (std::vector<std::string>::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
+ for (StringMap::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
{
- std::string call = (*it);
- writeToFile(call);
- writeToFile("\n");
+ std::string clsName = it->first;
+ std::string proxyClassName;
+ setProxyClassName(clsName.c_str(), proxyClassName);
+
+ writeToFile(NewStringf("v8::Persistent<v8::FunctionTemplate> %s::constructor_tpl;\n", proxyClassName.c_str()));
+ writeToFile(NewStringf("v8::Persistent<v8::Function> %s::constructor;\n", proxyClassName.c_str()));
}
writeToFile("//=====================================\n");
@@ -234,6 +283,44 @@
}
writeToFile("//=====================================\n");
+ writeToFile("//Proxy class constructor definitions\n");
+ writeToFile("//=====================================\n");
+ for (StringMap::iterator it = m_classDecls.begin(); it != m_classDecls.end(); it++)
+ {
+ std::string clsName = it->first;
+ std::string proxyClsName;
+ setProxyClassName(clsName.c_str(), proxyClsName);
+ writeToFile(NewStringf("v8::Handle<v8::Value> %s::%s(const v8::Arguments& %s)\n", proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME, ARGS_VAR));
+ writeToFile("{\n");
+ if (m_ctorSetupCode.find(clsName) != m_ctorSetupCode.end())
+ {
+ std::string code;
+ {
+ Indenter ind(m_indentationLevels);
+ FragmentWriter codeWriter(m_indentationLevels, code);
+ {
+ std::string mbMethodName;
+ mbMethodName += proxyClsName;
+ mbMethodName += "::";
+ mbMethodName += CLASS_PROXY_CTOR_NAME;
+
+ codeWriter.writeToFragment(NewStringf("Ptr<%s> %s;\n", clsName.c_str(), WRAPPED_PTR_VAR));
+ ExceptionCodeWriter writer(codeWriter, mbMethodName);
+ codeWriter.writeToFragment(m_ctorSetupCode[clsName]);
+ codeWriter.writeToFragment("\n");
+ }
+ codeWriter.writeToFragment(NewStringf("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Could not resolve suitable constructor for %s based on given arguments\")));\n", clsName.c_str()));
+ }
+ writeToFile(code);
+ }
+ else
+ {
+ writeToFile(NewStringf("\treturn v8::ThrowException(v8::Exception::Error(v8::String::New(\"Class %s has no public constructors\")));\n", clsName.c_str()));
+ }
+ writeToFile("}\n\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++)
@@ -286,16 +373,24 @@
Indenter ind(m_indentationLevels);
{
ExceptionCodeWriter writer(cls, proxyFuncName);
- std::string funcCall;
+ FunctionCallSetup setup;
std::string cleanup;
- getFunctionArgumentAssignmentCode(parms, cls, funcCall);
- cls.writeToFragment(NewStringf("%s(%s);\n", name, funcCall.c_str()));
+ getFunctionArgumentAssignmentCode(parms, proxyFuncName, cls, &setup);
+ cls.writeToFragment(NewStringf("%s(%s);\n", name, setup.getFunctionArgumentString()));
}
cls.writeToFragment("return v8::Undefined();\n");
}
cls.writeToFragment("}\n");
m_classMethodDecls.push_back(globalFuncFragment);
+ std::string initExportCode;
+ initExportCode += EXPORTS_VAR;
+ initExportCode += "->Set(v8::String::NewSymbol(\"";
+ initExportCode += Char(name);
+ initExportCode += "\"), v8::FunctionTemplate::New(";
+ initExportCode += proxyFuncName;
+ initExportCode += ")->GetFunction());\n";
+ m_classExportCalls.push_back(initExportCode);
}
else if (Strstr(name, ctorPrefix))
{
@@ -307,6 +402,7 @@
std::string mbName = Char(name);
//Strip the new_ prefix
std::string ctorName = mbName.substr(4);
+
std::string proxyClsName;
setProxyClassName(ctorName.c_str(), proxyClsName);
@@ -314,11 +410,42 @@
{
Indenter ind(m_indentationLevels);
- std::string funcCall;
- getFunctionArgumentAssignmentCode(parms, ctor, funcCall, false);
+ FunctionCallSetup setup;
+ std::string mbOvName;
+ mbOvName += Char(ovName);
+ getFunctionArgumentAssignmentCode(parms, mbOvName, ctor, &setup, false);
ctor.writeToFragment(NewStringf("Ptr<%s> retVal;\n", ctorName.c_str()));
- ctor.writeToFragment(NewStringf("retVal = new %s(%s);\n", ctorName.c_str(), funcCall.c_str()));
+ ctor.writeToFragment(NewStringf("retVal = new %s(%s);\n", ctorName.c_str(), setup.getFunctionArgumentString()));
ctor.writeToFragment("return retVal.Detach();\n");
+
+ std::string ctorFwdCode;
+ const std::vector<ArgInfo>& args = setup.getArgs();
+ //TODO: Naive implementation (arg count). Two constructor overloads with the same number of args will
+ //break this.
+ FragmentWriter ctorCheck(m_indentationLevels, ctorFwdCode);
+ ctorCheck.writeToFragment(NewStringf("//Checking args suitability for method: %s\n", ovName));
+ ctorCheck.writeToFragment(NewStringf("if (%s.Length() == %d)\n", ARGS_VAR, args.size()));
+ ctorCheck.writeToFragment("{\n");
+ {
+ Indenter ind2(m_indentationLevels);
+ ctorCheck.writeToFragment("//Forward ctor call\n");
+ ctorCheck.writeToFragment(NewStringf("%s = %s(args);\n", WRAPPED_PTR_VAR, ovName));
+ ctorCheck.writeToFragment(NewStringf("%s* proxy = new %s(%s);\n", proxyClsName.c_str(), proxyClsName.c_str(), WRAPPED_PTR_VAR));
+ ctorCheck.writeToFragment(NewStringf("proxy->Wrap(%s.This());\n", ARGS_VAR));
+ ctorCheck.writeToFragment(NewStringf("return %s.This();\n", ARGS_VAR));
+ }
+ ctorCheck.writeToFragment("}\n");
+
+ if (m_ctorSetupCode.find(ctorName) == m_ctorSetupCode.end())
+ {
+ m_ctorSetupCode[ctorName] = ctorFwdCode;
+ }
+ else
+ {
+ std::string& code = m_ctorSetupCode[ctorName];
+ code += "\n";
+ code += ctorFwdCode;
+ }
}
ctor.writeToFragment("}\n");
m_classMethodDecls.push_back(ctorFragment);
@@ -332,8 +459,10 @@
{
Indenter ind(m_indentationLevels);
- std::string funcCall;
- getFunctionArgumentAssignmentCode(parms, dtor, funcCall);
+ FunctionCallSetup setup;
+ std::string mbName;
+ mbName += Char(name);
+ getFunctionArgumentAssignmentCode(parms, mbName, dtor, &setup);
//TODO: Should check if node/v8 allows this. This is theoretical atm
//
@@ -412,6 +541,15 @@
m_currentExportFragment = std::string();
m_currentClassName = NewString(Getattr(n,"sym:name"));
+ String* baseClassName = NULL;
+ List *baselist = Getattr(n,"bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ baseClassName = NewString(Getattr(base.item,"name"));
+ } else {
+ baseClassName = NewString("");
+ }
+
FragmentWriter cls(m_indentationLevels, m_currentFragment);
FragmentWriter clsSetup(m_indentationLevels, m_currentClassSetupFragment);
@@ -420,8 +558,11 @@
//Error object.
if (!Strstr(m_currentClassName, "Exception"))
{
- cls.writeToFragment(NewStringf("//Node.js wrapper for class: %s\n", m_currentClassName));
+ cls.writeToFragment(NewStringf("//Node.js wrapper for class: %s (inherits from %s)\n", m_currentClassName, baseClassName));
+ std::string clsName;
+ clsName += Char(m_currentClassName);
+
std::string proxyClsName;
setProxyClassName(m_currentClassName, proxyClsName);
@@ -452,22 +593,12 @@
bool isMgObject = isCurrentClassMgObject();
- if (isMgObject)
- {
- Indenter ind(m_indentationLevels);
- std::string ptrDecl;
- ptrDecl += Char(m_currentClassName);
- ptrDecl += "* m_ptr;\n";
- cls.writeToFragment(ptrDecl);
- }
- else
- {
- Indenter ind(m_indentationLevels);
- std::string ptrDecl = "Ptr<";
- ptrDecl += Char(m_currentClassName);
- ptrDecl += "> m_ptr;\n";
- cls.writeToFragment(ptrDecl);
- }
+ std::string ptrDecl;
+ ptrDecl += "\t";
+ ptrDecl += Char(m_currentClassName);
+ ptrDecl += "* m_ptr;\n";
+ cls.writeToFragment(ptrDecl);
+
cls.writeToFragment("public:\n");
std::string ctorDecl;
ctorDecl += proxyClsName;
@@ -497,13 +628,18 @@
if (isMgObject) //Anything inheriting from MgObject will be MgDisposable
cls.writeToFragment("\t((MgDisposable*)m_ptr)->Release();\n");
else
- cls.writeToFragment("\tm_ptr = NULL;\n");
+ cls.writeToFragment("\tSAFE_RELEASE(m_ptr);\n");
+
+ if (m_bInsertDebuggingCode)
+ cls.writeToFragment(NewStringf("\tprintf(\"Released instance of %s\\n\");\n", clsName.c_str()));
cls.writeToFragment("}\n");
}
//Stubs to be implemented further down
{
Indenter ind(m_indentationLevels);
+ cls.writeToFragment("static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n");
+ cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> CreateJsProxy(%s* ptr);\n", clsName.c_str()));
cls.writeToFragment("static void Export(v8::Handle<v8::Object> exports);\n");
cls.writeToFragment("static void ApplyInheritanceChain(v8::Handle<v8::Object> exports);\n");
}
@@ -517,25 +653,73 @@
//Internal pointer accessor
{
Indenter ind(m_indentationLevels);
+
+ cls.writeToFragment("//Sets the internal pointer. Pointer will be AddRef()'d. Existing pointer (if any) will be Release()'d\n");
if (isMgObject)
+ cls.writeToFragment(NewStringf("void SetInternalPointer(%s* ptr) { if (m_ptr) { ((MgDisposable*)m_ptr)->Release(); }; m_ptr = SAFE_ADDREF((MgDisposable*)m_ptr); }\n", m_currentClassName));
+ else
+ cls.writeToFragment(NewStringf("void SetInternalPointer(%s* ptr) { SAFE_RELEASE(m_ptr); m_ptr = SAFE_ADDREF(m_ptr); }\n", m_currentClassName));
+
+ cls.writeToFragment("//Returns the internal pointer. Pointer is already AddRef()'d and requires release by the caller when done (automatically if assigned to a Ptr<>)\n");
+ if (isMgObject)
cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF((MgDisposable*)m_ptr); }\n", m_currentClassName));
else
- cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF(m_ptr.p); }\n", m_currentClassName));
+ cls.writeToFragment(NewStringf("%s* GetInternalPointer() { return SAFE_ADDREF(m_ptr); }\n", m_currentClassName));
}
+
+ //Function template to apply inheritance
+ {
+ Indenter ind(m_indentationLevels);
+ cls.writeToFragment(NewStringf("static v8::Persistent<v8::FunctionTemplate> constructor_tpl;\n"));
+ }
cls.writeToFragment("private:\n");
//Proxy Constructor
{
Indenter ind(m_indentationLevels);
- cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s) {\n", CLASS_PROXY_CTOR_NAME, ARGS_VAR));
+ cls.writeToFragment(NewStringf("static v8::Handle<v8::Value> %s(const v8::Arguments& %s);\n", CLASS_PROXY_CTOR_NAME, ARGS_VAR));
+ cls.writeToFragment(NewStringf("static v8::Persistent<v8::Function> constructor;\n"));
+ }
+
+ //node/v8 public factory
+ {
+ Indenter ind(m_indentationLevels);
+ clsSetup.writeToFragment(NewStringf("v8::Handle<v8::Value> %s::NewInstance(const v8::Arguments& %s)\n", proxyClsName.c_str(), ARGS_VAR));
+ clsSetup.writeToFragment("{\n");
{
Indenter ind2(m_indentationLevels);
- cls.writeToFragment("//TODO: Parse arguments and determine which actual native constructor to invoke\n");
- cls.writeToFragment("return v8::Undefined();\n");
+ clsSetup.writeToFragment("v8::HandleScope scope;\n");
+ clsSetup.writeToFragment(NewStringf("const unsigned argc = %s.Length();\n", ARGS_VAR));
+ clsSetup.writeToFragment("v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argc];\n");
+ clsSetup.writeToFragment("for (unsigned i = 0; i < argc; i++) {\n");
+ {
+ Indenter ind3(m_indentationLevels);
+ clsSetup.writeToFragment("argv[i] = args[i];\n");
+ }
+ clsSetup.writeToFragment("}\n");
+ clsSetup.writeToFragment("v8::Local<v8::Object> instance = constructor->NewInstance(argc, argv);\n");
+ clsSetup.writeToFragment("delete [] argv;\n");
+ clsSetup.writeToFragment("return scope.Close(instance);\n");
}
- cls.writeToFragment("}\n");
+ clsSetup.writeToFragment("}\n");
}
+ //node/v8 wrap mg pointer factory method
+ {
+ Indenter ind(m_indentationLevels);
+ clsSetup.writeToFragment(NewStringf("v8::Handle<v8::Value> %s::CreateJsProxy(%s* ptr)\n", proxyClsName.c_str(), m_currentClassName));
+ clsSetup.writeToFragment("{\n");
+ {
+ Indenter ind2(m_indentationLevels);
+ clsSetup.writeToFragment("v8::HandleScope scope;\n");
+ clsSetup.writeToFragment("v8::Local<v8::Object> instance = constructor->NewInstance();\n");
+ clsSetup.writeToFragment(NewStringf("%s* proxyVal = new %s(ptr);\n", proxyClsName.c_str(), proxyClsName.c_str()));
+ clsSetup.writeToFragment("proxyVal->Wrap(instance);\n");
+ clsSetup.writeToFragment("return scope.Close(instance);\n");
+ }
+ clsSetup.writeToFragment("}\n");
+ }
+
//node/v8 export function
{
Indenter ind(m_indentationLevels);
@@ -544,11 +728,14 @@
{
Indenter ind2(m_indentationLevels);
clsSetup.writeToFragment(NewStringf("v8::Local<v8::FunctionTemplate> %s = v8::FunctionTemplate::New(%s::%s);\n", CLASS_EXPORT_VAR, proxyClsName.c_str(), CLASS_PROXY_CTOR_NAME));
+ clsSetup.writeToFragment(NewStringf("constructor_tpl = v8::Persistent<v8::FunctionTemplate>::New(%s);\n", CLASS_EXPORT_VAR));
clsSetup.writeToFragment(NewStringf("%s->SetClassName(v8::String::NewSymbol(\"%s\"));\n", CLASS_EXPORT_VAR, m_currentClassName));
clsSetup.writeToFragment("//For the internal pointer\n");
clsSetup.writeToFragment(NewStringf("%s->InstanceTemplate()->SetInternalFieldCount(1);\n", CLASS_EXPORT_VAR));
- std::string ctorReg = "v8::Persistent<v8::Function> constructor = v8::Persistent<v8::Function>::New(";
+ std::string ctorReg;
+ ctorReg += proxyClsName;
+ ctorReg += "::constructor = v8::Persistent<v8::Function>::New(";
ctorReg += CLASS_EXPORT_VAR;
ctorReg += "->GetFunction());\n";
@@ -556,7 +743,9 @@
ctorReg2 += EXPORTS_VAR;
ctorReg2 += "->Set(v8::String::NewSymbol(\"";
ctorReg2 += Char(m_currentClassName);
- ctorReg2 += "\"), constructor);\n";
+ ctorReg2 += "\"), ";
+ ctorReg2 += proxyClsName;
+ ctorReg2 += "::constructor);\n";
m_classMemberExportCalls.push_back(ctorReg);
m_classMemberExportCalls.push_back(ctorReg2);
@@ -570,29 +759,39 @@
clsSetup.writeToFragment("}\n");
}
- //node/v8 inheritance hook
+ //node/v8 export function
{
Indenter ind(m_indentationLevels);
clsSetup.writeToFragment(NewStringf("void %s::ApplyInheritanceChain(v8::Handle<v8::Object> %s)\n", proxyClsName.c_str(), EXPORTS_VAR));
clsSetup.writeToFragment("{\n");
{
Indenter ind2(m_indentationLevels);
- clsSetup.writeToFragment("//TODO: Apply prototype inheritance chain\n");
+
+ if (Strcmp("", baseClassName) == 0)
+ {
+ clsSetup.writeToFragment("//This class has no base class. Nothing to do here\n");
+ }
+ else
+ {
+ std::string mbBaseClass;
+ setProxyClassName(baseClassName, mbBaseClass);
+ clsSetup.writeToFragment(NewStringf("%s::constructor_tpl->Inherit(%s::constructor_tpl);\n", proxyClsName.c_str(), mbBaseClass.c_str()));
+ }
}
clsSetup.writeToFragment("}\n");
}
-
cls.writeToFragment("};");
Delete(m_currentClassName);
m_currentClassName = NULL;
- m_classDecls.push_back(m_currentFragment);
+ m_classDecls[clsName] = m_currentFragment;
m_classExportCalls.push_back(m_currentExportFragment);
m_classInheritCalls.push_back(m_currentInheritFragment);
m_classSetupCalls.push_back(m_currentClassSetupFragment);
}
+ Delete(baseClassName);
return SWIG_OK;
}
@@ -673,11 +872,13 @@
Indenter ind2(m_indentationLevels);
if (parms)
{
- std::string funcCallArgsStr;
- getFunctionArgumentAssignmentCode(parms, meth, funcCallArgsStr);
+ FunctionCallSetup setup;
+ std::string mbQName;
+ mbQName += Char(overloaded_name_qualified);
+ getFunctionArgumentAssignmentCode(parms, mbQName, meth, &setup);
wrappedPtrCall += Char(name);
wrappedPtrCall += "(";
- wrappedPtrCall += funcCallArgsStr;
+ wrappedPtrCall += setup.getFunctionArgumentString();
wrappedPtrCall += ");\n";
}
else
@@ -712,7 +913,9 @@
{
if (isMgPointer) //Stub
{
- meth.writeToFragment("return v8::ThrowException(v8::Exception::Error(v8::String::New(\"TODO: Case not handled yet: Returning objects\")));\n");
+ meth.writeToFragment("v8::HandleScope scope;\n");
+ meth.writeToFragment(NewStringf("v8::Handle<v8::Value> instance = Proxy%s::CreateJsProxy(%s);\n", retTypeUnprefixed, FUNC_RET_VAR));
+ meth.writeToFragment("return scope.Close(instance);\n");
}
else
{
@@ -751,159 +954,252 @@
return SWIG_OK;
}
- void getFunctionArgumentAssignmentCode(ParmList* parms, FragmentWriter& frag, std::string& nativeMethodArgsString, bool bThrowV8Exceptions = true)
+ void writeArgumentCheckFragment(FragmentWriter& frag, std::string& callingMethodName, String* name, SwigType* type, int argNo, bool isArgMgPointer, bool bThrowV8Exceptions = true)
{
- int argNo = 0;
- Parm *p;
- for (p = parms; p; p = nextSibling(p))
+ if (isArgMgPointer)
{
- 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);
-
- frag.writeToFragment("//Argument\n");
- frag.writeToFragment(NewStringf("// Name - %s\n", name));
- frag.writeToFragment(NewStringf("// Type - %s\n", type));
- //frag.writeToFragment(NewStringf("// Value - %s\n", value));
-
- //Before we extract values from v8::Arguments, do basic checks on the parameters
- if (isArgMgPointer)
+ if (bThrowV8Exceptions)
{
- if (bThrowV8Exceptions)
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not an object\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
- else
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not an object\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
}
else
{
- //Write definition check
- if (bThrowV8Exceptions)
- frag.writeToFragment(NewStringf("if (%s[%d]->IsUndefined()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is undefined\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
- else
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsUndefined()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
- //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)
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsObject())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
{
- if (bThrowV8Exceptions)
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
- else
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment("MgStringCollection exArgs;\n");
+ frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not an object\");\n", (argNo + 1), name, type));
+ frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
}
- else if (Strcmp(type, "double") == 0 ||
- Strcmp(type, "float") == 0)
+ frag.writeToFragment("}\n");
+ }
+ }
+ else
+ {
+ //Write definition check
+ if (bThrowV8Exceptions)
+ {
+ frag.writeToFragment(NewStringf("if (%s[%d]->IsUndefined()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is undefined\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
+ }
+ else
+ {
+ frag.writeToFragment(NewStringf("if (%s[%d]->IsUndefined())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
{
- if (bThrowV8Exceptions)
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
- else
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment("MgStringCollection exArgs;\n");
+ frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is undefined\");\n", (argNo + 1), name, type));
+ frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
}
- else if (Strcmp(type, "STRINGPARAM") == 0)
+ frag.writeToFragment("}\n");
+ }
+ //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)
+ {
+ if (bThrowV8Exceptions)
{
- if (bThrowV8Exceptions)
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsString()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a string\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
- else
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsString()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
}
- else if (Strcmp(type, "bool") == 0)
+ else
{
- if (bThrowV8Exceptions)
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a boolean\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
- else
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean()) throw new MgInvalidArgumentException(L\"\", __LINE__, __WFILE__, NULL, L\"\", NULL);\n", ARGS_VAR, argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsInt32())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
+ {
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment("MgStringCollection exArgs;\n");
+ frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a number\");\n", (argNo + 1), name, type));
+ frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+ }
+ frag.writeToFragment("}\n");
}
}
-
- bool bIsMgObject = (Strcmp(typeUnprefixed, "MgObject") == 0);
-
- if (isArgMgPointer)
+ else if (Strcmp(type, "double") == 0 ||
+ Strcmp(type, "float") == 0)
{
- std::string proxyClsName;
- setProxyClassName(typeUnprefixed, proxyClsName);
- if (bIsMgObject)
+ if (bThrowV8Exceptions)
{
- frag.writeToFragment(NewStringf("Ptr<MgDisposable> arg%d = NULL;\n", argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a number\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
}
else
{
- frag.writeToFragment(NewStringf("Ptr<%s> arg%d = NULL;\n", typeUnprefixed, argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsNumber())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
+ {
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment("MgStringCollection exArgs;\n");
+ frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a number\");\n", (argNo + 1), name, type));
+ frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+ }
+ frag.writeToFragment("}\n");
}
- frag.writeToFragment(NewStringf("%s* proxyArg%d = NULL;\n", proxyClsName.c_str(), argNo));
- frag.writeToFragment(NewStringf("if (!%s[%d]->IsUndefined())\n", ARGS_VAR, argNo));
- frag.writeToFragment("{\n");
- {
- Indenter ind(m_indentationLevels);
- frag.writeToFragment(NewStringf("proxyArg%d = node::ObjectWrap::Unwrap<%s>(%s[%d]->ToObject());\n", argNo, proxyClsName.c_str(), ARGS_VAR, argNo));
- if (bIsMgObject)
- frag.writeToFragment(NewStringf("arg%d = (MgDisposable*)proxyArg%d->GetInternalPointer();\n", argNo, argNo));
- else
- frag.writeToFragment(NewStringf("arg%d = proxyArg%d->GetInternalPointer();\n", argNo, argNo));
- }
- frag.writeToFragment("}\n");
}
- else
+ else if (Strcmp(type, "STRINGPARAM") == 0)
{
- //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)
+ if (bThrowV8Exceptions)
{
- frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->IntegerValue();\n", type, argNo, type, ARGS_VAR, argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsString()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a string\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
}
- else if (Strcmp(type, "double") == 0 ||
- Strcmp(type, "float") == 0)
+ else
{
- frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->NumberValue();\n", type, argNo, type, ARGS_VAR, argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsString())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
+ {
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment("MgStringCollection exArgs;\n");
+ frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a string\");\n", (argNo + 1), name, type));
+ frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+ }
+ frag.writeToFragment("}\n");
}
- else if (Strcmp(type, "BYTE_ARRAY_OUT") == 0)
+ }
+ else if (Strcmp(type, "bool") == 0)
+ {
+ if (bThrowV8Exceptions)
{
- //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
- //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
- //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
- frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_OUT\n");
- frag.writeToFragment(NewStringf("BYTE_ARRAY_OUT arg%d = NULL;\n", argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean()) return v8::ThrowException(v8::Exception::Error(v8::String::New(\"Argument %d (%s: %s) is not a boolean\")));\n", ARGS_VAR, argNo, (argNo + 1), name, type));
}
- else if (Strcmp(type, "BYTE_ARRAY_IN") == 0)
+ else
{
- //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
- //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
- //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
- frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_IN\n");
- frag.writeToFragment(NewStringf("BYTE_ARRAY_IN arg%d = NULL;\n", argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsBoolean())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
+ {
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment("MgStringCollection exArgs;\n");
+ frag.writeToFragment(NewStringf("exArgs.Add(L\"Argument %d (%s: %s) is not a boolean\");\n", (argNo + 1), name, type));
+ frag.writeToFragment(NewStringf("throw new MgInvalidArgumentException(L\"%s\", __LINE__, __WFILE__, NULL, L\"MgFormatInnerExceptionMessage\", &exArgs);\n", callingMethodName.c_str()));
+ }
+ frag.writeToFragment("}\n");
}
- else if (Strcmp(type, "STRINGPARAM") == 0)
- {
- frag.writeToFragment(NewStringf("v8::String::Utf8Value mbArg%d(%s[%d]->ToString());\n", argNo, ARGS_VAR, argNo));
- frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(std::string(*mbArg%d));\n", argNo, argNo));
- }
- else if (Strcmp(type, "bool") == 0)
- {
- frag.writeToFragment(NewStringf("%s arg%d = %s[%d]->BooleanValue();\n", type, argNo, ARGS_VAR, argNo));
- }
}
+ }
+ }
+
+ void writeArgumentAssignmentCode(FragmentWriter& frag, SwigType* type, SwigType* typeUnprefixed, String* name, int argNo, bool isArgMgPointer, bool bIsMgObject)
+ {
+ if (isArgMgPointer)
+ {
+ std::string proxyClsName;
+ setProxyClassName(typeUnprefixed, proxyClsName);
+ if (bIsMgObject)
+ {
+ frag.writeToFragment(NewStringf("Ptr<MgDisposable> arg%d = NULL;\n", argNo));
+ }
+ else
+ {
+ frag.writeToFragment(NewStringf("Ptr<%s> arg%d = NULL;\n", typeUnprefixed, argNo));
+ }
+ frag.writeToFragment(NewStringf("%s* proxyArg%d = NULL;\n", proxyClsName.c_str(), argNo));
+ frag.writeToFragment(NewStringf("if (!%s[%d]->IsUndefined())\n", ARGS_VAR, argNo));
+ frag.writeToFragment("{\n");
+ {
+ Indenter ind(m_indentationLevels);
+ frag.writeToFragment(NewStringf("proxyArg%d = node::ObjectWrap::Unwrap<%s>(%s[%d]->ToObject());\n", argNo, proxyClsName.c_str(), ARGS_VAR, argNo));
+ if (bIsMgObject)
+ frag.writeToFragment(NewStringf("arg%d = (MgDisposable*)proxyArg%d->GetInternalPointer();\n", argNo, argNo));
+ else
+ frag.writeToFragment(NewStringf("arg%d = proxyArg%d->GetInternalPointer();\n", argNo, argNo));
+ }
+ frag.writeToFragment("}\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)
+ {
+ frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->IntegerValue();\n", type, argNo, type, ARGS_VAR, argNo));
+ }
+ else if (Strcmp(type, "double") == 0 ||
+ Strcmp(type, "float") == 0)
+ {
+ frag.writeToFragment(NewStringf("%s arg%d = (%s)%s[%d]->NumberValue();\n", type, argNo, type, ARGS_VAR, argNo));
+ }
+ else if (Strcmp(type, "BYTE_ARRAY_OUT") == 0)
+ {
+ //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
+ //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
+ //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
+ frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_OUT\n");
+ frag.writeToFragment(NewStringf("BYTE_ARRAY_OUT arg%d = NULL;\n", argNo));
+ }
+ else if (Strcmp(type, "BYTE_ARRAY_IN") == 0)
+ {
+ //frag.writeToFragment(NewStringf("std::string str%d = args[%d]->ToString();\n", argNo, argNo));
+ //frag.writeToFragment(NewStringf("Ptr<MgByte> bytes%d = new MgByte((BYTE_ARRAY_IN)str%d);\n", argNo, argNo));
+ //frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(args[%d]->ToString());\n", argNo, argNo));
+ frag.writeToFragment("//TODO: Case not handled: BYTE_ARRAY_IN\n");
+ frag.writeToFragment(NewStringf("BYTE_ARRAY_IN arg%d = NULL;\n", argNo));
+ }
+ else if (Strcmp(type, "STRINGPARAM") == 0)
+ {
+ frag.writeToFragment(NewStringf("v8::String::Utf8Value mbArg%d(%s[%d]->ToString());\n", argNo, ARGS_VAR, argNo));
+ frag.writeToFragment(NewStringf("STRING arg%d = MgUtil::MultiByteToWideChar(std::string(*mbArg%d));\n", argNo, argNo));
+ }
+ else if (Strcmp(type, "bool") == 0)
+ {
+ frag.writeToFragment(NewStringf("%s arg%d = %s[%d]->BooleanValue();\n", type, argNo, ARGS_VAR, argNo));
+ }
+ }
+ }
+
+ void getFunctionArgumentAssignmentCode(ParmList* parms, std::string& callingMethodName, FragmentWriter& frag, FunctionCallSetup* setup, bool bThrowV8Exceptions = true)
+ {
+ 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);
+ std::string sName;
+ std::string sType;
+ if (isArgMgPointer)
+ sType += Char(typeUnprefixed);
+ else
+ sType += Char(type);
+ if (name)
+ sName += Char(name);
+
+ setup->addArg(sName, sType, argNo, isArgMgPointer);
+ frag.writeToFragment("//Argument\n");
+ frag.writeToFragment(NewStringf("// Name - %s\n", name));
+ frag.writeToFragment(NewStringf("// Type - %s\n", type));
+ //frag.writeToFragment(NewStringf("// Value - %s\n", value));
+
+ //Before we extract values from v8::Arguments, do basic checks on the parameters
+ writeArgumentCheckFragment(frag, callingMethodName, name, type, argNo, isArgMgPointer, bThrowV8Exceptions);
+
+ bool bIsMgObject = (Strcmp(typeUnprefixed, "MgObject") == 0);
+
+ writeArgumentAssignmentCode(frag, type, typeUnprefixed, name, argNo, isArgMgPointer, bIsMgObject);
+
frag.writeToFragment("\n");
if (!nativeMethodArgsString.empty())
@@ -915,8 +1211,10 @@
out << argNo;
nativeMethodArgsString += out.str();
+ Delete(name);
argNo++;
}
+ setup->setFunctionArgumentString(nativeMethodArgsString);
}
void getScopeCloseCallForBasicType(SwigType* type, std::string& str, std::string& preCloseCallCode)
More information about the mapguide-commits
mailing list