summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-12-20 00:56:45 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-12-20 00:56:45 (GMT)
commit0388c7ac478187ff8d264b6e0275a4c4a43796b9 (patch)
tree7e62439ebf72b6369ee7b1daa370e6251c06b7e0
parent22e22bfd0965e01fea041e053873d352387805f6 (diff)
downloaduscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.zip
uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.tar.gz
uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.tar.bz2
Performance and bugfix for WebSockets
-rw-r--r--CMakeLists.txt22
-rw-r--r--apps/samples/miles/miles.js2
-rw-r--r--apps/samples/miles/miles.scxml1
-rw-r--r--apps/samples/vrml/ffmpeg-server.invoked.scxml7
-rw-r--r--apps/samples/vrml/viewer-webgl.js8
-rw-r--r--apps/samples/vrml/viewer.html43
-rw-r--r--apps/samples/vrml/vrml-server.scxml3
-rw-r--r--apps/samples/websockets/websockets.html4
-rwxr-xr-xcontrib/build-scripts/build-arabica-macosx.sh5
-rwxr-xr-xcontrib/build-scripts/build-v8-mac.sh8
-rw-r--r--contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new1018
-rwxr-xr-xcontrib/local/compress_and_upload_deps.sh1
-rw-r--r--contrib/src/evws/evws.c112
-rw-r--r--docs/Ubuntu-LTS.md4
-rw-r--r--src/bindings/swig/php/uscxmlNativePHP.php18
-rw-r--r--src/uscxml/Convenience.h12
-rw-r--r--src/uscxml/Interpreter.cpp58
-rw-r--r--src/uscxml/Interpreter.h8
-rw-r--r--src/uscxml/Message.cpp58
-rw-r--r--src/uscxml/Message.h4
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp5
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp15
-rw-r--r--src/uscxml/server/HTTPServer.cpp31
-rw-r--r--src/uscxml/util/Base64.h5
-rw-r--r--src/uscxml/util/Base64.hpp14
-rw-r--r--src/uscxml/util/MD5.c1
-rw-r--r--test/CMakeLists.txt9
-rw-r--r--test/samples/uscxml/test-performance.scxml2
-rwxr-xr-xtest/samples/w3c/update-txml.sh6
-rw-r--r--test/src/test-base64.cpp18
-rw-r--r--test/src/test-predicates.cpp66
31 files changed, 1409 insertions, 159 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0454f4c..da50553 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,18 @@ if (APPLE)
MACOSX_VERSION_MINOR
MACOSX_VERSION_PATCH)
endif()
+ if (MACOSX_VERSION VERSION_GREATER "10.8.99")
+ # LIST(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_OSX_SYSROOT})
+ # make sure that we find libxml2 here first
+ set(CMAKE_FIND_ROOT_PATH ${CMAKE_OSX_SYSROOT} ${CMAKE_FIND_ROOT_PATH})
+ endif()
+endif()
+
+if (NOT $ENV{MACOSX_DEPLOYMENT_TARGET} STREQUAL ""
+ AND ENV{MACOSX_DEPLOYMENT_TARGET} VERSION_LESS "10.9"
+ AND MACOSX_VERSION VERSION_GREATER "10.8.99")
+ message(WARNING "\nMACOSX_DEPLOYMENT_TARGET is set to $ENV{MACOSX_DEPLOYMENT_TARGET} implying libstdc++ instead of libc++ - linking against prebuilts from 10.8")
+ set(MACOSX_VERSION_MINOR 8)
endif()
# We use the toolchain file from http://code.google.com/p/android-cmake/
@@ -249,6 +261,8 @@ else()
endif()
include_directories(${USCXML_PREBUILT_LIBRARY_PATH}/include)
+#message(STATUS "Searching for prebuilt libraries in: ${CMAKE_FIND_ROOT_PATH}")
+
if (WIN32)
include_directories(${PROJECT_SOURCE_DIR}/contrib/src/getopt)
include_directories(${PROJECT_SOURCE_DIR}/contrib/src/inttypes)
@@ -266,8 +280,8 @@ if (CMAKE_CROSSCOMPILING)
OPTION(BUILD_TESTS "Build USCXML tests" OFF)
else()
OPTION(BUILD_TESTS "Build USCXML tests" ON)
- OPTION(RUN_W3C_ECMA_TESTS "Run W3C ECMAScript tests" OFF)
- OPTION(RUN_W3C_XPATH_TESTS "Run W3C XPath tests" OFF)
+ OPTION(BUILD_TESTS_W3C_ECMA "Run W3C ECMAScript tests" OFF)
+ OPTION(BUILD_TESTS_W3C_XPATH "Run W3C XPath tests" OFF)
endif()
OPTION(ENABLE_GCOV "Compile with gcov support" OFF)
@@ -500,7 +514,8 @@ if (NOT WIN32)
# message("CMAKE_SYSTEM_PROGRAM_PATH: ${CMAKE_SYSTEM_PROGRAM_PATH}")
# message("CMAKE_FIND_ROOT_PATH: ${CMAKE_FIND_ROOT_PATH}")
- if (APPLE)
+ # MacOSX Mavericks moved libxml2 into SDK
+ if (APPLE AND ${MACOSX_VERSION} VERSION_LESS "10.9.0")
set(PC_LIBXML_INCLUDEDIR "/usr/include/libxml2/")
endif()
@@ -957,6 +972,7 @@ foreach(LIBRARY ${USCXML_OPT_LIBS})
set(SKIP_NEXT ON)
endif()
elseif (LIBRARY MATCHES "uscxml.*")
+ elseif (LIBRARY MATCHES ".*\\.framework.*")
elseif (LIBRARY MATCHES "mmi_proto.*")
else()
if (NOT SKIP_NEXT)
diff --git a/apps/samples/miles/miles.js b/apps/samples/miles/miles.js
index cd61f64..01bb134 100644
--- a/apps/samples/miles/miles.js
+++ b/apps/samples/miles/miles.js
@@ -54,7 +54,7 @@ function Miles(element, params) {
var audioEncoding = "";
var repollInterval = {
- image: 50,
+ image: 20,
chat: 500,
participants: 1000
};
diff --git a/apps/samples/miles/miles.scxml b/apps/samples/miles/miles.scxml
index c1c6c69..8281e9f 100644
--- a/apps/samples/miles/miles.scxml
+++ b/apps/samples/miles/miles.scxml
@@ -8,6 +8,7 @@
<if cond="_event.data.origin">
<!-- <log label="Reply-length" expr="_event.data.base64.length" /> -->
<if cond="_event.name === 'thumbnail.reply'">
+ <!-- <log expr="_event.data.image.base64().length" /> -->
<respond status="200" to="_event.data.origin">
<header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload -->
<header name="Access-Control-Allow-Origin" value="*" />
diff --git a/apps/samples/vrml/ffmpeg-server.invoked.scxml b/apps/samples/vrml/ffmpeg-server.invoked.scxml
index bac0792..0c6449f 100644
--- a/apps/samples/vrml/ffmpeg-server.invoked.scxml
+++ b/apps/samples/vrml/ffmpeg-server.invoked.scxml
@@ -121,7 +121,7 @@
-->
<script>
//<![CDATA[
-// dump(_event);
+ dump(_event);
var pathDelim = ':'; // we need to flatten directories - this will seperate them in filenames
// store event
@@ -158,9 +158,7 @@
}
var keyFrame = job.keyFrames[kfIndex];
- keyFrame.modelFile = keyFrame.imageURL.substr(keyFrame.serverURL.length + 1);
- keyFrame.file = keyFrame.modelFile.substr(0, keyFrame.modelFile.indexOf('.'));
- keyFrame.ext = keyFrame.modelFile.substr(keyFrame.modelFile.indexOf('.') + 1);
+ keyFrame.file = keyFrame.imagePath.substr(1);
keyFrame.modelFile = keyFrame.file + ".osgb";
keyFrame.modelFile = keyFrame.modelFile.replace(/\//g, pathDelim);
@@ -236,6 +234,7 @@
_event.data.pathComponent.length == 3 &amp;&amp;
_event.data.pathComponent[1] === 'movie' &amp;&amp;
_event.data.pathComponent[2] === 'codecs'">
+ <log expr="_invokers['ffmpeg']" />
<send target="#_parent" event="send.codecs">
<param name="context" expr="_event.origin" />
<param name="codecs" expr="_invokers['ffmpeg']" />
diff --git a/apps/samples/vrml/viewer-webgl.js b/apps/samples/vrml/viewer-webgl.js
index c376e25..10dbd72 100644
--- a/apps/samples/vrml/viewer-webgl.js
+++ b/apps/samples/vrml/viewer-webgl.js
@@ -184,7 +184,7 @@ function VRMLViewer(element, params) {
}
if (self.enableSceneshots) {
self.imgElem.src = self.serverURL + self.imagePath + self.imageFormat + urlSuffixForPose(self.pose);
- if (self.enableMovies) {
+ if (self.enableMovies && self.movieAddButton) {
// we are showing an image, activate movie controls
self.movieAddButton.domNode.style.display = "";
self.movieDropDown.domNode.style.display = "";
@@ -964,7 +964,7 @@ function VRMLViewer(element, params) {
avatarPose.width = 60;
avatarPose.height = 60;
var avatarImgUrl = urlSuffixForPose(avatarPose);
- avatar.innerHTML = '<img src=' + self.imagePath + avatarImgUrl + ' /> ';
+ avatar.innerHTML = '<img src=' + self.imagePath + self.imageFormat + avatarImgUrl + ' /> ';
item.srcEcc = "VRMLViewer";
item.iconPoseUrl = self.imagePath + avatarImgUrl;
item.imagePath = self.imagePath;
@@ -1054,7 +1054,7 @@ function VRMLViewer(element, params) {
thumbPose.height = self.pose.height / 10;
var thumbImgUrl = urlSuffixForPose(thumbPose);
- thumbImgElem.src = self.imagePath + thumbImgUrl;
+ thumbImgElem.src = self.serverURL + self.imagePath + self.imageFormat + thumbImgUrl;
// removeImgElem.src = self.resRoot + 'img/close.png';
item.srcEcc = "VRMLViewer";
@@ -1074,7 +1074,7 @@ function VRMLViewer(element, params) {
style: "width: 320px",
options: []
});
- self.populateMovieCodecs("http://" + self.serverURL + '/movie/codecs', self.movieFormatSelection);
+ self.populateMovieCodecs(self.serverURL + '/movie/codecs', self.movieFormatSelection);
self.movieFormatLengthRowElem.appendChild(dojo.create('td', { innerHTML: 'Format:'} ));
self.movieFormatLengthRowElem.appendChild(dojo.create('td', { colspan: "2"}));
diff --git a/apps/samples/vrml/viewer.html b/apps/samples/vrml/viewer.html
index 345ee56..50a2fef 100644
--- a/apps/samples/vrml/viewer.html
+++ b/apps/samples/vrml/viewer.html
@@ -60,7 +60,32 @@
<script type="text/javascript">
require(["dojo/domReady!", "dojo"], function(dom, dojo) {
- var viewer = new VRMLViewer("scene1", {
+ var viewer = new VRMLViewer("scene1", {
+ pose: {
+ pitch : 0,
+ roll : 0,
+ yaw : 0,
+ zoom : 1,
+ x : 0,
+ y : 0,
+ z : 0,
+ autorotate : true
+ },
+ height: 300,
+ width: 400,
+ enableMovies: false,
+ enableDND: false,
+ enableWebGL: true,
+ enableSceneshots: false,
+ enableDraggables: false,
+ listNavigationStyle: true,
+ treeNavigationStyle: true,
+ listDirectory: "/hard_mp",
+ imagePath: "/hard_mp/HARD_MP_VAL_000",
+ imageFormat: "png",
+ serverURL: "http://localhost:8082/vrml",
+ });
+ var viewer2 = new VRMLViewer("scene2", {
pose: {
pitch : 0,
roll : 0,
@@ -71,22 +96,20 @@
z : 0,
autorotate : true
},
- height: 600,
- width: 800,
- enableMovies: false,
+ height: 300,
+ width: 400,
+ enableMovies: true,
enableDND: false,
- enableWebGL: true,
- enableSceneshots: false,
- enableDraggables: false,
+ enableWebGL: false,
+ enableSceneshots: true,
+ enableDraggables: true,
listNavigationStyle: true,
treeNavigationStyle: true,
listDirectory: "/hard_mp",
imagePath: "/hard_mp/HARD_MP_VAL_000",
imageFormat: "png",
- serverURL: "http://localhost:8081/vrml",
+ serverURL: "http://localhost:8082/vrml"
});
- //var viewer2 = new VRMLViewer("scene2");
-// var annotations = new Annotations("annotations1", { 'viewer': viewer });
});
</script>
</head>
diff --git a/apps/samples/vrml/vrml-server.scxml b/apps/samples/vrml/vrml-server.scxml
index e35d221..c71f066 100644
--- a/apps/samples/vrml/vrml-server.scxml
+++ b/apps/samples/vrml/vrml-server.scxml
@@ -325,8 +325,7 @@
<script>//dump(_event);</script>
<respond status="200" to="_event.data.context">
<header name="Connection" value="close" />
- <header name="Content-Type" valueexpr="application/json" />
- <header name="Content-Disposition" valueexpr="'attachment; filename=' + _event.data.filename" />
+ <header name="Content-Type" value="application/json" />
<content expr="_event.data.codecs" />
</respond>
</transition>
diff --git a/apps/samples/websockets/websockets.html b/apps/samples/websockets/websockets.html
index c90f728..88e4def 100644
--- a/apps/samples/websockets/websockets.html
+++ b/apps/samples/websockets/websockets.html
@@ -43,8 +43,8 @@
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend(littlePacket);
- // doSend(mediumPacket);
- // doSend(hugePacket);
+ doSend(mediumPacket);
+ //doSend(hugePacket);
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
diff --git a/contrib/build-scripts/build-arabica-macosx.sh b/contrib/build-scripts/build-arabica-macosx.sh
index 8489815..c5a4bb9 100755
--- a/contrib/build-scripts/build-arabica-macosx.sh
+++ b/contrib/build-scripts/build-arabica-macosx.sh
@@ -1,8 +1,9 @@
#!/bin/bash
#
-# build libevent for MacOSX
+# build arabica for MacOSX
#
+# ./configure --with-boost=/opt/local/include/ --with-libxml2=`xcrun --show-sdk-path`/usr --with-parser=libxml2
# exit on error
set -e
@@ -12,6 +13,7 @@ DIR="$( cd "$( dirname "$0" )" && pwd )"
MACOSX_VER=`/usr/bin/sw_vers -productVersion`
MACOSX_COMP=(`echo $MACOSX_VER | tr '.' ' '`)
DEST_DIR="${DIR}/../prebuilt/darwin-i386/${MACOSX_COMP[0]}.${MACOSX_COMP[1]}/gnu"
+SYSROOT=`xcrun --show-sdk-path`
if [ ! -f src/arabica.cpp ]; then
echo
@@ -63,6 +65,7 @@ LDFLAGS="${MACOSX_VERSION_MIN} -arch x86_64" \
--disable-dependency-tracking \
--with-pic
+
make
cp ./src/.libs/libarabica.a ./libarabica.x86_64.a
make clean
diff --git a/contrib/build-scripts/build-v8-mac.sh b/contrib/build-scripts/build-v8-mac.sh
index 4d5aa62..e979c4d 100755
--- a/contrib/build-scripts/build-v8-mac.sh
+++ b/contrib/build-scripts/build-v8-mac.sh
@@ -37,6 +37,14 @@ fi
DEPOT_PATH="${PWD}/../depot_tools"
export PATH="${DEPOT_PATH}:${PATH}"
+if [ ${MACOSX_COMP[1]} -lt 9 ]; then
+ CXXFLAGS="-mmacosx-version-min=10.6 -stdlib=libstdc++"
+ LDFLAGS="-stdlib=libstdc++"
+else
+ CXXFLAGS="-mmacosx-version-min=10.7 -stdlib=libc++"
+ LDFLAGS="-stdlib=libc++"
+fi
+
make dependencies
make ia32.release
diff --git a/contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new
new file mode 100644
index 0000000..cbe33e8
--- /dev/null
+++ b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new
@@ -0,0 +1,1018 @@
+# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
+# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
+# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
+# Copyright (C) 2006 Apple Computer, Inc.
+# Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
+# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
+# Copyright (C) Research In Motion Limited 2010. All rights reserved.
+# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+# Copyright (C) 2012 Ericsson AB. All rights reserved.
+# Copyright (C) 2013 Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+package CodeGeneratorArabicaV8;
+
+use strict;
+use Data::Dumper;
+use Carp qw/longmess cluck confess/;
+
+use constant FileNamePrefix => "V8";
+
+my $codeGenerator;
+
+
+my @headerContent = ();
+my @implContentHeader = ();
+my @implContent = ();
+my @implContentDecls = ();
+my %implIncludes = ();
+my %headerIncludes = ();
+
+# Default .h template
+my $headerTemplate = << 'EOF';
+/**
+ * @file
+ * @author This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+EOF
+
+# Default constructor
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ $codeGenerator = shift;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+sub GenerateInterface
+{
+ my $object = shift;
+ my $interface = shift;
+
+# print Dumper($interface);
+
+ # Start actual generation
+ if ($interface->extendedAttributes->{"Callback"}) {
+ die();
+ $object->GenerateCallbackHeader($interface);
+ $object->GenerateCallbackImplementation($interface);
+ } else {
+ $object->GenerateHeader($interface);
+ $object->GenerateImplementation($interface);
+ }
+}
+
+sub AddToImplIncludes
+{
+ my $header = shift;
+ my $conditional = shift;
+
+ if ($header eq "V8bool.h") {
+ confess();
+ }
+
+ if (not $conditional) {
+ $implIncludes{$header} = 1;
+ } elsif (not exists($implIncludes{$header})) {
+ $implIncludes{$header} = $conditional;
+ } else {
+ my $oldValue = $implIncludes{$header};
+ if ($oldValue ne 1) {
+ my %newValue = ();
+ $newValue{$conditional} = 1;
+ foreach my $condition (split(/\|/, $oldValue)) {
+ $newValue{$condition} = 1;
+ }
+ $implIncludes{$header} = join("|", sort keys %newValue);
+ }
+ }
+}
+
+sub GenerateHeader
+{
+ my $object = shift;
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $extensions = $interface->extendedAttributes;
+# print Dumper($extensions);
+
+ # Copy contents of parent interfaces except the first parent.
+ my @parents;
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentInterfaces($interface, \@parents, 1);
+ $codeGenerator->LinkOverloadedFunctions($interface);
+
+ # - Add default header template
+ push(@headerContent, GenerateHeaderContentHeader($interface));
+
+ $headerIncludes{"string"} = 1;
+ $headerIncludes{"uscxml/plugins/datamodel/ecmascript/v8/V8DOM.h"} = 1;
+ $headerIncludes{"DOM/Node.hpp"} = 1;
+ $headerIncludes{"v8.h"} = 1;
+
+ if ($interfaceName =~ /.*Array$/ or $interfaceName =~ /^ArrayBuffer.*/) {
+ $headerIncludes{"../../TypedArray.h"} = 1;
+ }
+
+ foreach (@{$interface->parents}) {
+ my $parent = $_;
+ $headerIncludes{"V8${parent}.h"} = 1;
+ }
+
+ push(@headerContent, "#include \<string\>\n");
+ foreach my $headerInclude (sort keys(%headerIncludes)) {
+ if ($headerInclude =~ /wtf|v8\.h/) {
+ push(@headerContent, "#include \<${headerInclude}\>\n");
+ } else {
+ push(@headerContent, "#include \"${headerInclude}\"\n");
+ }
+ }
+
+ push(@headerContent, "");
+ push(@headerContent, "\nnamespace Arabica {");
+ push(@headerContent, "\nnamespace DOM {\n");
+
+ push(@headerContent, "\nclass V8${interfaceName} {");
+ push(@headerContent, "\npublic:");
+
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ push(@headerContent, <<END);
+
+ struct V8${interfaceName}Private {
+ V8DOM* dom;
+ ${wrapperType}* nativeObj;
+ };
+END
+
+ if ($extensions->{'DontDestroyWrapped'}) {
+ push(@headerContent, "\n V8_DESTRUCTOR_KEEP_WRAPPED(V8${interfaceName}Private);");
+ } else {
+ push(@headerContent, "\n V8_DESTRUCTOR(V8${interfaceName}Private);");
+ }
+ push(@headerContent, "\n static bool hasInstance(v8::Handle<v8::Value>);");
+ push(@headerContent, "\n");
+
+ # callbacks for actual functions
+ my %generated;
+ foreach my $function (@{$interface->functions}) {
+ my $name = $function->signature->name;
+ my $attrExt = $function->signature->extendedAttributes;
+ my $custom = ($attrExt->{'Custom'} ? "Custom" : "");
+ next if (exists $generated{"${name}${custom}Callback"});
+ push(@headerContent, "\n static void ${name}${custom}Callback(const v8::FunctionCallbackInfo<v8::Value>&);");
+ $generated{"${name}${custom}Callback"} = 1;
+ }
+ push(@headerContent, "\n");
+
+ # attribute getter and setters
+ foreach my $attribute (@{$interface->attributes}) {
+ my $name = $attribute->signature->name;
+ my $attrExt = $attribute->signature->extendedAttributes;
+ my $customGetter = ($attrExt->{'CustomGetter'} ? "Custom" : "");
+ my $customSetter = ($attrExt->{'CustomSetter'} ? "Custom" : "");
+ push(@headerContent, "\n static void ${name}${customGetter}AttrGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info);");
+ if (!IsReadonly($attribute)) {
+ push(@headerContent, "\n static void ${name}${customSetter}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info);");
+ }
+ }
+
+ if ($extensions->{'CustomIndexedGetter'}) {
+ push(@headerContent, "\n static void indexedPropertyCustomGetter(uint32_t, const v8::AccessorInfo&);");
+ }
+ if ($extensions->{'CustomIndexedSetter'}) {
+ push(@headerContent, "\n static void indexedPropertyCustomSetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);");
+ }
+ push(@headerContent, "\n");
+
+ GenerateClassPrototypeHeader($interface);
+
+ push(@headerContent, "\n};\n\n}\n}\n\n");
+ push(@headerContent, "#endif // V8${interfaceName}" . "_h\n");
+
+}
+
+#
+# Write class template prototype constructor
+#
+sub GenerateClassPrototypeHeader
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $extensions = $interface->extendedAttributes;
+
+ if ($extensions->{'Constructors'}) {
+
+ push(@headerContent, "\n");
+ push(@headerContent, " static void constructor(const v8::FunctionCallbackInfo<v8::Value>&);\n");
+ push(@headerContent, <<END);
+ static v8::Handle<v8::FunctionTemplate> getConstructor(v8::Isolate* isolate) {
+ return v8::FunctionTemplate::New(isolate, constructor);
+ }
+END
+ }
+
+ push(@headerContent, <<END);
+ static v8::Handle<v8::FunctionTemplate> getTmpl(v8::Isolate* isolate) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
+ tmpl->SetClassName(v8::String::NewFromUtf8(isolate, "${interfaceName}"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ (void)prototype; // surpress unused warnings
+
+ instance->SetInternalFieldCount(1);
+END
+
+ push(@headerContent, "\n");
+ foreach my $attribute (@{$interface->attributes}) {
+ my $name = $attribute->signature->name;
+ my $attrExt = $attribute->signature->extendedAttributes;
+ my $customGetter = ($attrExt->{'CustomGetter'} ? "Custom" : "");
+ my $customSetter = ($attrExt->{'CustomSetter'} ? "Custom" : "");
+ my $getter = "V8${interfaceName}::${name}${customGetter}AttrGetter";
+ my $setter = (IsReadonly($attribute) ? "0" : "V8${interfaceName}::${name}${customSetter}AttrSetter");
+ push(@headerContent, <<END);
+ instance->SetAccessor(v8::String::NewFromUtf8(isolate, "${name}"), ${getter}, ${setter},
+ v8::External::New(isolate, 0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+END
+ }
+
+ if ($extensions->{'CustomIndexedGetter'} || $extensions->{'CustomIndexedSetter'}) {
+ my $indexedGetter = ($extensions->{'CustomIndexedGetter'} ? "V8${interfaceName}::indexedPropertyCustomGetter" : 0);
+ my $indexedSetter = ($extensions->{'CustomIndexedSetter'} ? "V8${interfaceName}::indexedPropertyCustomSetter" : 0);
+ push(@headerContent, "\n instance->SetIndexedPropertyHandler(${indexedGetter}, ${indexedSetter});");
+ }
+
+ push(@headerContent, "\n");
+ my %generated;
+ foreach my $function (@{$interface->functions}) {
+ my $name = $function->signature->name;
+ my $attrExt = $function->signature->extendedAttributes;
+ my $custom = ($attrExt->{'Custom'} ? "Custom" : "");
+ next if (exists $generated{"${name}"});
+ $generated{"${name}"} = 1;
+ push(@headerContent, <<END);
+ prototype->Set(v8::String::NewFromUtf8(isolate, "${name}"),
+ v8::FunctionTemplate::New(isolate, V8${interfaceName}::${name}${custom}Callback, v8::Undefined(isolate)), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+END
+ }
+
+ push(@headerContent, "\n");
+ foreach my $constant (@{$interface->constants}) {
+ my $name = $constant->name;
+ my $value = $constant->value;
+ my $type = IdlToV8Type($constant->type);
+ push(@headerContent, <<END);
+ tmpl->Set(v8::String::NewFromUtf8(isolate, "${name}"), ${type}::New(${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+ prototype->Set(v8::String::NewFromUtf8(isolate, "${name}"), ${type}::New(${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+END
+ }
+
+ push(@headerContent, "\n");
+ if (@{$interface->parents}) {
+ my $parent = @{$interface->parents}[0];
+ push(@headerContent, " tmpl->Inherit(V8${parent}::getTmpl());\n");
+ }
+ push(@headerContent, <<END);
+ return tmpl;
+ }
+
+END
+
+}
+
+sub GenerateImplementationAttributes
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $extensions = $interface->extendedAttributes;
+
+ # Generate property accessors for attributes.
+ for (my $index = 0; $index < @{$interface->attributes}; $index++) {
+ my $attribute = @{$interface->attributes}[$index];
+ my $attrType = $attribute->signature->type;
+ my $attrName = $attribute->signature->name;
+ my $attrExt = $attribute->signature->extendedAttributes;
+
+ my $wrapperRetType = IdlToWrapperType($attrType);
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $wrapperGetter;
+
+ if ($attrExt->{'AttributeIsPublic'} || $extensions->{'AttributesArePublic'}) {
+ $wrapperGetter = $attrName;
+ } else {
+ $wrapperGetter = IdlToWrapperAttrGetter($interface, $attribute)."()";
+
+ }
+
+ # getter
+ if (!$attrExt->{'CustomGetter'}) {
+ push(@implContent, <<END);
+
+ void V8${interfaceName}::${attrName}AttrGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Object> self = info.Holder();
+ struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));
+END
+ if (IsWrapperType($attrType)) {
+ AddToImplIncludes("V8".$attrType.".h");
+ push(@implContent, "\n ".GenerateConditionalUndefReturn($interface, $attribute, "privData->nativeObj->${wrapperGetter}"));
+
+ push(@implContent, <<END);
+
+ ${wrapperRetType}* arbaicaRet = new ${wrapperRetType}(privData->nativeObj->${wrapperGetter});
+
+ v8::Handle<v8::Function> arbaicaRetCtor = V8${attrType}::getTmpl(isolate)->GetFunction();
+ v8::Persistent<v8::Object> arbaicaRetObj = v8::Persistent<v8::Object>::New(arbaicaRetCtor->NewInstance());
+
+ struct V8${attrType}::V8${attrType}Private* retPrivData = new V8${attrType}::V8${attrType}Private();
+ retPrivData->dom = privData->dom;
+ retPrivData->nativeObj = arbaicaRet;
+
+ arbaicaRetObj->SetInternalField(0, V8DOM::toExternal(retPrivData));
+ arbaicaRetObj.MakeWeak(0, V8${attrType}::jsDestructor);
+ return arbaicaRetObj;
+END
+ } else {
+ my $v8Type = IdlToV8Type($attrType);
+ if ($attrType eq "DOMString") {
+ if ($attrExt->{'EmptyAsNull'}) {
+ push(@implContent, "\n if (privData->nativeObj->${wrapperGetter}.length() == 0)");
+ push(@implContent, "\n return v8::Undefined(isolate);");
+ }
+ push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter}.c_str());");
+ } else {
+ push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter});");
+ }
+ }
+ push(@implContent, "\n }\n");
+ }
+
+ if (!$attrExt->{'CustomSetter'}) {
+ # setter
+ if (!IsReadonly($attribute)) {
+ my $wrapperSetter = IdlToWrapperAttrSetter($attrName);
+ push(@implContent, "\n void V8${interfaceName}::${attrName}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {");
+ push(@implContent, "\n v8::Isolate* isolate = args.GetIsolate();");
+ push(@implContent, "\n v8::Local<v8::Object> self = info.Holder();");
+ push(@implContent, "\n struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));");
+
+ my ($handle, $deref) = IdlToArgHandle($attribute->signature->type, "local".ucfirst($attribute->signature->name), "value", $interfaceName);
+
+ push(@implContent, "\n $handle");
+ push(@implContent, "\n privData->nativeObj->${wrapperSetter}(${deref});");
+ push(@implContent, "\n }\n");
+
+ }
+ }
+ }
+}
+
+sub GenerateConditionalUndefReturn
+{
+ my $interface = shift;
+ my $attribute = shift;
+ my $getterExpression = shift;
+
+ return "" if ($attribute->signature->type eq "NamedNodeMap");
+ return "" if ($attribute->signature->type eq "NodeList");
+ return "if (!$getterExpression) return v8::Undefined(isolate);";
+}
+
+sub GenerateConstructor
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $extensions = $interface->extendedAttributes;
+
+ if ($extensions->{'Constructors'}) {
+
+ push(@implContent, "\n void V8${interfaceName}::constructor(const v8::FunctionCallbackInfo<v8::Value>& args) {");
+ push(@implContent, <<END);
+
+ v8::Isolate* isolate = args.GetIsolate();
+ if (!args.IsConstructCall()) {
+ isolate->ThrowException(v8::String::NewFromUtf8(isolate, "Cannot call constructor as function"));
+ return;
+ }
+END
+
+ push(@implContent, "\n ".IdlToWrapperType($interfaceName)."* localInstance = NULL;");
+ # dispatch the actual constructor
+ push(@implContent, "\n if (false) {\n}");
+ my @variants;
+ foreach my $fullCons (@{$extensions->{'Constructors'}}) {
+ push (@variants, $fullCons);
+
+ for (my $i = @{$fullCons}; $i > 0; $i--) {
+ my $variant = @{$fullCons}[$i];
+ if ($variant->{'domSignature::isOptional'}) {
+ my $slice;
+ for (my $j = 0; $j < $i; $j++) {
+ push(@{$slice}, @{$fullCons}[$j]);
+ }
+ push (@variants, $slice);
+ }
+ }
+
+ # sort to put most determinate signatures first
+ @variants = sort {
+ if (@{$b} != @{$a}) {
+ # more arguments are more determinant
+ @{$b} <=> @{$a};
+ } else {
+ my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a});
+ my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b});
+ @bWrap <=> @aWrap;
+ }
+ } @variants;
+ }
+ foreach my $constructor (@variants) {
+ push(@implContent, " else if (args.Length() == " . @{$constructor});
+
+ for (my $i = 0; $i < @{$constructor}; $i++) {
+ my $type = $constructor->[$i]->{'domSignature::type'};
+ AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type));
+ push(@implContent, " &&\n " . IdlToTypeChecker($type, "args[$i]"));
+
+ }
+ push(@implContent, ") {\n");
+ my $constructorArgs;
+ my $constructorSep = "";
+ for (my $i = 0; $i < @{$constructor}; $i++) {
+ my $type = $constructor->[$i]->{'domSignature::type'};
+ my $name = $constructor->[$i]->{'domSignature::name'};
+ my ($handle, $deref) = IdlToArgHandle($type, "local".ucfirst($name), "args[$i]", $interfaceName);
+ $constructorArgs .= ${constructorSep}.${deref};
+ $constructorSep = ", ";
+ push(@implContent, "\n $handle");
+
+ }
+ push(@implContent, "\n localInstance = new ".IdlToWrapperType($interfaceName)."(${constructorArgs});");
+ push(@implContent, "\n\n }");
+ }
+ push(@implContent, "\n");
+
+ push(@implContent, <<END);
+ if (!localInstance) {
+ throw V8Exception("Parameter mismatch while calling constructor for ${interfaceName}");
+ }
+
+ v8::Handle<v8::Function> retCtor = V8${interfaceName}::getTmpl(isolate)->GetFunction();
+ v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance());
+
+ struct V8${interfaceName}::V8${interfaceName}Private* retPrivData = new V8${interfaceName}::V8${interfaceName}Private();
+ retPrivData->nativeObj = localInstance;
+
+ retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));
+ retObj.MakeWeak(0, V8${interfaceName}::jsDestructor);
+
+ args.GetReturnValue().Set(retObj);
+ return;
+ }
+END
+ }
+
+}
+
+sub GenerateImplementationFunctionCallbacks
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $extensions = $interface->extendedAttributes;
+
+
+ # Generate methods for functions.
+ my %generated;
+ foreach my $function (@{$interface->functions}) {
+ my $name = $function->signature->name;
+ my $attrExt = $function->signature->extendedAttributes;
+ my $retType = $function->signature->type;
+ my $wrapperRetType = IdlToWrapperType($retType);
+
+ next if ($attrExt->{'Custom'});
+ next if (exists $generated{"${name}Callback"});
+ $generated{"${name}Callback"} = 1;
+
+ # get all functions with this name
+ my @sameFunctions = grep($_->signature->name eq $name, @{$interface->functions});
+
+ # signature
+ push(@implContent, <<END);
+
+ void V8${interfaceName}::${name}Callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Isolate* isolate = args.GetIsolate();
+END
+
+ # get this
+ push(@implContent, "\n v8::Local<v8::Object> self = args.Holder();");
+ push(@implContent, "\n struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));");
+
+ # establish all variants
+ my @variants;
+ foreach my $functionVar (@sameFunctions) {
+ push (@variants, $functionVar->parameters);
+
+ for (my $i = @{$functionVar->parameters}; $i > 0; $i--) {
+ my $variant = @{$functionVar->parameters}[$i];
+ if ($variant->{'domSignature::isOptional'}) {
+ my $slice;
+ for (my $j = 0; $j < $i; $j++) {
+ push(@{$slice}, @{$functionVar->parameters}[$j]);
+ }
+ push (@variants, $slice);
+ }
+ }
+ }
+
+ # arguments to local handles
+ push(@implContent, "\n if (false) {");
+
+ # sort to put most determinate signatures first
+ @variants = sort {
+ if (@{$b} != @{$a}) {
+ # more arguments are more determinant
+ @{$b} <=> @{$a};
+ } else {
+ my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a});
+ my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b});
+ @bWrap <=> @aWrap;
+ }
+ } @variants;
+
+ foreach my $variant (@variants) {
+ my $parameterIndex = 0;
+ my @argList;
+
+ push(@implContent, "\n } else if (args.Length() == " . @{$variant});
+ for (my $i = 0; $i < @{$variant}; $i++) {
+ my $type = $variant->[$i]->{'domSignature::type'};
+ push(@implContent, " &&\n " . IdlToTypeChecker($type, "args[$i]"));
+ }
+ push(@implContent, ")\n {");
+ foreach my $parameter (@{$variant}) {
+ my $value = "args[$parameterIndex]";
+ my $type = $parameter->type;
+ AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type));
+
+ my ($handle, $deref) = IdlToArgHandle($parameter->type, "local".ucfirst($parameter->name), "args[${parameterIndex}]", $interfaceName);
+ push(@implContent, "\n ${handle}");
+ push(@argList, $deref);
+ $parameterIndex++;
+ }
+
+ # invoke native function with argument handles
+ my $retNativeType = IdlToNativeType($retType);
+ my $wrapperFunctionName = IdlToWrapperFunction($interface, $function);
+ if (IsWrapperType($retType)) {
+ push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n");
+ } elsif ($retNativeType eq "void") {
+ push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n");
+ } else {
+ push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n");
+ }
+
+ # wrap return type if needed
+ if (IsWrapperType($retType)) {
+ AddToImplIncludes("V8".$retType.".h");
+
+ push(@implContent, <<END);
+ v8::Handle<v8::Function> retCtor = V8${retType}::getTmpl(isolate)->GetFunction();
+ v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance());
+
+ struct V8${retType}::V8${retType}Private* retPrivData = new V8${retType}::V8${retType}Private();
+ retPrivData->dom = privData->dom;
+ retPrivData->nativeObj = retVal;
+
+ retObj->SetInternalField(0, V8DOM::toExternal(retPrivData));
+
+ retObj.MakeWeak(0, V8${retType}::jsDestructor);
+ return retObj;
+END
+ } else {
+ my $toHandleString = NativeToHandle($retNativeType, "retVal");
+ push(@implContent, "\n return ${toHandleString};");
+ }
+ }
+ push(@implContent, <<END);
+
+ }
+ throw V8Exception("Parameter mismatch while calling ${name}");
+ return v8::Undefined(isolate);
+ }
+END
+ }
+
+}
+
+sub GenerateImplementation
+{
+ my $object = shift;
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
+ my $v8InterfaceName = "V8$interfaceName";
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $extensions = $interface->extendedAttributes;
+
+ AddToImplIncludes("V8${interfaceName}.h");
+
+ # Find the super descriptor.
+ my $parentClass = "";
+ my $parentClassTemplate = "";
+ foreach (@{$interface->parents}) {
+ my $parent = $_;
+ AddToImplIncludes("V8${parent}.h");
+ $parentClass = "V8" . $parent;
+ last;
+ }
+
+ push(@implContent, "namespace Arabica {\n");
+ push(@implContent, "namespace DOM {\n\n");
+
+ if ($extensions->{'Constructors'}) {
+ GenerateConstructor($interface);
+ }
+
+ GenerateImplementationAttributes($interface);
+ GenerateImplementationFunctionCallbacks($interface);
+
+
+ push(@implContent, <<END);
+ bool V8${interfaceName}::hasInstance(v8::Handle<v8::Value> value) {
+ return getTmpl()->HasInstance(value);
+ }
+
+}
+}
+END
+
+ # We've already added the header for this file in implContentHeader, so remove
+ # it from implIncludes to ensure we don't #include it twice.
+# delete $implIncludes{"${v8InterfaceName}.h"};
+}
+
+sub WriteData
+{
+ my $object = shift;
+ my $interface = shift;
+ my $outputDir = shift;
+ my $outputHeadersDir = shift;
+
+ my $name = $interface->name;
+ my $prefix = FileNamePrefix;
+ my $headerFileName = "$outputHeadersDir/$prefix$name.h";
+ my $implFileName = "$outputDir/$prefix$name.cpp";
+
+ # print "WriteData\n";
+ # print Dumper($interface);
+ # exit();
+
+ # Update a .cpp file if the contents are changed.
+ my $contents = $headerTemplate;
+ $contents .= join "", @implContentHeader;
+
+ my @includes = ();
+ my %implIncludeConditions = ();
+ foreach my $include (keys %implIncludes) {
+ my $condition = $implIncludes{$include};
+ my $checkType = $include;
+ $checkType =~ s/\.h//;
+ next if $codeGenerator->IsSVGAnimatedType($checkType);
+
+ if ($include =~ /wtf/) {
+ $include = "\<$include\>";
+ } else {
+ $include = "\"$include\"";
+ }
+
+ if ($condition eq 1) {
+ push @includes, $include;
+ } else {
+ push @{$implIncludeConditions{$condition}}, $include;
+ }
+ }
+ foreach my $include (sort @includes) {
+ $contents .= "#include $include\n";
+ }
+ foreach my $condition (sort keys %implIncludeConditions) {
+ $contents .= "\n#if " . $codeGenerator->GenerateConditionalStringFromAttributeValue($condition) . "\n";
+ foreach my $include (sort @{$implIncludeConditions{$condition}}) {
+ $contents .= "#include $include\n";
+ }
+ $contents .= "#endif\n";
+ }
+
+ $contents .= "\n";
+ $contents .= join "", @implContentDecls, @implContent;
+ $codeGenerator->UpdateFile($implFileName, $contents);
+
+ %implIncludes = ();
+ @implContentHeader = ();
+ @implContentDecls = ();
+ @implContent = ();
+
+ # Update a .h file if the contents are changed.
+ $contents = join "", @headerContent;
+ $codeGenerator->UpdateFile($headerFileName, $contents);
+
+ @headerContent = ();
+}
+
+sub IdlToV8Type
+{
+ my $idlType = shift;
+ return "v8::Integer" if ($idlType eq "unsigned short");
+ return "v8::Integer" if ($idlType eq "short");
+ return "v8::Integer" if ($idlType eq "unsigned long");
+ return "v8::Integer" if ($idlType eq "long");
+ return "v8::String" if ($idlType eq "DOMString");
+ return "v8::Boolean" if ($idlType eq "boolean");
+ return "v8::Number" if ($idlType eq "double");
+ die($idlType);
+}
+
+sub IdlToNativeType
+{
+ my $idlType = shift;
+
+ return IdlToWrapperType($idlType) if (IsWrapperType($idlType));
+
+ return "std::string" if ($idlType eq "DOMString");
+ return "bool" if ($idlType eq "boolean");
+ return "short" if ($idlType eq "short");
+ return "long" if ($idlType eq "long");
+ return "unsigned short" if ($idlType eq "unsigned short");
+ return "unsigned long" if ($idlType eq "unsigned long");
+ return "void" if ($idlType eq "void");
+ return "char" if ($idlType eq "byte");
+ return "unsigned char" if ($idlType eq "octet");
+ return "double" if ($idlType eq "double");
+ return "float" if ($idlType eq "float");
+ die(${idlType});
+}
+
+sub NativeToHandle
+{
+ my $nativeType = shift;
+ my $nativeName = shift;
+
+ return ("v8::Boolean::New(${nativeName})") if ($nativeType eq "bool");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "double");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "double");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "float");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "short");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "char");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned short");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned long");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned char");
+ return ("v8::Number::New(${nativeName})") if ($nativeType eq "long");
+ return ("v8::String::NewFromUtf8(isolate, ${nativeName}.c_str())") if ($nativeType eq "std::string");
+ return ("v8::Undefined(isolate)") if ($nativeType eq "void");
+
+ die($nativeType);
+}
+
+sub IdlToWrapperType
+{
+ my $idlType = shift;
+ return "Arabica::XPath::XPathValue<std::string>" if ($idlType eq "XPathResult");
+ return "Arabica::XPath::NodeSet<std::string>" if ($idlType eq "NodeSet");
+ return "Arabica::DOM::Node<std::string>" if ($idlType eq "Node");
+ return "Arabica::DOM::Element<std::string>" if ($idlType eq "Element");
+ return "uscxml::Event" if ($idlType eq "SCXMLEvent");
+ return "uscxml::Storage" if ($idlType eq "Storage");
+ return "uscxml::ArrayBuffer" if ($idlType eq "ArrayBuffer");
+ return "uscxml::ArrayBufferView" if ($idlType eq "ArrayBufferView");
+ return "uscxml::Int8Array" if ($idlType eq "Int8Array");
+ return "uscxml::Uint8Array" if ($idlType eq "Uint8Array");
+ return "uscxml::Uint8ClampedArray" if ($idlType eq "Uint8ClampedArray");
+ return "uscxml::Int16Array" if ($idlType eq "Int16Array");
+ return "uscxml::Uint16Array" if ($idlType eq "Uint16Array");
+ return "uscxml::Int32Array" if ($idlType eq "Int32Array");
+ return "uscxml::Uint32Array" if ($idlType eq "Uint32Array");
+ return "uscxml::Float32Array" if ($idlType eq "Float32Array");
+ return "uscxml::Float64Array" if ($idlType eq "Float64Array");
+ return "uscxml::DataView" if ($idlType eq "DataView");
+ return "Arabica::DOM::${idlType}<std::string>";
+}
+
+sub IdlToArgHandle
+{
+ my $type = shift;
+ my $localName = shift;
+ my $paramName = shift;
+ my $thisType = shift;
+
+ return ("v8::String::AsciiValue ${localName}(${paramName});", "*${localName}") if ($type eq "DOMString");
+ return ("unsigned long ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned long");
+ return ("long ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "long");
+ return ("double ${localName} = ${paramName}->ToNumber()->Value();", ${localName}) if ($type eq "double");
+ return ("float ${localName} = ${paramName}->ToNumber()->Value();", ${localName}) if ($type eq "float");
+ return ("unsigned short ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned short");
+ return ("bool ${localName} = ${paramName}->ToBoolean()->BooleanValue();", ${localName}) if ($type eq "boolean");
+ return ("char ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "byte");
+ return ("short ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "short");
+ return ("unsigned char ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "octet");
+ return ("void* ${localName} = v8::External::Unwrap(${paramName}->ToObject()->GetInternalField(0));", ${localName}) if ($type eq "any");
+ return ("std::vector<long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInteger()->Value());\n}", "${localName}") if ($type eq "long[]");
+ return ("std::vector<float> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "float[]");
+ return ("std::vector<double> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "double[]");
+ return ("std::vector<char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "byte[]");
+ return ("std::vector<short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "short[]");
+ return ("std::vector<unsigned short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned short[]");
+ return ("std::vector<unsigned long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned long[]");
+ return ("std::vector<unsigned char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "octet[]");
+
+ if (IsWrapperType($type)) {
+ my $wrapperType = IdlToWrapperType($type);
+ if ($type =~ /.*Array$/ or $type =~ /^ArrayBuffer.*/) {
+ return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "${localName}");
+ }
+
+ return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "*${localName}");
+ }
+
+ print $type."\n";
+ die();
+}
+
+sub IdlToTypeChecker
+{
+ my $idlType = shift;
+ my $attr = shift;
+
+ return $attr."->IsString()" if ($idlType eq "DOMString");
+ return $attr."->IsBoolean()" if ($idlType eq "boolean");
+ return $attr."->IsInt32()" if ($idlType eq "short");
+ return $attr."->IsInt32()" if ($idlType eq "long");
+ return $attr."->IsArray()" if ($idlType eq "long[]");
+ return $attr."->IsUint32()" if ($idlType eq "unsigned short");
+ return $attr."->IsUint32()" if ($idlType eq "unsigned long");
+ return $attr."->IsInt32()" if ($idlType eq "byte");
+ return $attr."->IsUint32()" if ($idlType eq "octet");
+ return $attr."->IsNumber()" if ($idlType eq "double");
+ return $attr."->IsArray()" if ($idlType eq "double[]");
+ return $attr."->IsNumber()" if ($idlType eq "float");
+ return $attr."->IsArray()" if ($idlType eq "float[]");
+ return $attr."->IsArray()" if ($idlType eq "short[]");
+ return $attr."->IsArray()" if ($idlType eq "unsigned short[]");
+ return $attr."->IsArray()" if ($idlType eq "unsigned long[]");
+ return $attr."->IsArray()" if ($idlType eq "byte[]");
+ return $attr."->IsArray()" if ($idlType eq "octet[]");
+ return "true" if ($idlType eq "any");
+
+ return $attr."->IsObject() && V8".$idlType."::hasInstance(".$attr.")" if (IsWrapperType($idlType));
+
+ print $idlType."\n";
+ die();
+
+}
+
+sub IdlToWrapperAttrGetter
+{
+ my $interface = shift;
+ my $attribute = shift;
+
+ return $attribute->signature->name if ($interface->name eq "NodeSet" && $attribute->signature->name eq "size");
+ return $attribute->signature->name if ($interface->name eq "NodeSet" && $attribute->signature->name eq "empty");
+ return "asString" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "stringValue");
+ return "asBool" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "booleanValue");
+ return "asNumber" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "numberValue");
+
+ return "get" . ucfirst($attribute->signature->name);
+}
+
+sub IdlToWrapperFunction
+{
+ my $interface = shift;
+ my $function = shift;
+
+ # if ($interface->name eq "NodeSet" && $function->signature->name eq "toDocumentOrder") {
+ # print Dumper($interface);
+ # print Dumper($function);
+ # }
+
+ return "to_document_order" if ($interface->name eq "NodeSet" && $function->signature->name eq "toDocumentOrder");
+
+ return $function->signature->name;
+
+}
+
+sub IdlToWrapperAttrSetter
+{
+ my $idlAttr = shift;
+ return "set" . ucfirst($idlAttr);
+}
+
+
+sub IsReadonly
+{
+ my $attribute = shift;
+ my $attrExt = $attribute->signature->extendedAttributes;
+ return ($attribute->type =~ /readonly/ || $attrExt->{"V8ReadOnly"}) && !$attrExt->{"Replaceable"};
+}
+
+
+my %non_wrapper_types = (
+ 'CompareHow' => 1,
+ 'DOMObject' => 1,
+ 'DOMString' => 1,
+ 'DOMString[]' => 1,
+ 'DOMTimeStamp' => 1,
+ 'Date' => 1,
+ 'Dictionary' => 1,
+ 'EventListener' => 1,
+ # FIXME: When EventTarget is an interface and not a mixin, fix this so that
+ # EventTarget is treated as a wrapper type.
+ 'EventTarget' => 1,
+ 'IDBKey' => 1,
+ 'JSObject' => 1,
+ 'MediaQueryListListener' => 1,
+ 'NodeFilter' => 1,
+ 'any' => 1,
+ 'boolean' => 1,
+ 'double' => 1,
+ 'float' => 1,
+ 'int' => 1,
+ 'long long' => 1,
+ 'long' => 1,
+ 'long[]' => 1,
+ 'short' => 1,
+ 'short[]' => 1,
+ 'void' => 1,
+ 'byte' => 1,
+ 'byte[]' => 1,
+ 'octet' => 1,
+ 'char' => 1,
+ 'float[]' => 1,
+ 'float' => 1,
+ 'double[]' => 1,
+ 'octet[]' => 1,
+ 'double' => 1,
+ 'unsigned int' => 1,
+ 'unsigned long long' => 1,
+ 'unsigned long' => 1,
+ 'unsigned long[]' => 1,
+ 'unsigned short' => 1,
+ 'unsigned short[]' => 1
+);
+
+sub IsWrapperType
+{
+ my $type = shift;
+ return !($non_wrapper_types{$type});
+}
+
+sub GenerateHeaderContentHeader
+{
+ my $interface = shift;
+ my $v8InterfaceName = "V8" . $interface->name;
+ my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
+
+ my @headerContentHeader = split("\r", $headerTemplate);
+
+ push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
+ push(@headerContentHeader, "\n#ifndef ${v8InterfaceName}" . "_h");
+ push(@headerContentHeader, "\n#define ${v8InterfaceName}" . "_h\n\n");
+ return @headerContentHeader;
+}
+
+1;
diff --git a/contrib/local/compress_and_upload_deps.sh b/contrib/local/compress_and_upload_deps.sh
index 90a398d..6fcffde 100755
--- a/contrib/local/compress_and_upload_deps.sh
+++ b/contrib/local/compress_and_upload_deps.sh
@@ -32,6 +32,7 @@ ssh ${USCXML_PREBUILT_HOST} mkdir -p ${USCXML_PREBUILT_PATH}/${VERSION}
PLATFORMS=`find . -maxdepth 1 -type d -regex ./[^\.].*`
#PLATFORMS="linux-x86_64"
+PLATFORMS="darwin-i386"
for FILE in ${PLATFORMS}; do
PLATFORM=`basename $FILE`
echo $FILE
diff --git a/contrib/src/evws/evws.c b/contrib/src/evws/evws.c
index b39bc03..5dbd8e9 100644
--- a/contrib/src/evws/evws.c
+++ b/contrib/src/evws/evws.c
@@ -66,11 +66,11 @@ struct evws *evws_new(struct event_base *base) {
ret_obj->base = base;
ret_obj->listener = NULL;
- ret_obj->connections.tqh_first = NULL;
- ret_obj->connections.tqh_last = &(ret_obj->connections.tqh_first);
-
- ret_obj->callbacks.tqh_first = NULL;
- ret_obj->callbacks.tqh_last = &(ret_obj->callbacks.tqh_first);
+ (&ret_obj->connections)->tqh_first = NULL;
+ (&ret_obj->connections)->tqh_last = &((&ret_obj->connections)->tqh_first);
+
+ (&ret_obj->callbacks)->tqh_first = NULL;
+ (&ret_obj->callbacks)->tqh_last = &((&ret_obj->callbacks)->tqh_first);
return ret_obj;
}
@@ -89,16 +89,22 @@ evutil_socket_t evws_bind_socket(struct evws * ws, unsigned short port) {
sin.sin_addr.s_addr = htonl(0);
sin.sin_port = htons(port);
- if(!(ws->listener = evconnlistener_new_bind(ws->base, cb_accept, ws, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE, -1, (struct sockaddr*)&sin, sizeof(sin)))) {
+ if(!(ws->listener = evconnlistener_new_bind(ws->base,
+ cb_accept,
+ ws,
+ LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE,
+ -1,
+ (struct sockaddr*)&sin, sizeof(sin)))
+ ) {
return 0;
}
return evconnlistener_get_fd(ws->listener);
}
int evws_set_cb(struct evws * ws, const char * uri, cb_frame_type message_cb, cb_type connect_cb, void * arg) {
- struct evws_cb *ws_cb;
+ struct evws_cb *ws_cb = NULL;
- for (ws_cb = ws->callbacks.tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) {
+ for (ws_cb = (&ws->callbacks)->tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) {
if (strcmp(ws_cb->uri, uri) == 0)
return (-1);
}
@@ -114,9 +120,9 @@ int evws_set_cb(struct evws * ws, const char * uri, cb_frame_type message_cb, cb
// TAILQ_INSERT_TAIL
ws_cb->next.tqe_next = NULL;
- ws_cb->next.tqe_prev = ws->callbacks.tqh_last;
- ws->callbacks.tqh_last = &ws_cb;
- ws->callbacks.tqh_last = &ws_cb->next.tqe_next;
+ ws_cb->next.tqe_prev = (&ws->callbacks)->tqh_last;
+ *(&ws->callbacks)->tqh_last = ws_cb;
+ (&ws->callbacks)->tqh_last = &(ws_cb->next.tqe_next);
return (0);
}
@@ -131,7 +137,7 @@ cb_frame_type evws_set_gencb(struct evws *ws, cb_frame_type cb, void * arg) {
// Broadcast data to all buffers associated with pattern
void evws_broadcast(struct evws *ws, const char *uri, enum evws_opcode opcode, const char *data, uint64_t length) {
struct evws_connection *ws_connection;
- for (ws_connection = ws->connections.tqh_first; ws_connection; ws_connection = ws_connection->next.tqe_next) {
+ for ((ws_connection) = (&ws->connections)->tqh_first; ws_connection; ws_connection = ws_connection->next.tqe_next) {
if (strcmp(ws_connection->uri, uri) == 0)
evws_send_data(ws_connection, opcode, data, length);
}
@@ -140,15 +146,12 @@ void evws_broadcast(struct evws *ws, const char *uri, enum evws_opcode opcode, c
// Error callback
static void cb_error(struct bufferevent *bev, short what, void *ctx) {
struct evws_connection *conn = ctx;
-
- //TAILQ_REMOVE
- if (conn->next.tqe_next != NULL)
+ if (conn->next.tqe_next != NULL) {
conn->next.tqe_next->next.tqe_prev = conn->next.tqe_prev;
- else {
- conn->ws->connections.tqh_last = conn->next.tqe_prev;
+ } else {
+ (&(conn->ws->connections))->tqh_last = conn->next.tqe_prev;
}
- conn->next.tqe_prev = &conn->next.tqe_next;
-
+ *(conn)->next.tqe_prev = conn->next.tqe_next;
evws_connection_free(conn);
}
@@ -224,11 +227,12 @@ void cb_read_handshake(struct bufferevent *bev, void *arg) {
origin = strdup(svalue);
}
header = evws_header_new(skey, svalue);
- //TAILQ_INSERT_TAIL
+
+ // TAILQ_INSERT_TAIL
header->next.tqe_next = NULL;
- header->next.tqe_prev = ws_conn->headers.tqh_last;
- ws_conn->headers.tqh_last = &header;
- ws_conn->headers.tqh_last = &header->next.tqe_next;
+ header->next.tqe_prev = (&ws_conn->headers)->tqh_last;
+ *(&ws_conn->headers)->tqh_last = header;
+ (&ws_conn->headers)->tqh_last = &(header->next.tqe_next);
free(line);
}
@@ -236,6 +240,9 @@ void cb_read_handshake(struct bufferevent *bev, void *arg) {
break;
};
+ if (key == NULL)
+ return;
+
// -- SHA1
SHA1Reset(&sha1);
@@ -280,24 +287,24 @@ void cb_read_handshake(struct bufferevent *bev, void *arg) {
"\r\n",
chksumBase64
);
- bufferevent_setcb(ws_conn->bufev, cb_read_frame, NULL, cb_error, ws_conn);
-
- //TAILQ_INSERT_TAIL(&(ws_conn->ws->connections), ws_conn, next);
+ bufferevent_setcb(ws_conn->bufev, cb_read_frame, ((void*)0), cb_error, ws_conn);
+
ws_conn->next.tqe_next = NULL;
- ws_conn->next.tqe_prev = ws_conn->ws->connections.tqh_last;
- ws_conn->ws->connections.tqh_last = &ws_conn;
- ws_conn->ws->connections.tqh_last = &ws_conn->next.tqe_next;
+ ws_conn->next.tqe_prev = (&(ws_conn->ws->connections))->tqh_last;
+ *(&(ws_conn->ws->connections))->tqh_last = ws_conn;
+ (&(ws_conn->ws->connections))->tqh_last = &(ws_conn->next.tqe_next);
{
struct evws_cb *ws_cb;
- for (ws_cb = ws_conn->ws->callbacks.tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) {
+ for (ws_cb = ((&ws_conn->ws->callbacks))->tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) {
if (strcmp(ws_cb->uri, ws_conn->uri) == 0) {
- if(ws_cb->conn_cb != NULL)
- ws_cb->conn_cb(ws_conn, NULL, 0, ws_cb->cb_arg);
+ if(ws_cb->conn_cb != ((void*)0))
+ ws_cb->conn_cb(ws_conn, ((void*)0), 0, ws_cb->cb_arg);
return;
}
}
}
+
}
int evws_parse_header_line(char *line, char **skey, char **svalue)
@@ -317,7 +324,7 @@ void cb_read_frame(struct bufferevent *bev, void *arg)
{
struct evws_connection *conn = arg;
struct evws *ws = conn->ws;
- char readbuf[1024];
+ char readbuf[2048]; // make sure a MTU fits
int size = 0;
struct evbuffer *buffer = bufferevent_get_input(bev);
while ((size = evbuffer_remove(buffer, readbuf, sizeof(readbuf))) > 0) {
@@ -414,11 +421,12 @@ NEXT_FRAME:
if (conn->frame->payload_read == conn->frame->size) {
// done reading this frame - invoke callbacks
struct evws_cb *ws_cb;
- for (ws_cb = ws->callbacks.tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) {
+ // TAILQ_FOREACH
+ for (ws_cb = ((&ws->callbacks))->tqh_first; ws_cb; ws_cb = (ws_cb->next.tqe_next)) {
if (strcmp(ws_cb->uri, conn->uri) == 0) {
- if(ws_cb->msg_cb != NULL)
+ if(ws_cb->msg_cb != ((void*)0))
ws_cb->msg_cb(conn, conn->frame, ws_cb->cb_arg);
- continue;
+ return;
}
}
ws->gencb(conn, conn->frame, ws->gencb_arg);
@@ -484,27 +492,28 @@ struct evws_connection* evws_connection_new(struct evws *ws, evutil_socket_t fd)
struct evws_connection* conn = calloc(1, sizeof(struct evws_connection));
conn->ws = ws;
conn->fd = fd;
- conn->uri = NULL;
-
+ conn->uri = ((void*)0);
+
conn->bufev = bufferevent_socket_new(ws->base, fd, BEV_OPT_CLOSE_ON_FREE);
conn->state = 0;
- conn->frame = NULL;
+ conn->frame = ((void*)0);
+
+ (&conn->headers)->tqh_first = NULL;
+ (&conn->headers)->tqh_last = &(((&conn->headers))->tqh_first);
- conn->headers.tqh_first = NULL;
- conn->headers.tqh_last = &(conn->headers.tqh_first);
-
return conn;
}
void evws_connection_free(struct evws_connection *conn) {
struct evws_header *header;
bufferevent_free(conn->bufev);
- if(conn->uri != NULL)
+ if(conn->uri != ((void*)0))
free(conn->uri);
-
- for (header = conn->headers.tqh_first; header; header = header->next.tqe_next) {
+
+ for (header = (&conn->headers)->tqh_first; header; header = header->next.tqe_next) {
evws_header_free(header);
}
+
free(conn);
}
@@ -530,19 +539,18 @@ struct evws_header *evws_header_new(char *key, char *value)
void evws_header_free(struct evws_header *header) {
if(header->key != NULL)
free(header->key);
- // @Note: segfault when freeing value, some strange value
if(header->value != NULL)
free(header->value);
free(header);
}
char *evws_find_header(const struct wsheadersq *q, const char *key) {
- struct evws_header *header;
- char * ret = NULL;
- for (header = q->tqh_first; header; header = header->next.tqe_next) {
-
- if(strcmp(header->key, key) == 0) {
- ret = header->value;
+ struct evws_header *hdr;
+ char * ret = ((void*)0);
+
+ for (hdr = q->tqh_first; hdr; hdr = hdr->next.tqe_next) {
+ if(strcmp(hdr->key, key) == 0) {
+ ret = hdr->value;
break;
}
}
diff --git a/docs/Ubuntu-LTS.md b/docs/Ubuntu-LTS.md
index 4dbc0e2..df687ab 100644
--- a/docs/Ubuntu-LTS.md
+++ b/docs/Ubuntu-LTS.md
@@ -17,6 +17,10 @@ $ ./configure --disable-render-text-node --disable-script-node-javascript --disa
$ sudo make install
$ cd ..
+for mavericks:
+PNG_CFLAGS="-I/opt/local/include" PNG_LIBS="-L/opt/local/lib" XML_CFLAGS="-I`xcrun --show-sdk-path`/usr/include/libxml2" XML_LIBS="-L`xcrun --show-sdk-path`/usr/lib" CPPFLAGS="--sysroot=`xcrun --show-sdk-path` -I/opt/local/include -I`xcrun --show-sdk-path`/usr/include/libxml2" LDFLAGS="--sysroot=`xcrun --show-sdk-path` -L/opt/local/lib -lboost_system-mt -lxml2 -lpng" ./configure --disable-render-text-node --disable-script-node-javascript --disable-script-node-java --disable-gl-renderer --disable-xembed --disable-player --disable-examples --disable-mozilla-plugin
+
+
$ sudo apt-get install git
$ git clone https://github.com/openscenegraph/osg
$ cd osg
diff --git a/src/bindings/swig/php/uscxmlNativePHP.php b/src/bindings/swig/php/uscxmlNativePHP.php
index d7bb3d0..3aba5be 100644
--- a/src/bindings/swig/php/uscxmlNativePHP.php
+++ b/src/bindings/swig/php/uscxmlNativePHP.php
@@ -2,12 +2,12 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.9
- *
- * This file is not intended to be easily readable and contains a number of
+ * Version 2.0.11
+ *
+ * This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG
- * interface file instead.
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
* ----------------------------------------------------------------------------- */
// Try to load our extension if it's not already loaded.
@@ -1030,13 +1030,7 @@ class Interpreter {
}
static function tokenizeIdRefs($idRefs) {
- $r=Interpreter_tokenizeIdRefs($idRefs);
- if (is_resource($r)) {
- $c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));
- if (class_exists($c)) return new $c($r);
- return new StringVector($r);
- }
- return $r;
+ return Interpreter_tokenizeIdRefs($idRefs);
}
static function spaceNormalize($text) {
diff --git a/src/uscxml/Convenience.h b/src/uscxml/Convenience.h
index 9f4c1a1..0177476 100644
--- a/src/uscxml/Convenience.h
+++ b/src/uscxml/Convenience.h
@@ -49,7 +49,7 @@ inline bool isNumeric( const char* pszInput, int nNumberBase) {
}
inline bool iequals(const std::string& a, const std::string& b) {
- // this impementation beats boost::iequals 2700ms vs 2100ms for test-performance.scxml
+ // this impementation beats boost::iequals 2700ms vs 2100ms for test-performance.scxml - we don't care for non-ascii yet
unsigned int size = a.size();
if (b.size() != size)
return false;
@@ -59,6 +59,16 @@ inline bool iequals(const std::string& a, const std::string& b) {
return true;
}
+inline bool equals(const std::string& a, const std::string& b) {
+ unsigned int size = a.size();
+ if (b.size() != size)
+ return false;
+ for (unsigned int i = 0; i < size; ++i)
+ if (a[i] != b[i])
+ return false;
+ return true;
+}
+
// see http://www.cplusplus.com/forum/general/27544/
// Little-endian operating systems:
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 1314986..dfd9311 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -912,11 +912,11 @@ void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) {
// namelist
if (HAS_ATTR(element, "namelist")) {
if (_dataModel) {
- std::vector<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
- for (int i = 0; i < names.size(); i++) {
- Data namelistValue = _dataModel.getStringAsData(names[i]);
- sendReq.namelist[names[i]] = namelistValue;
- sendReq.data.compound[names[i]] = namelistValue;
+ std::list<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
+ for (std::list<std::string>::const_iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) {
+ Data namelistValue = _dataModel.getStringAsData(*nameIter);
+ sendReq.namelist[*nameIter] = namelistValue;
+ sendReq.data.compound[*nameIter] = namelistValue;
}
} else {
LOG(ERROR) << "Namelist attribute at send requires datamodel to be defined";
@@ -1054,9 +1054,9 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) {
// namelist
if (HAS_ATTR(element, "namelist")) {
- std::vector<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
- for (int i = 0; i < names.size(); i++) {
- invokeReq.namelist[names[i]] = _dataModel.evalAsString(names[i]);
+ std::list<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
+ for (std::list<std::string>::const_iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) {
+ invokeReq.namelist[*nameIter] = _dataModel.evalAsString(*nameIter);
}
}
@@ -1235,10 +1235,11 @@ bool InterpreterImpl::hasConditionMatch(const Arabica::DOM::Node<std::string>& c
void InterpreterImpl::executeContent(const NodeList<std::string>& content, bool rethrow) {
for (unsigned int i = 0; i < content.getLength(); i++) {
- if (content.item(i).getNodeType() != Node_base::ELEMENT_NODE)
+ const Arabica::DOM::Node<std::string>& node = content.item(i);
+ if (node.getNodeType() != Node_base::ELEMENT_NODE)
continue;
try {
- executeContent(content.item(i), true);
+ executeContent(node, true);
}
CATCH_AND_DISTRIBUTE2("Error when executing content", content.item(i));
}
@@ -1246,10 +1247,11 @@ void InterpreterImpl::executeContent(const NodeList<std::string>& content, bool
void InterpreterImpl::executeContent(const NodeSet<std::string>& content, bool rethrow) {
for (unsigned int i = 0; i < content.size(); i++) {
- if (content[i].getNodeType() != Node_base::ELEMENT_NODE)
+ const Arabica::DOM::Node<std::string>& node = content[i];
+ if (node.getNodeType() != Node_base::ELEMENT_NODE)
continue;
try {
- executeContent(content[i], true);
+ executeContent(node, true);
}
CATCH_AND_DISTRIBUTE2("Error when executing content", content[i]);
}
@@ -1598,9 +1600,9 @@ NEXT_ANCESTOR:
return ancestor;
}
-Arabica::XPath::NodeSet<std::string> InterpreterImpl::getStates(const std::vector<std::string>& stateIds) {
+Arabica::XPath::NodeSet<std::string> InterpreterImpl::getStates(const std::list<std::string>& stateIds) {
Arabica::XPath::NodeSet<std::string> states;
- std::vector<std::string>::const_iterator tokenIter = stateIds.begin();
+ std::list<std::string>::const_iterator tokenIter = stateIds.begin();
while(tokenIter != stateIds.end()) {
states.push_back(getState(*tokenIter));
tokenIter++;
@@ -1717,18 +1719,32 @@ NodeSet<std::string> InterpreterImpl::getTargetStates(const Arabica::DOM::Node<s
}
std::string targetId = ((Arabica::DOM::Element<std::string>)transition).getAttribute("target");
-
- std::vector<std::string> targetIds = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "target"));
- for (int i = 0; i < targetIds.size(); i++) {
- Arabica::DOM::Node<std::string> state = getState(targetIds[i]);
+ std::list<std::string> targetIds = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "target"));
+ for (std::list<std::string>::const_iterator targetIter = targetIds.begin(); targetIter != targetIds.end(); targetIter++) {
+ Arabica::DOM::Node<std::string> state = getState(*targetIter);
assert(HAS_ATTR(state, "id"));
targetStates.push_back(state);
}
return targetStates;
}
-std::vector<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRefs) {
- std::vector<std::string> ids;
+std::list<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRefs) {
+ std::list<std::string> ids;
+
+ // appr. 3x faster than stringstream
+ size_t start = 0;
+ for (int i = 0; i < idRefs.size(); i++) {
+ if (isspace(idRefs[i])) {
+ if (i > 0 && start < i - 1) {
+ ids.push_back(idRefs.substr(start, i - start));
+ }
+ while(isspace(idRefs[++i])); // skip whitespaces
+ start = i;
+ } else if (i + 1 == idRefs.size()) {
+ ids.push_back(idRefs.substr(start, i + 1 - start));
+ }
+ }
+
#if 0
if (idRefs.length() > 0) {
@@ -1740,11 +1756,13 @@ std::vector<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRe
}
#endif
+#if 0
// this version is somewhat fatser than the one above
std::stringstream ss (idRefs);
std::string item;
while(ss >> item)
ids.push_back(item);
+#endif
return ids;
}
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 5cc9053..d2e63e9 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -236,7 +236,7 @@ public:
}
Arabica::DOM::Node<std::string> getState(const std::string& stateId);
- Arabica::XPath::NodeSet<std::string> getStates(const std::vector<std::string>& stateIds);
+ Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds);
Arabica::DOM::Document<std::string>& getDocument() {
return _document;
@@ -286,7 +286,7 @@ public:
static bool isCompound(const Arabica::DOM::Node<std::string>& state);
static bool isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2);
- static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs);
+ static std::list<std::string> tokenizeIdRefs(const std::string& idRefs);
static std::string spaceNormalize(const std::string& text);
bool isInEmbeddedDocument(const Arabica::DOM::Node<std::string>& node);
@@ -540,7 +540,7 @@ public:
Arabica::DOM::Node<std::string> getState(const std::string& stateId) {
return _impl->getState(stateId);
}
- Arabica::XPath::NodeSet<std::string> getStates(const std::vector<std::string>& stateIds) {
+ Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds) {
return _impl->getStates(stateIds);
}
@@ -628,7 +628,7 @@ public:
return InterpreterImpl::isDescendant(s1, s2);
}
- static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs) {
+ static std::list<std::string> tokenizeIdRefs(const std::string& idRefs) {
return InterpreterImpl::tokenizeIdRefs(idRefs);
}
static std::string spaceNormalize(const std::string& text) {
diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp
index c79e08a..26cf640 100644
--- a/src/uscxml/Message.cpp
+++ b/src/uscxml/Message.cpp
@@ -61,6 +61,64 @@ Blob::Blob(void* _data, size_t _size, const std::string& _mimeType, bool adopt)
size = _size;
}
+#if 0
+// there used to work base64 encoded images in a browser - can't check extensively just now
+static const std::string base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+std::string Blob::base64() {
+
+ int in_len = size;
+ char const* bytes_to_encode = data;
+
+ std::string ret;
+ int i = 0;
+ int j = 0;
+ unsigned char char_array_3[3];
+ unsigned char char_array_4[4];
+
+ while (in_len--) {
+ char_array_3[i++] = *(bytes_to_encode++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for(i = 0; (i <4) ; i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for(j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for (j = 0; (j < i + 1); j++)
+ ret += base64_chars[char_array_4[j]];
+
+ while((i++ < 3))
+ ret += '=';
+
+ }
+
+ return ret;
+
+}
+#else
+std::string Blob::base64() {
+ return base64Encode((char* const)data, size);
+}
+#endif
+
Data::Data(const char* _data, size_t _size, const std::string& mimeType, bool adopt) {
binary = boost::shared_ptr<Blob>(new Blob((void*)_data, _size, mimeType, adopt));
}
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index 5de9a56..5f6703e 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -55,9 +55,7 @@ public:
return uscxml::md5(data, size);
}
- std::string base64() {
- return base64Encode((char* const)data, size);
- }
+ std::string base64();
Blob* fromBase64(const std::string base64) {
std::string decoded = base64Decode(base64);
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index c9c00ef..772ad96 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -467,9 +467,8 @@ bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition,
return false;
}
- std::vector<std::string> eventNames = tokenizeIdRefs(eventName);
-
- std::vector<std::string>::iterator eventIter = eventNames.begin();
+ std::list<std::string> eventNames = tokenizeIdRefs(eventName);
+ std::list<std::string>::iterator eventIter = eventNames.begin();
while(eventIter != eventNames.end()) {
if(nameMatch(*eventIter, event) && hasConditionMatch(transition)) {
return true;
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index 947c0c2..9827b91 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -400,9 +400,10 @@ Data JSCDataModel::getValueAsData(const JSValueRef value) {
if (!isNumeric(property.c_str(), 10))
isArray = false;
propertySet.insert(property);
- JSStringRelease(stringValue);
+ //JSStringRelease(stringValue); // JSPropertyNameArrayRelease does the job it seems
free(buf);
}
+ JSPropertyNameArrayRelease(properties);
std::set<std::string>::iterator propIter = propertySet.begin();
while(propIter != propertySet.end()) {
if (isArray) {
@@ -537,14 +538,14 @@ void JSCDataModel::assign(const Element<std::string>& assignElem,
throw Event("error.execution", Event::PLATFORM);
// flags on attribute are ignored?
- if (key.compare("_sessionid") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_sessionid") == 0) // test 322
+ throw Event("error.execution", Event::PLATFORM);
if (key.compare("_name") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
- if (key.compare("_ioprocessors") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
+ throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_ioprocessors") == 0) // test 326
+ throw Event("error.execution", Event::PLATFORM);
if (key.compare("_invokers") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
+ throw Event("error.execution", Event::PLATFORM);
if (HAS_ATTR(assignElem, "expr")) {
evalAsValue(key + " = " + ATTR(assignElem, "expr"));
diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp
index 358c819..6b24cd8 100644
--- a/src/uscxml/server/HTTPServer.cpp
+++ b/src/uscxml/server/HTTPServer.cpp
@@ -92,17 +92,24 @@ HTTPServer::HTTPServer(unsigned short port, unsigned short wsPort, SSLConfig* ss
evhttp_set_allowed_methods(_http, allowedMethods); // allow all methods
- if (_port > 0)
+ if (_port > 0) {
_httpHandle = evhttp_bind_socket_with_handle(_http, INADDR_ANY, _port);
- if (_httpHandle)
- LOG(INFO) << "HTTP server listening on tcp/" << _port;
+ if (_httpHandle) {
+ LOG(INFO) << "HTTP server listening on tcp/" << _port;
+ } else {
+ LOG(ERROR) << "HTTP server cannot bind to tcp/" << _wsPort;
+ }
+ }
_wsPort = wsPort;
- if (_wsPort > 0)
+ if (_wsPort > 0) {
_wsHandle = evws_bind_socket(_evws, _wsPort);
- if (_wsHandle)
- LOG(INFO) << "WebSocket server listening on tcp/" << _wsPort;
-
+ if (_wsHandle) {
+ LOG(INFO) << "WebSocket server listening on tcp/" << _wsPort;
+ } else {
+ LOG(ERROR) << "WebSocket server cannot bind to tcp/" << _wsPort;
+ }
+ }
#if (defined EVENT_SSL_FOUND && defined OPENSSL_FOUND && defined OPENSSL_HAS_ELIPTIC_CURVES)
_sslHandle = NULL;
_https = NULL;
@@ -136,11 +143,15 @@ HTTPServer::HTTPServer(unsigned short port, unsigned short wsPort, SSLConfig* ss
evhttp_set_bevcb(_https, sslBufferEventCallback, ctx);
evhttp_set_gencb(_https, sslGeneralBufferEventCallback, NULL);
- if (_sslPort > 0)
+ if (_sslPort > 0) {
_sslHandle = evhttp_bind_socket_with_handle(_https, INADDR_ANY, _sslPort);
- if (_sslHandle)
- LOG(INFO) << "HTTPS server listening on tcp/" << _wsPort;
+ if (_sslHandle) {
+ LOG(INFO) << "HTTPS server listening on tcp/" << _wsPort;
+ } else {
+ LOG(ERROR) << "HTTPS server cannot bind to tcp/" << _wsPort;
+ }
+ }
}
#endif
diff --git a/src/uscxml/util/Base64.h b/src/uscxml/util/Base64.h
index 7dfc83c..a07d24e 100644
--- a/src/uscxml/util/Base64.h
+++ b/src/uscxml/util/Base64.h
@@ -36,9 +36,7 @@ extern "C" {
} base64_decodestate;
USCXML_API void base64_init_decodestate(base64_decodestate* state_in);
-
USCXML_API int base64_decode_value(char value_in);
-
USCXML_API int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
/// ENDCODE
@@ -54,11 +52,8 @@ extern "C" {
} base64_encodestate;
USCXML_API void base64_init_encodestate(base64_encodestate* state_in);
-
USCXML_API char base64_encode_value(char value_in);
-
USCXML_API int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
-
USCXML_API int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#ifdef __cplusplus
diff --git a/src/uscxml/util/Base64.hpp b/src/uscxml/util/Base64.hpp
index a106a12..e3cbe03 100644
--- a/src/uscxml/util/Base64.hpp
+++ b/src/uscxml/util/Base64.hpp
@@ -12,7 +12,7 @@ extern "C" {
namespace uscxml {
-USCXML_API inline std::string base64Encode(const char* data, unsigned int len) {
+USCXML_API inline std::string base64Encode(const char* data, unsigned int len, bool withBlockEnd = true) {
base64_encodestate* ctx = (base64_encodestate*)malloc(sizeof(base64_encodestate));
base64_init_encodestate(ctx);
@@ -22,10 +22,15 @@ USCXML_API inline std::string base64Encode(const char* data, unsigned int len) {
* be approximated with this formula:
*/
+ int written = 0;
char* out = (char*)malloc(len * 1.4 + 814);
- base64_encode_block(data, len, out, ctx);
+ written += base64_encode_block(data, len, out, ctx);
+ if (withBlockEnd) {
+ written += base64_encode_blockend(out + written, ctx);
+ written--; // drop the newline
+ }
+ std::string result(out, written);
free(ctx);
- std::string result(out);
free(out);
return result;
}
@@ -42,5 +47,8 @@ USCXML_API inline std::string base64Decode(const std::string& data) {
return result;
}
+// USCXML_API std::string base64Decode(const std::string& data);
+// USCXML_API std::string base64Encode(const char* data, unsigned int len);
+
}
#endif /* end of include guard: BASE64_H_5FKG12HF */
diff --git a/src/uscxml/util/MD5.c b/src/uscxml/util/MD5.c
index 1bf05e4..f553c9c 100644
--- a/src/uscxml/util/MD5.c
+++ b/src/uscxml/util/MD5.c
@@ -52,6 +52,7 @@
*/
#include "MD5.h"
+#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index eff801c..4c906fd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -35,6 +35,11 @@ if (OPENSCENEGRAPH_FOUND AND OFF)
set_target_properties(test-osg PROPERTIES FOLDER "Tests")
endif()
+add_executable(test-base64 src/test-base64.cpp)
+target_link_libraries(test-base64 uscxml)
+add_test(test-base64 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-base64)
+set_target_properties(test-base64 PROPERTIES FOLDER "Tests")
+
add_executable(test-eventdelay src/test-eventdelay.cpp)
target_link_libraries(test-eventdelay uscxml)
add_test(test-eventdelay ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-eventdelay)
@@ -130,11 +135,11 @@ foreach( W3C_TEST ${W3C_TESTS} )
string(REGEX MATCH "[^//]+/[^//]+.scxml" TEST_NAME ${W3C_TEST})
#message("TEST_NAME: ${TEST_NAME}")
if (NOT TEST_NAME MATCHES ".*sub.*")
- if (RUN_W3C_ECMA_TESTS AND TEST_NAME MATCHES "^ecma\\/.*")
+ if (BUILD_TESTS_W3C_ECMA AND TEST_NAME MATCHES "^ecma\\/.*")
add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST})
set_tests_properties(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "TEST FAILED")
endif()
- if (RUN_W3C_XPATH_TESTS AND TEST_NAME MATCHES "^xpath\\/.*")
+ if (BUILD_TESTS_W3C_XPATH AND TEST_NAME MATCHES "^xpath\\/.*")
add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-w3c ${W3C_TEST})
set_tests_properties(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION "TEST FAILED")
endif()
diff --git a/test/samples/uscxml/test-performance.scxml b/test/samples/uscxml/test-performance.scxml
index 4d2d4c4..d8e75da 100644
--- a/test/samples/uscxml/test-performance.scxml
+++ b/test/samples/uscxml/test-performance.scxml
@@ -1,6 +1,6 @@
<scxml datamodel="ecmascript">
<datamodel>
- <data id="iterations">10000</data>
+ <data id="iterations">100000</data>
</datamodel>
<state id="start">
<transition target="loop" />
diff --git a/test/samples/w3c/update-txml.sh b/test/samples/w3c/update-txml.sh
index 3c7255b..074318d 100755
--- a/test/samples/w3c/update-txml.sh
+++ b/test/samples/w3c/update-txml.sh
@@ -1,7 +1,7 @@
#!/bin/bash
wget -rl1 -Atxml,txt,xsl http://www.w3.org/Voice/2013/scxml-irp/
-find ./www.w3.org -name *.txml -exec cp {} ./txml \;
-find ./www.w3.org -name *.txt -exec cp {} ./txml \;
-find ./www.w3.org -name *.xsl -exec cp {} . \;
+find ./www.w3.org -name "*.txml" -exec cp {} ./txml \;
+find ./www.w3.org -name "*.txt" -exec cp {} ./txml \;
+find ./www.w3.org -name "*.xsl" -exec cp {} . \;
rm -rf www.w3.org \ No newline at end of file
diff --git a/test/src/test-base64.cpp b/test/src/test-base64.cpp
new file mode 100644
index 0000000..1267b7b
--- /dev/null
+++ b/test/src/test-base64.cpp
@@ -0,0 +1,18 @@
+#include "uscxml/util/Base64.hpp"
+#include <assert.h>
+
+#define SOURCE_LEN 10
+
+int main(int argc, char** argv) {
+ std::string data;
+ std::string base64CPP;
+ std::string base64C;
+
+ char buffer[SOURCE_LEN];
+ for (int i = 0; i < SOURCE_LEN; i++) {
+ buffer[i] = (char)55;
+ }
+
+ base64C = uscxml::base64Encode(buffer, SOURCE_LEN);
+
+} \ No newline at end of file
diff --git a/test/src/test-predicates.cpp b/test/src/test-predicates.cpp
index b3e46fe..ed155b4 100644
--- a/test/src/test-predicates.cpp
+++ b/test/src/test-predicates.cpp
@@ -43,12 +43,66 @@ int main(int argc, char** argv) {
assert(Interpreter::isDescendant(compoundChild1, compoundState));
- std::string idrefs("id1 \nid2 \tid3");
- std::vector<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
- assert(tokenizedIdrefs.size() == 3);
- assert(tokenizedIdrefs[0].compare("id1") == 0);
- assert(tokenizedIdrefs[1].compare("id2") == 0);
- assert(tokenizedIdrefs[2].compare("id3") == 0);
+ {
+ std::string idrefs("id1");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 1);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ }
+
+ {
+ std::string idrefs(" id1");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 1);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ }
+
+ {
+ std::string idrefs(" id1 ");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 1);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ }
+
+ {
+ std::string idrefs(" \tid1\n ");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 1);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ }
+
+ {
+ std::string idrefs("id1 id2 id3");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 3);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ tokenizedIdrefs.pop_front();
+ assert(tokenizedIdrefs.front().compare("id2") == 0);
+ tokenizedIdrefs.pop_front();
+ assert(tokenizedIdrefs.front().compare("id3") == 0);
+ }
+
+ {
+ std::string idrefs("\t id1 \nid2\n\n id3\t");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 3);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ tokenizedIdrefs.pop_front();
+ assert(tokenizedIdrefs.front().compare("id2") == 0);
+ tokenizedIdrefs.pop_front();
+ assert(tokenizedIdrefs.front().compare("id3") == 0);
+ }
+
+ {
+ std::string idrefs("id1 \nid2 \tid3");
+ std::list<std::string> tokenizedIdrefs = Interpreter::tokenizeIdRefs(idrefs);
+ assert(tokenizedIdrefs.size() == 3);
+ assert(tokenizedIdrefs.front().compare("id1") == 0);
+ tokenizedIdrefs.pop_front();
+ assert(tokenizedIdrefs.front().compare("id2") == 0);
+ tokenizedIdrefs.pop_front();
+ assert(tokenizedIdrefs.front().compare("id3") == 0);
+ }
std::string transEvents;
transEvents = "error";