Merge "Fixed IOT-110--Crash on destruction"
authorsudarshan prasad <sudarshan.prasad@intel.com>
Sat, 13 Dec 2014 01:20:04 +0000 (17:20 -0800)
committerGerrit Code Review <gerrit@oicreview.vlan14.01.org>
Sat, 13 Dec 2014 01:20:04 +0000 (17:20 -0800)
87 files changed:
.gitignore
Readme.scons.txt [new file with mode: 0644]
SConstruct [new file with mode: 0644]
arduino.scons [new file with mode: 0644]
auto_build.sh [moved from resource/auto_build.sh with 51% similarity]
build_common/SConscript [new file with mode: 0644]
build_common/android/SConscript [moved from resource/build_common/android/SConscript with 76% similarity]
build_common/android/jni/Android.mk [moved from resource/build_common/android/jni/Android.mk with 93% similarity]
build_common/arduino/SConscript [new file with mode: 0755]
build_common/darwin/SConscript [new file with mode: 0644]
build_common/ios/SConscript [new file with mode: 0644]
build_common/linux/SConscript [new file with mode: 0644]
build_common/windows/SConscript [new file with mode: 0644]
extra_options.scons [new file with mode: 0644]
resource/Readme.scons.txt [deleted file]
resource/SConscript [new file with mode: 0644]
resource/SConstruct [deleted file]
resource/arduino.scons [deleted file]
resource/build_common/SConscript [deleted file]
resource/build_common/arduino/SConscript [deleted file]
resource/build_common/darwin/SConscript [deleted file]
resource/build_common/ios/SConscript [deleted file]
resource/build_common/linux/SConscript [deleted file]
resource/build_common/windows/SConscript [deleted file]
resource/csdk/SConscript
resource/csdk/libcoap-4.1.1/SConscript
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript [new file with mode: 0644]
resource/examples/SConscript
resource/examples/ocicuc/SConscript
resource/oc_logger/SConscript
resource/oc_logger/examples/SConscript [new file with mode: 0644]
resource/src/SConscript
resource/third_party_libs.scons
scons_script_how_to.txt [new file with mode: 0644]
service/SConscript [new file with mode: 0644]
service/notification-manager/SConscript [new file with mode: 0644]
service/notification-manager/SampleApp/SConscript [new file with mode: 0644]
service/notification-manager/SampleApp/arduino/SConscript [new file with mode: 0644]
service/notification-manager/SampleApp/linux/SConscript [new file with mode: 0644]
service/protocol-plugin/SConscript [new file with mode: 0644]
service/protocol-plugin/build/linux/Makefile
service/protocol-plugin/lib/cpluff/SConscript [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp [new file with mode: 0644]
service/protocol-plugin/plugin-manager/SConscript [new file with mode: 0644]
service/protocol-plugin/plugin-manager/build/linux/Makefile
service/protocol-plugin/plugin-manager/src/Config.cpp [new file with mode: 0644]
service/protocol-plugin/plugin-manager/src/Config.h [new file with mode: 0644]
service/protocol-plugin/plugin-manager/src/CpluffAdapter.cpp
service/protocol-plugin/plugin-manager/src/CpluffAdapter.h
service/protocol-plugin/plugin-manager/src/FelixAdapter.cpp
service/protocol-plugin/plugin-manager/src/FelixAdapter.h
service/protocol-plugin/plugin-manager/src/Plugin.cpp
service/protocol-plugin/plugin-manager/src/Plugin.h
service/protocol-plugin/plugin-manager/src/PluginManager.cpp
service/protocol-plugin/plugin-manager/src/PluginManager.h
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.cpp
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.h
service/protocol-plugin/plugins/SConscript [new file with mode: 0644]
service/protocol-plugin/plugins/mqtt-fan/build/linux/Makefile
service/protocol-plugin/plugins/mqtt-fan/lib/Makefile
service/protocol-plugin/plugins/mqtt-fan/lib/SConscript [new file with mode: 0644]
service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript [new file with mode: 0644]
service/protocol-plugin/plugins/mqtt-fan/lib/python/Makefile
service/protocol-plugin/plugins/mqtt-fan/src/fanserver.cpp
service/protocol-plugin/plugins/mqtt-light/build/linux/Makefile
service/protocol-plugin/plugins/mqtt-light/lib/Makefile
service/protocol-plugin/plugins/mqtt-light/lib/python/Makefile
service/protocol-plugin/plugins/mqtt-light/src/lightserver.cpp
service/protocol-plugin/readme
service/protocol-plugin/sample-app/SConscript [new file with mode: 0644]
service/protocol-plugin/sample-app/linux/SConscript [new file with mode: 0644]
service/protocol-plugin/sample-app/linux/fan-control/Makefile [deleted file]
service/protocol-plugin/sample-app/linux/mqtt/Makefile [new file with mode: 0644]
service/protocol-plugin/sample-app/linux/mqtt/mqttclient.cpp [moved from service/protocol-plugin/sample-app/linux/fan-control/fanclient.cpp with 83% similarity]
service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml [new file with mode: 0644]
service/soft-sensor-manager/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/linux/ClientApp/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript [new file with mode: 0644]
service/things-manager/SConscript [new file with mode: 0644]
service/things-manager/sampleapp/SConscript [new file with mode: 0644]
service/things-manager/sampleapp/linux/tgmclient/SConscript [new file with mode: 0644]
service/third_party_libs.scons [new file with mode: 0644]

index c8d1cf5..a5463f0 100644 (file)
@@ -1,16 +1,30 @@
 # Ignore output dirs
 /release
-/csdk/release
-/csdk/libcoap-4.1.1/release/
-/examples/release
+resource/release
+resource/csdk/release
+resource/csdk/libcoap-4.1.1/release/
+resource/examples/release
+resource/examples/debug
 
 /debug
-csdk/debug/
-csdk/libcoap-4.1.1/debug/
-/examples/debug
-csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/debug
+resource/csdk/debug/
+resource/csdk/libcoap-4.1.1/debug/
+resource/csdk/libcoap-4.1.1/linux/
+resource/csdk/linux
+resource/csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/csdk/stack/samples/linux/SimpleClientServer/release/
 
+resource/csdk/connectivity/build/out/
 
+resource/oc_logger/bin/
+resource/oc_logger/lib/
+resource/oc_logger/samples/linux/release/
+resource/oc_logger/samples/linux/debug
+
+service/things-manager/build/linux/release
+service/things-manager/build/linux/debug
+service/things-manager/sdk/build/linux/
 # Ignore any object files
 *.o
 *.obj
@@ -22,4 +36,11 @@ csdk/stack/samples/linux/SimpleClientServer/debug/
 *.project
 
 # Ignore dependencies folder, which should be generated
-/dependencies
+dependencies/
+
+#ignore Klocwork stuff
+.kwlp/
+.kwps/
+
+#ignore various swap files
+*.swp
diff --git a/Readme.scons.txt b/Readme.scons.txt
new file mode 100644 (file)
index 0000000..8956c2d
--- /dev/null
@@ -0,0 +1,187 @@
+== How to build Iotivity projects ==
+
+Iotivity includes a series of projects. You can find all these projects here:
+    https://oic-review.01.org/gerrit/#/admin/projects/
+
+You can build Iotivity project on Linux / Windows / MAC OSX for various OS(
+Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...).
+The output of the build is in:
+  <top directory of the project>/out/<target_os>/<target_arch>/<build version>/
+e.g.
+       oic-resource/out/android/armeabi-v7a/release/.
+
+This document takes oic-resource project as example, the way to build other
+projects is almost the same.
+
+=== Iotivity project build tool scons ===
+
+Scons is a cross-platform build tool, its usage is quite similar to GNU make.
+To build a project, you just require to run following command at the directory
+where a SConstruct file exists(SConstruct is the entrance of scons build, it's
+equivalent to Makefile of 'make') :
+      $ scons [options] [target]
+
+In additional, usually the scons build script of a project provides useful help
+information(include build options). To see the help information:
+      $ scons [options] -h
+
+Note: If no value is specified for an option, the default value will be used.
+The change of options value may impact the output.
+
+
+=== Prerequites ===
+
+* 1. Scons
+
+Please refer to the following page to install scons:
+   http://www.scons.org/doc/production/HTML/scons-user.html#chap-build-install
+(Note: on Windows, install Python 2.x before installing scons)
+
+* 2. IDE/SDK Prerequites
+To build for some OS (Android / Arduino / IOS ...), an IDE/SDK may be required,
+please go to the relative page to download and install the required IDE/SDK.
+
+Android:
+To build for Android, Andorid NDK and SDK are required.
+  Android NDK: http://developer.android.com/tools/sdk/ndk/index.html
+  Android SDK: http://developer.android.com/sdk/index.html
+(Note: as in some Iotivity projects, C++11 features are used, recommend Android
+ NDK >= r10, according to our test result r10c is the best one currently)
+
+Arduino:
+To build for Arduino, Arduino IDE is required.
+  Arduino IDE: http://arduino.cc/en/Main/Software
+  (Note: recommend install Arduino IDE >=1.5.7)
+
+Arduino builds are dependent on latest Time library. Download it from here:
+    http://www.pjrc.com/teensy/td_libs_Time.html
+and extract to <arduino_ide_root>/libraries/
+
+(Note: If you are using Arduino IDE 1.5.8 BETA on Windows, it may pop up some
+dll isn't found. please copy relative dll from the IDE directory to
+C:\Windows\SysWOW64. IDE 1.5.7 doesn't have this issue. Other version IDE isn't
+tested.)
+
+Apple:
+To build for Mac OSX or IOS, Xcode is required.
+  Xcode: https://developer.apple.com/xcode/downloads/
+
+Java:
+To build the Java code, JDK is required.
+  JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html
+(If the project doesn't include Java code or you wouldn't like build the
+Java codes, this isn't required)
+
+(Note: for convenience, suggest add the IDE/SDK path in environment variable,
+so you don't need to add it in command line each time. The build script will
+guide you to do that.)
+
+* 3. External libraries
+For Android and IOS build, most of the external libraries are provided as
+binary in oic-utilities project (https://oic-review.01.org/gerrit/oic-utilities).
+Please download it in the same directory as other Iotivity projects. If it's
+in different directory, an additional option (OIC_UITLS) will be required. The
+build command should be:
+      $ scons OIC_UITLS=<path to oic-utilities> [other options] [target]
+
+(Note: for convenience, you can also add it in environment variable. So you
+don't need to add this option in command line each time.)
+  e.g.:
+      $ export OIC_UITLS=<path to oic-utilities project>
+
+
+=== Build Iotivity project on Linux(Ubuntu) ===
+
+1. Build Iotivity project for Linux
+      $ cd <top directory of the project>
+      $ sudo apt-get install libboost-dev libboost-program-options-dev
+      $ scons
+
+2. Build Iotivity project for Android
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard. To see all of its
+allowed value, please execute command 'scons TARGET_OS=android -Q -h'.
+
+Note: Currently as x86_64/arm64_v8a external library binaries aren't provided,
+you may meet link problem if build executable binary which depends on external
+library for x86_64/arm64_v8a.
+
+3. Build Iotivity project for Arduino
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy
+(xxx can be avr, arm; yyy is the name of the board, to get its allowed value
+run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in
+the output of above command line, that's due to some boards have different
+processor, to specify the processor, add 'CPU=zzz' in the command line. If no
+'CPU' option exists, that means the board only support one kind of processor,
+it's unnecessary to specify it)
+
+
+=== Build Iotivity project on Windows ===
+
+1. Build Iotivity project for Android(It's the same as on Ubuntu)
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard ...)
+
+2. Build Iotivity project for Arduino(It's the same as on Ubuntu)
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy
+(xxx can be avr, arm; yyy is the name of the board, to get its allowed value
+run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in
+the output of above command line, that's due to some boards have different
+processor, to specify the processor, add 'CPU=zzz' in the command line. If no
+'CPU' option exists, that means the board only support one kind of processor,
+it's unnecessary to specify it)
+
+
+Note: Currently most Iotivity project doesn't support Windows, so you can't set
+TARGET_OS to 'windows' except the project support Windows.
+
+That's to say if the project doesn't support Windows, run:
+      $ scons TARGET_OS=windows ....
+or run on Windows
+      $ scons
+may always fail.
+
+
+=== Build Iotivity project on Mac OSX ===
+
+1. Build Iotivity project for Mac OSX
+      $ cd <top directory of the project>
+      $ scons SYS_VERSION=yyy
+(yyy is the OSX version, e.g. 10.9)
+
+2. Build Iotivity project for Android(It's the same as on Ubuntu)
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard)
+
+3. Build Iotivity project for IOS
+      $ cd <top directory of the project>
+      $ scons TARGET_OS=ios TARGET_ARCH=xxx SYS_VERSION=yyy
+(xxx can be i386, x86_64, armv7, armv7s, arm64, yyy is IOS version, e.g. 7.0)
+
+Note:
+1) for convenience, a script (auto_build.sh) is provided to run possible build
+at once. Following is the usage:
+
+To build:
+     $ auto_build.sh <path-to-android-ndk> <path-to-arduino-home>
+To clean:
+     $ auto_build.sh -c
+
+2) Last sync and test with commit e9403ce6d4d7a1a0ac8d12c5acc876af7f7a8f76
+If you meet build error with newest code, it may due to the scripts are not up
+to date. Please try commit 5f16c38a5380e4b5c0d82e2cfea4af5fdc30c9ac or send mail
+to <OIC-OSD@list.01.org>.
+
+3) The build scripts for services have been provided. As the services code is
+out of date, it must the sync with newest resource code, otherwise, it can't
+pass the build, currently, the build scripts for services aren't enabled. Please
+remove the '#' at line 31 in 'SConstruct' file to enable it after the code is
+updated.
+
+4) For Arduino build, the Time library should >=1.3. The old can only be built
+with Arduino IDE 1.0.x
diff --git a/SConstruct b/SConstruct
new file mode 100644 (file)
index 0000000..fd1b034
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# The main build script
+#
+##
+
+# Load common build config
+SConscript('build_common/SConscript')
+
+# Load extra options
+SConscript('extra_options.scons')
+Import('env')
+
+target_os = env.get('TARGET_OS')
+if target_os == 'arduino':
+       SConscript('arduino.scons')
+# By default, src_dir is current dir, the build_dir is:
+#     ./out/<target_os>/<target_arch>/<release or debug>/
+#
+# The build_dir is a variant directory of the source directory(You can
+# consider build_dir as a soft link to src_dir, for detail please refer to:
+#     http://www.scons.org/doc/production/HTML/scons-user.html#f-VariantDir
+#
+# Any way, to make the output is in build_dir, when load scripts, the path should
+# be relevant to build_dir.
+build_dir = env.get('BUILD_DIR')
+
+# Build 'resource' sub-project
+SConscript(build_dir + 'resource/SConscript')
+
+# Build 'service' sub-project
+#SConscript(build_dir + 'service/SConscript')
+
+# Append targets information to the help information, to see help info, execute command line:
+#     $ scon [options] -h
+env.PrintTargets()
+
+# Print bin upload command line (arduino only)
+if target_os == 'arduino':
+       env.UploadHelp()
diff --git a/arduino.scons b/arduino.scons
new file mode 100644 (file)
index 0000000..4ab2aff
--- /dev/null
@@ -0,0 +1,11 @@
+##
+# This script includes arduino specific config for oic-resource
+##
+Import('env')
+
+env.ImportLib('Time')
+if env.get('NET') == 'Ethernet':
+       env.ImportLib('Ethernet')
+else:
+       env.ImportLib('WiFi')
+env.ImportLib('SPI')
\ No newline at end of file
similarity index 51%
rename from resource/auto_build.sh
rename to auto_build.sh
index 14aca7f..9f947eb 100755 (executable)
@@ -4,58 +4,58 @@ function clean()
 {
        echo "*********** Clean build *************"
        scons -c
-       rm out -rf
+       rm -rf out
 }
 
 function build()
 {
-       echo "*********** Build for linux *************"
-       scons
+       if [ $(uname -s) = "Linux" ]
+        then
+               echo "*********** Build for linux *************"
+               scons RELEASE=$3
+       fi
 
        # Note: for android, as oic-resource uses C++11 feature stoi and to_string,
        # it requires gcc-4.9, currently only android-ndk-r10(for linux)
        # and windows android-ndk-r10(64bit target version) support these features.
 
        echo "*********** Build for android x86 *************"
-       scons BUILD_TARGET=Android CPU_ARCH=x86 ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=x86 ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for android armeabi *************"
-       scons BUILD_TARGET=Android CPU_ARCH=armeabi ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=armeabi ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for android armeabi-v7a *************"
-       scons BUILD_TARGET=Android CPU_ARCH=armeabi-v7a ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=armeabi-v7a ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for android armeabi-v7a-hard *************"
-       scons BUILD_TARGET=Android CPU_ARCH=armeabi-v7a-hard ANDROID_HOME=$1 ANDROID_NDK=$2
+       scons TARGET_OS=android TARGET_ARCH=armeabi-v7a-hard ANDROID_NDK=$1 RELEASE=$3
 
        echo "*********** Build for arduino avr *************"
-       scons BUILD_TARGET=Arduino CPU_ARCH=avr ARDUINO_HOME=$3
+       scons TARGET_OS=arduino TARGET_ARCH=avr ARDUINO_HOME=$2 RELEASE=$3
 
        echo "*********** Build for arduino arm *************"
-       scons BUILD_TARGET=Arduino CPU_ARCH=arm ARDUINO_HOME=$3
+       scons TARGET_OS=arduino TARGET_ARCH=arm ARDUINO_HOME=$2 RELEASE=$3
 
        if [ $(uname -s) = "Darwin" ]
        then
-               echo "*********** Build for OSX i386 *************"
-               scons BUILD_TARGET=Darwin CPU_ARCH=i386 SYS_VERSION=10.9
-
-               echo "*********** Build for OSX x86_64 *************"
-               scons BUILD_TARGET=Darwin CPU_ARCH=x86_64 SYS_VERSION=10.9
+               echo "*********** Build for OSX *************"
+               scons TARGET_OS=darwin SYS_VERSION=10.9 RELEASE=$3
 
                echo "*********** Build for IOS i386 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=i386 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=i386 SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS x86_64 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=x86_64 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=x86_64 SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS armv7 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=armv7 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=armv7 SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS armv7s *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=armv7s SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=armv7s SYS_VERSION=7.0 RELEASE=$3
 
                echo "*********** Build for IOS arm64 *************"
-               scons BUILD_TARGET=IOS CPU_ARCH=arm64 SYS_VERSION=7.0
+               scons TARGET_OS=ios TARGET_ARCH=arm64 SYS_VERSION=7.0 RELEASE=$3
        fi
 }
 
@@ -63,7 +63,7 @@ function  help()
 {
        echo "Usage:"
         echo "  build:"
-        echo "     `basename $0` <path-to-android-sdk> <path-to-android-ndk> <path-to-arduino-home>"
+        echo "     `basename $0` <path-to-android-ndk> <path-to-arduino-home>"
         echo "  clean:"
         echo "     `basename $0` -c"
 }
@@ -78,12 +78,14 @@ then
                help
                exit -1
        fi
-elif [ $# -ne 3 ]
+elif [ $# -ne 2 ]
 then
        help
        exit -1
 fi
 
-
-build $1 $2 $3
+# Suppress "Reading ..." message and enable parallel build
+export SCONSFLAGS="-Q -j 8"
+build $1 $2 true
+build $1 $2 false
 echo "===================== done ====================="
diff --git a/build_common/SConscript b/build_common/SConscript
new file mode 100644 (file)
index 0000000..c6708e4
--- /dev/null
@@ -0,0 +1,182 @@
+##
+# This script includes generic build options:
+#    release/debug, target os, target arch, cross toolchain, build environment etc
+##
+import os
+import platform
+
+# Map of host os and allowed target os (host: allowed target os)
+host_target_map = {
+               'linux': ['linux', 'android', 'arduino'],
+               'windows': ['windows', 'winrt', 'android', 'arduino'],
+               'darwin': ['darwin', 'ios', 'android', 'arduino'],
+               }
+
+# Map of os and allowed archs (os: allowed archs)
+os_arch_map = {
+               'linux': ['x86', 'x86_64', 'arm', 'arm64'],
+               'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'],
+               'windows': ['x86', 'amd64', 'arm'],
+               'winrt': ['arm'],
+               'darwin': ['i386', 'x86_64'],
+               'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'],
+               'arduino': ['avr', 'arm'],
+               }
+
+host = platform.system().lower()
+
+if not host_target_map.has_key(host):
+       print "\nError: Current system (%s) isn't supported\n" % host
+       Exit(1)
+
+######################################################################
+# Get build options (the optins from command line)
+######################################################################
+target_os = ARGUMENTS.get('TARGET_OS', host).lower() # target os
+
+if target_os not in host_target_map[host]:
+       print "\nError: Unknown target os: %s (Allow values: %s)\n" % (target_os, host_target_map[host])
+       Exit(1)
+
+default_arch = platform.machine()
+if default_arch not in os_arch_map[target_os]:
+       default_arch = os_arch_map[target_os][0].lower()
+
+target_arch = ARGUMENTS.get('TARGET_ARCH', default_arch) # target arch
+
+######################################################################
+# Common build options (release, target os, target arch)
+######################################################################
+help_vars = Variables()
+help_vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
+help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map[host]))
+help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
+
+######################################################################
+# Platform(build target) specific options: SDK/NDK & toolchain
+######################################################################
+targets_support_cc = ['linux', 'arduino']
+
+if target_os in targets_support_cc:
+       # Set cross compile toolchain
+       help_vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX'))
+       help_vars.Add(PathVariable('TC_PATH',
+                       'Toolchain path (Generally only be required for cross-compiling)',
+                       os.environ.get('TC_PATH')))
+
+if target_os in ['android', 'arduino']: # Android/Arduino always uses GNU compiler regardless of the host
+       env = Environment(variables = help_vars,
+                       tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
+                       )
+else:
+       env = Environment(variables = help_vars, TARGET_ARCH = target_arch, TARGET_OS = target_os)
+
+Help(help_vars.GenerateHelpText(env))
+
+tc_set_msg = '''
+************************************ Warning **********************************
+*   Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default *
+* toolchain, if it isn't what you expect you should unset it, otherwise it may*
+* cause inexplicable errors.                                                  *
+*******************************************************************************
+'''
+
+if target_os in targets_support_cc:
+       prefix = env.get('TC_PREFIX')
+       tc_path = env.get('TC_PATH')
+       if prefix:
+               env.Replace(CC = prefix + 'gcc')
+               env.Replace(CXX = prefix + 'g++')
+               env.Replace(AR = prefix + 'ar')
+               env.Replace(AS = prefix + 'as')
+               env.Replace(LINK = prefix + 'ld')
+               env.Replace(RANLIB = prefix + 'ranlib')
+
+       if tc_path:
+               env.PrependENVPath('PATH', tc_path)
+               sys_root = os.path.abspath(tc_path + '/../')
+               env.AppendUnique(CCFLAGS = ['--sysroot=' + sys_root])
+               env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
+
+       if prefix or tc_path:
+               print tc_set_msg
+
+# Ensure scons be able to change its working directory
+env.SConscriptChdir(1)
+
+# Set the source directory and build directory
+#   Source directory: 'dir'
+#   Build directory: 'dir'/out/<target_os>/<target_arch>/<release or debug>/
+#
+# You can get the directory as following:
+#   env.get('SRC_DIR')
+#   env.get('BUILD_DIR')
+
+def __set_dir(env, dir):
+       if not os.path.exists(dir + '/SConstruct'):
+               print '''
+*************************************** Error *********************************
+* The directory(%s) seems isn't a source code directory, no SConstruct file is
+* found. *
+*******************************************************************************
+''' % dir
+               Exit(1)
+
+       if env.get('RELEASE'):
+               build_dir = dir + '/out/' + target_os + '/' + target_arch + '/release/'
+       else:
+               build_dir = dir + '/out/' + target_os + '/' + target_arch + '/debug/'
+       env.VariantDir(build_dir, dir, duplicate=0)
+
+       env.Replace(BUILD_DIR = build_dir)
+       env.Replace(SRC_DIR = dir)
+
+def __src_to_obj(env, src, home = ''):
+       obj = env.get('BUILD_DIR') + src.replace(home, '')
+       if env.get('OBJSUFFIX'):
+               obj += env.get('OBJSUFFIX')
+       return env.Object(obj, src)
+
+def __install(ienv, targets, name):
+       i_n = ienv.Install(env.get('BUILD_DIR'), targets)
+       Alias(name, i_n)
+       env.AppendUnique(TS = [name])
+
+def __append_target(ienv, target):
+       env.AppendUnique(TS = [target])
+
+def __print_targets(env):
+       Help('''
+===============================================================================
+Targets:\n    ''')
+       for t in env.get('TS'):
+               Help(t + ' ')
+       Help('''
+\nDefault all targets will be built. You can specify the target to build:
+
+    $ scons [options] [target]
+===============================================================================
+''')
+
+env.AddMethod(__set_dir, 'SetDir')
+env.AddMethod(__print_targets, 'PrintTargets')
+env.AddMethod(__src_to_obj, 'SrcToObj')
+env.AddMethod(__append_target, 'AppendTarget')
+env.AddMethod(__install, 'InstallTarget')
+env.SetDir(env.GetLaunchDir())
+
+Export('env')
+
+# Load config of target os
+env.SConscript(target_os + '/SConscript')
+
+# Delete the temp files of configuration
+if env.GetOption('clean'):
+       dir = env.get('SRC_DIR')
+
+       if os.path.exists(dir + '/config.log'):
+               Execute(Delete(dir + '/config.log'))
+               Execute(Delete(dir + '/.sconsign.dblite'))
+               Execute(Delete(dir + '/.sconf_temp'))
+
+Return('env')
similarity index 76%
rename from resource/build_common/android/SConscript
rename to build_common/android/SConscript
index 7704e70..6e81213 100644 (file)
@@ -5,13 +5,19 @@ import os
 import platform
 import subprocess
 
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ANDROID_NDK')
+Import('env')
 
-if not ANDROID_NDK:
+help_vars = Variables()
+help_vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+android_ndk = env.get('ANDROID_NDK')
+if not android_ndk:
        print '''
 *************************************** Error *********************************
-*   Android NDK path (ANDROID_NDK) isn't set, you can set enviornment variable*
-* ANDROID_NDK or add it in command line as:                                   *
+*    Android NDK path isn't set, you can set enviornment variable ANDROID_NDK *
+* or add it in command line as:                                               *
 *      # scons ANDROID_NDK=<path to android NDK> ...                          *
 *******************************************************************************
 '''
@@ -46,7 +52,7 @@ env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections', '-Wl,-z,nocopyreloc'])
 ######################################################################
 # Probe Android NDK default flags
 ######################################################################
-ndk_build_cmd = ANDROID_NDK + '/ndk-build'
+ndk_build_cmd = android_ndk + '/ndk-build'
 if env['HOST_OS'] == 'win32':
        if os.path.isfile(ndk_build_cmd + '.cmd'):
                ndk_build_cmd += '.cmd'
@@ -57,7 +63,7 @@ if not os.path.isfile(ndk_build_cmd):
 *   It seems android ndk path is not set properly, please check if "%s"
 * is the root directory of android ndk.                                       *
 *******************************************************************************
-''' % ANDROID_NDK
+''' % android_ndk
        Exit(1)
 
 ANDROID_HOME = os.environ.get('ANDROID_HOME')
@@ -72,24 +78,26 @@ if ANDROID_HOME is None or not os.path.exists(ANDROID_HOME):
 *******************************************************************************
 '''
 
+target_arch = env.get('TARGET_ARCH')
+
 # Android ndk early version doesn't support C++11. Detect the toolchain
 # and platform version to make sure the newest version is used.
 
 # Detect toolchain version
 for tc_ver in ['4.9', '4.8', '4.7', '']:
-       if os.path.exists(ANDROID_NDK + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
+       if os.path.exists(android_ndk + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
                break
 
 # Detect platform version.
 platform_ver = ''
 for pf_ver in range(0, 100): # 100 should be big enough :)
-       if os.path.exists(ANDROID_NDK + '/platforms/android-%d' % pf_ver):
+       if os.path.exists(android_ndk + '/platforms/android-%d' % pf_ver):
                platform_ver = "%d" % pf_ver
 
 cmd = [ndk_build_cmd]
-cmd.append('APP_ABI=' + TARGET_CPU_ARCH)
+cmd.append('APP_ABI=' + target_arch)
 cmd.append('APP_STL=gnustl_static')
-if RELEASE_BUILD:
+if env.get('RELEASE'):
        cmd.append('APP_OPTIM=release')
 else:
        cmd.append('APP_OPTIM=debug')
@@ -127,25 +135,30 @@ for flags in p.stdout.readlines():
                env.AppendUnique(CPPPATH = Split(flags[8:]))
 
        elif cmp(flags[0:8], 'SYSROOT=') == 0:
-               env.AppendUnique(LINKFLAGS = ['--sysroot=' + flags[8:].strip()])
-               env.AppendUnique(LIBPATH = [flags[8:].strip() + '/usr/lib'])
+               sysroot = flags[8:].strip()
+               env.AppendUnique(LINKFLAGS = ['--sysroot=' + sysroot])
+               env.AppendUnique(LIBPATH = [sysroot + '/usr/lib'])
+               # To fix android NDK issue
+               # Some functions, e.g. rand, srand. strtof ... are static in static inline
+               # prior to android-L. so libc.so before android-L doesn't have them. If build
+               # build on android-L and the function(s) is used, should link libc.a
+               if platform_ver == '' or int(platform_ver) > 20:
+                       env.AppendUnique(LIBS = File(sysroot + '/usr/lib/libc.a'))
 
        elif cmp(flags[0:8], 'LDFLAGS=') == 0:
                env.AppendUnique(LINKFLAGS = Split(flags[8:]))
 
        elif cmp(flags[0:7], 'TC_VER=') == 0:  # set gnustl library path
                ver = flags[7:].strip()
-               env.AppendUnique(LIBPATH = [ANDROID_NDK + '/sources/cxx-stl/gnu-libstdc++/'
-                               + ver + '/libs/' + TARGET_CPU_ARCH])
+               env.AppendUnique(LIBPATH = [android_ndk + '/sources/cxx-stl/gnu-libstdc++/'
+                               + ver + '/libs/' + target_arch])
 
 ######################################################################
 # Set release/debug flags
 ######################################################################
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
        env.AppendUnique(CPPDEFINES = ['NDEBUG'])
        env.AppendUnique(LINKFLAGS = ['-s'])
 else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
+       env.AppendUnique(CCFLAGS = ['-g'])
similarity index 93%
rename from resource/build_common/android/jni/Android.mk
rename to build_common/android/jni/Android.mk
index a7f2267..9bc6284 100644 (file)
@@ -1,6 +1,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := flags_probe
-include $(BUILD_SHARE_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
 
 $(info TC_PREFIX=$(TOOLCHAIN_PREFIX))
 $(info CFLAGS=$(TARGET_CFLAGS))
diff --git a/build_common/arduino/SConscript b/build_common/arduino/SConscript
new file mode 100755 (executable)
index 0000000..4c3a01f
--- /dev/null
@@ -0,0 +1,400 @@
+##
+# This script includes arduino specific config
+##
+import os
+import platform
+
+Import('env')
+
+def __parse_config(f):
+       dict = {}
+
+       if not os.path.isfile(f):
+               return dict
+
+       file = open(f, 'r')
+       strs = file.readlines()
+       for str in strs:
+               str = str.strip()
+               if len(str) > 0 and str[0] == '#':
+                       continue
+
+               idx = str.find('=')
+               if idx > 0:
+                       dict.setdefault(str[0:idx], str[idx + 1:])
+
+       return dict
+
+def __get_boards(dict):
+       boards = []
+       keys = dict.keys()
+       for key in keys:
+               idx = key.find('.name')
+               if idx > 0:
+                       if key.endswith('.name'):
+                               boards.append(key[0:idx])
+       return boards
+
+def __get_cpu(dict, board):
+       cpus = []
+       keys = dict.keys()
+       for key in keys:
+               idx = key.find(board + '.menu.cpu.')
+               start = len(board + '.menu.cpu.')
+               if idx >= 0:
+                       end = key.find('.', start)
+                       if end > 0:
+                               cpu = key[start:end]
+                               exist = False
+                               for c in cpus:
+                                       if c == cpu:
+                                               exist = True
+                                               break
+
+                               if not exist:
+                                       cpus.append(cpu)
+       return cpus
+
+def __get_board_info(board, key):
+       if cpu:
+               v = boards_info.get(board + '.menu.cpu.' + cpu + key)
+               if not v:
+                       v = boards_info.get(board + key)
+       else:
+               v = boards_info.get(board + key)
+       return v
+
+def __search_files(path, pattern, ondisk=True, source=True, strings=False, recursive=True):
+       if not recursive:
+               return Glob(pattern, ondisk, source, strings)
+
+       matches = []
+       for root, dirnames, filenames in os.walk(path):
+               matches.extend(Glob(root + '/' + pattern, ondisk, source, strings))
+
+       return matches
+
+# To make sure the src is built in 'BUILD_DIR' (by default it will be built at
+# the same directory as the .c .cpp .S)
+def __src_to_obj(env, srcs):
+       objs = []
+       prefix = env.get('BOARD') + '_'
+       if env.get('CPU'):
+               prefix += env.get('CPU') + '_'
+
+       build_dir = env.get('BUILD_DIR') + '/arduino/'
+       for src in srcs:
+               obj = src.path.replace(arduino_home, build_dir)
+               i = obj.rfind('.')
+               obj = obj[0:i]
+               if env.get('OBJSUFFIX'):
+                       obj += env.get('OBJSUFFIX')
+               objs.extend(env.Object(obj, src, OBJPREFIX=prefix))
+       return objs
+
+def __import_lib(env, lib):
+       lib_path = arduino_home + '/libraries/' + lib
+       if not os.path.exists(lib_path):
+               if target_arch == 'avr':
+                       lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib
+               else:
+                       lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib
+
+       if os.path.exists(lib_path + '/src'):
+               lib_path = lib_path + '/src'
+
+       env.AppendUnique(CPPPATH = [lib_path])
+
+       if os.path.exists(lib_path + '/utility'):
+               env.AppendUnique(CPPPATH = [lib_path + '/utility'])
+
+       lib_src = []
+       lib_src.extend(__search_files(lib_path, '*.S'))
+       lib_src.extend(__search_files(lib_path, '*.c'))
+       lib_src.extend(__search_files(lib_path, '*.cpp'))
+
+       build_dir = env.get('BUILD_DIR')
+       if build_dir:
+               lib_a = env.StaticLibrary(build_dir + lib, __src_to_obj(env, lib_src))
+       else:
+               lib_a = env.StaticLibrary(lib, __src_to_obj(env, lib_src))
+       env.AppendUnique(LIBS = [File(lib_a[0])])
+
+def __build_core(env):
+       core_src = __search_files(core_folder, '*.S')
+       core_src.extend(__search_files(core_folder, '*.c'))
+       core_src.extend(__search_files(core_folder, '*.cpp'))
+
+       core_src.extend(__search_files(variant_folder, '*.S'))
+       core_src.extend(__search_files(variant_folder, '*.c'))
+       core_src.extend(__search_files(variant_folder, '*.cpp'))
+
+       core_obj = __src_to_obj(env, core_src)
+       build_dir = env.get('BUILD_DIR')
+       if build_dir:
+               s_core = env.StaticLibrary(build_dir + 'core', core_obj)
+       else:
+               s_core = env.StaticLibrary('core', core_obj)
+       env.AppendUnique(LIBS = [File(s_core[0])])
+
+       # To avoid compiler issue. Otherewise there may be warnings:
+       #       undefined reference to '_exit' '_close', '_getpid' ...
+       # Above functions are used in libc.a and implemented in syscalls_sam3.c
+       if env.get('TARGET_ARCH') == 'arm':
+               for obj in core_obj:
+                       if obj.name.endswith('syscalls_sam3.o'):
+                               env.AppendUnique(LIBS = [File(obj)])
+
+def __create_bin(env, source):
+       name = source
+       if env.get('TARGET_ARCH') == 'avr':
+               eep = env.Command(name + '.eep', source, 'avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $SOURCE $TARGET')
+               hex = env.Command(name + '.hex', source, 'avr-objcopy -O ihex -R .eeprom $SOURCE $TARGET')
+       else:
+               hex = env.Command(name + '.hex', source, 'arm-none-eabi-objcopy -O binary $SOURCE $TARGET')
+
+# Print the command line that to upload binary to the board
+def __upload_help(env):
+       if target_arch == 'avr':
+               protocol = __get_board_info(board, '.upload.protocol')
+               speed = __get_board_info(board, '.upload.speed')
+
+               upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \
+       + mcu + ' -c' + protocol + ' -P<serial_port>' + ' -b' + speed + ' -D -Uflash:w:<hex_file>:i'
+       else:
+               uu = __get_board_info(board, '.upload.native_usb')
+               upload_cmd = arduino_home + '/hardware/tools/bossac -i -d --port=<serial_port> -U ' + uu + ' -e -w -v -b <bin file> -R'
+
+       Help('''
+===============================================================================
+You can upload the bin file with following command line:
+''')
+       Help('\n   $ ' + upload_cmd)
+       Help('''
+\nPlease replace <xxx> according to the actual situation.
+===============================================================================
+''')
+
+# ARDUINO_HOME build option
+help_vars = Variables()
+help_vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+target_arch = env.get('TARGET_ARCH')
+arduino_home = env.get('ARDUINO_HOME')
+if not arduino_home:
+       print '''
+************************************* Error ***********************************
+*   Arduino root directory isn't set, you can set enviornment variable        *
+* ARDUINO_HOME or add it in command line as:                                  *
+*      # scons ARDUINO_HOME=<path to arduino root directory> ...              *
+*******************************************************************************
+'''
+       Exit(1)
+
+# Overwrite suffixes and prefixes
+if env['HOST_OS'] == 'win32':
+       env['OBJSUFFIX'] = '.o'
+       env['SHOBJSUFFIX'] = '.os'
+       env['LIBPREFIX'] = 'lib'
+       env['LIBSUFFIX'] = '.a'
+       env['SHLIBPREFIX'] = 'lib'
+       env['SHLIBSUFFIX'] = '.so'
+       env['LIBPREFIXES'] = ['lib']
+       env['LIBSUFFIXES'] = ['.a', '.so']
+       env['PROGSUFFIX'] = ''
+elif platform.system().lower() == 'darwin':
+       env['SHLIBSUFFIX'] = '.so'
+       env['LIBSUFFIXES'] = ['.a', '.so']
+       env['PROGSUFFIX'] = ''
+
+# Debug/release relative flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+# BOARD / CPU option
+
+# Get IDE version
+if os.path.exists(arduino_home + '/lib/version.txt'):
+       vf = open(arduino_home + '/lib/version.txt', 'r')
+       version = vf.readline().replace('.', '')
+else:
+       print '''
+************************************* Error ***********************************
+* Can't find version file (lib/version.txt), please check if (%s)
+* is arduino root directory.                                                  *
+*******************************************************************************
+''' % arduino_home
+       Exit(1)
+
+if version[0:2] == '10':
+       is_1_0_x = True
+       boards_info = __parse_config(arduino_home + '/hardware/arduino/boards.txt')
+       env.PrependENVPath('PATH', arduino_home + '/hardware/tools/avr/bin/')
+       env.Replace(CC = 'avr-gcc')
+       env.Replace(CXX = 'avr-g++')
+       env.Replace(AR = 'avr-ar')
+       env.Replace(AS = 'avr-as')
+       env.Replace(LINK = 'avr-gcc')
+       env.Replace(RANLIB = 'avr-ranlib')
+       if target_arch != 'avr':
+               print '''
+************************************* Error ***********************************
+* Arduino 1.0.x IDE only support 'avr', to support other arch at least 1.5.x  *
+* is required.
+*******************************************************************************
+'''
+               Exit(1)
+else:
+       is_1_0_x = False
+       if target_arch == 'avr':
+               boards_info = __parse_config(arduino_home + '/hardware/arduino/avr/boards.txt')
+               platform_info = __parse_config(arduino_home + '/hardware/arduino/avr/platform.txt')
+       elif target_arch == 'arm':
+               boards_info = __parse_config(arduino_home + '/hardware/arduino/sam/boards.txt')
+               platform_info = __parse_config(arduino_home + '/hardware/arduino/sam/platform.txt')
+       else:
+               print '''
+************************************* Error ***********************************
+* CPU arch %s isn't supported currently.
+*******************************************************************************
+''' % target_arch
+
+#Board option, let user to select the board
+boards = __get_boards(boards_info)
+help_vars = Variables()
+help_vars.Add(EnumVariable('BOARD', 'arduino board', boards[0], boards))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+#CPU option
+board = env.get('BOARD')
+cpus = __get_cpu(boards_info, board)
+if len(cpus) > 0:
+       help_vars = Variables()
+       help_vars.Add(EnumVariable('CPU', 'arduino board cpu', cpus[0], cpus))
+       help_vars.Update(env)
+       Help(help_vars.GenerateHelpText(env))
+
+# Arduino commom flags
+cpu = env.get('CPU')
+board = env.get('BOARD')
+mcu = __get_board_info(board, '.build.mcu')
+f_cpu = __get_board_info(board, '.build.f_cpu')
+usb_vid = __get_board_info(board, '.build.vid')
+usb_pid = __get_board_info(board, '.build.pid')
+variant = __get_board_info(board, '.build.variant')
+
+if not usb_vid:
+       usb_vid = __get_board_info(board, '.vid.0')
+if not usb_pid:
+       usb_pid = __get_board_info(board, '.pid.0')
+
+if is_1_0_x:
+       core_base = arduino_home + '/hardware/arduino/'
+else:
+       if target_arch == 'avr':
+               core_base = arduino_home + '/hardware/arduino/avr/'
+       else:
+               core_base = arduino_home + '/hardware/arduino/sam/'
+
+variant_folder = core_base + 'variants/' + variant
+env.AppendUnique(CPPPATH = [variant_folder])
+
+core = __get_board_info(board, '.build.core')
+core_folder = core_base + 'cores/' + core + '/'
+env.AppendUnique(CPPPATH = [core_folder])
+
+if is_1_0_x:
+       comm_flags = []
+       if mcu:
+               comm_flags.extend(['-mmcu=' + mcu])
+       if f_cpu:
+               comm_flags.extend(['-DF_CPU=' + f_cpu])
+       comm_flags.extend(['-DARDUINO=' + version])
+       if usb_vid:
+               comm_flags.extend(['-DUSB_VID=' + usb_vid])
+       if usb_pid:
+               comm_flags.extend(['-DUSB_PID=' + usb_pid])
+
+       env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+       env.AppendUnique(ASFLAGS = comm_flags)
+
+       env.AppendUnique(CFLAGS = ['-Os', '-ffunction-sections', '-fdata-sections', '-MMD'])
+       env.AppendUnique(CFLAGS = comm_flags)
+
+       env.AppendUnique(CXXFLAGS = ['-Os', '-fno-exceptions', '-ffunction-sections', '-fdata-sections','-MMD'])
+       env.AppendUnique(CXXFLAGS = comm_flags)
+
+       env.AppendUnique(LINKFLAGS = ['-Os'])
+       if mcu == 'atmega2560':
+               env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections,--relax'])
+       else:
+               env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections'])
+       env.AppendUnique(LINKFLAGS = ['-mmcu=' + mcu])
+else:
+       if target_arch == 'avr':
+               cpu_flag = '-mmcu=' + mcu
+       else:
+               cpu_flag = '-mcpu=' + mcu
+
+       comm_flag = [cpu_flag, '-DF_CPU=' + f_cpu, '-DARDUINO=' + version, '-DARDUINO_' + __get_board_info(board, '.build.board')]
+       if target_arch == 'arm':
+               comm_flag.extend(['-DARDUINO_ARCH_SAM'])
+       else:
+               comm_flag.extend(['-DARDUINO_ARCH_AVR'])
+
+       compiler_path = platform_info.get('compiler.path')
+       compiler_path = compiler_path.replace('{runtime.ide.path}', arduino_home)
+       env.PrependENVPath('PATH', compiler_path)
+       env.Replace(CC = platform_info.get('compiler.c.cmd'))
+       env.Replace(CXX = platform_info.get('compiler.cpp.cmd'))
+       env.Replace(AR = platform_info.get('compiler.ar.cmd'))
+       if target_arch == 'arm':
+               env.AppendUnique(CPPPATH = [arduino_home + '/hardware/arduino/sam/system/libsam',
+                                                       arduino_home + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include/',
+                                                       arduino_home + '/hardware/arduino/sam/system//CMSIS/Device/ATMEL'])
+       env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+       env.AppendUnique(ASFLAGS = comm_flag)
+       env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags')))
+       env.AppendUnique(CXXFLAGS = Split(platform_info.get('compiler.cpp.flags')))
+       env.AppendUnique(ARFLAGS = Split(platform_info.get('compiler.ar.flags')))
+       env.AppendUnique(CCFLAGS = comm_flag)
+
+       extra_flags = __get_board_info(board, '.build.extra_flags')
+       if extra_flags:
+               extra_flags = extra_flags.replace('{build.usb_flags}', '')
+               env.AppendUnique(CCFLAGS = Split(extra_flags))
+               usb_flags = ['-DUSB_VID=' + usb_vid, '-DUSB_PID=' + usb_pid, '-DUSBCON', '-DUSB_MANUFACTURER="Unknown"']
+               env.AppendUnique(CCFLAGS = usb_flags)
+
+       if target_arch == 'arm':
+               env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag,
+                                       '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript'),
+                                       '-Wl,-Map,' + env.get('BUILD_DIR') + 'arduino_prj.map'])
+               env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group'))
+
+               variant_system_lib = __get_board_info(board, '.build.variant_system_lib')
+               if variant_system_lib:
+                       if variant_folder.find(' ') >= 0:
+                               variant_folder = '"' + variant_folder + '"'
+                       env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS '
+                                       + variant_folder + '/' + variant_system_lib + ' -Wl,--end-group')
+               else:
+                       env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group')
+       else:
+               env.AppendUnique(LINKFLAGS = Split(platform_info.get('compiler.c.elf.flags')))
+               env.AppendUnique(LINKFLAGS = [cpu_flag])
+               env.AppendUnique(LIBS = 'm')
+       env.Replace(ARCOM = '$AR ' + platform_info.get('compiler.ar.flags') + ' $TARGET $SOURCES')
+
+__build_core(env)
+
+env.AddMethod(__import_lib, "ImportLib") #import arduino library
+#env.AddMethod(__build_core, "BuildCore") #build arduino core
+env.AddMethod(__create_bin, "CreateBin") #create binary files(.eep and .hex)
+env.AddMethod(__upload_help, "UploadHelp") #print the command line that to upload binary to the boardf
diff --git a/build_common/darwin/SConscript b/build_common/darwin/SConscript
new file mode 100644 (file)
index 0000000..7d57774
--- /dev/null
@@ -0,0 +1,54 @@
+##
+# This script set darwin specific flags (GNU GCC)
+#
+##
+import os
+import platform
+
+Import('env')
+
+# SYS_VERSION build option
+help_vars = Variables()
+help_vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION'))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+sys_version = env.get('SYS_VERSION')
+
+if sys_version is None:
+       print '''
+*********************************** Error *************************************
+*   MAC OSX/IOS version isn't set, please set it in command line as :         *
+*      # scons SYS_VERSION=<version> ...                                      *
+*   To get the version, please see:                                                              *
+* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/   *
+* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ *
+*******************************************************************************
+'''
+       Exit(1)
+
+target_arch = env.get('TARGET_ARCH')
+target_os = env.get('TARGET_OS')
+# Set release/debug flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+if target_os == 'darwin':
+       sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + sys_version + '.sdk/'
+else:
+       if target_arch in ['i386', 'x86_64']:
+               sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + sys_version + '.sdk/'
+       else:
+               sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + sys_version + '.sdk/'
+
+# Set arch flags
+env.AppendUnique(CCFLAGS = ['-arch', target_arch, '-isysroot', sys_root])
+env.AppendUnique(LINKFLAGS = ['-arch', target_arch, '-isysroot', sys_root])
+
+if target_os == 'darwin':
+       flag = '-mmacosx-version-min=' + sys_version
+       env.AppendUnique(CCFLAGS = [flag])
+       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/build_common/ios/SConscript b/build_common/ios/SConscript
new file mode 100644 (file)
index 0000000..fcf62aa
--- /dev/null
@@ -0,0 +1,18 @@
+##
+# This script set ios specific flags (GNU GCC)
+#
+##
+Import('env')
+
+# setting of IOS is almost the same as Darwin(MAC OSX)
+env.SConscript('../darwin/SConscript')
+
+sys_version = env.get('SYS_VERSION')
+if env.get('TARGET_ARCH') in ['i386', 'x86_64']: #Simulator
+       flag = '-mios-simulator-version-min=' + sys_version
+       env.AppendUnique(CCFLAGS = [flag])
+       env.AppendUnique(LINKFLAGS = [flag])
+else:
+       flag = '-miphoneos-version-min=' + sys_version
+       env.AppendUnique(CCFLAGS = [flag])
+       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/build_common/linux/SConscript b/build_common/linux/SConscript
new file mode 100644 (file)
index 0000000..bb939be
--- /dev/null
@@ -0,0 +1,33 @@
+##
+# This script set linux specific flags (GNU GCC)
+#
+##
+Import('env')
+
+# Set release/debug flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['-Os'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+       env.AppendUnique(LINKFLAGS = ['-s'])
+else:
+       env.AppendUnique(CCFLAGS = ['-g'])
+
+# Set arch flags
+target_arch = env.get('TARGET_ARCH')
+if target_arch in ['x86']:
+       env.AppendUnique(CCFLAGS = ['-m32'])
+       env.AppendUnique(LINKFLAGS = ['-m32'])
+elif target_arch in ['x86_64']:
+       env.AppendUnique(CCFLAGS = ['-m64'])
+       env.AppendUnique(LINKFLAGS = ['-m64'])
+elif target_arch.find('v7a-hard') > 0:
+       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
+       env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard'])
+       env.AppendUnique(CCFLAGS = ['-mfloat-abi=hard'])
+       env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard'])
+elif target_arch.find('v7a') > 0:
+       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
+elif target_arch.find('arm64') > 0:
+       env.AppendUnique(CPPFLAGS = ['-march=armv8-a'])
+else:
+       env.AppendUnique(CPPFLAGS = ['-march=armv5te'])
diff --git a/build_common/windows/SConscript b/build_common/windows/SConscript
new file mode 100644 (file)
index 0000000..4c35d35
--- /dev/null
@@ -0,0 +1,17 @@
+##
+# This script includes windows specific config (MSVS/MSVC)
+##
+Import('env')
+
+# Set common flags
+env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996'])
+env.AppendUnique(CCFLAGS=['/EHsc'])
+
+# Set release/debug flags
+if env.get('RELEASE'):
+       env.AppendUnique(CCFLAGS = ['/MD', '/O2', '/GF'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+       env.AppendUnique(CCFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
+       env.AppendUnique(CPPDEFINES = ['_DEBUG'])
+       env.AppendUnique(LINKFLAGS = ['/debug'])
diff --git a/extra_options.scons b/extra_options.scons
new file mode 100644 (file)
index 0000000..e1280da
--- /dev/null
@@ -0,0 +1,65 @@
+######################################################################
+# This script manages extra build options
+#
+######################################################################
+import os
+import platform
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
+
+# Add 'OIC_UTILS' build option for user to set oic-utilities project path
+if target_os not in ['linux', 'darwin', 'arduino']:
+       default_dir = os.environ.get('OIC_UTILS')
+       if not default_dir:
+               default_dir = os.path.abspath(src_dir + '/../oic-utilities')
+       else:
+               default_dir = os.path.abspath(default_dir)
+
+       if not os.path.exists(default_dir):
+               default_dir = None
+
+       help_vars = Variables()
+       help_vars.Add(PathVariable('OIC_UTILS', 'oic-utilities project path', default_dir))
+       help_vars.Update(env)
+       Help(help_vars.GenerateHelpText(env))
+
+       utils_path = env.get('OIC_UTILS', default_dir)
+       if utils_path:
+               utils_path = os.path.abspath(utils_path)
+
+       if not utils_path or not os.path.exists(utils_path):
+               print '''
+*********************************** Error: ************************************
+*   oic-utilities project directory isn't set properly, please set enviornment*
+* variable OIC_UTILS or set it in command line:                               *
+*     # scons  OIC_UTILS=<path to oic-utilities> ...                          *
+*******************************************************************************
+'''
+               Exit(1)
+
+if target_os == 'arduino':
+       # Add 'NET' build option, let user select board network connection type
+       vars = Variables()
+       vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi']))
+       vars.Update(env)
+       Help(vars.GenerateHelpText(env))
+
+# check 'cereal' library, temporarily put it here
+if not os.path.exists(src_dir + '/extlibs/cereal'):
+       print '''
+*********************************** Error: **************************************
+*  'Cereal' library doesn't exist. please download cereal to extlibs directory  *
+* add apply the patch as following:                                             *
+*     $ git clone https://github.com/USCiLab/cereal.git <src_dir>/extlibs/cereal*
+*     $ cd <src_dir>/extlibs/cereal                                             *
+*     $ git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245               *
+*     $ git apply ../../resource/patches/cereal_gcc46.patch                     *
+*********************************************************************************
+'''
+       Exit(1)
+else:
+       env.AppendUnique(CPPPATH = [src_dir + '/extlibs/cereal/include'])
diff --git a/resource/Readme.scons.txt b/resource/Readme.scons.txt
deleted file mode 100644 (file)
index f8b9c45..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-1) Build with default option
-  To build with default option:
-  # scons
-
-  To see help information with default option(the output may be different with different options):
-  # scons -Q -h
-
-  To clean the project:
-  # scons -c
-
-2) Build with options
-  To build with options:
-  # scons OPTION1=xxx OPTION2=xxx OPTION3=....
-
-  To see help information:
-  # scons OPTION1=xxx OPTION2=xxx OPTION3=.... -Q -h
-
-  To clean the project:
-  # scons OPTION1=xxx OPTION2=xxx OPTION3=.... -c
-
-3) Examples
-  To build default
-  # scons
-  To see default help
-  # scons -Q -h
-  To clean
-  # scons -c
-
-  To build android armeabi-v7a
-  # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a
-  To see help
-  # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a -Q -h
-  To clean
-  # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a -c
-
-Note:
-  1. To build android binary, android NDK should be newer than r8e(recommend r10).
-  2. You may be asked to set some options. Besides set it in command line, you
-can also set it by create a environment variable. Command line has higher priority.
-If both are set, the command line value will be used.
diff --git a/resource/SConscript b/resource/SConscript
new file mode 100644 (file)
index 0000000..fc82826
--- /dev/null
@@ -0,0 +1,26 @@
+##
+# 'resource' sub-project main build script
+#
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+# Build libcoap
+SConscript('csdk/libcoap/SConscript')
+
+# Build liboctbstack
+SConscript('csdk/SConscript')
+
+if target_os != 'arduino':
+       # Build liboc_logger
+       SConscript('oc_logger/SConscript')
+
+       # Build liboc
+       SConscript('src/SConscript')
+
+       # Build examples
+       SConscript('examples/SConscript')
+else:
+       SConscript('csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript')
\ No newline at end of file
diff --git a/resource/SConstruct b/resource/SConstruct
deleted file mode 100644 (file)
index f2a9b50..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-##
-# The main build script
-#
-##
-import os
-
-SRC_TOP_DIR = os.path.abspath('.') + '/' #oic-resource project top directory
-
-# Common build options
-SConscript('build_common/SConscript')
-Import('RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH')
-
-# Set build directory
-if RELEASE_BUILD:
-       BUILD_DIR = SRC_TOP_DIR + '/out/' + BUILD_TARGET + '/' + TARGET_CPU_ARCH + '/release/'
-else:
-       BUILD_DIR = SRC_TOP_DIR + '/out/' + BUILD_TARGET + '/' + TARGET_CPU_ARCH + '/debug/'
-VariantDir(BUILD_DIR, SRC_TOP_DIR, duplicate=0)
-Export('SRC_TOP_DIR', 'BUILD_DIR')
-
-if BUILD_TARGET == 'arduino':
-       SConscript('arduino.scons')
-
-# Build libcoap
-SConscript(BUILD_DIR + 'csdk/libcoap/SConscript')
-
-# Build liboctbstack
-SConscript(BUILD_DIR + 'csdk/SConscript')
-
-if BUILD_TARGET != 'arduino':
-       # Build liboc_logger
-       SConscript(BUILD_DIR + 'oc_logger/SConscript')
-
-       # Build liboc
-       SConscript(BUILD_DIR + 'src/SConscript')
-
-       # Build examples
-       SConscript(BUILD_DIR + 'examples/SConscript')
-
-# Print targets
-Import('env')
-
-Help('''
-===============================================================================
-Targets:\n    ''')
-for t in env.get('TS'):
-       Help(t + ' ')
-Help('''
-\nDefault all targets will be built. You can specify the target to build:
-
-    #scons [options] [target]
-===============================================================================
-''')
\ No newline at end of file
diff --git a/resource/arduino.scons b/resource/arduino.scons
deleted file mode 100644 (file)
index 287482c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-##
-# This script includes arduino specific config for oic-resource
-##
-Import('env', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
-
-# 'NET' build option
-if env.get('NET') is None:
-       vars = Variables()
-       vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi']))
-       vars.Update(env)
-       Help(vars.GenerateHelpText(env))
-
-env.AppendUnique(CPPPATH = [
-               ARDUINO_HOME + '/libraries/Ethernet/src',
-               ARDUINO_HOME + '/libraries/Ethernet/src/utility',
-               ARDUINO_HOME + '/libraries/WiFi/src',
-               ARDUINO_HOME + '/libraries/WiFi/src/utility',
-               ARDUINO_HOME + '/libraries/Time/',
-               ])
-
-if TARGET_CPU_ARCH == 'arm':
-       # Include path
-       env.AppendUnique(CPPPATH = [
-                       ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino',
-                       ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/USB',
-                       ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/avr',
-                       ARDUINO_HOME + '/hardware/arduino/sam/system/libsam',
-                       ARDUINO_HOME + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include',
-                       ARDUINO_HOME + '/hardware/arduino/sam/system/CMSIS/Device/ATMEL',
-                       ARDUINO_HOME + '/hardware/arduino/sam/variants/arduino_due_x',
-                       ARDUINO_HOME + '/hardware/arduino/sam/libraries/SPI',
-                       ])
-
-       # Compiler/Linker flags
-       env.AppendUnique(CXXFLAGS = ['-ffunction-sections', '-fdata-sections', '-nostdlib',
-                                               '--param', 'max-inline-insns-single=500', '-fno-rtti', '-fno-exceptions',
-                                               '-mcpu=cortex-m3', '-mthumb'
-                                       ])
-       env.AppendUnique(CPPDEFINES = ['printf=iprintf', 'F_CPU=84000000L', 'ARDUINO=157',
-                                               'ARDUINO_SAM_DUE', 'ARDUINO_ARCH_SAM', '__SAM3X8E__', 'USB_VID=0x2341',
-                                               'USB_PID=0x003e', 'USBCON', 'DUSB_MANUFACTURER="Unknown"', 'WITH_ARDUINO',
-                                       ])
-
-       # Source
-       ARDUINO_SRC = []
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/*.c'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/avr/*.c'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/USB/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/variants/arduino_due_x/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/libraries/SPI/*.cpp'))
-else:
-       # Include path
-       env.AppendUnique(CPPPATH = [
-                       ARDUINO_HOME + '/hardware/arduino/avr/cores/arduino',
-                       ARDUINO_HOME + '/hardware/arduino/avr/libraries/SPI',
-                       ARDUINO_HOME + '/hardware/arduino/avr/variants/mega',
-                       ])
-
-       # Compiler/Linker flags
-       env.AppendUnique(CXXFLAGS = ['-mmcu=atmega2560', '-MMD', '-std=c++0x',
-                                               '-Wno-write-strings', '-ffunction-sections', '-fdata-sections',
-                                               '-fno-exceptions', '-felide-constructors'
-                                       ])
-       env.AppendUnique(CPPDEFINES = ['F_CPU=16000000L', 'ARDUINO=156', 'ARDUINO_AVR_MEGA2560',
-                                               'ARDUINO_ARCH_AVR', 'WITH_ARDUINO', 'ATMEGA2560'
-                                       ])
-
-       # Source
-       ARDUINO_SRC = [
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WInterrupts.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/wiring.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/wiring_digital.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/main.cpp',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/Stream.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WMath.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WString.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/HardwareSerial.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/Print.c',
-               ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/IPAddress.c',
-               ARDUINO_HOME + '/hardware/arduino/avr/libraries/SPI/SPI.cpp',
-               ]
-
-if env.get('NET') == 'Ethernet':
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/Ethernet/src/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/Ethernet/src/utility/*.cpp'))
-else:
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/WiFi/src/*.cpp'))
-       ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/WiFi/src/utility/*.cpp'))
-
-Export('ARDUINO_SRC')
\ No newline at end of file
diff --git a/resource/build_common/SConscript b/resource/build_common/SConscript
deleted file mode 100644 (file)
index b3dd335..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-##
-# This script includes generic build options:
-#    release/debug, build target, CPU ARCH, toolchain, build environment etc
-##
-import os
-import platform
-
-host = platform.system()
-default_arch = platform.machine()
-
-if host not in ['Linux', 'Windows', 'Darwin']:
-       host = 'Linux'
-
-# Map of host and allowed targets
-allow_target_map = {
-               'Linux': ['Linux', 'Android', 'Arduino'],
-               'Windows': ['Windows', 'WinRT', 'Android', 'Arduino'],
-               'Darwin': ['Darwin', 'IOS', 'Android', 'Arduino'],
-               }
-
-# Map of platform(target) and allowed archs
-allow_arch_map = {
-               'linux': ['x86', 'x86_64', 'arm', 'arm64'],
-               'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'],
-               'windows': ['x86', 'amd64', 'arm'],
-               'winrt': ['arm'],
-               'darwin': ['i386', 'x86_64'],
-               'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'],
-               'arduino': ['avr', 'arm'],
-               }
-
-######################################################################
-# Get build options (the optins from command line)
-######################################################################
-BUILD_TARGET = ARGUMENTS.get('BUILD_TARGET', host).lower() # target platform
-
-if not allow_arch_map.has_key(BUILD_TARGET):
-       print "\nError: Unknown target platform: %s (Allow values: %s)\n" % (BUILD_TARGET, allow_target_map[host])
-       Exit(1)
-
-if default_arch not in allow_arch_map[BUILD_TARGET]:
-       default_arch = allow_arch_map[BUILD_TARGET][0]
-       default_arch = default_arch.lower()
-
-TARGET_CPU_ARCH = ARGUMENTS.get('CPU_ARCH', default_arch) # target CPU ARCH
-ANDROID_NDK = ARGUMENTS.get('ANDROID_NDK', os.environ.get('ANDROID_NDK')) # ANDROID NDK base directory
-SYS_VERSION = ARGUMENTS.get('SYS_VERSION', os.environ.get('SYS_VERSION'))  # OSX/IOS version
-ARDUINO_HOME = ARGUMENTS.get('ARDUINO_HOME', os.environ.get('ARDUINO_HOME')) # ARDUINO root directory
-
-######################################################################
-# Common build options (release, build target, CPU)
-######################################################################
-vars = Variables()
-vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
-vars.Add(EnumVariable('BUILD_TARGET', 'Target platform', host, allow_target_map[host]))
-vars.Add(EnumVariable('CPU_ARCH', 'Target CPU ARCH', default_arch, allow_arch_map[BUILD_TARGET]))
-
-######################################################################
-# Platform(build target) specific options: SDK/NDK & toolchain
-######################################################################
-targets_support_cc = ['linux', 'arduino']
-
-if BUILD_TARGET == 'android':
-       vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK')))
-
-elif BUILD_TARGET in ['darwin', 'ios']:
-       vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION'))
-
-elif BUILD_TARGET == 'arduino':
-       vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
-
-if BUILD_TARGET in targets_support_cc:
-       # Set cross compile toolchain
-       vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX'))
-       vars.Add(PathVariable('TC_PATH',
-                       'Toolchain path (Generally only be required for cross-compiling)',
-                       os.environ.get('TC_PATH')))
-
-if BUILD_TARGET == 'android': # Android always uses GNU compiler regardless of the host
-       env = Environment(variables = vars,
-                       tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
-                       )
-else:
-       env = Environment(variables = vars, TARGET_ARCH = TARGET_CPU_ARCH, TARGET_OS = BUILD_TARGET)
-
-Help(vars.GenerateHelpText(env))
-
-RELEASE_BUILD = env.get('RELEASE') # Whethere is release build, True: release, False: debug
-
-tc_set_msg = '''
-************************************ Warning **********************************
-*   Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default *
-* toolchain, if it isn't what you expect you should unset it, otherwise it may*
-* cause inexplicable errors.                                                  *
-*******************************************************************************
-'''
-
-if BUILD_TARGET in targets_support_cc:
-       prefix = ARGUMENTS.get('TC_PREFIX', os.environ.get('TC_PREFIX'))
-       tc_path = ARGUMENTS.get('TC_PATH', os.environ.get('TC_PATH'))
-       if prefix:
-               env.Replace(CC = prefix + 'gcc')
-               env.Replace(CXX = prefix + 'g++')
-               env.Replace(AR = prefix + 'ar')
-               env.Replace(AS = prefix + 'as')
-               env.Replace(LINK = prefix + 'ld')
-               env.Replace(RANLIB = prefix + 'ranlib')
-
-       if tc_path:
-               env.PrependENVPath('PATH', tc_path)
-               sys_root = os.path.abspath(tc_path + '/../')
-               env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
-               env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
-               env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
-
-       if prefix or tc_path:
-               print tc_set_msg
-
-# Ensure scons be able to change its working directory
-env.SConscriptChdir(1)
-
-Export('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH',
-               'ANDROID_NDK', 'SYS_VERSION', 'ARDUINO_HOME')
-
-# Load config of specific platform(build target)
-env.SConscript(BUILD_TARGET + '/SConscript')
-
-Return('env')
\ No newline at end of file
diff --git a/resource/build_common/arduino/SConscript b/resource/build_common/arduino/SConscript
deleted file mode 100644 (file)
index d33cc55..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-##
-# This script includes arduino specific config
-##
-import os
-import platform
-
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
-
-if not ARDUINO_HOME:
-       print '''
-************************************* Error ***********************************
-*   Arduino root directory (ARDUINO_HOME) isn't set, you can set enviornment  *
-* variable ARDUINO_HOME or add it in command line as:                         *
-*      # scons ARDUINO_HOME=<path to arduino root directory> ...              *
-*******************************************************************************
-'''
-       Exit(1)
-
-# Overwrite suffixes and prefixes
-if env['HOST_OS'] == 'win32':
-       env['OBJSUFFIX'] = '.o'
-       env['SHOBJSUFFIX'] = '.os'
-       env['LIBPREFIX'] = 'lib'
-       env['LIBSUFFIX'] = '.a'
-       env['SHLIBPREFIX'] = 'lib'
-       env['SHLIBSUFFIX'] = '.so'
-       env['LIBPREFIXES'] = ['lib']
-       env['LIBSUFFIXES'] = ['.a', '.so']
-       env['PROGSUFFIX'] = ''
-elif platform.system().lower() == 'darwin':
-       env['SHLIBSUFFIX'] = '.so'
-       env['LIBSUFFIXES'] = ['.a', '.so']
-       env['PROGSUFFIX'] = ''
-
-# Set toolchain
-def find_toolchain(dir, tc):
-       for root, dirs, files in os.walk(dir, True, None, False):
-               for f in files:
-                       lf = f.lower()
-                       if lf == tc:
-                               return root
-       return None
-
-if TARGET_CPU_ARCH == 'arm':
-       prefix = 'arm-none-eabi-'
-else:
-       prefix = 'avr-'
-
-tc_path = find_toolchain(ARDUINO_HOME + '/hardware/tools/', prefix + 'g++')
-if not tc_path:
-       print '''
-************************************* Error ***********************************
-*   Arduino toolchain isn't detected. Please specify the toolchain prefix and *
-* path, you can do it by setting enviornment variable TC_PREFIX and TC_PATH or*
-* add it in command line as:                                                  *
-*     # scons TC_PREFIX=<prefix> TC_PATH=<path to toolchain> ...              *
-* e.g. scons TC_PREFIX=avr- TC_PATH=/opt/arduino-1.5.7/hardware/tools/avr/bin *                                                                         *
-* Note: TC_PREFIX shouldn't include path                                      *
-*******************************************************************************
-'''
-       Exit(1)
-
-env.PrependENVPath('PATH', tc_path)
-env.Replace(CC = prefix + 'gcc')
-env.Replace(CXX = prefix + 'g++')
-env.Replace(AR = prefix + 'ar')
-env.Replace(AS = prefix + 'as')
-env.Replace(LINK = prefix + 'ld')
-env.Replace(RANLIB = prefix + 'ranlib')
-
-sys_root = os.path.abspath(os.path.join(tc_path, '..'))
-env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
-
-# Debug/release relative flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-       env.AppendUnique(LINKFLAGS = ['-s'])
-else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
diff --git a/resource/build_common/darwin/SConscript b/resource/build_common/darwin/SConscript
deleted file mode 100644 (file)
index fb98616..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-##
-# This script set darwin specific flags (GNU GCC)
-#
-##
-import platform
-
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'SYS_VERSION')
-
-if SYS_VERSION is None:
-       print '''
-*********************************** Error *************************************
-*   MAC OSX/IOS version isn't set, please set it in command line as :         *
-*      # scons SYS_VERSION=<version> ...                                      *
-*   To get the version, please see:                                                              *
-* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/   *
-* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ *
-*******************************************************************************
-'''
-       Exit(1)
-
-# Set release/debug flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
-
-if BUILD_TARGET == 'darwin':
-       SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + SYS_VERSION + '.sdk/'
-else:
-       if TARGET_CPU_ARCH in ['i386', 'x86_64']:
-               SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + SYS_VERSION + '.sdk/'
-       else:
-               SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + SYS_VERSION + '.sdk/'
-
-# Set arch flags
-env.AppendUnique(CXXFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-env.AppendUnique(CCFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-env.AppendUnique(LINKFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-
-if BUILD_TARGET == 'darwin':
-       flag = '-mmacosx-version-min=' + SYS_VERSION
-       env.AppendUnique(CXXFLAGS = [flag])
-       env.AppendUnique(CCFLAGS = [flag])
-       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/resource/build_common/ios/SConscript b/resource/build_common/ios/SConscript
deleted file mode 100644 (file)
index 78630b1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-##
-# This script set ios specific flags (GNU GCC)
-#
-##
-Import('env', 'TARGET_CPU_ARCH', 'SYS_VERSION')
-
-# setting of IOS is almost the same as Darwin(MAC OSX)
-env.SConscript('../darwin/SConscript')
-
-if TARGET_CPU_ARCH in ['i386', 'x86_64']: #Simulator
-       flag = '-mios-simulator-version-min=' + SYS_VERSION
-       env.AppendUnique(CXXFLAGS = [flag])
-       env.AppendUnique(CCFLAGS = [flag])
-       env.AppendUnique(LINKFLAGS = [flag])
-else:
-       flag = '-miphoneos-version-min=' + SYS_VERSION
-       env.AppendUnique(CXXFLAGS = [flag])
-       env.AppendUnique(CCFLAGS = [flag])
-       env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
diff --git a/resource/build_common/linux/SConscript b/resource/build_common/linux/SConscript
deleted file mode 100644 (file)
index d0d999e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-##
-# This script set linux specific flags (GNU GCC)
-#
-##
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH')
-
-# Set release/debug flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['-Os'])
-       env.AppendUnique(CXXFLAGS = ['-Os'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-       env.AppendUnique(LINKFLAGS = ['-s'])
-else:
-       env.AppendUnique(CFLAGS = ['-g'])
-       env.AppendUnique(CXXFLAGS = ['-g'])
-
-# Set arch flags
-if TARGET_CPU_ARCH in ['x86']:
-       env.AppendUnique(CFLAGS = ['-m32'])
-       env.AppendUnique(CXXFLAGS = ['-m32'])
-       env.AppendUnique(LINKFLAGS = ['-m32'])
-elif TARGET_CPU_ARCH in ['x86_64']:
-       env.AppendUnique(CXXFLAGS = ['-m64'])
-       env.AppendUnique(CFLAGS = ['-m64'])
-       env.AppendUnique(LINKFLAGS = ['-m64'])
-elif TARGET_CPU_ARCH.find('v7a-hard') > 0:
-       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
-       env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard'])
-       env.AppendUnique(CFLAGS = ['-mfloat-abi=hard'])
-       env.AppendUnique(CXXFLAGS = ['-mfloat-abi=hard'])
-       env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard'])
-elif TARGET_CPU_ARCH.find('v7a') > 0:
-       env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
-elif TARGET_CPU_ARCH.find('arm64') > 0:
-       env.AppendUnique(CPPFLAGS = ['-march=armv8-a'])
-else:
-       env.AppendUnique(CPPFLAGS = ['-march=armv5te'])
\ No newline at end of file
diff --git a/resource/build_common/windows/SConscript b/resource/build_common/windows/SConscript
deleted file mode 100644 (file)
index 49fd8a0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-##
-# This script includes windows specific config (MSVS/MSVC)
-##
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH')
-
-# Set common flags
-env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996'])
-env.AppendUnique(CFLAGS=['/EHsc'])
-env.AppendUnique(CXXFLAGS=['/EHsc'])
-
-# Set release/debug flags
-if RELEASE_BUILD:
-       env.AppendUnique(CFLAGS = ['/MD', '/O2', '/GF'])
-       env.AppendUnique(CXXFLAGS = ['/MD', '/O2', '/GF'])
-       env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-else:
-       env.AppendUnique(CFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
-       env.AppendUnique(CXXFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
-       env.AppendUnique(CPPDEFINES = ['_DEBUG'])
-       env.AppendUnique(LINKFLAGS = ['/debug'])
\ No newline at end of file
index d47f3e0..5df1507 100644 (file)
@@ -1,18 +1,18 @@
 ##
-# liboctbstack (static library) build script
+# liboctbstack (share library) build script
 ##
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'RELEASE_BUILD', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 
-liboctbstack_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
-# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-Import('OIC_UTILS')
+liboctbstack_env = lib_env.Clone()
 
+target_os = env.get('TARGET_OS')
 # As in the source code, it includes arduino Time library (C++)
 # It requires compile the .c with g++
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
        liboctbstack_env.Replace(CC = env.get('CXX'))
        liboctbstack_env.Replace(CFLAGS = env.get('CXXFLAGS'))
 
@@ -20,7 +20,7 @@ if BUILD_TARGET == 'arduino':
 # Build flags
 ######################################################################
 liboctbstack_env.PrependUnique(CPPPATH = [
-               OIC_UTILS + '/tb/cJSON/',
+               '../../extlibs/cjson/',
                'ocsocket/include',
                'logger/include',
                'ocrandom/include',
@@ -32,14 +32,28 @@ liboctbstack_env.PrependUnique(CPPPATH = [
                '../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
+if target_os not in ['arduino', 'windows', 'winrt']:
        liboctbstack_env.AppendUnique(CPPDEFINES  = ['WITH_POSIX'])
        liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99'])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
+if target_os not in ['windows', 'winrt']:
        liboctbstack_env.AppendUnique(CFLAGS = ['-Wall'])
 
-if not RELEASE_BUILD:
+if target_os == 'android':
+       liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       liboctbstack_env.AppendUnique(LIBS = ['coap', 'm'])
+
+if target_os == 'arduino':
+       liboctbstack_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+else:
+       liboctbstack_env.AppendUnique(CFLAGS = ['-fPIC'])
+
+if target_os in ['darwin', 'ios']:
+       liboctbstack_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+       liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       liboctbstack_env.AppendUnique(LIBS = ['coap'])
+
+if not env.get('RELEASE'):
        liboctbstack_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
 ######################################################################
@@ -47,24 +61,20 @@ if not RELEASE_BUILD:
 ######################################################################
 OCTBSTACK_SRC = 'stack/src/'
 liboctbstack_src = [
+       '../../extlibs/cjson/cJSON.c',
        'occoap/src/occoap.c',
        'occoap/src/occoaphelper.c',
        OCTBSTACK_SRC + 'ocstack.c',
        OCTBSTACK_SRC + 'occlientcb.c',
        OCTBSTACK_SRC + 'ocresource.c',
        OCTBSTACK_SRC + 'ocobserve.c',
-       OCTBSTACK_SRC + 'ocserverrequest.c',
+        OCTBSTACK_SRC + 'ocserverrequest.c',
        OCTBSTACK_SRC + 'occollection.c',
+       OCTBSTACK_SRC + 'ocsecurity.c'
        ]
-
-if RELEASE_BUILD:
-       prefix = TARGET_CPU_ARCH + '-'
+if target_os == 'arduino':
+       liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
 else:
-       prefix = TARGET_CPU_ARCH + 'd-'
-cjson_obj = liboctbstack_env.Object(OIC_UTILS + '/tb/cJSON/cJSON.c', OBJPREFIX=prefix)
-liboctbstack_src.append(cjson_obj)
+       liboctbstack = liboctbstack_env.SharedLibrary('octbstack', liboctbstack_src)
 
-liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
-i_lctbs = liboctbstack_env.Install(BUILD_DIR, liboctbstack)
-Alias('liboctbstack', i_lctbs)
-env.AppendUnique(TS = ['liboctbstack'])
+liboctbstack_env.InstallTarget(liboctbstack, 'liboctbstack')
index 3f3efe3..7e1bdf1 100644 (file)
@@ -1,14 +1,15 @@
 ##
-# libcoap (static library) build script
+# libcoap (share library) build script
 ##
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'RELEASE_BUILD', 'BUILD_DIR', 'ARDUINO_HOME')
+Import('env')
 
 libcoap_env = env.Clone()
 
-# As in the source code, it includes arduino Time library (C++)
+target_os = env.get('TARGET_OS')
+# As in the source code(C) includes arduino Time library head file(C++)
 # It requires compile the .c with g++
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
        libcoap_env.Replace(CC = env.get('CXX'))
        libcoap_env.Replace(CFLAGS = env.get('CXXFLAGS'))
 
@@ -24,15 +25,24 @@ libcoap_env.PrependUnique(CPPPATH = [
                '../../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
+if target_os not in ['arduino', 'windows', 'winrt']:
        libcoap_env.AppendUnique(CPPDEFINES = ['WITH_POSIX'])
-       libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99'])
+       libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99', '-fPIC'])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
+if target_os not in ['windows', 'winrt']:
        libcoap_env.AppendUnique(CFLAGS = ['-Wall', '-ffunction-sections',
                        '-fdata-sections', '-fno-exceptions'])
 
-if not RELEASE_BUILD:
+if target_os == 'android':
+       libcoap_env.AppendUnique(LIBS = ['log'])
+
+if target_os == 'arduino':
+       libcoap_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+
+if target_os in ['darwin', 'ios']:
+       libcoap_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+if not env.get('RELEASE'):
        libcoap_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
 ######################################################################
@@ -45,7 +55,7 @@ libcoap_src = [
        'encode.c',
        'uri.c',
        'coap_list.c',
-       'resource.c',
+#      'resource.c',
        'hashkey.c',
     'str.c',
        'option.c',
@@ -59,22 +69,17 @@ libcoap_src = [
        '../../oc_logger/c/oc_console_logger.c'
        ]
 
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
        if env.get('NET') == 'Wifi':
                libcoap_src.append(['../ocsocket/src/ocsocket_arduino_wifi.cpp'])
        else:
                libcoap_src.append(['../ocsocket/src/ocsocket_arduino.cpp'])
-
-       if RELEASE_BUILD:
-               prefix = TARGET_CPU_ARCH + '-'
-       else:
-               prefix = TARGET_CPU_ARCH + 'd-'
-       time_obj = libcoap_env.Object(ARDUINO_HOME + '/libraries/Time/Time.cpp', OBJPREFIX=prefix)
-       libcoap_src.append(time_obj)
 else:
        libcoap_src.append(['../ocsocket/src/ocsocket.c'])
 
-libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap')
-i_lc = libcoap_env.Install(BUILD_DIR, libcoap)
-Alias('libcoap', i_lc)
-env.AppendUnique(TS = ['libcoap'])
\ No newline at end of file
+if target_os == 'arduino':
+       libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
+else:
+       libcoap = libcoap_env.SharedLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
+
+libcoap_env.InstallTarget(libcoap, 'libcoap')
diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript
new file mode 100644 (file)
index 0000000..f5a4222
--- /dev/null
@@ -0,0 +1,23 @@
+Import('env')
+
+arduino_simplecs_env = env.Clone()
+######################################################################
+# Build flags
+######################################################################
+arduino_simplecs_env.PrependUnique(CPPPATH = [
+               '../../../../../ocsocket/include',
+               '../../../../../logger/include',
+               '../../../../../stack/include',
+               '../../../../../../oc_logger/include'
+               ])
+
+arduino_simplecs_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+arduino_simplecs_env.PrependUnique(LIBS = ['octbstack', 'coap'])
+
+arduino_simplecs = arduino_simplecs_env.Program('SimpleClientServer', 'ocserver.cpp')
+env.CreateBin('SimpleClientServer')
+
+i_arduino_simplecs = arduino_simplecs_env.Install(env.get('BUILD_DIR'), arduino_simplecs)
+
+Alias('arduino_simplecs', i_arduino_simplecs)
+env.AppendTarget('arduino_simplecs')
\ No newline at end of file
index 3c7380f..12a7dcc 100644 (file)
@@ -1,10 +1,12 @@
 ##
 # Examples build script
 ##
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 # Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-examples_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
 
 ######################################################################
 # Build flags
@@ -19,34 +21,52 @@ examples_env.AppendUnique(CPPPATH = [
                '../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
-       examples_env.AppendUnique(CXXFLAGS = ['-std=c++11', '-Wall'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       examples_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+       # Note: 'pthread' is in libc for android. On other platform, if use
+       # new gcc(>4.9?) it isn't required, otherwise, it's required
+       if target_os != 'android':
+               examples_env.AppendUnique(LIBS = ['-lpthread'])
 
-examples_env.AppendUnique(LIBPATH = [BUILD_DIR])
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 examples_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger'])
 
-if BUILD_TARGET == 'android':
+if target_os == 'android':
        examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        examples_env.AppendUnique(LIBS = ['gnustl_static'])
-       examples_env.AppendUnique(LINKFLAGS = ['-static'])
        examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
 
-       if not RELEASE_BUILD:
+       if not env.get('RELEASE'):
                examples_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+       examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
 ######################################################################
 # Source files and Targets
 ######################################################################
 simpleserver = examples_env.Program('simpleserver', 'simpleserver.cpp')
+simpleserverHQ = examples_env.Program('simpleserverHQ', 'simpleserverHQ.cpp')
 simpleclient = examples_env.Program('simpleclient', 'simpleclient.cpp')
+simpleclientHQ = examples_env.Program('simpleclientHQ', 'simpleclientHQ.cpp')
+fridgeserver = examples_env.Program('fridgeserver', 'fridgeserver.cpp')
+fridgeclient = examples_env.Program('fridgeclient', 'fridgeclient.cpp')
 presenceserver = examples_env.Program('presenceserver', 'presenceserver.cpp')
 presenceclient = examples_env.Program('presenceclient', 'presenceclient.cpp')
 simpleclientserver = examples_env.Program('simpleclientserver', 'simpleclientserver.cpp')
 roomserver = examples_env.Program('roomserver', 'roomserver.cpp')
 roomclient = examples_env.Program('roomclient', 'roomclient.cpp')
+garageserver = examples_env.Program('garageserver', 'garageserver.cpp')
+garageclient = examples_env.Program('garageclient', 'garageclient.cpp')
 
-Alias("examples", [simpleserver, simpleclient, presenceserver, presenceclient,
-               simpleclientserver, roomserver, roomclient])
-env.AppendUnique(TS = ['examples'])
+Alias("examples", [simpleserver, simpleserverHQ, simpleclient, simpleclientHQ,
+               fridgeserver, fridgeclient, presenceserver, presenceclient,
+               simpleclientserver, roomserver, roomclient, garageserver,
+               garageclient])
+env.AppendTarget('examples')
 
-if BUILD_TARGET not in ['ios']:
-       SConscript(BUILD_DIR + 'examples/ocicuc/SConscript')
+#ios doesn't allow run application from terminal, so won't build these examples
+if target_os != 'ios':
+       SConscript('ocicuc/SConscript')
index eae0706..0b52b29 100644 (file)
@@ -1,11 +1,12 @@
 ##
 # Examples build script
 ##
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 # Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-ocicuc_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
+ocicuc_env = lib_env.Clone()
 ######################################################################
 # Build flags
 ######################################################################
@@ -18,22 +19,22 @@ ocicuc_env.AppendUnique(CPPPATH = [
                '../../oc_logger/include'
                ])
 
-ocicuc_env.AppendUnique(LIBPATH = [BUILD_DIR])
+ocicuc_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 ocicuc_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger'])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
-       ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++11'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++0x'])
 
-if BUILD_TARGET == 'android':
+if target_os == 'android':
        ocicuc_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        ocicuc_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
        ocicuc_env.AppendUnique(LIBS = ['boost_program_options-gcc-mt-1_49', 'boost_thread-gcc-mt-1_49', 'gnustl_static'])
-       ocicuc_env.AppendUnique(LINKFLAGS = ['-static'])
 
-       if not RELEASE_BUILD:
+       if not env.get('RELEASE'):
                ocicuc_env.AppendUnique(LIBS = ['log'])
 
-if BUILD_TARGET == 'darwin':
+if target_os == 'darwin':
        ocicuc_env.AppendUnique(LIBS = ['boost_program_options'])
 
 ######################################################################
@@ -41,8 +42,8 @@ if BUILD_TARGET == 'darwin':
 ######################################################################
 client = ocicuc_env.Program('client', ['client.cpp', 'driver.cpp', 'utility.cpp'])
 server = ocicuc_env.Program('server', ['server.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
-monoprocess = ocicuc_env.Program('monoprocess',
-               ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
+monoprocess = ocicuc_env.Program('monoprocess', ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
+small_example = ocicuc_env.Program('small_example', ['small_example.cpp', 'driver.cpp', 'utility.cpp'])
 
-Alias("examples_ocicuc", [client, server, monoprocess])
-env.AppendUnique(TS = ['examples_ocicuc'])
+Alias("examples_ocicuc", [client, server, monoprocess, small_example])
+env.AppendTarget('examples_ocicuc')
\ No newline at end of file
index 465627b..0b18e4d 100644 (file)
@@ -1,33 +1,36 @@
 ##
-# liboctbstack (static library) build script
+# liboc_logger (share library) build script
 ##
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 
-# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-
-liboc_logger_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
+liboc_logger_env = lib_env.Clone()
 ######################################################################
 # Build flags
 ######################################################################
 liboc_logger_env.PrependUnique(CPPPATH = ['include'])
 
-if BUILD_TARGET == 'android':
+target_os = env.get('TARGET_OS')
+if target_os == 'android':
        liboc_logger_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        liboc_logger_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+       liboc_logger_env.AppendUnique(LIBS = ['gnustl_static', 'log'])
 
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
-       liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99'])
-       liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x'])
+if target_os not in ['arduino', 'windows', 'winrt']:
+       liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99', '-fPIC'])
+       liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x', '-fPIC'])
 
 ######################################################################
 # Source files and Targets
 ######################################################################
-liboc_logger_core = liboc_logger_env.StaticLibrary('oc_logger_core', 'c/oc_logger.c',  OBJPREFIX='core')
-liboc_logger = liboc_logger_env.StaticLibrary('oc_logger',
+liboc_logger_core = liboc_logger_env.SharedLibrary('oc_logger_core', 'c/oc_logger.c',  OBJPREFIX='core_')
+liboc_logger = liboc_logger_env.SharedLibrary('oc_logger',
                ['c/oc_logger.c', 'c/oc_console_logger.c', 'cpp/oc_ostream_logger.cpp'])
-i_loggers = liboc_logger_env.Install(BUILD_DIR, [liboc_logger_core, liboc_logger])
-Alias('liboc_logger', i_loggers)
-env.AppendUnique(TS = ['liboc_logger'])
\ No newline at end of file
+
+liboc_logger_env.InstallTarget([liboc_logger_core, liboc_logger], 'liboc_logger')
+
+if target_os not in ['ios']:
+       SConscript('examples/SConscript')
diff --git a/resource/oc_logger/examples/SConscript b/resource/oc_logger/examples/SConscript
new file mode 100644 (file)
index 0000000..d3205ba
--- /dev/null
@@ -0,0 +1,35 @@
+##
+# liboc_logger examples build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+examples_env.PrependUnique(CPPPATH = ['../include'])
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+examples_env.AppendUnique(LIBS = ['oc_logger', 'stdc++'])
+
+target_os = env.get('TARGET_OS')
+if target_os == 'android':
+       examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+       examples_env.AppendUnique(LIBS = ['gnustl_static'])
+
+if target_os not in ['arduino', 'windows', 'winrt']:
+       examples_env.AppendUnique(CFLAGS = Split('-Wall -std=c99 -Werror'))
+       examples_env.AppendUnique(CXXFLAGS = Split('-Wall -std=c++0x'))
+
+######################################################################
+# Source files and Targets
+######################################################################
+examples_c = examples_env.Program('examples_c', 'test_logging.c', OBJPREFIX='c_')
+examples_cpp = examples_env.Program('examples_cpp', 'test_logging.cpp')
+
+Alias('liboc_logger_examples', [examples_c, examples_cpp])
+examples_env.AppendTarget('liboc_logger_examples')
\ No newline at end of file
index 2447934..7ec0c8e 100644 (file)
@@ -1,13 +1,13 @@
 ##
-# OCLib (static library) build script
+# OCLib (share library) build script
 ##
-Import('env', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
 
 # Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-
-oclib_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
 
+oclib_env = lib_env.Clone()
 ######################################################################
 # Build flags
 ######################################################################
@@ -21,26 +21,33 @@ oclib_env.AppendUnique(CPPPATH = [
                '../oc_logger/include'
                ])
 
-if BUILD_TARGET not in ['windows', 'winrt']:
-       oclib_env.AppendUnique(CXXFLAGS = ['-std=c++11', '-Wall'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+       oclib_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC'])
 
-if BUILD_TARGET == 'android':
+if target_os == 'android':
        oclib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
        oclib_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+       oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger', 'boost_thread-gcc-mt-1_49', 'gnustl_static', 'log'])
+
+if target_os in ['darwin', 'ios']:
+       oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger'])
 
 ######################################################################
 # Source files and Targets
 ######################################################################
 oclib_src = [
                'OCPlatform.cpp',
+               'OCPlatform_impl.cpp',
                'OCResource.cpp',
                'OCUtilities.cpp',
                'OCException.cpp',
+               'OCRepresentation.cpp',
                'InProcServerWrapper.cpp',
                'InProcClientWrapper.cpp'
        ]
 
-oclib = oclib_env.StaticLibrary('oc', oclib_src)
-i_ocl = oclib_env.Install(BUILD_DIR, oclib)
-Alias('liboc', i_ocl)
-env.AppendUnique(TS = ['liboc'])
\ No newline at end of file
+oclib = oclib_env.SharedLibrary('oc', oclib_src)
+oclib_env.InstallTarget(oclib, 'liboc')
index 2cf1cfc..a22bc36 100644 (file)
@@ -4,75 +4,66 @@
 #Note: The paths must keep consistent with oic-utilities
 ######################################################################
 import os
+import platform
 
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'SRC_TOP_DIR')
+Import('env', 'lib_env')
 
-# Add 'OIC_UTILS' build option for user to set oic-utilities project path
-default_dir = os.path.abspath(SRC_TOP_DIR + '/../oic-utilities')
-OIC_UTILS = ARGUMENTS.get('OIC_UTILS', default_dir)
-if not os.path.exists(OIC_UTILS):
-       print '''
-*********************************** Error: ************************************
-*   oic-utilities project directory(OIC_UTILS) isn't set properly, please set *
-* enviornment variable OIC_UTILS or set it in command line:                   *
-*     # scons  OIC_UTILS=<path to oic-utilities> ...                          *
-*******************************************************************************
-'''
-       Exit(1)
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
 
-if env.get('OIC_UTILS') is None:
-       vars = Variables()
-       vars.Add(PathVariable('OIC_UTILS', 'oic-utilities project path', OIC_UTILS))
-       vars.Update(env)
-       Help(vars.GenerateHelpText(env))
-       Export('OIC_UTILS')
+if target_os not in ['linux', 'darwin']:
+       utils_path = env.get('OIC_UTILS')
 
-       ######################################################################
-       # Check dependent packages (Linux)
-       ######################################################################
-       if BUILD_TARGET == 'linux':
-               # Delete the temp files of configuration
-               if env.GetOption('clean'):
-                       if os.path.exists(SRC_TOP_DIR + 'config.log'):
-                               Execute(Delete(SRC_TOP_DIR + 'config.log'))
-                               Execute(Delete(SRC_TOP_DIR + '.sconsign.dblite'))
-                               Execute(Delete(SRC_TOP_DIR + '.sconf_temp'))
-               elif not env.GetOption('help'):
-                       conf = Configure(env)
+######################################################################
+# Check dependent packages (Linux only)
+######################################################################
+if target_os == 'linux':
+       if not env.GetOption('help'):
+               if not target_arch == platform.machine():
+                       print '''
+*********************************** Warning ***********************************
+* You are trying cross build, please make sure (%s) version libraries are
+* installed!                                                                 *
+*******************************************************************************
+''' % target_arch
 
-                       if not conf.CheckLib('boost_program_options'):
-                               print 'Did not find boost_program_options, exiting!'
-                               Exit(1)
+               conf = Configure(lib_env)
 
-                       conf.Finish()
+               if not conf.CheckLib('boost_program_options'):
+                       print 'Did not find boost_program_options, exiting!'
+                       Exit(1)
 
-       ######################################################################
-       # The 'include' path of third party libraries
-       ######################################################################
+               conf.Finish()
 
-       if BUILD_TARGET == 'android':
-               env.AppendUnique(CPPPATH = [OIC_UTILS + '/android/boost/include'])
+######################################################################
+# The 'include' path of third party libraries
+######################################################################
+if target_os == 'android':
+       lib_env.AppendUnique(CPPPATH = [utils_path + '/android/boost/include'])
 
-       ######################################################################
-       # The path of third party libraries binary
-       ######################################################################
-       if BUILD_TARGET == 'android':
-               arch = TARGET_CPU_ARCH
-               if arch == 'armeabi-v7a-hard':
-                       arch = 'armeabi-v7a'
+######################################################################
+# The path of third party libraries binary
+######################################################################
+if target_os == 'android':
+       if target_arch == 'armeabi-v7a-hard':
+               target_arch = 'armeabi-v7a'
 
-               if arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+       if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+               if not env.GetOption('help') and not env.GetOption('clean'):
                        print '''
 *********************************** Warning ***********************************
-* current only x86, armeabi, armeabi-v7a libraries are offered!               *
+* current only x86, armeabi, armeabi-v7a libraries are provided!              *
 *******************************************************************************
 '''
-               else:
-                       env.AppendUnique(LIBPATH = [OIC_UTILS + '/android/boost/libs/' + arch])
+       else:
+               lib_env.AppendUnique(LIBPATH = [utils_path + '/android/boost/libs/' + target_arch])
+               # Too much boost warning, suppress the warning
+               lib_env.AppendUnique(CCFLAGS = ['-w'])
 
-       elif BUILD_TARGET == 'ios':
-               env.AppendUnique(FRAMEWORKPATH = [OIC_UTILS + '/ios/frameworks/'])
-               env.AppendUnique(FRAMEWORKS = ['boost'])
-       elif BUILD_TARGET == 'darwin':
-               env.AppendUnique(CPPPATH = ['/usr/local/include'])
-               env.AppendUnique(LIBPATH = ['/usr/local/lib'])
\ No newline at end of file
+elif target_os == 'ios':
+       lib_env.AppendUnique(FRAMEWORKPATH = [utils_path + '/ios/frameworks/'])
+       lib_env.AppendUnique(FRAMEWORKS = ['boost'])
+elif target_os == 'darwin':
+       lib_env.AppendUnique(CPPPATH = ['/usr/local/include'])
+       lib_env.AppendUnique(LIBPATH = ['/usr/local/lib'])
\ No newline at end of file
diff --git a/scons_script_how_to.txt b/scons_script_how_to.txt
new file mode 100644 (file)
index 0000000..c210419
--- /dev/null
@@ -0,0 +1,235 @@
+== How to write iotivity build script ==
+
+Iotivity projects are built with Scons. Scons is a cross-platform build tool,
+it's quite similar to 'make'. 'SConstruct' is the entrance of scons build, it's
+equivalent to 'Makefile' to 'make'.
+
+This document only a brief reference. Detail about how to write scons script,
+please refer to:
+       http://www.scons.org/doc/production/HTML/scons-user.html#
+
+== Background: How to control source code compiling ==
+
+Environment is a base conception of Scons. An environment is a collection of
+values that can affect how a program is built.
+
+e.g. There is a C file named hello.c, enter the following into a file named
+SConstruct:
+       env = Environment()
+       env.Program('H', 'hello.c')
+
+When run Scons in console, following will be executed:
+cc -o hello.o -c hello.c
+cc -o H hello.o
+
+If you would like keep debug information in the binary, '-g' flag should be added
+when build the source code. To do this, append a C compiler flags as following:
+       env = Environment()
+       env.AppendUnique(CFLAGS = ['-g'])
+       env.Program('H', 'hello.c')
+
+When run Scons, following will be executed:
+cc -o hello.o -c -g hello.c
+cc -o H hello.o
+
+In above example, 'CFLAGS' is changed. Following list the frequently used keys:
+
+CFLAGS: General options that are passed to the C compiler
+CCFLAGS: General options that are passed to the C & C++ compiler
+CXXFLAGS: General options that are passed to the C++ compiler
+CPPPATH: The directories that the preprocessor will search for include headers.
+CPPDEFINES: Platform independent specification of C preprocessor definitions.
+
+Note: CPPPATH and CPPDEFINES is common for all compiler. But others are
+compiler specific, when change the key value, it may requried to specify the
+target platform(actually the compiler).
+
+e.g.
+       env.AppendUnique(CPPPATH = ['.', 'include'])
+       env.AppendUnique(CPPDEFINES = ['NDEBUG', 'VER_TEST'])
+Above two lines are fine for all target platform. but below line:
+       env.AppenUnique(CXXFLAGS = ['-g'])
+is only fine for gcc compiler, as '-g' is a gcc flag, other compiler may don't
+understand it. so it may should be:
+       if target_os not in ['windows', 'winrt']:
+               env.AppenUnique(CXXFLAGS = ['-g'])
+
+Still take the hello.c as example. Assume hello.h is in ./include/ directory,
+#include "hello.h"
+int main(int argc, char** argv)
+{
+#ifdef LANG_FR
+    printf("Bonjour\n");
+#else
+       printf("Hello\n");
+#endif
+}
+
+The Scons configure file should as following:
+       env = Environment()
+       env.AppendUnique(CFLAGS = ['-g'])
+       env.AppendUnique(CPPPATH = ['include'])
+       env.AppendUnique(CPPDEFINES = ['LANG_FR'])
+       env.Program('H', 'hello.c')
+
+When run Scons, following will be executed:
+cc -o hello.o -c -g -Iinclude -DLANG_FR hello.c
+cc -o H hello.o
+
+=== Get extra information ===
+
+In above example, 'target_os' is used. How to get it?
+
+User can build iotivity project on linux / windows / MAC OSX for various
+targets(Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...). Most
+platform specific configures have been done in the common scripts whitch are in
+build_common. The common scripts prepare an environment named 'env' with
+target platform specific configuration.
+
+When write iotivity project build script, you can get this environment as
+following:
+       Import('env')
+
+You can use 'env' directly after import it. You can also clone a new environment
+and update its keys.
+
+       new_env1 = Clone('env')
+       new_env2 = Clone('env')
+       new_env1.AppendUnqiue(xxx = [...])
+       new_env2.AppendUnqiue(xxx = [...])
+
+The 'env' environment contains platform specific configuration, besides, there is
+some common information. You can get the information with following line:
+       env.get('XXX')
+
+XXX is the information name, below are the extra information added by iotivity
+common scrirpts:
+BUILD_DIR: the path of the build directory
+SRC_DIR: the path of the top directory of the source code
+OIC_UTILS: the path of oic-utilities project
+RELEASE: boolean. True - release build, False - debug build
+TARGET_OS: the name of the target OS. The possible value depends on the host
+       platform. Bellow is the list of host and possible target OS. (darwin means
+       MAC OSX)
+               linux: linux / android / arduino
+(the line means on linux, you can build the project for linux/android/arduino)
+               windows: windows / winrt / android / arduino
+               darwin: darwin / ios / android / arduino
+
+TARGET_ARCH: the target CPU arch. Its possible value depend on the target OS
+       Bellow list the target OS and allowed CPU architecture.
+               linux: x86 / x86_64 / arm / arm64
+(above line means if the target OS is linux, the CPU arch can be x86/x86_64/arm/arm64)
+               android: x86 / x86_64 / armeabi / armeabi-v7a / armeabi-v7a-hard / arm64-v8a
+               windows: x86 / amd64 / arm
+               winrt: arm
+               darwin: i386 / x86_64
+               ios: i386 / x86_64 / armv7 / armv7s / arm64,
+               arduino: avr / arm
+
+=== Extra functions ===
+
+For convenience, in the common scripts, some extra functions are added.
+
+PrintTargets(): print all targets in the help information.
+AppendTarget(target): add 'target' into targets list, when use PrintTargets,
+       the 'target' will be print.
+InstallTarget(files, name): it takes the same action as AppendTarget, besides,
+       it installs the 'files' to BUILD_DIR.
+
+Following functions are only for Arduino:
+ImportLib(lib): Arduino IDE includes many libraries. To control the binary size,
+by default, no library is used. If your project use some libraries, you can
+import the lib with this function. 'lib' is the name of the lib to import.
+The include path will be auto added to the environment and the library will be
+built and linked into the final binary.
+
+CreateBin('bin', src): For Arduino, after build the program, it's required to
+be converted into specific format (e.g .hex). This function will genearate the
+required .hex (and .eep if target arch is avr) file.
+
+UploadHelp(): For different board, the upload command line is different, this
+function print the recommended upload command line. You can see the recommended
+upload command line in the help information.
+
+==== Scripts Hierarchy ====
+
+Scons provides a function 'SConscript(scripts, [exports, variant_dir, duplicate])'
+It tells scons to execute one or more subsidiary configuration files(A script,
+usually named SConscript). Take below project hierarchy as example to show how
+to organize the scripts.
+
+               prj
+               |-------prj_1
+               |               |--------sub_prj_11
+               |               |--------sub_prj_..
+               |               |--------sub_prj_1n
+               |-------prj_2
+               |
+               | ... ...
+               |
+               |-------prj_n
+
+As above project hierarchy, in 'SConstruct' file in the 'prj' directory, there
+should include some lines like these:
+
+#Please change this part according to the organization of your projects.
+#Note: To make the output is in build_dir, the path of the scripts should
+#be relevant to build_dir
+SConscript(build_dir + 'prj_1/SConscript')
+SConscript(build_dir + 'prj_2/SConscript')
+... ...
+SConscript(build_dir + 'prj_n/SConscript')
+
+
+It's the same, in the 'prj_1/SConscript', there should include lines like
+these:
+SConscript('sub_prj_11/SConscript')
+... ...
+SConscript('sub_prj_1n/SConscript')
+
+The path is relevant to 'prj_1/SConscript'. You can also use the full path
+build_dir + 'prj_1/sub_prj_1x/SConscript', but it's not recommended.
+
+Above just to show a usual way to manage subsidiary scripts. You don't need
+restrictly follow it.
+
+==== The content of a typical script ====
+
+After run the scripts in build_common (usally it's done at the beginning of
+SConstruct), an global environment 'env' is exported, 'env' has include the
+default configuration of the target OS and arch. 'env' is used in all projects,
+should avoid to change its keys. To avoid change 'env', usually clone 'env' and
+update it accroding to the requirement of cuurent sub project. Then specify the
+target(usually binary) to build.
+
+Below is an example:
+       # import the global enviroment 'env'
+       Import('env')
+
+       # Clone a new enviroment from 'env'
+       new_env = env.Clone()
+
+       # Update the new enviroment, usally include add header file paths,
+       # library path, libs to link and other compiler flags. This part is
+       # optional. If not present, the default configuration will be used
+       new_env.AppeneUnique(xxx = [ .... ])
+
+       # Specify the target(application, library, object or others) to build
+       ts = new_env.Program('progam_name', [source_list])
+
+       # Install the target (optional)
+       new_env.InstallTarget(ts, 'target_name')
+or
+       new_env.Alias('target_name', ts)
+       new_env.AppendTarget('target_name')
+
+==== Tips ====
+1. library order: if A lib use B lib, both A and B are linked to target T, the
+       when specify libraries, A should in front of B, otherwise there may be link
+       error.
+2. On android:
+       (1)'pthread' is in libc. So don't use '-lpthread' for android
+       (2)By default 'rtti' and 'exception' is disabled, to enable it, you need
+       add flags '-frtti' and '-fexceptions'
+       (3)If STL is used, need link 'gnustl_static' library
diff --git a/service/SConscript b/service/SConscript
new file mode 100644 (file)
index 0000000..4f49777
--- /dev/null
@@ -0,0 +1,25 @@
+##
+# 'service' sub-project main build script
+#
+##
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os != 'arduino':
+       # Build things manager project
+       SConscript('things-manager/SConscript')
+
+       # Build soft sensor manager project
+       SConscript('soft-sensor-manager/SConscript')
+
+       # Build protocol plugin project
+       # protocol-plugin use 'sys/inotify.h', this header file doesn't
+       # exist on MAC OSX
+       if target_os not in ['darwin', 'ios']:
+               SConscript('protocol-plugin/SConscript')
+
+       # Build notification manager project
+       SConscript('notification-manager/SConscript')
+else:
+       SConscript('notification-manager/SampleApp/arduino/SConscript')
diff --git a/service/notification-manager/SConscript b/service/notification-manager/SConscript
new file mode 100644 (file)
index 0000000..a5e52dd
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+notimgr_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+notimgr_env.AppendUnique(CPPPATH = ['NotificationManager/include'])
+notimgr_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap'])
+
+if target_os not in ['windows', 'winrt']:
+       notimgr_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+if target_os == 'linux':
+       notimgr_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+       notimgr_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       notimgr_env.AppendUnique(LIBS = ['gnustl_static'])
+       notimgr_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+       if not env.get('RELEASE'):
+               notimgr_env.AppendUnique(LIBS = ['log'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+NOTI_SRC_DIR = 'NotificationManager/src/'
+notimgr_src = [
+               NOTI_SRC_DIR + 'LinuxMain.cpp',
+               NOTI_SRC_DIR + 'NotificationManager.cpp',
+               NOTI_SRC_DIR + 'RegistrationManager.cpp',
+               NOTI_SRC_DIR + 'ResourceManager.cpp',
+               NOTI_SRC_DIR + 'VirtualRepresentation.cpp']
+
+notificationmanager = notimgr_env.Program('noti_manager', notimgr_src)
+
+notimgr_env.InstallTarget(notificationmanager, 'notificationmanager')
+
+# Go to build sample apps
+SConscript('SampleApp/SConscript')
diff --git a/service/notification-manager/SampleApp/SConscript b/service/notification-manager/SampleApp/SConscript
new file mode 100644 (file)
index 0000000..d59dc6d
--- /dev/null
@@ -0,0 +1,10 @@
+##
+# Examples build script
+##
+Import('env')
+
+target_os = env.get('TARGET_OS')
+if target_os == 'linux':
+       SConscript('linux/SConscript')
+elif target_os == 'arduino':
+       SConscript('arduino/SConscript')
\ No newline at end of file
diff --git a/service/notification-manager/SampleApp/arduino/SConscript b/service/notification-manager/SampleApp/arduino/SConscript
new file mode 100644 (file)
index 0000000..04602f6
--- /dev/null
@@ -0,0 +1,33 @@
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+notimgr_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+resource_path = env.get('SRC_DIR') + '/resource'
+
+notimgr_env.AppendUnique(CPPPATH = [
+               resource_path + '/oc_logger/include',
+               resource_path + '/csdk/stack/include',
+               resource_path + '/csdk/ocsocket/include',
+               resource_path + '/csdk/logger/include'
+               ])
+
+notimgr_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+notimgr_env.PrependUnique(LIBS = ['octbstack', 'coap'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+thserver = notimgr_env.Program('thserver', 'thserver.cpp')
+notimgr_env.CreateBin('thserver')
+
+i_thserver = notimgr_env.Install(env.get('BUILD_DIR'), thserver)
+
+Alias('thserver_arduino', i_thserver)
+env.AppendTarget('thserver_arduino')
\ No newline at end of file
diff --git a/service/notification-manager/SampleApp/linux/SConscript b/service/notification-manager/SampleApp/linux/SConscript
new file mode 100644 (file)
index 0000000..be46453
--- /dev/null
@@ -0,0 +1,22 @@
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+notimgr_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+notimgr_env.AppendUnique(CPPPATH = ['../../NotificationManager/include'])
+notimgr_env.AppendUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap', 'pthread'])
+notimgr_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+sampleprovider = notimgr_env.Program('sampleprovider', 'sampleProvider/SampleProvider.cpp')
+sampleconsumer = notimgr_env.Program('sampleconsumer', 'sampleConsumer/SampleConsumer.cpp')
\ No newline at end of file
diff --git a/service/protocol-plugin/SConscript b/service/protocol-plugin/SConscript
new file mode 100644 (file)
index 0000000..d8db971
--- /dev/null
@@ -0,0 +1,13 @@
+##
+# protocol plugin build script
+##
+Import('env')
+
+SConscript('lib/cpluff/SConscript')
+SConscript('plugin-manager/SConscript')
+
+#The code include pthread_cancel method, can't build on android
+if env.get('TARGET_OS') != 'android':
+       SConscript('plugins/SConscript')
+
+SConscript('sample-app/SConscript')
index 7def475..53f0396 100644 (file)
@@ -20,14 +20,14 @@ plugins:
        cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE)
 
 sample-app:
-       cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE)
-       cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/fan-control/fanclient release/
+       cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE)
+       cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libpmimpl.so $(PROTOCOL_ROOT)sample-app/linux/mqtt/
+       cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/mqtt/mqttclient release/
        
 
 clean:
        cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE) clean
        cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE) clean
        cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE) clean
-       cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE) clean
-       cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE) clean
+       cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE) clean
        rm -rf release
diff --git a/service/protocol-plugin/lib/cpluff/SConscript b/service/protocol-plugin/lib/cpluff/SConscript
new file mode 100644 (file)
index 0000000..58e79f7
--- /dev/null
@@ -0,0 +1,31 @@
+##
+#c-pluff build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+cpluff_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+cpluff_env.AppendUnique(CPPPATH = ['libcpluff/'])
+if target_os not in ['windows', 'winrt']:
+       cpluff_env.AppendUnique(CFLAGS = ['-g','-fPIC', '-DPIC',
+                               '-DDLOPEN_POSIX',
+                               '-DCP_HOST=\\"' + platform.platform() + '\\"',
+                               '-DCP_SHREXT=\\".so\\"',
+                               '-DCP_FNAMESEP_CHAR=\\"\'/\'\\"',
+                               '-DCP_THREADS=\\"Posix\\"'])
+       cpluff_env.AppendUnique(LIBS = ['dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+cpluff_src = [f for f in env.Glob('libcpluff/*.c') if os.path.basename(f.path) not in ['thread_windows.c']]
+cpluff_src.extend(env.Glob('kazlib/*.c'))
+
+cpluff = cpluff_env.StaticLibrary('cpluff', cpluff_src)
+cpluff_env.InstallTarget(cpluff, 'libcpluff')
\ No newline at end of file
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml.hpp
new file mode 100644 (file)
index 0000000..9ddf195
--- /dev/null
@@ -0,0 +1,2601 @@
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+    #include <cstdlib>      // For std::size_t
+    #include <cassert>      // For assert
+    #include <new>          // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4). 
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+    #pragma warning(push)
+    #pragma warning(disable:4127)   // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+    
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+    //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, 
+    //! this function is called to notify user about the error.
+    //! It must be defined by the user.
+    //! <br><br>
+    //! This function cannot return. If it does, the results are undefined.
+    //! <br><br>
+    //! A very simple definition might look like that:
+    //! <pre>
+    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+    //! {
+    //!     std::cout << "Parse error: " << what << "\n";
+    //!     std::abort();
+    //! }
+    //! </pre>
+    //! \param what Human readable description of the error.
+    //! \param where Pointer to character data where error was detected.
+    void parse_error_handler(const char *what, void *where);
+}
+
+#else
+    
+#include <exception>    // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+    //! Parse error exception. 
+    //! This exception is thrown by the parser when an error occurs. 
+    //! Use what() function to get human-readable error message. 
+    //! Use where() function to get a pointer to position within source text where error was detected.
+    //! <br><br>
+    //! If throwing exceptions by the parser is undesirable, 
+    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+    //! This function must be defined by the user.
+    //! <br><br>
+    //! This class derives from <code>std::exception</code> class.
+    class parse_error: public std::exception
+    {
+    
+    public:
+    
+        //! Constructs parse error
+        parse_error(const char *what, void *where)
+            : m_what(what)
+            , m_where(where)
+        {
+        }
+
+        //! Gets human readable description of error.
+        //! \return Pointer to null terminated description of the error.
+        virtual const char *what() const throw()
+        {
+            return m_what;
+        }
+
+        //! Gets pointer to character data where error happened.
+        //! Ch should be the same as char type of xml_document that produced the error.
+        //! \return Pointer to location within the parsed string where error occured.
+        template<class Ch>
+        Ch *where() const
+        {
+            return reinterpret_cast<Ch *>(m_where);
+        }
+
+    private:  
+
+        const char *m_what;
+        void *m_where;
+
+    };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+    // Size of static memory block of memory_pool.
+    // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+    // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+    #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+    // Size of dynamic memory block of memory_pool.
+    // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+    // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+    #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+    // Memory allocation alignment.
+    // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+    // All memory allocations for nodes, attributes and strings will be aligned to this value.
+    // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+    #define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+    // Forward declarations
+    template<class Ch> class xml_node;
+    template<class Ch> class xml_attribute;
+    template<class Ch> class xml_document;
+    
+    //! Enumeration listing all node types produced by the parser.
+    //! Use xml_node::type() function to query node type.
+    enum node_type
+    {
+        node_document,      //!< A document node. Name and value are empty.
+        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
+        node_data,          //!< A data node. Name is empty. Value contains data text.
+        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
+        node_comment,       //!< A comment node. Name is empty. Value contains comment text.
+        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+        node_pi             //!< A PI node. Name contains target. Value contains instructions.
+    };
+
+    ///////////////////////////////////////////////////////////////////////
+    // Parsing flags
+
+    //! Parse flag instructing the parser to not create data nodes. 
+    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_data_nodes = 0x1;            
+
+    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+    //! Can be combined with other flags by use of | operator.
+    //! Note that child data nodes of element node take precendence over its value when printing. 
+    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_element_values = 0x2;
+    
+    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+    //! By default zero terminators are placed, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_string_terminators = 0x4;
+    
+    //! Parse flag instructing the parser to not translate entities in the source text.
+    //! By default entities are translated, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_entity_translation = 0x8;
+    
+    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+    //! By default, UTF-8 handling is enabled.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_utf8 = 0x10;
+    
+    //! Parse flag instructing the parser to create XML declaration node.
+    //! By default, declaration node is not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_declaration_node = 0x20;
+    
+    //! Parse flag instructing the parser to create comments nodes.
+    //! By default, comment nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_comment_nodes = 0x40;
+    
+    //! Parse flag instructing the parser to create DOCTYPE node.
+    //! By default, doctype node is not created.
+    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_doctype_node = 0x80;
+    
+    //! Parse flag instructing the parser to create PI nodes.
+    //! By default, PI nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_pi_nodes = 0x100;
+    
+    //! Parse flag instructing the parser to validate closing tag names. 
+    //! If not set, name inside closing tag is irrelevant to the parser.
+    //! By default, closing tags are not validated.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_validate_closing_tags = 0x200;
+    
+    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+    //! By default, whitespace is not trimmed. 
+    //! This flag does not cause the parser to modify source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_trim_whitespace = 0x400;
+
+    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+    //! By default, whitespace is not normalized. 
+    //! If this flag is specified, source text will be modified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_normalize_whitespace = 0x800;
+
+    // Compound flags
+    
+    //! Parse flags which represent default behaviour of the parser. 
+    //! This is always equal to 0, so that all other flags can be simply ored together.
+    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+    //! This also means that meaning of each flag is a <i>negation</i> of the default setting. 
+    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+    //! and using the flag will disable it.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_default = 0;
+    
+    //! A combination of parse flags that forbids any modifications of the source text. 
+    //! This also results in faster parsing. However, note that the following will occur:
+    //! <ul>
+    //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+    //! <li>entities will not be translated</li>
+    //! <li>whitespace will not be normalized</li>
+    //! </ul>
+    //! See xml_document::parse() function.
+    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+    
+    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+    
+    //! A combination of parse flags resulting in largest amount of data being extracted. 
+    //! This usually results in slowest parsing.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internals
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Struct that contains lookup tables for the parser
+        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+        template<int Dummy>
+        struct lookup_tables
+        {
+            static const unsigned char lookup_whitespace[256];              // Whitespace table
+            static const unsigned char lookup_node_name[256];               // Node name table
+            static const unsigned char lookup_text[256];                    // Text table
+            static const unsigned char lookup_text_pure_no_ws[256];         // Text table
+            static const unsigned char lookup_text_pure_with_ws[256];       // Text table
+            static const unsigned char lookup_attribute_name[256];          // Attribute name table
+            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
+            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
+            static const unsigned char lookup_digits[256];                  // Digits
+            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
+        };
+
+        // Find length of the string
+        template<class Ch>
+        inline std::size_t measure(const Ch *p)
+        {
+            const Ch *tmp = p;
+            while (*tmp) 
+                ++tmp;
+            return tmp - p;
+        }
+
+        // Compare strings for equality
+        template<class Ch>
+        inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+        {
+            if (size1 != size2)
+                return false;
+            if (case_sensitive)
+            {
+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (*p1 != *p2)
+                        return false;
+            }
+            else
+            {
+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+                        return false;
+            }
+            return true;
+        }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////
+    // Memory pool
+    
+    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+    //! In most cases, you will not need to use this class directly. 
+    //! However, if you need to create nodes manually or modify names/values of nodes, 
+    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. 
+    //! Not only is this faster than allocating them by using <code>new</code> operator, 
+    //! but also their lifetime will be tied to the lifetime of document, 
+    //! possibly simplyfing memory management. 
+    //! <br><br>
+    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. 
+    //! You can also call allocate_string() function to allocate strings.
+    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called, 
+    //! or when the pool is destroyed.
+    //! <br><br>
+    //! It is also possible to create a standalone memory_pool, and use it 
+    //! to allocate nodes, whose lifetime will not be tied to any document.
+    //! <br><br>
+    //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. 
+    //! Until static memory is exhausted, no dynamic memory allocations are done.
+    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+    //! by using global <code>new[]</code> and <code>delete[]</code> operators. 
+    //! This behaviour can be changed by setting custom allocation routines. 
+    //! Use set_allocator() function to set them.
+    //! <br><br>
+    //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+    //! This value defaults to the size of pointer on target architecture.
+    //! <br><br>
+    //! To obtain absolutely top performance from the parser,
+    //! it is important that all nodes are allocated from a single, contiguous block of memory.
+    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+    //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code> 
+    //! to obtain best wasted memory to performance compromise.
+    //! To do it, define their values before rapidxml.hpp file is included.
+    //! \param Ch Character type of created nodes. 
+    template<class Ch = char>
+    class memory_pool
+    {
+        
+    public:
+
+        //! \cond internal
+        typedef void *(alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
+        typedef void (free_func)(void *);              // Type of user-defined function used to free memory
+        //! \endcond
+        
+        //! Constructs empty pool with default allocator functions.
+        memory_pool()
+            : m_alloc_func(0)
+            , m_free_func(0)
+        {
+            init();
+        }
+
+        //! Destroys pool and frees all the memory. 
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Nodes allocated from the pool are no longer valid.
+        ~memory_pool()
+        {
+            clear();
+        }
+
+        //! Allocates a new node from the pool, and optionally assigns name and value to it. 
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param type Type of node to create.
+        //! \param name Name to assign to the node, or 0 to assign no name.
+        //! \param value Value to assign to the node, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated node. This pointer will never be NULL.
+        xml_node<Ch> *allocate_node(node_type type, 
+                                    const Ch *name = 0, const Ch *value = 0, 
+                                    std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+            xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+            if (name)
+            {
+                if (name_size > 0)
+                    node->name(name, name_size);
+                else
+                    node->name(name);
+            }
+            if (value)
+            {
+                if (value_size > 0)
+                    node->value(value, value_size);
+                else
+                    node->value(value);
+            }
+            return node;
+        }
+
+        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param name Name to assign to the attribute, or 0 to assign no name.
+        //! \param value Value to assign to the attribute, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated attribute. This pointer will never be NULL.
+        xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0, 
+                                              std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+            xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+            if (name)
+            {
+                if (name_size > 0)
+                    attribute->name(name, name_size);
+                else
+                    attribute->name(name);
+            }
+            if (value)
+            {
+                if (value_size > 0)
+                    attribute->value(value, value_size);
+                else
+                    attribute->value(value);
+            }
+            return attribute;
+        }
+
+        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+        //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+        //! \return Pointer to allocated char array. This pointer will never be NULL.
+        Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+        {
+            assert(source || size);     // Either source or size (or both) must be specified
+            if (size == 0)
+                size = internal::measure(source) + 1;
+            Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+            if (source)
+                for (std::size_t i = 0; i < size; ++i)
+                    result[i] = source[i];
+            return result;
+        }
+
+        //! Clones an xml_node and its hierarchy of child nodes and attributes.
+        //! Nodes and attributes are allocated from this memory pool.
+        //! Names and values are not cloned, they are shared between the clone and the source.
+        //! Result node can be optionally specified as a second parameter, 
+        //! in which case its contents will be replaced with cloned source node.
+        //! This is useful when you want to clone entire document.
+        //! \param source Node to clone.
+        //! \param result Node to put results in, or 0 to automatically allocate result node
+        //! \return Pointer to cloned node. This pointer will never be NULL.
+        xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+        {
+            // Prepare result node
+            if (result)
+            {
+                result->remove_all_attributes();
+                result->remove_all_nodes();
+                result->type(source->type());
+            }
+            else
+                result = allocate_node(source->type());
+
+            // Clone name and value
+            result->name(source->name(), source->name_size());
+            result->value(source->value(), source->value_size());
+
+            // Clone child nodes and attributes
+            for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+                result->append_node(clone_node(child));
+            for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+            return result;
+        }
+
+        //! Clears the pool. 
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Any nodes or strings allocated from the pool will no longer be valid.
+        void clear()
+        {
+            while (m_begin != m_static_memory)
+            {
+                char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+                if (m_free_func)
+                    m_free_func(m_begin);
+                else
+                    delete[] m_begin;
+                m_begin = previous_begin;
+            }
+            init();
+        }
+
+        //! Sets or resets the user-defined memory allocation functions for the pool.
+        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+        //! Allocation function must not return invalid pointer on failure. It should either throw,
+        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program. 
+        //! If it returns invalid pointer, results are undefined.
+        //! <br><br>
+        //! User defined allocation functions must have the following forms:
+        //! <br><code>
+        //! <br>void *allocate(std::size_t size);
+        //! <br>void free(void *pointer);
+        //! </code><br>
+        //! \param af Allocation function, or 0 to restore default function
+        //! \param ff Free function, or 0 to restore default function
+        void set_allocator(alloc_func *af, free_func *ff)
+        {
+            assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
+            m_alloc_func = af;
+            m_free_func = ff;
+        }
+
+    private:
+
+        struct header
+        {
+            char *previous_begin;
+        };
+
+        void init()
+        {
+            m_begin = m_static_memory;
+            m_ptr = align(m_begin);
+            m_end = m_static_memory + sizeof(m_static_memory);
+        }
+        
+        char *align(char *ptr)
+        {
+            std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+            return ptr + alignment;
+        }
+        
+        char *allocate_raw(std::size_t size)
+        {
+            // Allocate
+            void *memory;   
+            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
+            {
+                memory = m_alloc_func(size);
+                assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+            }
+            else
+            {
+                memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+                if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+                    RAPIDXML_PARSE_ERROR("out of memory", 0);
+#endif
+            }
+            return static_cast<char *>(memory);
+        }
+        
+        void *allocate_aligned(std::size_t size)
+        {
+            // Calculate aligned pointer
+            char *result = align(m_ptr);
+
+            // If not enough memory left in current pool, allocate a new pool
+            if (result + size > m_end)
+            {
+                // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+                std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+                if (pool_size < size)
+                    pool_size = size;
+                
+                // Allocate
+                std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
+                char *raw_memory = allocate_raw(alloc_size);
+                    
+                // Setup new pool in allocated memory
+                char *pool = align(raw_memory);
+                header *new_header = reinterpret_cast<header *>(pool);
+                new_header->previous_begin = m_begin;
+                m_begin = raw_memory;
+                m_ptr = pool + sizeof(header);
+                m_end = raw_memory + alloc_size;
+
+                // Calculate aligned pointer again using new pool
+                result = align(m_ptr);
+            }
+
+            // Update pool and return aligned pointer
+            m_ptr = result + size;
+            return result;
+        }
+
+        char *m_begin;                                      // Start of raw memory making up current pool
+        char *m_ptr;                                        // First free byte in current pool
+        char *m_end;                                        // One past last available byte in current pool
+        char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
+        alloc_func *m_alloc_func;                           // Allocator function, or 0 if default is to be used
+        free_func *m_free_func;                             // Free function, or 0 if default is to be used
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML base
+
+    //! Base class for xml_node and xml_attribute implementing common functions: 
+    //! name(), name_size(), value(), value_size() and parent().
+    //! \param Ch Character type to use
+    template<class Ch = char>
+    class xml_base
+    {
+
+    public:
+        
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        // Construct a base with empty name, value and parent
+        xml_base()
+            : m_name(0)
+            , m_value(0)
+            , m_parent(0)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+    
+        //! Gets name of the node. 
+        //! Interpretation of name depends on type of node.
+        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use name_size() function to determine length of the name.
+        //! \return Name of node, or empty string if node has no name.
+        Ch *name() const
+        {
+            return m_name ? m_name : nullstr();
+        }
+
+        //! Gets size of node name, not including terminator character.
+        //! This function works correctly irrespective of whether name is or is not zero terminated.
+        //! \return Size of node name, in characters.
+        std::size_t name_size() const
+        {
+            return m_name ? m_name_size : 0;
+        }
+
+        //! Gets value of node. 
+        //! Interpretation of value depends on type of node.
+        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use value_size() function to determine length of the value.
+        //! \return Value of node, or empty string if node has no value.
+        Ch *value() const
+        {
+            return m_value ? m_value : nullstr();
+        }
+
+        //! Gets size of node value, not including terminator character.
+        //! This function works correctly irrespective of whether value is or is not zero terminated.
+        //! \return Size of node value, in characters.
+        std::size_t value_size() const
+        {
+            return m_value ? m_value_size : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+    
+        //! Sets name of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it. 
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of name must be specified separately, because name does not have to be zero terminated.
+        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! \param name Name of node to set. Does not have to be zero terminated.
+        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+        void name(const Ch *name, std::size_t size)
+        {
+            m_name = const_cast<Ch *>(name);
+            m_name_size = size;
+        }
+
+        //! Sets name of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+        //! \param name Name of node to set. Must be zero terminated.
+        void name(const Ch *name)
+        {
+            this->name(name, internal::measure(name));
+        }
+
+        //! Sets value of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it. 
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of value must be specified separately, because it does not have to be zero terminated.
+        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! <br><br>
+        //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+        //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+        //! \param value value of node to set. Does not have to be zero terminated.
+        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+        void value(const Ch *value, std::size_t size)
+        {
+            m_value = const_cast<Ch *>(value);
+            m_value_size = size;
+        }
+
+        //! Sets value of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+        //! \param value Vame of node to set. Must be zero terminated.
+        void value(const Ch *value)
+        {
+            this->value(value, internal::measure(value));
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets node parent.
+        //! \return Pointer to parent node, or 0 if there is no parent.
+        xml_node<Ch> *parent() const
+        {
+            return m_parent;
+        }
+
+    protected:
+
+        // Return empty string
+        static Ch *nullstr()
+        {
+            static Ch zero = Ch('\0');
+            return &zero;
+        }
+
+        Ch *m_name;                         // Name of node, or 0 if no name
+        Ch *m_value;                        // Value of node, or 0 if no value
+        std::size_t m_name_size;            // Length of node name, or undefined of no name
+        std::size_t m_value_size;           // Length of node value, or undefined if no value
+        xml_node<Ch> *m_parent;             // Pointer to parent node, or 0 if none
+
+    };
+
+    //! Class representing attribute node of XML document. 
+    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. 
+    //! Thus, this text must persist in memory for the lifetime of attribute.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_attribute: public xml_base<Ch>
+    {
+
+        friend class xml_node<Ch>;
+    
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        //! Constructs an empty attribute with the specified type. 
+        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+        xml_attribute()
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets document of which attribute is a child.
+        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+        xml_document<Ch> *document() const
+        {
+            if (xml_node<Ch> *node = this->parent())
+            {
+                while (node->parent())
+                    node = node->parent();
+                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+            }
+            else
+                return 0;
+        }
+
+        //! Gets previous attribute, optionally matching attribute name. 
+        //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return this->m_parent ? m_prev_attribute : 0;
+        }
+
+        //! Gets next attribute, optionally matching attribute name. 
+        //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return this->m_parent ? m_next_attribute : 0;
+        }
+
+    private:
+
+        xml_attribute<Ch> *m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+        xml_attribute<Ch> *m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+    
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML node
+
+    //! Class representing a node of XML document. 
+    //! Each node may have associated name and value strings, which are available through name() and value() functions. 
+    //! Interpretation of name and value depends on type of the node.
+    //! Type of node can be determined by using type() function.
+    //! <br><br>
+    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. 
+    //! Thus, this text must persist in the memory for the lifetime of node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_node: public xml_base<Ch>
+    {
+
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        //! Constructs an empty node with the specified type. 
+        //! Consider using memory_pool of appropriate document to allocate nodes manually.
+        //! \param type Type of node to construct.
+        xml_node(node_type type)
+            : m_type(type)
+            , m_first_node(0)
+            , m_first_attribute(0)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+    
+        //! Gets type of node.
+        //! \return Type of node.
+        node_type type() const
+        {
+            return m_type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets document of which node is a child.
+        //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+        xml_document<Ch> *document() const
+        {
+            xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+            while (node->parent())
+                node = node->parent();
+            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+        }
+
+        //! Gets first child node, optionally matching node name.
+        //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                        return child;
+                return 0;
+            }
+            else
+                return m_first_node;
+        }
+
+        //! Gets last child node, optionally matching node name. 
+        //! Behaviour is undefined if node has no children.
+        //! Use first_node() to test if node has children.
+        //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(m_first_node);  // Cannot query for last child if node has no children
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                        return child;
+                return 0;
+            }
+            else
+                return m_last_node;
+        }
+
+        //! Gets previous sibling node, optionally matching node name. 
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                        return sibling;
+                return 0;
+            }
+            else
+                return m_prev_sibling;
+        }
+
+        //! Gets next sibling node, optionally matching node name. 
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                        return sibling;
+                return 0;
+            }
+            else
+                return m_next_sibling;
+        }
+
+        //! Gets first attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return m_first_attribute;
+        }
+
+        //! Gets last attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return m_first_attribute ? m_last_attribute : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+    
+        //! Sets type of node.
+        //! \param type Type of node to set.
+        void type(node_type type)
+        {
+            m_type = type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node manipulation
+
+        //! Prepends a new child node.
+        //! The prepended child becomes the first child, and all existing children are moved one position back.
+        //! \param child Node to prepend.
+        void prepend_node(xml_node<Ch> *child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+            if (first_node())
+            {
+                child->m_next_sibling = m_first_node;
+                m_first_node->m_prev_sibling = child;
+            }
+            else
+            {
+                child->m_next_sibling = 0;
+                m_last_node = child;
+            }
+            m_first_node = child;
+            child->m_parent = this;
+            child->m_prev_sibling = 0;
+        }
+
+        //! Appends a new child node. 
+        //! The appended child becomes the last child.
+        //! \param child Node to append.
+        void append_node(xml_node<Ch> *child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+            if (first_node())
+            {
+                child->m_prev_sibling = m_last_node;
+                m_last_node->m_next_sibling = child;
+            }
+            else
+            {
+                child->m_prev_sibling = 0;
+                m_first_node = child;
+            }
+            m_last_node = child;
+            child->m_parent = this;
+            child->m_next_sibling = 0;
+        }
+
+        //! Inserts a new child node at specified place inside the node. 
+        //! All children after and including the specified node are moved one position back.
+        //! \param where Place where to insert the child, or 0 to insert at the back.
+        //! \param child Node to insert.
+        void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+        {
+            assert(!where || where->parent() == this);
+            assert(child && !child->parent() && child->type() != node_document);
+            if (where == m_first_node)
+                prepend_node(child);
+            else if (where == 0)
+                append_node(child);
+            else
+            {
+                child->m_prev_sibling = where->m_prev_sibling;
+                child->m_next_sibling = where;
+                where->m_prev_sibling->m_next_sibling = child;
+                where->m_prev_sibling = child;
+                child->m_parent = this;
+            }
+        }
+
+        //! Removes first child node. 
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_first_node()
+        {
+            assert(first_node());
+            xml_node<Ch> *child = m_first_node;
+            m_first_node = child->m_next_sibling;
+            if (child->m_next_sibling)
+                child->m_next_sibling->m_prev_sibling = 0;
+            else
+                m_last_node = 0;
+            child->m_parent = 0;
+        }
+
+        //! Removes last child of the node. 
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_last_node()
+        {
+            assert(first_node());
+            xml_node<Ch> *child = m_last_node;
+            if (child->m_prev_sibling)
+            {
+                m_last_node = child->m_prev_sibling;
+                child->m_prev_sibling->m_next_sibling = 0;
+            }
+            else
+                m_first_node = 0;
+            child->m_parent = 0;
+        }
+
+        //! Removes specified child from the node
+        // \param where Pointer to child to be removed.
+        void remove_node(xml_node<Ch> *where)
+        {
+            assert(where && where->parent() == this);
+            assert(first_node());
+            if (where == m_first_node)
+                remove_first_node();
+            else if (where == m_last_node)
+                remove_last_node();
+            else
+            {
+                where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+                where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all child nodes (but not attributes).
+        void remove_all_nodes()
+        {
+            for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+                node->m_parent = 0;
+            m_first_node = 0;
+        }
+
+        //! Prepends a new attribute to the node.
+        //! \param attribute Attribute to prepend.
+        void prepend_attribute(xml_attribute<Ch> *attribute)
+        {
+            assert(attribute && !attribute->parent());
+            if (first_attribute())
+            {
+                attribute->m_next_attribute = m_first_attribute;
+                m_first_attribute->m_prev_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_next_attribute = 0;
+                m_last_attribute = attribute;
+            }
+            m_first_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_prev_attribute = 0;
+        }
+
+        //! Appends a new attribute to the node.
+        //! \param attribute Attribute to append.
+        void append_attribute(xml_attribute<Ch> *attribute)
+        {
+            assert(attribute && !attribute->parent());
+            if (first_attribute())
+            {
+                attribute->m_prev_attribute = m_last_attribute;
+                m_last_attribute->m_next_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_prev_attribute = 0;
+                m_first_attribute = attribute;
+            }
+            m_last_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_next_attribute = 0;
+        }
+
+        //! Inserts a new attribute at specified place inside the node. 
+        //! All attributes after and including the specified attribute are moved one position back.
+        //! \param where Place where to insert the attribute, or 0 to insert at the back.
+        //! \param attribute Attribute to insert.
+        void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+        {
+            assert(!where || where->parent() == this);
+            assert(attribute && !attribute->parent());
+            if (where == m_first_attribute)
+                prepend_attribute(attribute);
+            else if (where == 0)
+                append_attribute(attribute);
+            else
+            {
+                attribute->m_prev_attribute = where->m_prev_attribute;
+                attribute->m_next_attribute = where;
+                where->m_prev_attribute->m_next_attribute = attribute;
+                where->m_prev_attribute = attribute;
+                attribute->m_parent = this;
+            }
+        }
+
+        //! Removes first attribute of the node. 
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_first_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch> *attribute = m_first_attribute;
+            if (attribute->m_next_attribute)
+            {
+                attribute->m_next_attribute->m_prev_attribute = 0;
+            }
+            else
+                m_last_attribute = 0;
+            attribute->m_parent = 0;
+            m_first_attribute = attribute->m_next_attribute;
+        }
+
+        //! Removes last attribute of the node. 
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_last_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch> *attribute = m_last_attribute;
+            if (attribute->m_prev_attribute)
+            {
+                attribute->m_prev_attribute->m_next_attribute = 0;
+                m_last_attribute = attribute->m_prev_attribute;
+            }
+            else
+                m_first_attribute = 0;
+            attribute->m_parent = 0;
+        }
+
+        //! Removes specified attribute from node.
+        //! \param where Pointer to attribute to be removed.
+        void remove_attribute(xml_attribute<Ch> *where)
+        {
+            assert(first_attribute() && where->parent() == this);
+            if (where == m_first_attribute)
+                remove_first_attribute();
+            else if (where == m_last_attribute)
+                remove_last_attribute();
+            else
+            {
+                where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+                where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all attributes of node.
+        void remove_all_attributes()
+        {
+            for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+                attribute->m_parent = 0;
+            m_first_attribute = 0;
+        }
+        
+    private:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Restrictions
+
+        // No copying
+        xml_node(const xml_node &);
+        void operator =(const xml_node &);
+    
+        ///////////////////////////////////////////////////////////////////////////
+        // Data members
+    
+        // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+        // This is required for maximum performance, as it allows the parser to omit initialization of 
+        // unneded/redundant values.
+        //
+        // The rules are as follows:
+        // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+        // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+        // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+        node_type m_type;                       // Type of node; always valid
+        xml_node<Ch> *m_first_node;             // Pointer to first child node, or 0 if none; always valid
+        xml_node<Ch> *m_last_node;              // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+        xml_attribute<Ch> *m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid
+        xml_attribute<Ch> *m_last_attribute;    // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+        xml_node<Ch> *m_prev_sibling;           // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+        xml_node<Ch> *m_next_sibling;           // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML document
+    
+    //! This class represents root of the DOM hierarchy. 
+    //! It is also an xml_node and a memory_pool through public inheritance.
+    //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+    //! parse() function allocates memory for nodes and attributes by using functions of xml_document, 
+    //! which are inherited from memory_pool.
+    //! To access root node of the document, use the document itself, as if it was an xml_node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+    {
+    
+    public:
+
+        //! Constructs empty XML document
+        xml_document()
+            : xml_node<Ch>(node_document)
+        {
+        }
+
+        //! Parses zero-terminated XML string according to given flags.
+        //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+        //! The string must persist for the lifetime of the document.
+        //! In case of error, rapidxml::parse_error exception will be thrown.
+        //! <br><br>
+        //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+        //! Make sure that data is zero-terminated.
+        //! <br><br>
+        //! Document can be parsed into multiple times. 
+        //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+        //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+        template<int Flags>
+        void parse(Ch *text)
+        {
+            assert(text);
+            
+            // Remove current contents
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            
+            // Parse BOM, if any
+            parse_bom<Flags>(text);
+            
+            // Parse children
+            while (1)
+            {
+                // Skip whitespace before node
+                skip<whitespace_pred, Flags>(text);
+                if (*text == 0)
+                    break;
+
+                // Parse and append new child
+                if (*text == Ch('<'))
+                {
+                    ++text;     // Skip '<'
+                    if (xml_node<Ch> *node = parse_node<Flags>(text))
+                        this->append_node(node);
+                }
+                else
+                    RAPIDXML_PARSE_ERROR("expected <", text);
+            }
+
+        }
+
+        //! Clears the document by deleting all nodes and clearing the memory pool.
+        //! All nodes owned by document pool are destroyed.
+        void clear()
+        {
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            memory_pool<Ch>::clear();
+        }
+        
+    private:
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal character utility functions
+        
+        // Detect whitespace character
+        struct whitespace_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect node name character
+        struct node_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute name character
+        struct attribute_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA)
+        struct text_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_no_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_with_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                    return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+                if (Quote == Ch('\"'))
+                    return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pure_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                    return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+                if (Quote == Ch('\"'))
+                    return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Insert coded character, using UTF8 or 8-bit ASCII
+        template<int Flags>
+        static void insert_coded_character(Ch *&text, unsigned long code)
+        {
+            if (Flags & parse_no_utf8)
+            {
+                // Insert 8-bit ASCII character
+                // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+                text[0] = static_cast<unsigned char>(code);
+                text += 1;
+            }
+            else
+            {
+                // Insert UTF8 sequence
+                if (code < 0x80)    // 1 byte sequence
+                {
+                       text[0] = static_cast<unsigned char>(code);
+                    text += 1;
+                }
+                else if (code < 0x800)  // 2 byte sequence
+                {
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xC0);
+                    text += 2;
+                }
+                   else if (code < 0x10000)    // 3 byte sequence
+                {
+                       text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xE0);
+                    text += 3;
+                }
+                   else if (code < 0x110000)   // 4 byte sequence
+                {
+                       text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xF0);
+                    text += 4;
+                }
+                else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+                {
+                    RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+                }
+            }
+        }
+
+        // Skip characters until predicate evaluates to true
+        template<class StopPred, int Flags>
+        static void skip(Ch *&text)
+        {
+            Ch *tmp = text;
+            while (StopPred::test(*tmp))
+                ++tmp;
+            text = tmp;
+        }
+
+        // Skip characters until predicate evaluates to true while doing the following:
+        // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
+        // - condensing whitespace sequences to single space character
+        template<class StopPred, class StopPredPure, int Flags>
+        static Ch *skip_and_expand_character_refs(Ch *&text)
+        {
+            // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+            if (Flags & parse_no_entity_translation && 
+                !(Flags & parse_normalize_whitespace) &&
+                !(Flags & parse_trim_whitespace))
+            {
+                skip<StopPred, Flags>(text);
+                return text;
+            }
+            
+            // Use simple skip until first modification is detected
+            skip<StopPredPure, Flags>(text);
+
+            // Use translation skip
+            Ch *src = text;
+            Ch *dest = src;
+            while (StopPred::test(*src))
+            {
+                // If entity translation is enabled    
+                if (!(Flags & parse_no_entity_translation))
+                {
+                    // Test if replacement is needed
+                    if (src[0] == Ch('&'))
+                    {
+                        switch (src[1])
+                        {
+
+                        // &amp; &apos;
+                        case Ch('a'): 
+                            if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+                            {
+                                *dest = Ch('&');
+                                ++dest;
+                                src += 5;
+                                continue;
+                            }
+                            if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+                            {
+                                *dest = Ch('\'');
+                                ++dest;
+                                src += 6;
+                                continue;
+                            }
+                            break;
+
+                        // &quot;
+                        case Ch('q'): 
+                            if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+                            {
+                                *dest = Ch('"');
+                                ++dest;
+                                src += 6;
+                                continue;
+                            }
+                            break;
+
+                        // &gt;
+                        case Ch('g'): 
+                            if (src[2] == Ch('t') && src[3] == Ch(';'))
+                            {
+                                *dest = Ch('>');
+                                ++dest;
+                                src += 4;
+                                continue;
+                            }
+                            break;
+
+                        // &lt;
+                        case Ch('l'): 
+                            if (src[2] == Ch('t') && src[3] == Ch(';'))
+                            {
+                                *dest = Ch('<');
+                                ++dest;
+                                src += 4;
+                                continue;
+                            }
+                            break;
+
+                        // &#...; - assumes ASCII
+                        case Ch('#'): 
+                            if (src[2] == Ch('x'))
+                            {
+                                unsigned long code = 0;
+                                src += 3;   // Skip &#x
+                                while (1)
+                                {
+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+                                    if (digit == 0xFF)
+                                        break;
+                                    code = code * 16 + digit;
+                                    ++src;
+                                }
+                                insert_coded_character<Flags>(dest, code);    // Put character in output
+                            }
+                            else
+                            {
+                                unsigned long code = 0;
+                                src += 2;   // Skip &#
+                                while (1)
+                                {
+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+                                    if (digit == 0xFF)
+                                        break;
+                                    code = code * 10 + digit;
+                                    ++src;
+                                }
+                                insert_coded_character<Flags>(dest, code);    // Put character in output
+                            }
+                            if (*src == Ch(';'))
+                                ++src;
+                            else
+                                RAPIDXML_PARSE_ERROR("expected ;", src);
+                            continue;
+
+                        // Something else
+                        default:
+                            // Ignore, just copy '&' verbatim
+                            break;
+
+                        }
+                    }
+                }
+                
+                // If whitespace condensing is enabled
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Test if condensing is needed                 
+                    if (whitespace_pred::test(*src))
+                    {
+                        *dest = Ch(' '); ++dest;    // Put single space in dest
+                        ++src;                      // Skip first whitespace char
+                        // Skip remaining whitespace chars
+                        while (whitespace_pred::test(*src))
+                            ++src;
+                        continue;
+                    }
+                }
+
+                // No replacement, only copy character
+                *dest++ = *src++;
+
+            }
+
+            // Return new end
+            text = src;
+            return dest;
+
+        }
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal parsing functions
+        
+        // Parse BOM, if any
+        template<int Flags>
+        void parse_bom(Ch *&text)
+        {
+            // UTF-8?
+            if (static_cast<unsigned char>(text[0]) == 0xEF && 
+                static_cast<unsigned char>(text[1]) == 0xBB && 
+                static_cast<unsigned char>(text[2]) == 0xBF)
+            {
+                text += 3;      // Skup utf-8 bom
+            }
+        }
+
+        // Parse XML declaration (<?xml...)
+        template<int Flags>
+        xml_node<Ch> *parse_xml_declaration(Ch *&text)
+        {
+            // If parsing of declaration is disabled
+            if (!(Flags & parse_declaration_node))
+            {
+                // Skip until end of declaration
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 2;    // Skip '?>'
+                return 0;
+            }
+
+            // Create declaration
+            xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+            // Skip whitespace before attributes or ?>
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse declaration attributes
+            parse_node_attributes<Flags>(text, declaration);
+            
+            // Skip ?>
+            if (text[0] != Ch('?') || text[1] != Ch('>'))
+                RAPIDXML_PARSE_ERROR("expected ?>", text);
+            text += 2;
+            
+            return declaration;
+        }
+
+        // Parse XML comment (<!--...)
+        template<int Flags>
+        xml_node<Ch> *parse_comment(Ch *&text)
+        {
+            // If parsing of comments is disabled
+            if (!(Flags & parse_comment_nodes))
+            {
+                // Skip until end of comment
+                while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 3;     // Skip '-->'
+                return 0;      // Do not produce comment node
+            }
+
+            // Remember value start
+            Ch *value = text;
+
+            // Skip until end of comment
+            while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                ++text;
+            }
+
+            // Create comment node
+            xml_node<Ch> *comment = this->allocate_node(node_comment);
+            comment->value(value, text - value);
+            
+            // Place zero terminator after comment value
+            if (!(Flags & parse_no_string_terminators))
+                *text = Ch('\0');
+            
+            text += 3;     // Skip '-->'
+            return comment;
+        }
+
+        // Parse DOCTYPE
+        template<int Flags>
+        xml_node<Ch> *parse_doctype(Ch *&text)
+        {
+            // Remember value start
+            Ch *value = text;
+
+            // Skip to >
+            while (*text != Ch('>'))
+            {
+                // Determine character type
+                switch (*text)
+                {
+                
+                // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+                // This works for all W3C test files except for 2 most wicked
+                case Ch('['):
+                {
+                    ++text;     // Skip '['
+                    int depth = 1;
+                    while (depth > 0)
+                    {
+                        switch (*text)
+                        {
+                            case Ch('['): ++depth; break;
+                            case Ch(']'): --depth; break;
+                            case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                                                       default: break;
+                        }
+                        ++text;
+                    }
+                    break;
+                }
+                
+                // Error on end of text
+                case Ch('\0'):
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                
+                // Other character, skip it
+                default:
+                    ++text;
+
+                }
+            }
+            
+            // If DOCTYPE nodes enabled
+            if (Flags & parse_doctype_node)
+            {
+                // Create a new doctype node
+                xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+                doctype->value(value, text - value);
+                
+                // Place zero terminator after value
+                if (!(Flags & parse_no_string_terminators))
+                    *text = Ch('\0');
+
+                text += 1;      // skip '>'
+                return doctype;
+            }
+            else
+            {
+                text += 1;      // skip '>'
+                return 0;
+            }
+
+        }
+
+        // Parse PI
+        template<int Flags>
+        xml_node<Ch> *parse_pi(Ch *&text)
+        {
+            // If creation of PI nodes is enabled
+            if (Flags & parse_pi_nodes)
+            {
+                // Create pi node
+                xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+                // Extract PI target name
+                Ch *name = text;
+                skip<node_name_pred, Flags>(text);
+                if (text == name)
+                    RAPIDXML_PARSE_ERROR("expected PI target", text);
+                pi->name(name, text - name);
+                
+                // Skip whitespace between pi target and pi
+                skip<whitespace_pred, Flags>(text);
+
+                // Remember start of pi
+                Ch *value = text;
+                
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+
+                // Set pi value (verbatim, no entity expansion or whitespace normalization)
+                pi->value(value, text - value);     
+                
+                // Place zero terminator after name and value
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    pi->name()[pi->name_size()] = Ch('\0');
+                    pi->value()[pi->value_size()] = Ch('\0');
+                }
+                
+                text += 2;                          // Skip '?>'
+                return pi;
+            }
+            else
+            {
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 2;    // Skip '?>'
+                return 0;
+            }
+        }
+
+        // Parse and append data
+        // Return character that ends data.
+        // This is necessary because this character might have been overwritten by a terminating 0
+        template<int Flags>
+        Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+        {
+            // Backup to contents start if whitespace trimming is disabled
+            if (!(Flags & parse_trim_whitespace))
+                text = contents_start;     
+            
+            // Skip until end of data
+            Ch *value = text, *end;
+            if (Flags & parse_normalize_whitespace)
+                end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);   
+            else
+                end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+            // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+            if (Flags & parse_trim_whitespace)
+            {
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+                    if (*(end - 1) == Ch(' '))
+                        --end;
+                }
+                else
+                {
+                    // Backup until non-whitespace character is found
+                    while (whitespace_pred::test(*(end - 1)))
+                        --end;
+                }
+            }
+            
+            // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+            // Create new data node
+            if (!(Flags & parse_no_data_nodes))
+            {
+                xml_node<Ch> *data = this->allocate_node(node_data);
+                data->value(value, end - value);
+                node->append_node(data);
+            }
+
+            // Add data to parent node if no data exists yet
+            if (!(Flags & parse_no_element_values)) 
+                if (*node->value() == Ch('\0'))
+                    node->value(value, end - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+            {
+                Ch ch = *text;
+                *end = Ch('\0');
+                return ch;      // Return character that ends data; this is required because zero terminator overwritten it
+            }
+
+            // Return character that ends data
+            return *text;
+        }
+
+        // Parse CDATA
+        template<int Flags>
+        xml_node<Ch> *parse_cdata(Ch *&text)
+        {
+            // If CDATA is disabled
+            if (Flags & parse_no_data_nodes)
+            {
+                // Skip until end of cdata
+                while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 3;      // Skip ]]>
+                return 0;       // Do not produce CDATA node
+            }
+
+            // Skip until end of cdata
+            Ch *value = text;
+            while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                ++text;
+            }
+
+            // Create new cdata node
+            xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+            cdata->value(value, text - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+                *text = Ch('\0');
+
+            text += 3;      // Skip ]]>
+            return cdata;
+        }
+        
+        // Parse element node
+        template<int Flags>
+        xml_node<Ch> *parse_element(Ch *&text)
+        {
+            // Create element node
+            xml_node<Ch> *element = this->allocate_node(node_element);
+
+            // Extract element name
+            Ch *name = text;
+            skip<node_name_pred, Flags>(text);
+            if (text == name)
+                RAPIDXML_PARSE_ERROR("expected element name", text);
+            element->name(name, text - name);
+            
+            // Skip whitespace between element name and attributes or >
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse attributes, if any
+            parse_node_attributes<Flags>(text, element);
+
+            // Determine ending type
+            if (*text == Ch('>'))
+            {
+                ++text;
+                parse_node_contents<Flags>(text, element);
+            }
+            else if (*text == Ch('/'))
+            {
+                ++text;
+                if (*text != Ch('>'))
+                    RAPIDXML_PARSE_ERROR("expected >", text);
+                ++text;
+            }
+            else
+                RAPIDXML_PARSE_ERROR("expected >", text);
+
+            // Place zero terminator after name
+            if (!(Flags & parse_no_string_terminators))
+                element->name()[element->name_size()] = Ch('\0');
+
+            // Return parsed element
+            return element;
+        }
+
+        // Determine node type, and parse it
+        template<int Flags>
+        xml_node<Ch> *parse_node(Ch *&text)
+        {
+            // Parse proper node type
+            switch (text[0])
+            {
+
+            // <...
+            default: 
+                // Parse and append element node
+                return parse_element<Flags>(text);
+
+            // <?...
+            case Ch('?'): 
+                ++text;     // Skip ?
+                if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+                    (text[1] == Ch('m') || text[1] == Ch('M')) && 
+                    (text[2] == Ch('l') || text[2] == Ch('L')) &&
+                    whitespace_pred::test(text[3]))
+                {
+                    // '<?xml ' - xml declaration
+                    text += 4;      // Skip 'xml '
+                    return parse_xml_declaration<Flags>(text);
+                }
+                else
+                {
+                    // Parse PI
+                    return parse_pi<Flags>(text);
+                }
+            
+            // <!...
+            case Ch('!'): 
+
+                // Parse proper subset of <! node
+                switch (text[1])    
+                {
+                
+                // <!-
+                case Ch('-'):
+                    if (text[2] == Ch('-'))
+                    {
+                        // '<!--' - xml comment
+                        text += 3;     // Skip '!--'
+                        return parse_comment<Flags>(text);
+                    }
+                    break;
+
+                // <![
+                case Ch('['):
+                    if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') && 
+                        text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+                    {
+                        // '<![CDATA[' - cdata
+                        text += 8;     // Skip '![CDATA['
+                        return parse_cdata<Flags>(text);
+                    }
+                    break;
+
+                // <!D
+                case Ch('D'):
+                    if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') && 
+                        text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') && 
+                        whitespace_pred::test(text[8]))
+                    {
+                        // '<!DOCTYPE ' - doctype
+                        text += 9;      // skip '!DOCTYPE '
+                        return parse_doctype<Flags>(text);
+                    }
+                                       break;
+                               
+                               default:
+                                       break;
+
+                }   // switch
+
+                // Attempt to skip other, unrecognized node types starting with <!
+                ++text;     // Skip !
+                while (*text != Ch('>'))
+                {
+                    if (*text == 0)
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                ++text;     // Skip '>'
+                return 0;   // No node recognized
+
+            }
+        }
+
+        // Parse contents of the node - children, data etc.
+        template<int Flags>
+        void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+        {
+            // For all children and text
+            while (1)
+            {
+                // Skip whitespace between > and node contents
+                Ch *contents_start = text;      // Store start of node contents before whitespace is skipped
+                skip<whitespace_pred, Flags>(text);
+                Ch next_char = *text;
+
+            // After data nodes, instead of continuing the loop, control jumps here.
+            // This is because zero termination inside parse_and_append_data() function
+            // would wreak havoc with the above code.
+            // Also, skipping whitespace after data nodes is unnecessary.
+            after_data_node:    
+                
+                // Determine what comes next: node closing, child node, data node, or 0?
+                switch (next_char)
+                {
+                
+                // Node closing or child node
+                case Ch('<'):
+                    if (text[1] == Ch('/'))
+                    {
+                        // Node closing
+                        text += 2;      // Skip '</'
+                        if (Flags & parse_validate_closing_tags)
+                        {
+                            // Skip and validate closing tag name
+                            Ch *closing_name = text;
+                            skip<node_name_pred, Flags>(text);
+                            if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+                                RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+                        }
+                        else
+                        {
+                            // No validation, just skip name
+                            skip<node_name_pred, Flags>(text);
+                        }
+                        // Skip remaining whitespace after node name
+                        skip<whitespace_pred, Flags>(text);
+                        if (*text != Ch('>'))
+                            RAPIDXML_PARSE_ERROR("expected >", text);
+                        ++text;     // Skip '>'
+                        return;     // Node closed, finished parsing contents
+                    }
+                    else
+                    {
+                        // Child node
+                        ++text;     // Skip '<'
+                        if (xml_node<Ch> *child = parse_node<Flags>(text))
+                            node->append_node(child);
+                    }
+                    break;
+
+                // End of data - error
+                case Ch('\0'):
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+                // Data node
+                default:
+                    next_char = parse_and_append_data<Flags>(node, text, contents_start);
+                    goto after_data_node;   // Bypass regular processing after data nodes
+
+                }
+            }
+        }
+        
+        // Parse XML attributes of the node
+        template<int Flags>
+        void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+        {
+            // For all attributes 
+            while (attribute_name_pred::test(*text))
+            {
+                // Extract attribute name
+                Ch *name = text;
+                ++text;     // Skip first character of attribute name
+                skip<attribute_name_pred, Flags>(text);
+                if (text == name)
+                    RAPIDXML_PARSE_ERROR("expected attribute name", name);
+
+                // Create new attribute
+                xml_attribute<Ch> *attribute = this->allocate_attribute();
+                attribute->name(name, text - name);
+                node->append_attribute(attribute);
+
+                // Skip whitespace after attribute name
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip =
+                if (*text != Ch('='))
+                    RAPIDXML_PARSE_ERROR("expected =", text);
+                ++text;
+
+                // Add terminating zero after name
+                if (!(Flags & parse_no_string_terminators))
+                    attribute->name()[attribute->name_size()] = 0;
+
+                // Skip whitespace after =
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip quote and remember if it was ' or "
+                Ch quote = *text;
+                if (quote != Ch('\'') && quote != Ch('"'))
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                ++text;
+
+                // Extract attribute value and expand char refs in it
+                Ch *value = text, *end;
+                const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
+                if (quote == Ch('\''))
+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+                else
+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+                
+                // Set attribute value
+                attribute->value(value, end - value);
+                
+                // Make sure that end quote is present
+                if (*text != quote)
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                ++text;     // Skip quote
+
+                // Add terminating zero after value
+                if (!(Flags & parse_no_string_terminators))
+                    attribute->value()[attribute->value_size()] = 0;
+
+                // Skip whitespace after attribute value
+                skip<whitespace_pred, Flags>(text);
+            }
+        }
+
+    };
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Whitespace (space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
+             1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
+        };
+
+        // Node name (anything but space \n \r \t / > ? \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_node_name[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) (anything but < \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled 
+        // (anything but < \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+        // (anything but < \0 & space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote (anything but ' \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote that does not require processing (anything but ' \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote (anything but " \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote that does not require processing (anything but " \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Digits (dec and hex, 255 denotes end of numeric character reference)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_digits[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
+             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3
+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
+        };
+    
+        // Upper case conversion
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_upcase[256] = 
+        {
+          // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
+           0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
+           16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
+           32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
+           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
+           64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
+           96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127,  // 7
+           128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,  // 8
+           144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,  // 9
+           160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,  // A
+           176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,  // B
+           192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,  // C
+           208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,  // D
+           224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,  // E
+           240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255   // F
+        };
+    }
+    //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+    #pragma warning(pop)
+#endif
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp
new file mode 100644 (file)
index 0000000..52ebc29
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
+#define RAPIDXML_ITERATORS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
+
+#include "rapidxml.hpp"
+
+namespace rapidxml
+{
+
+    //! Iterator of child nodes of xml_node
+    template<class Ch>
+    class node_iterator
+    {
+    
+    public:
+
+        typedef typename xml_node<Ch> value_type;
+        typedef typename xml_node<Ch> &reference;
+        typedef typename xml_node<Ch> *pointer;
+        typedef std::ptrdiff_t difference_type;
+        typedef std::bidirectional_iterator_tag iterator_category;
+        
+        node_iterator()
+            : m_node(0)
+        {
+        }
+
+        node_iterator(xml_node<Ch> *node)
+            : m_node(node->first_node())
+        {
+        }
+        
+        reference operator *() const
+        {
+            assert(m_node);
+            return *m_node;
+        }
+
+        pointer operator->() const
+        {
+            assert(m_node);
+            return m_node;
+        }
+
+        node_iterator& operator++()
+        {
+            assert(m_node);
+            m_node = m_node->next_sibling();
+            return *this;
+        }
+
+        node_iterator operator++(int)
+        {
+            node_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        node_iterator& operator--()
+        {
+            assert(m_node && m_node->previous_sibling());
+            m_node = m_node->previous_sibling();
+            return *this;
+        }
+
+        node_iterator operator--(int)
+        {
+            node_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        bool operator ==(const node_iterator<Ch> &rhs)
+        {
+            return m_node == rhs.m_node;
+        }
+
+        bool operator !=(const node_iterator<Ch> &rhs)
+        {
+            return m_node != rhs.m_node;
+        }
+
+    private:
+
+        xml_node<Ch> *m_node;
+
+    };
+
+    //! Iterator of child attributes of xml_node
+    template<class Ch>
+    class attribute_iterator
+    {
+    
+    public:
+
+        typedef typename xml_attribute<Ch> value_type;
+        typedef typename xml_attribute<Ch> &reference;
+        typedef typename xml_attribute<Ch> *pointer;
+        typedef std::ptrdiff_t difference_type;
+        typedef std::bidirectional_iterator_tag iterator_category;
+        
+        attribute_iterator()
+            : m_attribute(0)
+        {
+        }
+
+        attribute_iterator(xml_node<Ch> *node)
+            : m_attribute(node->first_attribute())
+        {
+        }
+        
+        reference operator *() const
+        {
+            assert(m_attribute);
+            return *m_attribute;
+        }
+
+        pointer operator->() const
+        {
+            assert(m_attribute);
+            return m_attribute;
+        }
+
+        attribute_iterator& operator++()
+        {
+            assert(m_attribute);
+            m_attribute = m_attribute->next_attribute();
+            return *this;
+        }
+
+        attribute_iterator operator++(int)
+        {
+            attribute_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        attribute_iterator& operator--()
+        {
+            assert(m_attribute && m_attribute->previous_attribute());
+            m_attribute = m_attribute->previous_attribute();
+            return *this;
+        }
+
+        attribute_iterator operator--(int)
+        {
+            attribute_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        bool operator ==(const attribute_iterator<Ch> &rhs)
+        {
+            return m_attribute == rhs.m_attribute;
+        }
+
+        bool operator !=(const attribute_iterator<Ch> &rhs)
+        {
+            return m_attribute != rhs.m_attribute;
+        }
+
+    private:
+
+        xml_attribute<Ch> *m_attribute;
+
+    };
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp
new file mode 100644 (file)
index 0000000..f929b3c
--- /dev/null
@@ -0,0 +1,422 @@
+#ifndef RAPIDXML_PRINT_HPP_INCLUDED
+#define RAPIDXML_PRINT_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
+
+#include "rapidxml.hpp"
+
+// Only include streams if not disabled
+#ifndef RAPIDXML_NO_STREAMS
+    #include <ostream>
+    #include <iterator>
+#endif
+
+namespace rapidxml
+{
+
+    ///////////////////////////////////////////////////////////////////////
+    // Printing flags
+
+    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internal
+
+    //! \cond internal
+    namespace internal
+    {
+        
+        ///////////////////////////////////////////////////////////////////////////
+        // Internal character operations
+    
+        // Copy characters from given range to given output iterator
+        template<class OutIt, class Ch>
+        inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
+        {
+            while (begin != end)
+                *out++ = *begin++;
+            return out;
+        }
+        
+        // Copy characters from given range to given output iterator and expand
+        // characters into references (&lt; &gt; &apos; &quot; &amp;)
+        template<class OutIt, class Ch>
+        inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
+        {
+            while (begin != end)
+            {
+                if (*begin == noexpand)
+                {
+                    *out++ = *begin;    // No expansion, copy character
+                }
+                else
+                {
+                    switch (*begin)
+                    {
+                    case Ch('<'):
+                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('>'): 
+                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('\''): 
+                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
+                        break;
+                    case Ch('"'): 
+                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('&'): 
+                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
+                        break;
+                    default:
+                        *out++ = *begin;    // No expansion, copy character
+                    }
+                }
+                ++begin;    // Step to next character
+            }
+            return out;
+        }
+
+        // Fill given output iterator with repetitions of the same character
+        template<class OutIt, class Ch>
+        inline OutIt fill_chars(OutIt out, int n, Ch ch)
+        {
+            for (int i = 0; i < n; ++i)
+                *out++ = ch;
+            return out;
+        }
+
+        // Find character
+        template<class Ch, Ch ch>
+        inline bool find_char(const Ch *begin, const Ch *end)
+        {
+            while (begin != end)
+                if (*begin++ == ch)
+                    return true;
+            return false;
+        }
+
+        template<class OutIt, class Ch>
+        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
+
+        // Print children of the node                               
+        template<class OutIt, class Ch>
+        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
+                out = print_node(out, child, flags, indent);
+            return out;
+        }
+
+        // Print attributes of the node
+        template<class OutIt, class Ch>
+        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
+        {
+            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+            {
+                if (attribute->name() && attribute->value())
+                {
+                    // Print attribute name
+                    *out = Ch(' '), ++out;
+                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
+                    *out = Ch('='), ++out;
+                    // Print attribute value using appropriate quote type
+                    if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
+                    {
+                        *out = Ch('\''), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+                        *out = Ch('\''), ++out;
+                    }
+                    else
+                    {
+                        *out = Ch('"'), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+                        *out = Ch('"'), ++out;
+                    }
+                }
+            }
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_data);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_cdata);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'); ++out;
+            *out = Ch('!'); ++out;
+            *out = Ch('['); ++out;
+            *out = Ch('C'); ++out;
+            *out = Ch('D'); ++out;
+            *out = Ch('A'); ++out;
+            *out = Ch('T'); ++out;
+            *out = Ch('A'); ++out;
+            *out = Ch('['); ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch(']'); ++out;
+            *out = Ch(']'); ++out;
+            *out = Ch('>'); ++out;
+            return out;
+        }
+
+        // Print element node
+        template<class OutIt, class Ch>
+        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_element);
+
+            // Print element name and attributes, if any
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            out = print_attributes(out, node, flags);
+            
+            // If node is childless
+            if (node->value_size() == 0 && !node->first_node())
+            {
+                // Print childless node tag ending
+                *out = Ch('/'), ++out;
+                *out = Ch('>'), ++out;
+            }
+            else
+            {
+                // Print normal node tag ending
+                *out = Ch('>'), ++out;
+
+                // Test if node contains a single data node only (and no other nodes)
+                xml_node<Ch> *child = node->first_node();
+                if (!child)
+                {
+                    // If node has no children, only print its value without indenting
+                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+                }
+                else if (child->next_sibling() == 0 && child->type() == node_data)
+                {
+                    // If node has a sole data child, only print its value without indenting
+                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
+                }
+                else
+                {
+                    // Print all children with full indenting
+                    if (!(flags & print_no_indenting))
+                        *out = Ch('\n'), ++out;
+                    out = print_children(out, node, flags, indent + 1);
+                    if (!(flags & print_no_indenting))
+                        out = fill_chars(out, indent, Ch('\t'));
+                }
+
+                // Print node end
+                *out = Ch('<'), ++out;
+                *out = Ch('/'), ++out;
+                out = copy_chars(node->name(), node->name() + node->name_size(), out);
+                *out = Ch('>'), ++out;
+            }
+            return out;
+        }
+
+        // Print declaration node
+        template<class OutIt, class Ch>
+        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            // Print declaration start
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            *out = Ch('x'), ++out;
+            *out = Ch('m'), ++out;
+            *out = Ch('l'), ++out;
+
+            // Print attributes
+            out = print_attributes(out, node, flags);
+            
+            // Print declaration end
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            
+            return out;
+        }
+
+        // Print comment node
+        template<class OutIt, class Ch>
+        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_comment);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print doctype node
+        template<class OutIt, class Ch>
+        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_doctype);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('D'), ++out;
+            *out = Ch('O'), ++out;
+            *out = Ch('C'), ++out;
+            *out = Ch('T'), ++out;
+            *out = Ch('Y'), ++out;
+            *out = Ch('P'), ++out;
+            *out = Ch('E'), ++out;
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print pi node
+        template<class OutIt, class Ch>
+        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_pi);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+        ///////////////////////////////////////////////////////////////////////////
+                // Internal printing operations
+
+                // Print node
+                template<class OutIt, class Ch>
+                inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+                {
+                    // Print proper node type
+                    switch (node->type())
+                    {
+
+                    // Document
+                    case node_document:
+                        out = print_children(out, node, flags, indent);
+                        break;
+
+                    // Element
+                    case node_element:
+                        out = print_element_node(out, node, flags, indent);
+                        break;
+
+                    // Data
+                    case node_data:
+                        out = print_data_node(out, node, flags, indent);
+                        break;
+
+                    // CDATA
+                    case node_cdata:
+                        out = print_cdata_node(out, node, flags, indent);
+                        break;
+
+                    // Declaration
+                    case node_declaration:
+                        out = print_declaration_node(out, node, flags, indent);
+                        break;
+
+                    // Comment
+                    case node_comment:
+                        out = print_comment_node(out, node, flags, indent);
+                        break;
+
+                    // Doctype
+                    case node_doctype:
+                        out = print_doctype_node(out, node, flags, indent);
+                        break;
+
+                    // Pi
+                    case node_pi:
+                        out = print_pi_node(out, node, flags, indent);
+                        break;
+
+                        // Unknown
+                    default:
+                        assert(0);
+                        break;
+                    }
+
+                    // If indenting not disabled, add line break after node
+                    if (!(flags & print_no_indenting))
+                        *out = Ch('\n'), ++out;
+
+                    // Return modified iterator
+                    return out;
+                }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Printing
+
+    //! Prints XML to given output iterator.
+    //! \param out Output iterator to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output iterator pointing to position immediately after last character of printed text.
+    template<class OutIt, class Ch> 
+    inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
+    {
+        return internal::print_node(out, &node, flags, 0);
+    }
+
+#ifndef RAPIDXML_NO_STREAMS
+
+    //! Prints XML to given output stream.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output stream.
+    template<class Ch> 
+    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
+    {
+        print(std::ostream_iterator<Ch>(out), node, flags);
+        return out;
+    }
+
+    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed.
+    //! \return Output stream.
+    template<class Ch> 
+    inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
+    {
+        return print(out, node);
+    }
+
+#endif
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp
new file mode 100644 (file)
index 0000000..37c2953
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef RAPIDXML_UTILS_HPP_INCLUDED
+#define RAPIDXML_UTILS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
+//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <fstream>
+#include <stdexcept>
+
+namespace rapidxml
+{
+
+    //! Represents data loaded from a file
+    template<class Ch = char>
+    class file
+    {
+        
+    public:
+        
+        //! Loads file into the memory. Data will be automatically destroyed by the destructor.
+        //! \param filename Filename to load.
+        file(const char *filename)
+        {
+            using namespace std;
+
+            // Open stream
+            basic_ifstream<Ch> stream(filename, ios::binary);
+            if (!stream)
+                throw runtime_error(string("cannot open file ") + filename);
+            stream.unsetf(ios::skipws);
+            
+            // Determine stream size
+            stream.seekg(0, ios::end);
+            size_t size = stream.tellg();
+            stream.seekg(0);   
+            
+            // Load data and add terminating 0
+            m_data.resize(size + 1);
+            stream.read(&m_data.front(), static_cast<streamsize>(size));
+            m_data[size] = 0;
+        }
+
+        //! Loads file into the memory. Data will be automatically destroyed by the destructor
+        //! \param stream Stream to load from
+        file(std::basic_istream<Ch> &stream)
+        {
+            using namespace std;
+
+            // Load data and add terminating 0
+            stream.unsetf(ios::skipws);
+            m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
+            if (stream.fail() || stream.bad())
+                throw runtime_error("error reading stream");
+            m_data.push_back(0);
+        }
+        
+        //! Gets file data.
+        //! \return Pointer to data of file.
+        Ch *data()
+        {
+            return &m_data.front();
+        }
+
+        //! Gets file data.
+        //! \return Pointer to data of file.
+        const Ch *data() const
+        {
+            return &m_data.front();
+        }
+
+        //! Gets file data size.
+        //! \return Size of file data, in characters.
+        std::size_t size() const
+        {
+            return m_data.size();
+        }
+
+    private:
+
+        std::vector<Ch> m_data;   // File data
+
+    };
+
+    //! Counts children of node. Time complexity is O(n).
+    //! \return Number of children of node
+    template<class Ch>
+    inline std::size_t count_children(xml_node<Ch> *node)
+    {
+        xml_node<Ch> *child = node->first_node();
+        std::size_t count = 0;
+        while (child)
+        {
+            ++count;
+            child = child->next_sibling();
+        }
+        return count;
+    }
+
+    //! Counts attributes of node. Time complexity is O(n).
+    //! \return Number of attributes of node
+    template<class Ch>
+    inline std::size_t count_attributes(xml_node<Ch> *node)
+    {
+        xml_attribute<Ch> *attr = node->first_attribute();
+        std::size_t count = 0;
+        while (attr)
+        {
+            ++count;
+            attr = attr->next_attribute();
+        }
+        return count;
+    }
+
+}
+
+#endif
diff --git a/service/protocol-plugin/plugin-manager/SConscript b/service/protocol-plugin/plugin-manager/SConscript
new file mode 100644 (file)
index 0000000..1e7d42b
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# plugin-manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+plugin_manager_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+plugin_manager_env.AppendUnique(CPPPATH = [
+               '../lib/cpluff/libcpluff',
+               'src'
+               ])
+
+if target_os not in ['windows', 'winrt']:
+       plugin_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall',
+               '-fpermissive', '-Wsign-compare'])
+
+if target_os == 'android':
+       plugin_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       plugin_manager_env.AppendUnique(LIBS = ['boost_thread-gcc-mt-1_49', 'gnustl_static'])
+
+plugin_manager_env.AppendUnique(LIBS = ['oc', 'octbstack', 'expat', 'dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+ppm_src = ['src/Plugin.cpp', 'src/PluginManager.cpp']
+ppm = plugin_manager_env.StaticLibrary('ppm', ppm_src)
+
+pmimpl_src = [
+               'src/CpluffAdapter.cpp',
+               'src/FelixAdapter.cpp',
+               'src/Plugin.cpp',
+               'src/PluginManagerImpl.cpp']
+
+pmimpl_env = plugin_manager_env.Clone()
+pmimpl_env.PrependUnique(CCFLAGS = ['-fPIC'])
+pmimpl_env.PrependUnique(LIBS = File(env.get('BUILD_DIR') + '/libcpluff.a'))
+pmimpl = pmimpl_env.SharedLibrary('pmimpl', pmimpl_src)
+
+plugin_manager_env.InstallTarget([ppm, pmimpl], 'libppm')
index f6187f4..453451f 100644 (file)
@@ -1,12 +1,13 @@
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall
-
-CPLUFF_DIR = ../../../lib/cpluff/libcpluff
+LIB = ../../../lib
+CPLUFF_DIR = $(LIB)/cpluff/libcpluff
 
 SRC = ../../src/
 
 CXX_INC    = -I. -I$(CPLUFF_DIR)
+CXX_INC += -I$(LIB)/rapidxml 
 
 LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
 CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a 
@@ -22,8 +23,8 @@ PluginManager.o : $(SRC)PluginManager.cpp
        $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp 
 
 
-libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CPLUFF_DIR)/.libs/libcpluff.a 
-       $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CXX_LIBS) $(LINK_LIB)  
+libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CPLUFF_DIR)/.libs/libcpluff.a 
+       $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CXX_LIBS) $(LINK_LIB)  
 
 PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
        $(CXX) $(CXX_INC)  -fPIC  -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManagerImpl.cpp
@@ -31,6 +32,9 @@ PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
 Plugin.o : $(SRC)Plugin.cpp
        $(CXX) $(CXX_INC)  -fPIC  -c $(SRC)Plugin.cpp
 
+Config.o : $(SRC)Config.cpp
+       $(CXX) $(CXX_INC)  -fPIC  -c $(SRC)Config.cpp
+
 CpluffAdapter.o  : $(SRC)CpluffAdapter.cpp
        $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)CpluffAdapter.cpp
 
diff --git a/service/protocol-plugin/plugin-manager/src/Config.cpp b/service/protocol-plugin/plugin-manager/src/Config.cpp
new file mode 100644 (file)
index 0000000..528c7dd
--- /dev/null
@@ -0,0 +1,157 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.cpp
+
+/// @brief
+
+
+#include "Config.h"
+
+
+using namespace OIC;
+using namespace rapidxml;
+using namespace std;
+
+Config *Config::s_configinstance = NULL;
+
+Config::Config()
+{
+    if (loadConfigFile("./pluginmanager.xml") != PM_S_OK)
+    {
+        fprintf(stderr, "PM Configuration file is not exist current Folder.\n" );
+        exit(EXIT_FAILURE);
+    }
+}
+
+Config::~Config(void)
+{
+    s_configinstance->deleteinstance();
+    s_configinstance = NULL;
+}
+
+PMRESULT Config::loadConfigFile(const std::string configfilepath)
+{
+    // Read the xml file
+    std::ifstream xmlFile(configfilepath.c_str());
+    xml_document<> doc;
+    //into a vector
+    std::vector<char> buffer((istreambuf_iterator<char>(xmlFile)), istreambuf_iterator<char>());
+    buffer.push_back('\0');
+
+    // Parse the buffer using the xml file parsing library into doc
+    parsing(buffer, &doc);
+
+    // Find our root node
+    xml_node<> *root_node = doc.first_node("pluginManager");
+    xml_node<> *pluginInfo = root_node->first_node("pluginInfo");
+
+    getXmlData(pluginInfo, "pluginPath");
+    getXmlData(pluginInfo, "maxMEM");
+    getXmlData(pluginInfo, "version");
+    getXmlData(pluginInfo, "name");
+
+    return PM_S_OK;
+}
+
+PMRESULT Config::parsing(std::vector<char> buffer, xml_document<> *doc)
+{
+    // Parse the buffer using the xml file parsing library into doc
+    try
+    {
+        doc->parse<0>(&buffer[0]);
+    }
+    catch (rapidxml::parse_error err)
+    {
+        //print errors to screen
+        fprintf(stderr, "PM Configuration file parsing error \n");
+        exit(EXIT_FAILURE); //then exit
+    }
+    return PM_S_OK;
+}
+
+PMRESULT Config::getXmlData(xml_node<> *pluginInfo, std::string key)
+{
+    xml_attribute<> *iAttr = NULL;
+    std::string value  = "";
+    if (iAttr = pluginInfo->first_attribute(key.c_str()))
+    {
+        value = iAttr->value();
+        setValue(key, value);
+        return PM_S_OK;
+    }
+    else
+    {
+        return PM_S_FALSE;
+    }
+}
+
+void Config::setValue(const std::string key, const std::string value)
+{
+    m_configurationMap.insert( std::pair<std::string, std::string>(key, value));
+}
+
+std::string  Config::getValue(const std::string key)
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find(key.c_str());
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
+
+std::string  Config::getVersion()
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find("version");
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
+
+std::string  Config::getPluginPath()
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find("pluginPath");
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
\ No newline at end of file
diff --git a/service/protocol-plugin/plugin-manager/src/Config.h b/service/protocol-plugin/plugin-manager/src/Config.h
new file mode 100644 (file)
index 0000000..33f7f39
--- /dev/null
@@ -0,0 +1,122 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.h
+
+/// @brief
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include <map>
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rapidxml.hpp"
+#include <fstream>
+#include <vector>
+
+using namespace rapidxml;
+
+namespace OIC
+{
+
+    enum PMRESULT
+    {
+        PM_S_OK
+        , PM_S_FALSE
+        , PM_E_POINTER
+        , PM_E_OUTOFMEMORY
+        , PM_E_FAIL
+        , PM_E_NOINTERFACE
+        , PM_E_NOTIMPL
+    };
+    /**
+    * @brief    Configuration class
+    *
+    *
+    */
+    class Config
+    {
+        public:
+            /**
+            * A function to register pluins in the path.
+            * This function will load plugins in plugin manager table.
+            *
+            * @param path plugin file path to be registered.
+            * @return int, 1 is success, 0 is fail.
+            *
+            * NOTE:
+            *
+            */
+            /**
+            *
+            * new Singleton pattern instance.
+            *
+            * @return config pointer Address.
+            */
+            static Config *Getinstance()
+            {
+                if (NULL == s_configinstance)
+                {
+                    s_configinstance = new Config();
+                }
+
+                return s_configinstance;
+            }
+            std::string  getPluginPath();
+            std::string  getVersion();
+            std::string  getValue(const std::string key);
+
+        private:
+            static Config *s_configinstance;
+            typedef std::map<std::string, std::string> configmap;
+            configmap m_configurationMap;
+            /**
+            * Constructor for Config.
+            * During construction time, configuration file  will be loaded.
+            *
+            */
+            Config();
+
+            /**
+            * Virtual destructor
+            */
+            virtual ~Config(void);
+
+            /**
+            * delete Singleton pattern instance.
+            */
+            static void deleteinstance()
+            {
+                if (NULL != s_configinstance)
+                {
+                    delete s_configinstance;
+                    s_configinstance = NULL;
+                }
+            }
+            void setValue(const std::string key, const std::string value);
+            PMRESULT loadConfigFile(const std::string configfilepath);
+            PMRESULT parsing(std::vector<char> buffer, xml_document<> *doc);
+            PMRESULT getXmlData(  xml_node<> *pluginInfo, std::string key);
+    };
+}
+
+#endif
\ No newline at end of file
index b3d60e4..addc2a7 100644 (file)
@@ -34,14 +34,27 @@ CpluffAdapter::CpluffAdapter()
     m_context = cp_create_context(&m_status);
     m_cp_plugins = nullptr;
     m_plugin = nullptr;
-    registerAllPlugin("../../../plugins");
+
+    config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path does not exist\n");
+        pluginpath = "";
+    }
+    registerAllPlugin(pluginpath);
 }
 
 CpluffAdapter::~CpluffAdapter(void)
 {
     cp_release_info(m_context, m_cp_plugins);
-    m_thread_g.interrupt_all();
-    m_thread_g.join_all();
+    //Auto plugin detection is disabled
+    //m_thread_g.interrupt_all();
+    //m_thread_g.join_all();
     s_pinstance->deleteinstance();
     s_pinstance = nullptr;
 }
@@ -57,7 +70,12 @@ int CpluffAdapter::installPlugin(const std::string path)
     }
     else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
     {
-        printf("cp_install_plugin failed\n");
+        if (m_status == CP_ERR_CONFLICT)
+        {
+            printf("Plugin is already installed or conflicts symbol.\n");
+        }
+        printf("cp_install_plugin failed : %d \n" , m_status);
+
         return false;
     }
 
@@ -70,8 +88,7 @@ int CpluffAdapter::findPluginRecursive(const std::string path)
     File_list file_list;
     getFileList(file_list, path);
     File_list::iterator itr;
-    int flag = FALSE;
-
+    int flag = TRUE;
     for (itr = file_list.begin(); itr != file_list.end(); itr++)
     {
         if (itr->second == true)
@@ -91,9 +108,10 @@ int CpluffAdapter::findPluginRecursive(const std::string path)
                 }
             }
             std::string filename = filepath.substr(0, count );
-            //char *temp_char = const_cast<char *>(filename.c_str());
-            flag = installPlugin(filename);
-            //printf("plugin file path %s \n", plugin->plugin_path);
+            if (!installPlugin(filename))
+            {
+                printf("installPlugin failed path : %s \n", filename.c_str());
+            }
         }
     }
 
@@ -110,7 +128,7 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
     }
     else
     {
-        printPluginList(m_cp_plugins);
+        printPluginList();
     }
 
     for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
@@ -176,7 +194,8 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
         }
         if (plugin_compare_flag)
         {
-            m_plugins.push_back(*plugin);
+            //Auto plugin detection is disabled
+            /*
             try
             {
                 boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
@@ -188,6 +207,8 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
             {
                 printf("thread throw exception\n");
             }
+            */
+            m_plugins.push_back(*plugin);
             delete(plugin);
         }
         //printf("plugin size = %d\n",m_plugins.size());
@@ -208,11 +229,10 @@ int CpluffAdapter::registerPlugin(const std::string path)
     }
 
     //non recursive
-
-    flag = installPlugin(path);
-
-    flag = loadPluginInfoToManager(path);
-
+    if (installPlugin(path))
+    {
+        flag = loadPluginInfoToManager(path);
+    }
     return flag;
 }
 
@@ -227,11 +247,10 @@ int CpluffAdapter::registerAllPlugin(const std::string path)
     }
 
     //recursive
-
-    flag = findPluginRecursive(path);
-
-    flag = loadPluginInfoToManager(path);
-
+    if (findPluginRecursive(path))
+    {
+        flag = loadPluginInfoToManager(path);
+    }
     return flag;
 }
 
@@ -403,7 +422,7 @@ const char *CpluffAdapter::state_to_string(int state)
     }
 }
 
-void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+void CpluffAdapter::printPluginList()
 {
     const char format[] = "  %-30s %-15s %-15s %-20s\n";
     printf("\n====== Plugins List ======\n");
@@ -491,7 +510,8 @@ bool CpluffAdapter::isStarted(Plugin *plugin)
     }
     return FALSE;
 }
-
+//Auto plugin detection is disabled
+/*
 void CpluffAdapter::observePluginPath(void *str)
 {
     //printf("start observePluginPath\n");
@@ -568,7 +588,7 @@ void CpluffAdapter::observePluginPath(void *str)
     ( void ) close( fd );
     //printf("observePluginPath end\n");
 }
-
+*/
 const std::string CpluffAdapter::getState(const std::string plugID)
 {
     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
index ec565d3..e0b934f 100644 (file)
@@ -38,6 +38,7 @@
 #include <internal.h>
 
 #include "Plugin.h"
+#include "Config.h"
 
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     (int)( 1024 * ( EVENT_SIZE + 16 ) )
@@ -160,6 +161,13 @@ namespace OIC
             */
             const std::string getState(const std::string plugID);
 
+            /**
+            * print whole plugin info.
+            *
+            * @param cpluff plugins
+            */
+            void printPluginList();
+
 
             /**
             *
@@ -181,15 +189,14 @@ namespace OIC
 
         private:
 
+            Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             cp_context_t *m_context;
             cp_status_t m_status;
             cp_plugin_info_t **m_cp_plugins;
             cp_plugin_info_t *m_plugin;
-            boost::thread m_file_detect_thread;
-            boost::thread_group m_thread_g;
-            std::string m_path;
+            //boost::thread_group m_thread_g;
             static CpluffAdapter *s_pinstance;
 
             /**
@@ -222,7 +229,7 @@ namespace OIC
             * @param plugin file path.
             * @return void
             */
-            void observePluginPath(void *);
+            //void observePluginPath(void *);
 
 
             /**
@@ -243,13 +250,6 @@ namespace OIC
             bool getFileList(File_list &list, const std::string strDir);
 
             /**
-            * print whole plugin info.
-            *
-            * @param cpluff plugins
-            */
-            void printPluginList(cp_plugin_info_t **plugins);
-
-            /**
             * install plugin using c-pluff.
             *
             * @param Root path.
index 0247e74..50a92e2 100644 (file)
@@ -30,7 +30,18 @@ FelixAdapter *FelixAdapter::s_pinstance;
 
 FelixAdapter::FelixAdapter()
 {
-
+    config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path is not exist\n");
+        pluginpath = "";
+    }
+    registerAllPlugin(pluginpath);
 }
 
 FelixAdapter::~FelixAdapter(void)
@@ -113,12 +124,12 @@ bool FelixAdapter::isStarted(Plugin *plugin)
 {
     return FALSE;
 }
-
+/*
 void FelixAdapter::observePluginPath(void *str)
 {
 
 }
-
+*/
 const std::string FelixAdapter::getState(const std::string plugID)
 {
     return "";
index 3842184..7c6398c 100644 (file)
@@ -38,6 +38,7 @@
 #include <internal.h>
 
 #include "Plugin.h"
+#include "Config.h"
 
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     (int)( 1024 * ( EVENT_SIZE + 16 ) )
@@ -180,7 +181,7 @@ namespace OIC
 
 
         private:
-
+            Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             boost::thread m_file_detect_thread;
@@ -224,7 +225,7 @@ namespace OIC
             * @param plugin file path.
             * @return void
             */
-            void observePluginPath(void *);
+            //void observePluginPath(void *);
 
             /**
             * Get whole "SO" file list.
index d77f68f..7ef312c 100644 (file)
@@ -136,16 +136,6 @@ namespace OIC
             return false;
         }
     }
-
-    std::vector<std::string> Plugin::getSupportedType(void)
-    {
-        return m_supportedType;
-    }
-
-    void Plugin::addSupportedType(const std::string rscType)
-    {
-        m_supportedType.push_back(rscType);
-    }
 }
 
 
index bd823d8..5b1e3a6 100644 (file)
@@ -141,22 +141,6 @@ namespace OIC
             */
             bool operator==(Plugin &plugin);
 
-            /**
-            * Get supported resourc type
-            *
-            *
-            * @return vector of surported resource type
-            */
-            std::vector<std::string> getSupportedType(void);
-            /**
-            * Add supported resource type for a plugin
-            *
-            * @param resource type string
-            * @return void
-            *
-            */
-            void addSupportedType(const std::string rscType);
-
         private:
             std::map<std::string, AttributeValue> m_attributeMap;
             std::vector<std::string> m_supportedType;
index 7c158ca..c3abdb8 100644 (file)
@@ -56,18 +56,17 @@ int PluginManager::stopPlugins(const std::string key, const std::string value)
     return pluginManagerImpl->stopPlugins(key, value);
 }
 
-int PluginManager::startPlugins(Plugin *const plugin)
+int PluginManager::rescanPlugin()
 {
-    printf("PluginManager::startPlugins\n");
-    return pluginManagerImpl->startPlugins(plugin);
+    return pluginManagerImpl->rescanPlugin();
 }
 
-int PluginManager::stopPlugins(Plugin *const plugin)
+std::vector<Plugin> PluginManager::getPlugins(void)
 {
-    return pluginManagerImpl->stopPlugins(plugin);
+    return pluginManagerImpl->getAllPlugins();
 }
 
-std::vector<Plugin> PluginManager::getPlugins(void)
+std::string PluginManager::getState(const std::string plugID)
 {
-    return pluginManagerImpl->getAllPlugins();
+    return pluginManagerImpl->getState(plugID);
 }
\ No newline at end of file
index 41a631e..2ae8b73 100644 (file)
@@ -68,23 +68,13 @@ namespace OIC
             int stopPlugins(const std::string key, const std::string value);
 
             /**
-            * Start plugin
-            * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+            * Rescan Plugin.
+            * This function will call rescan function of plugins in the configuration folder
             *
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            int startPlugins(Plugin *const plugin);
-
-
-            /**
-            * Stop Plugin.
-            * This function will call stop function of plugin and unload dynamic plugin library from memory.
-            *
-            * @param Plugin
-            * @return int, 1 is success, 0 is fail.
-            */
-            int stopPlugins(Plugin *const plugin);
+            int rescanPlugin();
 
             /**
             * Get Plugin list.
@@ -95,6 +85,14 @@ namespace OIC
             */
             std::vector<Plugin> getPlugins(void);
 
+            /**
+            * Get Plugin state.
+            *
+            * @param Plugin ID
+            * @return Plugin state.
+            */
+            std::string getState(const std::string plugID);
+
         private:
             PluginManagerImpl *pluginManagerImpl;
             void (*destroy)(PluginManagerImpl *);
index d501786..2795e83 100644 (file)
@@ -110,6 +110,23 @@ int PluginManagerImpl::unregisterAllPlugin()
     return flag;
 }
 
+int PluginManagerImpl::rescanPlugin()
+{
+    Config *config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path does not exist\n");
+        pluginpath = "";
+    }
+    int result = registerAllPlugin(pluginpath);
+    return result;
+}
+
 
 std::vector<Plugin> &PluginManagerImpl::getAllPlugins(void)
 {
index f42236a..3beb8e8 100644 (file)
@@ -120,7 +120,7 @@ namespace OIC
             * @param Plugin ID
             * @return Plugin state.
             */
-            std::string getState(const std::string plugID);
+            virtual std::string getState(const std::string plugID);
 
             /**
             * Start  plugins by resource type
@@ -145,7 +145,7 @@ namespace OIC
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            virtual int startPlugins(Plugin *const plugin);
+            int startPlugins(Plugin *const plugin);
 
 
             /**
@@ -155,7 +155,16 @@ namespace OIC
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            virtual int stopPlugins(Plugin *const plugin);
+            int stopPlugins(Plugin *const plugin);
+
+            /**
+            * Rescan Plugin.
+            * This function will call rescan function of plugins in the configuration folder
+            *
+            * @param Plugin
+            * @return int, 1 is success, 0 is fail.
+            */
+            virtual int rescanPlugin();
 
             /**
             * get all plugins which currently registered.
diff --git a/service/protocol-plugin/plugins/SConscript b/service/protocol-plugin/plugins/SConscript
new file mode 100644 (file)
index 0000000..0d9e0cf
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Plugins build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+plugins_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+plugins_env.AppendUnique(CPPPATH = ['../lib/cpluff/libcpluff'])
+
+if target_os not in ['windows', 'winrt']:
+       plugins_env.AppendUnique(CXXFLAGS = ['-g3', '-Wall', '-pthread', '-std=c++0x'])
+       plugins_env.AppendUnique(LINKFLAGS = ['-fPIC'])
+
+       if target_os not in ['arduino', 'android']:
+               plugins_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+       plugins_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       plugins_env.AppendUnique(LIBS = ['gnustl_static'])
+       plugins_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+mqtt_fan_src = Glob('mqtt-fan/src/' + '*.cpp')
+fanserver = plugins_env.SharedLibrary('fanserver_mqtt_plugin', mqtt_fan_src)
+
+mqtt_light_src = Glob('mqtt-light/src/' + '*.cpp')
+lightserver = plugins_env.SharedLibrary('lightserver_mqtt_plugin', mqtt_light_src)
+
+SConscript('mqtt-fan/lib/SConscript')
index bf4db27..248e35c 100644 (file)
@@ -1,13 +1,15 @@
-include ../../../../config.mk
-
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall -pthread
 
+TOP_DIR = ../../../../../..
 LIB_DIR = ../../../../../../resource
 
 SRC_DIR = ../../src
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -17,9 +19,11 @@ CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
 CXX_INC += -I$(BOOST_DIR) 
 CXX_INC += -I../../lib 
 CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC          += -I../csdk/libcoap
+CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+CXX_LIBS  := ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
 
 .PHONY: lib release_build ./release/fanserver_mqtt_plugin.so 
 
@@ -34,7 +38,7 @@ release_build:
        cp plugin.xml release
 
 ./release/fanserver_mqtt_plugin.so: ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o
-       $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS)  -L../../lib -lmosquitto -lssl -lrt
+       $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS)  -L../../lib -L$(TOP_DIR)/out/linux/x86/release -lmosquitto -lssl -lrt -loc -loctbstack -loc_logger -lcoap
 
 ./release/obj/fanserver_mqtt_plugin.o: $(SRC_DIR)/fanserver_mqtt_plugin.cpp
        $(CXX) $(CXX_INC) -fPIC -o ./release/obj/fanserver_mqtt_plugin.o -c $(SRC_DIR)/fanserver_mqtt_plugin.cpp 
diff --git a/service/protocol-plugin/plugins/mqtt-fan/lib/SConscript b/service/protocol-plugin/plugins/mqtt-fan/lib/SConscript
new file mode 100644 (file)
index 0000000..a5695c2
--- /dev/null
@@ -0,0 +1,27 @@
+##
+# mosquitto build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+mosquitto_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+mosquitto_env.AppendUnique(CPPPATH = ['./'])
+if target_os not in ['windows', 'winrt']:
+       mosquitto_env.AppendUnique(CFLAGS = ['-Wall', '-ggdb', '-fPIC',
+                       '-DWITH_TLS', '-DWITH_TLS_PSK', '-DWITH_THREADING'])
+######################################################################
+# Source files and Targets
+######################################################################
+mosquitto_src = env.Glob('*.c')
+
+mosquitto = mosquitto_env.StaticLibrary('mosquitto', mosquitto_src)
+mosquitto_env.InstallTarget(mosquitto, 'libmosquitto')
+
+SConscript('cpp/SConscript')
diff --git a/service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript b/service/protocol-plugin/plugins/mqtt-fan/lib/cpp/SConscript
new file mode 100644 (file)
index 0000000..55e2333
--- /dev/null
@@ -0,0 +1,24 @@
+##
+# mosquittopp build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+mosquittopp_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+mosquittopp_env.AppendUnique(CPPPATH = ['./', '../'])
+if target_os not in ['windows', 'winrt']:
+       mosquittopp_env.AppendUnique(CFLAGS = ['-Wall', '-ggdb', '-O2', '-fPIC'])
+
+mosquittopp_env.AppendUnique(LIBS = ['mosquitto', 'ssl', 'crypto'])
+######################################################################
+# Source files and Targets
+######################################################################
+mosquittopp = mosquittopp_env.SharedLibrary('mosquittopp', 'mosquittopp.cpp')
+mosquittopp_env.InstallTarget(mosquittopp, 'libmosquittopp')
index 544679a..12111e0 100644 (file)
@@ -45,23 +45,22 @@ struct tm *tblock;           // Define a structure for time block
 
 int gObservation = 0;
 void *ChangeFanRepresentation (void *param);
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 
 // Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'fanResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
 
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
 
 // Forward declaring the entityHandler
-// void entityHandler(std::shared_ptr<OCResourceRequest> request,
-//                    std::shared_ptr<OCResourceResponse> response);
-
 /// This class represents a single resource named 'fanResource'. This resource has
 /// two simple properties named 'state' and 'power'
 typedef struct plugin_data_t plugin_data_t;
@@ -114,7 +113,7 @@ class FanResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
 
             // This will internally create and register the resource.
             OCStackResult result = OCPlatform::registerResource(
@@ -136,7 +135,7 @@ class FanResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
 
             OCResourceHandle resHandle;
 
@@ -251,13 +250,10 @@ class FanResource
     private:
         // This is just a sample implementation of entity handler.
         // Entity handler can be implemented in several ways by the manufacturer
-        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                            std::shared_ptr<OCResourceResponse> response)
+        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
         {
-            OCEntityHandlerResult result = OC_EH_OK;
-
             cout << "\tIn Server CPP entity handler:\n";
-
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
             if (request)
             {
                 // Get the request type and request flag
@@ -272,40 +268,52 @@ class FanResource
                 }
                 if (requestFlag & RequestHandlerFlag::RequestFlag)
                 {
-                    cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+                    cout << "\t\trequestFlag : Request   ===  Handle by FanServer\n";
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
 
                     // If the request type is GET
                     if (requestType == "GET")
                     {
                         cout << "\t\t\trequestType : GET\n";
-
-                        if (response)
+                        if (isSlowResponse) // Slow response case
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            static int startedThread = 0;
+                            if (!startedThread)
+                            {
+                                std::thread t(handleSlowResponse, (void *)this, request);
+                                startedThread = 1;
+                                t.detach();
+                            }
+                            ehResult = OC_EH_SLOW;
+                        }
+                        else // normal response case.
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_OK);
+                            pResponse->setResourceRepresentation(get());
+                            if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                            {
+                                ehResult = OC_EH_OK;
+                            }
                         }
                     }
                     else if (requestType == "PUT")
                     {
                         cout << "\t\t\trequestType : PUT\n";
-
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to PUT request
-
                         // Update the fanResource
                         put(rep);
-
-                        if (response)
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get());
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            ehResult = OC_EH_OK;
                         }
-
                     }
                     else if (requestType == "POST")
                     {
@@ -314,26 +322,19 @@ class FanResource
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to POST request
-
                         OCRepresentation rep_post = post(rep);
-
-                        if (response)
+                        pResponse->setResourceRepresentation(rep_post);
+                        pResponse->setErrorCode(200);
+                        if (rep_post.hasAttribute("createduri"))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(rep_post);
-
-                            if (rep_post.hasAttribute("createduri"))
-                            {
-                                result = OC_EH_RESOURCE_CREATED;
-
-                                response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                            }
-
+                            pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                            pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                         }
 
-                        // POST request operations
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
                     }
                     else if (requestType == "DELETE")
                     {
@@ -370,6 +371,7 @@ class FanResource
                         pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
                         startedThread = 1;
                     }
+                    ehResult = OC_EH_OK;
                 }
             }
             else
@@ -377,7 +379,7 @@ class FanResource
                 std::cout << "Request invalid" << std::endl;
             }
 
-            return result;
+            return ehResult;
         }
 };
 
@@ -436,34 +438,36 @@ void *ChangeFanRepresentation (void *param)
     return NULL;
 }
 
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    FanResource *fanPtr = (FanResource *) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(fanPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
+
 
 //int start_fanserver(void*)                // 1
 void *start_fanserver(void *d)      // 2
 {
-    /*PlatformConfig cfg;
-    cfg.ipAddress = "192.168.2.5";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;*/
-    // PlatformConfig cfg
-    // {
-    //     OC::ServiceType::InProc,
-    //     OC::ModeType::Server,
-    //     "192.168.2.5",
-    //     56832,
-    //     OC::QualityOfService::NonConfirmable
-    // };
-
-    // Create PlatformConfig object
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-
     // Create PlatformConfig object
     PlatformConfig cfg
     {
         OC::ServiceType::InProc,
-        OC::ModeType::Server,
+        OC::ModeType::Both,
         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
         0,         // Uses randomly available port
         OC::QualityOfService::LowQos
@@ -487,18 +491,9 @@ void *start_fanserver(void *d)      // 2
             printf("Mosquitto is working\n");
         }
 
-        //plugin_data_t *data = (plugin_data_t *)d;
-        //OCPlatform *platform = (OCPlatform*)data->str;
-        //myFanResource.m_platform = (OCPlatform*)data->str;
-        //OCPlatform platform(cfg);
-        // Invoke createResource function of class fan.
-
-        //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
         printf("Mosquitto Connection is done\n");
         myFanResource.createResource();
-        //myFanResource.addType(std::string("core.fan"));
-        //myFanResource.addInterface(std::string("oc.mi.ll"));
         // Get time of day
         timer = time(NULL);
         // Converts date/time to a structure
index 9b2aca2..788b7cf 100644 (file)
@@ -1,13 +1,15 @@
-include ../../../../config.mk
-
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall -pthread
 
+TOP_DIR = ../../../../../..
 LIB_DIR = ../../../../../../resource
 
 SRC_DIR = ../../src
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -17,9 +19,11 @@ CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
 CXX_INC += -I$(BOOST_DIR) 
 CXX_INC += -I../../lib 
 CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC          += -I../csdk/libcoap
+CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+CXX_LIBS  := ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
 
 .PHONY: lib release_build ./release/lightserver_mqtt_plugin.so 
 
@@ -34,7 +38,7 @@ release_build:
        cp plugin.xml release
 
 ./release/lightserver_mqtt_plugin.so: ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o
-       $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS)  -L../../lib -lmosquitto -lssl -lrt
+       $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS)  -L../../lib  -L$(TOP_DIR)/out/linux/x86/release -lmosquitto -lssl -lrt -loc -loctbstack -loc_logger -lcoap
 
 ./release/obj/lightserver_mqtt_plugin.o: $(SRC_DIR)/lightserver_mqtt_plugin.cpp
        $(CXX) $(CXX_INC) -fPIC -o ./release/obj/lightserver_mqtt_plugin.o -c $(SRC_DIR)/lightserver_mqtt_plugin.cpp 
index 93bad63..9f30718 100644 (file)
@@ -43,18 +43,19 @@ struct tm *tblock;           // Define a structure for time block
 
 int gObservation = 0;
 void *ChangeLightRepresentation (void *param);
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 // Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
 
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
 
 // Forward declaring the entityHandler
 // void entityHandler(std::shared_ptr<OCResourceRequest> request,
@@ -112,7 +113,7 @@ class LightResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
 
             // This will internally create and register the resource.
             OCStackResult result = OCPlatform::registerResource(
@@ -134,7 +135,7 @@ class LightResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
 
             OCResourceHandle resHandle;
 
@@ -249,13 +250,10 @@ class LightResource
     private:
         // This is just a sample implementation of entity handler.
         // Entity handler can be implemented in several ways by the manufacturer
-        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                            std::shared_ptr<OCResourceResponse> response)
+        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
         {
-            OCEntityHandlerResult result = OC_EH_OK;
-
             cout << "\tIn Server CPP entity handler:\n";
-
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
             if (request)
             {
                 // Get the request type and request flag
@@ -270,40 +268,52 @@ class LightResource
                 }
                 if (requestFlag & RequestHandlerFlag::RequestFlag)
                 {
-                    cout << "\t\trequestFlag : Request ===  Handle by LightServer\n";
+                    cout << "\t\trequestFlag : Request ===  Handle by FanServer\n";
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
 
                     // If the request type is GET
                     if (requestType == "GET")
                     {
                         cout << "\t\t\trequestType : GET\n";
-
-                        if (response)
+                        if (isSlowResponse) // Slow response case
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            static int startedThread = 0;
+                            if (!startedThread)
+                            {
+                                std::thread t(handleSlowResponse, (void *)this, request);
+                                startedThread = 1;
+                                t.detach();
+                            }
+                            ehResult = OC_EH_SLOW;
+                        }
+                        else // normal response case.
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_OK);
+                            pResponse->setResourceRepresentation(get());
+                            if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                            {
+                                ehResult = OC_EH_OK;
+                            }
                         }
                     }
                     else if (requestType == "PUT")
                     {
                         cout << "\t\t\trequestType : PUT\n";
-
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to PUT request
-
                         // Update the lightResource
                         put(rep);
-
-                        if (response)
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get());
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            ehResult = OC_EH_OK;
                         }
-
                     }
                     else if (requestType == "POST")
                     {
@@ -312,26 +322,19 @@ class LightResource
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to POST request
-
                         OCRepresentation rep_post = post(rep);
-
-                        if (response)
+                        pResponse->setResourceRepresentation(rep_post);
+                        pResponse->setErrorCode(200);
+                        if (rep_post.hasAttribute("createduri"))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(rep_post);
-
-                            if (rep_post.hasAttribute("createduri"))
-                            {
-                                result = OC_EH_RESOURCE_CREATED;
-
-                                response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                            }
-
+                            pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                            pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                         }
 
-                        // POST request operations
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
                     }
                     else if (requestType == "DELETE")
                     {
@@ -368,6 +371,7 @@ class LightResource
                         pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                         startedThread = 1;
                     }
+                    ehResult = OC_EH_OK;
                 }
             }
             else
@@ -375,7 +379,7 @@ class LightResource
                 std::cout << "Request invalid" << std::endl;
             }
 
-            return result;
+            return ehResult;
         }
 };
 
@@ -434,36 +438,36 @@ void *ChangeLightRepresentation (void *param)
     return NULL;
 }
 
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    LightResource *lightPtr = (LightResource *) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(lightPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
 
 
 //int start_lightserver(void*)                // 1
 void *start_lightserver(void *d)      // 2
 {
-    /*PlatformConfig cfg;
-    cfg.ipAddress = "192.168.2.5";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;*/
-    // PlatformConfig cfg
-    // {
-    //     OC::ServiceType::InProc,
-    //     OC::ModeType::Server,
-    //     "192.168.2.5",
-    //     56832,
-    //     OC::QualityOfService::NonConfirmable
-    // };
-
-    // Create PlatformConfig object
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-
     // Create PlatformConfig object
     PlatformConfig cfg
     {
         OC::ServiceType::InProc,
-        OC::ModeType::Server,
+        OC::ModeType::Both,
         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
         0,         // Uses randomly available port
         OC::QualityOfService::LowQos
@@ -487,18 +491,9 @@ void *start_lightserver(void *d)      // 2
             printf("Mosquitto is working\n");
         }
 
-        //plugin_data_t *data = (plugin_data_t *)d;
-        //OCPlatform *platform = (OCPlatform*)data->str;
-        //myLightResource.m_platform = (OCPlatform*)data->str;
-        //OCPlatform platform(cfg);
-        // Invoke createResource function of class light.
-
-        //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
         printf("Mosquitto Connection is done\n");
         myLightResource.createResource();
-        //myLightResource.addType(std::string("core.light"));
-        //myLightResource.addInterface(std::string("oc.mi.ll"));
         // Get time of day
         timer = time(NULL);
         // Converts date/time to a structure
index 935bc7e..351756b 100644 (file)
@@ -1,20 +1,75 @@
 
+This guide will help you setup your developing environment for Protocol plug-in Manager and Protocol plug-ins in Ubuntu. 
+
+1. Preparings
+Before starting, following tools should be installed. 
+
+Automake
+Automake is a tool for automatically generating Makefile.in files compiliant with the GNU Coding Standards. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+$ sudo apt-get install automake
+
+Libtool
+GNU libtool is a generic library support script. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install libtool
+
+gettext
+GNU `gettext' utilities are a set of tools that provides a framework to help other GNU packages produce multi-lingual messages. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install gettext
+
+Expat
+Expat is a stream-oriented XML parser library. This library is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install expat
+
+Building and Using Protocol Plug-in Manager
+
+Once the source code is downloaded into a specific folder, oic in this context, you may follow the steps to build and execute Protocol Plug-in Manager.
+The path for Protocol Plugin is as following;
+
+~/oic/oic-resource/service/protocol-plugin $_
+
+The Protocol Plug-in directory includes following sub directories;
+
+/plugin-manager        Directory for Plug-in Manager
+/plugins       Directory for Reference Plugins  
+/lib           Directory for Common Library
+/sample-app    Directory for Iotivity Sample Application
+/doc           Directory for Developers Document
+/build         Directory for Building and Binary Release
+
+
+2. Compiling C-Pluff library 
+Before building Protocol-Plugin Manager, C-Pluff library should be compiled as follows.
+
+~/oic/oic-service/protocol-plugin/lib/cpluff$ aclocal
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoconf
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoheader
+~/oic/oic-service/protocol-plugin/lib/cpluff$ automake
+~/oic/oic-service/protocol-plugin/lib/cpluff$ ./configure
+~/oic/oic-service/protocol-plugin/lib/cpluff$ make
+
+3. Run make
+By running make in the protocol-plugin path, protocol-plugin manager, all plugins and sample applications will be created. 
+NOTE: To build plugins in 64-bit Ubuntu Linux, OCLib.a and libcoap.a library should be re-compiled with ?fPIC option.
+~/oic/oic-service/protocol-plugin/build/linux$make
+
+
+4. Using Plugins 
 This version of protocol plug-in source code has following functionality.
 
-1. provides plug-in manager which can register, unregister, start and stop plug-in library.
-2. provides plug-in library which can communicate with MQTT protocol FAN.
-3. provides OIC Sample Client which can turn on/off FAN.
+1) provides plug-in manager which can start and stop plug-in library.
+2) provides plug-in library which can communicate with MQTT protocol Fan and Light.
+3) provides OIC Sample Client which can get info about Fan and Light with configuration file(pluginmanager.xml).
 
 So, to test a plug-in, follow below steps.
 
-1. Locate shared plug-in library and XML file in a specific folder.
-2. Register the plug-in with directory path input from plug-in manager sample.
-3. Start the plug-in from plug-in manager sample.
-4. Run OIC sample client.
-
-If you have any questions about protocol plug-in component, please contact with following addresses.
+1) Locate shared plug-in library and XML file in a specific folder.
+2) Register the plug-in with directory path input from plug-in manager sample.
+3) Start the plug-in from plug-in manager sample.
+4) Run OIC sample client.
+   ex)service/protocol-plugin/sample-app/linux/mqtt$./mqttclient
+  (mqtt broker is already installed in the local system.)
 
-kc7576.park@samsung.com
-heesung84.kim@samsung.com
-junho13.lee@samsung.com
-yh_.joo@samsung.com
\ No newline at end of file
diff --git a/service/protocol-plugin/sample-app/SConscript b/service/protocol-plugin/sample-app/SConscript
new file mode 100644 (file)
index 0000000..413dd94
--- /dev/null
@@ -0,0 +1,10 @@
+##
+#sample-app build script
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os == 'linux':
+       SConscript('linux/SConscript')
diff --git a/service/protocol-plugin/sample-app/linux/SConscript b/service/protocol-plugin/sample-app/linux/SConscript
new file mode 100644 (file)
index 0000000..339d4bb
--- /dev/null
@@ -0,0 +1,28 @@
+##
+#sample-app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+sample_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+sample_env.AppendUnique(CPPPATH = ['../../plugin-manager/src/',
+                               '../../lib/cpluff/libcpluff/'])
+if target_os not in ['windows', 'winrt']:
+       sample_env.AppendUnique(CXXFLAGS = ['-Wall', '-pthread', '-std=c++0x'])
+
+sample_env.AppendUnique(LIBS = ['oc', 'oc_logger', 'octbstack', 'coap', 'ppm', 'pmimpl', 'dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+fanclient = sample_env.Program('fanclient', 'fan-control/fanclient.cpp')
+
+Alias('fanclient', fanclient)
+env.AppendTarget('fanclient')
\ No newline at end of file
diff --git a/service/protocol-plugin/sample-app/linux/fan-control/Makefile b/service/protocol-plugin/sample-app/linux/fan-control/Makefile
deleted file mode 100644 (file)
index 6b5d664..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-CXX = g++
-
-CXX_FLAGS = -std=c++0x -Wall -pthread
-
-LIB_DIR = ../../../../../resource
-
-CXX_INC := -I$(LIB_DIR)/include/ 
-CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/ 
-CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
-CXX_INC += -I$(BOOST_DIR) 
-CXX_INC += -I../../lib
-CXX_INC += -I../../../lib/cpluff/libcpluff
-CXX_INC += -I../../../plugin-manager/src
-
-LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
-LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
-
-.PHONY: fanclient
-
-all: .PHONY
-
-fanclient: fanclient.o
-       $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(CXX_LIBS) $(LINK_LIB)
-
-fanclient.o: fanclient.cpp
-       $(CXX) $(CXX_FLAGS) -c fanclient.cpp $(CXX_INC)
-
-       
-clean:
-       rm -f *.o
-       rm -f fanclient 
diff --git a/service/protocol-plugin/sample-app/linux/mqtt/Makefile b/service/protocol-plugin/sample-app/linux/mqtt/Makefile
new file mode 100644 (file)
index 0000000..131e83a
--- /dev/null
@@ -0,0 +1,42 @@
+CXX = g++
+
+CXX_FLAGS = -std=c++0x -Wall -pthread
+
+TOP_DIR = ../../../../..
+LIB_DIR = ../../../../../resource
+
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
+CXX_INC := -I$(LIB_DIR)/include/ 
+CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/ 
+CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
+CXX_INC += -I$(BOOST_DIR) 
+CXX_INC += -I../../lib
+CXX_INC += -I../../../lib/cpluff/libcpluff
+CXX_INC += -I../../../plugin-manager/src
+CXX_INC   += -I$(CEREAL_DIR)/include
+CXX_INC += -I../../../lib/rapidxml 
+
+LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
+CXX_LIBS  := ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread -L$(TOP_DIR)/out/linux/x86/release -loc -loctbstack -loc_logger -lcoap
+
+.PHONY: mqttclient
+
+all: .PHONY
+
+mqttclient: mqttclient.o
+       $(CXX) $(CXX_FLAGS) -o mqttclient mqttclient.o $(CXX_LIBS) $(LINK_LIB)
+
+mqttclient.o: mqttclient.cpp
+       $(CXX) $(CXX_FLAGS) -c mqttclient.cpp $(CXX_INC)
+
+       
+clean:
+       rm -f *.o
+       rm -f *.so
+       rm -f mqttclient
@@ -32,7 +32,8 @@
 using namespace OC;
 using namespace OIC;
 
-std::shared_ptr<OCResource> curResource;
+std::shared_ptr<OCResource> curFanResource;
+std::shared_ptr<OCResource> curLightResource;
 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
 
 time_t timer;                // Define the timer
@@ -78,7 +79,7 @@ void onObserve(const HeaderOptions headerOptions, const OCRepresentation &rep,
         if (observe_count() > 30)
         {
             std::cout << "Cancelling Observe..." << std::endl;
-            OCStackResult result = curResource->cancelObserve();
+            OCStackResult result = curFanResource->cancelObserve();
 
             std::cout << "Cancel result: " << result << std::endl;
             sleep(10);
@@ -120,7 +121,7 @@ void onPost2(const HeaderOptions &headerOptions, const OCRepresentation &rep, co
         else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
             std::cout << endl << "ObserveAll is used." << endl << endl;
 
-        curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
+        //curFanResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
 
     }
     else
@@ -162,7 +163,7 @@ void onPost(const HeaderOptions &headerOptions, const OCRepresentation &rep, con
         rep2.setValue("state", myfan.m_state);
         rep2.setValue("power", myfan.m_power);
 
-        curResource->post(rep2, QueryParamsMap(), &onPost2);
+        curFanResource->post(rep2, QueryParamsMap(), &onPost2);
     }
     else
     {
@@ -206,7 +207,7 @@ void onPut(const HeaderOptions &headerOptions, const OCRepresentation &rep, cons
         std::cout << "\tpower: " << myfan.m_power << std::endl;
         std::cout << "\tname: " << myfan.m_name << std::endl;
 
-        postFanRepresentation(curResource);
+        postFanRepresentation(curFanResource);
     }
     else
     {
@@ -251,7 +252,7 @@ void onGet(const HeaderOptions &headerOptions, const OCRepresentation &rep, cons
         std::cout << "\tpower: " << myfan.m_power << std::endl;
         std::cout << "\tname: " << myfan.m_name << std::endl;
 
-        putFanRepresentation(curResource);
+        putFanRepresentation(curFanResource);
     }
     else
     {
@@ -288,7 +289,7 @@ void getLightRepresentation(std::shared_ptr<OCResource> resource)
 // Callback to found resources
 void foundResourceFan(std::shared_ptr<OCResource> resource)
 {
-    if (curResource)
+    if (curFanResource)
     {
         std::cout << "Found another resource, ignoring" << std::endl;
     }
@@ -325,7 +326,7 @@ void foundResourceFan(std::shared_ptr<OCResource> resource)
 
             if (resourceURI == "/a/fan")
             {
-                curResource = resource;
+                curFanResource = resource;
                 // Call a local function which will internally invoke get API on the resource pointer
                 getFanRepresentation(resource);
             }
@@ -346,7 +347,7 @@ void foundResourceFan(std::shared_ptr<OCResource> resource)
 // Callback to found resources
 void foundResourceLight(std::shared_ptr<OCResource> resource)
 {
-    if (curResource)
+    if (curLightResource)
     {
         std::cout << "Found another resource, ignoring" << std::endl;
     }
@@ -383,7 +384,7 @@ void foundResourceLight(std::shared_ptr<OCResource> resource)
 
             if (resourceURI == "/a/light")
             {
-                curResource = resource;
+                curLightResource = resource;
                 // Call a local function which will internally invoke get API on the resource pointer
                 getLightRepresentation(resource);
             }
@@ -425,7 +426,9 @@ void client1()
     std::cout << "Finding Fan Resource... time : " << asctime(tblock) << std::endl;
     while (1)
     {
-        // client1 related operations
+        std::cout << "Get Fan Resource....." << std::endl;
+        sleep(5);
+        getFanRepresentation(curFanResource);
     }
 }
 
@@ -449,7 +452,9 @@ void client2()
 
     while (1)
     {
-        // client2 related operations
+        std::cout << "Get Light Resource....." << std::endl;
+        sleep(5);
+        getLightRepresentation(curLightResource);
     }
 }
 
@@ -457,6 +462,11 @@ void client2()
 
 int main(int argc, char *argv[])
 {
+    std::string name;
+    std::string key = "Name";
+    std::string  state = "";
+    std::string  id = "";
+
     if (argc == 1)
     {
         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
@@ -494,41 +504,83 @@ int main(int argc, char *argv[])
 
         std::cout << "Created Platform..." << std::endl;
 
-
         PluginManager *m_pm = new PluginManager();
 
+        std::cout << "==== 1st TEST CASE ===" << std::endl;
         std::cout << "======================" << std::endl;
-
         std::cout << "start light Plugin by Resource Type"  << std::endl;
+
         m_pm->startPlugins("ResourceType", "oic.light");
 
         sleep(2);
 
+        std::cout << "\n==== 2nd TEST CASE =====" << std::endl;
         std::cout << "======================" << std::endl;
-        std::cout << "get Plugin List" << std::endl;
+        std::cout << "Get Plugin List\n" << std::endl;
         std::vector<Plugin> user_plugin;
+
         user_plugin = m_pm->getPlugins();
+
         for (unsigned int i = 0; i < user_plugin.size(); i++)
         {
-            printf("value Name = %s\n", user_plugin[i].getName().c_str());
-            printf("value ID = %s\n", user_plugin[i].getID().c_str());
+            std::cout << "value Name = " << user_plugin[i].getName() << std::endl;
+            std::cout << "value ID = " << user_plugin[i].getID() << std::endl;
+            id =  user_plugin[i].getID();
         }
-
+        std::cout << "\n===== 3rd TEST CASE =====" << std::endl;
         std::cout << "======================" << std::endl;
-        std::cout << "start Fan Plugin by Name" << std::endl;
-        m_pm->startPlugins("Name", "mqtt-fan");
+        std::cout << "Start Fan Plugin by Name\n" << std::endl;
+
+        name = user_plugin[0].getName().c_str();
+        m_pm->startPlugins(key, name);
+
+        sleep(5);
+
+        std::cout << "\n====== 4th TEST CASE ======" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Get Plugin Status\n" << std::endl;
+
+        state = m_pm->getState(id);
 
+        std::cout << "last plugin status :  " << state << std::endl;
+        std::cout << "sleep 15 seconds please add new plugin in the plugin folder  " << std::endl;
 
+        sleep(15);
+
+        std::cout << "\n====  5th TEST CASE  ====" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Rescan Plugins.........\n" << std::endl;
+
+        m_pm->rescanPlugin();
+
+        std::cout << "\n====  6th TEST CASE  ====" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Try to start new resource type.........\n" << std::endl;
+        std::cout << "start oic.test resource" <<  std::endl;
+
+        sleep(5);
+
+        int flag = m_pm->startPlugins("ResourceType", "oic.test");
+
+        if (!flag)
+            std::cout << "There are no resouce type. Start plugin failed" << std::endl;
         // Start each client in a seperate thread
-//        std::thread t1(client1);
-//        t1.detach();
 
-///*
-//        sleep(5);
+        sleep(10);
+
+        std::cout << "\n====== 7th TEST CASE =======" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << " start client to find resource" << std::endl;
+
+        std::thread t1(client1);
+        t1.detach();
+
+        sleep(5);
+
         // Start each client in a seperate thread
-//        std::thread t2(client2);
-//        t2.detach();
-//*/
+        std::thread t2(client2);
+        t2.detach();
+
         while (true)
         {
             // some operations
diff --git a/service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml b/service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml
new file mode 100644 (file)
index 0000000..c90bb9f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pluginManager>
+    <pluginInfo        
+        pluginPath="../../../plugins"        
+        maxMEM="64M"
+        maxPlugin=""
+        version="1.0"
+        name="pluginmanager">
+    </pluginInfo>
+    <specailpluginInfo>
+    </specailpluginInfo>
+</pluginManager>
diff --git a/service/soft-sensor-manager/SConscript b/service/soft-sensor-manager/SConscript
new file mode 100644 (file)
index 0000000..aec6fcb
--- /dev/null
@@ -0,0 +1,103 @@
+##
+# soft-sensor-manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+soft_sensor_manager_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+# As in the source code, it includes arduino Time library (C++)
+# It requires compile the .c with g++
+if target_os == 'arduino':
+       soft_sensor_manager_env.Replace(CC = env.get('CXX'))
+       soft_sensor_manager_env.Replace(CFLAGS = env.get('CXXFLAGS'))
+
+######################################################################
+# Build flags
+######################################################################
+if target_os not in ['windows', 'winrt']:
+       soft_sensor_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
+       if target_os != 'android':
+               soft_sensor_manager_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+#######################################################################
+## build SSM SDK
+#######################################################################
+sdk_env = soft_sensor_manager_env.Clone()
+sdk_env.AppendUnique(CPPPATH = ['SDK/include'])
+
+ssm_sdk = sdk_env.Object('SDK/src/SSMClient.cpp')
+i_ssmsdk = sdk_env.Install(env.get('BUILD_DIR'), )
+Alias('libSSMSDKLibrary', i_ssmsdk)
+env.AppendTarget('libSSMSDKLibrary')
+
+######################################################################
+# build DiscomfortIndexSensor plugin
+######################################################################
+DiscomfortIndexSensor_env = soft_sensor_manager_env.Clone()
+
+DiscomfortIndexSensor_env.AppendUnique(CCFLAGS = ['-fPIC'])
+DISCOMFORTINDEXSENSOR_DIR = 'SoftSensorPlugin/DiscomfortIndexSensor/'
+DiscomfortIndexSensor_env.AppendUnique(CPPPATH = [
+               DISCOMFORTINDEXSENSOR_DIR + 'include',
+               'SSMCore/src/SSMInterface/'
+               ])
+
+DiscomfortIndexSensor_src = [ Glob(DISCOMFORTINDEXSENSOR_DIR + 'src/*.cpp')]
+
+DiscomfortIndexSensor = DiscomfortIndexSensor_env.SharedLibrary('DiscomfortIndexSensor', DiscomfortIndexSensor_src)
+DiscomfortIndexSensor_env.InstallTarget(DiscomfortIndexSensor, 'libDiscomfortIndexSensor')
+
+######################################################################
+# build SSM CORE
+######################################################################
+ssmcore_env = soft_sensor_manager_env.Clone()
+MODEL_DIR = "\"\\\"" + env.get('BUILD_DIR') + "\\\"\""
+LOCATION = "\"\\\"" + env.get('BUILD_DIR') + "HighContextDictionary.xml" + "\\\"\""
+
+ssmcore_env.AppendUnique(CPPDEFINES = ['MODEL_DIRECTORY='+MODEL_DIR, 'HIGH_LOCATION='+LOCATION])
+ssmcore_env.AppendUnique(CPPPATH = [
+               'SSMCore/include/',
+               'SSMCore/src/',
+               'SSMCore/src/Common/'
+               'SSMCore/src/QueryProcessor/'
+               'SSMCore/src/SensorProcessor/'
+               'SSMCore/src/SSMInterface/'
+               ])
+
+import os.path
+
+if target_os != 'android':
+       SSMINTERFACE_PATH = 'SSMCore/src/SSMInterface/'
+       omit_src = ['SSMCore_JNI.cpp']
+       ssminterface_src = [f for f in env.Glob(SSMINTERFACE_PATH + '*.cpp') if os.path.basename(f.path) not in omit_src]
+else :
+       ssminterface_src = Glob(SSMINTERFACE_PATH + '*.cpp')
+
+ssm_core_cpp_src = [
+               'SSMCore/src/SSMResourceServerLauncher.cpp',
+               Glob('SSMCore/src/Common/*.cpp'),
+               Glob('SSMCore/src/QueryProcessor/*.cpp'),
+               Glob('SSMCore/src/SensorProcessor/*.cpp'),
+               ssminterface_src,
+               ]
+
+ssm_core_c_src = [
+               'SSMCore/src/Common/sqlite3.c'
+]
+
+libssmcore = ssmcore_env.StaticLibrary(
+               target = 'SSMCoreUbuntu',
+               source = [ssm_core_cpp_src, ssm_core_c_src]
+               )
+
+ssmcore_env.InstallTarget(libssmcore, 'libSSMCORE')
+
+#######################################################################
+## build SampleApp
+#######################################################################
+#SConscript('SampleApp/SConscript')
diff --git a/service/soft-sensor-manager/SampleApp/SConscript b/service/soft-sensor-manager/SampleApp/SConscript
new file mode 100644 (file)
index 0000000..925f281
--- /dev/null
@@ -0,0 +1,24 @@
+##
+# sampleapp build script
+##
+
+Import('env')
+
+# Add third party libraries
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons')
+sample_env = env.Clone()
+target_os = env.get('TARGET_OS')
+
+######################################################################
+# Build flags
+######################################################################
+
+######################################################################
+# Source files and Targets
+######################################################################
+if target_os == 'linux' :
+       # Build linux sample app
+       SConscript('linux/ClientApp/SConscript')
+       SConscript('linux/THSensorApp/SConscript')
+       SConscript('linux/THSensorApp1/SConscript')
+
diff --git a/service/soft-sensor-manager/SampleApp/linux/ClientApp/SConscript b/service/soft-sensor-manager/SampleApp/linux/ClientApp/SConscript
new file mode 100644 (file)
index 0000000..8ef6e46
--- /dev/null
@@ -0,0 +1,25 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons')
+linux_sample_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include/'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+clientapp = linux_sample_env.Program('ClientApp', 'src/SSMTestApp.cpp')
+Alias("clientapp_sample", clientapp)
+env.AppendTarget('clientapp_sample')
diff --git a/service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript b/service/soft-sensor-manager/SampleApp/linux/THSensorApp/SConscript
new file mode 100644 (file)
index 0000000..accd6ef
--- /dev/null
@@ -0,0 +1,25 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons')
+linux_sample_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include/'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+thsensorapp = linux_sample_env.Program('THSensorApp', 'src/ThingResourceServer.cpp')
+Alias("thsensorapp_sample", thsensorapp)
+env.AppendTarget('thsensorapp_sample')
diff --git a/service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript b/service/soft-sensor-manager/SampleApp/linux/THSensorApp1/SConscript
new file mode 100644 (file)
index 0000000..6b5a0bf
--- /dev/null
@@ -0,0 +1,25 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons')
+linux_sample_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include/'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+thsensorapp1 = linux_sample_env.Program('THSensorApp', 'src/ThingResourceServer1.cpp')
+Alias("thsensorapp1_sample", thsensorapp1)
+env.AppendTarget('thsensorapp1_sample')
diff --git a/service/things-manager/SConscript b/service/things-manager/SConscript
new file mode 100644 (file)
index 0000000..1fb3198
--- /dev/null
@@ -0,0 +1,36 @@
+##
+# things_manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', exports = 'lib_env')
+
+things_manager_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+things_manager_env.AppendUnique(CPPPATH = ['tgm/inc'])
+things_manager_env.AppendUnique(CPPPATH = ['sdk/inc'])
+
+if target_os not in ['windows', 'winrt']:
+       things_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
+       if target_os != 'android':
+               things_manager_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+if target_os == 'android':
+       things_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       things_manager_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+tgmsdk = things_manager_env.StaticLibrary('TGMSDKLibrary', 'sdk/src/TGMClient.cpp')
+
+things_manager_env.InstallTarget(tgmsdk, 'libTGMSDK')
+
+#Go to build sample apps
+SConscript('sampleapp/SConscript')
\ No newline at end of file
diff --git a/service/things-manager/sampleapp/SConscript b/service/things-manager/sampleapp/SConscript
new file mode 100644 (file)
index 0000000..bd1b631
--- /dev/null
@@ -0,0 +1,9 @@
+##
+# sampleapp build script
+##
+
+Import('env')
+
+if env.get('TARGET_OS') == 'linux':
+       # Build linux sample app
+       SConscript('linux/tgmclient/SConscript')
diff --git a/service/things-manager/sampleapp/linux/tgmclient/SConscript b/service/things-manager/sampleapp/linux/tgmclient/SConscript
new file mode 100644 (file)
index 0000000..2c347ff
--- /dev/null
@@ -0,0 +1,28 @@
+##
+# linux sample app  build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+linux_sample_env = lib_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['../../../sdk/inc'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger', 'TGMSDKLibrary'])
+
+if env.get('TARGET_OS') not in ['windows', 'winrt']:
+       linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+tgmclient = linux_sample_env.Program('tgmclient', 'tgmsdkclient.cpp')
+
+Alias("tgmclient_sample", tgmclient)
+env.AppendTarget('tgmclient_sample')
\ No newline at end of file
diff --git a/service/third_party_libs.scons b/service/third_party_libs.scons
new file mode 100644 (file)
index 0000000..e9a140c
--- /dev/null
@@ -0,0 +1,99 @@
+######################################################################
+# This script manages third party libraries
+#
+#Note: The paths must keep consistent with oic-resource
+######################################################################
+import os
+import platform
+
+Import('env', 'lib_env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
+
+if target_os not in ['linux', 'darwin']:
+       utils_path = env.get('OIC_UTILS')
+
+resource_path = src_dir + '/resource'
+
+######################################################################
+# Check dependent packages (Linux only)
+######################################################################
+if target_os == 'linux':
+       if not env.GetOption('help'):
+               if not target_arch == platform.machine():
+                       print '''
+*********************************** Warning ***********************************
+* You are trying cross build, please make sure (%s) version libraries are
+* installed!                                                                 *
+*******************************************************************************
+''' % target_arch
+
+               conf = Configure(lib_env)
+
+               if not conf.CheckLib('boost_thread'):
+                       print 'Did not find boost_thread, exiting!'
+                       Exit(1)
+
+               if not conf.CheckLib('boost_system'):
+                       print 'Did not find boost_system, exiting!'
+                       Exit(1)
+
+               conf.Finish()
+
+######################################################################
+# The 'include' path of external libraries
+######################################################################
+lib_env.AppendUnique(CPPPATH = [
+               resource_path ,
+               resource_path + '/include' ,
+               resource_path + '/oc_logger/include',
+               resource_path + '/csdk/stack/include',
+               resource_path + '/csdk/ocsocket/include',
+               resource_path + '/csdk/ocrandom/include',
+               resource_path + '/csdk/logger/include'
+               ])
+
+######################################################################
+# The 'include' path of third party libraries
+######################################################################
+if target_os == 'android':
+       lib_env.AppendUnique(CPPPATH = [
+                                       utils_path + '/android/boost/include',
+                                       utils_path + '/android/expat/include/expat/',
+                                       utils_path + '/android/openssl/include',
+                               ])
+
+######################################################################
+# The path of third party libraries binary
+######################################################################
+if target_os == 'android':
+       if target_arch == 'armeabi-v7a-hard':
+               target_arch = 'armeabi-v7a'
+
+       if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+               if not env.GetOption('help') and not env.GetOption('clean'):
+                       print '''
+*********************************** Warning ***********************************
+* current only x86, armeabi, armeabi-v7a libraries are provided!              *
+*******************************************************************************
+'''
+       else:
+               lib_env.AppendUnique(LIBPATH = [
+                                                               utils_path + '/android/boost/libs/' + target_arch,
+                                                               utils_path + '/android/expat/lib/' + target_arch,
+                                                               utils_path + '/android/openssl/lib/' + target_arch,
+                                                       ])
+               # Too much boost warning, suppress the warning
+               lib_env.AppendUnique(CCFLAGS = ['-w'])
+
+elif target_os == 'ios':
+       lib_env.AppendUnique(FRAMEWORKPATH = [utils_path + '/ios/frameworks/'])
+       lib_env.AppendUnique(FRAMEWORKS = ['boost', 'expat', 'openssl'])
+elif target_os == 'darwin':
+       lib_env.AppendUnique(CPPPATH = ['/usr/local/include'])
+       lib_env.AppendUnique(LIBPATH = ['/usr/local/lib'])
+
+Import('env')
+lib_env.AppendUnique(LIBPATH = env.get('BUILD_DIR'))