diff options
author | Mark Spruiell <mes@zeroc.com> | 2017-09-04 14:40:47 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2017-09-04 14:40:47 -0700 |
commit | cdfd2cbb48cccc460541d21f604834975fe05720 (patch) | |
tree | 6e1277a7ecbe091098ae4e2c8e3c87c44799f7ad | |
parent | Fix PHP build warnings (diff) | |
download | ice-cdfd2cbb48cccc460541d21f604834975fe05720.tar.bz2 ice-cdfd2cbb48cccc460541d21f604834975fe05720.tar.xz ice-cdfd2cbb48cccc460541d21f604834975fe05720.zip |
Initial commit of MATLAB prototype
61 files changed, 13618 insertions, 20 deletions
diff --git a/cpp/msbuild/ice.v120.sln b/cpp/msbuild/ice.v120.sln index 7bc262fd716..3e71b6c7a3d 100644 --- a/cpp/msbuild/ice.v120.sln +++ b/cpp/msbuild/ice.v120.sln @@ -35,6 +35,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2js", "..\src\slice2js {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2matlab", "..\src\slice2matlab\msbuild\slice2matlab.vcxproj", "{FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}" + ProjectSection(ProjectDependencies) = postProject + {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2php", "..\src\slice2php\msbuild\slice2php.vcxproj", "{55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}" ProjectSection(ProjectDependencies) = postProject {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} @@ -292,6 +297,14 @@ Global {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|Win32.Build.0 = Release|Win32 {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|x64.ActiveCfg = Release|x64 {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|x64.Build.0 = Release|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|Win32.ActiveCfg = Debug|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|Win32.Build.0 = Debug|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|x64.ActiveCfg = Debug|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|x64.Build.0 = Debug|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|Win32.ActiveCfg = Release|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|Win32.Build.0 = Release|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|x64.ActiveCfg = Release|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|x64.Build.0 = Release|x64 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|Win32.ActiveCfg = Debug|Win32 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|Win32.Build.0 = Debug|Win32 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/cpp/msbuild/ice.v140.sln b/cpp/msbuild/ice.v140.sln index b860db8ea68..09e620ae497 100644 --- a/cpp/msbuild/ice.v140.sln +++ b/cpp/msbuild/ice.v140.sln @@ -35,6 +35,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2js", "..\src\slice2js {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2matlab", "..\src\slice2matlab\msbuild\slice2matlab.vcxproj", "{FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}" + ProjectSection(ProjectDependencies) = postProject + {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2php", "..\src\slice2php\msbuild\slice2php.vcxproj", "{55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}" ProjectSection(ProjectDependencies) = postProject {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} @@ -346,6 +351,14 @@ Global {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|Win32.Build.0 = Release|Win32 {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|x64.ActiveCfg = Release|x64 {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|x64.Build.0 = Release|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|Win32.ActiveCfg = Debug|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|Win32.Build.0 = Debug|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|x64.ActiveCfg = Debug|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|x64.Build.0 = Debug|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|Win32.ActiveCfg = Release|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|Win32.Build.0 = Release|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|x64.ActiveCfg = Release|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|x64.Build.0 = Release|x64 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|Win32.ActiveCfg = Debug|Win32 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|Win32.Build.0 = Debug|Win32 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|x64.ActiveCfg = Debug|x64 @@ -694,6 +707,7 @@ Global {B8E063CB-1481-42CA-92F3-E96770EDD70E} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {A503D0D4-22BB-4BDB-B996-862D14DA3349} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {8DF85304-2A53-4C36-804F-5C6FA2F75ACF} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {ACAF39D3-B4BD-426B-98DE-D95944B0D3F6} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {3AB9772C-6113-4F1C-90FB-5368E7486C11} = {F48CC091-6F26-4EC8-A2FB-485975E7C908} diff --git a/cpp/msbuild/ice.v141.sln b/cpp/msbuild/ice.v141.sln index 33079688681..c856ad5fb02 100644 --- a/cpp/msbuild/ice.v141.sln +++ b/cpp/msbuild/ice.v141.sln @@ -35,6 +35,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2js", "..\src\slice2js {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2matlab", "..\src\slice2matlab\msbuild\slice2matlab.vcxproj", "{FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}" + ProjectSection(ProjectDependencies) = postProject + {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slice2php", "..\src\slice2php\msbuild\slice2php.vcxproj", "{55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}" ProjectSection(ProjectDependencies) = postProject {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} = {57CD6AC2-0C9D-4648-9E9D-5DF60C90F18A} @@ -336,6 +341,14 @@ Global {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|Win32.Build.0 = Release|Win32 {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|x64.ActiveCfg = Release|x64 {8DF85304-2A53-4C36-804F-5C6FA2F75ACF}.Release|x64.Build.0 = Release|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|Win32.ActiveCfg = Debug|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|Win32.Build.0 = Debug|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|x64.ActiveCfg = Debug|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Debug|x64.Build.0 = Debug|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|Win32.ActiveCfg = Release|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|Win32.Build.0 = Release|Win32 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|x64.ActiveCfg = Release|x64 + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}.Release|x64.Build.0 = Release|x64 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|Win32.ActiveCfg = Debug|Win32 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|Win32.Build.0 = Debug|Win32 {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6}.Debug|x64.ActiveCfg = Debug|x64 @@ -668,6 +681,7 @@ Global {B8E063CB-1481-42CA-92F3-E96770EDD70E} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {A503D0D4-22BB-4BDB-B996-862D14DA3349} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {8DF85304-2A53-4C36-804F-5C6FA2F75ACF} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} + {FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {55A6E595-EFE4-47B9-957C-E4CFF2E75FD6} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {ACAF39D3-B4BD-426B-98DE-D95944B0D3F6} = {2DC2B270-B7AE-48CF-8FB0-41A55A9747E9} {3AB9772C-6113-4F1C-90FB-5368E7486C11} = {F48CC091-6F26-4EC8-A2FB-485975E7C908} diff --git a/cpp/src/Slice/StringLiteralUtil.cpp b/cpp/src/Slice/StringLiteralUtil.cpp index ce3351f7de1..80c322b4d7f 100644 --- a/cpp/src/Slice/StringLiteralUtil.cpp +++ b/cpp/src/Slice/StringLiteralUtil.cpp @@ -29,9 +29,12 @@ public: StringLiteralGenerator(const string&, const string&, EscapeMode, unsigned char); - string escapeASCIIChar(char) const; - string escapeCodePoint(unsigned int) const; - string flushU8Buffer(vector<unsigned char>&) const; + string escapeASCIIChar(char); + string escapeCodePoint(unsigned int); + string flushU8Buffer(vector<unsigned char>&); + + enum Format { NoFormat, OctalFormat, HexFormat }; + void format(Format); private: @@ -39,6 +42,11 @@ private: const string _printableEscaped; const EscapeMode _escapeMode; const unsigned char _cutOff; + const string _shortUCNPrefix; + const string _octalChars; + const string _hexChars; + + Format _format; // The last format used for an escape. }; StringLiteralGenerator::StringLiteralGenerator(const string& nonPrintableEscaped, @@ -46,19 +54,33 @@ StringLiteralGenerator::StringLiteralGenerator(const string& nonPrintableEscaped EscapeMode escapeMode, unsigned char cutOff) : _nonPrintableEscaped(nonPrintableEscaped), - _printableEscaped(printableEscaped + "\\\""), + _printableEscaped(printableEscaped + "\\"), _escapeMode(escapeMode), - _cutOff(cutOff) + _cutOff(cutOff), + _shortUCNPrefix(escapeMode == Matlab ? "\\x" : "\\u"), + _octalChars("01234567"), + _hexChars("01234567890ABCDEFabcdef"), + _format(NoFormat) { + // + // Double quotes don't need to be escaped in Matlab because the string delimiter is a single quote. + // + if(_escapeMode != Matlab) + { + const_cast<string&>(_printableEscaped) += '"'; + } } string -StringLiteralGenerator::escapeASCIIChar(char c) const +StringLiteralGenerator::escapeASCIIChar(char c) { assert(static_cast<unsigned char>(c) < 128); string result; + Format lastFormat = _format; + _format = NoFormat; + if(_nonPrintableEscaped.find(c) != string::npos) { switch(c) @@ -125,10 +147,51 @@ StringLiteralGenerator::escapeASCIIChar(char c) const result = '\\'; result += c; } + else if(_escapeMode == Matlab && c == '\'') + { + // + // Matlab strings are converted by sprintf(), and sprintf() requires a single quote to be escaped + // with another single quote. + // + result = "''"; + } + else if(_escapeMode == Matlab && c == '%') + { + // + // Matlab strings are converted by sprintf(), and sprintf() requires a percent to be escaped + // with another percent. + // + result = "%%"; + } else if(c >= 32 && c <= 126) { - // Other printable ASCII - result = c; + // + // Other printable ASCII. + // + if(_escapeMode == Matlab) + { + // + // While interpreting an octal or hex escape, the Matlab parser will continue to consume adjacent + // legal characters. If the trailing character after an escaped value could be consumed, we escape it + // as well to terminate the original escape. + // + if((lastFormat == OctalFormat && _octalChars.find(c) != string::npos) || + (lastFormat == HexFormat && _hexChars.find(c) != string::npos)) + { + ostringstream os; + os << "\\" << oct << setfill('0') << setw(3) << static_cast<unsigned int>(c & 0xFF); + result = os.str(); + _format = OctalFormat; + } + else + { + result = c; + } + } + else + { + result = c; + } } else { @@ -137,10 +200,12 @@ StringLiteralGenerator::escapeASCIIChar(char c) const if((static_cast<unsigned char>(c) < _cutOff) || (_escapeMode == Octal)) { os << "\\" << oct << setfill('0') << setw(3) << static_cast<unsigned int>(c & 0xFF); + _format = OctalFormat; } else { - os << "\\u" << hex << setfill('0') << setw(4) << static_cast<unsigned int>(c & 0xFF); + os << _shortUCNPrefix << hex << setfill('0') << setw(4) << static_cast<unsigned int>(c & 0xFF); + _format = HexFormat; } result = os.str(); } @@ -148,7 +213,7 @@ StringLiteralGenerator::escapeASCIIChar(char c) const } string -StringLiteralGenerator::escapeCodePoint(unsigned int codePoint) const +StringLiteralGenerator::escapeCodePoint(unsigned int codePoint) { if(codePoint < 128) { @@ -165,6 +230,7 @@ StringLiteralGenerator::escapeCodePoint(unsigned int codePoint) const { os << "\\" << setfill('0') << setw(3) << oct << static_cast<unsigned int>(*q); } + _format = OctalFormat; return os.str(); } else @@ -176,20 +242,23 @@ StringLiteralGenerator::escapeCodePoint(unsigned int codePoint) const // Output octal escape // os << "\\" << setfill('0') << setw(3) << oct << codePoint; + _format = OctalFormat; } else if(codePoint <= 0xFFFF) { - os << "\\u" << setfill('0') << setw(4) << hex << codePoint; + os << _shortUCNPrefix << setfill('0') << setw(4) << hex << codePoint; + _format = HexFormat; } - else if(_escapeMode == ShortUCN) + else if(_escapeMode == ShortUCN || _escapeMode == Matlab) { // // Convert to surrogate pair // unsigned int highSurrogate = ((codePoint - 0x10000) / 0x400) + 0xD800; unsigned int lowSurrogate = ((codePoint - 0x10000) % 0x400) + 0xDC00; - os << "\\u" << setfill('0') << setw(4) << hex << highSurrogate; - os << "\\u" << setfill('0') << setw(4) << hex << lowSurrogate; + os << _shortUCNPrefix << setfill('0') << setw(4) << hex << highSurrogate; + os << _shortUCNPrefix << setfill('0') << setw(4) << hex << lowSurrogate; + _format = HexFormat; } else if(_escapeMode == EC6UCN) { @@ -204,7 +273,7 @@ StringLiteralGenerator::escapeCodePoint(unsigned int codePoint) const } string -StringLiteralGenerator::flushU8Buffer(vector<unsigned char>& u8buffer) const +StringLiteralGenerator::flushU8Buffer(vector<unsigned char>& u8buffer) { if(u8buffer.empty()) { @@ -224,6 +293,12 @@ StringLiteralGenerator::flushU8Buffer(vector<unsigned char>& u8buffer) const } } +void +StringLiteralGenerator::format(Format f) +{ + _format = f; +} + } string @@ -271,6 +346,7 @@ Slice::toStringLiteral(const string& value, if(c == '\\') { os << "\\\\"; + generator.format(StringLiteralGenerator::NoFormat); } else if(c == 'u' || c == 'U') { @@ -284,11 +360,16 @@ Slice::toStringLiteral(const string& value, // ASCII character that may need to escaped in languages such as Java os << generator.escapeASCIIChar(static_cast<char>(v)); } - else if(escapeMode == UCN || c == 'u') + else if(escapeMode == UCN) { // keep this escape as is os << "\\" << c << codePointStr; } + else if(c == 'u') + { + os << (escapeMode == Matlab ? "\\x" : "\\u") << codePointStr; + generator.format(StringLiteralGenerator::HexFormat); + } else { os << generator.escapeCodePoint(static_cast<unsigned int>(v)); @@ -298,6 +379,7 @@ Slice::toStringLiteral(const string& value, else { // unescaped backslash: escape it! + generator.format(StringLiteralGenerator::NoFormat); os << "\\\\"; os << generator.escapeASCIIChar(c); } diff --git a/cpp/src/Slice/Util.h b/cpp/src/Slice/Util.h index a31536a6ed8..33c52fe5035 100644 --- a/cpp/src/Slice/Util.h +++ b/cpp/src/Slice/Util.h @@ -31,16 +31,17 @@ std::vector<std::string> argvToArgs(int argc, wchar_t* argv[]); std::vector<std::string> argvToArgs(int argc, char* argv[]); #endif -enum EscapeMode { UCN, Octal, ShortUCN, EC6UCN }; +enum EscapeMode { UCN, Octal, ShortUCN, Matlab, EC6UCN }; // Parameters: // const string& value: input string provided by Slice Parser // const string& nonPrintableEscaped: which of \a, \b, \f, \n, \r, \t, \v, \0 (null), \x20 (\s), \x1b (\e) are // escaped in the target language // Warning: don't include \0 if the target language recognizes octal escapes -// const string& printableEscaped: additional printable ASCII characters other than \ and " that need to be escaped +// const string& printableEscaped: additional printable ASCII characters other than \ and the string delimiter +// that need to be escaped // EscapeMode escapeMode: whether we generate both UCNs, octal escape sequences, only short UCNs (\unnnn), -// or ECMAScript 6-style UCNs with \u{...} for astral characters +// Matlab syntax, or ECMAScript 6-style UCNs with \u{...} for astral characters. // unsigned char cutOff: characters < cutOff other than the nonPrintableEscaped are generated as // octal escape sequences, regardless of escapeMode. std::string diff --git a/cpp/src/slice2matlab/Main.cpp b/cpp/src/slice2matlab/Main.cpp new file mode 100644 index 00000000000..26ee9ae092c --- /dev/null +++ b/cpp/src/slice2matlab/Main.cpp @@ -0,0 +1,2993 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/DisableWarnings.h> +#include <IceUtil/CtrlCHandler.h> +#include <IceUtil/IceUtil.h> +#include <IceUtil/InputUtil.h> +#include <IceUtil/Options.h> +#include <IceUtil/OutputUtil.h> +#include <IceUtil/StringUtil.h> +#include <IceUtil/Mutex.h> +#include <IceUtil/MutexPtrLock.h> +#include <IceUtil/ConsoleUtil.h> +#include <IceUtil/FileUtil.h> +#include <Slice/Checksum.h> +#include <Slice/Preprocessor.h> +#include <Slice/FileTracker.h> +#include <Slice/Parser.h> +#include <Slice/Util.h> +#include <cstring> +#include <climits> + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef _WIN32 +# include <direct.h> +#else +# include <unistd.h> +#endif + +using namespace std; +using namespace Slice; +using namespace IceUtilInternal; + +namespace +{ + +string +lowerCase(const string& s) +{ + string result(s); + transform(result.begin(), result.end(), result.begin(), ::tolower); + return result; +} + +string +lookupKwd(const string& name) +{ + // + // Keyword list. *Must* be kept in alphabetical order. + // + static const string keywordList[] = + { + "break", "case", "catch", "classdef", "continue", "else", "elseif", "end", "for", "function", "global", + "if", "otherwise", "parfor", "persistent", "return", "spmd", "switch", "try", "while" + }; + bool found = binary_search(&keywordList[0], + &keywordList[sizeof(keywordList) / sizeof(*keywordList)], + name); + return found ? "slice_" + name : name; +} + +// +// Split a scoped name into its components and return the components as a list of (unscoped) identifiers. +// +vector<string> +splitScopedName(const string& scoped) +{ + assert(scoped[0] == ':'); + vector<string> ids; + string::size_type next = 0; + string::size_type pos; + while((pos = scoped.find("::", next)) != string::npos) + { + pos += 2; + if(pos != scoped.size()) + { + string::size_type endpos = scoped.find("::", pos); + if(endpos != string::npos) + { + ids.push_back(scoped.substr(pos, endpos - pos)); + } + } + next = pos; + } + if(next != scoped.size()) + { + ids.push_back(scoped.substr(next)); + } + else + { + ids.push_back(""); + } + + return ids; +} + +string +fixIdent(const string& ident) +{ + if(ident[0] != ':') + { + return lookupKwd(ident); + } + vector<string> ids = splitScopedName(ident); + transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd)); + stringstream result; + for(vector<string>::const_iterator i = ids.begin(); i != ids.end(); ++i) + { + result << "::" + *i; + } + return result.str(); +} + +string +replace(string s, string patt, string val) +{ + string r = s; + string::size_type pos = r.find(patt); + while(pos != string::npos) + { + r.replace(pos, patt.size(), val); + pos += val.size(); + pos = r.find(patt, pos); + } + return r; +} + +string +scopedToName(const string& scoped) +{ + string str = scoped; + if(str.find("::") == 0) + { + str.erase(0, 2); + } + + str = replace(str, "::", "."); + + return fixIdent(str); +} + +// +// Get the fully-qualified name of the given definition. If a suffix is provided, +// it is prepended to the definition's unqualified name. If the nameSuffix +// is provided, it is appended to the container's name. +// +string +getAbsolute(const ContainedPtr& cont, const string& pfx = std::string(), const string& suffix = std::string()) +{ + return scopedToName(cont->scope() + pfx + cont->name() + suffix); +} + +void +printHeader(IceUtilInternal::Output& out) +{ + static const char* header = + "%{\n" + "**********************************************************************\n" + "\n" + "Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.\n" + "\n" + "This copy of Ice is licensed to you under the terms described in the\n" + "ICE_LICENSE file included in this distribution.\n" + "\n" + "**********************************************************************\n" + "%}\n" + ; + + out << header; + out << "%\n"; + out << "% Ice version " << ICE_STRING_VERSION << "\n"; + out << "%\n"; +} + +string +typeToString(const TypePtr& type) +{ + static const char* builtinTable[] = + { + "uint8", + "logical", + "int16", + "int32", + "int64", + "single", + "double", + "char", + "Ice.Object", + "Ice.ObjectPrx", + "", + "Ice.Value" + }; + + if(!type) + { + return "void"; + } + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + return builtinTable[builtin->kind()]; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { + return getAbsolute(cl); + } + + ProxyPtr proxy = ProxyPtr::dynamicCast(type); + if(proxy) + { + return getAbsolute(proxy->_class(), "", "Prx"); + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + if(dict) + { + return "containers.Map"; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return "???"; + } + + ContainedPtr contained = ContainedPtr::dynamicCast(type); + if(contained) + { + return getAbsolute(contained); + } + + return "???"; +} + +string +dictionaryTypeToString(const TypePtr& type, bool key) +{ + assert(type); + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindBool: + case Builtin::KindByte: + case Builtin::KindShort: + { + // + // containers.Map supports a limited number of key types. + // + return key ? "int32" : typeToString(type); + } + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindString: + { + return typeToString(type); + } + case Builtin::KindFloat: + case Builtin::KindDouble: + { + assert(!key); + return typeToString(type); + } + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + case Builtin::KindValue: + { + assert(!key); + return "any"; + } + default: + { + return "???"; + } + } + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + // + // containers.Map doesn't natively support enumerators as keys but we can work around it using int32. + // + return key ? "int32" : "any"; + } + + return "any"; +} + +bool +declarePropertyType(const TypePtr& type, bool optional) +{ + return !optional && !SequencePtr::dynamicCast(type) && !ProxyPtr::dynamicCast(type) && + !ClassDefPtr::dynamicCast(type); +} + +string +constantValue(const TypePtr& type, const SyntaxTreeBasePtr& valueType, const string& value) +{ + ConstPtr constant = ConstPtr::dynamicCast(valueType); + if(constant) + { + return getAbsolute(constant) + ".value"; + } + else + { + BuiltinPtr bp; + if((bp = BuiltinPtr::dynamicCast(type))) + { + switch(bp->kind()) + { + case Builtin::KindString: + { + return "sprintf('" + toStringLiteral(value, "\a\b\f\n\r\t\v", "", Matlab, 255) + "')"; + } + case Builtin::KindBool: + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + case Builtin::KindValue: + { + return value; + } + + default: + { + return "???"; + } + } + + } + else if(EnumPtr::dynamicCast(type)) + { + EnumeratorPtr e = EnumeratorPtr::dynamicCast(valueType); + assert(e); + return getAbsolute(e); + } + else + { + return value; + } + } +} + +string +defaultValue(const DataMemberPtr& m) +{ + if(m->defaultValueType()) + { + return constantValue(m->type(), m->defaultValueType(), m->defaultValue()); + } + else if(m->optional()) + { + return "[]"; + } + else + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(m->type()); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindString: + return "''"; + case Builtin::KindBool: + return "false"; + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + return "0"; + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + case Builtin::KindValue: + return "[]"; + } + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(m->type()); + if(dict) + { + return "containers.Map('KeyType', '" + typeToString(dict->keyType()) + "', 'ValueType', '" + + typeToString(dict->valueType()) + "')"; + } + + return "[]"; + } +} + +} + +// +// CodeVisitor generates the Matlab mapping for a translation unit. +// +class CodeVisitor : public ParserVisitor +{ +public: + + CodeVisitor(const string&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual bool visitExceptionStart(const ExceptionPtr&); + virtual bool visitStructStart(const StructPtr&); + virtual void visitSequence(const SequencePtr&); + virtual void visitDictionary(const DictionaryPtr&); + virtual void visitEnum(const EnumPtr&); + virtual void visitConst(const ConstPtr&); + +private: + + void openClass(const string&, IceUtilInternal::Output&); + + struct MemberInfo + { + string fixedName; + bool inherited; + DataMemberPtr dataMember; + }; + typedef list<MemberInfo> MemberInfoList; + + // + // Convert an operation mode into a string. + // + string getOperationMode(Slice::Operation::Mode); + + void collectClassMembers(const ClassDefPtr&, MemberInfoList&, bool); + void collectExceptionMembers(const ExceptionPtr&, MemberInfoList&, bool); + + struct ParamInfo + { + string fixedName; + TypePtr type; + bool optional; + int tag; + ParamDeclPtr param; // 0 == return value + }; + typedef list<ParamInfo> ParamInfoList; + + ParamInfoList getInParams(const OperationPtr&); + ParamInfoList getOutParams(const OperationPtr&); + + string getOptionalFormat(const TypePtr&); + string getFormatType(FormatType); + + void marshal(IceUtilInternal::Output&, const string&, const string&, const TypePtr&, bool, int, int&); + void unmarshal(IceUtilInternal::Output&, const string&, const string&, const TypePtr&, bool, int, int&); + + const string _dir; +}; + +// +// CodeVisitor implementation. +// +CodeVisitor::CodeVisitor(const string& dir) : + _dir(dir) +{ +} + +bool +CodeVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + const ClassList bases = p->bases(); + const string self = name == "obj" ? "this" : "obj"; + + if(p->hasMetaData("matlab:internal")) + { + return false; + } + + if(!p->isInterface()) + { + ClassDefPtr base; + if(!bases.empty() && !bases.front()->isInterface()) + { + base = bases.front(); + } + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef " << name; + if(base) + { + out << " < " << getAbsolute(base); + } + else if(!p->isLocal()) + { + out << " < Ice.Value"; + } + + const DataMemberList members = p->dataMembers(); + if(!members.empty()) + { + out.inc(); + out << nl << "properties"; + out.inc(); + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + out << nl << fixIdent((*q)->name()); + if(declarePropertyType((*q)->type(), (*q)->optional())) + { + out << " " << typeToString((*q)->type()); + } + } + out.dec(); + out << nl << "end"; + } + + MemberInfoList allMembers; + collectClassMembers(p, allMembers, false); + + if(!allMembers.empty() || !p->isLocal()) + { + out << nl << "methods"; + out.inc(); + } + + if(!allMembers.empty()) + { + vector<string> allNames; + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + allNames.push_back(q->fixedName); + } + // + // Constructor + // + out << nl << "function " << self << " = " << name << spar << allNames << epar; + out.inc(); + out << nl << "if nargin == 0"; + out.inc(); + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + out << nl << q->fixedName << " = " << defaultValue(q->dataMember) << ';'; + } + out.dec(); + out << nl << "end"; + if(base || !p->isLocal()) + { + out << nl << self << " = " << self << "@" << (base ? getAbsolute(base) : "Ice.Value") << spar; + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(q->inherited) + { + out << q->fixedName; + } + } + out << epar << ';'; + } + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(!q->inherited) + { + out << nl << self << "." << q->fixedName << " = " << q->fixedName << ';'; + } + } + out.dec(); + out << nl << "end"; + } + + if(!p->isLocal()) + { + const DataMemberList optionalMembers = p->orderedOptionalDataMembers(); + + out << nl << "function id = ice_id(obj)"; + out.inc(); + out << nl << "id = obj.ice_staticId();"; + out.dec(); + out << nl << "end"; + out << nl << "function iceWriteImpl_(obj, os)"; + out.inc(); + out << nl << "os.startSlice(obj.ice_staticId(), " << p->compactId() << (!base ? ", true" : ", false") + << ");"; + for(DataMemberList::const_iterator d = members.begin(); d != members.end(); ++d) + { + if(!(*d)->optional()) + { + int idx = 0; + marshal(out, "os", "obj." + fixIdent((*d)->name()), (*d)->type(), false, 0, idx); + } + } + for(DataMemberList::const_iterator d = optionalMembers.begin(); d != optionalMembers.end(); ++d) + { + int idx = 0; + marshal(out, "os", "obj." + fixIdent((*d)->name()), (*d)->type(), true, (*d)->tag(), idx); + } + out << nl << "os.endSlice();"; + if(base) + { + out << nl << "iceWriteImpl_@" << getAbsolute(base) << "(obj);"; + } + out.dec(); + out << nl << "end"; + out << nl << "function obj = iceReadImpl_(obj, is)"; + out.inc(); + out << nl << "is.startSlice();"; + for(DataMemberList::const_iterator d = members.begin(); d != members.end(); ++d) + { + if(!(*d)->optional()) + { + int idx = 0; + unmarshal(out, "is", "obj." + fixIdent((*d)->name()), (*d)->type(), false, 0, idx); + } + } + for(DataMemberList::const_iterator d = optionalMembers.begin(); d != optionalMembers.end(); ++d) + { + int idx = 0; + unmarshal(out, "is", "obj." + fixIdent((*d)->name()), (*d)->type(), true, (*d)->tag(), idx); + } + out << nl << "os.endSlice();"; + if(base) + { + out << nl << "obj = iceReadImpl_@" << getAbsolute(base) << "(obj);"; + } + out.dec(); + out << nl << "end"; + } + + if(!allMembers.empty() || !p->isLocal()) + { + out.dec(); + out << nl << "end"; + } + + if(!p->isLocal()) + { + out << nl << "methods(Static)"; + out.inc(); + out << nl << "function id = ice_staticId()"; + out.inc(); + out << nl << "id = '" << scoped << "';"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out.dec(); + } + + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); + } + else if(!p->isLocal()) + { + // + // Generate proxy class. + // + + IceUtilInternal::Output out; + openClass(scoped + "Prx", out); + + const string prxName = name + "Prx"; + const string abs = getAbsolute(p, "", "Prx"); + + out << nl << "classdef " << prxName << " < "; + if(!bases.empty()) + { + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if(q != bases.begin()) + { + out << " & "; + } + out << getAbsolute(*q, "", "Prx"); + } + } + else + { + out << "Ice.ObjectPrx"; + } + + out.inc(); + + out << nl << "methods"; + out.inc(); + + // + // Constructor. + // + out << nl << "function obj = " << prxName << "(impl)"; + out.inc(); + if(!bases.empty()) + { + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + out << nl << "obj = obj@" << getAbsolute(*q, "", "Prx") << "(impl);"; + } + } + else + { + out << nl << "obj = obj@Ice.ObjectPrx(impl);"; + } + out.dec(); + out << nl << "end"; + + // + // Operations. + // + const OperationList ops = p->operations(); + for(OperationList::const_iterator q = ops.begin(); q != ops.end(); ++q) + { + OperationPtr op = *q; + const ParamInfoList inParams = getInParams(op); + const ParamInfoList outParams = getOutParams(op); + const bool twowayOnly = !outParams.empty(); + + ExceptionList exceptions = op->throws(); + exceptions.sort(); + exceptions.unique(); + + // + // Arrange exceptions into most-derived to least-derived order. If we don't + // do this, a base exception handler can appear before a derived exception + // handler, causing compiler warnings and resulting in the base exception + // being marshaled instead of the derived exception. + // +#if defined(__SUNPRO_CC) + exceptions.sort(Slice::derivedToBaseCompare); +#else + exceptions.sort(Slice::DerivedToBaseCompare()); +#endif + + // + // Ensure no parameter is named "obj". + // + string self = "obj"; + for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) + { + if(r->fixedName == "obj") + { + self = "obj_"; + } + } + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + if(r->fixedName == "obj") + { + self = "obj_"; + } + } + + // + // Synchronous method. + // + out << nl << "function "; + if(outParams.size() > 1) + { + out << "["; + for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) + { + if(r != outParams.begin()) + { + out << ", "; + } + out << r->fixedName; + } + out << "] = "; + } + else if(outParams.size() == 1) + { + out << outParams.begin()->fixedName << " = "; + } + out << fixIdent(op->name()) << spar; + + out << self; + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + out << r->fixedName; + } + out << "varargin"; // For the optional context + out << epar; + out.inc(); + + if(!inParams.empty()) + { + if(op->format() == DefaultFormat) + { + out << nl << "os_ = " << self << ".startWriteParams_();"; + } + else + { + out << nl << "os_ = " << self << ".startWriteParamsWithFormat_(" << getFormatType(op->format()) + << ");"; + } + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + int idx = 0; + marshal(out, "os_", r->fixedName, r->type, r->optional, r->tag, idx); + } + out << nl << self << ".endWriteParams_(os_);"; + } + + out << nl << "[ok_, is_] = " << self << ".invoke_('" << op->name() << "', '" + << getOperationMode(op->sendMode()) << "', " << (twowayOnly ? "true" : "false") + << ", " << (inParams.empty() ? "[]" : "os_") << ", varargin{:});"; + + if(outParams.empty() && exceptions.empty()) + { + out << nl << self << ".checkNoResponse_(ok_, is_);"; + } + else + { + out << nl << "if ok_"; + out.inc(); + if(outParams.empty()) + { + out << nl << "is_.skipEmptyEncapsulation();"; + } + else + { + out << nl << "is_.startEncapsulation();"; + // + // The return value (if any) appears first. We have to unmarshal any out parameters + // before the return value. + // + for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) + { + if(r->param) + { + int idx = 0; + unmarshal(out, "is_", r->fixedName, r->type, r->optional, r->tag, idx); + } + } + // + // Now do the return value if necessary. + // + if(!outParams.begin()->param) + { + ParamInfoList::const_iterator r = outParams.begin(); + int idx = 0; + unmarshal(out, "is_", r->fixedName, r->type, r->optional, r->tag, idx); + } + out << nl << "is_.endEncapsulation();"; + } + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << self << ".throwUserException_" << spar << "is_"; + for(ExceptionList::const_iterator e = exceptions.begin(); e != exceptions.end(); ++e) + { + out << "'" + getAbsolute(*e) + "'"; + } + out << epar << ';'; + out.dec(); + out << nl << "end"; + } + + out.dec(); + out << nl << "end"; + + // + // Asynchronous method. + // + out << nl << "function r_ = " << fixIdent(op->name()) << "Async" << spar; + out << self; + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + out << r->fixedName; + } + out << "varargin"; // For the optional context + out << epar; + out.inc(); + + if(!inParams.empty()) + { + if(op->format() == DefaultFormat) + { + out << nl << "os_ = " << self << ".startWriteParams_();"; + } + else + { + out << nl << "os_ = " << self << ".startWriteParamsWithFormat_(" << getFormatType(op->format()) + << ");"; + } + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + int idx = 0; + marshal(out, "os_", r->fixedName, r->type, r->optional, r->tag, idx); + } + out << nl << self << ".endWriteParams_(os_);"; + } + + if(!outParams.empty() || !exceptions.empty()) + { + out << nl << "function varargout = unmarshal(ok_, is_)"; + out.inc(); + out << nl << "if ok_"; + out.inc(); + if(outParams.empty()) + { + out << nl << "is_.skipEmptyEncapsulation();"; + } + else + { + out << nl << "is_.startEncapsulation();"; + int pos = op->returnType() ? 2 : 1; + // + // The return value (if any) appears first. We have to unmarshal any out parameters + // before the return value. + // + for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) + { + if(r->param) + { + int idx = 0; + unmarshal(out, "is_", r->fixedName, r->type, r->optional, r->tag, idx); + out << nl << "varargout{" << pos++ << "} = " << r->fixedName << ';'; + } + } + // + // Now do the return value if necessary. + // + if(!outParams.begin()->param) + { + ParamInfoList::const_iterator r = outParams.begin(); + int idx = 0; + unmarshal(out, "is_", r->fixedName, r->type, r->optional, r->tag, idx); + out << nl << "varargout{1} = " << r->fixedName << ';'; + } + out << nl << "is_.endEncapsulation();"; + } + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << self << ".throwUserException_" << spar << "is_"; + for(ExceptionList::const_iterator e = exceptions.begin(); e != exceptions.end(); ++e) + { + out << "'" + getAbsolute(*e) + "'"; + } + out << epar << ';'; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + } + + out << nl << "r_ = " << self << ".invokeAsync_('" << op->name() << "', '" + << getOperationMode(op->sendMode()) << "', " << (twowayOnly ? "true" : "false") << ", " + << (inParams.empty() ? "[]" : "os_") << ", " << outParams.size() << ", "; + if(!outParams.empty() || !exceptions.empty()) + { + out << "@unmarshal"; + } + else + { + out << "[]"; + } + out << ", varargin{:});"; + + out.dec(); + out << nl << "end"; + } + + out.dec(); + out << nl << "end"; + + out << nl << "methods(Static)"; + out.inc(); + out << nl << "function id = ice_staticId()"; + out.inc(); + out << nl << "id = '" << scoped << "';"; + out.dec(); + out << nl << "end"; + out << nl << "function r = ice_read(is_)"; + out.inc(); + out << nl << "r = Ice.ObjectPrx.read_(is_, '" << abs << "');"; + out.dec(); + out << nl << "end"; + out << nl << "function r = checkedCast(p, varargin)"; + out.inc(); + out << nl << "r = Ice.ObjectPrx.checkedCast_(p, " << abs << ".ice_staticId(), '" << abs << "', varargin{:});"; + out.dec(); + out << nl << "end"; + out << nl << "function r = uncheckedCast(p, varargin)"; + out.inc(); + out << nl << "r = Ice.ObjectPrx.uncheckedCast_(p, '" << abs << "', varargin{:});"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); + } + else + { + // + // Generate local abstract class. + // + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef (Abstract) " << name; + if(!bases.empty()) + { + out << " < "; + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + if(q != bases.begin()) + { + out << " & "; + } + out << " < " << getAbsolute(*q); + } + } + + const OperationList ops = p->operations(); + if(!ops.empty()) + { + out.inc(); + out << nl << "methods(Abstract)"; + out.inc(); + for(OperationList::const_iterator q = ops.begin(); q != ops.end(); ++q) + { + OperationPtr op = *q; + const ParamInfoList outParams = getOutParams(op); + out << nl; + if(outParams.size() > 1) + { + out << "["; + for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) + { + if(r != outParams.begin()) + { + out << ", "; + } + out << r->fixedName; + } + out << "] = "; + } + else if(outParams.size() == 1) + { + out << outParams.begin()->fixedName << " = "; + } + out << fixIdent(op->name()) << spar; + string self = "obj"; + const ParamInfoList inParams = getInParams(op); + for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) + { + if(r->fixedName == "obj") + { + self = "obj_"; + } + } + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + if(r->fixedName == "obj") + { + self = "obj_"; + } + } + out << self; + for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + { + out << r->fixedName; + } + out << epar; + } + out.dec(); + out << nl << "end"; + out.dec(); + } + + out << nl << "end"; + out << nl; + + out.close(); + } + + return false; +} + +bool +CodeVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + + IceUtilInternal::Output out; + openClass(scoped, out); + + ExceptionPtr base = p->base(); + + out << nl << "classdef " << name; + if(base) + { + out << " < " << getAbsolute(base); + } + else if(p->isLocal()) + { + out << " < Ice.LocalException"; + } + else + { + out << " < Ice.UserException"; + } + + const DataMemberList members = p->dataMembers(); + if(!members.empty()) + { + out.inc(); + out << nl << "properties"; + out.inc(); + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + out << nl << fixIdent((*q)->name()); + if(declarePropertyType((*q)->type(), (*q)->optional())) + { + out << " " << typeToString((*q)->type()); + } + } + out.dec(); + out << nl << "end"; + } + + MemberInfoList allMembers; + collectExceptionMembers(p, allMembers, false); + + vector<string> allNames; + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + allNames.push_back(q->fixedName); + } + out << nl << "methods"; + out.inc(); + + const string self = name == "obj" ? "this" : "obj"; + + // + // Constructor + // + out << nl << "function " << self << " = " << name << spar << "ice_exid" << "ice_exmsg" << allNames << epar; + out.inc(); + string exid = getAbsolute(p); + const string exmsg = getAbsolute(p); // TODO: Allow a message to be specified via metadata? + // + // The ID argument must use colon separators. + // + string::size_type pos = exid.find('.'); + assert(pos != string::npos); + while(pos != string::npos) + { + exid[pos] = ':'; + pos = exid.find('.', pos); + } + + if(!allMembers.empty()) + { + out << nl << "if nargin <= 2"; + out.inc(); + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + out << nl << q->fixedName << " = " << defaultValue(q->dataMember) << ';'; + } + out.dec(); + out << nl << "end"; + } + + out << nl << "if nargin == 0 || isempty(ice_exid)"; + out.inc(); + out << nl << "ice_exid = '" << exid << "';"; + out.dec(); + out << nl << "end"; + + out << nl << "if nargin < 2 || isempty(ice_exmsg)"; + out.inc(); + out << nl << "ice_exmsg = '" << exmsg << "';"; + out.dec(); + out << nl << "end"; + + if(!base) + { + out << nl << self << " = " << self << "@" << (p->isLocal() ? "Ice.LocalException" : "Ice.UserException") + << spar << "ice_exid" << "ice_exmsg" << epar << ';'; + } + else + { + out << nl << self << " = " << self << "@" << getAbsolute(base) << spar << "ice_exid" << "ice_exmsg"; + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(q->inherited) + { + out << q->fixedName; + } + } + out << epar << ';'; + } + for(MemberInfoList::const_iterator q = allMembers.begin(); q != allMembers.end(); ++q) + { + if(!q->inherited) + { + out << nl << self << "." << q->fixedName << " = " << q->fixedName << ';'; + } + } + out.dec(); + out << nl << "end"; + + out << nl << "function id = ice_id(obj)"; + out.inc(); + out << nl << "id = '" << scoped << "';"; + out.dec(); + out << nl << "end"; + + out << nl << "function obj = readImpl_(obj, is_)"; + out.inc(); + out << nl << "is_.startSlice();"; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + int idx = 0; + unmarshal(out, "is_", "obj." + fixIdent((*q)->name()), (*q)->type(), false, 0, idx); + } + out << nl << "is_.endSlice();"; + if(base) + { + out << nl << "obj = readImpl_@" << getAbsolute(base) << "(obj);"; + } + out.dec(); + out << nl << "end"; + + if(p->usesClasses(false)) + { + if(!base || (base && !base->usesClasses(false))) + { + out << nl << "function r = usesClasses_(obj)"; + out.inc(); + out << nl << "r = true;"; + out.dec(); + out << nl << "end"; + } + } + + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); + + return false; +} + +bool +CodeVisitor::visitStructStart(const StructPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + const string abs = getAbsolute(p); + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef " << name; + + const DataMemberList members = p->dataMembers(); + out.inc(); + out << nl << "properties"; + out.inc(); + vector<string> memberNames; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + const string m = fixIdent((*q)->name()); + memberNames.push_back(m); + out << nl << m; + if(declarePropertyType((*q)->type(), false)) + { + out << " " << typeToString((*q)->type()); + } + } + out.dec(); + out << nl << "end"; + + out << nl << "methods"; + out.inc(); + string self = name == "obj" ? "this" : "obj"; + out << nl << "function " << self << " = " << name << spar << memberNames << epar; + out.inc(); + out << nl << "if nargin > 0"; + out.inc(); + for(vector<string>::const_iterator q = memberNames.begin(); q != memberNames.end(); ++q) + { + out << nl << self << "." << *q << " = " << *q << ';'; + } + out.dec(); + out << nl << "else"; + out.inc(); + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + out << nl << self << "." << fixIdent((*q)->name()) << " = " << defaultValue(*q) << ';'; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + + if(!p->isLocal()) + { + out << nl << "methods(Static)"; + out.inc(); + out << nl << "function r = ice_read(is_)"; + out.inc(); + out << nl << "r = " << abs << "();"; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + int idx = 0; + unmarshal(out, "is_", "r." + fixIdent((*q)->name()), (*q)->type(), false, 0, idx); + } + out.dec(); + out << nl << "end"; + out << nl << "function ice_write(os_, v_)"; + out.inc(); + out << nl << "if isempty(v_)"; + out.inc(); + out << nl << "v_ = " << abs << "();"; + out.dec(); + out << nl << "end"; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + int idx = 0; + marshal(out, "os_", "v_." + fixIdent((*q)->name()), (*q)->type(), false, 0, idx); + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + } + + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); + + return false; +} + +void +CodeVisitor::visitSequence(const SequencePtr& p) +{ + if(p->isLocal()) + { + return; + } + + const TypePtr content = p->type(); + + const BuiltinPtr bp = BuiltinPtr::dynamicCast(content); + if(bp) + { + switch(bp->kind()) + { + case Builtin::KindBool: + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + case Builtin::KindString: + { + return; + } + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindValue: + { + break; + } + case Builtin::KindLocalObject: + { + assert(false); + } + } + } + + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef " << name; + out.inc(); + out << nl << "methods(Static)"; + out.inc(); + + out << nl << "function write(os, seq)"; + out.inc(); + out << nl << "sz = length(seq);"; + out << nl << "os.writeSize(sz);"; + out << nl << "for i = 1:sz"; + out.inc(); + int idx = 0; + marshal(out, "os", "seq{i}", content, false, 0, idx); + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + + out << nl << "function r = read(is)"; + out.inc(); + out << nl << "sz = is.readSize();"; + out << nl << "r = {};"; + out << nl << "for i = 1:sz"; + out.inc(); + idx = 0; + unmarshal(out, "is", "r{i}", content, false, 0, idx); + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); +} + +void +CodeVisitor::visitDictionary(const DictionaryPtr& p) +{ + const TypePtr key = p->keyType(); + const TypePtr value = p->valueType(); + + const StructPtr st = StructPtr::dynamicCast(key); + + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + const string abs = getAbsolute(p); + const string self = name == "obj" ? "this" : "obj"; + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef " << name; + out.inc(); + out << nl << "methods(Access=private)"; + out.inc(); + // + // Declare a private constructor so that programs can't instantiate this type. They need to use new(). + // + out << nl << "function " << self << " = " << name << "()"; + out.inc(); + out << nl << "% Use new()"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl << "methods(Static)"; + out.inc(); + out << nl << "function r = new()"; + out.inc(); + if(st) + { + out << nl << "r = struct();"; + } + else + { + out << nl << "r = containers.Map('KeyType', '" << dictionaryTypeToString(key, true) << "', 'ValueType', '" + << dictionaryTypeToString(value, false) << "');"; + } + out.dec(); + out << nl << "end"; + + if(!p->isLocal()) + { + out << nl << "function write(os, d)"; + out.inc(); + out << nl << "if isempty(d)"; + out.inc(); + out << nl << "os.writeSize(0);"; + out.dec(); + out << nl << "else"; + out.inc(); + if(st) + { + out << nl << "sz = length(d);"; + out << nl << "os.writeSize(sz);"; + out << nl << "for i = 1:sz"; + out.inc(); + int idx = 0; + marshal(out, "os", "d(i).key", key, false, 0, idx); + marshal(out, "os", "d(i).value", value, false, 0, idx); + out.dec(); + out << nl << "end"; + } + else + { + out << nl << "sz = d.Count;"; + out << nl << "os.writeSize(sz);"; + out << nl << "keys = d.keys();"; + out << nl << "values = d.values();"; + out << nl << "for i = 1:sz"; + out.inc(); + int idx = 0; + out << nl << "k = keys{i};"; + out << nl << "v = values{i};"; + marshal(out, "os", "k", key, false, 0, idx); + marshal(out, "os", "v", value, false, 0, idx); + out.dec(); + out << nl << "end"; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + + out << nl << "function r = read(is)"; + out.inc(); + out << nl << "sz = is.readSize();"; + out << nl << "r = " << abs << ".new();"; + out << nl << "for i = 1:sz"; + out.inc(); + int idx = 0; + unmarshal(out, "is", "k", key, false, 0, idx); + unmarshal(out, "is", "v", value, false, 0, idx); + if(st) + { + out << nl << "r(i).key = k;"; + out << nl << "r(i).value = v;"; + } + else if(EnumPtr::dynamicCast(key)) + { + out << nl << "r(int32(k)) = v;"; + } + else + { + out << nl << "r(k) = v;"; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + } + + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); +} + +void +CodeVisitor::visitEnum(const EnumPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + const string abs = getAbsolute(p); + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef " << name << " < int32"; + + const EnumeratorList enumerators = p->enumerators(); + out.inc(); + out << nl << "enumeration"; + out.inc(); + for(EnumeratorList::const_iterator q = enumerators.begin(); q != enumerators.end(); ++q) + { + out << nl << fixIdent((*q)->name()) << " (" << (*q)->value() << ")"; + } + out.dec(); + out << nl << "end"; + + out << nl << "methods(Static)"; + out.inc(); + if(!p->isLocal()) + { + out << nl << "function ice_write(os, v)"; + out.inc(); + out << nl << "if isempty(v)"; + out.inc(); + string firstEnum = fixIdent(enumerators.front()->name()); + out << nl << "os.writeEnum(int32(" << abs << "." << firstEnum << "), " << p->maxValue() << ");"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "os.writeEnum(int32(v), " << p->maxValue() << ");"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl << "function r = ice_read(is)"; + out.inc(); + out << nl << "v = is.readEnum(" << p->maxValue() << ");"; + out << nl << "r = " << abs << ".ice_getValue(v);"; + out.dec(); + out << nl << "end"; + } + out << nl << "function r = ice_getValue(v)"; + out.inc(); + out << nl << "switch v"; + out.inc(); + for(EnumeratorList::const_iterator q = enumerators.begin(); q != enumerators.end(); ++q) + { + out << nl << "case " << (*q)->value(); + out.inc(); + out << nl << "r = " << abs << "." << fixIdent((*q)->name()) << ";"; + out.dec(); + } + out << nl << "otherwise"; + out.inc(); + out << nl << "throw(Ice.MarshalException('', '', sprintf('enumerator value %d is out of range', v)));"; + out.dec(); + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out << nl; + out.close(); +} + +void +CodeVisitor::visitConst(const ConstPtr& p) +{ + const string name = fixIdent(p->name()); + const string scoped = p->scoped(); + + IceUtilInternal::Output out; + openClass(scoped, out); + + out << nl << "classdef " << name; + + out.inc(); + out << nl << "properties(Constant)"; + out.inc(); + out << nl << "value " << typeToString(p->type()) << " = " + << constantValue(p->type(), p->valueType(), p->value()); + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out << nl; + out.close(); + out.close(); +} + +void +CodeVisitor::openClass(const string& scoped, IceUtilInternal::Output& out) +{ + vector<string> v = splitScopedName(scoped); + assert(v.size() > 1); + + string path; + if(!_dir.empty()) + { + path = _dir + "/"; + } + + // + // Create a package directory corresponding to each Slice module. + // + for(vector<string>::size_type i = 0; i < v.size() - 1; i++) + { + path += "+" + lookupKwd(v[i]); + if(!IceUtilInternal::directoryExists(path)) + { + if(IceUtilInternal::mkdir(path, 0777) != 0) + { + ostringstream os; + os << "cannot create directory `" << path << "': " << strerror(errno); + throw FileException(__FILE__, __LINE__, os.str()); + } + FileTracker::instance()->addDirectory(path); + } + path += "/"; + } + + // + // There are two options: + // + // 1) Create a subdirectory named "@ClassName" containing a file "ClassName.m". + // 2) Create a file named "ClassName.m". + // + // The class directory is useful if you want to add additional supporting files for the class. We only + // generate a single file for a class so we use option 2. + // + const string cls = lookupKwd(v[v.size() - 1]); + path += "/" + cls + ".m"; + + out.open(path); + printHeader(out); + FileTracker::instance()->addFile(path); +} + +string +CodeVisitor::getOperationMode(Slice::Operation::Mode mode) +{ + switch(mode) + { + case Operation::Normal: + return "Normal"; + case Operation::Nonmutating: + return "Nonmutating"; + case Operation::Idempotent: + return "Idempotent"; + default: + return "???"; + } +} + +void +CodeVisitor::collectClassMembers(const ClassDefPtr& p, MemberInfoList& allMembers, bool inherited) +{ + ClassList bases = p->bases(); + if(!bases.empty() && !bases.front()->isInterface()) + { + collectClassMembers(bases.front(), allMembers, true); + } + + DataMemberList members = p->dataMembers(); + + for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + { + MemberInfo m; + m.fixedName = fixIdent((*q)->name()); + m.inherited = inherited; + m.dataMember = *q; + allMembers.push_back(m); + } +} + +void +CodeVisitor::collectExceptionMembers(const ExceptionPtr& p, MemberInfoList& allMembers, bool inherited) +{ + ExceptionPtr base = p->base(); + if(base) + { + collectExceptionMembers(base, allMembers, true); + } + + DataMemberList members = p->dataMembers(); + + for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + { + MemberInfo m; + m.fixedName = fixIdent((*q)->name()); + m.inherited = inherited; + m.dataMember = *q; + allMembers.push_back(m); + } +} + +CodeVisitor::ParamInfoList +CodeVisitor::getInParams(const OperationPtr& op) +{ + const ParamDeclList l = op->inParameters(); + ParamInfoList r; + for(ParamDeclList::const_iterator p = l.begin(); p != l.end(); ++p) + { + ParamInfo info; + info.fixedName = fixIdent((*p)->name()); + info.type = (*p)->type(); + info.optional = (*p)->optional(); + info.tag = (*p)->tag(); + info.param = *p; + r.push_back(info); + } + return r; +} + +CodeVisitor::ParamInfoList +CodeVisitor::getOutParams(const OperationPtr& op) +{ + const ParamDeclList l = op->outParameters(); + ParamInfoList r; + + if(op->returnType()) + { + ParamInfo info; + info.fixedName = "result"; + for(ParamDeclList::const_iterator p = l.begin(); p != l.end(); ++p) + { + if((*p)->name() == "result") + { + info.fixedName = "result_"; + break; + } + } + info.type = op->returnType(); + info.optional = op->returnIsOptional(); + info.tag = op->returnTag(); + r.push_back(info); + } + + for(ParamDeclList::const_iterator p = l.begin(); p != l.end(); ++p) + { + ParamInfo info; + info.fixedName = fixIdent((*p)->name()); + info.type = (*p)->type(); + info.optional = (*p)->optional(); + info.tag = (*p)->tag(); + info.param = *p; + r.push_back(info); + } + + return r; +} + +string +CodeVisitor::getOptionalFormat(const TypePtr& type) +{ + BuiltinPtr bp = BuiltinPtr::dynamicCast(type); + if(bp) + { + switch(bp->kind()) + { + case Builtin::KindByte: + case Builtin::KindBool: + { + return "'OptionalFormatF1'"; + } + case Builtin::KindShort: + { + return "'OptionalFormatF2'"; + } + case Builtin::KindInt: + case Builtin::KindFloat: + { + return "'OptionalFormatF4'"; + } + case Builtin::KindLong: + case Builtin::KindDouble: + { + return "'OptionalFormatF8'"; + } + case Builtin::KindString: + { + return "'OptionalFormatVSize'"; + } + case Builtin::KindObject: + { + return "'OptionalFormatClass'"; + } + case Builtin::KindObjectProxy: + { + return "'OptionalFormatFSize'"; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + case Builtin::KindValue: + { + return "'OptionalFormatClass'"; + } + } + } + + if(EnumPtr::dynamicCast(type)) + { + return "'OptionalFormatSize'"; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return seq->type()->isVariableLength() ? "'OptionalFormatFSize'" : "'OptionalFormatVSize'"; + } + + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + if(d) + { + return (d->keyType()->isVariableLength() || d->valueType()->isVariableLength()) ? + "'OptionalFormatFSize'" : "'OptionalFormatVSize'"; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + return st->isVariableLength() ? "'OptionalFormatFSize'" : "'OptionalFormatVSize'"; + } + + if(ProxyPtr::dynamicCast(type)) + { + return "'OptionalFormatFSize'"; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + assert(cl); + return "'OptionalFormatClass'"; +} + +string +CodeVisitor::getFormatType(FormatType type) +{ + switch(type) + { + case DefaultFormat: + return "Ice.FormatType.DefaultFormat"; + case CompactFormat: + return "Ice.FormatType.CompactFormat"; + case SlicedFormat: + return "Ice.FormatType.SlicedFormat"; + default: + assert(false); + } + + return "???"; +} + +void +CodeVisitor::marshal(IceUtilInternal::Output& out, const string& stream, const string& v, const TypePtr& type, + bool optional, int tag, int& idx) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindByte: + { + if(optional) + { + out << nl << stream << ".writeByteOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeByte(" << v << ");"; + } + break; + } + case Builtin::KindBool: + { + if(optional) + { + out << nl << stream << ".writeBoolOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeBool(" << v << ");"; + } + break; + } + case Builtin::KindShort: + { + if(optional) + { + out << nl << stream << ".writeShortOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeShort(" << v << ");"; + } + break; + } + case Builtin::KindInt: + { + if(optional) + { + out << nl << stream << ".writeIntOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeInt(" << v << ");"; + } + break; + } + case Builtin::KindLong: + { + if(optional) + { + out << nl << stream << ".writeLongOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeLong(" << v << ");"; + } + break; + } + case Builtin::KindFloat: + { + if(optional) + { + out << nl << stream << ".writeFloatOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeFloat(" << v << ");"; + } + break; + } + case Builtin::KindDouble: + { + if(optional) + { + out << nl << stream << ".writeDoubleOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeDouble(" << v << ");"; + } + break; + } + case Builtin::KindString: + { + if(optional) + { + out << nl << stream << ".writeStringOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeString(" << v << ");"; + } + break; + } + case Builtin::KindObject: + case Builtin::KindValue: + { + if(optional) + { + out << nl << stream << ".writeValueOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeValue(" << v << ");"; + } + break; + } + case Builtin::KindObjectProxy: + { + if(optional) + { + out << nl << stream << ".writeProxyOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeProxy(" << v << ");"; + } + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + if(prx) + { + if(optional) + { + out << nl << stream << ".writeProxyOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeProxy(" << v << ");"; + } + return; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { + if(optional) + { + out << nl << stream << ".writeValueOpt(" << tag << ", " << v << ");"; + } + else + { + out << nl << stream << ".writeValue(" << v << ");"; + } + return; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + const string typeS = getAbsolute(st); + if(optional) + { + if(optional) + { + out << nl << "if ~isempty(" << v << ") && " << stream << ".writeOptional(" << tag << ", " + << getOptionalFormat(type) << ")"; + out.inc(); + } + + if(st->isVariableLength()) + { + out << nl << "pos = " << stream << ".startSize();"; + out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; + out << nl << stream << ".endSize(pos);"; + } + else + { + out << nl << stream << ".writeSize(" << st->minWireSize() << ");"; + out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; + } + if(optional) + { + out.dec(); + out << nl << "end"; + } + } + else + { + out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; + } + return; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + const string typeS = getAbsolute(en); + if(optional) + { + out << nl << "if " << stream << ".writeOptional(" << tag << ", " << getOptionalFormat(type) << ")"; + out.inc(); + out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; + } + return; + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + if(dict) + { + if(optional) + { + out << nl << "if " << stream << ".writeOptional(" << tag << ", " << getOptionalFormat(dict) << "))"; + out.inc(); + out << nl << getAbsolute(dict) << ".write(" << stream << ", " << v << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << getAbsolute(dict) << ".write(" << stream << ", " << v << ");"; + } + return; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + const TypePtr content = seq->type(); + const BuiltinPtr b = BuiltinPtr::dynamicCast(content); + + if(b && b->kind() != Builtin::KindObject && b->kind() != Builtin::KindObjectProxy && + b->kind() != Builtin::KindValue) + { + static const char* builtinTable[] = + { + "Byte", + "Bool", + "Short", + "Int", + "Long", + "Float", + "Double", + "String", + "???", + "???", + "???", + "???" + }; + string bs = builtinTable[b->kind()]; + out << nl << stream << ".write" << builtinTable[b->kind()] << "Seq"; + if(optional) + { + out << "Opt(" << tag << ", "; + } + else + { + out << "("; + } + out << v << ");"; + return; + } + + if(optional) + { + out << nl << "if " << stream << ".writeOptional(" << tag << ", " << getOptionalFormat(seq) << "))"; + out.inc(); + out << nl << getAbsolute(seq) << ".write(" << stream << ", " << v << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << getAbsolute(seq) << ".write(" << stream << ", " << v << ");"; + } + return; + } + + assert(false); +} + + +void +CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const string& v, const TypePtr& type, + bool optional, int tag, int& idx) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindByte: + { + if(optional) + { + out << nl << v << " = " << stream << ".readByteOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readByte();"; + } + break; + } + case Builtin::KindBool: + { + if(optional) + { + out << nl << v << " = " << stream << ".readBoolOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readBool();"; + } + break; + } + case Builtin::KindShort: + { + if(optional) + { + out << nl << v << " = " << stream << ".readShortOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readShort();"; + } + break; + } + case Builtin::KindInt: + { + if(optional) + { + out << nl << v << " = " << stream << ".readIntOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readInt();"; + } + break; + } + case Builtin::KindLong: + { + if(optional) + { + out << nl << v << " = " << stream << ".readLongOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readLong();"; + } + break; + } + case Builtin::KindFloat: + { + if(optional) + { + out << nl << v << " = " << stream << ".readFloatOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readFloat();"; + } + break; + } + case Builtin::KindDouble: + { + if(optional) + { + out << nl << v << " = " << stream << ".readDoubleOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readDouble();"; + } + break; + } + case Builtin::KindString: + { + if(optional) + { + out << nl << v << " = " << stream << ".readStringOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readString();"; + } + break; + } + case Builtin::KindObject: + case Builtin::KindValue: + { +#if 0 // TBD + if(optional) + { + out << nl << stream << ".readValue(" << tag << ", " << param << ");"; + } + else if(holder && mode == OptionalNone) + { + out << nl << stream << ".readValue(" << param << ");"; + } + else + { + if(patchParams.empty()) + { + out << nl << stream << ".readValue(new Patcher());"; + } + else + { + out << nl << stream << ".readValue(" << patchParams << ");"; + } + } +#endif + break; + } + case Builtin::KindObjectProxy: + { + if(optional) + { + out << nl << v << " = " << stream << ".readProxyOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readProxy();"; + } + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + if(prx) + { + const string typeS = getAbsolute(prx->_class(), "", "Prx"); + if(optional) + { + out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; + out.inc(); + out << nl << stream << ".skip(4);"; + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + } + return; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { +#if 0 // TBD + if(optional) + { + const string typeS = typeToString(type, TypeModeIn, package); + out << nl << "if(" << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << "))"; + out << sb; + out << nl << stream << ".readValue(new Ice.OptionalObject(" << v << ", " << typeS << ".class, " + << getStaticId(type, package) << "));"; + out << eb; + if(mode == OptionalOutParam) + { + out << nl << "else"; + out << sb; + out << nl << v << ".clear();"; + out << eb; + } + } + else + { + if(holder && mode == OptionalNone) + { + out << nl << stream << ".readValue(" << param << ");"; + } + else + { + if(patchParams.empty()) + { + out << nl << stream << ".readValue(new Patcher());"; + } + else + { + out << nl << stream << ".readValue(" << patchParams << ");"; + } + } + } +#endif + return; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + const string typeS = getAbsolute(st); + if(optional) + { + out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; + out.inc(); + + if(st->isVariableLength()) + { + out << nl << stream << ".skip(4);"; + } + else + { + out << nl << stream << ".skipSize();"; + } + + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + + out.dec(); + out << nl << "end"; + } + else + { + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + } + return; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + const string typeS = getAbsolute(en); + if(optional) + { + out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; + out.inc(); + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + } + return; + } + + DictionaryPtr dict = DictionaryPtr::dynamicCast(type); + if(dict) + { + if(optional) + { + out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(dict) << "))"; + out.inc(); + out << nl << v << " = " << getAbsolute(dict) << ".read(" << stream << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << v << " = " << getAbsolute(dict) << ".read(" << stream << ");"; + } + return; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + const TypePtr content = seq->type(); + const BuiltinPtr b = BuiltinPtr::dynamicCast(content); + + if(b && b->kind() != Builtin::KindObject && b->kind() != Builtin::KindObjectProxy && + b->kind() != Builtin::KindValue) + { + static const char* builtinTable[] = + { + "Byte", + "Bool", + "Short", + "Int", + "Long", + "Float", + "Double", + "String", + "???", + "???", + "???", + "???" + }; + string bs = builtinTable[b->kind()]; + out << nl << v << " = " << stream << ".read" << builtinTable[b->kind()] << "Seq"; + if(optional) + { + out << "Opt(" << tag << ");"; + } + else + { + out << "();"; + } + return; + } + + if(optional) + { + out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(seq) << "))"; + out.inc(); + out << nl << v << " = " << getAbsolute(seq) << ".read(" << stream << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << v << " = " << getAbsolute(seq) << ".read(" << stream << ");"; + } + return; + } + + assert(false); +} + +static void +generate(const UnitPtr& un, const string& dir, bool all, bool checksum, const vector<string>& includePaths) +{ + CodeVisitor codeVisitor(dir); + un->visit(&codeVisitor, false); + +#if 0 + if(checksum) + { + ChecksumMap checksums = createChecksums(un); + if(!checksums.empty()) + { + out << sp; + if(ns) + { + out << "namespace"; // Global namespace. + out << sb; + out << "new Ice\\SliceChecksumInit(array("; + for(ChecksumMap::const_iterator p = checksums.begin(); p != checksums.end();) + { + out << nl << "\"" << p->first << "\" => \""; + ostringstream str; + str.flags(ios_base::hex); + str.fill('0'); + for(vector<unsigned char>::const_iterator q = p->second.begin(); q != p->second.end(); ++q) + { + str << static_cast<int>(*q); + } + out << str.str() << "\""; + if(++p != checksums.end()) + { + out << ","; + } + } + out << "));"; + out << eb; + } + else + { + for(ChecksumMap::const_iterator p = checksums.begin(); p != checksums.end(); ++p) + { + out << nl << "$Ice_sliceChecksums[\"" << p->first << "\"] = \""; + ostringstream str; + str.flags(ios_base::hex); + str.fill('0'); + for(vector<unsigned char>::const_iterator q = p->second.begin(); q != p->second.end(); ++q) + { + str << static_cast<int>(*q); + } + out << str.str() << "\";"; + } + } + } + } + + out << nl; // Trailing newline. +#endif +} + +namespace +{ + +IceUtil::Mutex* globalMutex = 0; +bool interrupted = false; + +class Init +{ +public: + + Init() + { + globalMutex = new IceUtil::Mutex; + } + + ~Init() + { + delete globalMutex; + globalMutex = 0; + } +}; + +Init init; + +} + +static void +interruptedCallback(int /*signal*/) +{ + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(globalMutex); + + interrupted = true; +} + +static void +usage(const string& n) +{ + consoleErr << "Usage: " << n << " [options] slice-files...\n"; + consoleErr << + "Options:\n" + "-h, --help Show this message.\n" + "-v, --version Display the Ice version.\n" + "-DNAME Define NAME as 1.\n" + "-DNAME=DEF Define NAME as DEF.\n" + "-UNAME Remove any definition for NAME.\n" + "-IDIR Put DIR in the include file search path.\n" + "-E Print preprocessor output on stdout.\n" + "--output-dir DIR Create files in the directory DIR.\n" + "-d, --debug Print debug messages.\n" + "--depend Generate Makefile dependencies.\n" + "--depend-xml Generate dependencies in XML format.\n" + "--depend-file FILE Write dependencies to FILE instead of standard output.\n" + "--validate Validate command line options.\n" + "--all Generate code for Slice definitions in included files.\n" + "--checksum Generate checksums for Slice definitions.\n" + ; +} + +int +compile(const vector<string>& argv) +{ + IceUtilInternal::Options opts; + opts.addOpt("h", "help"); + opts.addOpt("v", "version"); + opts.addOpt("", "validate"); + opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("E"); + opts.addOpt("", "output-dir", IceUtilInternal::Options::NeedArg); + opts.addOpt("", "depend"); + opts.addOpt("", "depend-xml"); + opts.addOpt("", "depend-file", IceUtilInternal::Options::NeedArg, ""); + opts.addOpt("d", "debug"); + opts.addOpt("", "all"); + opts.addOpt("", "checksum"); + + bool validate = find(argv.begin(), argv.end(), "--validate") != argv.end(); + + vector<string> args; + try + { + args = opts.parse(argv); + } + catch(const IceUtilInternal::BadOptException& e) + { + consoleErr << argv[0] << ": error: " << e.reason << endl; + if(!validate) + { + usage(argv[0]); + } + return EXIT_FAILURE; + } + + if(opts.isSet("help")) + { + usage(argv[0]); + return EXIT_SUCCESS; + } + + if(opts.isSet("version")) + { + consoleErr << ICE_STRING_VERSION << endl; + return EXIT_SUCCESS; + } + + vector<string> cppArgs; + vector<string> optargs = opts.argVec("D"); + for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs.push_back("-D" + *i); + } + + optargs = opts.argVec("U"); + for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs.push_back("-U" + *i); + } + + vector<string> includePaths = opts.argVec("I"); + for(vector<string>::const_iterator i = includePaths.begin(); i != includePaths.end(); ++i) + { + cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i)); + } + + bool preprocess = opts.isSet("E"); + + string output = opts.optArg("output-dir"); + + bool depend = opts.isSet("depend"); + + bool dependxml = opts.isSet("depend-xml"); + + string dependFile = opts.optArg("depend-file"); + + bool debug = opts.isSet("debug"); + + bool all = opts.isSet("all"); + + bool checksum = opts.isSet("checksum"); + + if(args.empty()) + { + consoleErr << argv[0] << ": error: no input file" << endl; + if(!validate) + { + usage(argv[0]); + } + return EXIT_FAILURE; + } + + if(depend && dependxml) + { + consoleErr << argv[0] << ": error: cannot specify both --depend and --depend-xml" << endl; + if(!validate) + { + usage(argv[0]); + } + return EXIT_FAILURE; + } + + if(validate) + { + return EXIT_SUCCESS; + } + + int status = EXIT_SUCCESS; + + IceUtil::CtrlCHandler ctrlCHandler; + ctrlCHandler.setCallback(interruptedCallback); + + ostringstream os; + if(dependxml) + { + os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<dependencies>" << endl; + } + + for(vector<string>::const_iterator i = args.begin(); i != args.end(); ++i) + { + // + // Ignore duplicates. + // + vector<string>::iterator p = find(args.begin(), args.end(), *i); + if(p != i) + { + continue; + } + + if(depend || dependxml) + { + PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs); + FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2PHP__"); + + if(cppHandle == 0) + { + return EXIT_FAILURE; + } + + UnitPtr u = Unit::createUnit(false, false, false, false); + int parseStatus = u->parse(*i, cppHandle, debug); + u->destroy(); + + if(parseStatus == EXIT_FAILURE) + { + return EXIT_FAILURE; + } + + if(!icecpp->printMakefileDependencies(os, depend ? Preprocessor::PHP : Preprocessor::SliceXML, + includePaths, "-D__SLICE2PHP__")) + { + return EXIT_FAILURE; + } + + if(!icecpp->close()) + { + return EXIT_FAILURE; + } + } + else + { + PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs); + FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2PHP__"); + + if(cppHandle == 0) + { + return EXIT_FAILURE; + } + + if(preprocess) + { + char buf[4096]; + while(fgets(buf, static_cast<int>(sizeof(buf)), cppHandle) != ICE_NULLPTR) + { + if(fputs(buf, stdout) == EOF) + { + return EXIT_FAILURE; + } + } + if(!icecpp->close()) + { + return EXIT_FAILURE; + } + } + else + { + UnitPtr u = Unit::createUnit(false, all, false, false); + int parseStatus = u->parse(*i, cppHandle, debug); + + if(!icecpp->close()) + { + u->destroy(); + return EXIT_FAILURE; + } + + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + else + { + string base = icecpp->getBaseName(); + string::size_type pos = base.find_last_of("/\\"); + if(pos != string::npos) + { + base.erase(0, pos + 1); + } + + try + { + generate(u, output, all, checksum, includePaths); + } + catch(const Slice::FileException& ex) + { + // + // If a file could not be created, then cleanup any created files. + // + FileTracker::instance()->cleanup(); + u->destroy(); + consoleErr << argv[0] << ": error: " << ex.reason() << endl; + return EXIT_FAILURE; + } + catch(const string& err) + { + FileTracker::instance()->cleanup(); + consoleErr << argv[0] << ": error: " << err << endl; + status = EXIT_FAILURE; + } + } + + u->destroy(); + } + } + + { + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(globalMutex); + + if(interrupted) + { + FileTracker::instance()->cleanup(); + return EXIT_FAILURE; + } + } + } + + if(dependxml) + { + os << "</dependencies>\n"; + } + + if(depend || dependxml) + { + writeDependencies(os.str(), dependFile); + } + + return status; +} + +#ifdef _WIN32 +int wmain(int argc, wchar_t* argv[]) +#else +int main(int argc, char* argv[]) +#endif +{ + vector<string> args = Slice::argvToArgs(argc, argv); + try + { + return compile(args); + } + catch(const std::exception& ex) + { + consoleErr << args[0] << ": error:" << ex.what() << endl; + return EXIT_FAILURE; + } + catch(const std::string& msg) + { + consoleErr << args[0] << ": error:" << msg << endl; + return EXIT_FAILURE; + } + catch(const char* msg) + { + consoleErr << args[0] << ": error:" << msg << endl; + return EXIT_FAILURE; + } + catch(...) + { + consoleErr << args[0] << ": error:" << "unknown exception" << endl; + return EXIT_FAILURE; + } +} diff --git a/cpp/src/slice2matlab/Slice2Matlab.rc b/cpp/src/slice2matlab/Slice2Matlab.rc new file mode 100644 index 00000000000..605db23d085 --- /dev/null +++ b/cpp/src/slice2matlab/Slice2Matlab.rc @@ -0,0 +1,33 @@ +#include<IceUtil/ResourceConfig.h> + +#define ICE_INTERNALNAME "slice2matlab\0" +#define ICE_ORIGINALFILENAME "slice2matlab.exe\0" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION ICE_VERSION +PRODUCTVERSION ICE_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE VFT2_UNKNOWN +FILEFLAGS VER_DEBUG +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", ICE_COMPANY_NAME + VALUE "FileDescription", "Slice to Matlab Compiler\0" + VALUE "FileVersion", ICE_STRING_VERSION + VALUE "InternalName", ICE_INTERNALNAME + VALUE "LegalCopyright", ICE_COPYRIGHT + VALUE "OriginalFilename", ICE_ORIGINALFILENAME + VALUE "ProductName", ICE_PRODUCT_NAME + VALUE "ProductVersion", ICE_STRING_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/cpp/src/slice2matlab/msbuild/packages.config b/cpp/src/slice2matlab/msbuild/packages.config new file mode 100644 index 00000000000..8386dfda383 --- /dev/null +++ b/cpp/src/slice2matlab/msbuild/packages.config @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="mcpp.v100" version="2.7.2.17" targetFramework="native" /> + <package id="mcpp.v120" version="2.7.2.17" targetFramework="native" /> + <package id="mcpp.v140" version="2.7.2.17" targetFramework="native" /> + <package id="mcpp.v141" version="2.7.2.17" targetFramework="native" /> +</packages>
\ No newline at end of file diff --git a/cpp/src/slice2matlab/msbuild/slice2matlab.vcxproj b/cpp/src/slice2matlab/msbuild/slice2matlab.vcxproj new file mode 100644 index 00000000000..47bf883da36 --- /dev/null +++ b/cpp/src/slice2matlab/msbuild/slice2matlab.vcxproj @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{FBDCD48E-57DB-4CC1-A9D6-7D9F1C97D0E1}</ProjectGuid> + <RootNamespace>slice2matlab</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup> + <DefaultPlatformToolset Condition="'$(VisualStudioVersion)' == '10.0' And '$(DefaultPlatformToolset)' == ''">v100</DefaultPlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <Import Project="$(MSBuildThisFileDirectory)\..\..\..\msbuild\ice.cpp98.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>ICE_STATIC_LIBS;ICE_BUILDING_SLICE_COMPILERS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <AdditionalDependencies>rpcrt4.lib;advapi32.lib;DbgHelp.lib;Shlwapi.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>ICE_STATIC_LIBS;ICE_BUILDING_SLICE_COMPILERS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <AdditionalDependencies>rpcrt4.lib;advapi32.lib;DbgHelp.lib;Shlwapi.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>ICE_STATIC_LIBS;ICE_BUILDING_SLICE_COMPILERS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <AdditionalDependencies>rpcrt4.lib;advapi32.lib;DbgHelp.lib;Shlwapi.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>ICE_STATIC_LIBS;ICE_BUILDING_SLICE_COMPILERS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <AdditionalDependencies>rpcrt4.lib;advapi32.lib;DbgHelp.lib;Shlwapi.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\Main.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="..\Slice2Matlab.rc" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\IceUtil\msbuild\iceutil\iceutil.vcxproj"> + <Project>{4d1a5110-3176-44ba-8bbb-57bf56519b9f}</Project> + </ProjectReference> + <ProjectReference Include="..\..\Slice\msbuild\slice.vcxproj"> + <Project>{57cd6ac2-0c9d-4648-9e9d-5df60c90f18a}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + <Import Project="..\..\..\msbuild\packages\mcpp.v100.2.7.2.17\build\native\mcpp.v100.targets" Condition="Exists('..\..\..\msbuild\packages\mcpp.v100.2.7.2.17\build\native\mcpp.v100.targets')" /> + <Import Project="..\..\..\msbuild\packages\mcpp.v120.2.7.2.17\build\native\mcpp.v120.targets" Condition="Exists('..\..\..\msbuild\packages\mcpp.v120.2.7.2.17\build\native\mcpp.v120.targets')" /> + <Import Project="..\..\..\msbuild\packages\mcpp.v140.2.7.2.17\build\native\mcpp.v140.targets" Condition="Exists('..\..\..\msbuild\packages\mcpp.v140.2.7.2.17\build\native\mcpp.v140.targets')" /> + <Import Project="..\..\..\msbuild\packages\mcpp.v141.2.7.2.17\build\native\mcpp.v141.targets" Condition="Exists('..\..\..\msbuild\packages\mcpp.v141.2.7.2.17\build\native\mcpp.v141.targets')" /> + </ImportGroup> + <Import Project="$(MSBuildThisFileDirectory)..\..\..\msbuild\ice.sign.targets" /> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('..\..\..\msbuild\packages\mcpp.v100.2.7.2.17\build\native\mcpp.v100.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\msbuild\packages\mcpp.v100.2.7.2.17\build\native\mcpp.v100.targets'))" /> + <Error Condition="!Exists('..\..\..\msbuild\packages\mcpp.v120.2.7.2.17\build\native\mcpp.v120.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\msbuild\packages\mcpp.v120.2.7.2.17\build\native\mcpp.v120.targets'))" /> + <Error Condition="!Exists('..\..\..\msbuild\packages\mcpp.v140.2.7.2.17\build\native\mcpp.v140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\msbuild\packages\mcpp.v140.2.7.2.17\build\native\mcpp.v140.targets'))" /> + <Error Condition="!Exists('..\..\..\msbuild\packages\mcpp.v141.2.7.2.17\build\native\mcpp.v141.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\msbuild\packages\mcpp.v141.2.7.2.17\build\native\mcpp.v141.targets'))" /> + </Target> +</Project> diff --git a/cpp/src/slice2matlab/msbuild/slice2matlab.vcxproj.filters b/cpp/src/slice2matlab/msbuild/slice2matlab.vcxproj.filters new file mode 100644 index 00000000000..32065e79211 --- /dev/null +++ b/cpp/src/slice2matlab/msbuild/slice2matlab.vcxproj.filters @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{47F3A182-A9BF-4F97-9FCA-5E589023804E}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{696A80CE-5F76-4E59-AE7F-FFBFB029D4B9}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{CD1D3DC3-DAD5-45AC-A584-9C90DB426C23}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\Main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="..\Slice2Matlab.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> +</Project> diff --git a/matlab/.gitignore b/matlab/.gitignore new file mode 100644 index 00000000000..54737717b5a --- /dev/null +++ b/matlab/.gitignore @@ -0,0 +1 @@ +*.mexw64 diff --git a/matlab/README.md b/matlab/README.md new file mode 100644 index 00000000000..5dc1a984fdc --- /dev/null +++ b/matlab/README.md @@ -0,0 +1,92 @@ +# Ice for MATLAB + +> *This project is in the prototype stage and is changing rapidly. Do not use +in a production application.* + +## Prerequisites + +The build system currently requires Microsoft Visual Studio 2015. + +Ice for MATLAB is intended to support MATLAB 2016a or later but has only been +tested with 2017a. + +## Build Instructions + +Open a Visual Studio command prompt. For example, with Visual Studio 2015, you +can open one of: + +- VS2015 x86 Native Tools Command Prompt +- VS2015 x64 Native Tools Command Prompt + +Using the first Command Prompt produces `Win32` binaries by default, while +the second Command Prompt produces `x64` binaries by default. Select the +platform that matches your MATLAB installation. + +In the Command Prompt, change to the `matlab` subdirectory: + + cd matlab + +Add the MATLAB `bin` directory to your PATH: + + PATH=<MATLAB installation directory>\bin;%PATH% + +Now you're ready to build Ice for MATLAB: + + msbuild msbuild\ice.proj + +Upon completion, an x64 build generates the following components: + + - Ice for C++11 library, located in `cpp\bin\x64\Release` + - slice2matlab executable, located in `cpp\bin\x64\Release` + - icematlab.mexw64 MEX file, located in `matlab\src\IceMatlab` + - MATLAB code for core Slice files, located in `matlab\lib\generated` + +## Using Ice for MATLAB + +### Search Path + +Add the following directories to your MATLAB search path: + + - `matlab\lib` + - `matlab\lib\generated` + - `matlab\src\IceMatlab` + +### Slice Files + +Use `slice2matlab` to compile your Slice files. Run `slice2matlab -h` for a +description of its command-line options. You can place the generated `*.m` +files anywhere you like, but the enclosing directory must be in your MATLAB +search path. + +### Loading the Library + +The Ice for MATLAB library can be loaded with this command: + + loadlibrary icematlab + +The MEX file depends on `bzip2.dll` and `ice37++11.dll`. The build copied +these DLLs to `matlab\src\IceMatlab`. + +### Running the Test + +One test has been ported to MATLAB so far, and the code is located in +`matlab\test\Ice\operations`. Since Ice for MATLAB only supports client +functionality, you will have to build and start a test server from a +different language mapping. + +In a Command Prompt, start the test server. + +In MATLAB, change to the test directory: + + cd matlab\test\Ice\operations + +Now you can start the MATLAB test client. Assuming the server is running on +the same host, use this command: + + Client.start({}) + +If you started the server on a different host, use this command instead: + + Client.start({'--Ice.Default.Host=<addr>'}) + +Replace `<addr>` with the host name or IP address of the server host. diff --git a/matlab/lib/+Ice/Communicator.m b/matlab/lib/+Ice/Communicator.m new file mode 100644 index 00000000000..2cce5e4ca49 --- /dev/null +++ b/matlab/lib/+Ice/Communicator.m @@ -0,0 +1,31 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Communicator < Ice.WrapperObject + methods + function self = Communicator(impl) + self = self@Ice.WrapperObject(impl); + end + function r = stringToProxy(self, str) + impl = libpointer('voidPtr'); + Ice.Util.callMethod(self, 'stringToProxy', str, impl); + r = Ice.ObjectPrx(impl); + end + function r = getProperties(self) + impl = libpointer('voidPtr'); + Ice.Util.callMethod(self, 'getProperties', impl); + r = Ice.Properties(impl); + end + function destroy(self) + Ice.Util.callMethod(self, 'destroy'); + end + end +end diff --git a/matlab/lib/+Ice/Connection.m b/matlab/lib/+Ice/Connection.m new file mode 100755 index 00000000000..164cc7af7a8 --- /dev/null +++ b/matlab/lib/+Ice/Connection.m @@ -0,0 +1,76 @@ +%{
+**********************************************************************
+
+Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.
+
+This copy of Ice is licensed to you under the terms described in the
+ICE_LICENSE file included in this distribution.
+
+**********************************************************************
+%}
+%
+% Ice version 3.7.0
+%
+
+classdef Connection < Ice.WrapperObject
+ methods
+ function self = Connection(impl)
+ self = self@Ice.WrapperObject(impl);
+ end
+ function close(obj, mode)
+ Ice.Util.callMethod(obj, 'close', mode);
+ end
+ function r = createProxy(obj, id)
+ proxy = libpointer('voidPtr');
+ Ice.Util.callMethod(obj, 'createProxy', id, proxy);
+ r = Ice.ObjectPrx(proxy);
+ end
+ function r = getEndpoint(obj)
+ throw(Ice.FeatureNotSupportedException('', '', 'getEndpoint'));
+ end
+ function flushBatchRequests(obj, compress)
+ Ice.Util.callMethod(obj, 'flushBatchRequests', compress);
+ end
+ function r = flushBatchRequestsAsync(obj)
+ future = libpointer('voidPtr');
+ Ice.Util.callMethod(obj, 'flushBatchRequestsAsync', future);
+ assert(~isNull(future));
+ r = Ice.Future(future, 'flushBatchRequests', 0, 'Ice_SentFuture', []);
+ end
+ function heartbeat(obj)
+ Ice.Util.callMethod(obj, 'heartbeat');
+ end
+ function r = heartbeatAsync(obj)
+ future = libpointer('voidPtr');
+ Ice.Util.callMethod(obj, 'heartbeatAsync', future);
+ assert(~isNull(future));
+ r = Ice.Future(future, 'heartbeat', 0, 'Ice_SentFuture', []);
+ end
+ function setACM(obj, timeout, close, heartbeat)
+ Ice.Util.callMethod(obj, 'setACM', timeout, close, heartbeat);
+ end
+ function r = getACM(obj)
+ r = Ice.Util.callMethodWithResult(obj, 'getACM');
+ end
+ function r = type(obj)
+ r = Ice.Util.callMethodWithResult(obj, 'type');
+ end
+ function r = timeout(obj)
+ t = libpointer('int32Ptr', 0);
+ r = Ice.Util.callMethod(obj, 'timeout', t);
+ r = t.Value;
+ end
+ function r = toString(obj)
+ r = Ice.Util.callMethodWithResult(obj, 'toString');
+ end
+ function r = getInfo(obj)
+ throw(Ice.FeatureNotSupportedException('', '', 'getInfo'));
+ end
+ function setBufferSize(obj, rcvSize, sndSize)
+ Ice.Util.callMethod(obj, 'setBufferSize', rcvSize, sndSize);
+ end
+ function throwException(obj)
+ Ice.Util.callMethod(obj, 'throwException');
+ end
+ end
+end
diff --git a/matlab/lib/+Ice/Exception.m b/matlab/lib/+Ice/Exception.m new file mode 100644 index 00000000000..47ae4ba719b --- /dev/null +++ b/matlab/lib/+Ice/Exception.m @@ -0,0 +1,21 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) Exception < MException + methods(Abstract) + ice_id(obj) + end + methods + function self = Exception(id, msg) + self = self@MException(id, msg) + end + end +end diff --git a/matlab/lib/+Ice/Future.m b/matlab/lib/+Ice/Future.m new file mode 100644 index 00000000000..1678a804885 --- /dev/null +++ b/matlab/lib/+Ice/Future.m @@ -0,0 +1,67 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Future < handle + properties(SetAccess=private) + ID = 0 + NumOutputArguments + Operation + Read = false + State = 'running' + end + methods + function obj = Future(impl, op, numOutArgs, type, fetchFunc) + obj.impl = impl; + obj.Operation = op; + obj.NumOutputArguments = numOutArgs; + obj.type_ = type; + obj.fetchFunc_ = fetchFunc; + idPtr = libpointer('uint64Ptr', 0); + Ice.Util.callMethodOnType(obj, obj.type_, 'id', idPtr); + obj.ID = idPtr.Value; + end + function delete(obj) + if ~isempty(obj.impl) + Ice.Util.callMethodOnType(obj, obj.type_, '_release'); + end + end + function ok = wait(obj) + okPtr = libpointer('uint8Ptr', 0); % Output param + Ice.Util.callMethodOnType(obj, obj.type_, 'wait', okPtr); + ok = okPtr.Value == 1; + end + function varargout = fetchOutputs(obj) + if obj.Read + throw(MException('Ice:InvalidStateException', 'outputs already read')); + end + if obj.NumOutputArguments == 0 + Ice.Util.callMethodOnType(obj, obj.type_, 'check'); + else + [varargout{1:nargout}] = obj.fetchFunc_(obj); + end + obj.Read = true; + end + function cancel(obj) + Ice.Util.callMethodOnType(obj, obj.type_, 'cancel'); + end + function r = get.State(obj) + obj.State = Ice.Util.callMethodOnTypeWithResult(obj, obj.type_, 'state'); + r = obj.State; + end + end + properties(Access=private) + type_ + fetchFunc_ + end + properties(Hidden,SetAccess=protected) + impl + end +end diff --git a/matlab/lib/+Ice/InitializationData.m b/matlab/lib/+Ice/InitializationData.m new file mode 100644 index 00000000000..56c1570d37e --- /dev/null +++ b/matlab/lib/+Ice/InitializationData.m @@ -0,0 +1,28 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Sealed) InitializationData + methods + function r = clone(obj) + r = Ice.InitializationData(); + r.properties_ = obj.properties_; + r.logger = obj.logger; + r.compactIdResolver = obj.compactIdResolver; + r.valueFactoryManager = obj.valueFactoryManager; + end + end + properties + properties_ + logger + compactIdResolver + valueFactoryManager + end +end diff --git a/matlab/lib/+Ice/InputStream.m b/matlab/lib/+Ice/InputStream.m new file mode 100644 index 00000000000..a3dd84bbf4a --- /dev/null +++ b/matlab/lib/+Ice/InputStream.m @@ -0,0 +1,197 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef InputStream < Ice.WrapperObject + methods + function self = InputStream(impl) + self = self@Ice.WrapperObject(impl); + end + function r = readBool(self) + v = libpointer('uint8Ptr', 0); + Ice.Util.callMethod(self, 'readBool', v); + r = v.Value == 1; + end + function r = readBoolSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readBoolSeq'); + end + function r = readBoolOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readBoolOpt', tag); + end + function r = readBoolSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readBoolSeqOpt', tag); + end + function r = readByte(self) + v = libpointer('uint8Ptr', 0); + Ice.Util.callMethod(self, 'readByte', v); + r = v.Value; + end + function r = readByteSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readByteSeq'); + end + function r = readByteOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readByteOpt', tag); + end + function r = readByteSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readByteSeqOpt', tag); + end + function r = readShort(self) + v = libpointer('int16Ptr', 0); + Ice.Util.callMethod(self, 'readShort', v); + r = v.Value; + end + function r = readShortSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readShortSeq'); + end + function r = readShortOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readShortOpt', tag); + end + function r = readShortSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readShortSeqOpt', tag); + end + function r = readInt(self) + v = libpointer('int32Ptr', 0); + Ice.Util.callMethod(self, 'readInt', v); + r = v.Value; + end + function r = readIntSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readIntSeq'); + end + function r = readIntOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readIntOpt', tag); + end + function r = readIntSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readIntSeqOpt', tag); + end + function r = readLong(self) + v = libpointer('int64Ptr', 0); + Ice.Util.callMethod(self, 'readLong', v); + r = v.Value; + end + function r = readLongSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readLongSeq'); + end + function r = readLongOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readLongOpt', tag); + end + function r = readLongSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readLongSeqOpt', tag); + end + function r = readFloat(self) + v = libpointer('singlePtr', 0); + Ice.Util.callMethod(self, 'readFloat', v); + r = v.Value; + end + function r = readFloatSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readFloatSeq'); + end + function r = readFloatOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readFloatOpt', tag); + end + function r = readFloatSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readFloatSeqOpt', tag); + end + function r = readDouble(self) + v = libpointer('doublePtr', 0); + Ice.Util.callMethod(self, 'readDouble', v); + r = v.Value; + end + function r = readDoubleSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readDoubleSeq'); + end + function r = readDoubleOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readDoubleOpt', tag); + end + function r = readDoubleSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readDoubleSeqOpt', tag); + end + function r = readString(self) + r = Ice.Util.callMethodWithResult(self, 'readString'); + end + function r = readStringSeq(self) + r = Ice.Util.callMethodWithResult(self, 'readStringSeq'); + end + function r = readStringOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readStringOpt', tag); + end + function r = readStringSeqOpt(self, tag) + r = Ice.Util.callMethodWithResult(self, 'readStringSeqOpt', tag); + end + function skip(self, n) + Ice.Util.callMethod(self, 'skip', n); + end + function startException(self) + Ice.Util.callMethod(self, 'startException'); + end + function endException(self) + Ice.Util.callMethod(self, 'endException'); + end + function startEncapsulation(self) + Ice.Util.callMethod(self, 'startEncapsulation'); + end + function endEncapsulation(self) + Ice.Util.callMethod(self, 'endEncapsulation'); + end + function skipEmptyEncapsulation(self) + Ice.Util.callMethod(self, 'skipEmptyEncapsulation'); + end + function skipEncapsulation(self) + Ice.Util.callMethod(self, 'skipEncapsulation'); + end + function r = getEncoding(self) + r = Ice.Util.callMethodWithResult(self, 'getEncoding'); + end + function startSlice(self) + Ice.Util.callMethod(self, 'startSlice'); + end + function endSlice(self) + Ice.Util.callMethod(self, 'endSlice'); + end + function skipSlice(self) + Ice.Util.callMethod(self, 'skipSlice'); + end + function r = readSize(self) + v = libpointer('int32Ptr', 0); + Ice.Util.callMethod(self, 'readSize', v); + r = v.Value; + end + function r = readOptional(self, tag, fmt) + v = libpointer('uint8Ptr', 0); + Ice.Util.callMethod(self, 'readOptional', tag, fmt); + r = v.Value == 1; + end + function r = readProxy(self) + v = libpointer('voidPtr'); + Ice.Util.callMethod(self, 'readProxy', v); + if ~isNull(v) + r = Ice.ObjectPrx(v); + else + r = []; + end + end + function r = readProxyOpt(self, tag) + v = libpointer('voidPtr'); + Ice.Util.callMethod(self, 'readProxyOpt', tag, v); + if ~isNull(v) + r = Ice.ObjectPrx(v); + else + r = []; + end + end + function r = readEnum(self, maxValue) + v = libpointer('int32Ptr', 0); + Ice.Util.callMethod(self, 'readEnum', maxValue, v); + r = v.Value; + end + function throwException(self) + Ice.Util.callMethod(self, 'throwException', self); + end + end +end diff --git a/matlab/lib/+Ice/LocalException.m b/matlab/lib/+Ice/LocalException.m new file mode 100644 index 00000000000..4406fdb6601 --- /dev/null +++ b/matlab/lib/+Ice/LocalException.m @@ -0,0 +1,18 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) LocalException < Ice.Exception + methods + function obj = LocalException(id, msg) + obj = obj@Ice.Exception(id, msg) + end + end +end diff --git a/matlab/lib/+Ice/ObjectPrx.m b/matlab/lib/+Ice/ObjectPrx.m new file mode 100644 index 00000000000..fd45058b589 --- /dev/null +++ b/matlab/lib/+Ice/ObjectPrx.m @@ -0,0 +1,763 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef ObjectPrx < Ice.WrapperObject + methods + function self = ObjectPrx(impl) + self = self@Ice.WrapperObject(impl); + end + + function delete(self) + self.callMethod('_release'); + self.impl = []; + end + + % + % Override == operator. + % + function r = eq(self, other) + if isempty(other) || ~isa(other, 'Ice.ObjectPrx') + r = false; + else + v = libpointer('uint8Ptr', 0); + self.callMethod('equals', other.impl, v); + r = v.Value == 1; + end + end + + function r = ice_createOutputStream(self) + stream = libpointer('voidPtr'); + self.callMethod('ice_createOutputStream', stream); + r = Ice.OutputStream(stream); + end + + function r = ice_toString(self) + r = self.callMethodWithResult('ice_toString'); + end + + function r = ice_getCommunicator(self) + v = libpointer('voidPtr'); + self.callMethod('ice_getCommunicator', v); + assert(~isNull(v)); + r = Ice.Communicator(v); + end + + function ice_ping(self, varargin) + [ok, inStream] = self.invoke_('ice_ping', 'Nonmutating', false, [], varargin{:}); + self.checkNoResponse_(ok, inStream); + end + + function r = ice_pingAsync(self, varargin) + r = self.invokeAsync_('ice_ping', 'Nonmutating', false, [], 0, [], varargin{:}); + end + + function r = ice_isA(self, id, varargin) + os = self.startWriteParams_(); + os.writeString(id); + self.endWriteParams_(os); + [ok, inStream] = self.invoke_('ice_isA', 'Nonmutating', true, os, varargin{:}); + if ok + inStream.startEncapsulation(); + r = inStream.readBool(); + inStream.endEncapsulation(); + else + self.throwUserException_(inStream); + end + end + + function r = ice_isAAsync(self, id, varargin) + os = self.startWriteParams_(); + os.writeString(id); + self.endWriteParams_(os); + function varargout = unmarshal(ok, is) + if ok + is.startEncapsulation(); + varargout{1} = is.readBool(); + is.endEncapsulation(); + else + self.throwUserException_(is); + end + end + r = self.invokeAsync_('ice_isA', 'Nonmutating', true, os, 1, @unmarshal, varargin{:}); + end + + function r = ice_id(self, varargin) + [ok, inStream] = self.invoke_('ice_id', 'Nonmutating', true, [], varargin{:}); + if ok + inStream.startEncapsulation(); + r = inStream.readString(); + inStream.endEncapsulation(); + else + self.throwUserException_(inStream); + end + end + + function r = ice_idAsync(self, varargin) + function varargout = unmarshal(ok, is) + if ok + is.startEncapsulation(); + varargout{1} = is.readString(); + is.endEncapsulation(); + else + self.throwUserException_(is); + end + end + r = self.invokeAsync_('ice_id', 'Nonmutating', true, [], 1, @unmarshal, varargin{:}); + end + + function r = ice_ids(self, varargin) + [ok, inStream] = self.invoke_('ice_ids', 'Nonmutating', true, [], varargin{:}); + if ok + inStream.startEncapsulation(); + r = inStream.readStringSeq(); + inStream.endEncapsulation(); + else + self.throwUserException_(inStream); + end + end + + function r = ice_idsAsync(self, varargin) + function varargout = unmarshal(ok, is) + if ok + is.startEncapsulation(); + varargout{1} = is.readStringSeq(); + is.endEncapsulation(); + else + self.throwUserException_(is); + end + end + r = self.invokeAsync_('ice_ids', 'Nonmutating', true, [], 1, @unmarshal, varargin{:}); + end + + function r = ice_getIdentity(self) + r = self.callMethodWithResult('ice_getIdentity'); + end + + function r = ice_identity(self, id) + v = libpointer('voidPtr'); + self.callMethod('ice_identity', id, v); + if isNull(v) + r = self; + else + r = Ice.ObjectPrx(v); % Don't use newInstance_ here + end + end + + function r = ice_getContext(self) + r = self.callMethodWithResult('ice_getContext'); + end + + function r = ice_context(self, ctx) + v = libpointer('voidPtr'); + self.callMethod('ice_context', ctx, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getFacet(self) + r = self.callMethodWithResult('ice_getFacet'); + end + + function r = ice_facet(self, f) + v = libpointer('voidPtr'); + self.callMethod('ice_facet', f, v); + if isNull(v) + r = self; + else + r = Ice.ObjectPrx(v); % Don't use newInstance_ here + end + end + + function r = ice_getAdapterId(self) + r = self.callMethodWithResult('ice_getAdapterId'); + end + + function r = ice_adapterId(self, id) + v = libpointer('voidPtr'); + self.callMethod('ice_adapterId', id, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getEndpoints(self) + r = self.callMethodWithResult('ice_getEndpoints'); + end + + function r = ice_endpoints(self, endpts) + v = libpointer('voidPtr'); + self.callMethod('ice_endpoints', endpts, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getLocatorCacheTimeout(self) + v = libpointer('int32Ptr', 0); + self.callMethod('ice_getLocatorCacheTimeout', v); + r = v.Value; + end + + function r = ice_locatorcacheTimeout(self, t) + v = libpointer('voidPtr'); + self.callMethod('ice_locatorCacheTimeout', t, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getInvocationTimeout(self) + v = libpointer('int32Ptr', 0); + self.callMethod('ice_getInvocationTimeout', v); + r = v.Value; + end + + function r = ice_invocationTimeout(self, t) + v = libpointer('voidPtr'); + self.callMethod('ice_invocationTimeout', t, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getConnectionId(self) + r = self.callMethodWithResult('ice_getConnectionId'); + end + + function r = ice_connectionId(self, id) + v = libpointer('voidPtr'); + self.callMethod('ice_connectionId', id, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isConnectionCached(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isConnectionCached', v); + r = v.Value == 1; + end + + function r = ice_connectionCached(self, b) + v = libpointer('voidPtr'); + if b + val = 1; + else + val = 0; + end + self.callMethod('ice_connectionCached', val, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getEndpointSelection(self) + v = libpointer('Ice_EndpointSelectionType', 'Random'); + self.callMethod('ice_getEndpointSelection', v); + r = v.Value; + end + + function r = ice_endpointSelection(self, t) + v = libpointer('voidPtr'); + self.callMethod('ice_endpointSelection', t, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getEncodingVersion(self) + r = self.callMethodWithResult('ice_getEncodingVersion'); + end + + function r = ice_encodingVersion(self, ver) + v = libpointer('voidPtr'); + self.callMethod('ice_encodingVersion', ver, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getRouter(self) + v = libpointer('voidPtr'); + self.callMethod('ice_getRouter', v); + if isNull(v) + r = []; + else + r = Ice.RouterPrx(v); + end + end + + function r = ice_router(self, rtr) + v = libpointer('voidPtr'); + if isempty(rtr) + impl = libpointer('voidPtr'); + else + impl = rtr.impl; + end + self.callMethod('ice_router', impl, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getLocator(self) + v = libpointer('voidPtr'); + self.callMethod('ice_getLocator', v); + if isNull(v) + r = []; + else + r = Ice.LocatorPrx(v); + end + end + + function r = ice_locator(self, loc) + v = libpointer('voidPtr'); + if isempty(loc) + impl = libpointer('voidPtr'); + else + impl = loc.impl; + end + self.callMethod('ice_locator', impl, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isSecure(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isSecure', v); + r = v.Value == 1; + end + + function r = ice_secure(self, b) + v = libpointer('voidPtr'); + if b + val = 1; + else + val = 0; + end + self.callMethod('ice_secure', val, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isPreferSecure(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isPreferSecure', v); + r = v.Value == 1; + end + + function r = ice_preferSecure(self, b) + v = libpointer('voidPtr'); + if b + val = 1; + else + val = 0; + end + self.callMethod('ice_preferSecure', val, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isTwoway(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isTwoway', v); + r = v.Value == 1; + end + + function r = ice_twoway(self) + v = libpointer('voidPtr'); + self.callMethod('ice_twoway', v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isOneway(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isOneway', v); + r = v.Value == 1; + end + + function r = ice_oneway(self) + v = libpointer('voidPtr'); + self.callMethod('ice_oneway', v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isBatchOneway(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isBatchOneway', v); + r = v.Value == 1; + end + + function r = ice_batchOneway(self) + v = libpointer('voidPtr'); + self.callMethod('ice_batchOneway', v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isDatagram(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isDatagram', v); + r = v.Value == 1; + end + + function r = ice_datagram(self) + v = libpointer('voidPtr'); + self.callMethod('ice_datagram', v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_isBatchDatagram(self) + v = libpointer('uint8Ptr', 0); + self.callMethod('ice_isBatchDatagram', v); + r = v.Value == 1; + end + + function r = ice_batchDatagram(self) + v = libpointer('voidPtr'); + self.callMethod('ice_batchDatagram', v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_compress(self, b) + v = libpointer('voidPtr'); + if b + val = 1; + else + val = 0; + end + self.callMethod('ice_compress', val, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_timeout(self, t) + v = libpointer('voidPtr'); + self.callMethod('ice_timeout', t, v); + if isNull(v) + r = self; + else + r = self.newInstance_(v); + end + end + + function r = ice_getConnection(self) + v = libpointer('voidPtr'); + self.callMethod('ice_getConnection', v); + if isNull(v) + r = []; + else + r = Ice.Connection(v); + end + end + + function r = ice_getConnectionAsync(self) + future = libpointer('voidPtr'); + self.callMethod('ice_getConnectionAsync', future); + assert(~isNull(future)); + function varargout = fetch(f) + con = libpointer('voidPtr', 0); % Output param + Ice.Util.callMethodOnType(f, 'Ice_GetConnectionFuture', 'fetch', con); + assert(~isNull(con)); + varargout{1} = Ice.Connection(con); + end + r = Ice.Future(future, 'ice_getConnection', 1, 'Ice_GetConnectionFuture', @fetch); + end + + function r = ice_getCachedConnection(self) + v = libpointer('voidPtr'); + self.callMethod('ice_getCachedConnection', v); + if isNull(v) + r = []; + else + r = Ice.Connection(v); + end + end + + function ice_flushBatchRequests(self) + self.callMethod('ice_flushBatchRequests'); + end + + function r = ice_flushBatchRequestsAsync(self) + future = libpointer('voidPtr'); + self.callMethod('ice_flushBatchRequestsAsync', future); + assert(~isNull(future)); + r = Ice.Future(future, 'ice_flushBatchRequests', 0, 'Ice_SentFuture', []); + end + end + + methods(Access=protected) + function checkNoResponse_(self, ok, inStream) + if self.ice_isTwoway() + if ok == 0 + try + self.throwUserException_(inStream); + catch ex + ex.throwAsCaller(); + end + else + inStream.skipEmptyEncapsulation(); + end + end + end + + function os = startWriteParams_(self) + os = self.ice_createOutputStream(); + os.startEncapsulation(); + end + + function os = startWriteParamsWithFormat_(self, format) + os = self.ice_createOutputStream(); + os.startEncapsulationWithFormat(format); + end + + function endWriteParams_(self, os) + os.endEncapsulation(); + end + + function [ok, inStream] = invoke_(self, op, mode, twowayOnly, os, varargin) + try + % Vararg accepted for optional context argument. + if length(varargin) > 1 + throw(MException('Ice:ArgumentException', 'one optional argument is allowed for request context')) + end + if twowayOnly && ~self.ice_isTwoway() + throw(Ice.TwowayOnlyException('', 'invocation requires twoway proxy', op)); + end + if ~isempty(os) + outStream = os.impl; + else + outStream = libpointer('voidPtr'); % Null pointer for output stream + end + okPtr = libpointer('uint8Ptr', 0); % Output param + inStreamPtr = libpointer('voidPtr'); % Output param + if length(varargin) == 1 + self.callMethod('ice_invoke', op, mode, outStream, varargin{1}, okPtr, inStreamPtr); + else + self.callMethod('ice_invokeNC', op, mode, outStream, okPtr, inStreamPtr); + end + ok = okPtr.Value == 1; + inStream = []; + if ~isNull(inStreamPtr) + inStream = Ice.InputStream(inStreamPtr); + end + catch ex + ex.throwAsCaller(); + end + end + + function fut = invokeAsync_(self, op, mode, twowayOnly, os, numOutArgs, unmarshalFunc, varargin) + function varargout = fetch(f) + okPtr = libpointer('uint8Ptr', 0); % Output param + inStreamPtr = libpointer('voidPtr', 0); % Output param + Ice.Util.callMethodOnType(f, 'Ice_InvocationFuture', 'stream', okPtr, inStreamPtr); + ok = okPtr.Value == 1; + assert(~isNull(inStreamPtr)); + inStream = Ice.InputStream(inStreamPtr); + [varargout{1:numOutArgs}] = unmarshalFunc(ok, inStream); + end + try + % Vararg accepted for optional context argument. + if length(varargin) > 1 + throw(MException('Ice:ArgumentException', 'one optional argument is allowed for request context')) + end + if twowayOnly && ~self.ice_isTwoway() + throw(Ice.TwowayOnlyException('', 'invocation requires twoway proxy', op)); + end + if ~isempty(os) + outStream = os.impl; + else + outStream = libpointer('voidPtr'); % Null pointer for output stream + end + futPtr = libpointer('voidPtr'); % Output param + if length(varargin) == 1 + self.callMethod('ice_invokeAsync', op, mode, outStream, varargin{1}, futPtr); + else + self.callMethod('ice_invokeAsyncNC', op, mode, outStream, futPtr); + end + assert(~isNull(futPtr)); + fut = Ice.Future(futPtr, op, numOutArgs, 'Ice_InvocationFuture', @fetch); + catch ex + ex.throwAsCaller(); + end + end + + function throwUserException_(self, inStream, varargin) % Varargs are user exception type names + try + inStream.throwUserException(); + catch ex + if isa(ex, Ice.UserException) + for i = 1:length(varargin) + if isa(ex, varargin{i}) + ex.throwAsCaller(); + end + end + uue = Ice.UnknownUserException('', '', ex.ice_id()); + uue.throwAsCaller(); + else + ex.throwAsCaller(); + end + end + end + + function r = newInstance_(self, impl) + constructor = str2func(class(self)); % Obtain the constructor for this class + r = constructor(impl); % Call the constructor + end + + function r = clone_(self) + implPtr = libpointer('voidPtr'); % Output param + self.callMethod('clone', implPtr); + r = implPtr; + end + end + + methods(Access=private) + % We don't use the functions in Ice.Util because they use the most-derived class name, whereas we always + % want to use Ice_ObjectPrx_xxx. + function callMethod(self, fn, varargin) + name = strcat('Ice_ObjectPrx_', fn); + ex = calllib('icematlab', name, self.impl, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + + function r = callMethodWithResult(self, fn, varargin) + name = strcat('Ice_ObjectPrx_', fn); + result = calllib('icematlab', name, self.impl, varargin{:}); + if ~isempty(result.exception) + result.exception.throwAsCaller(); + end + r = result.result; + end + end + + methods(Static,Access=protected) + function r = read_(inStream, cls) + p = inStream.readProxy(); + if ~isempty(p) + constructor = str2func(cls); + r = constructor(p.clone_()); + else + r = []; + end + end + + function r = checkedCast_(p, id, cls, varargin) + %try + hasFacet = false; + facet = []; + context = {}; + if length(varargin) == 1 + facet = varargin{1}; + hasFacet = true; + elseif length(varargin) == 2 + facet = varargin{1}; + context = {varargin{2}}; + elseif length(varargin) > 2 + throw(MException('Ice:ArgumentException', 'too many arguments to checkedCast')); + end + if ~isempty(p) + if hasFacet + p = p.ice_facet(facet); + end + if isa(p, cls) + r = p; + elseif p.ice_isA(id, context{:}) + constructor = str2func(cls); + r = constructor(p.clone_()); + else + r = []; + end + else + r = p; + end + %catch ex + % ex.throwAsCaller(); + %end + end + + function r = uncheckedCast_(p, cls, varargin) + facet = []; + if length(varargin) == 1 + facet = varargin{1}; + elseif length(varargin) > 1 + throw(MException('Ice:ArgumentException', 'too many arguments to uncheckedCast')); + end + if ~isempty(p) + if ~isempty(facet) + p = p.ice_facet(facet); + end + if isa(p, cls) + r = p; + else + constructor = str2func(cls); + r = constructor(p.clone_()); + end + else + r = p; + end + end + end +end diff --git a/matlab/lib/+Ice/Optional.m b/matlab/lib/+Ice/Optional.m new file mode 100644 index 00000000000..ec30540fd11 --- /dev/null +++ b/matlab/lib/+Ice/Optional.m @@ -0,0 +1,48 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Optional + methods + function obj = Optional(v) + if nargin == 0 + obj.isSet = false + else + obj.value = v + end + end + function obj = set.value(obj, v) + if isempty(v) + obj.value = v + obj.isSet = false + else + obj.value = v + obj.isSet = true + end + end + function v = get.value(obj) + if obj.isSet + v = obj.value + else + throw(MException('ICE:IllegalStateException', 'Optional does not have a value')) + end + end + function obj = clear(obj) % Use with v = v.clear() + obj.value = [] + obj.isSet = false + end + end + properties + value + end + properties(SetAccess = private) + isSet + end +end diff --git a/matlab/lib/+Ice/OutputStream.m b/matlab/lib/+Ice/OutputStream.m new file mode 100644 index 00000000000..32e5b8220f0 --- /dev/null +++ b/matlab/lib/+Ice/OutputStream.m @@ -0,0 +1,161 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef OutputStream < Ice.WrapperObject + methods + function self = OutputStream(impl) + self = self@Ice.WrapperObject(impl); + end + function writeBool(self, v) + Ice.Util.callMethod(self, 'writeBool', v); + end + function writeBoolOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeBoolOpt', tag, v); + end + function writeBoolSeq(self, v) + Ice.Util.callMethod(self, 'writeBoolSeq', v, length(v)); + end + function writeBoolSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeBoolSeqOpt', tag, v, length(v)); + end + function writeByte(self, v) + Ice.Util.callMethod(self, 'writeByte', v); + end + function writeByteOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeByteOpt', tag, v); + end + function writeByteSeq(self, v) + Ice.Util.callMethod(self, 'writeByteSeq', v, length(v)); + end + function writeByteSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeByteSeqOpt', tag, v, length(v)); + end + function writeShort(self, v) + Ice.Util.callMethod(self, 'writeShort', v); + end + function writeShortOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeShortOpt', tag, v); + end + function writeShortSeq(self, v) + Ice.Util.callMethod(self, 'writeShortSeq', v, length(v)); + end + function writeShortSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeShortSeqOpt', tag, v, length(v)); + end + function writeInt(self, v) + Ice.Util.callMethod(self, 'writeInt', v); + end + function writeIntOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeIntOpt', tag, v); + end + function writeIntSeq(self, v) + Ice.Util.callMethod(self, 'writeIntSeq', v, length(v)); + end + function writeIntSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeIntSeqOpt', tag, v, length(v)); + end + function writeLong(self, v) + Ice.Util.callMethod(self, 'writeLong', v); + end + function writeLongOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeLongOpt', tag, v); + end + function writeLongSeq(self, v) + Ice.Util.callMethod(self, 'writeLongSeq', v, length(v)); + end + function writeLongSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeLongSeqOpt', tag, v, length(v)); + end + function writeFloat(self, v) + Ice.Util.callMethod(self, 'writeFloat', v); + end + function writeFloatOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeFloatOpt', tag, v); + end + function writeFloatSeq(self, v) + Ice.Util.callMethod(self, 'writeFloatSeq', v, length(v)); + end + function writeFloatSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeFloatSeqOpt', tag, v, length(v)); + end + function writeDouble(self, v) + Ice.Util.callMethod(self, 'writeDouble', v); + end + function writeDoubleOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeDoubleOpt', tag, v); + end + function writeDoubleSeq(self, v) + Ice.Util.callMethod(self, 'writeDoubleSeq', v, length(v)); + end + function writeDoubleSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeDoubleSeqOpt', tag, v, length(v)); + end + function writeString(self, str) + Ice.Util.callMethod(self, 'writeString', str); + end + function writeStringOpt(self, tag, str) + Ice.Util.callMethod(self, 'writeStringOpt', tag, str); + end + function writeStringSeq(self, v) + Ice.Util.callMethod(self, 'writeStringSeq', v); + end + function writeStringSeqOpt(self, tag, v) + Ice.Util.callMethod(self, 'writeStringSeqOpt', tag, v); + end + function writeSize(self, size) + Ice.Util.callMethod(self, 'writeSize', size); + end + function writeProxy(self, v) + if isempty(v) + impl = libpointer; + else + impl = v.impl; + end + Ice.Util.callMethod(self, 'writeProxy', impl); + end + function writeProxyOpt(self, tag, v) + if ~isempty(v) + Ice.Util.callMethod(self, 'writeProxyOpt', tag, v.impl); + end + end + function writeEnum(self, v, maxValue) + Ice.Util.callMethod(self, 'writeEnum', v, maxValue); + end + function startEncapsulation(self) + Ice.Util.callMethod(self, 'startEncapsulation'); + end + function startEncapsulationWithFormat(self, fmt) + Ice.Util.callMethod(self, 'startEncapsulationWithFormat', fmt); + end + function endEncapsulation(self) + Ice.Util.callMethod(self, 'endEncapsulation'); + end + function startSlice(self, typeId, compactId, last) + Ice.Util.callMethod(self, 'startSlice', typeId, compactId, last); + end + function endSlice(self) + Ice.Util.callMethod(self, 'endSlice'); + end + function r = writeOptional(self, tag, f) + supportsOptionals = libpointer('uint8Ptr', 0); + Ice.Util.callMethod(self, 'writeOptional', tag, f, supportsOptionals); + r = supportsOptionals.Value; + end + function r = startSize(self) + pos = libpointer('uint32Ptr', 0); + Ice.Util.callMethod(self, 'startSize', pos); + r = pos.Value; + end + function endSize(self, pos) + Ice.Util.callMethod(self, 'endSize', pos); + end + end +end diff --git a/matlab/lib/+Ice/Properties.m b/matlab/lib/+Ice/Properties.m new file mode 100644 index 00000000000..7a8ad2848d1 --- /dev/null +++ b/matlab/lib/+Ice/Properties.m @@ -0,0 +1,63 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Properties < Ice.WrapperObject + methods + function self = Properties(impl) + self = self@Ice.WrapperObject(impl); + end + function r = getProperty(self, key) + r = Ice.Util.callMethodWithResult(self, 'getProperty', key); + end + function r = getPropertyWithDefault(self, key, def) + r = Ice.Util.callMethodWithResult(self, 'getPropertyWithDefault', key, def); + end + function r = getPropertyAsInt(self, key) + v = libpointer('int32Ptr', 0); + Ice.Util.callMethod(self, 'getPropertyAsInt', key, v); + r = v.Value; + end + function r = getPropertyAsIntWithDefault(self, key, def) + v = libpointer('int32Ptr', 0); + Ice.Util.callMethod(self, 'getPropertyAsIntWithDefault', key, def, v); + r = v.Value; + end + function r = getPropertyAsList(self, key) + r = Ice.Util.callMethodWithResult(self, 'getPropertyAsList', key); + end + function r = getPropertyAsListWithDefault(self, key, def) + r = Ice.Util.callMethodWithResult(self, 'getPropertyAsListWithDefault', key, def); + end + function r = getPropertiesForPrefix(self, prefix) + r = Ice.Util.callMethodWithResult(self, 'getPropertiesForPrefix', prefix); + end + function setProperty(self, key, value) + Ice.Util.callMethod(self, 'setProperty', key, value); + end + function r = getCommandLineOptions(self) + r = Ice.Util.callMethodWithResult(self, 'getCommandLineOptions'); + end + function r = parseCommandLineOptions(self, prefix, options) + r = Ice.Util.callMethodWithResult(self, 'parseCommandLineOptions', prefix, options); + end + function r = parseIceCommandLineOptions(self, options) + r = Ice.Util.callMethodWithResult(self, 'parseIceCommandLineOptions', options); + end + function load(self, file) + Ice.Util.callMethod(self, 'load', file); + end + function r = clone(self) + impl = libpointer('voidPtr'); + Ice.Util.callMethod(self, 'clone', impl); + r = Ice.Properties(impl); + end + end +end diff --git a/matlab/lib/+Ice/UserException.m b/matlab/lib/+Ice/UserException.m new file mode 100644 index 00000000000..8c74080ecbb --- /dev/null +++ b/matlab/lib/+Ice/UserException.m @@ -0,0 +1,29 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) UserException < Ice.Exception + methods + function obj = UserException(id, msg) + obj = obj@Ice.Exception(id, msg) + end + function self = read_(self, is) + is.startException(); + self = self._readImpl(is); + is.endException(); + end + function r = usesClasses_(self) + r = false + end + end + methods(Abstract) + self = readImpl_(self, is) + end +end diff --git a/matlab/lib/+Ice/Util.m b/matlab/lib/+Ice/Util.m new file mode 100644 index 00000000000..297eaff7522 --- /dev/null +++ b/matlab/lib/+Ice/Util.m @@ -0,0 +1,116 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Util + methods(Static) + % + % Internal method - invoke a C function with the given name. + % The value for fn MUST be given in single quotes! + % + function call(fn, varargin) + ex = calllib('icematlab', fn, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + + % + % Internal method - invoke a C function representing a global function. + % The value for fn MUST be given in single quotes! + % + function r = callWithResult(fn, varargin) + result = calllib('icematlab', fn, varargin{:}); + if isempty(result) + r = result; + elseif ~isempty(result.exception) + result.exception.throwAsCaller(); + else + r = result.result; + end + end + + % + % Internal method - invoke a C function representing an object method. + % The value for fn MUST be given in single quotes! + % + function callMethod(self, fn, varargin) + name = replace(strcat(class(self), '.', fn), '.', '_'); + ex = calllib('icematlab', name, self.impl, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + + % + % Internal method - invoke a C function representing an object method. + % The value for fn MUST be given in single quotes! + % + function r = callMethodWithResult(self, fn, varargin) + name = replace(strcat(class(self), '.', fn), '.', '_'); + result = calllib('icematlab', name, self.impl, varargin{:}); + if isempty(result) + r = result; + elseif ~isempty(result.exception) + result.exception.throwAsCaller(); + else + r = result.result; + end + end + + % + % Internal method - invoke a C function representing an object method. + % The value for fn MUST be given in single quotes! + % + function callMethodOnType(self, type, fn, varargin) + name = strcat(type, '_', fn); + ex = calllib('icematlab', name, self.impl, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + + % + % Internal method - invoke a C function representing an object method. + % The value for fn MUST be given in single quotes! + % + function r = callMethodOnTypeWithResult(self, type, fn, varargin) + name = strcat(type, '_', fn); + result = calllib('icematlab', name, self.impl, varargin{:}); + if isempty(result) + r = result; + elseif ~isempty(result.exception) + result.exception.throwAsCaller(); + else + r = result.result; + end + end + + function r = strcmp(s1, s2) + n = min(length(s1), length(s2)); + for i = 1:n + if s1(i) < s2(i) + r = -1; + return; + elseif s1(i) > s2(i) + r = 1; + return; + end + end + if length(s1) > n + r = 1; + elseif length(s2) > n + r = -1; + else + r = 0; + end + end + end +end diff --git a/matlab/lib/+Ice/Value.m b/matlab/lib/+Ice/Value.m new file mode 100644 index 00000000000..0e24b1ee5e7 --- /dev/null +++ b/matlab/lib/+Ice/Value.m @@ -0,0 +1,41 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) Value < matlab.mixin.Copyable + methods + function ice_preMarshal(obj) + end + function ice_postUnmarshal(obj) + end + function id = ice_id(obj) + id = ice_staticId() + end + function iceWrite_(self, os) + os.startValue([]); + self.iceWriteImpl_(os); + os.endValue(); + end + function self = iceRead_(self, is) + is.startValue(); + self = self.iceReadImpl_(is); + is.endValue(false); + end + end + methods(Abstract) + iceWriteImpl_(self, os) + self = iceReadImpl_(self, is) + end + methods(Static) + function id = ice_staticId() + id = '::Ice::Object' + end + end +end diff --git a/matlab/lib/+Ice/WrapperObject.m b/matlab/lib/+Ice/WrapperObject.m new file mode 100644 index 00000000000..b5c1e019558 --- /dev/null +++ b/matlab/lib/+Ice/WrapperObject.m @@ -0,0 +1,26 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) WrapperObject < handle + methods + function self = WrapperObject(impl) + self.impl = impl; + end + function delete(self) + if ~isempty(self.impl) + Ice.Util.callMethod(self, '_release'); + end + end + end + properties(Hidden,SetAccess=protected) + impl + end +end diff --git a/matlab/lib/+Ice/createProperties.m b/matlab/lib/+Ice/createProperties.m new file mode 100644 index 00000000000..d619a4de343 --- /dev/null +++ b/matlab/lib/+Ice/createProperties.m @@ -0,0 +1,29 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function [properties, remArgs] = createProperties(varargin) + if length(varargin) >= 1 && ~isempty(varargin{1}) + args = varargin{1}; + else + args = {}; + end + if length(varargin) >= 2 && ~isempty(varargin{2}) + if ~isa(varargin{2}, 'Ice.Properties') + throw(MException('Ice:ArgumentException', 'expecting Ice.Properties object')); + end + defaults = varargin{2}.impl; + else + defaults = libpointer('voidPtr'); + end + impl = libpointer('voidPtr'); + remArgs = Ice.Util.callWithResult('Ice_createProperties', args, defaults, impl); + properties = Ice.Properties(impl); +end diff --git a/matlab/lib/+Ice/identityToString.m b/matlab/lib/+Ice/identityToString.m new file mode 100644 index 00000000000..d3580ef1819 --- /dev/null +++ b/matlab/lib/+Ice/identityToString.m @@ -0,0 +1,14 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = identityToString(id) + r = Ice.Util.callWithResult('Ice_identityToString', id); +end diff --git a/matlab/lib/+Ice/initialize.m b/matlab/lib/+Ice/initialize.m new file mode 100644 index 00000000000..b164fe6c40a --- /dev/null +++ b/matlab/lib/+Ice/initialize.m @@ -0,0 +1,47 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function [communicator, args] = initialize(varargin) + if length(varargin) >= 1 && ~isempty(varargin{1}) + args = varargin{1}; + else + args = {}; + end + + if length(varargin) >= 2 && ~isempty(varargin{2}) + if ~isa(varargin{2}, 'Ice.InitializationData') + throw(MException('Ice:ArgumentException', 'initData argument must be an Ice.InitializationData object')); + end + initData = varargin{2}; + else + initData = []; + end + + % + % Implementation note: We need to extract and pass the libpointer object for properties to the C function. + % Passing the wrapper (Ice.Properties) object won't work because the C code has no way to obtain the + % inner pointer. + % + props = libpointer('voidPtr'); + if ~isempty(initData) + if ~isempty(initData.properties_) + if ~isa(initData.properties_, 'Ice.Properties') + throw(MException('Ice:ArgumentException', 'invalid value for properties_ member')); + else + props = initData.properties_.impl; + end + end + end + + impl = libpointer('voidPtr'); + args = Ice.Util.callWithResult('Ice_initialize', args, props, impl); + communicator = Ice.Communicator(impl); +end diff --git a/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m b/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m new file mode 100644 index 00000000000..ff9549f0188 --- /dev/null +++ b/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m @@ -0,0 +1,45 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = proxyIdentityAndFacetCompare(lhs, rhs) + if isempty(lhs) && isempty(rhs) + r = 0; + elseif isempty(lhs) && ~isempty(rhs) + r = -1; + elseif ~isempty(lhs) && isempty(rhs) + r = 1; + else + lhsIdentity = lhs.ice_getIdentity(); + rhsIdentity = rhs.ice_getIdentity(); + n = Ice.Util.strcmp(lhsIdentity.name, rhsIdentity.name); + if n ~= 0 + r = n; + return; + end + n = Ice.Util.strcmp(lhsIdentity.category, rhsIdentity.category); + if n ~= 0 + r = n; + return; + end + + lhsFacet = lhs.ice_getFacet(); + rhsFacet = rhs.ice_getFacet(); + if isempty(lhsFacet) && isempty(rhsFacet) + r = 0; + elseif isempty(lhsFacet) + r = -1; + elseif isempty(rhsFacet) + r = 1; + else + r = Ice.Util.strcmp(lhsFacet, rhsFacet); + end + end +end diff --git a/matlab/lib/+Ice/proxyIdentityCompare.m b/matlab/lib/+Ice/proxyIdentityCompare.m new file mode 100644 index 00000000000..0b660c86346 --- /dev/null +++ b/matlab/lib/+Ice/proxyIdentityCompare.m @@ -0,0 +1,29 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = proxyIdentityCompare(lhs, rhs) + if isempty(lhs) && isempty(rhs) + r = 0; + elseif isempty(lhs) && ~isempty(rhs) + r = -1; + elseif ~isempty(lhs) && isempty(rhs) + r = 1; + else + lhsIdentity = lhs.ice_getIdentity(); + rhsIdentity = rhs.ice_getIdentity(); + n = Ice.Util.strcmp(lhsIdentity.name, rhsIdentity.name); + if n ~= 0 + r = n; + return; + end + r = Ice.Util.strcmp(lhsIdentity.category, rhsIdentity.category); + end +end diff --git a/matlab/lib/+Ice/stringToIdentity.m b/matlab/lib/+Ice/stringToIdentity.m new file mode 100644 index 00000000000..e846ad1a61e --- /dev/null +++ b/matlab/lib/+Ice/stringToIdentity.m @@ -0,0 +1,14 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = stringToIdentity(s) + r = Ice.Util.callWithResult('Ice_stringToIdentity', s); +end diff --git a/matlab/lib/generated/.gitignore b/matlab/lib/generated/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/matlab/lib/generated/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/matlab/msbuild/ice.proj b/matlab/msbuild/ice.proj new file mode 100644 index 00000000000..0b777a901b9 --- /dev/null +++ b/matlab/msbuild/ice.proj @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + + <PropertyGroup> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Configuration Condition="'$(Configuration)' == ''">Release</Configuration> + </PropertyGroup> + + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <Import Project="$(MSBuildThisFileDirectory)\..\..\config\ice.common.targets"/> + + <PropertyGroup> + <topSrcDir>$(MSBuildThisFileDirectory)..\..</topSrcDir> + <sliceDir>$(topSrcDir)\slice</sliceDir> + <srcDir>$(MSBuildThisFileDirectory)..\src\IceMatlab</srcDir> + <testDir>$(MSBuildThisFileDirectory)..\test</testDir> + <slice2matlabexe>$(topSrcDir)\cpp\bin\$(Platform)\$(Configuration)\slice2matlab</slice2matlabexe> + <slice2matlab Condition="'$(DefaultPlatformToolset)' == 'v140'">c++98\slice2matlab</slice2matlab> + <cpp11core Condition="'$(DefaultPlatformToolset)' == 'v140'">c++11\ice++11</cpp11core> + </PropertyGroup> + + <ItemGroup> + <Slice Include="$(sliceDir)\Ice\Connection.ice" /> + <Slice Include="$(sliceDir)\Ice\Current.ice" /> + <Slice Include="$(sliceDir)\Ice\Identity.ice" /> + <Slice Include="$(sliceDir)\Ice\LocalException.ice" /> + <Slice Include="$(sliceDir)\Ice\Version.ice" /> + </ItemGroup> + + <Target Name="CppPrereqs"> + <MSBuild Projects="$(topSrcDir)\cpp\msbuild\ice.proj" + Targets="NuGetRestore" + BuildInParallel="false"/> + + <MSBuild Projects="$(topSrcDir)\cpp\msbuild\ice.$(DefaultPlatformToolset).sln" + Targets="$(slice2matlab);$(cpp11core)" + BuildInParallel="false" + Properties="Platform=$(Platform);Configuration=$(Configuration)"/> + </Target> + + <Target Name="Build" DependsOnTargets="CppPrereqs"> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(MSBuildThisFileDirectory)..\lib\generated %(Slice.FullPath)"/> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\operations\generated $(testDir)\Ice\operations\Test.ice"/> + <Exec Command="mex -outdir $(srcDir) -output icematlab -I$(topSrcDir)\cpp\include -I$(topSrcDir)\cpp\include\generated\cpp11\$(Platform)\$(Configuration) -DICE_CPP11_MAPPING -DICE_BUILDING_SRC -L$(topSrcDir)\cpp\lib\$(Platform)\$(Configuration) -lmex -lmx $(srcDir)\*.cpp"/> + <Exec Command="copy /Y $(topSrcDir)\cpp\bin\$(Platform)\$(Configuration)\bzip2.dll $(srcDir)"/> + <Exec Command="copy /Y "$(topSrcDir)\cpp\bin\$(Platform)\$(Configuration)\ice37++11.dll" $(srcDir)"/> + </Target> + +</Project> diff --git a/matlab/src/IceMatlab/Communicator.cpp b/matlab/src/IceMatlab/Communicator.cpp new file mode 100644 index 00000000000..0d4208bf9f9 --- /dev/null +++ b/matlab/src/IceMatlab/Communicator.cpp @@ -0,0 +1,86 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Communicator.h> +#include <Ice/Proxy.h> +#include <Ice/OutputStream.h> +#include "icematlab.h" +#include "Util.h" + +#define SELF (*(reinterpret_cast<shared_ptr<Ice::Communicator>*>(self))) + +using namespace std; +using namespace IceMatlab; + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_Communicator__release(void* self) +{ + delete &SELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Communicator_stringToProxy(void* self, const char* s, void** proxy) +{ + try + { + shared_ptr<Ice::ObjectPrx> p = SELF->stringToProxy(s); + *proxy = new shared_ptr<Ice::ObjectPrx>(p); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Communicator_getProperties(void* self, void** props) +{ + try + { + shared_ptr<Ice::Properties> p = SELF->getProperties(); + *props = new shared_ptr<Ice::Properties>(p); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Communicator_createOutputStream(void* self, mxArray* encoding, void** stream) +{ + Ice::EncodingVersion v; + getEncodingVersion(encoding, v); + *stream = new Ice::OutputStream(SELF, v); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Communicator_destroy(void* self) +{ + try + { + SELF->destroy(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +} diff --git a/matlab/src/IceMatlab/Connection.cpp b/matlab/src/IceMatlab/Connection.cpp new file mode 100644 index 00000000000..fd965e75d13 --- /dev/null +++ b/matlab/src/IceMatlab/Connection.cpp @@ -0,0 +1,286 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Ice.h> +#include "icematlab.h" +#include "Future.h" +#include "Util.h" + +#define SELF (*(reinterpret_cast<shared_ptr<Ice::Connection>*>(self))) + +using namespace std; +using namespace IceMatlab; + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_Connection__release(void* self) +{ + delete &SELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_close(void* self, mxArray* m) +{ + try + { + Ice::ConnectionClose mode = static_cast<Ice::ConnectionClose>(getEnumerator(m, "Ice.ConnectionClose")); + SELF->close(mode); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_createProxy(void* self, mxArray* id, void** r) +{ + try + { + Ice::Identity ident; + getIdentity(id, ident); + shared_ptr<Ice::ObjectPrx> proxy = SELF->createProxy(ident); + *r = new shared_ptr<Ice::ObjectPrx>(proxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_flushBatchRequests(void* self, mxArray* c) +{ + try + { + Ice::CompressBatch mode = static_cast<Ice::CompressBatch>(getEnumerator(c, "Ice.CompressBatch")); + SELF->flushBatchRequests(mode); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_flushBatchRequestsAsync(void* self, mxArray* c, void** future) +{ + *future = 0; + auto f = make_shared<SentFuture>(); + + try + { + Ice::CompressBatch mode = static_cast<Ice::CompressBatch>(getEnumerator(c, "Ice.CompressBatch")); + function<void()> token = SELF->flushBatchRequestsAsync( + mode, + [f](exception_ptr e) + { + f->exception(e); + }, + [f](bool /*sentSynchronously*/) + { + f->sent(); + }); + f->token(token); + *future = new shared_ptr<SentFuture>(f); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_heartbeat(void* self) +{ + try + { + SELF->heartbeat(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_heartbeatAsync(void* self, void** future) +{ + *future = 0; + auto f = make_shared<SentFuture>(); + + try + { + function<void()> token = SELF->heartbeatAsync( + [f](exception_ptr e) + { + f->exception(e); + }, + [f](bool /*sentSynchronously*/) + { + f->sent(); + }); + f->token(token); + *future = new shared_ptr<SentFuture>(f); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_setACM(void* self, mxArray* t, mxArray* c, mxArray* h) +{ + Ice::optional<int> timeout; + Ice::optional<Ice::ACMClose> close; + Ice::optional<Ice::ACMHeartbeat> heartbeat; + + try + { + if(!mxIsEmpty(t)) + { + if(!mxIsScalar(t)) + { + throw invalid_argument("scalar value required for timeout"); + } + if(!mxIsNumeric(t)) + { + throw invalid_argument("numeric value required for timeout"); + } + timeout = static_cast<int>(mxGetScalar(t)); + } + if(!mxIsEmpty(c)) + { + if(!mxIsClass(c, "Ice.ACMClose")) + { + throw invalid_argument("ACMClose enumerator required for close"); + } + close = static_cast<Ice::ACMClose>(static_cast<int>(mxGetScalar(c))); + } + if(!mxIsEmpty(h)) + { + if(!mxIsClass(c, "Ice.ACMHeartbeat")) + { + throw invalid_argument("ACMHeartbeat enumerator required for heartbeat"); + } + heartbeat = static_cast<Ice::ACMHeartbeat>(static_cast<int>(mxGetScalar(h))); + } + SELF->setACM(timeout, close, heartbeat); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_getACM(void* self) +{ + try + { + Ice::ACM acm = SELF->getACM(); + mxArray* params[3]; + params[0] = createInt(acm.timeout); + params[1] = createEnumerator("Ice.ACMClose", static_cast<int>(acm.close)); + params[2] = createEnumerator("Ice.ACMHeartbeat", static_cast<int>(acm.heartbeat)); + mxArray* r; + mexCallMATLAB(1, &r, 3, params, "Ice.ACM"); + return createResultValue(r); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_type(void* self) +{ + try + { + return createResultValue(createStringFromUTF8(SELF->type())); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_timeout(void* self, int* timeout) +{ + try + { + *timeout = SELF->timeout(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_toString(void* self) +{ + try + { + return createResultValue(createStringFromUTF8(SELF->toString())); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_setBufferSize(void* self, int rcvSize, int sndSize) +{ + try + { + SELF->setBufferSize(rcvSize, sndSize); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Connection_throwException(void* self) +{ + try + { + SELF->throwException(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +} diff --git a/matlab/src/IceMatlab/Future.cpp b/matlab/src/IceMatlab/Future.cpp new file mode 100644 index 00000000000..f3d326c2135 --- /dev/null +++ b/matlab/src/IceMatlab/Future.cpp @@ -0,0 +1,166 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include "icematlab.h" +#include "Future.h" +#include "Util.h" + +using namespace std; +using namespace IceMatlab; + +void +IceMatlab::Future::token(function<void()> t) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(!isFinished()) + { + _token = std::move(t); + } +} + +bool +IceMatlab::Future::waitUntilFinished() +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + while(!isFinished()) + { + wait(); + } + return !_exception; +} + +void +IceMatlab::Future::exception(exception_ptr e) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _token = nullptr; + _exception = e; + notifyAll(); +} + +exception_ptr +IceMatlab::Future::getException() const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + return _exception; +} + +void +IceMatlab::Future::sent() +{ +} + +void +IceMatlab::Future::cancel() +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(_token) + { + _token(); + _token = nullptr; + } +} + +IceMatlab::SentFuture::SentFuture() : + _sent(false) +{ +} + +void +IceMatlab::SentFuture::sent() +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _sent = true; + notifyAll(); +} + +string +IceMatlab::SentFuture::state() const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(_exception || _sent) + { + return "finished"; + } + else + { + return "running"; + } +} + +bool +IceMatlab::SentFuture::isFinished() const +{ + return _sent || _exception; +} + +#define SFSELF (*(reinterpret_cast<shared_ptr<SentFuture>*>(self))) + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_SentFuture__release(void* self) +{ + delete &SFSELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_SentFuture_id(void* self, unsigned long long* id) +{ + *id = reinterpret_cast<unsigned long long>(self); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_SentFuture_wait(void* self, unsigned char* ok) +{ + // TBD: Timeout? + + bool b = SFSELF->waitUntilFinished(); + *ok = b ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_SentFuture_state(void* self) +{ + return createResultValue(createStringFromUTF8(SFSELF->state())); +} + +EXPORTED_FUNCTION mxArray* +Ice_SentFuture_cancel(void* self) +{ + SFSELF->cancel(); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_SentFuture_check(void* self) +{ + if(!SFSELF->waitUntilFinished()) + { + assert(SFSELF->getException()); + try + { + rethrow_exception(SFSELF->getException()); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + } + + return 0; +} + +} diff --git a/matlab/src/IceMatlab/Future.h b/matlab/src/IceMatlab/Future.h new file mode 100644 index 00000000000..28a5b112cc4 --- /dev/null +++ b/matlab/src/IceMatlab/Future.h @@ -0,0 +1,58 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Ice.h> + +namespace IceMatlab +{ + +class Future : public IceUtil::Monitor<IceUtil::Mutex> +{ +public: + + void token(std::function<void()>); + bool waitUntilFinished(); + + virtual void exception(std::exception_ptr); + std::exception_ptr getException() const; + + virtual void sent(); + virtual std::string state() const = 0; + void cancel(); + +protected: + + virtual bool isFinished() const = 0; + + std::function<void()> _token; + std::exception_ptr _exception; // If a local exception occurs. +}; + +// +// For invocations that are considered completed when sent. +// +class SentFuture : public Future +{ +public: + + SentFuture(); + + virtual void sent(); + virtual std::string state() const; + +protected: + + virtual bool isFinished() const; + +private: + + bool _sent; +}; + +} diff --git a/matlab/src/IceMatlab/IceMatlab.rc b/matlab/src/IceMatlab/IceMatlab.rc new file mode 100644 index 00000000000..10fa5af893a --- /dev/null +++ b/matlab/src/IceMatlab/IceMatlab.rc @@ -0,0 +1,38 @@ +#include <IceUtil/ResourceConfig.h> + +#ifdef _DEBUG +# define ICE_INTERNALNAME "icematlab_d\0" +# define ICE_ORIGINALFILENAME "icematlab_d.dll\0" +#else +# define ICE_INTERNALNAME "icematlab\0" +# define ICE_ORIGINALFILENAME "icematlab.dll\0" +#endif + +VS_VERSION_INFO VERSIONINFO +FILEVERSION ICE_VERSION +PRODUCTVERSION ICE_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +FILEFLAGS VER_DEBUG +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", ICE_COMPANY_NAME + VALUE "FileDescription", "Ice for Matlab Extension\0" + VALUE "FileVersion", ICE_STRING_VERSION + VALUE "InternalName", ICE_INTERNALNAME + VALUE "LegalCopyright", ICE_COPYRIGHT + VALUE "OriginalFilename", ICE_ORIGINALFILENAME + VALUE "ProductName", ICE_PRODUCT_NAME + VALUE "ProductVersion", ICE_STRING_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/matlab/src/IceMatlab/Init.cpp b/matlab/src/IceMatlab/Init.cpp new file mode 100644 index 00000000000..e9fe0b57256 --- /dev/null +++ b/matlab/src/IceMatlab/Init.cpp @@ -0,0 +1,94 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Ice.h> +#include <Ice/RegisterPlugins.h> +#include "icematlab.h" +#include "Util.h" + +using namespace std; +using namespace IceMatlab; + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_initialize(mxArray* args, void* propsImpl, void** r) +{ + try + { + Ice::StringSeq a; + getStringList(args, a); + + // + // Collect InitializationData members. + // + Ice::InitializationData id; + + // + // Properties + // + if(propsImpl) + { + id.properties = *(reinterpret_cast<shared_ptr<Ice::Properties>*>(propsImpl)); + } + + shared_ptr<Ice::Communicator> c = Ice::initialize(a, id); + *r = new shared_ptr<Ice::Communicator>(c); + return createResultValue(createStringList(a)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_stringToIdentity(mxArray* s) +{ + try + { + Ice::Identity id = Ice::stringToIdentity(getStringFromUTF16(s)); + return createResultValue(createIdentity(id)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_identityToString(mxArray* id) +{ + try + { + Ice::Identity ident; + getIdentity(id, ident); + return createResultValue(createStringFromUTF8(Ice::identityToString(ident))); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +// +// This function exists so that mex may be used to compile the library. It is not otherwise needed. +// +void +mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ +} + +} diff --git a/matlab/src/IceMatlab/InputStream.cpp b/matlab/src/IceMatlab/InputStream.cpp new file mode 100644 index 00000000000..33633f0d3f9 --- /dev/null +++ b/matlab/src/IceMatlab/InputStream.cpp @@ -0,0 +1,830 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Ice.h> +#include <Ice/Optional.h> +#include "icematlab.h" +#include "InputStream.h" +#include "Util.h" + +#define SELF (reinterpret_cast<IceMatlab::InputStreamData*>(self)) + +using namespace std; +using namespace IceMatlab; + +void* +IceMatlab::createInputStream(const shared_ptr<Ice::Communicator>& communicator, const Ice::EncodingVersion& encoding, + vector<Ice::Byte>& data) +{ + InputStreamData* p = new InputStreamData; + p->data.swap(data); + p->in = new Ice::InputStream(communicator, encoding, p->data); + return p; +} + +namespace +{ + +template<typename T> +mxArray* +readSeq(Ice::InputStream* in, mxClassID cls) +{ + try + { + pair<const T*, const T*> p; + in->read(p); + const size_t nelem = p.second - p.first; + if(nelem > 0) + { + mxArray* r = mxCreateUninitNumericMatrix(1, nelem, cls, mxREAL); + memcpy(reinterpret_cast<T*>(mxGetData(r)), p.first, nelem * sizeof(T)); + return createResultValue(r); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +template<typename T> +mxArray* +readOpt(Ice::InputStream* in, int tag, mxClassID cls) +{ + try + { + Ice::optional<T> opt; + in->read(tag, opt); + if(opt.has_value()) + { + mxArray* r = mxCreateUninitNumericMatrix(1, 1, cls, mxREAL); + *(reinterpret_cast<T*>(mxGetData(r))) = opt.value(); + return createResultValue(r); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +template<typename T> +mxArray* +readSeqOpt(Ice::InputStream* in, int tag, mxClassID cls) +{ + try + { + Ice::optional<pair<const T*, const T*>> opt; + in->read(tag, opt); + const size_t sz = opt.value().second - opt.value().first; + if(opt.has_value() && sz > 0) + { + mxArray* r = mxCreateUninitNumericMatrix(1, sz / sizeof(T), cls, mxREAL); + memcpy(reinterpret_cast<T*>(mxGetData(r)), opt.value().first, sz); + return createResultValue(r); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +} + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_InputStream__release(void* self) +{ + delete SELF->in; + delete SELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readBool(void* self, unsigned char* v) +{ + try + { + bool b; + SELF->in->read(b); + *v = b ? 1 : 0; + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readBoolSeq(void* self) +{ + try + { + pair<const bool*, const bool*> p; + SELF->in->read(p); + const size_t sz = p.second - p.first; + if(sz > 0) + { + mxArray* r = mxCreateLogicalMatrix(1, sz); + memcpy(mxGetLogicals(r), p.first, sz); + return createResultValue(r); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readBoolOpt(void* self, int tag) +{ + try + { + Ice::optional<bool> opt; + SELF->in->read(tag, opt); + if(opt.has_value()) + { + return createResultValue(mxCreateLogicalScalar(opt.value())); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readBoolSeqOpt(void* self, int tag) +{ + try + { + Ice::optional<pair<const bool*, const bool*>> opt; + SELF->in->read(tag, opt); + const size_t sz = opt.value().second - opt.value().first; + if(opt.has_value() && sz > 0) + { + mxArray* r = mxCreateLogicalMatrix(1, sz); + memcpy(mxGetLogicals(r), opt.value().first, sz); + return createResultValue(r); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readByte(void* self, unsigned char* v) +{ + try + { + Ice::Byte b; + SELF->in->read(b); + *v = b; + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readByteSeq(void* self) +{ + return readSeq<Ice::Byte>(SELF->in, mxUINT8_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readByteOpt(void* self, int tag) +{ + return readOpt<Ice::Byte>(SELF->in, tag, mxUINT8_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readByteSeqOpt(void* self, int tag) +{ + return readSeqOpt<Ice::Byte>(SELF->in, tag, mxUINT8_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readShort(void* self, short* v) +{ + try + { + SELF->in->read(*v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readShortSeq(void* self) +{ + return readSeq<short>(SELF->in, mxINT16_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readShortOpt(void* self, int tag) +{ + return readOpt<short>(SELF->in, tag, mxINT16_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readShortSeqOpt(void* self, int tag) +{ + return readSeqOpt<short>(SELF->in, tag, mxINT16_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readInt(void* self, int* v) +{ + try + { + SELF->in->read(*v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readIntSeq(void* self) +{ + return readSeq<int>(SELF->in, mxINT32_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readIntOpt(void* self, int tag) +{ + return readOpt<int>(SELF->in, tag, mxINT32_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readIntSeqOpt(void* self, int tag) +{ + return readSeqOpt<int>(SELF->in, tag, mxINT32_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readLong(void* self, long long* v) +{ + try + { + SELF->in->read(*v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readLongSeq(void* self) +{ + return readSeq<long long>(SELF->in, mxINT64_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readLongOpt(void* self, int tag) +{ + return readOpt<long long>(SELF->in, tag, mxINT64_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readLongSeqOpt(void* self, int tag) +{ + return readSeqOpt<long long>(SELF->in, tag, mxINT64_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readFloat(void* self, float* v) +{ + try + { + SELF->in->read(*v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readFloatSeq(void* self) +{ + return readSeq<float>(SELF->in, mxSINGLE_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readFloatOpt(void* self, int tag) +{ + return readOpt<float>(SELF->in, tag, mxSINGLE_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readFloatSeqOpt(void* self, int tag) +{ + return readSeqOpt<float>(SELF->in, tag, mxSINGLE_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readDouble(void* self, double* v) +{ + try + { + SELF->in->read(*v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readDoubleSeq(void* self) +{ + return readSeq<double>(SELF->in, mxDOUBLE_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readDoubleOpt(void* self, int tag) +{ + return readOpt<double>(SELF->in, tag, mxDOUBLE_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readDoubleSeqOpt(void* self, int tag) +{ + return readSeqOpt<double>(SELF->in, tag, mxDOUBLE_CLASS); +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readString(void* self) +{ + string s; + try + { + SELF->in->read(s, false); + return createResultValue(createStringFromUTF8(s)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readStringSeq(void* self) +{ + try + { + vector<string> v; + SELF->in->read(v, false); + return createResultValue(createStringList(v)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readStringOpt(void* self, int tag) +{ + try + { + Ice::optional<string> opt; + SELF->in->read(tag, opt); + if(opt.has_value()) + { + return createResultValue(createStringFromUTF8(opt.value())); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readStringSeqOpt(void* self, int tag) +{ + try + { + if(SELF->in->readOptional(tag, Ice::OptionalFormat::FSize)) + { + SELF->in->skip(4); + return Ice_InputStream_readStringSeq(self); + } + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_skip(void* self, int n) +{ + try + { + SELF->in->skip(n); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_startException(void* self) +{ + try + { + SELF->in->startException(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_endException(void* self) +{ + try + { + SELF->in->endException(false); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_startEncapsulation(void* self) +{ + try + { + SELF->in->startEncapsulation(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_endEncapsulation(void* self) +{ + try + { + SELF->in->endEncapsulation(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_skipEmptyEncapsulation(void* self) +{ + try + { + SELF->in->skipEmptyEncapsulation(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_skipEncapsulation(void* self) +{ + try + { + return createResultValue(createEncodingVersion(SELF->in->skipEncapsulation())); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_getEncoding(void* self) +{ + try + { + return createResultValue(createEncodingVersion(SELF->in->getEncoding())); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_startSlice(void* self) +{ + try + { + SELF->in->startSlice(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_endSlice(void* self) +{ + try + { + SELF->in->endSlice(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_skipSlice(void* self) +{ + try + { + SELF->in->skipSlice(); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readSize(void* self, int* size) +{ + try + { + *size = SELF->in->readSize(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readOptional(void* self, int tag, Ice_OptionalFormat f, unsigned char* r) +{ + try + { + bool b = SELF->in->readOptional(tag, static_cast<Ice::OptionalFormat>(f)); + *r = b ? 1 : 0; + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readProxy(void* self, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> proxy; + SELF->in->read(proxy); + if(proxy) + { + *r = new shared_ptr<Ice::ObjectPrx>(proxy); + } + else + { + *r = 0; + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readProxyOpt(void* self, int tag, void** r) +{ + try + { + Ice::optional<shared_ptr<Ice::ObjectPrx>> opt; + SELF->in->readAll({tag}, opt); + if(opt.has_value()) + { + *r = new shared_ptr<Ice::ObjectPrx>(opt.value()); + } + else + { + *r = 0; + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_readEnum(void* self, int maxValue, int* r) +{ + try + { + *r = SELF->in->readEnum(maxValue); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +namespace +{ + +class MatlabUserException : public Ice::UserException +{ +public: + + MatlabUserException(const string& id, mxArray* ex, mxArray* streamWrapper) : + _id(id), _ex(ex), _streamWrapper(streamWrapper) + { + } + + mxArray* exception() const + { + return _ex; + } + + virtual string ice_id() const override + { + return _id; + } + + virtual void _read(Ice::InputStream*) override + { + // + // Call read_() on the exception instance. + // + mxArray* params[2]; + params[0] = _ex; + params[1] = _streamWrapper; + mxArray* err = mexCallMATLABWithTrap(0, 0, 2, params, "read_"); + if(err) + { + mxDestroyArray(err); + throw Ice::MarshalException(__FILE__, __LINE__, "failure in exception's read_ method"); + } + } + + virtual bool _usesClasses() const override + { + // + // Call usesClasses_() on the exception instance. + // + mxArray* ex = const_cast<mxArray*>(_ex); + mxArray* r; + mxArray* err = mexCallMATLABWithTrap(1, &r, 1, &ex, "usesClasses_"); + if(err) + { + mxDestroyArray(err); + throw Ice::MarshalException(__FILE__, __LINE__, "failure in exception's usesClasses_ method"); + } + else + { + bool b = mxIsLogicalScalarTrue(r) ? true : false; + mxDestroyArray(r); + return b; + } + } + + virtual void ice_throw() const override + { + throw static_cast<const MatlabUserException&>(*this); + } + +protected: + + virtual IceUtil::Exception* ice_cloneImpl() const override + { + return 0; + } + + virtual void _writeImpl(Ice::OutputStream*) const override + { + assert(false); + } + + virtual void _readImpl(Ice::InputStream* in) override + { + assert(false); + } + +private: + + string _id; + mxArray* _ex; + mxArray* _streamWrapper; +}; + +void createException(mxArray* streamWrapper, const string& id) +{ + // + // Convert the Slice type ID to a Matlab class name. + // + string cls = idToClass(id); + // + // Attempt to call the class constructor to obtain an instance. This may raise an exception. + // + mxArray* ex; + mxArray* err = mexCallMATLABWithTrap(1, &ex, 0, 0, cls.c_str()); + if(err) + { + mxDestroyArray(err); + } + else + { + throw MatlabUserException(id, ex, streamWrapper); + } +} + +} + +EXPORTED_FUNCTION mxArray* +Ice_InputStream_throwException(void* self, mxArray* wrapper) +{ + try + { + SELF->in->throwException([wrapper](const string& id){ createException(wrapper, id); }); + } + catch(MatlabUserException& ex) + { + return ex.exception(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +} diff --git a/matlab/src/IceMatlab/InputStream.h b/matlab/src/IceMatlab/InputStream.h new file mode 100644 index 00000000000..a801d6a5cb4 --- /dev/null +++ b/matlab/src/IceMatlab/InputStream.h @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/InputStream.h> + +namespace IceMatlab +{ + +struct InputStreamData +{ + std::vector<Ice::Byte> data; + Ice::InputStream* in; +}; + +// +// Consumes the vector. +// +void* createInputStream(const std::shared_ptr<Ice::Communicator>&, const Ice::EncodingVersion&, + std::vector<Ice::Byte>&); + +} diff --git a/matlab/src/IceMatlab/ObjectPrx.cpp b/matlab/src/IceMatlab/ObjectPrx.cpp new file mode 100644 index 00000000000..3da06a7fd71 --- /dev/null +++ b/matlab/src/IceMatlab/ObjectPrx.cpp @@ -0,0 +1,1144 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Ice.h> +#include "icematlab.h" +#include "Future.h" +#include "InputStream.h" +#include "Util.h" + +#define DEREF(x) (*(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(x))) +#define SELF DEREF(self) + +using namespace std; +using namespace IceMatlab; + +namespace +{ + +class InvocationFuture : public Future +{ +public: + + InvocationFuture(bool, bool); + ~InvocationFuture(); + + virtual void exception(exception_ptr); + virtual void sent(); + virtual string state() const; + + void finished(const std::shared_ptr<Ice::Communicator>&, const Ice::EncodingVersion&, bool, + std::pair<const Ice::Byte*, const Ice::Byte*>); + void getResults(bool&, void*&); + +protected: + + virtual bool isFinished() const; + +private: + + const bool _twoway; + enum State { Running, Sent, Finished }; + State _state; + bool _ok; // True for success, false for user exception. + void* _stream; // The InputStream for reading the results. +}; + +#define IFSELF (*(reinterpret_cast<shared_ptr<InvocationFuture>*>(self))) + +InvocationFuture::InvocationFuture(bool twoway, bool batch) : + _twoway(twoway), + _state(batch ? State::Finished : State::Running), + _ok(false), + _stream(0) +{ +} + +InvocationFuture::~InvocationFuture() +{ + if(_stream) + { + Ice_InputStream__release(_stream); + } +} + +void +InvocationFuture::sent() +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(_state == State::Running) + { + _state = _twoway ? State::Sent : State::Finished; + } +} + +void +InvocationFuture::exception(exception_ptr e) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _state = State::Finished; + _token = nullptr; + _exception = e; + notifyAll(); +} + +void +InvocationFuture::finished(const std::shared_ptr<Ice::Communicator>& communicator, + const Ice::EncodingVersion& encoding, bool b, pair<const Ice::Byte*, const Ice::Byte*> p) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _ok = b; + _state = State::Finished; + _token = nullptr; + if(p.second > p.first) + { + vector<Ice::Byte> data(p.first, p.second); + _stream = createInputStream(communicator, encoding, data); + } + notifyAll(); +} + +string +InvocationFuture::state() const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + string st; + switch(_state) + { + case State::Running: + st = "running"; + break; + case State::Sent: + st = "sent"; + break; + case State::Finished: + st = "finished"; + break; + } + return st; +} + +void +InvocationFuture::getResults(bool& ok, void*& stream) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + assert(_twoway); + ok = _ok; + assert(_stream); + stream = _stream; + _stream = 0; +} + +bool +InvocationFuture::isFinished() const +{ + return _state == State::Finished; +} + +class GetConnectionFuture : public Future +{ +public: + + virtual string state() const; + + void finished(shared_ptr<Ice::Connection>); + shared_ptr<Ice::Connection> getConnection() const; + +protected: + + virtual bool isFinished() const; + +private: + + shared_ptr<Ice::Connection> _connection; +}; + +#define GCFSELF (*(reinterpret_cast<shared_ptr<GetConnectionFuture>*>(self))) + +string +GetConnectionFuture::state() const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(_exception || _connection) + { + return "finished"; + } + else + { + return "running"; + } +} + +void +GetConnectionFuture::finished(shared_ptr<Ice::Connection> con) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _token = nullptr; + _connection = con; + notifyAll(); +} + +shared_ptr<Ice::Connection> +GetConnectionFuture::getConnection() const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + return _connection; +} + +bool +GetConnectionFuture::isFinished() const +{ + return _connection || _exception; +} + +} + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx__release(void* self) +{ + delete &SELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_equals(void* self, void* other, unsigned char* r) +{ + assert(other); // Wrapper only calls this function for non-nil arguments. + try + { + *r = Ice::targetEqualTo(SELF, DEREF(other)) ? 1 : 0; + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_createOutputStream(void* self, void** stream) +{ + *stream = new Ice::OutputStream(SELF->ice_getCommunicator(), SELF->ice_getEncodingVersion()); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_invoke(void* self, const char* op, Ice_OperationMode m, void* inParams, mxArray* context, + unsigned char* result, void** outParams) +{ + Ice::OutputStream* out = reinterpret_cast<Ice::OutputStream*>(inParams); + Ice::OperationMode mode = static_cast<Ice::OperationMode>(m); + pair<const Ice::Byte*, const Ice::Byte*> params(0, 0); + if(out) + { + params = out->finished(); + } + vector<Ice::Byte> v; + + *outParams = 0; + + try + { + Ice::Context ctx; + getStringMap(context, ctx); + *result = SELF->ice_invoke(op, mode, params, v, ctx) ? 1 : 0; + if(!v.empty()) + { + *outParams = createInputStream(SELF->ice_getCommunicator(), SELF->ice_getEncodingVersion(), v); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_invokeNC(void* self, const char* op, Ice_OperationMode m, void* inParams, unsigned char* result, + void** outParams) +{ + Ice::OutputStream* out = reinterpret_cast<Ice::OutputStream*>(inParams); + Ice::OperationMode mode = static_cast<Ice::OperationMode>(m); + pair<const Ice::Byte*, const Ice::Byte*> params(0, 0); + if(out) + { + params = out->finished(); + } + vector<Ice::Byte> v; + + *outParams = 0; + + try + { + *result = SELF->ice_invoke(op, mode, params, v) ? 1 : 0; + if(!v.empty()) + { + *outParams = createInputStream(SELF->ice_getCommunicator(), SELF->ice_getEncodingVersion(), v); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_invokeAsync(void* self, const char* op, Ice_OperationMode m, void* inParams, mxArray* context, + void** future) +{ + const shared_ptr<Ice::ObjectPrx> proxy = SELF; + Ice::OutputStream* out = reinterpret_cast<Ice::OutputStream*>(inParams); + Ice::OperationMode mode = static_cast<Ice::OperationMode>(m); + pair<const Ice::Byte*, const Ice::Byte*> params(0, 0); + if(out) + { + params = out->finished(); + } + + *future = 0; + auto f = make_shared<InvocationFuture>(proxy->ice_isTwoway(), + proxy->ice_isBatchOneway() || proxy->ice_isBatchDatagram()); + + try + { + Ice::Context ctx; + getStringMap(context, ctx); + function<void()> token = proxy->ice_invokeAsync( + op, mode, params, + [proxy, f](bool ok, pair<const Ice::Byte*, const Ice::Byte*> outParams) + { + f->finished(proxy->ice_getCommunicator(), proxy->ice_getEncodingVersion(), ok, outParams); + }, + [f](exception_ptr e) + { + f->exception(e); + }, + [f](bool /*sentSynchronously*/) + { + f->sent(); + }, + ctx); + f->token(token); + *future = new shared_ptr<InvocationFuture>(f); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_invokeAsyncNC(void* self, const char* op, Ice_OperationMode m, void* inParams, void** future) +{ + const shared_ptr<Ice::ObjectPrx> proxy = SELF; + Ice::OutputStream* out = reinterpret_cast<Ice::OutputStream*>(inParams); + Ice::OperationMode mode = static_cast<Ice::OperationMode>(m); + pair<const Ice::Byte*, const Ice::Byte*> params(0, 0); + if(out) + { + params = out->finished(); + } + + *future = 0; + auto f = make_shared<InvocationFuture>(proxy->ice_isTwoway(), + proxy->ice_isBatchOneway() || proxy->ice_isBatchDatagram()); + + try + { + function<void()> token = proxy->ice_invokeAsync( + op, mode, params, + [proxy, f](bool ok, pair<const Ice::Byte*, const Ice::Byte*> outParams) + { + f->finished(proxy->ice_getCommunicator(), + proxy->ice_getEncodingVersion(), ok, outParams); + }, + [f](exception_ptr e) + { + f->exception(e); + }, + [f](bool /*sentSynchronously*/) + { + f->sent(); + }); + f->token(token); + *future = new shared_ptr<InvocationFuture>(f); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_toString(void* self) +{ + return createResultValue(createStringFromUTF8(SELF->ice_toString())); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getCommunicator(void* self, void** r) +{ + *r = new shared_ptr<Ice::Communicator>(SELF->ice_getCommunicator()); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getIdentity(void* self) +{ + return createResultValue(createIdentity(SELF->ice_getIdentity())); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_identity(void* self, mxArray* id, void** r) +{ + try + { + Ice::Identity ident; + getIdentity(id, ident); + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_identity(ident); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getContext(void* self) +{ + return createResultValue(createStringMap(SELF->ice_getContext())); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_context(void* self, mxArray* c, void** r) +{ + try + { + Ice::Context ctx; + getStringMap(c, ctx); + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_context(ctx); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getFacet(void* self) +{ + const string f = SELF->ice_getFacet(); + return createResultValue(createStringFromUTF8(f)); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_facet(void* self, const char* f, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_facet(f); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getAdapterId(void* self) +{ + const string f = SELF->ice_getAdapterId(); + return createResultValue(createStringFromUTF8(f)); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_adapterId(void* self, const char* id, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_adapterId(id); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getEndpoints(void* self) +{ + // TBD + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_endpoints(void* self, mxArray* endpts, void** r) +{ + // TBD +#if 0 + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_endpoints(id); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } +#endif + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getLocatorCacheTimeout(void* self, int* t) +{ + *t = SELF->ice_getLocatorCacheTimeout(); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_locatorCacheTimeout(void* self, int t, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_locatorCacheTimeout(t); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getInvocationTimeout(void* self, int* t) +{ + *t = SELF->ice_getInvocationTimeout(); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_invocationTimeout(void* self, int t, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_invocationTimeout(t); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getConnectionId(void* self) +{ + const string f = SELF->ice_getConnectionId(); + return createResultValue(createStringFromUTF8(f)); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_connectionId(void* self, const char* id, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_connectionId(id); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isConnectionCached(void* self, unsigned char* r) +{ + *r = SELF->ice_isConnectionCached() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_connectionCached(void* self, unsigned char v, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_connectionCached(v == 1); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getEndpointSelection(void* self, Ice_EndpointSelectionType* r) +{ + *r = SELF->ice_getEndpointSelection() == Ice::EndpointSelectionType::Random ? Random : Ordered; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_endpointSelection(void* self, Ice_EndpointSelectionType v, void** r) +{ + try + { + Ice::EndpointSelectionType type = static_cast<Ice::EndpointSelectionType>(v); + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_endpointSelection(type); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getEncodingVersion(void* self) +{ + return createResultValue(createEncodingVersion(SELF->ice_getEncodingVersion())); +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_encodingVersion(void* self, mxArray* v, void** r) +{ + try + { + Ice::EncodingVersion ev; + getEncodingVersion(v, ev); + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_encodingVersion(ev); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getRouter(void* self, void** r) +{ + shared_ptr<Ice::ObjectPrx> router = SELF->ice_getRouter(); + *r = router ? new shared_ptr<Ice::ObjectPrx>(router) : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_router(void* self, void* rtr, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> router; + if(rtr) + { + router = *(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(rtr)); + } + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_router(Ice::uncheckedCast<Ice::RouterPrx>(router)); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getLocator(void* self, void** r) +{ + shared_ptr<Ice::ObjectPrx> locator = SELF->ice_getLocator(); + *r = locator ? new shared_ptr<Ice::ObjectPrx>(locator) : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_locator(void* self, void* loc, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> locator; + if(loc) + { + locator = *(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(loc)); + } + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_locator(Ice::uncheckedCast<Ice::LocatorPrx>(locator)); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isSecure(void* self, unsigned char* r) +{ + *r = SELF->ice_isSecure() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_secure(void* self, unsigned char b, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_secure(b == 1); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isPreferSecure(void* self, unsigned char* r) +{ + *r = SELF->ice_isPreferSecure() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_preferSecure(void* self, unsigned char b, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_preferSecure(b == 1); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isTwoway(void* self, unsigned char* r) +{ + *r = SELF->ice_isTwoway() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_twoway(void* self, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_twoway(); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isOneway(void* self, unsigned char* r) +{ + *r = SELF->ice_isOneway() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_oneway(void* self, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_oneway(); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isBatchOneway(void* self, unsigned char* r) +{ + *r = SELF->ice_isBatchOneway() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_batchOneway(void* self, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_batchOneway(); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isDatagram(void* self, unsigned char* r) +{ + *r = SELF->ice_isDatagram() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_datagram(void* self, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_datagram(); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_isBatchDatagram(void* self, unsigned char* r) +{ + *r = SELF->ice_isBatchDatagram() ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_batchDatagram(void* self, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_batchDatagram(); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_compress(void* self, unsigned char b, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_compress(b == 1); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_timeout(void* self, int t, void** r) +{ + try + { + shared_ptr<Ice::ObjectPrx> newProxy = SELF->ice_timeout(t); + *r = newProxy.get() == SELF.get() ? 0 : new shared_ptr<Ice::ObjectPrx>(newProxy); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getConnection(void* self, void** r) +{ + *r = 0; + try + { + shared_ptr<Ice::Connection> conn = SELF->ice_getConnection(); + if(conn) + { + *r = new shared_ptr<Ice::Connection>(conn); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getConnectionAsync(void* self, void** future) +{ + *future = 0; + auto f = make_shared<GetConnectionFuture>(); + + try + { + function<void()> token = SELF->ice_getConnectionAsync( + [f](shared_ptr<Ice::Connection> con) + { + f->finished(con); + }, + [f](exception_ptr e) + { + f->exception(e); + }, + nullptr); + f->token(token); + *future = new shared_ptr<GetConnectionFuture>(f); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_getCachedConnection(void* self, void** r) +{ + *r = 0; + try + { + shared_ptr<Ice::Connection> conn = SELF->ice_getCachedConnection(); + if(conn) + { + *r = new shared_ptr<Ice::Connection>(conn); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_flushBatchRequests(void* self) +{ + try + { + SELF->ice_flushBatchRequests(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_ice_flushBatchRequestsAsync(void* self, void** future) +{ + *future = 0; + auto f = make_shared<SentFuture>(); + + try + { + function<void()> token = SELF->ice_flushBatchRequestsAsync( + [f](exception_ptr e) + { + f->exception(e); + }, + [f](bool /*sentSynchronously*/) + { + f->sent(); + }); + f->token(token); + *future = new shared_ptr<SentFuture>(f); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_ObjectPrx_clone(void* self, void** r) +{ + shared_ptr<Ice::ObjectPrx> p = SELF; + *r = new shared_ptr<Ice::ObjectPrx>(p); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture__release(void* self) +{ + delete &IFSELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture_id(void* self, unsigned long long* id) +{ + *id = reinterpret_cast<unsigned long long>(self); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture_wait(void* self, unsigned char* ok) +{ + // TBD: Timeout? + + bool b = IFSELF->waitUntilFinished(); + *ok = b ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture_stream(void* self, unsigned char* ok, void** stream) +{ + // TBD: Timeout? + + if(!IFSELF->waitUntilFinished()) + { + assert(IFSELF->getException()); + try + { + rethrow_exception(IFSELF->getException()); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + } + + bool b; + IFSELF->getResults(b, *stream); + *ok = b ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture_state(void* self) +{ + return createResultValue(createStringFromUTF8(IFSELF->state())); +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture_cancel(void* self) +{ + IFSELF->cancel(); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_InvocationFuture_check(void* self) +{ + if(!IFSELF->waitUntilFinished()) + { + assert(IFSELF->getException()); + try + { + rethrow_exception(IFSELF->getException()); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + } + + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_GetConnectionFuture__release(void* self) +{ + delete &GCFSELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_GetConnectionFuture_id(void* self, unsigned long long* id) +{ + *id = reinterpret_cast<unsigned long long>(self); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_GetConnectionFuture_wait(void* self, unsigned char* ok) +{ + // TBD: Timeout? + + bool b = GCFSELF->waitUntilFinished(); + *ok = b ? 1 : 0; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_GetConnectionFuture_fetch(void* self, void** con) +{ + // TBD: Timeout? + + if(!GCFSELF->waitUntilFinished()) + { + assert(GCFSELF->getException()); + try + { + rethrow_exception(GCFSELF->getException()); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + } + + assert(GCFSELF->connection()); + *con = new shared_ptr<Ice::Connection>(GCFSELF->getConnection()); + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_GetConnectionFuture_state(void* self) +{ + return createResultValue(createStringFromUTF8(GCFSELF->state())); +} + +EXPORTED_FUNCTION mxArray* +Ice_GetConnectionFuture_cancel(void* self) +{ + GCFSELF->cancel(); + return 0; +} + +} diff --git a/matlab/src/IceMatlab/OutputStream.cpp b/matlab/src/IceMatlab/OutputStream.cpp new file mode 100644 index 00000000000..61b9afedf03 --- /dev/null +++ b/matlab/src/IceMatlab/OutputStream.cpp @@ -0,0 +1,716 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Ice.h> +#include "icematlab.h" +#include "Util.h" + +#define SELF (reinterpret_cast<Ice::OutputStream*>(self)) + +using namespace std; +using namespace IceMatlab; + + +extern "C" +{ + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream__release(void* self) +{ + delete SELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeBool(void* self, unsigned char v) +{ + try + { + SELF->write(v == 1); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeBoolOpt(void* self, int tag, unsigned char v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<bool>(v == 1)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeBoolSeq(void* self, const unsigned char* v, int size) +{ + const bool* p = reinterpret_cast<const bool*>(v); + try + { + SELF->write(p, p + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeBoolSeqOpt(void* self, int tag, const unsigned char* v, int size) +{ + const bool* p = reinterpret_cast<const bool*>(v); + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(p, p + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeByte(void* self, unsigned char v) +{ + try + { + SELF->write(static_cast<Ice::Byte>(v)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeByteOpt(void* self, int tag, unsigned char v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<Ice::Byte>(static_cast<Ice::Byte>(v))); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeByteSeq(void* self, const unsigned char* v, int size) +{ + const Ice::Byte* p = reinterpret_cast<const Ice::Byte*>(v); + try + { + SELF->write(p, p + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeByteSeqOpt(void* self, int tag, const unsigned char* v, int size) +{ + const Ice::Byte* p = reinterpret_cast<const Ice::Byte*>(v); + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(p, p + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeShort(void* self, short v) +{ + try + { + SELF->write(v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeShortOpt(void* self, int tag, short v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<short>(v)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeShortSeq(void* self, const short* v, int size) +{ + try + { + SELF->write(v, v + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeShortSeqOpt(void* self, int tag, const short* v, int size) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(v, v + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeInt(void* self, int v) +{ + try + { + SELF->write(v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeIntOpt(void* self, int tag, int v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<int>(v)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeIntSeq(void* self, const int* v, int size) +{ + try + { + SELF->write(v, v + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeIntSeqOpt(void* self, int tag, const int* v, int size) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(v, v + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeLong(void* self, long long v) +{ + try + { + SELF->write(v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeLongOpt(void* self, int tag, long long v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<long long>(v)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeLongSeq(void* self, const long long* v, int size) +{ + try + { + SELF->write(v, v + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeLongSeqOpt(void* self, int tag, const long long* v, int size) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(v, v + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeFloat(void* self, float v) +{ + try + { + SELF->write(v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeFloatOpt(void* self, int tag, float v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<float>(v)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeFloatSeq(void* self, const float* v, int size) +{ + try + { + SELF->write(v, v + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeFloatSeqOpt(void* self, int tag, const float* v, int size) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(v, v + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeDouble(void* self, double v) +{ + try + { + SELF->write(v); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeDoubleOpt(void* self, int tag, double v) +{ + try + { + SELF->writeAll({tag}, IceUtil::Optional<double>(v)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeDoubleSeq(void* self, const double* v, int size) +{ + try + { + SELF->write(v, v + size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeDoubleSeqOpt(void* self, int tag, const double* v, int size) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(v, v + size); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeString(void* self, mxArray* str) +{ + try + { + SELF->write(getStringFromUTF16(str), false); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeStringOpt(void* self, int tag, mxArray* str) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) + { + SELF->write(getStringFromUTF16(str), false); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeStringSeq(void* self, mxArray* v) +{ + try + { + if(mxIsEmpty(v)) + { + SELF->writeSize(0); + } + else if(!mxIsCell(v)) + { + throw invalid_argument("value is not a cell array"); + } + else + { + size_t m = mxGetM(v); + size_t n = mxGetN(v); + if(m != 1) + { + throw invalid_argument("cell array must be a 1xN matrix"); + } + SELF->writeSize(n); + for(size_t i = 0; i < n; ++i) + { + mxArray* e = mxGetCell(v, i); + SELF->write(getStringFromUTF16(e), false); + } + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeStringSeqOpt(void* self, int tag, mxArray* v) +{ + try + { + if(SELF->writeOptional(tag, Ice::OptionalFormat::FSize)) + { + Ice::OutputStream::size_type pos = SELF->startSize(); + mxArray* ex = Ice_OutputStream_writeStringSeq(self, v); + if(ex) + { + return ex; + } + SELF->endSize(pos); + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeSize(void* self, int size) +{ + try + { + SELF->writeSize(size); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeProxy(void* self, void* proxy) +{ + shared_ptr<Ice::ObjectPrx> p; + if(proxy) + { + p = *(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(proxy)); + } + try + { + SELF->writeProxy(p); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeProxyOpt(void* self, int tag, void* proxy) +{ + assert(proxy); // Wrapper only calls this function for a non-nil value. + shared_ptr<Ice::ObjectPrx> p = *(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(proxy)); + try + { + SELF->writeAll({tag}, IceUtil::Optional<shared_ptr<Ice::ObjectPrx>>(p)); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeEnum(void* self, int val, int maxValue) +{ + try + { + SELF->writeEnum(val, maxValue); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_startEncapsulation(void* self) +{ + try + { + SELF->startEncapsulation(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_startEncapsulationWithFormat(void* self, Ice_FormatType t) +{ + Ice::FormatType type = static_cast<Ice::FormatType>(t); + try + { + SELF->startEncapsulation(SELF->getEncoding(), type); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_endEncapsulation(void* self) +{ + try + { + SELF->endEncapsulation(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_startSlice(void* self, const char* typeId, int compactId, unsigned char last) +{ + try + { + SELF->startSlice(typeId, compactId, last == 1); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_endSlice(void* self) +{ + try + { + SELF->endSlice(); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_writeOptional(void* self, int tag, Ice_OptionalFormat f, unsigned char* supportsOptionals) +{ + Ice::OptionalFormat fmt = static_cast<Ice::OptionalFormat>(f); + try + { + *supportsOptionals = SELF->writeOptional(tag, fmt); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_startSize(void* self, unsigned int* pos) +{ + try + { + *pos = static_cast<unsigned int>(SELF->startSize()); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_OutputStream_endSize(void* self, unsigned int pos) +{ + try + { + SELF->endSize(pos); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +} diff --git a/matlab/src/IceMatlab/Properties.cpp b/matlab/src/IceMatlab/Properties.cpp new file mode 100644 index 00000000000..87dd2c1dd77 --- /dev/null +++ b/matlab/src/IceMatlab/Properties.cpp @@ -0,0 +1,254 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#define EXPORT_FCNS + +#include <Ice/Properties.h> +#include <Ice/Initialize.h> +#include "icematlab.h" +#include "Util.h" + +#define SELF (*(reinterpret_cast<shared_ptr<Ice::Properties>*>(self))) + +using namespace std; +using namespace IceMatlab; + +extern "C" +{ + +// +// Implementation note: We need to pass the implementation object from MATLAB code for the defaults argument. +// If we passed the wrapper object instead, there is no way to extract the void pointer from the mxArray object. +// +EXPORTED_FUNCTION mxArray* +Ice_createProperties(mxArray* args, void* defaultsImpl, void** r) +{ + try + { + vector<string> a; + getStringList(args, a); + shared_ptr<Ice::Properties> def; + if(defaultsImpl) + { + def = *(reinterpret_cast<shared_ptr<Ice::Properties>*>(defaultsImpl)); + } + shared_ptr<Ice::Properties> props = Ice::createProperties(a, def); + *r = new shared_ptr<Ice::Properties>(props); + return createResultValue(createStringList(a)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties__release(void* self) +{ + delete &SELF; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getProperty(void* self, const char* key) +{ + try + { + return createResultValue(createStringFromUTF8(SELF->getProperty(key))); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getPropertyWithDefault(void* self, const char* key, const char* dflt) +{ + try + { + return createResultValue(createStringFromUTF8(SELF->getPropertyWithDefault(key, dflt))); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getPropertyAsInt(void* self, const char* key, int* r) +{ + try + { + *r = SELF->getPropertyAsInt(key); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getPropertyAsIntWithDefault(void* self, const char* key, int dflt, int* r) +{ + try + { + *r = SELF->getPropertyAsIntWithDefault(key, dflt); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getPropertyAsList(void* self, const char* key) +{ + try + { + Ice::StringSeq l = SELF->getPropertyAsList(key); + return createResultValue(createStringList(l)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getPropertyAsListWithDefault(void* self, const char* key, mxArray* dflt) +{ + try + { + Ice::StringSeq d; + getStringList(dflt, d); + Ice::StringSeq l = SELF->getPropertyAsListWithDefault(key, d); + return createResultValue(createStringList(l)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getPropertiesForPrefix(void* self, const char* prefix) +{ + try + { + Ice::PropertyDict d = SELF->getPropertiesForPrefix(prefix); + return createResultValue(createStringMap(d)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_setProperty(void* self, const char* key, const char* value) +{ + try + { + SELF->setProperty(key, value); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_getCommandLineOptions(void* self) +{ + try + { + Ice::StringSeq opts = SELF->getCommandLineOptions(); + return createResultValue(createStringList(opts)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_parseCommandLineOptions(void* self, const char* prefix, mxArray* options) +{ + try + { + Ice::StringSeq opts; + getStringList(options, opts); + Ice::StringSeq rem = SELF->parseCommandLineOptions(prefix, opts); + return createResultValue(createStringList(rem)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_parseIceCommandLineOptions(void* self, mxArray* options) +{ + try + { + Ice::StringSeq opts; + getStringList(options, opts); + Ice::StringSeq rem = SELF->parseIceCommandLineOptions(opts); + return createResultValue(createStringList(rem)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_load(void* self, const char* file) +{ + try + { + SELF->load(file); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Properties_clone(void* self, void** r) +{ + try + { + shared_ptr<Ice::Properties> c = SELF->clone(); + *r = new shared_ptr<Ice::Properties>(c); + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +} diff --git a/matlab/src/IceMatlab/Util.cpp b/matlab/src/IceMatlab/Util.cpp new file mode 100644 index 00000000000..d4c15b7255e --- /dev/null +++ b/matlab/src/IceMatlab/Util.cpp @@ -0,0 +1,648 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/LocalException.h> +#include <iostream> +#include <string> +#include <locale> +#include <codecvt> +#include "icematlab.h" +#include "Util.h" + +using namespace std; + +namespace +{ + +string +replace(string s, string patt, string val) +{ + string r = s; + string::size_type pos = r.find(patt); + while(pos != string::npos) + { + r.replace(pos, patt.size(), val); + pos += val.size(); + pos = r.find(patt, pos); + } + return r; +} + +void +getMajorMinor(mxArray* p, Ice::Byte& major, Ice::Byte& minor) +{ + mxArray* maj = mxGetProperty(p, 0, "major"); + assert(maj); + if(!mxIsScalar(maj)) + { + throw std::invalid_argument("major is not a scalar"); + } + major = static_cast<Ice::Byte>(mxGetScalar(maj)); + mxArray* min = mxGetProperty(p, 0, "minor"); + assert(min); + if(!mxIsScalar(min)) + { + throw std::invalid_argument("minor is not a scalar"); + } + minor = static_cast<Ice::Byte>(mxGetScalar(min)); +} + +} + +mxArray* +IceMatlab::createStringFromUTF8(const string& s) +{ +#ifdef _MSC_VER + // + // Workaround for Visual Studio bug that causes a link error when using char16_t. + // + wstring utf16 = wstring_convert<codecvt_utf8_utf16<wchar_t>, wchar_t>{}.from_bytes(s.data()); +#else + u16string utf16 = wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(s.data()); +#endif + mwSize dims[2] = { 1, utf16.size() }; + mxArray* r = mxCreateCharArray(2, dims); + mxChar* buf = mxGetChars(r); + int i = 0; +#ifdef _MSC_VER + for(wchar_t c : utf16) +#else + for(char16_t c : utf16) +#endif + { + buf[i++] = static_cast<mxChar>(c); + } + return r; +} + +string +IceMatlab::getStringFromUTF16(mxArray* p) +{ + char* s = mxArrayToUTF8String(p); + if(!s) + { + throw std::invalid_argument("value is not a char array"); + } + string str(s); + mxFree(s); + return str; +} + +mxArray* +IceMatlab::createEmpty() +{ + return mxCreateNumericMatrix(0, 0, mxDOUBLE_CLASS, mxREAL); +} + +mxArray* +IceMatlab::createBool(bool v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxLOGICAL_CLASS, mxREAL); + bool* p = reinterpret_cast<bool*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createByte(Ice::Byte v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxUINT8_CLASS, mxREAL); + Ice::Byte* p = reinterpret_cast<Ice::Byte*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createShort(short v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxINT16_CLASS, mxREAL); + short* p = reinterpret_cast<short*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createInt(int v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); + int* p = reinterpret_cast<int*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createLong(long long v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + long long* p = reinterpret_cast<long long*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createFloat(float v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); + float* p = reinterpret_cast<float*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createDouble(double v) +{ + mxArray* r = mxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); + double* p = reinterpret_cast<double*>(mxGetPr(r)); + *p = v; + return r; +} + +mxArray* +IceMatlab::createEnumerator(const string& type, int v) +{ + string func = type + ".ice_getValue"; + mxArray* param = createInt(v); + mxArray* r; + mexCallMATLAB(1, &r, 1, ¶m, func.c_str()); + mxFree(param); + return r; +} + +int +IceMatlab::getEnumerator(mxArray* p, const string& type) +{ + if(!mxIsClass(p, type.c_str())) + { + throw invalid_argument("expected enumerator of type " + type); + } + return static_cast<int>(mxGetScalar(p)); +} + +mxArray* +IceMatlab::createIdentity(const Ice::Identity& id) +{ + mxArray* params[2]; + params[0] = createStringFromUTF8(id.name); + params[1] = createStringFromUTF8(id.category); + mxArray* r; + mexCallMATLAB(1, &r, 2, params, "Ice.Identity"); + return r; +} + +void +IceMatlab::getIdentity(mxArray* p, Ice::Identity& id) +{ + if(!mxIsClass(p, "Ice.Identity")) + { + throw std::invalid_argument("argument is not Ice.Identity"); + } + mxArray* name = mxGetProperty(p, 0, "name"); + assert(name); + id.name = getStringFromUTF16(name); + mxArray* category = mxGetProperty(p, 0, "category"); + assert(category); + id.category = getStringFromUTF16(category); +} + +mxArray* +IceMatlab::createStringMap(const map<string, string>& m) +{ + mxArray* r; + if(m.empty()) + { + mexCallMATLAB(1, &r, 0, 0, "containers.Map"); + } + else + { + mwSize dims[2] = {1, 0}; + dims[1] = m.size(); + mxArray* keys = mxCreateCellArray(2, dims); + mxArray* values = mxCreateCellArray(2, dims); + int idx = 0; + for(map<string, string>::const_iterator p = m.begin(); p != m.end(); ++p) + { + mxSetCell(keys, idx, createStringFromUTF8(p->first)); + mxSetCell(values, idx, createStringFromUTF8(p->second)); + idx++; + } + mxArray* params[2]; + params[0] = keys; + params[1] = values; + mexCallMATLAB(1, &r, 2, params, "containers.Map"); + } + return r; +} + +void +IceMatlab::getStringMap(mxArray* p, map<string, string>& m) +{ + if(mxIsEmpty(p)) + { + m.clear(); + } + else if(!mxIsClass(p, "containers.Map")) + { + throw std::invalid_argument("argument is not a containers.Map"); + } + else + { + mxArray* params[1]; + params[0] = p; + mxArray* keys; + mexCallMATLAB(1, &keys, 1, params, "keys"); + mxArray* values; + mexCallMATLAB(1, &values, 1, params, "values"); + assert(mxGetM(keys) == 1 && mxGetM(values) == 1); + assert(mxGetN(keys) == mxGetN(values)); + const size_t n = mxGetN(keys); + try + { + for(size_t i = 0; i < n; ++i) + { + string k = getStringFromUTF16(mxGetCell(keys, i)); + string v = getStringFromUTF16(mxGetCell(values, i)); + m[k] = v; + } + mxDestroyArray(keys); + mxDestroyArray(values); + } + catch(...) + { + mxDestroyArray(keys); + mxDestroyArray(values); + throw; + } + } +} + +mxArray* +IceMatlab::createEncodingVersion(const Ice::EncodingVersion& v) +{ + mxArray* params[2]; + params[0] = mxCreateDoubleScalar(v.major); + params[1] = mxCreateDoubleScalar(v.minor); + mxArray* r; + mexCallMATLAB(1, &r, 2, params, "Ice.EncodingVersion"); + return r; +} + +void +IceMatlab::getEncodingVersion(mxArray* p, Ice::EncodingVersion& v) +{ + if(!mxIsClass(p, "Ice.EncodingVersion")) + { + throw std::invalid_argument("argument is not Ice.EncodingVersion"); + } + getMajorMinor(p, v.major, v.minor); +} + +mxArray* +IceMatlab::createProtocolVersion(const Ice::ProtocolVersion& v) +{ + mxArray* params[2]; + params[0] = mxCreateDoubleScalar(v.major); + params[1] = mxCreateDoubleScalar(v.minor); + mxArray* r; + mexCallMATLAB(1, &r, 2, params, "Ice.ProtocolVersion"); + return r; +} + +void +IceMatlab::getProtocolVersion(mxArray* p, Ice::ProtocolVersion& v) +{ + if(!mxIsClass(p, "Ice.ProtocolVersion")) + { + throw std::invalid_argument("argument is not Ice.ProtocolVersion"); + } + getMajorMinor(p, v.major, v.minor); +} + +mxArray* +IceMatlab::convertException(const std::exception& exc) +{ + mxArray* ex; + if(dynamic_cast<const Ice::LocalException*>(&exc)) + { + const Ice::LocalException* iceEx = dynamic_cast<const Ice::LocalException*>(&exc); + const string typeId = iceEx->ice_id(); + // + // The exception ID uses single colon separators. + // + string id = typeId.substr(2); // Remove leading "::" from type ID + id = replace(id, "::", ":"); + + string cls = typeId.substr(2); // Remove leading "::" from type ID + cls = replace(cls, "::", "."); + + mxArray* params[10]; + params[0] = createStringFromUTF8(id); + int idx = 2; + string msg = typeId; // Use the type ID as the default exception message + + try + { + iceEx->ice_throw(); + } + catch(const Ice::InitializationException& e) + { + msg = e.reason; + params[idx++] = createStringFromUTF8(e.reason); + } + catch(const Ice::PluginInitializationException& e) + { + msg = e.reason; + params[idx++] = createStringFromUTF8(e.reason); + } + catch(const Ice::AlreadyRegisteredException& e) + { + params[idx++] = createStringFromUTF8(e.kindOfObject); + params[idx++] = createStringFromUTF8(e.id); + } + catch(const Ice::NotRegisteredException& e) + { + params[idx++] = createStringFromUTF8(e.kindOfObject); + params[idx++] = createStringFromUTF8(e.id); + } + catch(const Ice::TwowayOnlyException& e) + { + params[idx++] = createStringFromUTF8(e.operation); + } + catch(const Ice::UnknownException& e) + { + params[idx++] = createStringFromUTF8(e.unknown); + } + catch(const Ice::ObjectAdapterDeactivatedException& e) + { + params[idx++] = createStringFromUTF8(e.name); + } + catch(const Ice::ObjectAdapterIdInUseException& e) + { + params[idx++] = createStringFromUTF8(e.id); + } + catch(const Ice::NoEndpointException& e) + { + params[idx++] = createStringFromUTF8(e.proxy); + } + catch(const Ice::EndpointParseException& e) + { + params[idx++] = createStringFromUTF8(e.str); + } + catch(const Ice::EndpointSelectionTypeParseException& e) + { + params[idx++] = createStringFromUTF8(e.str); + } + catch(const Ice::VersionParseException& e) + { + params[idx++] = createStringFromUTF8(e.str); + } + catch(const Ice::IdentityParseException& e) + { + params[idx++] = createStringFromUTF8(e.str); + } + catch(const Ice::ProxyParseException& e) + { + params[idx++] = createStringFromUTF8(e.str); + } + catch(const Ice::IllegalIdentityException& e) + { + params[idx++] = createIdentity(e.id); + } + catch(const Ice::RequestFailedException& e) + { + params[idx++] = createIdentity(e.id); + params[idx++] = createStringFromUTF8(e.facet); + params[idx++] = createStringFromUTF8(e.operation); + } + catch(const Ice::FileException& e) + { + params[idx++] = mxCreateDoubleScalar(e.error); + params[idx++] = createStringFromUTF8(e.path); + } + catch(const Ice::SyscallException& e) // This must appear after all subclasses of SyscallException. + { + params[idx++] = mxCreateDoubleScalar(e.error); + } + catch(const Ice::DNSException& e) + { + params[idx++] = mxCreateDoubleScalar(e.error); + params[idx++] = createStringFromUTF8(e.host); + } + catch(const Ice::UnsupportedProtocolException& e) + { + params[idx++] = createProtocolVersion(e.bad); + params[idx++] = createProtocolVersion(e.supported); + } + catch(const Ice::UnsupportedEncodingException& e) + { + params[idx++] = createEncodingVersion(e.bad); + params[idx++] = createEncodingVersion(e.supported); + } + catch(const Ice::ConnectionManuallyClosedException& e) + { + params[idx++] = mxCreateLogicalScalar(e.graceful ? 1 : 0); + } + catch(const Ice::NoValueFactoryException& e) + { + params[idx++] = createStringFromUTF8(e.reason); + params[idx++] = createStringFromUTF8(e.type); + } + catch(const Ice::UnexpectedObjectException& e) + { + params[idx++] = createStringFromUTF8(e.reason); + params[idx++] = createStringFromUTF8(e.type); + params[idx++] = createStringFromUTF8(e.expectedType); + } + catch(const Ice::ProtocolException& e) // This must appear after all subclasses of ProtocolException. + { + params[idx++] = createStringFromUTF8(e.reason); + } + catch(const Ice::FeatureNotSupportedException& e) + { + params[idx++] = createStringFromUTF8(e.unsupportedFeature); + } + catch(const Ice::SecurityException& e) + { + params[idx++] = createStringFromUTF8(e.reason); + } + catch(const Ice::IllegalServantException& e) + { + params[idx++] = createStringFromUTF8(e.reason); + } + catch(const Ice::LocalException&) + { + // + // Nothing to do. + // + } + + // + // NOTE: Matlab interprets the msg argument as an sprintf format string. It will complain if it + // finds invalid syntax. + // + params[1] = createStringFromUTF8(msg); + mexCallMATLAB(1, &ex, idx, params, cls.c_str()); + } + else + { + mxArray* params[2]; + params[0] = createStringFromUTF8("Ice:CppException"); + params[1] = createStringFromUTF8(exc.what()); + mexCallMATLAB(1, &ex, 2, params, "MException"); + } + return ex; +} + +static const char* resultFields[] = {"exception", "result"}; + +mxArray* +IceMatlab::createResultValue(mxArray* result) +{ + mwSize dims[2] = {1, 1}; + mxArray* r = mxCreateStructArray(2, dims, 2, resultFields); + mxSetFieldByNumber(r, 0, 1, result); + return r; +} + +mxArray* +IceMatlab::createResultException(mxArray* ex) +{ + mwSize dims[2] = {1, 1}; + mxArray* r = mxCreateStructArray(2, dims, 2, resultFields); + mxSetFieldByNumber(r, 0, 0, ex); + return r; +} + +mxArray* +IceMatlab::createStringList(const vector<string>& v) +{ + mxArray* r = mxCreateCellMatrix(1, v.size()); + mwIndex i = 0; + for(vector<string>::const_iterator p = v.begin(); p != v.end(); ++p, ++i) + { + mxSetCell(r, i, createStringFromUTF8(*p)); + } + return r; +} + +void +IceMatlab::getStringList(mxArray* m, vector<string>& v) +{ + if(!mxIsCell(m)) + { + throw std::invalid_argument("argument is not a cell array"); + } + if(mxGetM(m) > 1) + { + throw std::invalid_argument("invalid dimension in cell array"); + } + size_t n = mxGetN(m); + v.clear(); + for(size_t i = 0; i < n; ++i) + { + mxArray* c = mxGetCell(m, i); + v.push_back(getStringFromUTF16(c)); + } +} + +#if 0 +void* +IceMatlab::getImpl(mxArray* obj, const std::string& className) +{ + void* p = 0; + if(!mxIsEmpty(obj)) + { + if(!mxIsClass(obj, className.c_str())) + { + throw std::invalid_argument("expecting object of type " + className); + } + mxArray* implProp = mxGetProperty(obj, 0, "impl"); + assert(implProp); + mxArray* value = mxGetProperty(implProp, 0, "value"); + assert(value); + p = mxGetData(value); + } + return p; +} +#endif + +namespace +{ + +string +lookupKwd(const string& name) +{ + // + // Keyword list. *Must* be kept in alphabetical order. + // + // This list must match the one in slice2matlab. + // + static const string keywordList[] = + { + "break", "case", "catch", "classdef", "continue", "else", "elseif", "end", "for", "function", "global", + "if", "otherwise", "parfor", "persistent", "return", "spmd", "switch", "try", "while" + }; + bool found = binary_search(&keywordList[0], + &keywordList[sizeof(keywordList) / sizeof(*keywordList)], + name); + return found ? "slice_" + name : name; +} + +// +// Split a scoped name into its components and return the components as a list of (unscoped) identifiers. +// +vector<string> +splitScopedName(const string& scoped) +{ + assert(scoped[0] == ':'); + vector<string> ids; + string::size_type next = 0; + string::size_type pos; + while((pos = scoped.find("::", next)) != string::npos) + { + pos += 2; + if(pos != scoped.size()) + { + string::size_type endpos = scoped.find("::", pos); + if(endpos != string::npos) + { + ids.push_back(scoped.substr(pos, endpos - pos)); + } + } + next = pos; + } + if(next != scoped.size()) + { + ids.push_back(scoped.substr(next)); + } + else + { + ids.push_back(""); + } + + return ids; +} + +} + +string +IceMatlab::idToClass(const string& id) +{ + vector<string> ids = splitScopedName(id); + transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd)); + stringstream result; + for(vector<string>::const_iterator i = ids.begin(); i != ids.end(); ++i) + { + if(i != ids.begin()) + { + result << "."; + } + result << *i; + } + return result.str(); +} diff --git a/matlab/src/IceMatlab/Util.h b/matlab/src/IceMatlab/Util.h new file mode 100644 index 00000000000..60ba9a2c038 --- /dev/null +++ b/matlab/src/IceMatlab/Util.h @@ -0,0 +1,47 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Identity.h> +#include <Ice/Version.h> +#include <mex.h> + +typedef struct mxArray_tag mxArray; // Forward declaration to avoid importing mex.h here + +namespace IceMatlab +{ + +mxArray* createStringFromUTF8(const std::string&); +std::string getStringFromUTF16(mxArray*); +mxArray* createEmpty(); +mxArray* createBool(bool); +mxArray* createByte(Ice::Byte); +mxArray* createShort(short); +mxArray* createInt(int); +mxArray* createLong(long long); +mxArray* createFloat(float); +mxArray* createDouble(double); +mxArray* createEnumerator(const std::string&, int); +int getEnumerator(mxArray*, const std::string&); +mxArray* createIdentity(const Ice::Identity&); +void getIdentity(mxArray*, Ice::Identity&); +mxArray* createStringMap(const std::map<std::string, std::string>&); +void getStringMap(mxArray*, std::map<std::string, std::string>&); +mxArray* createProtocolVersion(const Ice::ProtocolVersion&); +void getProtocolVersion(mxArray*, Ice::ProtocolVersion&); +mxArray* createEncodingVersion(const Ice::EncodingVersion&); +void getEncodingVersion(mxArray*, Ice::EncodingVersion&); +mxArray* convertException(const std::exception&); +mxArray* createResultValue(mxArray*); +mxArray* createResultException(mxArray*); +mxArray* createStringList(const std::vector<std::string>&); +void getStringList(mxArray*, std::vector<std::string>&); + +std::string idToClass(const std::string&); + +} diff --git a/matlab/src/IceMatlab/icematlab.h b/matlab/src/IceMatlab/icematlab.h new file mode 100644 index 00000000000..5226c61bd41 --- /dev/null +++ b/matlab/src/IceMatlab/icematlab.h @@ -0,0 +1,280 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifdef _WIN32 +#ifdef EXPORT_FCNS +#define EXPORTED_FUNCTION __declspec(dllexport) +#else +#define EXPORTED_FUNCTION __declspec(dllimport) +#endif +#else +#define EXPORTED_FUNCTION +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct mxArray_tag mxArray; // Forward declaration to avoid importing mex.h here + +EXPORTED_FUNCTION mxArray* Ice_initialize(mxArray*, void*, void**); +EXPORTED_FUNCTION mxArray* Ice_stringToIdentity(mxArray*); +EXPORTED_FUNCTION mxArray* Ice_identityToString(mxArray*); + +EXPORTED_FUNCTION mxArray* Ice_Communicator__release(void*); +EXPORTED_FUNCTION mxArray* Ice_Communicator_stringToProxy(void*, const char*, void**); +EXPORTED_FUNCTION mxArray* Ice_Communicator_getProperties(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_Communicator_createOutputStream(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_Communicator_destroy(void*); + +typedef enum +{ + Normal, + Nonmutating, + Idempotent +} Ice_OperationMode; + +typedef enum +{ + Random, + Ordered +} Ice_EndpointSelectionType; + +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx__release(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_equals(void*, void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_createOutputStream(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invoke(void*, const char*, Ice_OperationMode, void*, mxArray*, + unsigned char*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invokeNC(void*, const char*, Ice_OperationMode, void*, unsigned char*, + void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invokeAsync(void*, const char*, Ice_OperationMode, void*, mxArray*, + void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invokeAsyncNC(void*, const char*, Ice_OperationMode, void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_toString(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getCommunicator(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getIdentity(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_identity(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getContext(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_context(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getFacet(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_facet(void*, const char*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getAdapterId(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_adapterId(void*, const char*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getEndpoints(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_endpoints(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getLocatorCacheTimeout(void*, int*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_locatorCacheTimeout(void*, int, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getInvocationTimeout(void*, int*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invocationTimeout(void*, int, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getConnectionId(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_connectionId(void*, const char*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isConnectionCached(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_connectionCached(void*, unsigned char, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getEndpointSelection(void*, Ice_EndpointSelectionType*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_endpointSelection(void*, Ice_EndpointSelectionType, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getEncodingVersion(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_encodingVersion(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getRouter(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_router(void*, void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getLocator(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_locator(void*, void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isSecure(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_secure(void*, unsigned char, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isPreferSecure(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_preferSecure(void*, unsigned char, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isTwoway(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_twoway(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isOneway(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_oneway(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isBatchOneway(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_batchOneway(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isDatagram(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_datagram(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_compress(void*, unsigned char, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_timeout(void*, int, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getConnection(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getConnectionAsync(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getCachedConnection(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_flushBatchRequests(void*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_flushBatchRequestsAsync(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_clone(void*, void**); + +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture__release(void*); +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture_id(void*, unsigned long long*); +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture_wait(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture_stream(void*, unsigned char*, void**); +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture_state(void*); +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture_cancel(void*); +EXPORTED_FUNCTION mxArray* Ice_InvocationFuture_check(void*); + +EXPORTED_FUNCTION mxArray* Ice_GetConnectionFuture__release(void*); +EXPORTED_FUNCTION mxArray* Ice_GetConnectionFuture_id(void*, unsigned long long*); +EXPORTED_FUNCTION mxArray* Ice_GetConnectionFuture_wait(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_GetConnectionFuture_fetch(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_GetConnectionFuture_state(void*); +EXPORTED_FUNCTION mxArray* Ice_GetConnectionFuture_cancel(void*); + +EXPORTED_FUNCTION mxArray* Ice_SentFuture__release(void*); +EXPORTED_FUNCTION mxArray* Ice_SentFuture_id(void*, unsigned long long*); +EXPORTED_FUNCTION mxArray* Ice_SentFuture_wait(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_SentFuture_state(void*); +EXPORTED_FUNCTION mxArray* Ice_SentFuture_cancel(void*); +EXPORTED_FUNCTION mxArray* Ice_SentFuture_check(void*); + +typedef enum +{ + DefaultFormat, + CompactFormat, + SlicedFormat +} Ice_FormatType; + +typedef enum +{ + OptionalFormatF1 = 0, + OptionalFormatF2 = 1, + OptionalFormatF4 = 2, + OptionalFormatF8 = 3, + OptionalFormatSize = 4, + OptionalFormatVSize = 5, + OptionalFormatFSize = 6, + OptionalFormatClass = 7 +} Ice_OptionalFormat; + +EXPORTED_FUNCTION mxArray* Ice_OutputStream__release(void*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBool(void*, unsigned char); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolOpt(void*, int, unsigned char); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolSeq(void*, const unsigned char*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolSeqOpt(void*, int, const unsigned char*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByte(void*, unsigned char); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteOpt(void*, int, unsigned char); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteSeq(void*, const unsigned char*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteSeqOpt(void*, int, const unsigned char*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShort(void*, short); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortOpt(void*, int, short); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortSeq(void*, const short*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortSeqOpt(void*, int, const short*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeInt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntOpt(void*, int, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntSeq(void*, const int*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntSeqOpt(void*, int, const int*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLong(void*, long long); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongOpt(void*, int, long long); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongSeq(void*, const long long*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongSeqOpt(void*, int, const long long*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloat(void*, float); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatOpt(void*, int, float); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatSeq(void*, const float*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatSeqOpt(void*, int, const float*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDouble(void*, double); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleOpt(void*, int, double); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleSeq(void*, const double*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleSeqOpt(void*, int, const double*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeString(void*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringOpt(void*, int, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringSeq(void*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringSeqOpt(void*, int, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeSize(void*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeProxy(void*, void*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeProxyOpt(void*, int, void*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeEnum(void*, int, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_startEncapsulation(void*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_startEncapsulationWithFormat(void*, Ice_FormatType); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_endEncapsulation(void*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_startSlice(void*, const char*, int, unsigned char); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_endSlice(void*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeOptional(void*, int, Ice_OptionalFormat, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_startSize(void*, unsigned int*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_endSize(void*, unsigned int); + +EXPORTED_FUNCTION mxArray* Ice_InputStream__release(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readBool(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readBoolSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readBoolOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readBoolSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readByte(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readByteSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readByteOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readByteSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readShort(void*, short*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readShortSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readShortOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readShortSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readInt(void*, int*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readIntSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readIntOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readIntSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readLong(void*, long long*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readLongSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readLongOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readLongSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloat(void*, float*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloatSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloatOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloatSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readDouble(void*, double*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readDoubleSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readDoubleOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readDoubleSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readString(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readStringSeq(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readStringOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readStringSeqOpt(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_skip(void*, int); +EXPORTED_FUNCTION mxArray* Ice_InputStream_startException(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_endException(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_startEncapsulation(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_endEncapsulation(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_skipEmptyEncapsulation(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_skipEncapsulation(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_getEncoding(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_startSlice(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_endSlice(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_skipSlice(void*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readSize(void*, int*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readOptional(void*, int, Ice_OptionalFormat, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readProxy(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readProxyOpt(void*, int, void**); +EXPORTED_FUNCTION mxArray* Ice_InputStream_readEnum(void*, int, int*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_throwException(void*, mxArray*); + +EXPORTED_FUNCTION mxArray* Ice_createProperties(mxArray*, void*, void**); +EXPORTED_FUNCTION mxArray* Ice_Properties__release(void*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getProperty(void*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getPropertyWithDefault(void*, const char*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getPropertyAsInt(void*, const char*, int*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getPropertyAsIntWithDefault(void*, const char*, int, int*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getPropertyAsList(void*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getPropertyAsListWithDefault(void*, const char*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getPropertiesForPrefix(void*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Properties_setProperty(void*, const char*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Properties_getCommandLineOptions(void*); +EXPORTED_FUNCTION mxArray* Ice_Properties_parseCommandLineOptions(void*, const char*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_Properties_parseIceCommandLineOptions(void*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_Properties_load(void*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Properties_clone(void*, void**); + +EXPORTED_FUNCTION mxArray* Ice_Connection__release(void*); +EXPORTED_FUNCTION mxArray* Ice_Connection_close(void*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_Connection_createProxy(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_Connection_flushBatchRequests(void*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_Connection_flushBatchRequestsAsync(void*, mxArray*, void**); +EXPORTED_FUNCTION mxArray* Ice_Connection_heartbeat(void*); +EXPORTED_FUNCTION mxArray* Ice_Connection_heartbeatAsync(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_Connection_setACM(void*, mxArray*, mxArray*, mxArray*); +EXPORTED_FUNCTION mxArray* Ice_Connection_getACM(void*); +EXPORTED_FUNCTION mxArray* Ice_Connection_type(void*); +EXPORTED_FUNCTION mxArray* Ice_Connection_timeout(void*, int*); +EXPORTED_FUNCTION mxArray* Ice_Connection_toString(void*); +EXPORTED_FUNCTION mxArray* Ice_Connection_setBufferSize(void*, int, int); +EXPORTED_FUNCTION mxArray* Ice_Connection_throwException(void*); + +#ifdef __cplusplus +} +#endif diff --git a/matlab/test/Ice/operations/AllTests.m b/matlab/test/Ice/operations/AllTests.m new file mode 100644 index 00000000000..294c4ac6b23 --- /dev/null +++ b/matlab/test/Ice/operations/AllTests.m @@ -0,0 +1,53 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef AllTests + methods(Static) + function r = allTests(app) + communicator = app.communicator(); + ref = ['test:', app.getTestEndpoint(0, '')]; + base = communicator.stringToProxy(ref); + cl = Test.MyClassPrx.checkedCast(base); + derived = Test.MyDerivedClassPrx.checkedCast(cl); + + fprintf('testing twoway operations... '); + Twoways.twoways(app, cl); + Twoways.twoways(app, derived); + derived.opDerived(); + fprintf('ok\n'); + + fprintf('testing oneway operations... '); + Oneways.oneways(app, cl); + fprintf('ok\n'); + + fprintf('testing twoway operations with AMI... '); + TwowaysAMI.twowaysAMI(app, cl); + TwowaysAMI.twowaysAMI(app, derived); + fprintf('ok\n'); + + fprintf('testing oneway operations with AMI... '); + OnewaysAMI.onewaysAMI(app, cl); + fprintf('ok\n'); + + fprintf('testing batch oneway operations... '); + BatchOneways.batchOneways(app, cl); + BatchOneways.batchOneways(app, derived); + fprintf('ok\n'); + + fprintf('testing batch AMI oneway operations... '); + BatchOnewaysAMI.batchOneways(app, cl); + BatchOnewaysAMI.batchOneways(app, derived); + fprintf('ok\n'); + + r = cl; + end + end +end diff --git a/matlab/test/Ice/operations/Application.m b/matlab/test/Ice/operations/Application.m new file mode 100644 index 00000000000..9ffff601346 --- /dev/null +++ b/matlab/test/Ice/operations/Application.m @@ -0,0 +1,157 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) Application < handle + methods(Sealed) + % + % main() initializes the Communicator, calls run(), and destroys + % the Communicator upon return from run(). It thereby handles + % all exceptions properly, i.e., error messages are printed + % if exceptions propagate to main(), and the Communicator is + % always destroyed, regardless of exceptions. + % + function r = main(obj, appName, varargin) + if ~isempty(obj.communicator_) + printf('%s: only one instance of the Application class can be used', appName); + r = 1; + return; + end + + obj.testName_ = appName; + + args = {}; + initializationData = []; + + if length(varargin) >= 1 + args = varargin{1}; + end + if length(varargin) >= 2 + initializationData = varargin{2}; + end + + % + % We parse the properties here to extract Ice.ProgramName. + % + if isempty(initializationData) + [initializationData, args] = obj.getInitData(args); + end + + if ~isempty(initializationData) + initData = initializationData.clone(); + else + initData = Ice.InitializationData(); + end + + [initData.properties_, args] = Ice.createProperties(args, initData.properties_); + + %TBD + % If the process logger is the default logger, we replace it with a + % a logger that uses the program name as the prefix. + % + %if(Util.getProcessLogger() instanceof LoggerI) + %{ + % Util.setProcessLogger(new LoggerI(initData.properties_.getProperty('Ice.ProgramName'), '')); + %} + + status = 0; + + try + [communicator, args] = Ice.initialize(args, initData); + obj.communicator_ = communicator; + + status = obj.run(args); + catch ex + fprintf('%s: caught %s', obj.testName_, ex.identifier); + disp(getReport(ex,'extended')); + status = 1; + end + obj.communicator_.destroy(); + obj.communicator_ = []; + + r = status; + end + function r = initialize(obj, varargin) + assert(length(varargin) <= 1); + if length(varargin) == 0 + r = Ice.initialize(); + else + r = Ice.initialize(varargin{1}); + end + end + function setLogger(obj, logger) + obj.logger_ = logger; + end + function r = appName(obj) + r = obj.testName_; + end + function r = communicator(obj) + r = obj.communicator_; + end + function r = createInitializationData(obj) + initData = Ice.InitializationData(); + initData.logger = obj.logger_; + r = initData; + end + function r = getTestEndpoint(obj, num, prot) + r = Application.getTestEndpointWithProperties(obj.communicator_.getProperties(), num, prot); + end + function r = getTestHost(obj) + r = Application.getTestHostWithProperties(obj.communicator_.getProperties()); + end + function r = getTestProtocol(obj) + r = Application.getTestProtocolWithProperties(obj.communicator_.getProperties()); + end + function r = getTestPort(obj, num) + r = Application.getTestPortWithProperties(obj.communicator_.getProperties(), num); + end + end + methods(Static) + function r = getTestEndpointWithProperties(props, num, prot) + protocol = prot; + if length(protocol) == 0 + protocol = props.getPropertyWithDefault('Ice.Default.Protocol', 'default'); + end + + basePort = props.getPropertyAsIntWithDefault('Test.BasePort', 12010); + + r = sprintf('%s -p %d', protocol, basePort + num); + end + function r = getTestHostWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Host', '127.0.0.1'); + end + function r = getTestProtocolWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Protocol', 'tcp'); + end + function r = getTestPortWithProperties(props, num) + r = props.getPropertyAsIntWithDefault('Test.BasePort', 12010) + num; + end + end + methods(Abstract) + r = run(obj, args) + end + methods(Access=protected) + % + % Hook to override the initialization data. This hook is + % necessary because some properties must be set prior to + % communicator initialization. + % + function [initData, remArgs] = getInitData(obj, args) + initData = obj.createInitializationData(); + [initData.properties_, remArgs] = Ice.createProperties(args); + remArgs = initData.properties_.parseCommandLineOptions('Test', remArgs); + end + end + properties(Access=private) + testName_ + communicator_ + logger_ + end +end diff --git a/matlab/test/Ice/operations/BatchOneways.m b/matlab/test/Ice/operations/BatchOneways.m new file mode 100644 index 00000000000..83e9843ce4c --- /dev/null +++ b/matlab/test/Ice/operations/BatchOneways.m @@ -0,0 +1,114 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef BatchOneways + methods(Static) + function batchOneways(app, p) + communicator = app.communicator(); + properties = communicator.getProperties(); + bs1 = zeros(1, 10 * 1024); + + batch = p.ice_batchOneway(); + batch.ice_flushBatchRequests(); % Empty flush + + if ~isempty(batch.ice_getConnection()) + batch.ice_getConnection().flushBatchRequests(Ice.CompressBatch.BasedOnProxy); + end + %communicator.flushBatchRequests(com.zeroc.Ice.CompressBatch.BasedOnProxy); + + p.opByteSOnewayCallCount(); % Reset the call count + + for i = 1:30 + try + batch.opByteSOneway(bs1); + catch ex + if isa(ex, 'Ice.MemoryLimitException') + assert(false); + else + rethrow(ex); + end + end + end + + count = 0; + while count < 27 % 3 * 9 requests auto-flushed. + count = count + p.opByteSOnewayCallCount(); + pause(0.1); + end + + if ~isempty(batch.ice_getConnection()) + batch1 = p.ice_batchOneway(); + batch2 = p.ice_batchOneway(); + + batch1.ice_ping(); + batch2.ice_ping(); + batch1.ice_flushBatchRequests(); + batch1.ice_getConnection().close(Ice.ConnectionClose.GracefullyWithWait); + batch1.ice_ping(); + batch2.ice_ping(); + + batch1.ice_getConnection(); + batch2.ice_getConnection(); + + batch1.ice_ping(); + batch1.ice_getConnection().close(Ice.ConnectionClose.GracefullyWithWait); + batch1.ice_ping(); + batch2.ice_ping(); + end + + identity = Ice.Identity(); + identity.name = "invalid"; + batch3 = batch.ice_identity(identity); + batch3.ice_ping(); + batch3.ice_flushBatchRequests(); + + % Make sure that a bogus batch request doesn't cause troubles to other ones. + batch3.ice_ping(); + batch.ice_ping(); + batch.ice_flushBatchRequests(); + batch.ice_ping(); + + p.ice_ping(); + if ~isempty(p.ice_getConnection()) && isempty(properties.getProperty('Ice.Override.Compress')) + prx = p.ice_getConnection().createProxy(p.ice_getIdentity()).ice_batchOneway(); + + batchC1 = Test.MyClassPrx.uncheckedCast(prx.ice_compress(false)); + batchC2 = Test.MyClassPrx.uncheckedCast(prx.ice_compress(true)); + batchC3 = Test.MyClassPrx.uncheckedCast(prx.ice_identity(identity)); + + batchC1.opByteSOneway(bs1); + batchC1.opByteSOneway(bs1); + batchC1.opByteSOneway(bs1); + batchC1.ice_getConnection().flushBatchRequests(Ice.CompressBatch.Yes); + + batchC2.opByteSOneway(bs1); + batchC2.opByteSOneway(bs1); + batchC2.opByteSOneway(bs1); + batchC1.ice_getConnection().flushBatchRequests(Ice.CompressBatch.No); + + batchC1.opByteSOneway(bs1); + batchC1.opByteSOneway(bs1); + batchC1.opByteSOneway(bs1); + batchC1.ice_getConnection().flushBatchRequests(Ice.CompressBatch.BasedOnProxy); + + batchC1.opByteSOneway(bs1); + batchC2.opByteSOneway(bs1); + batchC1.opByteSOneway(bs1); + batchC1.ice_getConnection().flushBatchRequests(Ice.CompressBatch.BasedOnProxy); + + batchC1.opByteSOneway(bs1); + batchC3.opByteSOneway(bs1); + batchC1.opByteSOneway(bs1); + batchC1.ice_getConnection().flushBatchRequests(Ice.CompressBatch.BasedOnProxy); + end + end + end +end diff --git a/matlab/test/Ice/operations/BatchOnewaysAMI.m b/matlab/test/Ice/operations/BatchOnewaysAMI.m new file mode 100644 index 00000000000..85720f5285b --- /dev/null +++ b/matlab/test/Ice/operations/BatchOnewaysAMI.m @@ -0,0 +1,70 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef BatchOnewaysAMI + methods(Static) + function batchOneways(app, p) + communicator = app.communicator(); + properties = communicator.getProperties(); + bs1 = zeros(1, 10 * 1024); + + batch = p.ice_batchOneway(); + future = batch.ice_flushBatchRequestsAsync(); % Empty flush + future.wait(); + assert(strcmp(future.State, 'finished')); + + futures = {}; + for i = 1:30 + futures{i} = batch.opByteSOnewayAsync(bs1); + end + for i = 1:30 + assert(futures{i}.wait()); + end + + count = 0; + while count < 27 % 3 * 9 requests auto-flushed. + count = count + p.opByteSOnewayCallCount(); + pause(0.1); + end + + if ~isempty(batch.ice_getConnection()) + batch2 = p.ice_batchOneway(); + + batch.ice_pingAsync(); + batch2.ice_pingAsync(); + assert(batch.ice_flushBatchRequestsAsync().wait()); + batch.ice_getConnection().close(Ice.ConnectionClose.GracefullyWithWait); + batch.ice_pingAsync(); + batch2.ice_pingAsync(); + + batch.ice_getConnection(); + batch2.ice_getConnection(); + + batch.ice_pingAsync(); + batch.ice_getConnection().close(Ice.ConnectionClose.GracefullyWithWait); + assert(batch.ice_pingAsync().wait()); + assert(batch2.ice_pingAsync().wait()); + end + + identity = Ice.Identity(); + identity.name = 'invalid'; + batch3 = batch.ice_identity(identity); + batch3.ice_pingAsync(); + assert(batch3.ice_flushBatchRequestsAsync().wait()); + + % Make sure that a bogus batch request doesn't cause troubles to other ones. + batch3.ice_pingAsync(); + batch.ice_pingAsync(); + assert(batch.ice_flushBatchRequestsAsync().wait()); + batch.ice_pingAsync(); + end + end +end diff --git a/matlab/test/Ice/operations/Client.m b/matlab/test/Ice/operations/Client.m new file mode 100644 index 00000000000..79e1771d502 --- /dev/null +++ b/matlab/test/Ice/operations/Client.m @@ -0,0 +1,52 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Client < Application + methods + function r = run(obj, args) + myClass = AllTests.allTests(obj); + + fprintf('testing server shutdown... '); + myClass.shutdown(); + try + myClass.ice_timeout(100).ice_ping(); % Use timeout to speed up testing on Windows + throw(MException()); + catch ex + if isa(ex, 'Ice.LocalException') + fprintf('ok\n'); + else + rethrow(ex); + end + end + + r = 0; + end + end + methods(Access=protected) + function [r, remArgs] = getInitData(obj, args) + [initData, remArgs] = getInitData@Application(obj, args); + initData.properties_.setProperty('Ice.ThreadPool.Client.Size', '2'); + initData.properties_.setProperty('Ice.ThreadPool.Client.SizeWarn', '0'); + initData.properties_.setProperty('Ice.BatchAutoFlushSize', '100'); + r = initData; + end + end + methods(Static) + function start(args) + addpath('generated'); + if ~libisloaded('icematlab') + loadlibrary('icematlab') + end + c = Client(); + status = c.main('Client', args); + end + end +end diff --git a/matlab/test/Ice/operations/Oneways.m b/matlab/test/Ice/operations/Oneways.m new file mode 100644 index 00000000000..d6b00720b87 --- /dev/null +++ b/matlab/test/Ice/operations/Oneways.m @@ -0,0 +1,33 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Oneways + methods(Static) + function oneways(app, p) + p = p.ice_oneway(); + + p.ice_ping(); + + p.opVoid(); + + p.opIdempotent(); + + p.opNonmutating(); + + try + p.opByte(hex2dec('ff'), hex2dec('0f')); + assert(false); + catch ex + assert(isa(ex, 'Ice.TwowayOnlyException')); + end + end + end +end diff --git a/matlab/test/Ice/operations/OnewaysAMI.m b/matlab/test/Ice/operations/OnewaysAMI.m new file mode 100644 index 00000000000..bb5dc3ee223 --- /dev/null +++ b/matlab/test/Ice/operations/OnewaysAMI.m @@ -0,0 +1,63 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef OnewaysAMI + methods(Static) + function onewaysAMI(app, p) + p = p.ice_oneway(); + + call(p, 'ice_ping'); + + try + p.ice_isAAsync(Test.MyClassPrx.ice_staticId()); + catch ex + assert(isa(ex, 'Ice.TwowayOnlyException')); + end + + try + p.ice_idAsync(); + catch ex + assert(isa(ex, 'Ice.TwowayOnlyException')); + end + + try + p.ice_idsAsync(); + catch ex + assert(isa(ex, 'Ice.TwowayOnlyException')); + end + + call(p, 'opVoid'); + + call(p, 'opIdempotent'); + + call(p, 'opNonmutating'); + + try + p.opByteAsync(hex2dec('ff'), hex2dec('0f')); + catch ex + assert(isa(ex, 'Ice.TwowayOnlyException')); + end + end + end +end + +function varargout = call(p, op, varargin) + try + name = [op, 'Async']; + future = p.(name)(varargin{:}); + assert(strcmp(future.Operation, op)); + assert(future.wait()); + assert(strcmp(future.State, 'finished')); + catch ex + disp(getReport(ex, 'extended')); + assert(false); + end +end diff --git a/matlab/test/Ice/operations/Test.ice b/matlab/test/Ice/operations/Test.ice new file mode 100644 index 00000000000..4ae52d91ca9 --- /dev/null +++ b/matlab/test/Ice/operations/Test.ice @@ -0,0 +1,377 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Current.ice> + +module Test +{ + +enum MyEnum +{ + enum1, + enum2, + enum3 +} + +interface MyClass; + +struct AnotherStruct +{ + string s; +} + +struct Structure +{ + MyClass* p; + MyEnum e; + AnotherStruct s; +} + +sequence<byte> ByteS; +sequence<bool> BoolS; +sequence<short> ShortS; +sequence<int> IntS; +sequence<long> LongS; +sequence<float> FloatS; +sequence<double> DoubleS; +sequence<string> StringS; +sequence<MyEnum> MyEnumS; +sequence<MyClass*> MyClassS; + +sequence<ByteS> ByteSS; +sequence<BoolS> BoolSS; +sequence<ShortS> ShortSS; +sequence<IntS> IntSS; +sequence<LongS> LongSS; +sequence<FloatS> FloatSS; +sequence<DoubleS> DoubleSS; +sequence<StringS> StringSS; +sequence<MyEnumS> MyEnumSS; +sequence<MyClassS> MyClassSS; + +sequence<StringSS> StringSSS; + +struct MyStruct +{ + int i; + int j; +} + +dictionary<byte, bool> ByteBoolD; +dictionary<short, int> ShortIntD; +dictionary<long, float> LongFloatD; +dictionary<string, string> StringStringD; +dictionary<string, MyEnum> StringMyEnumD; +dictionary<MyEnum, string> MyEnumStringD; +dictionary<MyStruct, MyEnum> MyStructMyEnumD; + +sequence<ByteBoolD> ByteBoolDS; +sequence<ShortIntD> ShortIntDS; +sequence<LongFloatD> LongFloatDS; +sequence<StringStringD> StringStringDS; +sequence<StringMyEnumD> StringMyEnumDS; +sequence<MyEnumStringD> MyEnumStringDS; +sequence<MyStructMyEnumD> MyStructMyEnumDS; + +dictionary<byte, ByteS> ByteByteSD; +dictionary<bool, BoolS> BoolBoolSD; +dictionary<short, ShortS> ShortShortSD; +dictionary<int, IntS> IntIntSD; +dictionary<long, LongS> LongLongSD; +dictionary<string, FloatS> StringFloatSD; +dictionary<string, DoubleS> StringDoubleSD; +dictionary<string, StringS> StringStringSD; +dictionary<MyEnum, MyEnumS> MyEnumMyEnumSD; + +exception SomeException {} + +interface MyClass +{ + void shutdown(); + + void opVoid(); + + byte opByte(byte p1, byte p2, + out byte p3); + + bool opBool(bool p1, bool p2, + out bool p3); + + long opShortIntLong(short p1, int p2, long p3, + out short p4, out int p5, out long p6); + + double opFloatDouble(float p1, double p2, + out float p3, out double p4); + + string opString(string p1, string p2, + out string p3); + + MyEnum opMyEnum(MyEnum p1, out MyEnum p2); + + MyClass* opMyClass(MyClass* p1, out MyClass* p2, out MyClass* p3); + + Structure opStruct(Structure p1, Structure p2, + out Structure p3); + + ByteS opByteS(ByteS p1, ByteS p2, + out ByteS p3); + + BoolS opBoolS(BoolS p1, BoolS p2, + out BoolS p3); + + LongS opShortIntLongS(Test::ShortS p1, IntS p2, LongS p3, + out ::Test::ShortS p4, out IntS p5, out LongS p6); + + DoubleS opFloatDoubleS(FloatS p1, DoubleS p2, + out FloatS p3, out DoubleS p4); + + StringS opStringS(StringS p1, StringS p2, + out StringS p3); + + ByteSS opByteSS(ByteSS p1, ByteSS p2, + out ByteSS p3); + + BoolSS opBoolSS(BoolSS p1, BoolSS p2, + out BoolSS p3); + + LongSS opShortIntLongSS(ShortSS p1, IntSS p2, LongSS p3, + out ShortSS p4, out IntSS p5, out LongSS p6); + + DoubleSS opFloatDoubleSS(FloatSS p1, DoubleSS p2, + out FloatSS p3, out DoubleSS p4); + + StringSS opStringSS(StringSS p1, StringSS p2, + out StringSS p3); + + StringSSS opStringSSS(StringSSS p1, StringSSS p2, + out StringSSS p3); + + ByteBoolD opByteBoolD(ByteBoolD p1, ByteBoolD p2, + out ByteBoolD p3); + + ShortIntD opShortIntD(ShortIntD p1, ShortIntD p2, + out ShortIntD p3); + + LongFloatD opLongFloatD(LongFloatD p1, LongFloatD p2, + out LongFloatD p3); + + StringStringD opStringStringD(StringStringD p1, StringStringD p2, + out StringStringD p3); + + StringMyEnumD opStringMyEnumD(StringMyEnumD p1, StringMyEnumD p2, + out StringMyEnumD p3); + + MyEnumStringD opMyEnumStringD(MyEnumStringD p1, MyEnumStringD p2, + out MyEnumStringD p3); + + MyStructMyEnumD opMyStructMyEnumD(MyStructMyEnumD p1, MyStructMyEnumD p2, + out MyStructMyEnumD p3); + + ByteBoolDS opByteBoolDS(ByteBoolDS p1, ByteBoolDS p2, + out ByteBoolDS p3); + + ShortIntDS opShortIntDS(ShortIntDS p1, ShortIntDS p2, + out ShortIntDS p3); + + LongFloatDS opLongFloatDS(LongFloatDS p1, LongFloatDS p2, + out LongFloatDS p3); + + StringStringDS opStringStringDS(StringStringDS p1, StringStringDS p2, + out StringStringDS p3); + + StringMyEnumDS opStringMyEnumDS(StringMyEnumDS p1, StringMyEnumDS p2, + out StringMyEnumDS p3); + + MyEnumStringDS opMyEnumStringDS(MyEnumStringDS p1, MyEnumStringDS p2, + out MyEnumStringDS p3); + + MyStructMyEnumDS opMyStructMyEnumDS(MyStructMyEnumDS p1, MyStructMyEnumDS p2, + out MyStructMyEnumDS p3); + + ByteByteSD opByteByteSD(ByteByteSD p1, ByteByteSD p2, + out ByteByteSD p3); + + BoolBoolSD opBoolBoolSD(BoolBoolSD p1, BoolBoolSD p2, + out BoolBoolSD p3); + + ShortShortSD opShortShortSD(ShortShortSD p1, ShortShortSD p2, + out ShortShortSD p3); + + IntIntSD opIntIntSD(IntIntSD p1, IntIntSD p2, + out IntIntSD p3); + + LongLongSD opLongLongSD(LongLongSD p1, LongLongSD p2, + out LongLongSD p3); + + StringFloatSD opStringFloatSD(StringFloatSD p1, StringFloatSD p2, + out StringFloatSD p3); + + StringDoubleSD opStringDoubleSD(StringDoubleSD p1, StringDoubleSD p2, + out StringDoubleSD p3); + + StringStringSD opStringStringSD(StringStringSD p1, StringStringSD p2, + out StringStringSD p3); + + MyEnumMyEnumSD opMyEnumMyEnumSD(MyEnumMyEnumSD p1, MyEnumMyEnumSD p2, + out MyEnumMyEnumSD p3); + + IntS opIntS(IntS s); + + void opByteSOneway(ByteS s); + + int opByteSOnewayCallCount(); + + Ice::Context opContext(); + + void opDoubleMarshaling(double p1, DoubleS p2); + + idempotent void opIdempotent(); + + ["nonmutating"] idempotent void opNonmutating(); + + byte opByte1(byte opByte1); + short opShort1(short opShort1); + int opInt1(int opInt1); + long opLong1(long opLong1); + float opFloat1(float opFloat1); + double opDouble1(double opDouble1); + string opString1(string opString1); + StringS opStringS1(StringS opStringS1); + ByteBoolD opByteBoolD1(ByteBoolD opByteBoolD1); + StringS opStringS2(StringS stringS); + ByteBoolD opByteBoolD2(ByteBoolD byteBoolD); + + StringS opStringLiterals(); + + ["marshaled-result"] Structure opMStruct1(); + ["marshaled-result"] Structure opMStruct2(Structure p1, out Structure p2); + + ["marshaled-result"] StringS opMSeq1(); + ["marshaled-result"] StringS opMSeq2(StringS p1, out StringS p2); + + ["marshaled-result"] StringStringD opMDict1(); + ["marshaled-result"] StringStringD opMDict2(StringStringD p1, out StringStringD p2); +} + +struct MyStruct1 +{ + string tesT; // Same name as the enclosing module + MyClass* myClass; // Same name as an already defined class + string myStruct1; // Same name as the enclosing struct +} + +class MyClass1 +{ + string tesT; // Same name as the enclosing module + MyClass* myClass; // Same name as an already defined class + string myClass1; // Same name as the enclosing class +} + +interface MyDerivedClass extends MyClass +{ + void opDerived(); + MyClass1 opMyClass1(MyClass1 opMyClass1); + MyStruct1 opMyStruct1(MyStruct1 opMyStruct1); +} + +// +// String literals +// + +const string s0 = "\u005c"; // backslash +const string s1 = "\u0041"; // A +const string s2 = "\u0049\u0063\u0065"; // Ice +const string s3 = "\u004121"; // A21 +const string s4 = "\\u0041 \\U00000041"; // \\u0041 \\U00000041 +const string s5 = "\u00FF"; // ÿ +const string s6 = "\u03FF"; // GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL (U+03FF) +const string s7 = "\u05F0"; // HEBREW LIGATURE YIDDISH DOUBLE VAV (U+05F0) +const string s8 = "\U00010000"; // LINEAR B SYLLABLE B008 A (U+10000) +const string s9 = "\U0001F34C"; // BANANA (U+1F34C) +const string s10 = "\u0DA7"; // Sinhala Letter Alpapraana Ttayanna +const string s11 = "\xE2\x82\xac\342\202\254\342\x82\254"; // 3 euro signs (U+20AC) in UTF-8 +const string s12 = "\x5C101"; // \101 (not an octal escape) +const string s13 = "\U0001F34C0123"; // \xd83c\xdf4c\060\061\062\063 +const string s14 = "\U0001F34Cabcd"; // \xd83c\xdf4c\141bcd +const string s15 = "\U0001F34CABCD"; // \xd83c\xdf4c\141BCD +const string s16 = "\x7fabcd"; // \177abcd +const string s17 = "\x7fABCD"; // \177ABCD +const string s18 = "\x011238"; // \001\061\062\0638 +const string s19 = "abc\x011238\x08abcd"; // abc\001\061\062\0638\babcd + +const string sw0 = "\U0000005c"; // backslash +const string sw1 = "\U00000041"; // A +const string sw2 = "\U00000049\U00000063\U00000065"; // Ice +const string sw3 = "\U0000004121"; // A21 +const string sw4 = "\\u0041 \\U00000041"; // \\u0041 \\U00000041 +const string sw5 = "\U000000FF"; // ÿ +const string sw6 = "\U000003FF"; // GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL (U+03FF) +const string sw7 = "\U000005F0"; // HEBREW LIGATURE YIDDISH DOUBLE VAV (U+05F0) +const string sw8 = "\U00010000"; // LINEAR B SYLLABLE B008 A (U+10000) +const string sw9 = "\U0001F34C"; // BANANA (U+1F34C) +const string sw10 = "\U00000DA7"; // Sinhala Letter Alpapraana Ttayanna + +/** +\' single quote byte 0x27 in ASCII encoding +\" double quote byte 0x22 in ASCII encoding +\? question mark byte 0x3f in ASCII encoding +\\ backslash byte 0x5c in ASCII encoding +\a audible bell byte 0x07 in ASCII encoding +\b backspace byte 0x08 in ASCII encoding +\f form feed - new page byte 0x0c in ASCII encoding +\n line feed - new line byte 0x0a in ASCII encoding +\r carriage return byte 0x0d in ASCII encoding +\t horizontal tab byte 0x09 in ASCII encoding +\v vertical tab byte 0x0b in ASCII encoding +**/ + +const string ss0 = "\'\"\?\\\a\b\f\n\r\t\v\6"; +const string ss1 = "\u0027\u0022\u003f\u005c\u0007\u0008\u000c\u000a\u000d\u0009\u000b\u0006"; +const string ss2 = "\U00000027\U00000022\U0000003f\U0000005c\U00000007\U00000008\U0000000c\U0000000a\U0000000d\U00000009\U0000000b\U00000006"; + +const string ss3 = "\\\\U\\u\\"; /* \\U\u\ */ +const string ss4 = "\\\u0041\\"; /* \A\ */ +const string ss5 = "\\u0041\\"; /* \u0041\ */ + +// +// Ĩ - Unicode Character 'LATIN CAPITAL LETTER I WITH TILDE' (U+0128) +// Ÿ - Unicode Character 'LATIN CAPITAL LETTER Y WITH DIAERESIS' (U+0178) +// ÿ - Unicode Character 'LATIN SMALL LETTER Y WITH DIAERESIS' (U+00FF) +// Ā - Unicode Character 'LATIN CAPITAL LETTER A WITH MACRON' (U+0100) +// ἀ - Unicode Character 'GREEK SMALL LETTER ALPHA WITH PSILI' (U+1F00) +// 𐆔 - Unicode Character 'ROMAN DIMIDIA SEXTULA SIGN' (U+10194) +// 𐅪 - Unicode Character 'GREEK ACROPHONIC THESPIAN ONE HUNDRED' (U+1016A) +// 𐆘 - Unicode Character 'ROMAN SESTERTIUS SIGN' (U+10198) +// 🍀 - Unicode Character 'FOUR LEAF CLOVER' (U+1F340) +// 🍁 - Unicode Character 'MAPLE LEAF' (U+1F341) +// 🍂 - Unicode Character 'FALLEN LEAF' (U+1F342) +// 🍃 - Unicode Character 'LEAF FLUTTERING IN WIND' (U+1F343) +// +const string su0 = "ĨŸÿĀἀ𐆔𐅪𐆘🍀🍁🍂🍃"; +const string su1 = "\u0128\u0178\u00FF\u0100\u1F00\U00010194\U0001016A\U00010198\U0001F340\U0001F341\U0001F342\U0001F343"; +const string su2 = "\U00000128\U00000178\U000000FF\U00000100\U00001F00\U00010194\U0001016A\U00010198\U0001F340\U0001F341\U0001F342\U0001F343"; + +} + +module Test2 +{ + +/** + * + * Makes sure that proxy operations are correctly generated when extending an interface from + * a different module (ICE-7639). + * + **/ +interface MyDerivedClass extends Test::MyClass +{ +} + +} diff --git a/matlab/test/Ice/operations/Twoways.m b/matlab/test/Ice/operations/Twoways.m new file mode 100644 index 00000000000..a10439c4d23 --- /dev/null +++ b/matlab/test/Ice/operations/Twoways.m @@ -0,0 +1,1407 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Twoways + methods(Static) + function twoways(app, p) + communicator = app.communicator(); + + literals = p.opStringLiterals(); + + assert(strcmp(Test.s0.value, sprintf('\\')) && ... + strcmp(Test.s0.value, Test.sw0.value) && ... + strcmp(Test.s0.value, literals{1}) && ... + strcmp(Test.s0.value, literals{12})); + + assert(strcmp(Test.s1.value, sprintf('A')) && ... + strcmp(Test.s1.value, Test.sw1.value) && ... + strcmp(Test.s1.value, literals{2}) && ... + strcmp(Test.s1.value, literals{13})); + + assert(strcmp(Test.s2.value, sprintf('Ice')) && ... + strcmp(Test.s2.value, Test.sw2.value) && ... + strcmp(Test.s2.value, literals{3}) && ... + strcmp(Test.s2.value, literals{14})); + + assert(strcmp(Test.s3.value, sprintf('A21')) && ... + strcmp(Test.s3.value, Test.sw3.value) && ... + strcmp(Test.s3.value, literals{4}) && ... + strcmp(Test.s3.value, literals{15})); + + assert(strcmp(Test.s4.value, sprintf('\\u0041 \\U00000041')) && ... + strcmp(Test.s4.value, Test.sw4.value) && ... + strcmp(Test.s4.value, literals{5}) && ... + strcmp(Test.s4.value, literals{16})); + + assert(strcmp(Test.s5.value, sprintf('\x00FF')) && ... + strcmp(Test.s5.value, Test.sw5.value) && ... + strcmp(Test.s5.value, literals{6}) && ... + strcmp(Test.s5.value, literals{17})); + + assert(strcmp(Test.s6.value, sprintf('\x03FF')) && ... + strcmp(Test.s6.value, Test.sw6.value) && ... + strcmp(Test.s6.value, literals{7}) && ... + strcmp(Test.s6.value, literals{18})); + + assert(strcmp(Test.s7.value, sprintf('\x05F0')) && ... + strcmp(Test.s7.value, Test.sw7.value) && ... + strcmp(Test.s7.value, literals{8}) && ... + strcmp(Test.s7.value, literals{19})); + + assert(strcmp(Test.s8.value, sprintf('\xD800\xDC00')) && ... + strcmp(Test.s8.value, Test.sw8.value) && ... + strcmp(Test.s8.value, literals{9}) && ... + strcmp(Test.s8.value, literals{20})); + + assert(strcmp(Test.s9.value, sprintf('\xD83C\xDF4C')) && ... + strcmp(Test.s9.value, Test.sw9.value) && ... + strcmp(Test.s9.value, literals{10}) && ... + strcmp(Test.s9.value, literals{21})); + + assert(strcmp(Test.s10.value, sprintf('\x0DA7')) && ... + strcmp(Test.s10.value, Test.sw10.value) && ... + strcmp(Test.s10.value, literals{11}) && ... + strcmp(Test.s10.value, literals{22})); + + assert(strcmp(Test.s11.value, sprintf('\x20ac\x20ac\x20ac'))); + + assert(strcmp(Test.s12.value, sprintf('\\101'))); + + assert(strcmp(Test.s13.value, sprintf('\xd83c\xdf4c\060\061\062\063'))); + + assert(strcmp(Test.s14.value, sprintf('\xd83c\xdf4c\141bcd'))); + + assert(strcmp(Test.s15.value, sprintf('\xd83c\xdf4c\101BCD'))); + + assert(strcmp(Test.s16.value, sprintf('\177abcd'))); + + assert(strcmp(Test.s17.value, sprintf('\177ABCD'))); + + assert(strcmp(Test.s18.value, sprintf('\001\061\062\0638'))); + + assert(strcmp(Test.s19.value, sprintf('abc\001\061\062\0638\babcd'))); + + assert(strcmp(Test.ss0.value, sprintf('''"\x003f\\\x0007\b\f\n\r\t\x000b\6')) && ... + strcmp(Test.ss0.value, Test.ss1.value) && ... + strcmp(Test.ss0.value, Test.ss2.value) && ... + strcmp(Test.ss0.value, literals{23}) && ... + strcmp(Test.ss0.value, literals{24}) && ... + strcmp(Test.ss0.value, literals{25})); + + assert(strcmp(Test.ss3.value, sprintf('\\\\U\\u\\')) && ... + strcmp(Test.ss3.value, literals{26})); + + assert(strcmp(Test.ss4.value, sprintf('\\A\\')) && ... + strcmp(Test.ss4.value, literals{27})); + + assert(strcmp(Test.ss5.value, sprintf('\\u0041\\')) && ... + strcmp(Test.ss5.value, literals{28})); + + assert(strcmp(Test.su0.value, Test.su1.value) && ... + strcmp(Test.su0.value, Test.su2.value) && ... + strcmp(Test.su0.value, literals{29}) && ... + strcmp(Test.su0.value, literals{30}) && ... + strcmp(Test.su0.value, literals{31})); + + p.ice_ping(); + + assert(p.ice_isA(Test.MyClassPrx.ice_staticId())); + + assert(strcmp(p.ice_id(), Test.MyDerivedClassPrx.ice_staticId())); + + ids = p.ice_ids(); + assert(length(ids) == 3); + assert(strcmp(ids{1}, '::Ice::Object')); + assert(strcmp(ids{2}, '::Test::MyClass')); + assert(strcmp(ids{3}, '::Test::MyDerivedClass')); + + p.opVoid(); + + [r, p3] = p.opByte(hex2dec('ff'), hex2dec('0f')); + assert(p3 == hex2dec('f0')); + assert(r == hex2dec('ff')); + + [r, p3] = p.opBool(true, false); + assert(p3); + assert(~r); + + [r, p4, p5, p6] = p.opShortIntLong(10, 11, 12); + assert(p4 == 10); + assert(p5 == 11); + assert(p6 == 12); + assert(r == 12); + + [r, p4, p5, p6] = p.opShortIntLong(intmin('int16'), intmin('int32'), intmin('int64')); + assert(p4 == intmin('int16')); + assert(p5 == intmin('int32')); + assert(p6 == intmin('int64')); + assert(r == intmin('int64')); + + [r, p4, p5, p6] = p.opShortIntLong(intmax('int16'), intmax('int32'), intmax('int64')); + assert(p4 == intmax('int16')); + assert(p5 == intmax('int32')); + assert(p6 == intmax('int64')); + assert(r == intmax('int64')); + + [r, p3, p4] = p.opFloatDouble(3.14, 1.1E10); + assert(p3 == single(3.14)); + assert(p4 == 1.1E10); + assert(r == 1.1E10); + + [r, p3, p4] = p.opFloatDouble(realmin('single'), realmin('double')); + assert(p3 == realmin('single')); + assert(p4 == realmin('double')); + assert(r == realmin('double')); + + [r, p3, p4] = p.opFloatDouble(realmax('single'), realmax('double')); + assert(p3 == realmax('single')); + assert(p4 == realmax('double')); + assert(r == realmax('double')); + + [r, p3] = p.opString('hello', 'world'); + assert(strcmp(p3, 'world hello')); + assert(strcmp(r, 'hello world')); + + [r, p2] = p.opMyEnum(Test.MyEnum.enum2); + assert(p2 == Test.MyEnum.enum2); + assert(r == Test.MyEnum.enum3); + + % + % Test marshalling of null enum (first enum value is + % marshalled in this case). + % + [r, p2] = p.opMyEnum([]); + assert(p2 == Test.MyEnum.enum1); + assert(r == Test.MyEnum.enum3); + + [r, p2, p3] = p.opMyClass(p); + assert(Ice.proxyIdentityAndFacetCompare(p2, p) == 0); + assert(Ice.proxyIdentityAndFacetCompare(p3, p) ~= 0); + assert(Ice.proxyIdentityAndFacetCompare(r, p) == 0); + assert(isequal(p2.ice_getIdentity(), Ice.stringToIdentity('test'))); + assert(isequal(p3.ice_getIdentity(), Ice.stringToIdentity('noSuchIdentity'))); + assert(isequal(r.ice_getIdentity(), Ice.stringToIdentity('test'))); + r.opVoid(); + p2.opVoid(); + try + p3.opVoid(); + assert(false); + catch ex + assert(isa(ex, 'Ice.ObjectNotExistException')); + end + + [r, p2, p3] = p.opMyClass([]); + assert(isempty(p2)); + assert(~isempty(p3)); + assert(Ice.proxyIdentityAndFacetCompare(r, p) == 0); + r.opVoid(); + + si1 = Test.Structure(); + si1.p = p; + si1.e = Test.MyEnum.enum3; + si1.s = Test.AnotherStruct(); + si1.s.s = 'abc'; + si2 = Test.Structure(); + si2.p = []; + si2.e = Test.MyEnum.enum2; + si2.s = Test.AnotherStruct(); + si2.s.s = 'def'; + + [r, p3] = p.opStruct(si1, si2); + assert(isempty(r.p)); + assert(r.e == Test.MyEnum.enum2); + assert(strcmp(r.s.s, 'def')); + assert(p3.p == p); + assert(p3.e == Test.MyEnum.enum3); + assert(strcmp(p3.s.s, 'a new string')); + p3.p.opVoid(); + + % + % Test marshalling of null structs and structs with default member values. + % + si1 = Test.Structure(); + si2 = []; + + [r, p3] = p.opStruct(si1, si2); + assert(isempty(r.p)); + assert(r.e == Test.MyEnum.enum1); + assert(isempty(r.s.s)); + assert(isempty(p3.p)); + assert(p3.e == Test.MyEnum.enum1); + assert(strcmp(p3.s.s, 'a new string')); + + bsi1 = ... + [ ... + hex2dec('01'), ... + hex2dec('11'), ... + hex2dec('12'), ... + hex2dec('22') ... + ]; + bsi2 = ... + [ + hex2dec('f1'), ... + hex2dec('f2'), ... + hex2dec('f3'), ... + hex2dec('f4') ... + ]; + + [r, p3] = p.opByteS(bsi1, bsi2); + assert(length(p3) == 4); + assert(p3(1) == hex2dec('22')); + assert(p3(2) == hex2dec('12')); + assert(p3(3) == hex2dec('11')); + assert(p3(4) == hex2dec('01')); + assert(length(r) == 8); + assert(r(1) == hex2dec('01')); + assert(r(2) == hex2dec('11')); + assert(r(3) == hex2dec('12')); + assert(r(4) == hex2dec('22')); + assert(r(5) == hex2dec('f1')); + assert(r(6) == hex2dec('f2')); + assert(r(7) == hex2dec('f3')); + assert(r(8) == hex2dec('f4')); + + bsi1 = [true, true, false]; + bsi2 = [false]; + + [r, p3] = p.opBoolS(bsi1, bsi2); + assert(length(p3) == 4); + assert(p3(1)); + assert(p3(2)); + assert(~p3(3)); + assert(~p3(4)); + assert(length(r) == 3); + assert(~r(1)); + assert(r(2)); + assert(r(3)); + + ssi = [1, 2, 3]; + isi = [5, 6, 7, 8]; + lsi = [10, 30, 20]; + + [r, p4, p5, p6] = p.opShortIntLongS(ssi, isi, lsi); + assert(length(p4) == 3); + assert(p4(1) == 1); + assert(p4(2) == 2); + assert(p4(3) == 3); + assert(length(p5) == 4); + assert(p5(1) == 8); + assert(p5(2) == 7); + assert(p5(3) == 6); + assert(p5(4) == 5); + assert(length(p6) == 6); + assert(p6(1) == 10); + assert(p6(2) == 30); + assert(p6(3) == 20); + assert(p6(4) == 10); + assert(p6(5) == 30); + assert(p6(6) == 20); + assert(length(r) == 3); + assert(r(1) == 10); + assert(r(2) == 30); + assert(r(3) == 20); + + fsi = [3.14, 1.11]; + dsi = [1.1E10, 1.2E10, 1.3E10]; + + [r, p3, p4] = p.opFloatDoubleS(fsi, dsi); + assert(length(p3) == 2); + assert(p3(1) == single(3.14)); + assert(p3(2) == single(1.11)); + assert(length(p4) == 3); + assert(p4(1) == 1.3E10); + assert(p4(2) == 1.2E10); + assert(p4(3) == 1.1E10); + assert(length(r) == 5); + assert(r(1) == 1.1E10); + assert(r(2) == 1.2E10); + assert(r(3) == 1.3E10); + assert(r(4) == single(3.14)); + assert(r(5) == single(1.11)); + + ssi1 = {'abc', 'de', 'fghi'}; + ssi2 = {'xyz'}; + + [r, p3] = p.opStringS(ssi1, ssi2); + assert(length(p3) == 4); + assert(strcmp(p3{1}, 'abc')); + assert(strcmp(p3{2}, 'de')); + assert(strcmp(p3{3}, 'fghi')); + assert(strcmp(p3{4}, 'xyz')); + assert(length(r) == 3); + assert(strcmp(r{1}, 'fghi')); + assert(strcmp(r{2}, 'de')); + assert(strcmp(r{3}, 'abc')); + + bsi1 = ... + { ... + [hex2dec('01'), hex2dec('11'), hex2dec('12')], ... + [hex2dec('ff')] ... + }; + bsi2 = ... + { ... + [hex2dec('0e')], ... + [hex2dec('f2'), hex2dec('f1')] ... + }; + + [r, p3] = p.opByteSS(bsi1, bsi2); + assert(length(p3) == 2); + assert(length(p3{1}) == 1); + assert(p3{1}(1) == hex2dec('ff')); + assert(length(p3{2}) == 3); + assert(p3{2}(1) == hex2dec('01')); + assert(p3{2}(2) == hex2dec('11')); + assert(p3{2}(3) == hex2dec('12')); + assert(length(r) == 4); + assert(length(r{1}) == 3); + assert(r{1}(1) == hex2dec('01')); + assert(r{1}(2) == hex2dec('11')); + assert(r{1}(3) == hex2dec('12')); + assert(length(r{2}) == 1); + assert(r{2}(1) == hex2dec('ff')); + assert(length(r{3}) == 1); + assert(r{3}(1) == hex2dec('0e')); + assert(length(r{4}) == 2); + assert(r{4}(1) == hex2dec('f2')); + assert(r{4}(2) == hex2dec('f1')); + + bsi1 = ... + { ... + [true], ... + [false], ... + [true, true] ... + }; + + bsi2 = ... + { ... + [false, false, true] ... + }; + + [r, p3] = p.opBoolSS(bsi1, bsi2); + assert(length(p3) == 4); + assert(length(p3{1}) == 1); + assert(p3{1}(1)); + assert(length(p3{2}) == 1); + assert(~p3{2}(1)); + assert(length(p3{3}) == 2); + assert(p3{3}(1)); + assert(p3{3}(2)); + assert(length(p3{4}) == 3); + assert(~p3{4}(1)); + assert(~p3{4}(2)); + assert(p3{4}(3)); + assert(length(r) == 3); + assert(length(r{1}) == 2); + assert(r{1}(1)); + assert(r{1}(2)); + assert(length(r{2}) == 1); + assert(~r{2}(1)); + assert(length(r{3}) == 1); + assert(r{3}(1)); + + ssi = ... + { ... + [1, 2, 5], ... + [13], ... + [] ... + }; + isi = ... + { ... + [24, 98], ... + [42] ... + }; + lsi = ... + { ... + [496, 1729], ... + }; + + [r, p4, p5, p6] = p.opShortIntLongSS(ssi, isi, lsi); + assert(length(r) == 1); + assert(length(r{1}) == 2); + assert(r{1}(1) == 496); + assert(r{1}(2) == 1729); + assert(length(p4) == 3); + assert(length(p4{1}) == 3); + assert(p4{1}(1) == 1); + assert(p4{1}(2) == 2); + assert(p4{1}(3) == 5); + assert(length(p4{2}) == 1); + assert(p4{2}(1) == 13); + assert(length(p4{3}) == 0); + assert(length(p5) == 2); + assert(length(p5{1}) == 1); + assert(p5{1}(1) == 42); + assert(length(p5{2}) == 2); + assert(p5{2}(1) == 24); + assert(p5{2}(2) == 98); + assert(length(p6) == 2); + assert(length(p6{1}) == 2); + assert(p6{1}(1) == 496); + assert(p6{1}(2) == 1729); + assert(length(p6{2}) == 2); + assert(p6{2}(1) == 496); + assert(p6{2}(2) == 1729); + + fsi = ... + { ... + [3.14], ... + [1.11], ... + [], ... + }; + dsi = ... + { ... + [1.1E10, 1.2E10, 1.3E10] ... + }; + + [r, p3, p4] = p.opFloatDoubleSS(fsi, dsi); + assert(length(p3) == 3); + assert(length(p3{1}) == 1); + assert(p3{1}(1) == single(3.14)); + assert(length(p3{2}) == 1); + assert(p3{2}(1) == single(1.11)); + assert(length(p3{3}) == 0); + assert(length(p4) == 1); + assert(length(p4{1}) == 3); + assert(p4{1}(1) == 1.1E10); + assert(p4{1}(2) == 1.2E10); + assert(p4{1}(3) == 1.3E10); + assert(length(r) == 2); + assert(length(r{1}) == 3); + assert(r{1}(1) == 1.1E10); + assert(r{1}(2) == 1.2E10); + assert(r{1}(3) == 1.3E10); + assert(length(r{2}) == 3); + assert(r{2}(1) == 1.1E10); + assert(r{2}(2) == 1.2E10); + assert(r{2}(3) == 1.3E10); + + ssi1 = ... + { ... + {'abc'}, ... + {'de', 'fghi'} ... + }; + ssi2 = ... + { ... + {}, ... + {}, ... + {'xyz'} ... + }; + + [r, p3] = p.opStringSS(ssi1, ssi2); + assert(length(p3) == 5); + assert(length(p3{1}) == 1); + assert(strcmp(p3{1}(1), 'abc')); + assert(length(p3{2}) == 2); + assert(strcmp(p3{2}(1), 'de')); + assert(strcmp(p3{2}(2), 'fghi')); + assert(length(p3{3}) == 0); + assert(length(p3{4}) == 0); + assert(length(p3{5}) == 1); + assert(strcmp(p3{5}(1), 'xyz')); + assert(length(r) == 3); + assert(length(r{1}) == 1); + assert(strcmp(r{1}(1), 'xyz')); + assert(length(r{2}) == 0); + assert(length(r{3}) == 0); + + sssi1 = ... + { ... + { ... + { ... + 'abc', 'de' ... + }, ... + { ... + 'xyz' ... + } ... + }, ... + { ... + { ... + 'hello' ... + } ... + } ... + }; + + sssi2 = ... + { ... + { ... + { ... + '', '' ... + }, ... + { ... + 'abcd' ... + } ... + }, ... + { ... + { ... + '' ... + } ... + }, ... + { ... + } ... + }; + + [r, p3] = p.opStringSSS(sssi1, sssi2); + assert(length(p3) == 5); + assert(length(p3{1}) == 2); + assert(length(p3{1}{1}) == 2); + assert(length(p3{1}{2}) == 1); + assert(length(p3{2}) == 1); + assert(length(p3{2}{1}) == 1); + assert(length(p3{3}) == 2); + assert(length(p3{3}{1}) == 2); + assert(length(p3{3}{2}) == 1); + assert(length(p3{4}) == 1); + assert(length(p3{4}{1}) == 1); + assert(length(p3{5}) == 0); + assert(strcmp(p3{1}{1}(1), 'abc')); + assert(strcmp(p3{1}{1}(2), 'de')); + assert(strcmp(p3{1}{2}(1), 'xyz')); + assert(strcmp(p3{2}{1}(1), 'hello')); + assert(strcmp(p3{3}{1}(1), '')); + assert(strcmp(p3{3}{1}(2), '')); + assert(strcmp(p3{3}{2}(1), 'abcd')); + assert(strcmp(p3{4}{1}(1), '')); + + assert(length(r) == 3); + assert(length(r{1}) == 0); + assert(length(r{2}) == 1); + assert(length(r{2}{1}) == 1); + assert(length(r{3}) == 2); + assert(length(r{3}{1}) == 2); + assert(length(r{3}{2}) == 1); + assert(strcmp(r{2}{1}(1), '')); + assert(strcmp(r{3}{1}(1), '')); + assert(strcmp(r{3}{1}(2), '')); + assert(strcmp(r{3}{2}(1), 'abcd')); + + di1 = Test.ByteBoolD.new(); + di1(10) = true; + di1(100) = false; + di2 = Test.ByteBoolD.new(); + di2(10) = true; + di2(11) = false; + di2(101) = true; + + [r, p3] = p.opByteBoolD(di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r(10)); + assert(~r(11)); + assert(~r(100)); + assert(r(101)); + + di1 = Test.ShortIntD.new(); + di1(110) = -1; + di1(1100) = 123123; + di2 = Test.ShortIntD.new(); + di2(110) = -1; + di2(111) = -100; + di2(1101) = 0; + + [r, p3] = p.opShortIntD(di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r(110) == -1); + assert(r(111) == -100); + assert(r(1100) == 123123); + assert(r(1101) == 0); + + di1 = Test.LongFloatD.new(); + di1(999999110) = -1.1; + di1(999999111) = 123123.2; + di2 = Test.LongFloatD.new(); + di2(999999110) = -1.1; + di2(999999120) = -100.4; + di2(999999130) = 0.5; + + [r, p3] = p.opLongFloatD(di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r(999999110) == single(-1.1)); + assert(r(999999120) == single(-100.4)); + assert(r(999999111) == single(123123.2)); + assert(r(999999130) == single(0.5)); + + di1 = Test.StringStringD.new(); + di1('foo') = 'abc -1.1'; + di1('bar') = 'abc 123123.2'; + di2 = Test.StringStringD.new(); + di2('foo') = 'abc -1.1'; + di2('FOO') = 'abc -100.4'; + di2('BAR') = 'abc 0.5'; + + [r, p3] = p.opStringStringD(di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(strcmp(r('foo'), 'abc -1.1')); + assert(strcmp(r('FOO'), 'abc -100.4')); + assert(strcmp(r('bar'), 'abc 123123.2')); + assert(strcmp(r('BAR'), 'abc 0.5')); + + di1 = Test.StringMyEnumD.new(); + di1('abc') = Test.MyEnum.enum1; + di1('') = Test.MyEnum.enum2; + di2 = Test.StringMyEnumD.new(); + di2('abc') = Test.MyEnum.enum1; + di2('qwerty') = Test.MyEnum.enum3; + di2('Hello!!') = Test.MyEnum.enum2; + + [r, p3] = p.opStringMyEnumD(di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r('abc') == Test.MyEnum.enum1); + assert(r('qwerty') == Test.MyEnum.enum3); + assert(r('') == Test.MyEnum.enum2); + assert(r('Hello!!') == Test.MyEnum.enum2); + + di1 = Test.MyEnumStringD.new(); + di1(int32(Test.MyEnum.enum1)) = 'abc'; + di2 = Test.MyEnumStringD.new(); + di2(int32(Test.MyEnum.enum2)) = 'Hello!!'; + di2(int32(Test.MyEnum.enum3)) = 'qwerty'; + + [r, p3] = p.opMyEnumStringD(di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 3); + assert(strcmp(r(int32(Test.MyEnum.enum1)), 'abc')); + assert(strcmp(r(int32(Test.MyEnum.enum2)), 'Hello!!')); + assert(strcmp(r(int32(Test.MyEnum.enum3)), 'qwerty')); + + s11 = Test.MyStruct(1, 1); + s12 = Test.MyStruct(1, 2); + di1 = Test.MyStructMyEnumD.new(); + di1(1).key = s11; + di1(1).value = Test.MyEnum.enum1; + di1(2).key = s12; + di1(2).value = Test.MyEnum.enum2; + + s22 = Test.MyStruct(2, 2); + s23 = Test.MyStruct(2, 3); + di2 = Test.MyStructMyEnumD.new(); + di2(1).key = s11; + di2(1).value = Test.MyEnum.enum1; + di2(2).key = s22; + di2(2).value = Test.MyEnum.enum3; + di2(3).key = s23; + di2(3).value = Test.MyEnum.enum2; + + [r, p3] = p.opMyStructMyEnumD(di1, di2); + + assert(isequal(p3, di1)); + assert(length(r) == 4); + for i = 1:length(r) + if isequal(r(i).key, s11) + assert(r(i).value == Test.MyEnum.enum1); + elseif isequal(r(i).key, s12) + assert(r(i).value == Test.MyEnum.enum2); + elseif isequal(r(i).key, s22) + assert(r(i).value == Test.MyEnum.enum3); + elseif isequal(r(i).key, s23) + assert(r(i).value == Test.MyEnum.enum2); + else + assert(false); + end + end + + di1 = Test.ByteBoolD.new(); + di1(10) = true; + di1(100) = false; + di2 = Test.ByteBoolD.new(); + di2(10) = true; + di2(11) = false; + di2(101) = true; + di3 = Test.ByteBoolD.new(); + di3(100) = false; + di3(101) = false; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opByteBoolDS(dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}(10)); + assert(~r{1}(11)); + assert(r{1}(101)); + assert(r{2}.Count == 2); + assert(r{2}(10)); + assert(~r{2}(100)); + + assert(length(p3) == 3); + assert(p3{1}.Count == 2); + assert(~p3{1}(100)); + assert(~p3{1}(101)); + assert(p3{2}.Count == 2); + assert(p3{2}(10)); + assert(~p3{2}(100)); + assert(p3{3}.Count == 3); + assert(p3{3}(10)); + assert(~p3{3}(11)); + assert(p3{3}(101)); + + di1 = Test.ShortIntD.new(); + di1(110) = -1; + di1(1100) = 123123; + di2 = Test.ShortIntD.new(); + di2(110) = -1; + di2(111) = -100; + di2(1101) = 0; + di3 = Test.ShortIntD.new(); + di3(100) = -1001; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opShortIntDS(dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}(110) == -1); + assert(r{1}(111) == -100); + assert(r{1}(1101) == 0); + assert(r{2}.Count == 2); + assert(r{2}(110) == -1); + assert(r{2}(1100) == 123123); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(p3{1}(100) == -1001); + assert(p3{2}.Count == 2); + assert(p3{2}(110) == -1); + assert(p3{2}(1100) == 123123); + assert(p3{3}.Count == 3); + assert(p3{3}(110) == -1); + assert(p3{3}(111) == -100); + assert(p3{3}(1101) == 0); + + di1 = Test.LongFloatD.new(); + di1(999999110) = -1.1; + di1(999999111) = 123123.2; + di2 = Test.LongFloatD.new(); + di2(999999110) = -1.1; + di2(999999120) = -100.4; + di2(999999130) = 0.5; + di3 = Test.LongFloatD.new(); + di3(999999140) = 3.14; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opLongFloatDS(dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}(999999110) == single(-1.1)); + assert(r{1}(999999120) == single(-100.4)); + assert(r{1}(999999130) == single(0.5)); + assert(r{2}.Count == 2); + assert(r{2}(999999110) == single(-1.1)); + assert(r{2}(999999111) == single(123123.2)); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(p3{1}(999999140) == single(3.14)); + assert(p3{2}.Count == 2); + assert(p3{2}(999999110) == single(-1.1)); + assert(p3{2}(999999111) == single(123123.2)); + assert(p3{3}.Count == 3); + assert(p3{3}(999999110) == single(-1.1)); + assert(p3{3}(999999120) == single(-100.4)); + assert(p3{3}(999999130) == single(0.5)); + + di1 = Test.StringStringD.new(); + di1('foo') = 'abc -1.1'; + di1('bar') = 'abc 123123.2'; + di2 = Test.StringStringD.new(); + di2('foo') = 'abc -1.1'; + di2('FOO') = 'abc -100.4'; + di2('BAR') = 'abc 0.5'; + di3 = Test.StringStringD.new(); + di3('f00') = 'ABC -3.14'; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opStringStringDS(dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(strcmp(r{1}('foo'), 'abc -1.1')); + assert(strcmp(r{1}('FOO'), 'abc -100.4')); + assert(strcmp(r{1}('BAR'), 'abc 0.5')); + assert(r{2}.Count == 2); + assert(strcmp(r{2}('foo'), 'abc -1.1')); + assert(strcmp(r{2}('bar'), 'abc 123123.2')); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(strcmp(p3{1}('f00'), 'ABC -3.14')); + assert(p3{2}.Count == 2); + assert(strcmp(p3{2}('foo'), 'abc -1.1')); + assert(strcmp(p3{2}('bar'), 'abc 123123.2')); + assert(p3{3}.Count == 3); + assert(strcmp(p3{3}('foo'), 'abc -1.1')); + assert(strcmp(p3{3}('FOO'), 'abc -100.4')); + assert(strcmp(p3{3}('BAR'), 'abc 0.5')); + + di1 = Test.StringMyEnumD.new(); + di1('abc') = Test.MyEnum.enum1; + di1('') = Test.MyEnum.enum2; + di2 = Test.StringMyEnumD.new(); + di2('abc') = Test.MyEnum.enum1; + di2('qwerty') = Test.MyEnum.enum3; + di2('Hello!!') = Test.MyEnum.enum2; + di3 = Test.StringMyEnumD.new(); + di3('Goodbye') = Test.MyEnum.enum1; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opStringMyEnumDS(dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}('abc') == Test.MyEnum.enum1); + assert(r{1}('qwerty') == Test.MyEnum.enum3); + assert(r{1}('Hello!!') == Test.MyEnum.enum2); + assert(r{2}.Count == 2); + assert(r{2}('abc') == Test.MyEnum.enum1); + assert(r{2}('') == Test.MyEnum.enum2); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(p3{1}('Goodbye') == Test.MyEnum.enum1); + assert(p3{2}.Count == 2); + assert(p3{2}('abc') == Test.MyEnum.enum1); + assert(p3{2}('') == Test.MyEnum.enum2); + assert(p3{3}.Count == 3); + assert(p3{3}('abc') == Test.MyEnum.enum1); + assert(p3{3}('qwerty') == Test.MyEnum.enum3); + assert(p3{3}('Hello!!') == Test.MyEnum.enum2); + + di1 = Test.MyEnumStringD.new(); + di1(int32(Test.MyEnum.enum1)) = 'abc'; + di2 = Test.MyEnumStringD.new(); + di2(int32(Test.MyEnum.enum2)) = 'Hello!!'; + di2(int32(Test.MyEnum.enum3)) = 'qwerty'; + di3 = Test.MyEnumStringD.new(); + di3(int32(Test.MyEnum.enum1)) = 'Goodbye'; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opMyEnumStringDS(dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 2); + assert(strcmp(r{1}(int32(Test.MyEnum.enum2)), 'Hello!!')); + assert(strcmp(r{1}(int32(Test.MyEnum.enum3)), 'qwerty')); + assert(r{2}.Count == 1); + assert(strcmp(r{2}(int32(Test.MyEnum.enum1)), 'abc')); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(strcmp(p3{1}(int32(Test.MyEnum.enum1)), 'Goodbye')); + assert(p3{2}.Count == 1); + assert(strcmp(p3{2}(int32(Test.MyEnum.enum1)), 'abc')); + assert(p3{3}.Count == 2); + assert(strcmp(p3{3}(int32(Test.MyEnum.enum2)), 'Hello!!')); + assert(strcmp(p3{3}(int32(Test.MyEnum.enum3)), 'qwerty')); + + s11 = Test.MyStruct(1, 1); + s12 = Test.MyStruct(1, 2); + di1 = Test.MyStructMyEnumD.new(); + di1(1).key = s11; + di1(1).value = Test.MyEnum.enum1; + di1(2).key = s12; + di1(2).value = Test.MyEnum.enum2; + + s22 = Test.MyStruct(2, 2); + s23 = Test.MyStruct(2, 3); + di2 = Test.MyStructMyEnumD.new(); + di2(1).key = s11; + di2(1).value = Test.MyEnum.enum1; + di2(2).key = s22; + di2(2).value = Test.MyEnum.enum3; + di2(3).key = s23; + di2(3).value = Test.MyEnum.enum2; + + di3 = Test.MyStructMyEnumD.new(); + di3(1).key = s23; + di3(1).value = Test.MyEnum.enum2; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = p.opMyStructMyEnumDS(dsi1, dsi2); + + function checkStructDict(d) + for i = 1:length(d) + if isequal(d(i).key, s11) + assert(d(i).value == Test.MyEnum.enum1); + elseif isequal(d(i).key, s12) + assert(d(i).value == Test.MyEnum.enum2); + elseif isequal(d(i).key, s22) + assert(d(i).value == Test.MyEnum.enum3); + elseif isequal(d(i).key, s23) + assert(d(i).value == Test.MyEnum.enum2); + else + assert(false); + end + end + end + assert(length(r) == 2); + assert(length(r{1}) == 3); + checkStructDict(r{1}); + checkStructDict(r{2}); + + assert(length(p3) == 3); + assert(length(p3{1}) == 1); + checkStructDict(p3{1}); + assert(length(p3{2}) == 2); + checkStructDict(p3{2}); + assert(length(p3{3}) == 3); + checkStructDict(p3{3}); + + sdi1 = Test.ByteByteSD.new(); + sdi2 = Test.ByteByteSD.new(); + + si1 = [hex2dec('01'), hex2dec('11')]; + si2 = [hex2dec('12')]; + si3 = [hex2dec('f2'), hex2dec('f3')]; + + sdi1(hex2dec('01')) = si1; + sdi1(hex2dec('22')) = si2; + sdi2(hex2dec('f1')) = si3; + + [r, p3] = p.opByteByteSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(hex2dec('f1')); % Need to use a temp + assert(length(a) == 2); + assert(a(1) == hex2dec('f2')); + assert(a(2) == hex2dec('f3')); + assert(r.Count == 3); + a = r(hex2dec('01')); % Need to use a temp + assert(length(a) == 2); + assert(a(1) == hex2dec('01')); + assert(a(2) == hex2dec('11')); + a = r(hex2dec('22')); % Need to use a temp + assert(length(a) == 1); + assert(a(1) == hex2dec('12')); + a = r(hex2dec('f1')); % Need to use a temp + assert(length(a) == 2); + assert(a(1) == hex2dec('f2')); + assert(a(2) == hex2dec('f3')); + + sdi1 = Test.BoolBoolSD.new(); + sdi2 = Test.BoolBoolSD.new(); + + si1 = [true, false]; + si2 = [false, true, true]; + + sdi1(false) = si1; + sdi1(true) = si2; + sdi2(false) = si1; + + [r, p3] = p.opBoolBoolSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(false); % Need to use temp + assert(length(a) == 2); + assert(a(1)); + assert(~a(2)); + assert(r.Count == 2); + a = r(false); % Need to use temp + assert(length(a) == 2); + assert(a(1)); + assert(~a(2)); + a = r(true); % Need to use temp + assert(length(a) == 3); + assert(~a(1)); + assert(a(2)); + assert(a(3)); + + sdi1 = Test.ShortShortSD.new(); + sdi2 = Test.ShortShortSD.new(); + + si1 = [1, 2, 3]; + si2 = [4, 5]; + si3 = [6, 7]; + + sdi1(1) = si1; + sdi1(2) = si2; + sdi2(4) = si3; + + [r, p3] = p.opShortShortSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(4); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 6); + assert(a(2) == 7); + assert(r.Count == 3); + a = r(1); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 1); + assert(a(2) == 2); + assert(a(3) == 3); + a = r(2); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 4); + assert(a(2) == 5); + a = r(4); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 6); + assert(a(2) == 7); + + sdi1 = Test.IntIntSD.new(); + sdi2 = Test.IntIntSD.new(); + + si1 = [100, 200, 300]; + si2 = [400, 500]; + si3 = [600, 700]; + + sdi1(100) = si1; + sdi1(200) = si2; + sdi2(400) = si3; + + [r, p3] = p.opIntIntSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(400); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 600); + assert(a(2) == 700); + assert(r.Count == 3); + a = r(100); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 100); + assert(a(2) == 200); + assert(a(3) == 300); + a = r(200); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 400); + assert(a(2) == 500); + a = r(400); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 600); + assert(a(2) == 700); + + sdi1 = Test.LongLongSD.new(); + sdi2 = Test.LongLongSD.new(); + + si1 = [999999110, 999999111, 999999110]; + si2 = [999999120, 999999130]; + si3 = [999999110, 999999120]; + + sdi1(999999990) = si1; + sdi1(999999991) = si2; + sdi2(999999992) = si3; + + [r, p3] = p.opLongLongSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(999999992); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 999999110); + assert(a(2) == 999999120); + assert(r.Count == 3); + a = r(999999990); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 999999110); + assert(a(2) == 999999111); + assert(a(3) == 999999110); + a = r(999999991); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 999999120); + assert(a(2) == 999999130); + a = r(999999992); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 999999110); + assert(a(2) == 999999120); + + sdi1 = Test.StringFloatSD.new(); + sdi2 = Test.StringFloatSD.new(); + + si1 = [-1.1, 123123.2, 100.0]; + si2 = [42.24, -1.61]; + si3 = [-3.14, 3.14]; + + sdi1('abc') = si1; + sdi1('ABC') = si2; + sdi2('aBc') = si3; + + [r, p3] = p.opStringFloatSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3('aBc'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == single(-3.14)); + assert(a(2) == single(3.14)); + assert(r.Count == 3); + a = r('abc'); % Need to use temp + assert(length(a) == 3); + assert(a(1) == single(-1.1)); + assert(a(2) == single(123123.2)); + assert(a(3) == single(100.0)); + a = r('ABC'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == single(42.24)); + assert(a(2) == single(-1.61)); + a = r('aBc'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == single(-3.14)); + assert(a(2) == single(3.14)); + + sdi1 = Test.StringDoubleSD.new(); + sdi2 = Test.StringDoubleSD.new(); + + si1 = [ 1.1E10, 1.2E10, 1.3E10 ]; + si2 = [ 1.4E10, 1.5E10 ]; + si3 = [ 1.6E10, 1.7E10 ]; + + sdi1('Hello!!') = si1; + sdi1('Goodbye') = si2; + sdi2('') = si3; + + [r, p3] = p.opStringDoubleSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(''); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 1.6E10); + assert(a(2) == 1.7E10); + assert(r.Count== 3); + a = r('Hello!!'); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 1.1E10); + assert(a(2) == 1.2E10); + assert(a(3) == 1.3E10); + a = r('Goodbye'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 1.4E10); + assert(a(2) == 1.5E10); + a = r(''); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 1.6E10); + assert(a(2) == 1.7E10); + + sdi1 = Test.StringStringSD.new(); + sdi2 = Test.StringStringSD.new(); + + si1 = { 'abc', 'de', 'fghi' }; + si2 = { 'xyz', 'or' }; + si3 = { 'and', 'xor' }; + + sdi1('abc') = si1; + sdi1('def') = si2; + sdi2('ghi') = si3; + + [r, p3] = p.opStringStringSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3('ghi'); % Need to use temp + assert(length(a) == 2); + assert(strcmp(a(1), 'and')); + assert(strcmp(a(2), 'xor')); + assert(r.Count== 3); + a = r('abc'); % Need to use temp + assert(length(a) == 3); + assert(strcmp(a(1), 'abc')); + assert(strcmp(a(2), 'de')); + assert(strcmp(a(3), 'fghi')); + a = r('def'); % Need to use temp + assert(length(a) == 2); + assert(strcmp(a(1), 'xyz')); + assert(strcmp(a(2), 'or')); + a = r('ghi'); % Need to use temp + assert(length(a) == 2); + assert(strcmp(a(1), 'and')); + assert(strcmp(a(2), 'xor')); + + sdi1 = Test.MyEnumMyEnumSD.new(); + sdi2 = Test.MyEnumMyEnumSD.new(); + + si1 = { Test.MyEnum.enum1, Test.MyEnum.enum1, Test.MyEnum.enum2 }; + si2 = { Test.MyEnum.enum1, Test.MyEnum.enum2 }; + si3 = { Test.MyEnum.enum3, Test.MyEnum.enum3 }; + + sdi1(int32(Test.MyEnum.enum3)) = si1; + sdi1(int32(Test.MyEnum.enum2)) = si2; + sdi2(int32(Test.MyEnum.enum1)) = si3; + + [r, p3] = p.opMyEnumMyEnumSD(sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(int32(Test.MyEnum.enum1)); % Need to use temp + assert(length(a) == 2); + assert(a{1} == Test.MyEnum.enum3); + assert(a{2} == Test.MyEnum.enum3); + assert(r.Count== 3); + a = r(int32(Test.MyEnum.enum3)); % Need to use temp + assert(length(a) == 3); + assert(a{1} == Test.MyEnum.enum1); + assert(a{2} == Test.MyEnum.enum1); + assert(a{3} == Test.MyEnum.enum2); + a = r(int32(Test.MyEnum.enum2)); % Need to use temp + assert(length(a) == 2); + assert(a{1} == Test.MyEnum.enum1); + assert(a{2} == Test.MyEnum.enum2); + a = r(int32(Test.MyEnum.enum1)); % Need to use temp + assert(length(a) == 2); + assert(a{1} == Test.MyEnum.enum3); + assert(a{2} == Test.MyEnum.enum3); + + lengths = [0, 1, 2, 126, 127, 128, 129, 253, 254, 255, 256, 257, 1000]; + + for l = lengths + s = zeros(1, l); + if l > 0 + s(1:l) = (1:l); + end + r = p.opIntS(s); + assert(length(r) == l); + for j = 1:l + assert(r(j) == -j); + end + end + + ctx = Ice.Context.new(); + ctx('one') = 'ONE'; + ctx('two') = 'TWO'; + ctx('three') = 'THREE'; + + assert(p.ice_getContext().Count == 0); + r = p.opContext(); + assert(~isequal(r, ctx)); + + r = p.opContext(ctx); + assert(p.ice_getContext().Count == 0); + assert(isequal(r, ctx)); + + p2 = Test.MyClassPrx.checkedCast(p.ice_context(ctx)); + assert(isequal(p2.ice_getContext(), ctx)); + r = p2.opContext(); + assert(isequal(r, ctx)); + r = p2.opContext(ctx); + assert(isequal(r, ctx)); + + % + % Test implicit context propagation + % +%{ + impls = {'Shared', 'PerThread'}; + for i = 1:2 + initData = app.createInitializationData(); + initData.properties_ = communicator.getProperties().clone(); + initData.properties_.setProperty('Ice.ImplicitContext', impls{i}); + + ic = app.initialize(initData); + + ctx = Ice.Context.new(); + ctx('one') = 'ONE'; + ctx('two') = 'TWO'; + ctx('three') = 'THREE'; + + p3 = Test.MyClassPrx.uncheckedCast(ic.stringToProxy(['test:', app.getTestEndpoint(0)])); + + ic.getImplicitContext().setContext(ctx); + assert(isequal(ic.getImplicitContext().getContext(), ctx)); + assert(isequal(p3.opContext(), ctx)); + + assert(!ic.getImplicitContext().containsKey('zero')); + r = ic.getImplicitContext().put('zero', 'ZERO'); + assert(strcmp(r, '')); + assert(ic.getImplicitContext().containsKey('zero')); + assert(strcmp(ic.getImplicitContext().get('zero'), 'ZERO')); + + ctx = ic.getImplicitContext().getContext(); + assert(isequal(p3.opContext(), ctx)); + + prxContext = Ice.Context.new(); + prxContext('one') = 'UN'; + prxContext('four') = 'QUATRE'; + + combined = Ice.Context.new(ctx); + keys = prxContext.keys(); + for j = 1:prxContext.Count + combined(keys{j}) = prxContext(keys{j}); + end + assert(strcmp(combined('one'), 'UN')); + + p3 = p3.ice_context(prxContext); + + ic.getImplicitContext().setContext([]); + assert(isequal(p3.opContext(), prxContext)); + + ic.getImplicitContext().setContext(ctx); + assert(isequal(p3.opContext(), combined)); + + assert(strcmp(ic.getImplicitContext().remove('one'), 'ONE')); + + ic.destroy(); + end +%} + + d = 1278312346.0 / 13.0; + ds = zeros(1, 5); + for i = 1:5 + ds(i) = d; + end + p.opDoubleMarshaling(d, ds); + + p.opIdempotent(); + + p.opNonmutating(); + + assert(p.opByte1(hex2dec('FF')) == hex2dec('FF')); + assert(p.opShort1(hex2dec('7FFF')) == hex2dec('7FFF')); + assert(p.opInt1(hex2dec('7FFFFFFF')) == hex2dec('7FFFFFFF')); + %assert(p.opLong1(0x7FFFFFFFFFFFFFFF) == 0x7FFFFFFFFFFFFFFF); + assert(p.opFloat1(1.0) == single(1.0)); + assert(p.opDouble1(1.0) == 1.0); + assert(strcmp(p.opString1('opString1'), 'opString1')); + assert(length(p.opStringS1({})) == 0); + assert(p.opByteBoolD1([]).Count == 0); + assert(length(p.opStringS2([])) == 0); + assert(p.opByteBoolD2([]).Count == 0); + + d = Test.MyDerivedClassPrx.uncheckedCast(p); + s = Test.MyStruct1(); + s.tesT = 'Test.MyStruct1.s'; + s.myClass = []; + s.myStruct1 = 'Test.MyStruct1.myStruct1'; + s = d.opMyStruct1(s); + assert(strcmp(s.tesT, 'Test.MyStruct1.s')); + assert(isempty(s.myClass)); + assert(strcmp(s.myStruct1, 'Test.MyStruct1.myStruct1')); + + %{ + c = new MyClass1(); + c.tesT = 'Test.MyClass1.testT'; + c.myClass = null; + c.myClass1 = 'Test.MyClass1.myClass1'; + c = d.opMyClass1(c); + assert(c.tesT.equals('Test.MyClass1.testT')); + assert(c.myClass == null); + assert(c.myClass1.equals('Test.MyClass1.myClass1')); + %} + end + end +end diff --git a/matlab/test/Ice/operations/TwowaysAMI.m b/matlab/test/Ice/operations/TwowaysAMI.m new file mode 100644 index 00000000000..9a84165b699 --- /dev/null +++ b/matlab/test/Ice/operations/TwowaysAMI.m @@ -0,0 +1,1266 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef TwowaysAMI + methods(Static) + function twowaysAMI(app, p) + communicator = app.communicator(); + + call(p, 'ice_ping'); + + b = call(p, 'ice_isA', Test.MyClassPrx.ice_staticId()); + assert(b); + + id = call(p, 'ice_id'); + assert(strcmp(id, Test.MyDerivedClassPrx.ice_staticId())); + + ids = call(p, 'ice_ids'); + assert(length(ids) == 3); + + call(p, 'opVoid'); + + [r, p3] = call(p, 'opByte', hex2dec('ff'), hex2dec('0f')); + assert(p3 == hex2dec('f0')); + assert(r == hex2dec('ff')); + + [r, p3] = call(p, 'opBool', true, false); + assert(p3); + assert(~r); + + [r, p4, p5, p6] = call(p, 'opShortIntLong', 10, 11, 12); + assert(p4 == 10); + assert(p5 == 11); + assert(p6 == 12); + assert(r == 12); + + [r, p3, p4] = call(p, 'opFloatDouble', 3.14, 1.1E10); + assert(p3 == single(3.14)); + assert(p4 == 1.1E10); + assert(r == 1.1E10); + + [r, p3] = call(p, 'opString', 'hello', 'world'); + assert(strcmp(p3, 'world hello')); + assert(strcmp(r, 'hello world')); + + [r, p2] = call(p, 'opMyEnum', Test.MyEnum.enum2); + assert(p2 == Test.MyEnum.enum2); + assert(r == Test.MyEnum.enum3); + + [r, p2, p3] = call(p, 'opMyClass', p); + assert(isequal(p2.ice_getIdentity(), Ice.stringToIdentity('test'))); + assert(isequal(p3.ice_getIdentity(), Ice.stringToIdentity('noSuchIdentity'))); + assert(isequal(r.ice_getIdentity(), Ice.stringToIdentity('test'))); + + si1 = Test.Structure(); + si1.p = p; + si1.e = Test.MyEnum.enum3; + si1.s = Test.AnotherStruct(); + si1.s.s = 'abc'; + si2 = Test.Structure(); + si2.p = []; + si2.e = Test.MyEnum.enum2; + si2.s = Test.AnotherStruct(); + si2.s.s = 'def'; + + [r, p3] = call(p, 'opStruct', si1, si2); + assert(isempty(r.p)); + assert(r.e == Test.MyEnum.enum2); + assert(strcmp(r.s.s, 'def')); + assert(p3.p == p); + assert(p3.e == Test.MyEnum.enum3); + assert(strcmp(p3.s.s, 'a new string')); + p3.p.opVoid(); + + bsi1 = ... + [ ... + hex2dec('01'), ... + hex2dec('11'), ... + hex2dec('12'), ... + hex2dec('22') ... + ]; + bsi2 = ... + [ + hex2dec('f1'), ... + hex2dec('f2'), ... + hex2dec('f3'), ... + hex2dec('f4') ... + ]; + + [r, p3] = call(p, 'opByteS', bsi1, bsi2); + assert(length(p3) == 4); + assert(p3(1) == hex2dec('22')); + assert(p3(2) == hex2dec('12')); + assert(p3(3) == hex2dec('11')); + assert(p3(4) == hex2dec('01')); + assert(length(r) == 8); + assert(r(1) == hex2dec('01')); + assert(r(2) == hex2dec('11')); + assert(r(3) == hex2dec('12')); + assert(r(4) == hex2dec('22')); + assert(r(5) == hex2dec('f1')); + assert(r(6) == hex2dec('f2')); + assert(r(7) == hex2dec('f3')); + assert(r(8) == hex2dec('f4')); + + bsi1 = [true, true, false]; + bsi2 = [false]; + + [r, p3] = call(p, 'opBoolS', bsi1, bsi2); + assert(length(p3) == 4); + assert(p3(1)); + assert(p3(2)); + assert(~p3(3)); + assert(~p3(4)); + assert(length(r) == 3); + assert(~r(1)); + assert(r(2)); + assert(r(3)); + + ssi = [1, 2, 3]; + isi = [5, 6, 7, 8]; + lsi = [10, 30, 20]; + + [r, p4, p5, p6] = call(p, 'opShortIntLongS', ssi, isi, lsi); + assert(length(p4) == 3); + assert(p4(1) == 1); + assert(p4(2) == 2); + assert(p4(3) == 3); + assert(length(p5) == 4); + assert(p5(1) == 8); + assert(p5(2) == 7); + assert(p5(3) == 6); + assert(p5(4) == 5); + assert(length(p6) == 6); + assert(p6(1) == 10); + assert(p6(2) == 30); + assert(p6(3) == 20); + assert(p6(4) == 10); + assert(p6(5) == 30); + assert(p6(6) == 20); + assert(length(r) == 3); + assert(r(1) == 10); + assert(r(2) == 30); + assert(r(3) == 20); + + fsi = [3.14, 1.11]; + dsi = [1.1E10, 1.2E10, 1.3E10]; + + [r, p3, p4] = call(p, 'opFloatDoubleS', fsi, dsi); + assert(length(p3) == 2); + assert(p3(1) == single(3.14)); + assert(p3(2) == single(1.11)); + assert(length(p4) == 3); + assert(p4(1) == 1.3E10); + assert(p4(2) == 1.2E10); + assert(p4(3) == 1.1E10); + assert(length(r) == 5); + assert(r(1) == 1.1E10); + assert(r(2) == 1.2E10); + assert(r(3) == 1.3E10); + assert(r(4) == single(3.14)); + assert(r(5) == single(1.11)); + + ssi1 = {'abc', 'de', 'fghi'}; + ssi2 = {'xyz'}; + + [r, p3] = call(p, 'opStringS', ssi1, ssi2); + assert(length(p3) == 4); + assert(strcmp(p3{1}, 'abc')); + assert(strcmp(p3{2}, 'de')); + assert(strcmp(p3{3}, 'fghi')); + assert(strcmp(p3{4}, 'xyz')); + assert(length(r) == 3); + assert(strcmp(r{1}, 'fghi')); + assert(strcmp(r{2}, 'de')); + assert(strcmp(r{3}, 'abc')); + + bsi1 = ... + { ... + [hex2dec('01'), hex2dec('11'), hex2dec('12')], ... + [hex2dec('ff')] ... + }; + bsi2 = ... + { ... + [hex2dec('0e')], ... + [hex2dec('f2'), hex2dec('f1')] ... + }; + + [r, p3] = call(p, 'opByteSS', bsi1, bsi2); + assert(length(p3) == 2); + assert(length(p3{1}) == 1); + assert(p3{1}(1) == hex2dec('ff')); + assert(length(p3{2}) == 3); + assert(p3{2}(1) == hex2dec('01')); + assert(p3{2}(2) == hex2dec('11')); + assert(p3{2}(3) == hex2dec('12')); + assert(length(r) == 4); + assert(length(r{1}) == 3); + assert(r{1}(1) == hex2dec('01')); + assert(r{1}(2) == hex2dec('11')); + assert(r{1}(3) == hex2dec('12')); + assert(length(r{2}) == 1); + assert(r{2}(1) == hex2dec('ff')); + assert(length(r{3}) == 1); + assert(r{3}(1) == hex2dec('0e')); + assert(length(r{4}) == 2); + assert(r{4}(1) == hex2dec('f2')); + assert(r{4}(2) == hex2dec('f1')); + + bsi1 = ... + { ... + [true], ... + [false], ... + [true, true] ... + }; + + bsi2 = ... + { ... + [false, false, true] ... + }; + + [r, p3] = call(p, 'opBoolSS', bsi1, bsi2); + assert(length(p3) == 4); + assert(length(p3{1}) == 1); + assert(p3{1}(1)); + assert(length(p3{2}) == 1); + assert(~p3{2}(1)); + assert(length(p3{3}) == 2); + assert(p3{3}(1)); + assert(p3{3}(2)); + assert(length(p3{4}) == 3); + assert(~p3{4}(1)); + assert(~p3{4}(2)); + assert(p3{4}(3)); + assert(length(r) == 3); + assert(length(r{1}) == 2); + assert(r{1}(1)); + assert(r{1}(2)); + assert(length(r{2}) == 1); + assert(~r{2}(1)); + assert(length(r{3}) == 1); + assert(r{3}(1)); + + ssi = ... + { ... + [1, 2, 5], ... + [13], ... + [] ... + }; + isi = ... + { ... + [24, 98], ... + [42] ... + }; + lsi = ... + { ... + [496, 1729], ... + }; + + [r, p4, p5, p6] = call(p, 'opShortIntLongSS', ssi, isi, lsi); + assert(length(r) == 1); + assert(length(r{1}) == 2); + assert(r{1}(1) == 496); + assert(r{1}(2) == 1729); + assert(length(p4) == 3); + assert(length(p4{1}) == 3); + assert(p4{1}(1) == 1); + assert(p4{1}(2) == 2); + assert(p4{1}(3) == 5); + assert(length(p4{2}) == 1); + assert(p4{2}(1) == 13); + assert(length(p4{3}) == 0); + assert(length(p5) == 2); + assert(length(p5{1}) == 1); + assert(p5{1}(1) == 42); + assert(length(p5{2}) == 2); + assert(p5{2}(1) == 24); + assert(p5{2}(2) == 98); + assert(length(p6) == 2); + assert(length(p6{1}) == 2); + assert(p6{1}(1) == 496); + assert(p6{1}(2) == 1729); + assert(length(p6{2}) == 2); + assert(p6{2}(1) == 496); + assert(p6{2}(2) == 1729); + + fsi = ... + { ... + [3.14], ... + [1.11], ... + [], ... + }; + dsi = ... + { ... + [1.1E10, 1.2E10, 1.3E10] ... + }; + + [r, p3, p4] = call(p, 'opFloatDoubleSS', fsi, dsi); + assert(length(p3) == 3); + assert(length(p3{1}) == 1); + assert(p3{1}(1) == single(3.14)); + assert(length(p3{2}) == 1); + assert(p3{2}(1) == single(1.11)); + assert(length(p3{3}) == 0); + assert(length(p4) == 1); + assert(length(p4{1}) == 3); + assert(p4{1}(1) == 1.1E10); + assert(p4{1}(2) == 1.2E10); + assert(p4{1}(3) == 1.3E10); + assert(length(r) == 2); + assert(length(r{1}) == 3); + assert(r{1}(1) == 1.1E10); + assert(r{1}(2) == 1.2E10); + assert(r{1}(3) == 1.3E10); + assert(length(r{2}) == 3); + assert(r{2}(1) == 1.1E10); + assert(r{2}(2) == 1.2E10); + assert(r{2}(3) == 1.3E10); + + ssi1 = ... + { ... + {'abc'}, ... + {'de', 'fghi'} ... + }; + ssi2 = ... + { ... + {}, ... + {}, ... + {'xyz'} ... + }; + + [r, p3] = call(p, 'opStringSS', ssi1, ssi2); + assert(length(p3) == 5); + assert(length(p3{1}) == 1); + assert(strcmp(p3{1}(1), 'abc')); + assert(length(p3{2}) == 2); + assert(strcmp(p3{2}(1), 'de')); + assert(strcmp(p3{2}(2), 'fghi')); + assert(length(p3{3}) == 0); + assert(length(p3{4}) == 0); + assert(length(p3{5}) == 1); + assert(strcmp(p3{5}(1), 'xyz')); + assert(length(r) == 3); + assert(length(r{1}) == 1); + assert(strcmp(r{1}(1), 'xyz')); + assert(length(r{2}) == 0); + assert(length(r{3}) == 0); + + sssi1 = ... + { ... + { ... + { ... + 'abc', 'de' ... + }, ... + { ... + 'xyz' ... + } ... + }, ... + { ... + { ... + 'hello' ... + } ... + } ... + }; + + sssi2 = ... + { ... + { ... + { ... + '', '' ... + }, ... + { ... + 'abcd' ... + } ... + }, ... + { ... + { ... + '' ... + } ... + }, ... + { ... + } ... + }; + + [r, p3] = call(p, 'opStringSSS', sssi1, sssi2); + assert(length(p3) == 5); + assert(length(p3{1}) == 2); + assert(length(p3{1}{1}) == 2); + assert(length(p3{1}{2}) == 1); + assert(length(p3{2}) == 1); + assert(length(p3{2}{1}) == 1); + assert(length(p3{3}) == 2); + assert(length(p3{3}{1}) == 2); + assert(length(p3{3}{2}) == 1); + assert(length(p3{4}) == 1); + assert(length(p3{4}{1}) == 1); + assert(length(p3{5}) == 0); + assert(strcmp(p3{1}{1}(1), 'abc')); + assert(strcmp(p3{1}{1}(2), 'de')); + assert(strcmp(p3{1}{2}(1), 'xyz')); + assert(strcmp(p3{2}{1}(1), 'hello')); + assert(strcmp(p3{3}{1}(1), '')); + assert(strcmp(p3{3}{1}(2), '')); + assert(strcmp(p3{3}{2}(1), 'abcd')); + assert(strcmp(p3{4}{1}(1), '')); + + assert(length(r) == 3); + assert(length(r{1}) == 0); + assert(length(r{2}) == 1); + assert(length(r{2}{1}) == 1); + assert(length(r{3}) == 2); + assert(length(r{3}{1}) == 2); + assert(length(r{3}{2}) == 1); + assert(strcmp(r{2}{1}(1), '')); + assert(strcmp(r{3}{1}(1), '')); + assert(strcmp(r{3}{1}(2), '')); + assert(strcmp(r{3}{2}(1), 'abcd')); + + di1 = Test.ByteBoolD.new(); + di1(10) = true; + di1(100) = false; + di2 = Test.ByteBoolD.new(); + di2(10) = true; + di2(11) = false; + di2(101) = true; + + [r, p3] = call(p, 'opByteBoolD', di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r(10)); + assert(~r(11)); + assert(~r(100)); + assert(r(101)); + + di1 = Test.ShortIntD.new(); + di1(110) = -1; + di1(1100) = 123123; + di2 = Test.ShortIntD.new(); + di2(110) = -1; + di2(111) = -100; + di2(1101) = 0; + + [r, p3] = call(p, 'opShortIntD', di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r(110) == -1); + assert(r(111) == -100); + assert(r(1100) == 123123); + assert(r(1101) == 0); + + di1 = Test.LongFloatD.new(); + di1(999999110) = -1.1; + di1(999999111) = 123123.2; + di2 = Test.LongFloatD.new(); + di2(999999110) = -1.1; + di2(999999120) = -100.4; + di2(999999130) = 0.5; + + [r, p3] = call(p, 'opLongFloatD', di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r(999999110) == single(-1.1)); + assert(r(999999120) == single(-100.4)); + assert(r(999999111) == single(123123.2)); + assert(r(999999130) == single(0.5)); + + di1 = Test.StringStringD.new(); + di1('foo') = 'abc -1.1'; + di1('bar') = 'abc 123123.2'; + di2 = Test.StringStringD.new(); + di2('foo') = 'abc -1.1'; + di2('FOO') = 'abc -100.4'; + di2('BAR') = 'abc 0.5'; + + [r, p3] = call(p, 'opStringStringD', di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(strcmp(r('foo'), 'abc -1.1')); + assert(strcmp(r('FOO'), 'abc -100.4')); + assert(strcmp(r('bar'), 'abc 123123.2')); + assert(strcmp(r('BAR'), 'abc 0.5')); + + di1 = Test.StringMyEnumD.new(); + di1('abc') = Test.MyEnum.enum1; + di1('') = Test.MyEnum.enum2; + di2 = Test.StringMyEnumD.new(); + di2('abc') = Test.MyEnum.enum1; + di2('qwerty') = Test.MyEnum.enum3; + di2('Hello!!') = Test.MyEnum.enum2; + + [r, p3] = call(p, 'opStringMyEnumD', di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 4); + assert(r('abc') == Test.MyEnum.enum1); + assert(r('qwerty') == Test.MyEnum.enum3); + assert(r('') == Test.MyEnum.enum2); + assert(r('Hello!!') == Test.MyEnum.enum2); + + di1 = Test.MyEnumStringD.new(); + di1(int32(Test.MyEnum.enum1)) = 'abc'; + di2 = Test.MyEnumStringD.new(); + di2(int32(Test.MyEnum.enum2)) = 'Hello!!'; + di2(int32(Test.MyEnum.enum3)) = 'qwerty'; + + [r, p3] = call(p, 'opMyEnumStringD', di1, di2); + + assert(isequal(p3, di1)); + assert(r.Count == 3); + assert(strcmp(r(int32(Test.MyEnum.enum1)), 'abc')); + assert(strcmp(r(int32(Test.MyEnum.enum2)), 'Hello!!')); + assert(strcmp(r(int32(Test.MyEnum.enum3)), 'qwerty')); + + s11 = Test.MyStruct(1, 1); + s12 = Test.MyStruct(1, 2); + di1 = Test.MyStructMyEnumD.new(); + di1(1).key = s11; + di1(1).value = Test.MyEnum.enum1; + di1(2).key = s12; + di1(2).value = Test.MyEnum.enum2; + + s22 = Test.MyStruct(2, 2); + s23 = Test.MyStruct(2, 3); + di2 = Test.MyStructMyEnumD.new(); + di2(1).key = s11; + di2(1).value = Test.MyEnum.enum1; + di2(2).key = s22; + di2(2).value = Test.MyEnum.enum3; + di2(3).key = s23; + di2(3).value = Test.MyEnum.enum2; + + [r, p3] = call(p, 'opMyStructMyEnumD', di1, di2); + + assert(isequal(p3, di1)); + assert(length(r) == 4); + for i = 1:length(r) + if isequal(r(i).key, s11) + assert(r(i).value == Test.MyEnum.enum1); + elseif isequal(r(i).key, s12) + assert(r(i).value == Test.MyEnum.enum2); + elseif isequal(r(i).key, s22) + assert(r(i).value == Test.MyEnum.enum3); + elseif isequal(r(i).key, s23) + assert(r(i).value == Test.MyEnum.enum2); + else + assert(false); + end + end + + di1 = Test.ByteBoolD.new(); + di1(10) = true; + di1(100) = false; + di2 = Test.ByteBoolD.new(); + di2(10) = true; + di2(11) = false; + di2(101) = true; + di3 = Test.ByteBoolD.new(); + di3(100) = false; + di3(101) = false; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opByteBoolDS', dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}(10)); + assert(~r{1}(11)); + assert(r{1}(101)); + assert(r{2}.Count == 2); + assert(r{2}(10)); + assert(~r{2}(100)); + + assert(length(p3) == 3); + assert(p3{1}.Count == 2); + assert(~p3{1}(100)); + assert(~p3{1}(101)); + assert(p3{2}.Count == 2); + assert(p3{2}(10)); + assert(~p3{2}(100)); + assert(p3{3}.Count == 3); + assert(p3{3}(10)); + assert(~p3{3}(11)); + assert(p3{3}(101)); + + di1 = Test.ShortIntD.new(); + di1(110) = -1; + di1(1100) = 123123; + di2 = Test.ShortIntD.new(); + di2(110) = -1; + di2(111) = -100; + di2(1101) = 0; + di3 = Test.ShortIntD.new(); + di3(100) = -1001; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opShortIntDS', dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}(110) == -1); + assert(r{1}(111) == -100); + assert(r{1}(1101) == 0); + assert(r{2}.Count == 2); + assert(r{2}(110) == -1); + assert(r{2}(1100) == 123123); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(p3{1}(100) == -1001); + assert(p3{2}.Count == 2); + assert(p3{2}(110) == -1); + assert(p3{2}(1100) == 123123); + assert(p3{3}.Count == 3); + assert(p3{3}(110) == -1); + assert(p3{3}(111) == -100); + assert(p3{3}(1101) == 0); + + di1 = Test.LongFloatD.new(); + di1(999999110) = -1.1; + di1(999999111) = 123123.2; + di2 = Test.LongFloatD.new(); + di2(999999110) = -1.1; + di2(999999120) = -100.4; + di2(999999130) = 0.5; + di3 = Test.LongFloatD.new(); + di3(999999140) = 3.14; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opLongFloatDS', dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}(999999110) == single(-1.1)); + assert(r{1}(999999120) == single(-100.4)); + assert(r{1}(999999130) == single(0.5)); + assert(r{2}.Count == 2); + assert(r{2}(999999110) == single(-1.1)); + assert(r{2}(999999111) == single(123123.2)); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(p3{1}(999999140) == single(3.14)); + assert(p3{2}.Count == 2); + assert(p3{2}(999999110) == single(-1.1)); + assert(p3{2}(999999111) == single(123123.2)); + assert(p3{3}.Count == 3); + assert(p3{3}(999999110) == single(-1.1)); + assert(p3{3}(999999120) == single(-100.4)); + assert(p3{3}(999999130) == single(0.5)); + + di1 = Test.StringStringD.new(); + di1('foo') = 'abc -1.1'; + di1('bar') = 'abc 123123.2'; + di2 = Test.StringStringD.new(); + di2('foo') = 'abc -1.1'; + di2('FOO') = 'abc -100.4'; + di2('BAR') = 'abc 0.5'; + di3 = Test.StringStringD.new(); + di3('f00') = 'ABC -3.14'; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opStringStringDS', dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(strcmp(r{1}('foo'), 'abc -1.1')); + assert(strcmp(r{1}('FOO'), 'abc -100.4')); + assert(strcmp(r{1}('BAR'), 'abc 0.5')); + assert(r{2}.Count == 2); + assert(strcmp(r{2}('foo'), 'abc -1.1')); + assert(strcmp(r{2}('bar'), 'abc 123123.2')); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(strcmp(p3{1}('f00'), 'ABC -3.14')); + assert(p3{2}.Count == 2); + assert(strcmp(p3{2}('foo'), 'abc -1.1')); + assert(strcmp(p3{2}('bar'), 'abc 123123.2')); + assert(p3{3}.Count == 3); + assert(strcmp(p3{3}('foo'), 'abc -1.1')); + assert(strcmp(p3{3}('FOO'), 'abc -100.4')); + assert(strcmp(p3{3}('BAR'), 'abc 0.5')); + + di1 = Test.StringMyEnumD.new(); + di1('abc') = Test.MyEnum.enum1; + di1('') = Test.MyEnum.enum2; + di2 = Test.StringMyEnumD.new(); + di2('abc') = Test.MyEnum.enum1; + di2('qwerty') = Test.MyEnum.enum3; + di2('Hello!!') = Test.MyEnum.enum2; + di3 = Test.StringMyEnumD.new(); + di3('Goodbye') = Test.MyEnum.enum1; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opStringMyEnumDS', dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 3); + assert(r{1}('abc') == Test.MyEnum.enum1); + assert(r{1}('qwerty') == Test.MyEnum.enum3); + assert(r{1}('Hello!!') == Test.MyEnum.enum2); + assert(r{2}.Count == 2); + assert(r{2}('abc') == Test.MyEnum.enum1); + assert(r{2}('') == Test.MyEnum.enum2); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(p3{1}('Goodbye') == Test.MyEnum.enum1); + assert(p3{2}.Count == 2); + assert(p3{2}('abc') == Test.MyEnum.enum1); + assert(p3{2}('') == Test.MyEnum.enum2); + assert(p3{3}.Count == 3); + assert(p3{3}('abc') == Test.MyEnum.enum1); + assert(p3{3}('qwerty') == Test.MyEnum.enum3); + assert(p3{3}('Hello!!') == Test.MyEnum.enum2); + + di1 = Test.MyEnumStringD.new(); + di1(int32(Test.MyEnum.enum1)) = 'abc'; + di2 = Test.MyEnumStringD.new(); + di2(int32(Test.MyEnum.enum2)) = 'Hello!!'; + di2(int32(Test.MyEnum.enum3)) = 'qwerty'; + di3 = Test.MyEnumStringD.new(); + di3(int32(Test.MyEnum.enum1)) = 'Goodbye'; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opMyEnumStringDS', dsi1, dsi2); + + assert(length(r) == 2); + assert(r{1}.Count == 2); + assert(strcmp(r{1}(int32(Test.MyEnum.enum2)), 'Hello!!')); + assert(strcmp(r{1}(int32(Test.MyEnum.enum3)), 'qwerty')); + assert(r{2}.Count == 1); + assert(strcmp(r{2}(int32(Test.MyEnum.enum1)), 'abc')); + + assert(length(p3) == 3); + assert(p3{1}.Count == 1); + assert(strcmp(p3{1}(int32(Test.MyEnum.enum1)), 'Goodbye')); + assert(p3{2}.Count == 1); + assert(strcmp(p3{2}(int32(Test.MyEnum.enum1)), 'abc')); + assert(p3{3}.Count == 2); + assert(strcmp(p3{3}(int32(Test.MyEnum.enum2)), 'Hello!!')); + assert(strcmp(p3{3}(int32(Test.MyEnum.enum3)), 'qwerty')); + + s11 = Test.MyStruct(1, 1); + s12 = Test.MyStruct(1, 2); + di1 = Test.MyStructMyEnumD.new(); + di1(1).key = s11; + di1(1).value = Test.MyEnum.enum1; + di1(2).key = s12; + di1(2).value = Test.MyEnum.enum2; + + s22 = Test.MyStruct(2, 2); + s23 = Test.MyStruct(2, 3); + di2 = Test.MyStructMyEnumD.new(); + di2(1).key = s11; + di2(1).value = Test.MyEnum.enum1; + di2(2).key = s22; + di2(2).value = Test.MyEnum.enum3; + di2(3).key = s23; + di2(3).value = Test.MyEnum.enum2; + + di3 = Test.MyStructMyEnumD.new(); + di3(1).key = s23; + di3(1).value = Test.MyEnum.enum2; + + dsi1 = {di1, di2}; + dsi2 = {di3}; + + [r, p3] = call(p, 'opMyStructMyEnumDS', dsi1, dsi2); + + function checkStructDict(d) + for i = 1:length(d) + if isequal(d(i).key, s11) + assert(d(i).value == Test.MyEnum.enum1); + elseif isequal(d(i).key, s12) + assert(d(i).value == Test.MyEnum.enum2); + elseif isequal(d(i).key, s22) + assert(d(i).value == Test.MyEnum.enum3); + elseif isequal(d(i).key, s23) + assert(d(i).value == Test.MyEnum.enum2); + else + assert(false); + end + end + end + assert(length(r) == 2); + assert(length(r{1}) == 3); + checkStructDict(r{1}); + checkStructDict(r{2}); + + assert(length(p3) == 3); + assert(length(p3{1}) == 1); + checkStructDict(p3{1}); + assert(length(p3{2}) == 2); + checkStructDict(p3{2}); + assert(length(p3{3}) == 3); + checkStructDict(p3{3}); + + sdi1 = Test.ByteByteSD.new(); + sdi2 = Test.ByteByteSD.new(); + + si1 = [hex2dec('01'), hex2dec('11')]; + si2 = [hex2dec('12')]; + si3 = [hex2dec('f2'), hex2dec('f3')]; + + sdi1(hex2dec('01')) = si1; + sdi1(hex2dec('22')) = si2; + sdi2(hex2dec('f1')) = si3; + + [r, p3] = call(p, 'opByteByteSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(hex2dec('f1')); % Need to use a temp + assert(length(a) == 2); + assert(a(1) == hex2dec('f2')); + assert(a(2) == hex2dec('f3')); + assert(r.Count == 3); + a = r(hex2dec('01')); % Need to use a temp + assert(length(a) == 2); + assert(a(1) == hex2dec('01')); + assert(a(2) == hex2dec('11')); + a = r(hex2dec('22')); % Need to use a temp + assert(length(a) == 1); + assert(a(1) == hex2dec('12')); + a = r(hex2dec('f1')); % Need to use a temp + assert(length(a) == 2); + assert(a(1) == hex2dec('f2')); + assert(a(2) == hex2dec('f3')); + + sdi1 = Test.BoolBoolSD.new(); + sdi2 = Test.BoolBoolSD.new(); + + si1 = [true, false]; + si2 = [false, true, true]; + + sdi1(false) = si1; + sdi1(true) = si2; + sdi2(false) = si1; + + [r, p3] = call(p, 'opBoolBoolSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(false); % Need to use temp + assert(length(a) == 2); + assert(a(1)); + assert(~a(2)); + assert(r.Count == 2); + a = r(false); % Need to use temp + assert(length(a) == 2); + assert(a(1)); + assert(~a(2)); + a = r(true); % Need to use temp + assert(length(a) == 3); + assert(~a(1)); + assert(a(2)); + assert(a(3)); + + sdi1 = Test.ShortShortSD.new(); + sdi2 = Test.ShortShortSD.new(); + + si1 = [1, 2, 3]; + si2 = [4, 5]; + si3 = [6, 7]; + + sdi1(1) = si1; + sdi1(2) = si2; + sdi2(4) = si3; + + [r, p3] = call(p, 'opShortShortSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(4); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 6); + assert(a(2) == 7); + assert(r.Count == 3); + a = r(1); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 1); + assert(a(2) == 2); + assert(a(3) == 3); + a = r(2); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 4); + assert(a(2) == 5); + a = r(4); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 6); + assert(a(2) == 7); + + sdi1 = Test.IntIntSD.new(); + sdi2 = Test.IntIntSD.new(); + + si1 = [100, 200, 300]; + si2 = [400, 500]; + si3 = [600, 700]; + + sdi1(100) = si1; + sdi1(200) = si2; + sdi2(400) = si3; + + [r, p3] = call(p, 'opIntIntSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(400); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 600); + assert(a(2) == 700); + assert(r.Count == 3); + a = r(100); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 100); + assert(a(2) == 200); + assert(a(3) == 300); + a = r(200); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 400); + assert(a(2) == 500); + a = r(400); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 600); + assert(a(2) == 700); + + sdi1 = Test.LongLongSD.new(); + sdi2 = Test.LongLongSD.new(); + + si1 = [999999110, 999999111, 999999110]; + si2 = [999999120, 999999130]; + si3 = [999999110, 999999120]; + + sdi1(999999990) = si1; + sdi1(999999991) = si2; + sdi2(999999992) = si3; + + [r, p3] = call(p, 'opLongLongSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(999999992); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 999999110); + assert(a(2) == 999999120); + assert(r.Count == 3); + a = r(999999990); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 999999110); + assert(a(2) == 999999111); + assert(a(3) == 999999110); + a = r(999999991); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 999999120); + assert(a(2) == 999999130); + a = r(999999992); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 999999110); + assert(a(2) == 999999120); + + sdi1 = Test.StringFloatSD.new(); + sdi2 = Test.StringFloatSD.new(); + + si1 = [-1.1, 123123.2, 100.0]; + si2 = [42.24, -1.61]; + si3 = [-3.14, 3.14]; + + sdi1('abc') = si1; + sdi1('ABC') = si2; + sdi2('aBc') = si3; + + [r, p3] = call(p, 'opStringFloatSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3('aBc'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == single(-3.14)); + assert(a(2) == single(3.14)); + assert(r.Count == 3); + a = r('abc'); % Need to use temp + assert(length(a) == 3); + assert(a(1) == single(-1.1)); + assert(a(2) == single(123123.2)); + assert(a(3) == single(100.0)); + a = r('ABC'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == single(42.24)); + assert(a(2) == single(-1.61)); + a = r('aBc'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == single(-3.14)); + assert(a(2) == single(3.14)); + + sdi1 = Test.StringDoubleSD.new(); + sdi2 = Test.StringDoubleSD.new(); + + si1 = [ 1.1E10, 1.2E10, 1.3E10 ]; + si2 = [ 1.4E10, 1.5E10 ]; + si3 = [ 1.6E10, 1.7E10 ]; + + sdi1('Hello!!') = si1; + sdi1('Goodbye') = si2; + sdi2('') = si3; + + [r, p3] = call(p, 'opStringDoubleSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(''); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 1.6E10); + assert(a(2) == 1.7E10); + assert(r.Count== 3); + a = r('Hello!!'); % Need to use temp + assert(length(a) == 3); + assert(a(1) == 1.1E10); + assert(a(2) == 1.2E10); + assert(a(3) == 1.3E10); + a = r('Goodbye'); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 1.4E10); + assert(a(2) == 1.5E10); + a = r(''); % Need to use temp + assert(length(a) == 2); + assert(a(1) == 1.6E10); + assert(a(2) == 1.7E10); + + sdi1 = Test.StringStringSD.new(); + sdi2 = Test.StringStringSD.new(); + + si1 = { 'abc', 'de', 'fghi' }; + si2 = { 'xyz', 'or' }; + si3 = { 'and', 'xor' }; + + sdi1('abc') = si1; + sdi1('def') = si2; + sdi2('ghi') = si3; + + [r, p3] = call(p, 'opStringStringSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3('ghi'); % Need to use temp + assert(length(a) == 2); + assert(strcmp(a(1), 'and')); + assert(strcmp(a(2), 'xor')); + assert(r.Count== 3); + a = r('abc'); % Need to use temp + assert(length(a) == 3); + assert(strcmp(a(1), 'abc')); + assert(strcmp(a(2), 'de')); + assert(strcmp(a(3), 'fghi')); + a = r('def'); % Need to use temp + assert(length(a) == 2); + assert(strcmp(a(1), 'xyz')); + assert(strcmp(a(2), 'or')); + a = r('ghi'); % Need to use temp + assert(length(a) == 2); + assert(strcmp(a(1), 'and')); + assert(strcmp(a(2), 'xor')); + + sdi1 = Test.MyEnumMyEnumSD.new(); + sdi2 = Test.MyEnumMyEnumSD.new(); + + si1 = { Test.MyEnum.enum1, Test.MyEnum.enum1, Test.MyEnum.enum2 }; + si2 = { Test.MyEnum.enum1, Test.MyEnum.enum2 }; + si3 = { Test.MyEnum.enum3, Test.MyEnum.enum3 }; + + sdi1(int32(Test.MyEnum.enum3)) = si1; + sdi1(int32(Test.MyEnum.enum2)) = si2; + sdi2(int32(Test.MyEnum.enum1)) = si3; + + [r, p3] = call(p, 'opMyEnumMyEnumSD', sdi1, sdi2); + + assert(p3.Count == 1); + a = p3(int32(Test.MyEnum.enum1)); % Need to use temp + assert(length(a) == 2); + assert(a{1} == Test.MyEnum.enum3); + assert(a{2} == Test.MyEnum.enum3); + assert(r.Count== 3); + a = r(int32(Test.MyEnum.enum3)); % Need to use temp + assert(length(a) == 3); + assert(a{1} == Test.MyEnum.enum1); + assert(a{2} == Test.MyEnum.enum1); + assert(a{3} == Test.MyEnum.enum2); + a = r(int32(Test.MyEnum.enum2)); % Need to use temp + assert(length(a) == 2); + assert(a{1} == Test.MyEnum.enum1); + assert(a{2} == Test.MyEnum.enum2); + a = r(int32(Test.MyEnum.enum1)); % Need to use temp + assert(length(a) == 2); + assert(a{1} == Test.MyEnum.enum3); + assert(a{2} == Test.MyEnum.enum3); + + lengths = [0, 1, 2, 126, 127, 128, 129, 253, 254, 255, 256, 257, 1000]; + + for l = lengths + s = zeros(1, l); + if l > 0 + s(1:l) = (1:l); + end + r = call(p, 'opIntS', s); + assert(length(r) == l); + for j = 1:l + assert(r(j) == -j); + end + end + + ctx = Ice.Context.new(); + ctx('one') = 'ONE'; + ctx('two') = 'TWO'; + ctx('three') = 'THREE'; + + assert(p.ice_getContext().Count == 0); + r = call(p, 'opContext'); + assert(~isequal(r, ctx)); + + r = call(p, 'opContext', ctx); + assert(p.ice_getContext().Count == 0); + assert(isequal(r, ctx)); + + p2 = Test.MyClassPrx.checkedCast(p.ice_context(ctx)); + assert(isequal(p2.ice_getContext(), ctx)); + r = p2.opContext(); + assert(isequal(r, ctx)); + r = p2.opContext(ctx); + assert(isequal(r, ctx)); + + % + % Test implicit context propagation + % +%{ + impls = {'Shared', 'PerThread'}; + for i = 1:2 + initData = app.createInitializationData(); + initData.properties_ = communicator.getProperties().clone(); + initData.properties_.setProperty('Ice.ImplicitContext', impls{i}); + + ic = app.initialize(initData); + + ctx = Ice.Context.new(); + ctx('one') = 'ONE'; + ctx('two') = 'TWO'; + ctx('three') = 'THREE'; + + p3 = Test.MyClassPrx.uncheckedCast(ic.stringToProxy(['test:', app.getTestEndpoint(0)])); + + ic.getImplicitContext().setContext(ctx); + assert(isequal(ic.getImplicitContext().getContext(), ctx)); + assert(isequal(p3.opContext(), ctx)); + + assert(!ic.getImplicitContext().containsKey('zero')); + r = ic.getImplicitContext().put('zero', 'ZERO'); + assert(strcmp(r, '')); + assert(ic.getImplicitContext().containsKey('zero')); + assert(strcmp(ic.getImplicitContext().get('zero'), 'ZERO')); + + ctx = ic.getImplicitContext().getContext(); + assert(isequal(p3.opContext(), ctx)); + + prxContext = Ice.Context.new(); + prxContext('one') = 'UN'; + prxContext('four') = 'QUATRE'; + + combined = Ice.Context.new(ctx); + keys = prxContext.keys(); + for j = 1:prxContext.Count + combined(keys{j}) = prxContext(keys{j}); + end + assert(strcmp(combined('one'), 'UN')); + + p3 = p3.ice_context(prxContext); + + ic.getImplicitContext().setContext([]); + assert(isequal(p3.opContext(), prxContext)); + + ic.getImplicitContext().setContext(ctx); + assert(isequal(p3.opContext(), combined)); + + assert(strcmp(ic.getImplicitContext().remove('one'), 'ONE')); + + ic.destroy(); + end +%} + + d = 1278312346.0 / 13.0; + ds = zeros(1, 5); + for i = 1:5 + ds(i) = d; + end + call(p, 'opDoubleMarshaling', d, ds); + + call(p, 'opIdempotent'); + + call(p, 'opNonmutating'); + + assert(call(p, 'opByte1', hex2dec('FF')) == hex2dec('FF')); + assert(call(p, 'opShort1', hex2dec('7FFF')) == hex2dec('7FFF')); + assert(call(p, 'opInt1', hex2dec('7FFFFFFF')) == hex2dec('7FFFFFFF')); + %assert(call(p, 'opLong1', 0x7FFFFFFFFFFFFFFF) == 0x7FFFFFFFFFFFFFFF); + assert(call(p, 'opFloat1', 1.0) == single(1.0)); + assert(call(p, 'opDouble1', 1.0) == 1.0); + assert(strcmp(call(p, 'opString1', 'opString1'), 'opString1')); + assert(length(call(p, 'opStringS1', {})) == 0); + empty = call(p, 'opByteBoolD1', []); + assert(empty.Count == 0); + assert(length(call(p, 'opStringS2', [])) == 0); + empty = call(p, 'opByteBoolD2', []); + assert(empty.Count == 0); + + d = Test.MyDerivedClassPrx.uncheckedCast(p); + s = Test.MyStruct1(); + s.tesT = 'Test.MyStruct1.s'; + s.myClass = []; + s.myStruct1 = 'Test.MyStruct1.myStruct1'; + s = call(d, 'opMyStruct1', s); + assert(strcmp(s.tesT, 'Test.MyStruct1.s')); + assert(isempty(s.myClass)); + assert(strcmp(s.myStruct1, 'Test.MyStruct1.myStruct1')); + + %{ + c = new MyClass1(); + c.tesT = 'Test.MyClass1.testT'; + c.myClass = null; + c.myClass1 = 'Test.MyClass1.myClass1'; + c = d.opMyClass1(c); + assert(c.tesT.equals('Test.MyClass1.testT')); + assert(c.myClass == null); + assert(c.myClass1.equals('Test.MyClass1.myClass1')); + %} + end + end +end + +function varargout = call(p, op, varargin) + try + name = [op, 'Async']; + future = p.(name)(varargin{:}); + assert(strcmp(future.Operation, op)); + assert(~future.Read); + assert(future.wait()); + assert(strcmp(future.State, 'finished')); + [varargout{1:nargout}] = future.fetchOutputs(); + assert(future.Read); + catch ex + disp(getReport(ex, 'extended')); + assert(false); + end +end diff --git a/matlab/test/Ice/operations/generated/.gitignore b/matlab/test/Ice/operations/generated/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/matlab/test/Ice/operations/generated/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/slice/Ice/Connection.ice b/slice/Ice/Connection.ice index fc48f8d159f..1a4b67da136 100644 --- a/slice/Ice/Connection.ice +++ b/slice/Ice/Connection.ice @@ -181,7 +181,7 @@ local enum ConnectionClose * The user-level interface to a connection. * **/ -["php:internal"] +["php:internal", "matlab:internal"] local interface Connection { /** |