# 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
*.project
# Ignore dependencies folder, which should be generated
-/dependencies
+dependencies/
+
+#ignore Klocwork stuff
+.kwlp/
+.kwps/
+
+#ignore various swap files
+*.swp
--- /dev/null
+== 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
--- /dev/null
+##
+# 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()
--- /dev/null
+##
+# 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
{
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
}
{
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"
}
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 ====================="
--- /dev/null
+##
+# 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')
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> ... *
*******************************************************************************
'''
######################################################################
# 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'
* 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')
*******************************************************************************
'''
+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')
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'])
include $(CLEAR_VARS)
LOCAL_MODULE := flags_probe
-include $(BUILD_SHARE_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
$(info TC_PREFIX=$(TOOLCHAIN_PREFIX))
$(info CFLAGS=$(TARGET_CFLAGS))
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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'])
--- /dev/null
+##
+# 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'])
--- /dev/null
+######################################################################
+# 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'])
+++ /dev/null
-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.
--- /dev/null
+##
+# '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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
+++ /dev/null
-##
-# 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
##
-# 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'))
# Build flags
######################################################################
liboctbstack_env.PrependUnique(CPPPATH = [
- OIC_UTILS + '/tb/cJSON/',
+ '../../extlibs/cjson/',
'ocsocket/include',
'logger/include',
'ocrandom/include',
'../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'])
######################################################################
######################################################################
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')
##
-# 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'))
'../../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'])
######################################################################
'encode.c',
'uri.c',
'coap_list.c',
- 'resource.c',
+# 'resource.c',
'hashkey.c',
'str.c',
'option.c',
'../../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')
--- /dev/null
+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
##
# 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
'../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')
##
# 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
######################################################################
'../../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'])
######################################################################
######################################################################
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
##
-# 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')
--- /dev/null
+##
+# 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
##
-# 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
######################################################################
'../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')
#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
--- /dev/null
+== 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
--- /dev/null
+##
+# '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')
--- /dev/null
+##
+# 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')
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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')
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
--- /dev/null
+##
+#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
--- /dev/null
+#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 (' & " < > &#...;)
+ // - 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])
+ {
+
+ // & '
+ 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;
+
+ // "
+ 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;
+
+ // >
+ case Ch('g'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('>');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // <
+ 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
--- /dev/null
+#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
--- /dev/null
+#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 (< > ' " &)
+ 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
--- /dev/null
+#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
--- /dev/null
+##
+# 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')
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
$(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
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
--- /dev/null
+//******************************************************************
+//
+// 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
--- /dev/null
+//******************************************************************
+//
+// 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
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;
}
}
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;
}
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)
}
}
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());
+ }
}
}
}
else
{
- printPluginList(m_cp_plugins);
+ printPluginList();
}
for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
}
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,
{
printf("thread throw exception\n");
}
+ */
+ m_plugins.push_back(*plugin);
delete(plugin);
}
//printf("plugin size = %d\n",m_plugins.size());
}
//non recursive
-
- flag = installPlugin(path);
-
- flag = loadPluginInfoToManager(path);
-
+ if (installPlugin(path))
+ {
+ flag = loadPluginInfoToManager(path);
+ }
return flag;
}
}
//recursive
-
- flag = findPluginRecursive(path);
-
- flag = loadPluginInfoToManager(path);
-
+ if (findPluginRecursive(path))
+ {
+ flag = loadPluginInfoToManager(path);
+ }
return flag;
}
}
}
-void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+void CpluffAdapter::printPluginList()
{
const char format[] = " %-30s %-15s %-15s %-20s\n";
printf("\n====== Plugins List ======\n");
}
return FALSE;
}
-
+//Auto plugin detection is disabled
+/*
void CpluffAdapter::observePluginPath(void *str)
{
//printf("start observePluginPath\n");
( 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()));
#include <internal.h>
#include "Plugin.h"
+#include "Config.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
*/
const std::string getState(const std::string plugID);
+ /**
+ * print whole plugin info.
+ *
+ * @param cpluff plugins
+ */
+ void printPluginList();
+
/**
*
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;
/**
* @param plugin file path.
* @return void
*/
- void observePluginPath(void *);
+ //void observePluginPath(void *);
/**
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.
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)
{
return FALSE;
}
-
+/*
void FelixAdapter::observePluginPath(void *str)
{
}
-
+*/
const std::string FelixAdapter::getState(const std::string plugID)
{
return "";
#include <internal.h>
#include "Plugin.h"
+#include "Config.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
private:
-
+ Config *config;
typedef std::map<std::string, bool> File_list;
std::vector<Plugin> m_plugins;
boost::thread m_file_detect_thread;
* @param plugin file path.
* @return void
*/
- void observePluginPath(void *);
+ //void observePluginPath(void *);
/**
* Get whole "SO" file list.
return false;
}
}
-
- std::vector<std::string> Plugin::getSupportedType(void)
- {
- return m_supportedType;
- }
-
- void Plugin::addSupportedType(const std::string rscType)
- {
- m_supportedType.push_back(rscType);
- }
}
*/
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;
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
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.
*/
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 *);
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)
{
* @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
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- virtual int startPlugins(Plugin *const plugin);
+ int startPlugins(Plugin *const plugin);
/**
* @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.
--- /dev/null
+##
+# 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')
-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/
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
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
-include config.mk
+include config.mk
.PHONY : really clean install
--- /dev/null
+##
+# 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')
--- /dev/null
+##
+# 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')
-include ../config.mk
-
# Set DESTDIR if it isn't given
DESTDIR?=/
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;
// 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(
// 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;
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
}
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")
{
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")
{
pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
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
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
-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/
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
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
-include config.mk
+include config.mk
.PHONY : really clean install
-include ../config.mk
-
# Set DESTDIR if it isn't given
DESTDIR?=/
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,
// 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(
// 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;
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
}
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")
{
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")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
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
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
+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
--- /dev/null
+##
+#sample-app build script
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os == 'linux':
+ SConscript('linux/SConscript')
--- /dev/null
+##
+#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
+++ /dev/null
-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
--- /dev/null
+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
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
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);
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
rep2.setValue("state", myfan.m_state);
rep2.setValue("power", myfan.m_power);
- curResource->post(rep2, QueryParamsMap(), &onPost2);
+ curFanResource->post(rep2, QueryParamsMap(), &onPost2);
}
else
{
std::cout << "\tpower: " << myfan.m_power << std::endl;
std::cout << "\tname: " << myfan.m_name << std::endl;
- postFanRepresentation(curResource);
+ postFanRepresentation(curFanResource);
}
else
{
std::cout << "\tpower: " << myfan.m_power << std::endl;
std::cout << "\tname: " << myfan.m_name << std::endl;
- putFanRepresentation(curResource);
+ putFanRepresentation(curFanResource);
}
else
{
// Callback to found resources
void foundResourceFan(std::shared_ptr<OCResource> resource)
{
- if (curResource)
+ if (curFanResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
}
if (resourceURI == "/a/fan")
{
- curResource = resource;
+ curFanResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getFanRepresentation(resource);
}
// Callback to found resources
void foundResourceLight(std::shared_ptr<OCResource> resource)
{
- if (curResource)
+ if (curLightResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
}
if (resourceURI == "/a/light")
{
- curResource = resource;
+ curLightResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getLightRepresentation(resource);
}
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);
}
}
while (1)
{
- // client2 related operations
+ std::cout << "Get Light Resource....." << std::endl;
+ sleep(5);
+ getLightRepresentation(curLightResource);
}
}
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;
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
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<pluginManager>
+ <pluginInfo
+ pluginPath="../../../plugins"
+ maxMEM="64M"
+ maxPlugin=""
+ version="1.0"
+ name="pluginmanager">
+ </pluginInfo>
+ <specailpluginInfo>
+ </specailpluginInfo>
+</pluginManager>
--- /dev/null
+##
+# 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')
--- /dev/null
+##
+# 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')
+
--- /dev/null
+##
+# 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')
--- /dev/null
+##
+# 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')
--- /dev/null
+##
+# 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')
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# sampleapp build script
+##
+
+Import('env')
+
+if env.get('TARGET_OS') == 'linux':
+ # Build linux sample app
+ SConscript('linux/tgmclient/SConscript')
--- /dev/null
+##
+# 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
--- /dev/null
+######################################################################
+# 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'))