publish meeting summary and scons-RfC (sync with master)

This commit is contained in:
Fischlurch 2012-01-12 20:53:13 +01:00
commit 956592dc0c
556 changed files with 10435 additions and 5626 deletions

2
.gitignore vendored
View file

@ -7,6 +7,8 @@
*.gch
,valgrind.log*
*.pyc
/.sconf_temp
/.settings
optcache
Makefile.in
build/*

View file

@ -1,6 +1,6 @@
# -*- python -*-
##
## SConstruct - SCons based build-sytem for Lumiera
## SConstruct - SCons based build-system for Lumiera
##
# Copyright (C) Lumiera.org
@ -23,424 +23,62 @@
# NOTE: scons -h for help.
# This script /defines/ the components and how they fit together.
# SCons will derive dependencies and the necessary build steps.
# Read more about the SCons build system at: http://www.scons.org
# Basically, this script just /defines/ the components and how they
# fit together. SCons will derive the necessary build steps.
#-----------------------------------Configuration
TARGDIR = 'target'
VERSION = '0.pre.01'
TOOLDIR = './admin/scons' # SCons plugins
SCRIPTDIR = './admin'
OPTCACHE = 'optcache'
CUSTOPTFILE = 'custom-options'
# these are accessible via env.path.xxxx
srcIcon = 'icons'
srcConf = 'data/config'
buildExe = '#$TARGDIR'
buildLib = '#$TARGDIR/modules'
buildPlug = '#$TARGDIR/modules'
buildIcon = '#$TARGDIR/gui/icons'
buildUIRes = '#$TARGDIR/'
buildConf = '#$TARGDIR/config'
installExe = '#$DESTDIR/lib/lumiera'
installLib = '#$DESTDIR/lib/lumiera/modules'
installPlug = '#$DESTDIR/lib/lumiera/modules'
installIcon = '#$DESTDIR/share/lumiera/icons'
installUIRes = '#$DESTDIR/share/lumiera/'
installConf = '#$DESTDIR/lib/lumiera/config'
localDefinitions = locals()
#-----------------------------------Configuration
import os
# SCons plugins and extension modules
#------------------------------------------------
import sys
sys.path.append('./admin/scons')
#------------------------------------------------
sys.path.append(TOOLDIR)
sys.path.append(SCRIPTDIR)
import Setup
import Options
import Platform
from Buildhelper import *
from LumieraEnvironment import *
#####################################################################
def setupBasicEnvironment(localDefinitions):
""" define cmdline options, build type decisions
"""
EnsurePythonVersion(2,4)
EnsureSConsVersion(1,0)
Decider('MD5-timestamp') # detect changed files by timestamp, then do a MD5
vars = defineCmdlineVariables()
env = LumieraEnvironment(variables=vars
,toolpath = [TOOLDIR]
,pathConfig = extract_localPathDefs(localDefinitions) # e.g. buildExe -> env.path.buildExe
,TARGDIR = TARGDIR
,DESTDIR = '$INSTALLDIR/$PREFIX'
,VERSION = VERSION
)
handleVerboseMessages(env)
env.Append ( CCCOM=' -std=gnu99')
env.Append ( SHCCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honour CFLAGS, only CCFLAGS
env.Replace( CPPPATH =["#src"] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['LUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall -Wextra '
, CFLAGS='-std=gnu99'
)
handleNoBugSwitches(env)
env.Append(CPPDEFINES = '_GNU_SOURCE')
appendCppDefine(env,'DEBUG','DEBUG', 'NDEBUG')
# appendCppDefine(env,'OPENGL','USE_OPENGL')
appendVal(env,'ARCHFLAGS','CCFLAGS') # for both C and C++
appendVal(env,'OPTIMIZE', 'CCFLAGS', val=' -O3')
appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb')
# setup search path for Lumiera plugins
appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:ORIGIN/modules\\"'
,'LUMIERA_PLUGIN_PATH=\\"ORIGIN/modules\\"')
appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR/:.\\"'
,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera/:.\\"')
prepareOptionsHelp(vars,env)
vars.Save(OPTCACHE, env)
return env
def appendCppDefine(env,var,cppVar, elseVal=''):
if env[var]:
env.Append(CPPDEFINES = env.subst(cppVar) )
elif elseVal:
env.Append(CPPDEFINES = env.subst(elseVal))
def appendVal(env,var,targetVar,val=None):
if env[var]:
env.Append( **{targetVar: env.subst(val) or env[var]})
def handleNoBugSwitches(env):
""" set the build level for NoBug.
Release builds imply no DEBUG
whereas ALPHA and BETA require DEBUG
"""
level = env['BUILDLEVEL']
if level in ['ALPHA', 'BETA']:
if not env['DEBUG']:
print 'Warning: NoBug ALPHA or BETA builds requires DEBUG=yes, switching DEBUG on!'
env.Replace( DEBUG = 1 )
env.Append(CPPDEFINES = 'EBUG_'+level)
elif level == 'RELEASE':
env.Replace( DEBUG = 0 )
def handleVerboseMessages(env):
""" toggle verbose build output """
if not env['VERBOSE']:
# SetOption('silent', True)
env['CCCOMSTR'] = env['SHCCCOMSTR'] = " Compiling $SOURCE"
env['CXXCOMSTR'] = env['SHCXXCOMSTR'] = " Compiling++ $SOURCE"
env['LINKCOMSTR'] = " Linking --> $TARGET"
env['LDMODULECOMSTR'] = " creating module [ $TARGET ]"
def defineCmdlineVariables():
""" several toggles and configuration variables can be set on the commandline,
current settings will be persisted in a options cache file.
you may define custom variable settings in a separate file.
Commandline will override both.
"""
vars = Variables([OPTCACHE, CUSTOPTFILE])
vars.AddVariables(
('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','')
,('CC', 'Set the C compiler to use.', 'gcc')
,('CXX', 'Set the C++ compiler to use.', 'g++')
,PathVariable('CCACHE', 'Integrate with CCache', '', PathVariable.PathAccept)
,PathVariable('DISTCC', 'Invoke C/C++ compiler commands through DistCC', '', PathVariable.PathAccept)
,EnumVariable('BUILDLEVEL', 'NoBug build level for debugging', 'ALPHA', allowed_values=('ALPHA', 'BETA', 'RELEASE'))
,BoolVariable('DEBUG', 'Build with debugging information and no optimisations', False)
,BoolVariable('OPTIMIZE', 'Build with strong optimisation (-O3)', False)
,BoolVariable('VALGRIND', 'Run Testsuite under valgrind control', True)
,BoolVariable('VERBOSE', 'Print full build commands', False)
,('TESTSUITES', 'Run only Testsuites matching the given pattern', '')
# ,BoolVariable('OPENGL', 'Include support for OpenGL preview rendering', False)
# ,EnumVariable('DIST_TARGET', 'Build target architecture', 'auto',
# allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2)
,PathVariable('PREFIX', 'Installation dir prefix', 'usr/local', PathVariable.PathAccept)
,PathVariable('INSTALLDIR', 'Root output directory for install. Final installation will happen in INSTALLDIR/PREFIX/... ', '/', PathVariable.PathIsDir)
,PathVariable('PKGLIBDIR', 'Installation dir for plugins, defaults to PREFIX/lib/lumiera/modules', '',PathVariable.PathAccept)
,PathVariable('PKGDATADIR', 'Installation dir for default config, usually PREFIX/share/lumiera', '',PathVariable.PathAccept)
)
return vars
def prepareOptionsHelp(vars,env):
prelude = """
USAGE: scons [-c] [OPTS] [key=val [key=val...]] [TARGETS]
Build and optionally install Lumiera.
Without specifying any target, just the (re)build target will run.
Add -c to the commandline to clean up anything a given target would produce
Special Targets:
build : just compile and link
testcode: additionally compile the Testsuite
check : build and run the Testsuite
doc : generate documentation (Doxygen)
all : build and testcode and doc
install : install created artifacts at PREFIX
Configuration Options:
"""
Help(prelude + vars.GenerateHelpText(env))
def configurePlatform(env):
""" locate required libs.
setup platform specific options.
Abort build in case of failure.
"""
conf = env.Configure()
# run all configuration checks in the given env
# Perform checks for prerequisites --------------------------------------------
problems = []
if not conf.TryAction('pkg-config --version > $TARGET')[0]:
problems.append('We need pkg-config for including library configurations, exiting.')
if not conf.CheckLibWithHeader('m', 'math.h','C'):
problems.append('Did not find math.h / libm.')
if not conf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'):
problems.append('Functions for runtime dynamic loading not available.')
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'C'):
problems.append('Did not find the pthread lib or pthread.h.')
else:
conf.env.Append(CPPFLAGS = ' -DHAVE_PTHREAD')
conf.env.Append(CCFLAGS = ' -pthread')
if conf.CheckCHeader('execinfo.h'):
conf.env.Append(CPPFLAGS = ' -DHAVE_EXECINFO_H')
if conf.CheckCHeader('valgrind/valgrind.h'):
conf.env.Append(CPPFLAGS = ' -DHAVE_VALGRIND_H')
else:
print 'Valgrind not found. The use of Valgrind is optional; building without.'
if not conf.CheckPkgConfig('nobugmt', 201006.1):
problems.append('Did not find NoBug [http://www.lumiera.org/nobug_manual.html].')
else:
conf.env.mergeConf('nobugmt')
if not conf.CheckCXXHeader('tr1/memory'):
problems.append('We rely on the std::tr1 standard C++ extension for shared_ptr.')
if not conf.CheckCXXHeader('boost/config.hpp'):
problems.append('We need the C++ boost-libraries.')
else:
if not conf.CheckCXXHeader('boost/scoped_ptr.hpp'):
problems.append('We need boost::scoped_ptr (scoped_ptr.hpp).')
if not conf.CheckCXXHeader('boost/format.hpp'):
problems.append('We need boost::format (header).')
if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'):
problems.append('We need boost::program_options (including binary lib for linking).')
if not conf.CheckLibWithHeader('boost_system-mt','boost/system/error_code.hpp','C++'):
problems.append('We need the boost::system support library (including binary lib).')
if not conf.CheckLibWithHeader('boost_filesystem-mt','boost/filesystem.hpp','C++'):
problems.append('We need the boost::filesystem lib (including binary lib for linking).')
if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'):
problems.append('We need the boost regular expression lib (incl. binary lib for linking).')
if conf.CheckLib(symbol='clock_gettime'):
print 'Using function clock_gettime() as defined in the C-lib...'
else:
if not conf.CheckLib(symbol='clock_gettime', library='rt'):
problems.append('No library known to provide the clock_gettime() function.')
if not conf.CheckPkgConfig('gavl', 1.0):
problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].')
else:
conf.env.mergeConf('gavl')
if not conf.CheckPkgConfig('gtkmm-2.4', 2.8):
problems.append('Unable to configure GTK--')
if not conf.CheckPkgConfig('glibmm-2.4', '2.16'):
problems.append('Unable to configure Lib glib--')
if not conf.CheckPkgConfig('gthread-2.0', '2.12.4'):
problems.append('Need gthread support lib for glib-- based thread handling.')
if not conf.CheckPkgConfig('cairomm-1.0', 0.6):
problems.append('Unable to configure Cairo--')
verGDL = '2.27.1'
if not conf.CheckPkgConfig('gdl-1.0', verGDL, alias='gdl'):
print 'No sufficiently recent (>=%s) version of GDL found. Maybe use custom package gdl-lum?' % verGDL
if not conf.CheckPkgConfig('gdl-lum', verGDL, alias='gdl'):
problems.append('GNOME Docking Library not found. We either need a sufficiently recent GDL '
'version (>=%s), or the custom package "gdl-lum" from Lumiera.org.' % verGDL)
if not conf.CheckPkgConfig('librsvg-2.0', '2.18.1'):
problems.append('Need rsvg Library for rendering icons.')
if not conf.CheckCHeader(['X11/Xutil.h', 'X11/Xlib.h'],'<>'):
problems.append('Xlib.h and Xutil.h required. Please install libx11-dev.')
if not conf.CheckPkgConfig('xv') : problems.append('Need libXv...')
if not conf.CheckPkgConfig('xext'): problems.append('Need libXext.')
# report missing dependencies
if problems:
print "*** unable to build due to the following problems:"
for isue in problems:
print " * %s" % isue
print
print "build aborted."
Exit(1)
print "** Gathered Library Info: %s" % conf.env.libInfo.keys()
# create new env containing the finished configuration
return conf.Finish()
def defineSetupTargets(env, artifacts):
""" build operations and targets to be done /before/ compiling.
things like creating a source tarball or preparing a version header.
"""
pass ## currently none
def defineBuildTargets(env, artifacts):
""" define the source file/dirs comprising each artifact to be built.
setup sub-environments with special build options if necessary.
We use a custom function to declare a whole tree of srcfiles.
"""
# use PCH to speed up building // disabled for now due to strange failures
# env['GCH'] = ( env.PrecompiledHeader('src/pre.hpp')
# + env.PrecompiledHeader('src/pre_a.hpp')
# )
lLib = env.SharedLibrary('lumiera', srcSubtree(env,'src/lib'), install=True)
lApp = env.SharedLibrary('lumieracommon', srcSubtree(env,'src/common'), install=True, LIBS=lLib)
lBack = env.SharedLibrary('lumierabackend', srcSubtree(env,'src/backend'),install=True)
lProc = env.SharedLibrary('lumieraproc', srcSubtree(env,'src/proc'), install=True)
core = lLib+lApp+lBack+lProc
artifacts['corelib'] = core
artifacts['support'] = lLib
artifacts['config'] = ( env.ConfigData(env.path.srcConf+'setup.ini', targetDir='$ORIGIN')
+ env.ConfigData(env.path.srcConf+'dummy_lumiera.ini')
)
artifacts['lumiera'] = ( env.Program('lumiera', ['src/lumiera/main.cpp'] + core, install=True)
+ artifacts['config']
)
# building Lumiera Plugins
artifacts['plugins'] = [] # currently none
# render and install Icons
vector_icon_dir = env.path.srcIcon+'svg'
prerendered_icon_dir = env.path.srcIcon+'prerendered'
artifacts['icons'] = ( [env.IconRender(f) for f in scanSubtree(vector_icon_dir, ['*.svg'])]
+ [env.IconResource(f) for f in scanSubtree(prerendered_icon_dir, ['*.png'])]
)
# the Lumiera GTK GUI
envGtk = env.Clone()
envGtk.mergeConf(['gtkmm-2.4','gthread-2.0','cairomm-1.0','gdl','xv','xext','sm'])
envGtk.Append(LIBS=core)
objgui = srcSubtree(envGtk,'src/gui', appendCPP='LUMIERA_PLUGIN')
guimodule = envGtk.LumieraPlugin('gtk_gui', objgui, install=True)
artifacts['gui'] = ( guimodule
+ [env.GuiResource(f) for f in env.Glob('src/gui/*.rc')]
+ artifacts['icons']
)
# call subdir SConscript(s) for independent components
SConscript(dirs=['src/tool'], exports='env artifacts core')
SConscript(dirs=['tests'], exports='env artifacts core')
def definePostBuildTargets(env, artifacts):
""" define further actions after the core build (e.g. Documentaion).
define alias targets to trigger the installing.
"""
build = env.Alias('build', ( artifacts['lumiera']
+ artifacts['plugins']
+ artifacts['tools']
+ artifacts['gui']
))
# additional files to be cleaned when cleaning 'build'
env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ])
env.Clean ('build', [ 'src/pre.gch' ])
doxydoc = artifacts['doxydoc'] = env.Doxygen('doc/devel/Doxyfile')
env.Alias ('doc', doxydoc)
env.Clean ('doc', doxydoc + ['doc/devel/,doxylog','doc/devel/warnings.txt'])
env.Alias ('all', build+artifacts['testsuite']+doxydoc)
env.Default('build')
# SCons default target
def defineInstallTargets(env, artifacts):
""" define additional artifacts to be installed into target locations.
@note: we use customised SCons builders defining install targets
for all executables automatically. see LumieraEnvironment.py
"""
env.SymLink('$DESTDIR/bin/lumiera',env.path.installExe+'lumiera','../lib/lumiera/lumiera')
# env.Install(dir = '$DESTDIR/share/doc/lumiera$VERSION/devel', source=artifacts['doxydoc'])
env.Alias('install', artifacts['gui'])
env.Alias('install', '$DESTDIR')
#####################################################################
env = Setup.defineBuildEnvironment() # dirs & compiler flags
env = Platform.configure(env) # library dependencies
### === MAIN BUILD === ##############################################
# call subdir SConscript(s) to define the actual build targets...
SConscript(dirs=['data','src','src/tool','research','tests','doc'], exports='env')
### === MAIN === ####################################################
# additional files to be cleaned when cleaning 'build'
env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ])
env.Clean ('build', [ 'src/pre.gch' ])
env = setupBasicEnvironment(localDefinitions)
if not (isCleanupOperation(env) or isHelpRequest()):
env = configurePlatform(env)
artifacts = {}
# the various things we build.
# Each entry actually is a SCons-Node list.
# Passing these entries to other builders defines dependencies.
# 'lumiera' : the App
# 'gui' : the GTK UI (plugin)
# 'plugins' : plugin shared lib
# 'tools' : small tool applications (e.g mpegtoc)
defineSetupTargets(env, artifacts)
defineBuildTargets(env, artifacts)
definePostBuildTargets(env, artifacts)
defineInstallTargets(env, artifacts)
### === Alias Targets === ###########################################
# pick up the targets defined by the sub SConscripts
Import('lumiera plugins tools gui testsuite doxydoc')
build = env.Alias('build', lumiera + plugins + tools +gui)
env.Default('build')
# SCons default target
env.Alias ('all', build + testsuite + doxydoc)
env.Alias ('doc', doxydoc)
env.Alias('install', gui)
env.Alias('install', '$DESTDIR')
#####################################################################

View file

@ -1,213 +0,0 @@
#!/usr/bin/python
#
# render_icons.py - Icon rendering utility script
#
# Copyright (C) Lumiera.org
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sys
import getopt
from xml.dom import minidom
import os
import shutil
#svgDir = "svg"
#prerenderedDir = "prerendered"
inkscapePath = "/usr/bin/inkscape"
rsvgPath = "./rsvg-convert"
artworkLayerPrefix = "artwork:"
#
# 2/2011 some notes by Ichthyo
# The purpose of this python script is
# - to parse a SVG
# - to invoke Inkscape to render this SVG into a raster image (icon)
#
# For the actual call into Incscape we rely on an executable 'rsvg-convert',
# which is built during the Lumiera build process.
#
# Judging from the code and the actual SVGs, this seems to work as follows:
# The SVG contains a design to be rendered into raster images of various sizes.
# These sizes are determined by special rectangles, which act as bounding box and
# are placed on a special 'plate' layer, which is a child layer of the main
# 'artwork:' layer. The grid of the SVG is setup such as to result in pixel sizes
# suitable for icon generation. The actual size of the generated icons are then
# parsed from the height and width attributes of the mentioned bounding box
# rectangles.
#
# The parser seems to be rather simplistic; the sizes and positions need to be
# integral numbers. In one instance we had a float number in the y coordinate,
# which resulted in an invalid, zero sized output icon
#
#
def createDirectory( name ):
try:
if os.path.isfile(name):
os.remove(name)
if not os.path.exists(name):
os.mkdir(name)
except:
print 'WARNING: createDirectory("%s") failed. Permission problems?' % name
def copyMergeDirectory( src, dst ):
listing = os.listdir(src)
for file_name in listing:
src_file_path = os.path.join(src, file_name)
dst_file_path = os.path.join(dst, file_name)
shutil.copyfile(src_file_path, dst_file_path)
def getDocumentSize( svg_element ):
width = float(svg_element.getAttribute("width"))
height = float(svg_element.getAttribute("height"))
return [width, height]
def findChildLayerElement( parent_element ):
for node in parent_element.childNodes:
if node.nodeType == minidom.Node.ELEMENT_NODE:
if node.tagName == "g":
if node.getAttribute("inkscape:groupmode") == "layer":
return node
return None
def parsePlateLayer( layer ):
rectangles = []
for node in layer.childNodes:
if node.nodeType == minidom.Node.ELEMENT_NODE:
if node.tagName == "rect":
x = float(node.getAttribute("x"))
y = float(node.getAttribute("y"))
width = float(node.getAttribute("width"))
height = float(node.getAttribute("height"))
rectangles.append([x, y, width, height])
return rectangles
def parseSVG( file_path ):
print "Parsing " + file_path
svgdoc = minidom.parse(file_path)
for root_node in svgdoc.childNodes:
if root_node.nodeType == minidom.Node.ELEMENT_NODE:
if root_node.tagName == "svg":
size = getDocumentSize( root_node )
layer = findChildLayerElement( root_node )
if layer != None:
layer_name = layer.getAttribute("inkscape:label")
if layer_name[:len(artworkLayerPrefix)] == artworkLayerPrefix:
artwork_name = layer_name[len(artworkLayerPrefix):]
plate = findChildLayerElement( layer )
if plate != None:
return artwork_name, size, parsePlateLayer( plate )
return None
def renderSvgInkscape(file_path, out_dir, artwork_name, rectangle, doc_size):
# Calculate the rendering rectangle
x1 = rectangle[0]
y1 = doc_size[1] - rectangle[1] - rectangle[3]
x2 = x1 + rectangle[2]
y2 = y1 + rectangle[3]
# Call Inkscape to do the render
os.spawnlp(os.P_WAIT, inkscapePath, inkscapePath,
file_path,
"-z",
"-a %g:%g:%g:%g" % (x1, y1, x2, y2),
"-w %g" % (rectangle[2]), "-h %g" % (rectangle[3]),
"--export-png=" + os.path.join(out_dir, "%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name)))
def renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size):
# Prepare a Cairo context
width = int(rectangle[2])
height = int(rectangle[3])
if not os.path.exists(rsvgPath):
print "Error: executable %s not found." % rsvgPath
os.spawnlp(os.P_WAIT, rsvgPath, rsvgPath,
"--source-rect=%g:%g:%g:%g" % (rectangle[0], rectangle[1], rectangle[2], rectangle[3]),
"--output=" + os.path.join(out_dir, "%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name)),
file_path)
def renderSvgIcon(file_path, out_dir):
artwork_name, doc_size, rectangles = parseSVG(file_path)
for rectangle in rectangles:
renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size)
def getTargetNames(file_path):
"""get a list of target names to be rendered from the given source SVG
usable to setup the build targets for SCons
"""
artwork_name, _ , rectangles = parseSVG(file_path)
return ["%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name) for rectangle in rectangles ]
#def renderSvgIcons():
# listing = os.listdir(svgDir)
# for file_path in listing:
# [root, extension] = os.path.splitext(file_path)
# if extension.lower() == ".svg":
# renderSvgIcon(os.path.join(svgDir, file_path))
#def copyPrerenderedIcons():
# listing = os.listdir(prerenderedDir)
# for list_item in listing:
# src_dir = os.path.join(prerenderedDir, list_item)
# copyMergeDirectory(src_dir, list_item)
def printHelp():
print "render-icon.py SRCFILE.svg TARGETDIR"
print "An icon rendering utility script for lumiera"
def parseArguments(argv):
optlist, args = getopt.getopt(argv, "")
if len(args) == 2:
return args[0], args[1]
printHelp()
return None, None
def main(argv):
in_path, out_dir = parseArguments(argv)
if not (in_path and out_dir):
print "Missing arguments in_path and out_dir."
sys.exit(1)
if os.path.isfile(out_dir):
print "Unable to use '%s' as output directory, because it\'s a file." % out_dir
sys.exit(1)
if not os.path.isdir(out_dir):
print "Output directory '%s' not found." % out_dir
sys.exit(1)
# Create the icons folders
createDirectory(os.path.join(out_dir, "48x48"))
createDirectory(os.path.join(out_dir, "32x32"))
createDirectory(os.path.join(out_dir, "24x24"))
createDirectory(os.path.join(out_dir, "22x22"))
createDirectory(os.path.join(out_dir, "16x16"))
renderSvgIcon(in_path, out_dir)
# Copy in prerendered icons
#copyPrerenderedIcons()
if __name__=="__main__":
main(sys.argv[1:])

View file

@ -336,7 +336,7 @@ function change_state()
local state="$2"
local nl=$'\n'
local comment=".State -> $state$nl//add reason$nl $(date +%c) $(git config --get user.name) <$(git config --get user.email)>$nl"
local comment=".State -> $state$nl//add reason$nl$nl$(git config --get user.name):: '$(date +%c)' ~<$(git config --get user.email)>~$nl"
edit_state "$name" "$state" "$comment"
edit "$name" -4 "endof_comments"
process_file "$name"

View file

@ -25,11 +25,8 @@ import os
import sys
import glob
import fnmatch
import re
import tarfile
from SCons import Util
from SCons.Action import Action
@ -49,20 +46,11 @@ def isHelpRequest():
def srcSubtree(env,tree,isShared=True,builder=None,appendCPP=None, **args):
""" convenience wrapper: scans the given subtree, which is
relative to the current SConscript, find all source files and
declare them as Static or SharedObjects for compilation
def srcSubtree(tree, **args):
""" convenience wrapper: scan the given subtree, which is relative
to the current SConscript, and find all source files.
"""
if appendCPP: env.Append(CPPDEFINES=appendCPP)
root = env.subst(tree) # expand Construction Vars
if not builder:
if isShared:
builder = lambda f: env.SharedObject(f, **args)
else:
builder = lambda f: env.Object(f, **args)
return [builder(f) for f in scanSubtree(root)]
return list(scanSubtree(tree, **args))
@ -74,12 +62,12 @@ def scanSubtree(roots, patterns=SRCPATTERNS):
(python generator function)
"""
for root in globRootdirs(roots):
for (dir,_,files) in os.walk(root):
if dir.startswith('./'):
dir = dir[2:]
for (d,_,files) in os.walk(root):
if d.startswith('./'):
d = d[2:]
for p in patterns:
for f in fnmatch.filter(files, p):
yield os.path.join(dir,f)
yield os.path.join(d,f)
@ -87,16 +75,16 @@ def globRootdirs(roots):
""" helper: expand shell wildcards and filter the resulting list,
so that it only contains existing directories
"""
filter = lambda f: os.path.isdir(f) and os.path.exists(f)
isDirectory = lambda f: os.path.isdir(f) and os.path.exists(f)
roots = glob.glob(roots)
return (dir for dir in roots if filter(dir) )
return (d for d in roots if isDirectory(d) )
def findSrcTrees(location, patterns=SRCPATTERNS):
""" find possible source tree roots, starting with the given location.
When delving down from the initial location(s), a source tree is defined
as a directory containing source files and possibly further sub directories.
as a directory containidsource files and possibly further sub directories.
After having initially expanded the given location with #globRootdirs, each
directory is examined depth first, until encountering a directory containing
source files, which then yields a result. Especially, this can be used to traverse
@ -104,11 +92,11 @@ def findSrcTrees(location, patterns=SRCPATTERNS):
to be built into packages, plugins, individual tool executables etc.
@return: the relative path names of all source root dirs found (generator function).
"""
for dir in globRootdirs(location):
if isSrcDir(dir,patterns):
yield dir
for directory in globRootdirs(location):
if isSrcDir (directory,patterns):
yield directory
else:
for result in findSrcTrees(str(dir)+'/*'):
for result in findSrcTrees (str(directory)+'/*'):
yield result
@ -118,7 +106,7 @@ def isSrcDir(path, patterns=SRCPATTERNS):
@return: True if it's a directory containing any source file
"""
if not os.path.isdir(path):
return False
return False
else:
for p in patterns:
if glob.glob(path+'/'+p):
@ -133,38 +121,39 @@ def filterNodes(nlist, removeName=None):
if removeName:
predicate = lambda n : not fnmatch.fnmatch(os.path.basename(str(n[0])), removeName)
else:
predicate = lambda n : True;
predicate = lambda n : True
return filter(predicate, nlist)
def getDirname(dir, basePrefix=None):
def getDirname (d, basePrefix=None):
""" extract directory name without leading path,
or without the explicitly given basePrefix
"""
dir = os.path.realpath(dir)
if not os.path.isdir(dir):
dir,_ = os.path.split(dir)
d = os.path.realpath(d)
if not os.path.isdir(d):
d,_ = os.path.split(d)
if basePrefix:
basePrefix = os.path.realpath(basePrefix)
if str(dir).startswith(basePrefix):
name = str(dir)[len(basePrefix):]
name = str(d)
if str(d).startswith(basePrefix):
name = name[len(basePrefix):]
else:
_, name = os.path.split(dir)
_, name = os.path.split(d)
return name
def createPlugins(env, dir, **kw):
def createPlugins(env, directory, **kw):
""" investigate the given source directory to identify all contained source trees.
@return: a list of build nodes defining a plugin for each of these source trees.
"""
return [env.LumieraPlugin( getDirname(tree)
, srcSubtree(env, tree, appendCPP='LUMIERA_PLUGIN')
, srcSubtree(tree)
, **kw
)
for tree in findSrcTrees(dir)
for tree in findSrcTrees(directory)
]

186
admin/scons/IconSvgRenderer.py Executable file
View file

@ -0,0 +1,186 @@
#!/usr/bin/python
#
# IconSvgRenderer.py - Icon rendering utility script
#
# Copyright (C) Lumiera.org
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import os
import sys
import getopt
import shutil
from xml.dom import minidom
rsvgPath = "./rsvg-convert"
artworkLayerPrefix = "artwork:"
#
# 2/2011 some notes by Ichthyo
# The purpose of this python script is
# - to parse a SVG
# - to invoke Inkscape to render this SVG into a raster image (icon)
#
# For the actual Cairo based SVG rendering we rely on an executable 'rsvg-convert',
# which is built during the Lumiera build process.
#
# Judging from the code and the actual SVGs, this seems to work as follows:
# The SVG contains a design to be rendered into raster images of various sizes.
# These sizes are determined by special rectangles, which act as bounding box and
# are placed on a special 'plate' layer, which is a child layer of the main
# 'artwork:' layer. The grid of the SVG is setup such as to result in pixel sizes
# suitable for icon generation. The actual size of the generated icons are then
# parsed from the height and width attributes of the mentioned bounding box
# rectangles.
#
# The parser seems to be rather simplistic; the sizes and positions need to be
# integral numbers. In one instance we had a float number in the y coordinate,
# which resulted in an invalid, zero sized output icon
#
#
def createDirectory (name):
try:
if os.path.isfile (name):
os.remove (name)
if not os.path.exists (name):
os.mkdir (name)
except:
print 'WARNING: createDirectory("%s") failed. Permission problems?' % name
def copyMergeDirectory (src, dst):
listing = os.listdir (src)
for file_name in listing:
src_file_path = os.path.join (src, file_name)
dst_file_path = os.path.join (dst, file_name)
shutil.copyfile (src_file_path, dst_file_path)
def getDocumentSize (svg_element):
width = float(svg_element.getAttribute("width"))
height = float(svg_element.getAttribute("height"))
return [width, height]
def findChildLayerElement (parent_element):
for node in parent_element.childNodes:
if node.nodeType == minidom.Node.ELEMENT_NODE:
if node.tagName == "g":
if node.getAttribute("inkscape:groupmode") == "layer":
return node
return None
def parsePlateLayer (layer):
rectangles = []
for node in layer.childNodes:
if node.nodeType == minidom.Node.ELEMENT_NODE:
if node.tagName == "rect":
x = float(node.getAttribute("x"))
y = float(node.getAttribute("y"))
width = float(node.getAttribute("width"))
height = float(node.getAttribute("height"))
rectangles.append([x, y, width, height])
return rectangles
def parseSVG (file_path):
print "Parsing " + file_path
svgdoc = minidom.parse (file_path)
for root_node in svgdoc.childNodes:
if root_node.nodeType == minidom.Node.ELEMENT_NODE:
if root_node.tagName == "svg":
size = getDocumentSize (root_node)
layer = findChildLayerElement (root_node)
if layer != None:
layer_name = layer.getAttribute ("inkscape:label")
if layer_name[:len(artworkLayerPrefix)] == artworkLayerPrefix:
artwork_name = layer_name[len(artworkLayerPrefix):]
plate = findChildLayerElement(layer)
if plate != None:
return artwork_name, size, parsePlateLayer(plate)
return None
def renderSvgRsvg (file_path, out_dir, artwork_name, rectangle, _doc_size):
# Prepare a Cairo context
width = int(rectangle[2])
height = int(rectangle[3])
if not os.path.exists(rsvgPath):
print "Error: executable %s not found." % rsvgPath
os.spawnlp(os.P_WAIT, rsvgPath, rsvgPath,
"--source-rect=%g:%g:%g:%g" % (rectangle[0], rectangle[1], width, height),
"--output=" + os.path.join(out_dir, "%gx%g/%s.png" % (width, height, artwork_name)),
file_path)
def renderSvgIcon (file_path, out_dir):
artwork_name, doc_size, rectangles = parseSVG (file_path)
for rectangle in rectangles:
renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size)
def getTargetNames (file_path):
"""get a list of target names to be rendered from the given source SVG
usable to setup the build targets for SCons
"""
artwork_name, _ , rectangles = parseSVG (file_path)
return ["%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name) for rectangle in rectangles ]
def printHelp():
print "render-icon.py SRCFILE.svg TARGETDIR"
print "An icon rendering utility script for lumiera"
def parseArguments(argv):
_optlist, args = getopt.getopt(argv, "")
if len(args) == 2:
return args[0], args[1]
printHelp()
return None, None
def main (argv):
in_path, out_dir = parseArguments(argv)
if not (in_path and out_dir):
print "Missing arguments in_path and out_dir."
sys.exit(1)
if os.path.isfile(out_dir):
print "Unable to use '%s' as output directory, because it\'s a file." % out_dir
sys.exit(1)
if not os.path.isdir(out_dir):
print "Output directory '%s' not found." % out_dir
sys.exit(1)
# Create the icons folders
createDirectory(os.path.join(out_dir, "48x48"))
createDirectory(os.path.join(out_dir, "32x32"))
createDirectory(os.path.join(out_dir, "24x24"))
createDirectory(os.path.join(out_dir, "22x22"))
createDirectory(os.path.join(out_dir, "16x16"))
renderSvgIcon (in_path, out_dir)
if __name__=="__main__":
main(sys.argv[1:])

View file

@ -22,11 +22,10 @@
#####################################################################
import os
from os import path
import SCons
import SCons.SConf
from SCons.Action import Action
from SCons.Environment import Environment
from Buildhelper import *
@ -38,9 +37,15 @@ class LumieraEnvironment(Environment):
This allows us to carry structured config data without
using global vars. Idea inspired by Ardour.
"""
def __init__(self, pathConfig, **kw):
Environment.__init__ (self,**kw)
self.path = Record (pathConfig)
def __init__(self, buildSetup, buildVars, **kw):
kw.update(VERSION = buildSetup.VERSION
,TARGDIR = buildSetup.TARGDIR
,DESTDIR = '$INSTALLDIR/$PREFIX'
,toolpath = [buildSetup.TOOLDIR ]
,variables = buildVars
)
Environment.__init__ (self, **kw)
self.path = Record (extract_localPathDefs(buildSetup)) # e.g. buildExe -> env.path.buildExe
self.libInfo = {}
self.Tool("BuilderGCH")
self.Tool("BuilderDoxygen")
@ -49,6 +54,7 @@ class LumieraEnvironment(Environment):
register_LumieraResourceBuilder(self)
register_LumieraCustomBuilders(self)
def Configure (self, *args, **kw):
kw['env'] = self
return apply(LumieraConfigContext, args, kw)
@ -123,7 +129,7 @@ def register_LumieraResourceBuilder(env):
used to generate png from the svg source using librsvg.
"""
import render_icon as renderer # load Joel's python script for invoking the rsvg-convert (SVG render)
import IconSvgRenderer as renderer # load Joel's python script for invoking the rsvg-convert (SVG render)
renderer.rsvgPath = env.subst("$TARGDIR/rsvg-convert")
def invokeRenderer(target, source, env):
@ -151,43 +157,44 @@ def register_LumieraResourceBuilder(env):
return (generateTargets, source)
def IconResource(env, source):
"""Copy icon pixmap to corresponding icon dir. """
subdir = getDirname(str(source))
toBuild = env.path.buildIcon+subdir
toInstall = env.path.installIcon+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
"""Copy icon pixmap to corresponding icon dir. """
subdir = getDirname(str(source))
toBuild = env.path.buildIcon+subdir
toInstall = env.path.installIcon+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
def GuiResource(env, source):
subdir = getDirname(str(source))
toBuild = env.path.buildUIRes+subdir
toInstall = env.path.installUIRes+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
subdir = getDirname(str(source))
toBuild = env.path.buildUIRes+subdir
toInstall = env.path.installUIRes+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
def ConfigData(env, source, targetDir=None):
""" install (copy) configuration- and metadata.
target dir is either the install location configured (in SConstruct),
or an explicitly given absolute or relative path segment, which might refer
to the location of the executable through the $ORIGIN token
"""
subdir = getDirname(str(source), env.path.srcConf) # removes source location path prefix
if targetDir:
if path.isabs(targetDir):
toBuild = toInstall = path.join(targetDir,subdir)
else:
if targetDir.startswith('$ORIGIN'):
targetDir = targetDir[len('$ORIGIN'):]
toBuild = path.join(env.path.buildExe, targetDir, subdir)
toInstall = path.join(env.path.installExe, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf, targetDir, subdir)
toInstall = path.join(env.path.installConf, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf,subdir)
toInstall = path.join(env.path.installConf,subdir)
env.Install (toInstall, source)
return env.Install(toBuild, source)
def ConfigData(env, prefix, source, targetDir=None):
""" install (copy) configuration- and metadata.
target dir is either the install location configured (in SConstruct),
or an explicitly given absolute or relative path segment, which might refer
to the location of the executable through the $ORIGIN token
"""
source = path.join(prefix,str(source))
subdir = getDirname(source, prefix) # removes source location path prefix
if targetDir:
if path.isabs(targetDir):
toBuild = toInstall = path.join(targetDir,subdir)
else:
if targetDir.startswith('$ORIGIN'):
targetDir = targetDir[len('$ORIGIN'):]
toBuild = path.join(env.path.buildExe, targetDir, subdir)
toInstall = path.join(env.path.installExe, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf, targetDir, subdir)
toInstall = path.join(env.path.installConf, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf,subdir)
toInstall = path.join(env.path.installConf,subdir)
env.Install (toInstall, source)
return env.Install(toBuild, source)
buildIcon = env.Builder( action = Action(invokeRenderer, "rendering Icon: $SOURCE --> $TARGETS")
@ -205,8 +212,8 @@ def register_LumieraResourceBuilder(env):
class WrappedStandardExeBuilder(SCons.Util.Proxy):
""" Helper to add customisations and default configurations to SCons standard builders.
The original builder object is wrapped and most calls are simply forwarded to this
wrapped object by Python magic. But some calls are intecepted in order to inject
suitalbe default configuration based on the project setup.
wrapped object by Python magic. But some calls are intercepted in order to inject
suitable default configuration based on the project setup.
"""
def __init__(self, originalBuilder):
@ -291,7 +298,7 @@ class LumieraModuleBuilder(WrappedStandardExeBuilder):
explicit spec, falling back on the lib filename
"""
if 'soname' in kw:
soname = self.subst(kw['soname']) # explicitely defined by user
soname = self.subst(kw['soname']) # explicitly defined by user
else: # else: use the library filename as DT_SONAME
if SCons.Util.is_String(target):
pathname = target.strip()
@ -331,7 +338,7 @@ class LumieraPluginBuilder(LumieraModuleBuilder):
def register_LumieraCustomBuilders (lumiEnv):
""" install the customised builder versions tightly integrated with our buildsystem.
""" install the customised builder versions tightly integrated with our build system.
Especially, these builders automatically add the build and installation locations
and set the RPATH and SONAME in a way to allow a relocatable Lumiera directory structure
"""
@ -362,7 +369,7 @@ def register_LumieraCustomBuilders (lumiEnv):
action = Action(makeLink, "Install link: $TARGET -> "+srcSpec)
env.Command (target,source, action)
# adding SymLink direclty as method on the environment object
# adding SymLink directly as method on the environment object
# Probably that should better be a real builder, but I couldn't figure out
# how to get the linktext through literally, which is necessary for relative links.
# Judging from the sourcecode of SCons.Builder.BuilderBase, there seems to be no way

81
admin/scons/Options.py Normal file
View file

@ -0,0 +1,81 @@
# -*- python -*-
##
## Options.py - SCons build: command line options and help
##
# Copyright (C) Lumiera.org
# 2012, Hermann Vosseler <Ichthyostega@web.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#####################################################################
from SCons.Script import PathVariable, EnumVariable, BoolVariable, Help
def defineCmdlineVariables(buildVars):
""" several toggles and configuration variables can be set on the commandline,
current settings will be persisted in a options cache file.
you may define custom variable settings in a separate file.
Commandline will override both.
"""
buildVars.AddVariables(
('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','')
,('CC', 'Set the C compiler to use.', 'gcc')
,('CXX', 'Set the C++ compiler to use.', 'g++')
,PathVariable('CCACHE', 'Integrate with CCache', '', PathVariable.PathAccept)
,PathVariable('DISTCC', 'Invoke C/C++ compiler commands through DistCC', '', PathVariable.PathAccept)
,EnumVariable('BUILDLEVEL', 'NoBug build level for debugging', 'ALPHA', allowed_values=('ALPHA', 'BETA', 'RELEASE'))
,BoolVariable('DEBUG', 'Build with debugging information and no optimisations', False)
,BoolVariable('OPTIMIZE', 'Build with strong optimisation (-O3)', False)
,BoolVariable('VALGRIND', 'Run Testsuite under valgrind control', True)
,BoolVariable('VERBOSE', 'Print full build commands', False)
,('TESTSUITES', 'Run only Testsuites matching the given pattern', '')
# ,BoolVariable('OPENGL', 'Include support for OpenGL preview rendering', False)
# ,EnumVariable('DIST_TARGET', 'Build target architecture', 'auto',
# allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2)
,PathVariable('PREFIX', 'Installation dir prefix', 'usr/local', PathVariable.PathAccept)
,PathVariable('INSTALLDIR', 'Root output directory for install. Final installation will happen in INSTALLDIR/PREFIX/... ', '/', PathVariable.PathIsDir)
,PathVariable('PKGLIBDIR', 'Installation dir for plugins, defaults to PREFIX/lib/lumiera/modules', '',PathVariable.PathAccept)
,PathVariable('PKGDATADIR', 'Installation dir for default config, usually PREFIX/share/lumiera', '',PathVariable.PathAccept)
)
def prepareOptionsHelp(buildVars,env):
prelude = """
USAGE: scons [-c] [OPTS] [key=val [key=val...]] [TARGETS]
Build and optionally install Lumiera.
Without specifying any target, just the (re)build target will run.
Add -c to the commandline to clean up anything a given target would produce
Special Targets:
build : just compile and link
research: build experimental code (might fail)
testcode: additionally compile the Testsuite
check : build and run the Testsuite
doc : generate documentation (Doxygen)
all : build and testcode and doc
install : install created artifacts at PREFIX
Configuration Options:
"""
Help(prelude + buildVars.GenerateHelpText(env))

149
admin/scons/Platform.py Normal file
View file

@ -0,0 +1,149 @@
# -*- python -*-
##
## Platform.py - SCons build: platform configuration and library detection
##
# Copyright (C) Lumiera.org
# 2012, Hermann Vosseler <Ichthyostega@web.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#####################################################################
from SCons.Script import Exit
from Buildhelper import isCleanupOperation, isHelpRequest
def configure(env):
""" locate required libraries.
setup platform specific options.
Abort build in case of failure.
"""
if isCleanupOperation(env) or isHelpRequest():
return env # skip configure in these cases
conf = env.Configure()
# run all configuration checks in the build environment defined thus far
# Perform checks for prerequisites --------------------------------------------
problems = []
if not conf.TryAction('pkg-config --version > $TARGET')[0]:
problems.append('We need pkg-config for including library configurations, exiting.')
if not conf.CheckLibWithHeader('m', 'math.h','C'):
problems.append('Did not find math.h / libm.')
if not conf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'):
problems.append('Functions for runtime dynamic loading not available.')
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'C'):
problems.append('Did not find the pthread lib or pthread.h.')
else:
conf.env.Append(CPPFLAGS = ' -DHAVE_PTHREAD')
conf.env.Append(CCFLAGS = ' -pthread')
if conf.CheckCHeader('execinfo.h'):
conf.env.Append(CPPFLAGS = ' -DHAVE_EXECINFO_H')
if conf.CheckCHeader('valgrind/valgrind.h'):
conf.env.Append(CPPFLAGS = ' -DHAVE_VALGRIND_H')
else:
print 'Valgrind not found. The use of Valgrind is optional; building without.'
if not conf.CheckPkgConfig('nobugmt', 201006.1):
problems.append('Did not find NoBug [http://www.lumiera.org/nobug_manual.html].')
else:
conf.env.mergeConf('nobugmt')
if not conf.CheckCXXHeader('tr1/memory'):
problems.append('We rely on the std::tr1 standard C++ extension for shared_ptr.')
if not conf.CheckCXXHeader('boost/config.hpp'):
problems.append('We need the C++ boost-libraries.')
else:
if not conf.CheckCXXHeader('boost/scoped_ptr.hpp'):
problems.append('We need boost::scoped_ptr (scoped_ptr.hpp).')
if not conf.CheckCXXHeader('boost/format.hpp'):
problems.append('We need boost::format (header).')
if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'):
problems.append('We need boost::program_options (including binary lib for linking).')
if not conf.CheckLibWithHeader('boost_system-mt','boost/system/error_code.hpp','C++'):
problems.append('We need the boost::system support library (including binary lib).')
if not conf.CheckLibWithHeader('boost_filesystem-mt','boost/filesystem.hpp','C++'):
problems.append('We need the boost::filesystem lib (including binary lib for linking).')
if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'):
problems.append('We need the boost regular expression lib (incl. binary lib for linking).')
if conf.CheckLib(symbol='clock_gettime'):
print 'Using function clock_gettime() as defined in the C-lib...'
else:
if not conf.CheckLib(symbol='clock_gettime', library='rt'):
problems.append('No library known to provide the clock_gettime() function.')
if not conf.CheckPkgConfig('gavl', 1.0):
problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].')
else:
conf.env.mergeConf('gavl')
if not conf.CheckPkgConfig('alsa', '1.0.23'):
problems.append('Support for ALSA sound output is required')
if not conf.CheckPkgConfig('gtkmm-2.4', 2.8):
problems.append('Unable to configure GTK--')
if not conf.CheckPkgConfig('glibmm-2.4', '2.16'):
problems.append('Unable to configure Lib glib--')
if not conf.CheckPkgConfig('gthread-2.0', '2.12.4'):
problems.append('Need gthread support lib for glib-- based thread handling.')
if not conf.CheckPkgConfig('cairomm-1.0', 0.6):
problems.append('Unable to configure Cairo--')
verGDL = '2.27.1'
if not conf.CheckPkgConfig('gdl-1.0', verGDL, alias='gdl'):
print 'No sufficiently recent (>=%s) version of GDL found. Maybe use custom package gdl-lum?' % verGDL
if not conf.CheckPkgConfig('gdl-lum', verGDL, alias='gdl'):
problems.append('GNOME Docking Library not found. We either need a sufficiently recent GDL '
'version (>=%s), or the custom package "gdl-lum" from Lumiera.org.' % verGDL)
if not conf.CheckPkgConfig('librsvg-2.0', '2.18.1'):
problems.append('Need rsvg Library for rendering icons.')
if not conf.CheckCHeader(['X11/Xutil.h', 'X11/Xlib.h'],'<>'):
problems.append('Xlib.h and Xutil.h required. Please install libx11-dev.')
if not conf.CheckPkgConfig('xv') : problems.append('Need libXv...')
if not conf.CheckPkgConfig('xext'): problems.append('Need libXext.')
# report missing dependencies
if problems:
print "*** unable to build due to the following problems:"
for isue in problems:
print " * %s" % isue
print
print "build aborted."
Exit(1)
print "** Gathered Library Info: %s" % conf.env.libInfo.keys()
# create new env containing the finished configuration
return conf.Finish()

137
admin/scons/Setup.py Normal file
View file

@ -0,0 +1,137 @@
# -*- python -*-
##
## Setup.py - SCons build: setup, definitions and compiler flags
##
# Copyright (C) Lumiera.org
# 2012, Hermann Vosseler <Ichthyostega@web.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#####################################################################
from SCons.Script import EnsurePythonVersion, EnsureSConsVersion, Variables, Decider
from LumieraEnvironment import *
from Buildhelper import *
import Options
#-------------------------------------------------------Configuration
TARGDIR = 'target'
VERSION = '0.pre.01'
TOOLDIR = './admin/scons' # SCons plugins
OPTCACHE = 'optcache'
CUSTOPTFILE = 'custom-options'
# these are accessible via env.path.xxxx
buildExe = '#$TARGDIR'
buildLib = '#$TARGDIR/modules'
buildPlug = '#$TARGDIR/modules'
buildIcon = '#$TARGDIR/gui/icons'
buildUIRes = '#$TARGDIR/'
buildConf = '#$TARGDIR/config'
installExe = '#$DESTDIR/lib/lumiera'
installLib = '#$DESTDIR/lib/lumiera/modules'
installPlug = '#$DESTDIR/lib/lumiera/modules'
installIcon = '#$DESTDIR/share/lumiera/icons'
installUIRes = '#$DESTDIR/share/lumiera/'
installConf = '#$DESTDIR/lib/lumiera/config'
#-------------------------------------------------------Configuration
buildSetup = Record(locals())
def defineBuildEnvironment():
""" create a custom build environment,
define the basic compiler and linker flags,
define locations in source and target tree,
parse the commandline and pick up options
"""
EnsureSConsVersion(1,0)
EnsurePythonVersion(2,4)
Decider('MD5-timestamp') # detect changed files by timestamp, then do a MD5
buildVars = Variables([OPTCACHE, CUSTOPTFILE])
Options.defineCmdlineVariables(buildVars)
env = LumieraEnvironment(buildSetup, buildVars)
env.Replace( CPPPATH =["#src"] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['LUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall -Wextra '
, CFLAGS='-std=gnu99'
)
handleVerboseMessages(env)
handleNoBugSwitches(env)
env.Append(CPPDEFINES = '_GNU_SOURCE')
appendCppDefine(env,'DEBUG','DEBUG', 'NDEBUG')
# appendCppDefine(env,'OPENGL','USE_OPENGL')
appendVal(env,'ARCHFLAGS','CCFLAGS') # for both C and C++
appendVal(env,'OPTIMIZE', 'CCFLAGS', val=' -O3')
appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb')
# setup search path for Lumiera plugins
appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:ORIGIN/modules\\"'
,'LUMIERA_PLUGIN_PATH=\\"ORIGIN/modules\\"')
appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR/:.\\"'
,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera/:.\\"')
Options.prepareOptionsHelp(buildVars,env)
buildVars.Save(OPTCACHE, env)
return env
def appendCppDefine(env,var,cppVar, elseVal=''):
if env[var]:
env.Append(CPPDEFINES = env.subst(cppVar) )
elif elseVal:
env.Append(CPPDEFINES = env.subst(elseVal))
def appendVal(env,var,targetVar,val=None):
if env[var]:
env.Append( **{targetVar: env.subst(val) or env[var]})
def handleNoBugSwitches(env):
""" set the build level for NoBug.
Release builds imply no DEBUG
whereas ALPHA and BETA require DEBUG
"""
level = env['BUILDLEVEL']
if level in ['ALPHA', 'BETA']:
if not env['DEBUG']:
print 'Warning: NoBug ALPHA or BETA builds requires DEBUG=yes, switching DEBUG on!'
env.Replace( DEBUG = 1 )
env.Append(CPPDEFINES = 'EBUG_'+level)
elif level == 'RELEASE':
env.Replace( DEBUG = 0 )
def handleVerboseMessages(env):
""" toggle verbose build output """
if not env['VERBOSE']:
# SetOption('silent', True)
env['CCCOMSTR'] = env['SHCCCOMSTR'] = " Compiling $SOURCE"
env['CXXCOMSTR'] = env['SHCXXCOMSTR'] = " Compiling++ $SOURCE"
env['LINKCOMSTR'] = " Linking --> $TARGET"
env['LDMODULECOMSTR'] = " creating module [ $TARGET ]"

25
data/SConscript Normal file
View file

@ -0,0 +1,25 @@
# -*- python -*-
##
## SConscript - SCons buildscript for Icons and Resources
##
from Buildhelper import scanSubtree
Import('env')
# define Icons to render and install
vector_icon_dir = 'icons/svg'
prerendered_icon_dir = 'icons/prerendered'
icons = ( [env.IconRender(f) for f in scanSubtree(vector_icon_dir, ['*.svg'])]
+ [env.IconResource(f) for f in scanSubtree(prerendered_icon_dir, ['*.png'])]
)
#define Configuration files to install (dir-prefix, name)
config = ( env.ConfigData('config','setup.ini', targetDir='$ORIGIN')
+ env.ConfigData('config','dummy_lumiera.ini')
)
Export('icons config')

26
data/icons/README Normal file
View file

@ -0,0 +1,26 @@
#
# Lumiera Icon Artwork
#
# Copyright (C) Lumiera.org
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
#
# Icon Artwork and similar materials accompanying the Lumiera Application
# is dual-licensed under the GNU General Public License version 2 or above,
# and
# Creative Commons Attribution-ShareAlike 3.0 Unported License
#
#
This directory holds Icons and similar graphics resources for the Lumiera GUI.
- prerendered: Raster image Icons rendered into a selection of sizes
- svg: Scalable Vector Grahpics Icons, to be rendered into suitable sizes
by the build process. Rendering is done with the help of lib Cairo.
The build creates an executable from src/tools/rsvg-convert.c
The invocation of the icon rendering is done with the help of a
Python script IconSvgRenderer.py, which first parses the SVG document
and then invokes rsvg-convert to generate the raster images.

View file

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 540 B

View file

Before

Width:  |  Height:  |  Size: 453 B

After

Width:  |  Height:  |  Size: 453 B

View file

Before

Width:  |  Height:  |  Size: 631 B

After

Width:  |  Height:  |  Size: 631 B

View file

Before

Width:  |  Height:  |  Size: 695 B

After

Width:  |  Height:  |  Size: 695 B

View file

Before

Width:  |  Height:  |  Size: 788 B

After

Width:  |  Height:  |  Size: 788 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View file

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

17
doc/SConscript Normal file
View file

@ -0,0 +1,17 @@
# -*- python -*-
##
## SConscript - SCons buildscript for Documentation
##
from Buildhelper import scanSubtree
Import('env')
doxydoc = env.Doxygen('devel/Doxyfile')
# env.Install(dir = '$DESTDIR/share/doc/lumiera$VERSION/devel', source=documentation)
env.Clean (doxydoc, doxydoc + ['devel/,doxylog','devel/warnings.txt'])
Export('doxydoc')

View file

@ -0,0 +1,37 @@
2012-01-11 Lumiera Developers Meeting
=====================================
:Author: cehteh
:Date: 2012-01-11
Jan 11, 2011 on #lumiera 20:00 - 22:30
__Participants__
* cehteh
* ichthyo
* benn
* raffa
Conclusions
-----------
. _ichthyo_ removed most of the TiddlyWikis, and worked the content into the website
. _cehteh_ reports that Lumiera got another donation (75 €), arrangements with
the FFIS to get access (view) about the donations account are under way. We'll
ask donors then if they want to be published or stay anonymous and will set up
a wiki page listing donations and expenses.
. _ichthyo_ reworked the SCons build, as discussed last time
. _cehteh_ writes a very short RfC, to document that we're using SCons for now.
. possibly no one going to LAC, too far away
. we discussed a link checker / link resolver for the website.
The idea is to have a semi automatic tool, which is used locally when
authoring website content to find cross references.
. _benny_ and _ichthyo_ follow up on the
link:http://libregraphicsmag.com/[Libre Graphics Magazine]'s offer to promote
graphics and media projects and try to get into discussion with them and see
what can be done within our limited time.
. when it comes to have a working example for media file output, we stick to the
mainstream solutions *ffmpeg* and or *gstreamer*, but care not to lock ourselves
into a single solution. Concluded that we do this over plugin interfaces --
it mostly boils down to support ffmpeg -- besides we'll investigate simple
alternatives for basic output.

View file

@ -0,0 +1,88 @@
Make Scons the official build System
====================================
// please don't remove the //word: comments
[grid="all"]
`------------`-----------------------
*State* _Final_
*Date* _Mi 11 Jan 2012 21:45:58 CET_
*Proposed by* Christian Thaeter <ct@pipapo.org>
-------------------------------------
********************************************************************************
.Abstract
_Bless SCons the default build system for Lumiera._
********************************************************************************
Description
-----------
//description: add a detailed description:
So far we using autotools and scons in parallel. Over time the need arose to have one
reliable supported build system. This shall be SCons.
Tasks
~~~~~
// List what needs to be done to implement this Proposal:
// * first step ([green]#✔ done#)
// * second step [,yellow]#WIP#
Nothing to do except for releases SCons _must be working_ and all non functional
build systems will be stripped on the release branches.
////
Discussion
~~~~~~~~~~
Pros
^^^^
// add a fact list/enumeration which make this suitable:
// * foo
// * bar ...
Cons
^^^^
// fact list of the known/considered bad implications:
Alternatives
^^^^^^^^^^^^
//alternatives: explain alternatives and tell why they are not viable:
Rationale
---------
//rationale: Give a concise summary why it should be done *this* way:
////
Conclusion
----------
//conclusion: When approbate (this proposal becomes a Final)
// write some conclusions about its process:
result of discussions and evaluation during the last years
Comments
--------
//comments: append below
.State -> Final
//add reason
Decided on the December 2011 Developer meeting.
Christian Thaeter:: 'Wed 11 Jan 2012 22:28:36 CET' ~<ct@pipapo.org>~
//endof_comments:
''''
Back to link:/documentation/devel/rfc.html[Lumiera Design Process overview]

BIN
doc/devel/uml/fig151685.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,97 +0,0 @@
# Copyright (C) Lumiera.org
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
svgdir = $(top_srcdir)/icons/svg
prerendereddir = $(top_srcdir)/icons/prerendered
icondir = $(top_builddir)
iconcommand = python $(top_srcdir)/admin/render_icon.py
16x16 = $(icondir)/16x16
22x22 = $(icondir)/22x22
24x24 = $(icondir)/24x24
32x32 = $(icondir)/32x32
48x48 = $(icondir)/48x48
16x16pre = $(prerendereddir)/16x16
22x22pre = $(prerendereddir)/22x22
24x24pre = $(prerendereddir)/24x24
32x32pre = $(prerendereddir)/32x32
48x48pre = $(prerendereddir)/48x48
icons = \
$(16x16)/app-icon.png $(22x22)/app-icon.png $(24x24)/app-icon.png $(32x32)/app-icon.png $(48x48)/app-icon.png \
$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \
$(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \
$(16x16)/track-disabled.png \
$(16x16)/track-enabled.png \
$(16x16)/track-locked.png \
$(16x16)/track-unlocked.png \
$(16x16)/panel-assets.png $(22x22)/panel-assets.png $(32x32)/panel-assets.png \
$(16x16)/panel-timeline.png \
$(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png
dist_pkgdata_DATA += $(icons)
all: $(icons)
clean-local:
rm -rf $(16x16) $(22x22) $(24x24) $(32x32) $(48x48)
# ========== SVG Icons ==========
# App Icon
$(16x16)/app-icon.png $(22x22)/app-icon.png $(24x24)/app-icon.png $(32x32)/app-icon.png $(48x48)/app-icon.png : $(svgdir)/app-icon.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
# Timeline Tools
$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png : $(svgdir)/tool-arrow.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
$(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png : $(svgdir)/tool-i-beam.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
# Timeline Tracks
$(16x16)/track-disabled.png : $(svgdir)/track-disabled.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
$(16x16)/track-enabled.png : $(svgdir)/track-enabled.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
$(16x16)/track-locked.png : $(svgdir)/track-locked.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
$(16x16)/track-unlocked.png : $(svgdir)/track-unlocked.svg $(top_builddir)/rsvg-convert
$(iconcommand) $< $(icondir)
# ========== Prerendered Icons ==========
# Panels
$(16x16)/panel-assets.png: $(16x16pre)/panel-assets.png
cp $(16x16pre)/panel-assets.png $(16x16)
$(22x22)/panel-assets.png: $(22x22pre)/panel-assets.png
cp $(22x22pre)/panel-assets.png $(22x22)
$(32x32)/panel-assets.png: $(32x32pre)/panel-assets.png
cp $(32x32pre)/panel-assets.png $(32x32)
$(16x16)/panel-timeline.png: $(16x16pre)/panel-timeline.png
cp $(16x16pre)/panel-timeline.png $(16x16)
$(16x16)/panel-viewer.png: $(16x16pre)/panel-viewer.png
cp $(16x16pre)/panel-viewer.png $(16x16)
$(22x22)/panel-viewer.png: $(22x22pre)/panel-viewer.png
cp $(22x22pre)/panel-viewer.png $(22x22)
$(32x32)/panel-viewer.png: $(32x32pre)/panel-viewer.png
cp $(32x32pre)/panel-viewer.png $(32x32)

1
research/DIR_INFO Normal file
View file

@ -0,0 +1 @@
Experiments and Investigations. Not installed

22
research/SConscript Normal file
View file

@ -0,0 +1,22 @@
# -*- python -*-
##
## SConscript - SCons buildscript for experiments and investigations.
## Things defined here usuall won't be installed
##
Import('env core support_lib')
envR = env.Clone()
# envR.Append(CCFLAGS=' -O3 ')
# build additional test and administrative tools....
experiments = [ envR.Program('try', ['try.cpp'] + support_lib) #### to try out some feature...
]
#
# define Phony targets
# - 'scons research' triggers building of experimental code
#
env.Alias('research', experiments )

165
research/try.cpp Normal file
View file

@ -0,0 +1,165 @@
/* try.cpp - for trying out some language features....
* scons will create the binary bin/try
*
*/
// 8/07 - how to control NOBUG??
// execute with NOBUG_LOG='ttt:TRACE' bin/try
// 1/08 - working out a static initialisation problem for Visitor (Tag creation)
// 1/08 - check 64bit longs
// 4/08 - comparison operators on shared_ptr<Asset>
// 4/08 - conversions on the value_type used for boost::any
// 5/08 - how to guard a downcasting access, so it is compiled in only if the involved types are convertible
// 7/08 - combining partial specialisation and subclasses
// 10/8 - abusing the STL containers to hold noncopyable values
// 6/09 - investigating how to build a mixin template providing an operator bool()
// 12/9 - tracking down a strange "warning: type qualifiers ignored on function return type"
// 1/10 - can we determine at compile time the presence of a certain function (for duck-typing)?
// 4/10 - pretty printing STL containers with python enabled GDB?
// 1/11 - exploring numeric limits
// 1/11 - integer floor and wrap operation(s)
// 1/11 - how to fetch the path of the own executable -- at least under Linux?
// 10/11 - simple demo using a pointer and a struct
// 11/11 - using the boost random number generator(s)
// 12/11 - how to detect if string conversion is possible?
// 1/12 - is partial application of member functions possible?
/** @file try.cpp
** Research: perform a partial application of a member function.
** The result of this partial application should be a functor expecting the remaining arguments.
** The idea was to use this at various library functions expecting a functor or callback, so to
** improve readability of the client code: clients could then just pass a member pointer, without
** the need to use any tr1::bind expression.
**
** \par Costs in code size
** While this turned out to be possible, even without much work, just based on the existing
** templates for partial functor application (function-closure.hpp), the resulting code size
** is rather sobering. Especially in debug mode, quite some overhead is created, which makes
** usage of this convenience feature in general purpose library code rather questionable.
** When compiling with -O3 though, most of the overhead will be removed
**
** The following numbers could be observed:
** \code
** debug / stripped // debug-O3 / stripped
** just using a member pointer: 39013 / 7048 42061 / 7056
** using tr1::bind and function: 90375 / 15416 65415 / 9376
** partial apply, passing functor: 158727 / 23576 97479 / 11296
** partial apply with mem pointer: 119495 / 17816 78031 / 9440
** \endcode
*/
#include "lib/meta/tuple.hpp"
#include "lib/meta/function-closure.hpp"
//#include <tr1/functional>
#include <iostream>
using lib::meta::Types;
using lib::meta::Tuple;
//using std::tr1::placeholders::_1;
//using std::tr1::placeholders::_2;
using std::tr1::function;
using std::tr1::bind;
using std::string;
using std::cout;
using std::endl;
namespace lib {
namespace meta{
namespace func{
template<typename SIG, uint num>
struct _PupS
{
typedef typename _Fun<SIG>::Ret Ret;
typedef typename _Fun<SIG>::Args::List Args;
typedef typename Splice<Args,NullType,num>::Front ArgsFront;
typedef typename Splice<Args,NullType,num>::Back ArgsBack;
typedef typename Types<ArgsFront>::Seq ArgsToClose;
typedef typename Types<ArgsBack>::Seq ArgsRemaining;
typedef typename _Sig<Ret,ArgsRemaining>::Type ReducedSignature;
typedef function<ReducedSignature> Function;
};
template<typename SIG, typename A1>
inline
typename _PupS<SIG,1>::Function
papply (SIG f, A1 a1)
{
typedef typename _PupS<SIG,1>::ArgsToClose ArgsToClose;
typedef Tuple<ArgsToClose> ArgTuple;
ArgTuple val(a1);
return PApply<SIG,ArgsToClose>::bindFront (f, val);
}
template<typename SIG, typename A1, typename A2>
inline
typename _PupS<SIG,2>::Function
papply (SIG f, A1 a1, A2 a2)
{
typedef typename _PupS<SIG,2>::ArgPrefix ArgsToClose;
typedef Tuple<ArgsToClose> ArgTuple;
ArgTuple val(a1,a2);
return PApply<SIG,ArgsToClose>::bindFront (f, val);
}
}}} // namespace lib::meta::func
class Something
{
int i_;
void
privateFun(char a)
{
char aa(a + i_);
cout << "Char-->" << aa <<endl;
}
public:
Something(int ii=0)
: i_(ii)
{ }
typedef function<void(char)> FunP;
FunP
getBinding()
{
// function<void(Something*,char)> memf = bind (&Something::privateFun, _1, _2);
// return lib::meta::func::papply (memf, this);
return lib::meta::func::papply (&Something::privateFun, this);
}
// typedef void (Something::*FunP) (char);
//
// FunP
// getBinding()
// {
// return &Something::privateFun;
// }
};
int
main (int, char**)
{
Something some(23);
Something::FunP fup = some.getBinding();
fup ('a');
cout << "\n.gulp.\n";
return 0;
}

48
src/SConscript Normal file
View file

@ -0,0 +1,48 @@
# -*- python -*-
##
## SConscript - SCons buildscript for the Lumiera Application.
## Definitions how to build the main tree
##
from Buildhelper import srcSubtree
from Buildhelper import scanSubtree
Import('env icons config')
# define the source file/dirs comprising each artifact to be built.
lLib = env.SharedLibrary('lumiera', srcSubtree('lib'), install=True)
lApp = env.SharedLibrary('lumieracommon', srcSubtree('common'), install=True, LIBS=lLib)
lBack = env.SharedLibrary('lumierabackend', srcSubtree('backend'),install=True)
lProc = env.SharedLibrary('lumieraproc', srcSubtree('proc'), install=True)
core = lLib+lApp+lBack+lProc
core_lib = core
support_lib = lLib
lumiera = ( env.Program('lumiera', ['lumiera/main.cpp'] + core, install=True)
+ config
)
# Install the lumiera application:
# symlink the executable into the bin dir
env.SymLink('#$DESTDIR/bin/lumiera',env.path.installExe+'lumiera','../lib/lumiera/lumiera')
# building Lumiera Plugins
plugins = [] # currently none
# the Lumiera GTK GUI
envGtk = env.Clone()
envGtk.mergeConf(['gtkmm-2.4','gthread-2.0','cairomm-1.0','gdl','xv','xext','sm'])
envGtk.Append(LIBS=core)
guimodule = envGtk.LumieraPlugin('gtk_gui', srcSubtree('gui'), install=True)
gui = ( guimodule
+ icons
+ [env.GuiResource(f) for f in env.Glob('gui/*.rc')]
)
Export('lumiera core core_lib support_lib plugins gui')

View file

@ -83,8 +83,8 @@ namespace backend {
/**
* Descriptor holding the global informations,
* needed for further handling this media within Lumiera.
* Descriptor holding the global information record
* required for further handling this kind of media within Lumiera.
*/
struct MediaDesc
{

View file

@ -188,7 +188,7 @@ namespace backend {
/** @note by design there is no possibility to find out
* just based on the thread handle, if the thread is alive.
* just based on the thread handle if some thread is alive.
* We define our own accounting here based on the internals
* of the thread wrapper. This will break down, if you mix
* uses of the C++ wrapper with the raw C functions. */

View file

@ -37,7 +37,7 @@
#include <errno.h>
/**
* @file
* @file threads.c
*
*/
@ -93,17 +93,17 @@ thread_loop (void* thread)
do {
lumiera_threadpool_release_thread(t);
LUMIERA_CONDITION_WAIT (t->state != LUMIERA_THREADSTATE_IDLE);
INFO (threads, "Thread awaken with state %s", lumiera_threadstate_names[t->state]);
TRACE (threads, "Thread awaken with state %s", lumiera_threadstate_names[t->state]);
// NULL function means: no work to do
INFO (threads, "function %p", t->function);
TRACE (threads, "function %p", t->function);
if (t->function)
t->function (t->arguments);
TRACE (threads, "function done");
if (t->kind & LUMIERA_THREAD_JOINABLE)
{
INFO (threads, "Thread zombified");
TRACE (threads, "Thread zombified");
/* move error state to data the other thread will it pick up from there */
t->arguments = (void*)lumiera_error ();
t->state = LUMIERA_THREADSTATE_ZOMBIE;
@ -111,14 +111,14 @@ thread_loop (void* thread)
LUMIERA_CONDITION_SIGNAL;
LUMIERA_CONDITION_WAIT (t->state == LUMIERA_THREADSTATE_JOINED);
INFO (threads, "Thread joined");
TRACE (threads, "Thread joined");
}
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
// SHUTDOWN state
INFO (threads, "Thread Shutdown");
TRACE (threads, "Thread done.");
}
//////////////////////////////////////////////////////////////////////TICKET #844 no error must be pending here, else do app shutdown
return 0;

View file

@ -37,7 +37,7 @@
/**
* @file
* @file threads.h
*
*/

View file

@ -68,7 +68,7 @@
namespace lumiera { ///////TODO: shouldn't that be namespace lib? or proc?
using std::string;
using lumiera::P;
using lib::P;
@ -185,7 +185,7 @@ namespace lumiera { ///////TODO: shouldn't that be namespace lib? or proc?
*/
template<typename TYPES>
class ConfigRules
: public typelist::InstantiateForEach<TYPES, QueryHandler>
: public lib::meta::InstantiateForEach<TYPES, QueryHandler>
{
protected:
ConfigRules () {}
@ -212,13 +212,13 @@ namespace lumiera { ///////TODO: shouldn't that be namespace lib? or proc?
* the list of all concrete types participating in the
* rule based config query system
*/
typedef lumiera::typelist::Types < mobject::session::Track
, asset::Pipe
, const asset::ProcPatt
, asset::Timeline
, asset::Sequence
> ::List
InterfaceTypes;
typedef lib::meta::Types < proc::mobject::session::Track
, proc::asset::Pipe
, const proc::asset::ProcPatt
, proc::asset::Timeline
, proc::asset::Sequence
> ::List
InterfaceTypes;
/**
* user-visible Interface to the ConfigRules subsystem.

View file

@ -248,7 +248,7 @@ lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin),
LumieraPlugin
lumiera_plugin_load (const char* plugin)
{
TRACE (pluginloader_dbg);
TRACE (pluginloader_dbg, "plugin=%s", plugin);
/* dispatch on ext, call the registered function */
const char* ext = strrchr (plugin, '.');
@ -417,6 +417,7 @@ lumiera_plugin_delete_fn (PSplaynode node)
LUMIERA_INTERFACE_CAST(lumieraorg__plugin, 0) self->plugin;
lumiera_interfaceregistry_bulkremove_interfaces (handle->plugin_interfaces ());
}
TRACE (pluginloader_dbg, "unloading plugin/module %s", self->name);
itr->lumiera_plugin_unload_fn (self);
break;
}

View file

@ -34,7 +34,7 @@
LumieraPlugin
lumiera_plugin_load_DYNLIB (const char* name)
{
TRACE (pluginloader_dbg);
TRACE (pluginloader_dbg, "load DYNLIB: %s", name);
REQUIRE (name);
LumieraPlugin self = lumiera_plugin_new (name);
LumieraInterface plugin = NULL;

View file

@ -54,10 +54,13 @@
namespace lumiera {
namespace query {
namespace asset = proc::asset;
using asset::Pipe;
using asset::ProcPatt;
using asset::PProcPatt;
using mobject::Session;
using proc::mobject::Session;
using lib::meta::InstantiateChained;
using util::isnil;
@ -246,10 +249,10 @@ namespace lumiera {
* values for some types of interest for testing and debugging.
*/
class MockConfigRules
: public typelist::InstantiateChained < InterfaceTypes
, LookupPreconfigured // building block used for each of the types
, MockTable // for implementing the base class (interface)
>
: public InstantiateChained < InterfaceTypes
, LookupPreconfigured // building block used for each of the types
, MockTable // for implementing the base class (interface)
>
{
protected:
MockConfigRules (); ///< to be used only by the singleton factory

View file

@ -1,5 +1,5 @@
/*
Notification(Proxy) - public service allowing to push informations into the GUI
Notification(Proxy) - public service allowing to push information into the GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>

View file

@ -1,5 +1,5 @@
/*
NotificationService - public service allowing to push informations into the GUI
NotificationService - public service allowing to push information into the GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>

View file

@ -1,5 +1,5 @@
/*
NOTIFICATION-SERVICE.hpp - public service allowing to push informations into the GUI
NOTIFICATION-SERVICE.hpp - public service allowing to push information into the GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>

View file

@ -189,8 +189,7 @@ TimeCode::set_widget_name(string name)
void
TimeCode::setup_events()
{
// FIXME: change to set_can_focus(true) once Debian squeeze is released
clock_base.set_flags(CAN_FOCUS);
clock_base.set_can_focus(true);
const Gdk::EventMask eventMask =
Gdk::BUTTON_PRESS_MASK|
@ -210,15 +209,14 @@ TimeCode::setup_events()
ms_seconds_ebox.add_events(eventMask);
audio_frames_ebox.add_events(eventMask);
// FIXME: change to set_can_focus(true) once Debian squeeze is released
hours_ebox.set_flags(CAN_FOCUS);
minutes_ebox.set_flags(CAN_FOCUS);
seconds_ebox.set_flags(CAN_FOCUS);
frames_ebox.set_flags(CAN_FOCUS);
audio_frames_ebox.set_flags(CAN_FOCUS);
ms_hours_ebox.set_flags(CAN_FOCUS);
ms_minutes_ebox.set_flags(CAN_FOCUS);
ms_seconds_ebox.set_flags(CAN_FOCUS);
hours_ebox.set_can_focus(true);
minutes_ebox.set_can_focus(true);
seconds_ebox.set_can_focus(true);
frames_ebox.set_can_focus(true);
audio_frames_ebox.set_can_focus(true);
ms_hours_ebox.set_can_focus(true);
ms_minutes_ebox.set_can_focus(true);
ms_seconds_ebox.set_can_focus(true);
hours_ebox.signal_motion_notify_event().connect(bind(mem_fun(
*this, &TimeCode::field_motion_notify_event), SMPTE_Hours));

View file

@ -78,7 +78,7 @@ public:
* from the session / current timeline to be displayed. It doesn't
* make sense to display raw time values here, as each timeline might
* turn out to have a different origin; this is the result of resolving
* a placement, and only the session has the necessary informations...
* a placement, and only the session has the necessary information...
*/
Offset get_time_offset() const;

View file

@ -1,5 +1,5 @@
/*
GUINOTIFICATION-FACADE.h - access point for pushing informations into the GUI
GUINOTIFICATION-FACADE.h - access point for pushing information into the GUI
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -24,7 +24,7 @@
** Major public Interface of the Lumiera GUI. While generally speaking, the GUI
** controls the application and thus acts on its own, it exposes some services
** usable by scripts or the two lower layers. The main purpose of these services
** is to push informations and status updates into the GUI.
** is to push status updates and similar information up into the GUI.
**
** @see notification-service.hpp implementation
** @see gui::GuiFacade

View file

@ -60,7 +60,7 @@ namespace lumiera {
/******************************************************************
* Interface to the Player subsystem of Lumiera (Proc-Layer).
* Interface to the Player subsystem of Lumiera (Proc-Layer).
* Global access point for starting playback and render processes,
* calculating media data by running the render engine.
*
@ -100,7 +100,7 @@ namespace lumiera {
void play(bool); ///< play/pause toggle
void scrub(bool); ///< scrubbing playback
void adjustSpeed(double); ///< playback speed control
void go(lib::time::Time); ///< skip to the given point in time
void go(time::Time); ///< skip to the given point in time
void controlPlayhead (time::Control<time::Time> & ctrl);
void controlDuration (time::Control<time::Duration> & ctrl);
@ -119,13 +119,13 @@ namespace lumiera {
};
typedef lib::IterSource<mobject::ModelPort>::iterator ModelPorts;
typedef lib::IterSource<mobject::OutputDesignation>::iterator Pipes;
typedef lib::IterSource<proc::mobject::ModelPort>::iterator ModelPorts;
typedef lib::IterSource<proc::mobject::OutputDesignation>::iterator Pipes;
typedef proc::play::POutputManager Output;
typedef mobject::session::PClipMO Clip;
typedef mobject::PTrack Track;
typedef asset::PTimeline Timeline;
typedef asset::PViewer Viewer;
typedef proc::mobject::session::PClipMO Clip;
typedef proc::mobject::PTrack Track;
typedef proc::asset::PTimeline Timeline;
typedef proc::asset::PViewer Viewer;
/** core operation: create a new playback process
* outputting to the given viewer/display */

View file

@ -103,6 +103,8 @@
namespace lib {
namespace advice {
namespace error = lumiera::error;
using std::tr1::placeholders::_1;
using std::tr1::unordered_map;
using lib::iter_stl::eachVal;
@ -118,7 +120,6 @@ namespace advice {
using std::cout;
using std::endl;
using namespace lumiera;

View file

@ -21,15 +21,15 @@
*/
/** @file diagnostic-context.hpp
** Facility for collecting diagnostic informations explicitly.
** Facility for collecting diagnostic context information explicitly.
** Unlike a trace logging run, this facility is intended to be fed explicitly with
** diagnostic information describing the currently ongoing operation in a semantic
** high-level manner. The rationale is to pinpoint \em those informations which aren't
** obvious when just looking at a callstack with the debugger. Instances of the class
** DiagnosticContext should be placed explicitly as automatic (stack) variable
** into selected relevant scopes; these "information frames" can be accessed
** from an enclosed scope as a per-thread stack. DiagnosticContext provides
** an controlled environment for adding diagnostic code on demand; typically
** high-level manner. The rationale is to pinpoint \em those pieces of information,
** which aren't obvious when just looking at a callstack with the debugger.
** Instances of the class DiagnosticContext should be placed explicitly as automatic
** (stack) variable into selected relevant scopes; these "information frames" could
** be accessed from an enclosed scope as a per-thread stack. DiagnosticContext
** provides an controlled environment for adding diagnostic code on demand; typically
** to be configured such as to resolve into an empty class for release builds.
**
** As of 2/10, this is an experimental feature in evaluation. To start with,
@ -57,26 +57,23 @@ namespace lib {
#ifdef NOBUG_MODE_ALPHA ////////////////////////TODO don't we need the handle in BETA builds for resource logging?
/**
* Diagnostic data frame to collect specific informations concerning a scope.
* Diagnostic data frame to collect specific information concerning a scope.
* To be placed explicitly as an automatic (stack) variable. Provides a controlled
* environment for hooking up diagnostic code. Within each thread, a stack of
* such information frames concerning nested scopes is maintained automatically.
* It can be accessed via static API.
* @warning never store this into global data structures.
* @note as of 2/10 used for housing the NoBug resource tracker handle
* in conjunction with object monitor based locking
* @see sync.hpp
* @warning relies on thread-local access; never use this within global data structures.
*/
template<typename VAL>
class DiagnosticContext
: boost::noncopyable
{
typedef nobug_resource_user* Handle;
typedef ThreadLocalPtr<DiagnosticContext> ThreadLocalAccess;
typedef std::vector<VAL> ValSequence;
Handle handle_;
const VAL value_;
DiagnosticContext * const prev_;
/** embedded thread local pointer
@ -90,8 +87,8 @@ namespace lib {
public:
DiagnosticContext()
: handle_(0)
DiagnosticContext(VAL const& value_to_log = VAL())
: value_(value_to_log)
, prev_(current().get())
{
current().set (this);
@ -104,9 +101,9 @@ namespace lib {
}
operator Handle* () ///< payload: NoBug resource tracker user handle
operator VAL const&() ///< access the payload by conversion
{
return &handle_;
return value_;
}
/** accessing the innermost diagnostic context created */
@ -116,39 +113,37 @@ namespace lib {
DiagnosticContext* innermost = current().get();
if (!innermost)
throw lumiera::error::Logic ("Accessing Diagnostic context out of order; "
"an instance should have been created in "
"an instance should have been created within "
"an enclosing scope");
return *innermost;
}
};
#else /* not NOBUG_ALPHA */
/**
* Disabled placeholder for the Diagnostic context, not used in release builds.
*/
class DiagnosticContext
: boost::noncopyable
{
public:
operator Handle* () ///< payload: NoBug resource tracker user handle
/** snapshot of the current stack of diagnostic frames
* @return vector with all the payload values currently
* on the thread-local diagnostic stack. Might
* be empty. Values start with frame next to
* the current scope and end with outermost.
* @warning can be inefficient on very large stacks
* @todo benchmark and improve the data structure
* used for the snapshot. Vector is not
* an optimal choice here.
*/
static ValSequence
extractStack()
{
return 0;
}
/** accessing the innermost diagnostic context created */
static DiagnosticContext&
access ()
{
UNIMPLEMENTED ("how to disable DiagnosticContext with minimum overhead");
ValSequence loggedValues;
DiagnosticContext* next = current().get();
while (next)
{
loggedValues.push_back (*next);
next = next->prev_;
}
return loggedValues;
}
};
#endif /* NOBUG_ALPHA? */

View file

@ -66,7 +66,6 @@
namespace lib {
using lumiera::P;
using util::isSameObject;
/**
@ -189,7 +188,7 @@ namespace lib {
}
typedef lumiera::P<TAR> PTarget;
typedef P<TAR> PTarget;
/** factory for creating smart-ptr managed
* TAR instances, automatically registered

View file

@ -125,6 +125,8 @@ namespace lumiera {
LUMIERA_ERROR_DECLARE (LIFECYCLE); ///< Lifecycle assumptions violated
LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch
LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached
LUMIERA_ERROR_DECLARE (CAPACITY); ///< predefined fixed storage capacity
LUMIERA_ERROR_DECLARE (INDEX_BOUNDS); ///< index out of bounds
LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value
LUMIERA_ERROR_DECLARE (UNCONNECTED); ///< missing connection
LUMIERA_ERROR_DECLARE (UNIMPLEMENTED);///< unimplemented feature

View file

@ -82,6 +82,8 @@ namespace lumiera {
LUMIERA_ERROR_DEFINE (LIFECYCLE, "Lifecycle assumptions violated");
LUMIERA_ERROR_DEFINE (WRONG_TYPE, "runtime type mismatch");
LUMIERA_ERROR_DEFINE (ITER_EXHAUST, "end of sequence reached");
LUMIERA_ERROR_DEFINE (CAPACITY, "predefined fixed storage capacity");
LUMIERA_ERROR_DEFINE (INDEX_BOUNDS, "index out of bounds");
LUMIERA_ERROR_DEFINE (BOTTOM_VALUE, "invalid or NIL value");
LUMIERA_ERROR_DEFINE (UNCONNECTED, "missing connection");
LUMIERA_ERROR_DEFINE (UNIMPLEMENTED, "using a feature not yet implemented....");

259
src/lib/format-string.cpp Normal file
View file

@ -0,0 +1,259 @@
/*
FormatString - string template formatting based on boost::format
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file format-string.cpp
** Implementation for printf-style formatting, based on boost::format.
** This file holds the generic implementation of our format frontend,
** which actually just invokes boost::format. The corresponding header
** format-string.hpp provides some template functions and classes,
** either invoking a custom string conversion, or passing primitive
** values down unaltered.
**
** Here, we define explicit specialisations for the frontend to invoke,
** which in turn just pass on the given argument value to the embedded
** boost::format object, which in turn dumps the formatted result
** into an embedded string stream.
**
** To avoid exposing boost::format in the frontend header, we use an
** opaque buffer of appropriate size to piggyback the formatter object.
** @warning unfortunately this requires a hard coded buffer size constant
** in the front-end, which we define there manually, based on
** the current implementation layout found in the boost libraries.
** If Boost eventually changes the implementation, the assertion
** in our constructor will trigger.
**
** @see FormatString_test
**
*/
#include "lib/error.hpp"
#include "lib/format-util.hpp"
#include "lib/format-string.hpp"
#include <boost/static_assert.hpp>
#include <boost/format.hpp>
#include <iostream>
namespace util {
using boost::format;
namespace { // implementation details...
inline boost::format&
accessImpl (char* buffer)
{
return reinterpret_cast<boost::format&> (*buffer);
}
inline void
destroyImpl (char* buffer)
{
accessImpl(buffer).~format();
}
/** in case the formatting of a (primitive) value fails,
* we try to supply an error indicator instead */
void
pushFailsafeReplacement (char* formatter, const char* errorMsg =NULL)
try {
string placeholder("<Error");
if (errorMsg){
placeholder += ": ";
placeholder += errorMsg;
}
placeholder += ">";
accessImpl(formatter) % placeholder;
}
ERROR_LOG_AND_IGNORE (progress, "Supplying placeholder for problematic format parameter")
inline void
suppressInsufficientArgumentErrors (char* formatter)
{
using namespace boost::io;
accessImpl(formatter).exceptions (all_error_bits ^ too_few_args_bit);
}
}//(End) implementation details
/** Build a formatter object based on the given format string.
* The actual implementation is delegated to an boost::format object,
* which is placement-constructed into an opaque buffer embedded into
* this object. Defining the necessary size for this buffer relies
* on a implementation details of boost::format (and might break)
*/
_Fmt::_Fmt (string formatString)
try {
BOOST_STATIC_ASSERT (sizeof(boost::format) <= FORMATTER_SIZE);
new(formatter_) boost::format(formatString);
suppressInsufficientArgumentErrors (formatter_);
}
catch (boost::io::bad_format_string& syntaxError)
{
throw lumiera::error::Fatal (syntaxError
, _Fmt("Format string '%s' is broken") % formatString
, LUMIERA_ERROR_FORMAT_SYNTAX);
}
_Fmt::~_Fmt ()
{
destroyImpl (formatter_);
}
/** @internal access point for the frontend,
* allowing to push a single parameter value down
* into the implementation for the actual formatting.
* Only selected primitive types are handled directly this way,
* while all custom conversions, the handling of pointers and the
* fallback (showing a type string) is done in the frontend.
* @note we need to generate instantiations of this template function
* explicitly for all basic types to be supported for direct handling,
* otherwise we'll get linker errors. Lumiera uses the ``inclusion model''
* for template instantiation, which means there is no compiler magic
* involved and a template function either needs to be \em defined in
* a header or explicitly instantiated in some translation unit.
*/
template<typename VAL>
void
_Fmt::format (const VAL val, Implementation& formatter)
try {
accessImpl(formatter) % val;
}
catch (boost::io::too_many_args& argErr)
{
WARN (progress, "Format: excess argument '%s' of type %s ignored."
, cStr(str(val))
, cStr(tyStr(val)));
}
catch (std::exception& failure)
{
_clear_errorflag();
WARN (progress, "Format: Parameter '%s' causes problems: %s"
, cStr(str(val))
, failure.what());
pushFailsafeReplacement (formatter, failure.what());
}
catch (...)
{
_clear_errorflag();
WARN (progress, "Format: Unexpected problems accepting format parameter '%s'", cStr(str(val)));
pushFailsafeReplacement (formatter);
}
/* ===== explicitly supported =================== */
template void _Fmt::format (const char, Implementation&);
template void _Fmt::format (const uchar, Implementation&);
template void _Fmt::format (const int, Implementation&);
template void _Fmt::format (const uint, Implementation&);
template void _Fmt::format (const short, Implementation&);
template void _Fmt::format (const ushort, Implementation&);
template void _Fmt::format (const int64_t, Implementation&);
template void _Fmt::format (const uint64_t,Implementation&);
template void _Fmt::format (const float, Implementation&);
template void _Fmt::format (const double, Implementation&);
template void _Fmt::format (const string, Implementation&);
template void _Fmt::format (const void *, Implementation&);
template void _Fmt::format (const char *, Implementation&);
/** @remarks usually the _Fmt helper is used inline
* at places where a string is expected. The '%' operator
* used to fed parameters has a higher precedence than the
* assignment or comparison operators, ensuring that all parameters
* are evaluated and formatted prior to receiving the formatted result
*/
_Fmt::operator string() const
try {
return accessImpl(formatter_).str();
}
catch (std::exception& failure)
{
_clear_errorflag();
WARN (progress, "Format: Failure to receive formatted result: %s", failure.what());
return "<formatting failure>";
}
catch (...)
{
_clear_errorflag();
WARN (progress, "Format: Unexpected problems while formatting output.");
return "<unexpected problems>";
}
/** send the formatted buffer directly to the output stream.
* @note this is more efficient than creating a string and outputting that,
* because boost::format internally uses a string-stream to generate
* the formatted representation, relying on the C++ output framework
*/
std::ostream&
operator<< (std::ostream& os, _Fmt const& fmt)
try {
return os << accessImpl(fmt.formatter_);
}
catch(std::exception& failure)
{
_clear_errorflag();
WARN (progress, "Format: Failure when outputting formatted result: %s", failure.what());
return os << "<formatting failure>";
}
catch(...)
{
_clear_errorflag();
WARN (progress, "Format: Unexpected problems while producing formatted output.");
return os << "<unexpected problems>";
}
LUMIERA_ERROR_DEFINE (FORMAT_SYNTAX, "Syntax error in format string for boost::format");
} // namespace util

421
src/lib/format-string.hpp Normal file
View file

@ -0,0 +1,421 @@
/*
FORMAT-STRING.hpp - string template formatting based on boost::format
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file format-string.hpp
** Front-end for printf-style string template interpolation.
** While the actual implementation just delegates to boost::format, this front-end
** hides the direct dependency, additionally invokes a custom toSting conversion
** whenever possible, provides a direct automatic conversion to the formatted result
** to string and catches any exceptions.
**
** This front-end is used pervasively for diagnostics and logging, so keeping down the
** compilation and object size cost and reliably handling any error is more important
** than the (small) performance gain of directly invoking boost::format (which is
** known to be 10 times slower than printf anyway).
**
** \par Implementation notes
** To perform the formatting, usually a \c _Fmt object is created as an anonymous
** temporary, but it may as well be stored into a variable. Copying is not permitted.
** Individual parameters are then fed for formatting through the \c '%' operator.
** Each instance of _Fmt uses its own embedded boost::format object for implementation,
** but this formatter resides within an opaque buffer embedded into the frontend object.
** The rationale for this admittedly tricky approach is to confine any usage of boost::format
** to the implementation translation unit (format-string.cpp).
**
** The implementation is invoked by the frontend through a set of explicit specialisations
** for all the relevant \em primitive data types. For custom types, we prefer to invoke
** operator string() if possible, which is determined by a simple metaprogramming test,
** which is defined in lib/meta/util.pp, without relying on boost. As a fallback, for
** all other types without built-in or custom string conversion, we use the mangled
** type string produced by RTTI.
**
** The compile time and object size overhead incurred by using this header was verified
** to be negligible, in comparison to using boost::format. When compiling a demo example
** on x86_64, the following executable sizes could be observed:
**
** debug stripped
** just string concatenation ............... 42k 8.8k
** including and using format-string.hpp ... 50k 9.4k
** including and using boost::format ....... 420k 140k
**
** In addition, we need to take the implementation translation unit (format-string.cpp)
** into account, which is required once per application and contains the specialisations
** for all primitive types. In the test showed above, the corresponding object file
** had a size of 1300k (with debug information) resp. 290k (stripped).
**
** \par Usage
** The syntax of the format string is defined by boost::format and closely mimics
** the printf formatting directives. The notable difference is that boost::format
** uses the C++ stream output framework, and thus avoiding the perils of printf.
** The individual formatting placeholders just set the corresponding flags on
** an embedded string stream, thus the actual parameter types cause the
** selection of a suitable format, not the definitions within the
** format string.
**
** An illegal format string will raise an error::Fatal. Any other error during usage of
** the formatter is caught, logged and suppressed, inserting an error indicator into
** the formatted result instead
**
** A formatter is usually created as an anonymous object, at places where a string
** is expected. An arbitrary number of parameters is then supplied using the \c '%' operator.
** The result can be obtained
** - by string conversion
** - by feeding into an output stream.
**
** Code example:
** \code
** double total = 22.9499;
** const char * currency = "";
** cout << _Fmt("price %+5.2f %s") % total % currency << endl;
** \endcode
**
** @remarks See the unit-test for extensive usage examples and corner cases.
** The header format-util.hpp provides an alternative string conversion,
** using a bit of boost type traits and lexical_cast, but no boost::format.
** @warning not suited for performance critical code. About 10 times slower than printf.
**
** @see FormatString_test
** @see format-util.hpp
**
*/
#ifndef UTIL_FORMAT_STRING_H
#define UTIL_FORMAT_STRING_H
#include "lib/error.hpp"
#include "lib/meta/util.hpp"
#include "lib/meta/size-trait.hpp"
#include <string>
#include <typeinfo>
#include <boost/noncopyable.hpp>
#include <boost/utility/enable_if.hpp>
namespace std { // forward declaration to avoid including <iostream>
template<typename C>
class char_traits;
template<typename C, class _TRAITS>
class basic_ostream;
typedef basic_ostream<char, char_traits<char> > ostream;
}
namespace util {
using std::string;
using boost::enable_if;
typedef unsigned char uchar;
LUMIERA_ERROR_DECLARE (FORMAT_SYNTAX); ///< "Syntax error in format string for boost::format"
/**
* A front-end for using printf-style formatting.
* Values to be formatted can be supplied through the
* operator%. Custom defined string conversions on objects
* will be used, any errors while invoking the format operation
* will be suppressed. The implementation is based on boost::format,
* but kept opaque to keep code size and compilation times down.
* @see FormatString_test
*/
class _Fmt
: boost::noncopyable
{
/** size of an opaque implementation Buffer */
enum{ FORMATTER_SIZE = lib::meta::SizeTrait::BOOST_FORMAT };
typedef char Implementation[FORMATTER_SIZE];
/** @internal buffer to hold a boost::format */
mutable Implementation formatter_;
template<typename VAL>
static void format (const VAL, Implementation&);
/** helper to prepare parameters for inclusion */
template<typename VAL, class SEL =void>
struct Converter;
public:
~_Fmt ();
_Fmt (string formatString);
operator string() const; ///< get the formatted result
template<typename VAL>
_Fmt&
operator% (VAL const&);
friend std::ostream&
operator<< (std::ostream& os, _Fmt const&);
friend bool operator== (_Fmt const&, _Fmt const&);
friend bool operator== (_Fmt const&, string const&);
friend bool operator== (_Fmt const&, const char * const);
friend bool operator== (string const& , _Fmt const&);
friend bool operator== (const char * const, _Fmt const&);
template<typename X>
friend bool operator != (_Fmt const& fmt, X const& x) { return !(fmt == x); }
template<typename X>
friend bool operator != (X const& x, _Fmt const& fmt) { return !(x == fmt); }
};
/* ===== forwarding into the implementation ====== */
/** The percent operator (\c '%' ) is used do feed parameter values
* to be included into the formatted result, at the positions marked
* by printf-style placeholders within the format string.
*
* \par type specific treatment
* Basic types (numbers, chars, strings) are passed to the implementation
* (= boost::format) literally. For custom types, we try to use a custom
* string conversion, if applicable. Non-NULL pointers will be dereferenced,
* with the exception of C-Strings and \c void*. Any other type gets just
* translated into a type-ID (using the mangled RTTI info). In case of errors
* during the conversion, a string representation of the error is returned
* @param val arbitrary value or pointer to be included into the result
* @warning you need to provide exactly the right number of parameters,
* i.e. matching the number of fields in the format string.
*/
template<typename VAL>
inline _Fmt&
_Fmt::operator% (VAL const& val)
{
Converter<VAL>::dump (val, formatter_);
return *this;
}
namespace { // helpers to pick a suitable specialisation....
/**
* by default we don't allow to
* treat any types directly by boost::format.
* As fallback we rather just produce a type-ID
*/
template<typename X>
struct _allow_call { enum{ value = false };};
/* the following definitions enable some primitive types
* to be handed over to the boost::format implementation */
template<> struct _allow_call<string> { enum{ value = true }; };
template<> struct _allow_call<char> { enum{ value = true }; };
template<> struct _allow_call<uchar> { enum{ value = true }; };
template<> struct _allow_call<int> { enum{ value = true }; };
template<> struct _allow_call<uint> { enum{ value = true }; };
template<> struct _allow_call<short> { enum{ value = true }; };
template<> struct _allow_call<ushort> { enum{ value = true }; };
template<> struct _allow_call<int64_t> { enum{ value = true }; };
template<> struct _allow_call<uint64_t>{ enum{ value = true }; };
template<> struct _allow_call<float> { enum{ value = true }; };
template<> struct _allow_call<double> { enum{ value = true }; };
template<typename X>
struct _shall_format_directly
{
typedef typename lib::meta::UnConst<X>::Type BaseType;
enum{ value = _allow_call<BaseType>::value };
};
template<typename X>
struct _shall_convert_toString
{
enum{ value = ! _shall_format_directly<X>::value
&& lib::meta::can_convertToString<X>::value
};
};
inline void
_clear_errorflag()
{
const char* errID = lumiera_error();
TRACE_IF (errID, progress, "Lumiera errorstate '%s' cleared.", errID);
}
inline string
_log_and_stringify (std::exception const& ex)
{
_clear_errorflag();
WARN (progress, "Error while invoking custom string conversion: %s", ex.what());
try {
return string("<string conversion failed: ")+ex.what()+">";
}
catch(...) { /* secondary errors ignored */ }
return "(formatting failure)";
}
inline string
_log_unknown_exception()
{
const char* errID = lumiera_error();
if (errID)
ERROR (progress, "Unknown error while invoking custom string conversion. Lumiera error flag = %s", errID);
else
ERROR (progress, "Unknown error while invoking custom string conversion. No Lumiera error flag set.");
return "<Unknown error in string conversion>";
}
}//(End) guards/helpers
/* === explicit specialisations to control the kind of conversion === */
/** default/fallback: just indicate the (static) type */
template<typename VAL, class SEL>
struct _Fmt::Converter
{
static void
dump (VAL const&, Implementation& impl)
{
format (string("«")+typeid(VAL).name()+"»", impl);
}
};
template<typename VAL>
struct _Fmt::Converter<VAL*>
{
static void
dump (const VAL *pVal, Implementation& impl)
{
if (pVal)
Converter<VAL>::dump(*pVal, impl);
else
format ("<null>", impl);
}
};
template<>
struct _Fmt::Converter<void *>
{
static void
dump (const void* address, Implementation& impl)
{
format (address, impl);
}
};
template<>
struct _Fmt::Converter<const char *>
{
static void
dump (const char* cString, Implementation& impl)
{
format (cString? cString : "", impl);
}
};
/** some custom types explicitly provide a string representation */
template<typename VAL>
struct _Fmt::Converter<VAL, typename enable_if< _shall_convert_toString<VAL> >::type>
{
static void
dump (VAL const& val, Implementation& impl)
try {
format (string(val), impl);
}
catch(std::exception const& ex)
{
format (_log_and_stringify(ex), impl);
}
catch(...)
{
format (_log_unknown_exception(), impl);
}
};
/** some basic types are directly forwarded down to the implementation;
* @note this requires explicit specialisations in format-string.cpp */
template<typename VAL>
struct _Fmt::Converter<VAL, typename enable_if< _shall_format_directly<VAL> >::type>
{
static void
dump (const VAL val, Implementation& impl)
{
format (val, impl);
}
};
/* === comparison of formatter objects === */
inline bool
operator== (_Fmt const& left, _Fmt const& right)
{
return string(left) == string(right);
}
inline bool
operator== (_Fmt const& fmt, string const& str)
{
return string(fmt) == str;
}
inline bool
operator== (_Fmt const& fmt, const char * const cString)
{
return string(fmt) == string(cString);
}
inline bool
operator== (string const& str, _Fmt const& fmt)
{
return fmt == str;
}
inline bool
operator== (const char * const cString, _Fmt const& fmt)
{
return fmt == cString;
}
} // namespace util
#endif

View file

@ -1,5 +1,5 @@
/*
FORMAT.hpp - helpers for formatting and diagnostics
FORMAT-UTIL.hpp - helpers for formatting and diagnostics
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
@ -21,20 +21,25 @@
*/
/** @file format.hpp
/** @file format-util.hpp
** Collection of small helpers and convenience shortcuts for diagnostics & formatting.
** - util::str() performs a failsafe to-String conversion, thereby preferring a
** built-in conversion operator, falling back to just a mangled type string.
** - util::tyStr() generates a string corresponding to the type of the given object.
** Currently just implemented through the mangled RTTI type string
**
** @todo we could add a facade to boost::format here, see Ticket #166
** @see FormatHelper_test
** @see format-string.hpp frontend for boost::format, printf-style
**
*/
#ifndef UTIL_FORMAT_H
#define UTIL_FORMAT_H
#ifndef LIB_FORMAT_UTIL_H
#define LIB_FORMAT_UTIL_H
//#include "lib/util.hpp"
#include "lib/meta/trait.hpp"
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <string>
#include <cstring>
@ -46,61 +51,65 @@
namespace util {
using boost::enable_if;
using lib::meta::can_ToString;
using lib::meta::can_lexical2string;
using lib::Symbol;
using boost::enable_if;
using boost::disable_if;
using util::isnil;
using std::string;
namespace { // we need to guard the string conversion
// to avoid a compiler error in case the type isn't convertible....
template<typename X>
inline string
invoke_2string ( typename enable_if< can_ToString<X>,
X >::type const& val)
{
return string(val);
}
template<typename X>
inline string
invoke_2string ( typename disable_if< can_ToString<X>,
X >::type const&)
{
return "";
}
struct use_StringConversion : can_ToString<X> { };
template<typename X>
inline string
invoke_indirect2string ( typename enable_if< can_lexical2string<X>,
X >::type const& val)
{
try { return boost::lexical_cast<string> (val); }
catch(...) { return ""; }
}
struct use_LexicalConversion
{
enum { value = can_lexical2string<X>::value
&& !can_ToString<X>::value
};
};
/** helper: reliably get some string representation for type X */
template<typename X, typename COND =void>
struct _InvokeFailsafe
{
static string toString (X const&) { return ""; }
};
template<typename X>
inline string
invoke_indirect2string ( typename disable_if< can_lexical2string<X>,
X >::type const&)
{
return "";
}
}
struct _InvokeFailsafe<X, typename enable_if< use_StringConversion<X> >::type>
{
static string
toString (X const& val)
try { return string(val); }
catch(...) { return ""; }
};
template<typename X>
struct _InvokeFailsafe<X, typename enable_if< use_LexicalConversion<X> >::type>
{
static string
toString (X const& val)
try { return boost::lexical_cast<string> (val); }
catch(...) { return ""; }
};
}//(End) guards/helpers
/** try to get an object converted to string.
* An custom/standard conversion to string is used,
* A custom/standard conversion to string is used,
* if applicable; otherwise, some standard types can be
* converted by a lexical_cast (based on operator<< ).
* Otherwise, either the fallback string is used, or just
* a string denoting the (mangled) type.
* a string based on the (mangled) type.
*/
template<typename TY>
inline string
@ -109,24 +118,16 @@ namespace util {
, Symbol fallback =0 /// < replacement text to show if string conversion fails
)
{
if (can_ToString<TY>::value)
return string(prefix) + invoke_2string<TY>(val);
string res = _InvokeFailsafe<TY>::toString(val);
if (!isnil (res))
return string(prefix) + res;
else
{
if (can_lexical2string<TY>::value)
{
string res (invoke_indirect2string<TY> (val));
if ("" != res)
return string(prefix) + res;
}
return fallback? string(fallback)
: tyStr(val);
}
return fallback? string(fallback)
: tyStr(val);
}
/** @return a string denoting the type. */
template<typename TY>
inline string
@ -142,5 +143,4 @@ namespace util {
} // namespace util
#endif /*UTIL_FORMAT_H*/
#endif

View file

@ -25,6 +25,7 @@
#define LUMIERA_FRAMEID_H
#include <boost/operators.hpp>
namespace lumiera {

View file

@ -191,15 +191,6 @@ namespace lib {
return *this;
}
IterAdapter
operator++(int)
{
_maybe_throw();
IterAdapter oldPos(*this);
iterate();
return oldPos;
}
bool
isValid () const
{
@ -334,13 +325,6 @@ namespace lib {
return *this;
}
RangeIter
operator++(int)
{
_maybe_throw();
return RangeIter (p_++,e_);
}
bool
isValid () const
{
@ -551,12 +535,6 @@ namespace lib {
return *this;
}
PtrDerefIter
operator++(int)
{
return PtrDerefIter (i_++);
}
bool
isValid () const
{

View file

@ -339,10 +339,10 @@ namespace lib {
/** pipes a given Lumiera Forward Iterator through
* a transformation function and wraps the resulting
* transforming Iterator, exposing just a IterSource.
* transforming Iterator, exposing just an IterSource.
* This convenience shortcut can be used to build a
* processing chain; the resulting IterSource will
* hide any involved detail types.
* hide any detail types involved.
* @note as with any IterSource, there is one virtual
* function call for every fetched element.
*/

View file

@ -491,7 +491,7 @@ namespace lib {
namespace { // Helper to pick up the produced value type automatically
using lumiera::typelist::FunctionSignature;
using lib::meta::FunctionSignature;
template<typename SIG>
struct _ProducedOutput
@ -543,7 +543,7 @@ namespace lib {
/** filters away repeated values
* emitted by source iterator */
template<class IT>
FilterIter<IT>
inline FilterIter<IT>
filterRepetitions (IT const& source)
{
typedef typename IT::value_type Val;

View file

@ -48,7 +48,6 @@
#ifndef LIB_MAYBE_H
#define LIB_MAYBE_H
//#include "pre.hpp"
#include "lib/error.hpp"
//#include "lib/wrapper.hpp"
#include "lib/util.hpp"

View file

@ -45,28 +45,28 @@
*/
#ifndef LUMIERA_META_CONFIGFLAGS_H
#define LUMIERA_META_CONFIGFLAGS_H
#ifndef LIB_META_CONFIGFLAGS_H
#define LIB_META_CONFIGFLAGS_H
#include "lib/meta/typelist.hpp"
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta{
const size_t CONFIG_FLAGS_MAX = 5;
template<char bit> struct Flag { typedef Flag ID; };
template<uint bit> struct Flag { typedef Flag ID; };
template<> struct Flag<0> { typedef NullType ID; };
template< char f1=0
, char f2=0
, char f3=0
, char f4=0
, char f5=0
template< uint f1=0
, uint f2=0
, uint f3=0
, uint f4=0
, uint f5=0
>
struct Flags
{
@ -81,11 +81,11 @@ namespace typelist{
};
template< char f1=0
, char f2=0
, char f3=0
, char f4=0
, char f5=0
template< uint f1=0
, uint f2=0
, uint f3=0
, uint f4=0
, uint f5=0
>
struct Config ///< distinct type representing a configuration
{
@ -95,31 +95,31 @@ namespace typelist{
template<char Fl, class CONF>
template<uint Fl, class CONF>
struct ConfigSetFlag; ///< set (prepend) the Flag to the given config
template< char Fl
, char f1
, char f2
, char f3
, char f4
, char IGN
template< uint Fl
, uint f1
, uint f2
, uint f3
, uint f4
, uint IGN
>
struct ConfigSetFlag<Fl, Config<f1,f2,f3,f4,IGN> >
{
typedef typelist::Config<Fl,f1,f2,f3,f4> Config;
typedef lib::meta::Config<Fl,f1,f2,f3,f4> Config;
};
/** build a configuration type from a list-of-flags */
template<class FLAGS, class CONF=typelist::Config<> >
template<class FLAGS, class CONF=Config<> >
struct BuildConfigFromFlags
{
typedef CONF Config;
typedef Config Type;
};
template<char Fl, class FLAGS, class CONF>
template<uint Fl, class FLAGS, class CONF>
struct BuildConfigFromFlags< Node<Flag<Fl>,FLAGS>, CONF>
{
typedef typename ConfigSetFlag< Fl
@ -134,8 +134,8 @@ namespace typelist{
namespace {
/** helper comparing enum values and chars (flags) */
template<char ii, char jj>
/** helper comparing enum values and flags */
template<uint ii, uint jj>
struct maxC
{
enum{ VAL = ii < jj? jj : ii };
@ -157,7 +157,7 @@ namespace typelist{
template<class FLAGS>
struct FlagInfo;
template<char ff, class FLAGS>
template<uint ff, class FLAGS>
struct FlagInfo<Node<Flag<ff>, FLAGS> >
{
enum{ BITS = maxC< ff, FlagInfo<FLAGS>::BITS> ::VAL
@ -199,5 +199,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -30,7 +30,7 @@
** Because, if we can get a \c bool answer to such a question <i>at compile time,</i> we can use
** \c boost::enable_if to pick a special implementation based on the test result. Together, these
** techniques allow to adopt a duck-typed programming style, where an arbitrary object is allowed
** to enter a given API function, provided this object supports some special operations.
** to enter a given API function, provided this object supports some specific operations.
**
** While C++ certainly isn't a dynamic language and doesn't provide any kind of run time introspection,
** doing such check-and branch at compile time allows even to combine such a flexible approach with
@ -92,16 +92,6 @@
#include "lib/meta/util.hpp"
namespace lib {
namespace meta{
///////////////TICKET #175 sort out meta namespace
using lumiera::Yes_t;
using lumiera::No_t;
}} // namespace lib::meta

View file

@ -44,8 +44,8 @@
*/
#ifndef LUMIERA_META_FUNCTION_CLOSURE_H
#define LUMIERA_META_FUNCTION_CLOSURE_H
#ifndef LIB_META_FUNCTION_CLOSURE_H
#define LIB_META_FUNCTION_CLOSURE_H
#include "lib/meta/function.hpp"
#include "lib/meta/tuple.hpp"
@ -54,9 +54,9 @@
namespace lumiera {
namespace typelist{
namespace func {
namespace lib {
namespace meta{
namespace func{
using std::tr1::function;
@ -67,18 +67,26 @@ namespace func {
using tuple::element;
/**
* Helper to dissect an arbitrary function signature,
* irrespective if the parameter is given as function reference,
* function pointer, member function pointer or functor object.
* The base case assumes a (language) function reference.
*/
template<typename SIG>
struct _Fun
{
typedef typename FunctionSignature<function<SIG> >::Ret Ret;
typedef typename FunctionSignature<function<SIG> >::Args Args;
};
/** Specialisation for using a function pointer */
template<typename SIG>
struct _Fun<SIG*>
{
typedef typename FunctionSignature<function<SIG> >::Ret Ret;
typedef typename FunctionSignature<function<SIG> >::Args Args;
};
/** Specialisation for passing a functor */
template<typename SIG>
struct _Fun<function<SIG> >
{
@ -86,6 +94,115 @@ namespace func {
typedef typename FunctionSignature<function<SIG> >::Args Args;
};
/** Specialisations for member function pointers */
template<typename RET, class CLASS>
struct _Fun<RET (CLASS::*) (void) >
{
typedef RET Ret;
typedef Types<CLASS* const> Args;
};
template< typename RET, class CLASS
, typename A1
>
struct _Fun<RET (CLASS::*) (A1) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
>
struct _Fun<RET (CLASS::*) (A1,A2) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
, typename A3
>
struct _Fun<RET (CLASS::*) (A1,A2,A3) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2,A3> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
, typename A3
, typename A4
>
struct _Fun<RET (CLASS::*) (A1,A2,A3,A4) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2,A3,A4> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
struct _Fun<RET (CLASS::*) (A1,A2,A3,A4,A5) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2,A3,A4,A5> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
, typename A6
>
struct _Fun<RET (CLASS::*) (A1,A2,A3,A4,A5,A6) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2,A3,A4,A5,A6> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
, typename A6
, typename A7
>
struct _Fun<RET (CLASS::*) (A1,A2,A3,A4,A5,A6,A7) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2,A3,A4,A5,A6,A7> Args;
};
template< typename RET, class CLASS
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
, typename A6
, typename A7
, typename A8
>
struct _Fun<RET (CLASS::*) (A1,A2,A3,A4,A5,A6,A7,A8) >
{
typedef RET Ret;
typedef Types<CLASS* const, A1,A2,A3,A4,A5,A6,A7,A8> Args;
};
template<typename FUN>
struct is_Functor { static const bool value = false; };
template<typename SIG>
@ -796,10 +913,11 @@ namespace func {
/* ========== function-style interface ============= */
/** build a TupleApplicator, which embodies the given
* argument tuple and can be used to apply various
* functions to them.
* argument tuple and can be used to apply them
* to various functions repeatedly.
*/
template<typename ARG>
inline
typename _Sig<void, ARG>::Applicator
tupleApplicator (Tuple<ARG>& args)
{
@ -810,6 +928,7 @@ namespace func {
/** apply the given function to the argument tuple */
template<typename SIG, typename ARG>
inline
typename _Fun<SIG>::Ret
apply (SIG& f, Tuple<ARG>& args)
{
@ -824,6 +943,7 @@ namespace func {
* invoked later to yield the
* function result. */
template<typename SIG, typename ARG>
inline
typename _Clo<SIG,ARG>::Type
closure (SIG& f, Tuple<ARG>& args)
{
@ -836,6 +956,7 @@ namespace func {
/** close the given function over the first argument */
template<typename SIG, typename ARG>
inline
typename _PapS<SIG>::Function
applyFirst (SIG& f, ARG arg)
{
@ -848,6 +969,7 @@ namespace func {
/** close the given function over the last argument */
template<typename SIG, typename ARG>
inline
typename _PapE<SIG>::Function
applyLast (SIG& f, ARG arg)
{
@ -862,6 +984,7 @@ namespace func {
/** bind the last function argument to an arbitrary term,
* which especially might be a (nested) binder... */
template<typename SIG, typename TERM>
inline
typename _PapE<SIG>::Function
bindLast (SIG& f, TERM const& arg)
{
@ -875,6 +998,7 @@ namespace func {
/** build a functor chaining the given functions */
template<typename SIG1, typename SIG2>
inline
typename _Chain<SIG1,SIG2>::Function
chained (SIG1& f1, SIG2& f2)
{
@ -884,5 +1008,5 @@ namespace func {
}}} // namespace lumiera::typelist::func
}}} // namespace lib::meta::func
#endif

View file

@ -52,8 +52,8 @@
*/
#ifndef LUMIERA_META_FUNCTION_ERASURE_H
#define LUMIERA_META_FUNCTION_ERASURE_H
#ifndef LIB_META_FUNCTION_ERASURE_H
#define LIB_META_FUNCTION_ERASURE_H
#include "lib/util.hpp"
#include "lib/error.hpp"
@ -64,8 +64,8 @@
#include <tr1/functional>
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta{
using std::tr1::function;
using util::unConst;
@ -240,5 +240,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -44,8 +44,8 @@
*/
#ifndef LUMIERA_META_FUNCTION_H
#define LUMIERA_META_FUNCTION_H
#ifndef LIB_META_FUNCTION_H
#define LIB_META_FUNCTION_H
#include "lib/meta/typelist.hpp"
@ -53,8 +53,8 @@
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta{
using std::tr1::function;
@ -357,5 +357,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -33,8 +33,8 @@
*/
#ifndef LUMIERA_META_GENERATOR_COMBINATIONS_H
#define LUMIERA_META_GENERATOR_COMBINATIONS_H
#ifndef LIB_META_GENERATOR_COMBINATIONS_H
#define LIB_META_GENERATOR_COMBINATIONS_H
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-manip.hpp"
@ -42,8 +42,8 @@
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta{
template<class TYPES_1, class TYPES_2>
@ -97,5 +97,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -39,7 +39,7 @@ This code is heavily inspired by
/** @file generator.hpp
** Helpers for working with lumiera::typelist::Types (i.e. lists-of-types).
** Helpers for working with lib::meta::Types (i.e. lists-of-types).
** The main purpose is to build interfaces and polymorphic implementations
** (using virtual functions) based on templated Types or Collections of types,
** which is not possible without Template Metaprogramming.
@ -56,15 +56,15 @@ This code is heavily inspired by
*/
#ifndef LUMIERA_META_GENERATOR_H
#define LUMIERA_META_GENERATOR_H
#ifndef LIB_META_GENERATOR_H
#define LIB_META_GENERATOR_H
#include "lib/meta/typelist.hpp"
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta{
/**
* Apply a template to a collection of types.
@ -207,5 +207,5 @@ namespace typelist{
};
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -21,8 +21,8 @@
*/
#ifndef LUMIERA_META_MAYBE_COMPARE_H
#define LUMIERA_META_MAYBE_COMPARE_H
#ifndef LIB_META_MAYBE_COMPARE_H
#define LIB_META_MAYBE_COMPARE_H
#include "lib/functor-util.hpp"
@ -30,8 +30,8 @@
#include <tr1/functional>
namespace lumiera {
namespace typelist {
namespace lib {
namespace meta{
using std::tr1::function;
@ -72,5 +72,5 @@ namespace typelist {
}
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

149
src/lib/meta/size-trait.hpp Normal file
View file

@ -0,0 +1,149 @@
/*
SIZE-TRAIT.hpp - helpers and definitions to deal with the size of some known types
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LIB_META_SIZE_TRAIT_H
#define LIB_META_SIZE_TRAIT_H
#include <vector>
#include <string>
namespace lib {
namespace meta {
/**
* A collection of constants to describe the expected size
* of some known classes, without needing to include the
* respective headers. This is an optimisation to improve
* compilation times and/or reduce size of the generated
* object files in debug mode. To get those sizes computed
* in a fairly portable way, but without much overhead,
* we mimic the memory layout of "the real thing"
* with some reasonable simplifications:
* - the size of vectors doesn't really depend on the elements
* - our strings, streams and buffers use just simple chars
*
* \par Interface
* The purpose of this whole construction is to pull off
* some constants based on sizeof expressions:
* - the size of a string
* - the size of a vector
* - the size of a boost::format
*
* @warning this setup is quite fragile and directly relies
* on the implementation layout of the GNU STL and Boost.
* Whenever using this stuff, make sure to place an assertion
* somewhere down in the implementation level to check against
* the size of the real thing.
*/
class SizeTrait
{
//-------------------------------------mimicked-definitions--
typedef std::vector<size_t> Vector;
typedef std::vector<bool> BVector;
struct CompatAllocator
: std::allocator<char>
{ };
struct Locale
{
void* _M_impl;
};
template<class T>
struct Optional
{
bool m_initialized_;
T m_storage_;
};
enum IOS_Openmode
{
_S_app = 1L << 0,
_S_ate = 1L << 1,
_S_bin = 1L << 2,
_S_in = 1L << 3,
_S_out = 1L << 4,
_S_trunc = 1L << 5,
_S_ios_openmode_end = 1L << 16
};
struct BasicStringbuf
{
char * _M_in_beg;
char * _M_in_cur;
char * _M_in_end;
char * _M_out_beg;
char * _M_out_cur;
char * _M_out_end;
Locale _M_buf_locale;
virtual ~BasicStringbuf() { }
};
struct BasicAltstringbuf
: BasicStringbuf
{
char * putend_;
bool is_allocated_;
IOS_Openmode mode_;
CompatAllocator alloc_;
};
struct BoostFormat
{
Vector items_;
BVector bound_; // note: differs in size
int style_;
int cur_arg_;
int num_args_;
mutable bool dumped_;
std::string prefix_;
unsigned char exceptions;
BasicAltstringbuf buf_;
Optional<Locale> loc_;
};
//-------------------------------------mimicked-definitions--
public:/* ===== Interface: size constants ===== */
enum { ALIGNMENT = sizeof(size_t)
, STRING = sizeof(std::string)
, VECTOR = sizeof(Vector)
, BVECTOR = sizeof(BVector)
, BOOST_FORMAT = sizeof(BoostFormat)
};
};
}} // namespace lib::meta
#endif

View file

@ -33,7 +33,7 @@
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/utility/enable_if.hpp>
#include <string>
//Forward declarations for the Unwrap helper....
@ -42,14 +42,14 @@ namespace boost{
}
namespace std {
namespace tr1 {
template<class X> class reference_wrapper;
template<class X> class reference_wrapper;
template<class X> class shared_ptr;
}}
namespace lumiera{
template<class X, class B> class P;
namespace lib{
template<class X, class B> class P;
}
namespace mobject{
template<class X, class B> class Placement;
template<class X, class B> class Placement;
}
@ -127,12 +127,12 @@ namespace meta {
};
template<typename X, class B>
struct Unwrap<lumiera::P<X, B> >
struct Unwrap<P<X, B> >
{
typedef X Type;
static X&
extract (lumiera::P<X,B> ptr)
extract (P<X,B> ptr)
{
ASSERT (ptr);
return *ptr;

View file

@ -44,8 +44,8 @@
*/
#ifndef LUMIERA_META_TUPLE_H
#define LUMIERA_META_TUPLE_H
#ifndef LIB_META_TUPLE_H
#define LIB_META_TUPLE_H
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-util.hpp"
@ -54,8 +54,8 @@
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta {
@ -283,6 +283,7 @@ namespace typelist{
namespace tuple { // some convenience access functions
template<uint n, class TUP>
inline
typename Shifted<TUP,n>::Head&
element (TUP& tup)
{
@ -743,5 +744,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -49,15 +49,17 @@
*/
#ifndef LUMIERA_META_TYPELIST_MANIP_H
#define LUMIERA_META_TYPELIST_MANIP_H
#ifndef LIB_META_TYPELIST_MANIP_H
#define LIB_META_TYPELIST_MANIP_H
#include "lib/meta/typelist.hpp"
namespace lumiera {
namespace typelist{
#include <sys/types.h>
namespace lib {
namespace meta {
/** pick the n-th element from a typelist */
@ -325,5 +327,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -24,7 +24,7 @@
/** @file typelist-util.hpp
** Metaprogramming: simple helpers for working with lists-of-types.
** This header provides some very basic "meta functions" for extracting
** some informations from a list-of-types. In Lumiera, we use template
** pieces of information from a list-of-types. In Lumiera, we use template
** metaprogramming and especially such lists-of-types, whenever we build
** some common implementation backbone, without being able to subsume all
** participating types (classes) into a single inheritance hierarchy.
@ -42,15 +42,15 @@
*/
#ifndef LUMIERA_META_TYPELIST_UTIL_H
#define LUMIERA_META_TYPELIST_UTIL_H
#ifndef LIB_META_TYPELIST_UTIL_H
#define LIB_META_TYPELIST_UTIL_H
#include "lib/meta/typelist.hpp"
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta {
/**
@ -123,5 +123,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -55,7 +55,7 @@ This code is heavily inspired by
** effectively this is a flavour of functional programming. Just the
** "execution environment" is the compiler, during compilation.
**
** @see lumiera::visitor::Applicable usage example
** @see lib::visitor::Applicable usage example
** @see control::CommandSignature more elaborate usage example (dissecting a functor signature)
** @see TypeList_test
** @see TypeListManip_test
@ -63,14 +63,14 @@ This code is heavily inspired by
*/
#ifndef LUMIERA_META_TYPELIST_H
#define LUMIERA_META_TYPELIST_H
#ifndef LIB_META_TYPELIST_H
#define LIB_META_TYPELIST_H
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta {
struct NullType
{
@ -129,5 +129,5 @@ namespace typelist{
typedef Node<NullType,NullType> NodeNull;
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -41,8 +41,8 @@
*/
#ifndef LUMIERA_META_TYPESEQ_UTIL_H
#define LUMIERA_META_TYPESEQ_UTIL_H
#ifndef LIB_META_TYPESEQ_UTIL_H
#define LIB_META_TYPESEQ_UTIL_H
#include "lib/meta/typelist.hpp"
#include "lib/meta/typelist-manip.hpp"
@ -50,8 +50,8 @@
namespace lumiera {
namespace typelist{
namespace lib {
namespace meta {
@ -203,5 +203,5 @@ namespace typelist{
}} // namespace lumiera::typelist
}} // namespace lib::meta
#endif

View file

@ -21,92 +21,154 @@
*/
#ifndef LUMIERA_META_UTIL_H
#define LUMIERA_META_UTIL_H
/** @file util.hpp
** Simple and lightweight helpers for metaprogramming and type detection.
** This header is a collection of very basic type detection and metaprogramming utilities.
** @warning indirectly, this header gets included into the majority of compilation units.
** Avoid anything here which increases compilation times or adds much debugging info.
**
** @see MetaUtils_test
** @see trait.hpp
** @see typelist.hpp
**
*/
#ifndef LIB_META_UTIL_H
#define LIB_META_UTIL_H
#include <string>
namespace lib {
namespace meta {
namespace lumiera {
/* types for figuring out the overload resolution chosen by the compiler */
typedef char Yes_t;
struct No_t { char padding[8]; };
namespace typelist {
/** Compile-time Type equality:
* Simple Trait template to pick up types considered
* \em identical by the compiler.
* @warning identical, not sub-type!
*/
template<typename T1, typename T2>
struct is_sameType
{
static const bool value = false;
};
template<typename T>
struct is_sameType<T,T>
{
static const bool value = true;
};
/** semi-automatic detection if an instantiation is possible.
* Requires help by the template to be tested, which needs to define
* a typedef member \c is_defined. The embedded metafunction Test can be used
* as a predicate for filtering types which may yield a valid instantiation
* of the candidate template in question.
* \par
* A fully automated solution for this problem is impossible by theoretic reasons.
* Any non trivial use of such a \c is_defined trait would break the "One Definition Rule",
* as the state of any type can change from "partially defined" to "fully defined" over
* the course of any translation unit. Thus, even if there may be a \em solution out there,
* we can expect it to break at some point by improvements/fixes to the C++ Language.
*/
template<template<class> class _CandidateTemplate_>
struct Instantiation
{
template<class X>
class Test
{
typedef _CandidateTemplate_<X> Instance;
template<class U>
static Yes_t check(typename U::is_defined *);
template<class U>
static No_t check(...);
public:
static const bool value = (sizeof(Yes_t)==sizeof(check<Instance>(0)));
};
};
/** Trait template for detecting a typelist type.
* For example, this allows to write specialisations with the help of
* boost::enable_if
*/
template<typename TY>
class is_Typelist
{
template<class X>
static Yes_t check(typename X::List *);
template<class>
static No_t check(...);
public:
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
};
} // namespace typelist
} // namespace lumiera
typedef char Yes_t;
struct No_t { char more_than_one[4]; };
/** Compile-time Type equality:
* Simple Trait template to pick up types considered
* \em identical by the compiler.
* @warning identical, not sub-type!
*/
template<typename T1, typename T2>
struct is_sameType
{
static const bool value = false;
};
template<typename T>
struct is_sameType<T,T>
{
static const bool value = true;
};
/** detect possibility of a conversion to string.
* Naive implementation just trying a the direct conversion.
* The embedded constant #value will be true in case this succeeds.
* Might fail in more tricky situations (references, const, volatile)
* @see string-util.hpp more elaborate solution including lexical_cast
*/
template<typename T>
struct can_convertToString
{
static T & probe();
static Yes_t check(std::string);
static No_t check(...);
public:
static const bool value = (sizeof(Yes_t)==sizeof(check(probe())));
};
/** strip const from type: naive implementation */
template<typename T>
struct UnConst
{
typedef T Type;
};
template<typename T>
struct UnConst<const T>
{
typedef T Type;
};
template<typename T>
struct UnConst<const T *>
{
typedef T* Type;
};
template<typename T>
struct UnConst<T * const>
{
typedef T* Type;
};
template<typename T>
struct UnConst<const T * const>
{
typedef T* Type;
};
/** semi-automatic detection if an instantiation is possible.
* Requires help by the template to be tested, which needs to define
* a typedef member \c is_defined. The embedded metafunction Test can be used
* as a predicate for filtering types which may yield a valid instantiation
* of the candidate template in question.
* \par
* A fully automated solution for this problem is impossible by theoretic reasons.
* Any non trivial use of such a \c is_defined trait would break the "One Definition Rule",
* as the state of any type can change from "partially defined" to "fully defined" over
* the course of any translation unit. Thus, even if there may be a \em solution out there,
* we can expect it to break at some point by improvements/fixes to the C++ Language.
*/
template<template<class> class _CandidateTemplate_>
struct Instantiation
{
template<class X>
class Test
{
typedef _CandidateTemplate_<X> Instance;
template<class U>
static Yes_t check(typename U::is_defined *);
template<class U>
static No_t check(...);
public:
static const bool value = (sizeof(Yes_t)==sizeof(check<Instance>(0)));
};
};
/** Trait template for detecting a typelist type.
* For example, this allows to write specialisations with the help of
* boost::enable_if
*/
template<typename TY>
class is_Typelist
{
template<class X>
static Yes_t check(typename X::List *);
template<class>
static No_t check(...);
public:
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
};
}} // namespace lib::meta
#endif

View file

@ -54,9 +54,9 @@ namespace lib {
namespace factory {
using lumiera::typelist::Types;
using lumiera::typelist::FunctionSignature;
using lumiera::typelist::FunctionTypedef;
using lib::meta::Types;
using lib::meta::FunctionSignature;
using lib::meta::FunctionTypedef;
using std::tr1::function;

View file

@ -21,7 +21,7 @@
*/
/** @file multifact.hpp
** Building blocks of a configurable factory, generating families of related objects.
** Building blocks to create a configurable factory, generating families of related objects.
** Serving the "classical" factory situation: obtaining objects of various kinds, which
** are related somehow (usually through an common interface). The creation of these
** objects is non-trivial while number and exact parametrisation aren't known beforehand
@ -70,7 +70,7 @@
namespace lib {
namespace factory {
//////TODO: couldn't these wrappers be extracted into a separate header?
/////////////////////////////////TICKET #470 : couldn't these wrappers be extracted into a separate header?
/**
* Dummy "wrapper",

View file

@ -0,0 +1,104 @@
/*
NOBUG-RESOURCE-HANDLE-CONTEXT.hpp - thread local stack to manage NoBug resource handles
Copyright (C) Lumiera.org
2010, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file nobug-resource-handle-context.hpp
** Thread-local stack of NoBug resource handles.
** This helper allows to access the resource handle in the nearest enclosing scope.
** The motivation for this approach was to avoid passing the resource handle over
** several intermediary function calls when using a scoped variable to control
** object monitor locking. Within this usage context, the necessity of passing
** a NoBug resource handle seems to be a cross-cutting concern, and not directly
** related to the core concern (controlling a mutex).
**
** @remarks as of 8/2011, this feature is not used anymore. In 12/2011, the concept
** of a diagnostic context stack was generalised. At that point, this header was
** created as an off-spin, now based on the generalised feature, to document this
** usage possibility, which might be required again at some point in the future.
**
** @see lib::DiagnosticContext
** @see diagnostic-context-test.hpp
**
**/
#ifndef LIB_NOBUG_RESOURCE_HANDLE_CONTEXT_H
#define LIB_NOBUG_RESOURCE_HANDLE_CONTEXT_H
#include "lib/error.hpp"
#include "lib/thread-local.hpp"
#include <boost/noncopyable.hpp>
#include <nobug.h>
namespace lib {
#ifdef NOBUG_MODE_ALPHA ////////////////////////TODO don't we need the handle in BETA builds for resource logging?
/**
* Diagnostic data frame to hold a NoBug resource handle.
* This way, code in nested function calls may pick up the nearest available handle.
* @warning relies on thread-local access; never use this within global data structures.
*/
class NobugResourceHandleContext
: DiagnosticContext<nobug_resource_user*>
{
public:
};
#else /* not NOBUG_ALPHA */
/**
* Disabled placeholder for the Diagnostic context, not used in release builds.
*/
class NobugResourceHandleContext
: boost::noncopyable
{
typedef nobug_resource_user* Handle;
public:
operator Handle () ///< payload: NoBug resource tracker user handle
{
return 0;
}
/** accessing the innermost diagnostic context created */
static NobugResourceHandleContext&
access ()
{
UNIMPLEMENTED ("how to disable DiagnosticContext with minimum overhead");
}
};
#endif /* NOBUG_ALPHA? */
} // namespace lib
#endif

View file

@ -73,6 +73,7 @@
#include "lib/util.hpp"
#include <boost/noncopyable.hpp>
#include <boost/static_assert.hpp>
namespace lib {
@ -252,6 +253,8 @@ namespace lib {
template<typename SUB>
struct Buff : Buffer
{
BOOST_STATIC_ASSERT (siz >= sizeof(SUB));
SUB&
get() const ///< core operation: target is contained within the inline buffer
{
@ -266,7 +269,6 @@ namespace lib {
explicit
Buff (SUB const& obj)
{
REQUIRE (siz >= sizeof(SUB));
new(Buffer::ptr()) SUB (obj);
}
@ -613,6 +615,8 @@ namespace lib {
void
placeDefault()
{
BOOST_STATIC_ASSERT (siz >= sizeof(DEFAULT));
new(&buf_) DEFAULT();
}
@ -640,13 +644,14 @@ namespace lib {
destroy(); \
try \
{ \
REQUIRE (siz >= sizeof(TY)); \
return *new(&buf_) _CTOR_CALL_; \
} \
catch (...) \
{ \
placeDefault(); \
throw; \
BOOST_STATIC_ASSERT (siz >= sizeof(TY));\
\
return *new(&buf_) _CTOR_CALL_; \
} \
catch (...) \
{ \
placeDefault(); \
throw; \
}

View file

@ -46,15 +46,15 @@
*/
#ifndef LUMIERA_P_H
#define LUMIERA_P_H
#ifndef LIB_P_H
#define LIB_P_H
#include "lib/error.hpp"
#include <tr1/memory>
namespace lumiera {
namespace lib {
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
@ -125,5 +125,5 @@ namespace lumiera {
};
} // namespace lumiera
} // namespace lib
#endif

View file

@ -34,8 +34,8 @@
** assume the presence of a garbage collector or similar mechanism,
** so 'objects' need just to be mentioned by reference.
**
** In C++ to employ many of the well known techniques, you're more or less
** bound to explicitly put the objects somewhere in heap allocated memory
** In C++, in order to employ many of the well known techniques, we're bound
** more or less to explicitly put the objects somewhere in heap allocated memory
** and then pass an interface pointer or reference into the actual algorithm.
** Often, this hinders a design based on constant values and small descriptor
** objects used inline, thus forcing into unnecessarily complex and heavyweight
@ -68,7 +68,7 @@
** Moreover, the PolymorphicValue container provides static builder functions,
** allowing to place a concrete instance of a subclass into the content buffer.
** After construction, the actual type of this instance will be forgotten
** (``type erasure''), but because the embedded vtable, on access the
** (``type erasure''), but because of the embedded vtable, on access the
** proper implementation functions will be invoked.
**
** Expanding on that pattern, the copying and cloning operations of the whole
@ -86,7 +86,7 @@
** the copy or clone operations, we need to do an elaborate re-cast operation,
** first going down to the leaf type and then back up into the mixed in
** management interface. Basically this operation is performed by using
** an \c dynamic_cast<CopyAPI&>(bufferContents)
** a \c dynamic_cast<CopyAPI&>(bufferContents)
** - but when the used client types provide some collaboration and implement
** this management interface either directly on the API or as an immediate
** sub-interface, then this copy/management interface is located within the
@ -146,6 +146,7 @@
#include "lib/meta/duck-detector.hpp"
#include <boost/utility/enable_if.hpp>
#include <boost/static_assert.hpp>
namespace lib {
@ -155,8 +156,8 @@ namespace lib {
namespace error = lumiera::error;
using boost::enable_if;
using lumiera::Yes_t;
using lumiera::No_t;
using lib::meta::Yes_t;
using lib::meta::No_t;
struct EmptyBase{ };
@ -345,7 +346,7 @@ namespace lib {
* - the caller cares for thread safety. No concurrent get calls while in mutation!
*
* @warning when a create or copy-into operation fails with exception, the whole
* PolymorphicValue object is in undefined state and must not be used further.
* PolymorphicValue object is in undefined state and must not be used henceforth.
*/
template
< class IFA ///< the nominal Base/Interface class for a family of types
@ -384,7 +385,8 @@ namespace lib {
template<class IMP>
PolymorphicValue (IMP*)
{
REQUIRE (siz >= sizeof(IMP));
BOOST_STATIC_ASSERT (siz >= sizeof(IMP));
new(&buf_) IMP();
}

View file

@ -40,7 +40,6 @@
#ifndef LIB_RESULT_H
#define LIB_RESULT_H
//#include "pre.hpp"
#include "lib/error.hpp"
#include "lib/wrapper.hpp"
#include "lib/util.hpp"

View file

@ -0,0 +1,614 @@
/*
SCOPED-COLLECTION.hpp - managing a fixed collection of noncopyable polymorphic objects
Copyright (C) Lumiera.org
2012, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file scoped-collection.hpp
** Managing a collection of noncopyable polymorphic objects in compact storage.
** This helper supports the frequently encountered situation where a service
** implementation internally manages a collection of implementation related
** sub-components with reference semantics. Typically, those objects are
** being used polymorphically, and often they are also added step by step.
** The storage holding all those child objects is allocated in one chunk
** and never adjusted.
**
** \par usage patterns
** The common ground for all usage of this container is to hold and some
** with exclusive ownership; when the enclosing container goes out of scope,
** all the dtors of the embedded objects will be invoked. Frequently this
** side effect is the reason for using the container: we want to own some
** resource handles to be available exactly as long as the managing object
** needs and accesses them.
**
** There are two different usage patterns for populating a ScopedCollection
** - the "stack style" usage creates an empty container (using the one arg
** ctor just to specify the maximum size). The storage to hold up to this
** number of objects is (heap) allocated right away, but no objects are
** created. Later on, individual objects are "pushed" into the collection
** by invoking #appendNewElement() to create a new element of the default
** type I) or #appendNew<Type>(args) to create some subtype. This way,
** the container is being filled successively.
** - the "RAII style" usage strives to create all of the content objects
** right away, immediately after the memory allocation. This usage pattern
** avoids any kind of "lifecycle state". Either the container comes up sane
** and fully populated, or the ctor call fails and any already created
** objects are discarded.
** @note intentionally there is no operation to discard individual objects,
** all you can do is to #clear() the whole container.
** @note the container can hold instances of a subclass of the type defined
** by the template parameter I. But you need to ensure in this case
** that the defined buffer size for each element (2nt template parameter)
** is sufficient to hold any of these subclass instances. This condition
** is protected by a static assertion (compilation failure).
** @warning when using subclasses, a virtual dtor is mandatory
** @warning deliberately \em not threadsafe
**
** @see ScopedCollection_test
** @see scoped-ptrvect.hpp quite similar, but using individual heap pointers
*/
#ifndef LIB_SCOPED_COLLECTION_H
#define LIB_SCOPED_COLLECTION_H
#include "lib/error.hpp"
#include "lib/iter-adapter.hpp"
#include <boost/noncopyable.hpp>
#include <boost/scoped_array.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace lib {
namespace error = lumiera::error;
using error::LUMIERA_ERROR_CAPACITY;
using error::LUMIERA_ERROR_INDEX_BOUNDS;
/**
* A fixed collection of noncopyable polymorphic objects.
*
* All child objects reside in a common chunk of storage
* and are owned and managed by this collection holder.
* Array style access and iteration.
*/
template
< class I ///< the nominal Base/Interface class for a family of types
, size_t siz = sizeof(I) ///< maximum storage required for the targets to be held inline
>
class ScopedCollection
: boost::noncopyable
{
public:
/**
* Storage Frame to hold one Child object.
* The storage will be an heap allocated
* array of such Wrapper objects.
* @note doesn't manage the Child
*/
class ElementHolder
: boost::noncopyable
{
mutable char buf_[siz];
public:
I&
accessObj() const
{
return reinterpret_cast<I&> (buf_);
}
void
destroy()
{
accessObj().~I();
}
#define TYPE_SANITY_CHECK \
BOOST_STATIC_ASSERT ((boost::is_base_of<I,TY>::value || boost::is_same<I,TY>::value))
/** Abbreviation for placement new */
#define EMBEDDED_ELEMENT_CTOR(_CTOR_CALL_) \
TYPE_SANITY_CHECK; \
return *new(&buf_) _CTOR_CALL_; \
template<class TY>
TY&
create ()
{
EMBEDDED_ELEMENT_CTOR ( TY() )
}
template<class TY, typename A1>
TY& //___________________________________________
create (A1 a1) ///< place object of type TY, using 1-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1) )
}
template< class TY
, typename A1
, typename A2
>
TY& //___________________________________________
create (A1 a1, A2 a2) ///< place object of type TY, using 2-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2) )
}
template< class TY
, typename A1
, typename A2
, typename A3
>
TY& //___________________________________________
create (A1 a1, A2 a2, A3 a3) ///< place object of type TY, using 3-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3) )
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
>
TY& //___________________________________________
create (A1 a1, A2 a2, A3 a3, A4 a4) ///< place object of type TY, using 4-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3,a4) )
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
TY& //___________________________________________
create (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) ///< place object of type TY, using 5-arg ctor
{
EMBEDDED_ELEMENT_CTOR ( TY(a1,a2,a3,a4,a5) )
}
#undef EMBEDDED_ELEMENT_CTOR
#undef TYPE_SANITY_CHECK
};
~ScopedCollection ()
{
clear();
}
explicit
ScopedCollection (size_t maxElements)
: level_(0)
, capacity_(maxElements)
, elements_(new ElementHolder[maxElements])
{ }
/** creating a ScopedCollection in RAII-style:
* The embedded elements will be created immediately.
* Ctor fails in case of any error during element creation.
* @param builder functor to be invoked for each "slot".
* It gets an ElementHolder& as parameter, and should
* use this to create an object of some I-subclass
*/
template<class CTOR>
ScopedCollection (size_t maxElements, CTOR builder)
: level_(0)
, capacity_(maxElements)
, elements_(new ElementHolder[maxElements])
{
populate_by (builder);
}
/** variation of RAII-style: using a builder function,
* which is a member of some object. This supports the
* typical usage situation, where a manager object builds
* a ScopedCollection of some components
* @param builder member function used to create the elements
* @param instance the owning class instance, on which the
* builder member function will be invoked ("this").
*/
template<class TY>
ScopedCollection (size_t maxElements, void (TY::*builder) (ElementHolder&), TY * const instance)
: level_(0)
, capacity_(maxElements)
, elements_(new ElementHolder[maxElements])
{
populate_by (builder,instance);
}
/* == some pre-defined Builders == */
class FillAll; ///< fills the ScopedCollection with default constructed I-instances
template<typename TY>
class FillWith; ///< fills the ScopedCollection with default constructed TY-instances
template<typename IT>
class PullFrom; ///< fills by copy-constructing values pulled from the iterator IT
template<typename IT>
static PullFrom<IT>
pull (IT iter) ///< convenience shortcut to pull from any given Lumiera Forward Iterator
{
return PullFrom<IT> (iter);
}
void
clear()
{
REQUIRE (level_ <= capacity_, "Storage corrupted");
while (level_)
{
--level_;
try {
elements_[level_].destroy();
}
ERROR_LOG_AND_IGNORE (progress, "Clean-up of element in ScopedCollection")
}
}
/** init all elements default constructed */
void
populate()
try {
while (level_ < capacity_)
{
elements_[level_].template create<I>();
++level_;
}
}
catch(...)
{
WARN (progress, "Failure while populating ScopedCollection. "
"All elements will be discarded");
clear();
throw;
}
/** init all elements at once,
* invoking a builder functor for each.
* @param builder to create the individual elements
* this functor is responsible to invoke the appropriate
* ElementHolder#create function, which places a new element
* into the storage frame passed as parameter.
*/
template<class CTOR>
void
populate_by (CTOR builder)
try {
while (level_ < capacity_)
{
ElementHolder& storageFrame (elements_[level_]);
builder (storageFrame);
++level_;
} }
catch(...)
{
WARN (progress, "Failure while populating ScopedCollection. "
"All elements will be discarded");
clear();
throw;
}
/** variation of element initialisation,
* invoking a member function of some manager object
* for each collection element to be created.
*/
template<class TY>
void
populate_by (void (TY::*builder) (ElementHolder&), TY * const instance)
try {
while (level_ < capacity_)
{
ElementHolder& storageFrame (elements_[level_]);
(instance->*builder) (storageFrame);
++level_;
} }
catch(...)
{
WARN (progress, "Failure while populating ScopedCollection. "
"All elements will be discarded");
clear();
throw;
}
/** push a new element of default type
* to the end of this container
* @note EX_STRONG */
I& appendNewElement() { return appendNew<I>(); }
template< class TY >
TY& //_________________________________________
appendNew () ///< add object of type TY, using 0-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>();
++level_;
return newElm;
}
template< class TY
, typename A1
>
TY& //_________________________________________
appendNew (A1 a1) ///< add object of type TY, using 1-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2) ///< add object of type TY, using 2-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
, typename A3
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2, A3 a3) ///< add object of type TY, using 3-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2,a3);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2, A3 a3, A4 a4) ///< add object of type TY, using 4-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2,a3,a4);
++level_;
return newElm;
}
template< class TY
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
TY& //_________________________________________
appendNew (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) ///< add object of type TY, using 5-arg ctor
{
__ensureSufficientCapacity();
TY& newElm = elements_[level_].template create<TY>(a1,a2,a3,a4,a5);
++level_;
return newElm;
}
/* === Element access and iteration === */
I&
operator[] (size_t index) const
{
if (index < level_)
return elements_[index].accessObj();
throw error::Logic ("Attempt to access not (yet) existing object in ScopedCollection"
, LUMIERA_ERROR_INDEX_BOUNDS);
}
typedef IterAdapter< I *, const ScopedCollection *> iterator;
typedef IterAdapter<const I *, const ScopedCollection *> const_iterator;
iterator begin() { return iterator (this, _access_begin()); }
const_iterator begin() const { return const_iterator (this, _access_begin()); }
iterator end () { return iterator(); }
const_iterator end () const { return const_iterator(); }
size_t size () const { return level_; }
size_t capacity () const { return capacity_; }
bool empty () const { return 0 == level_; }
private:
/* ==== Storage: heap allocated array of element buffers ==== */
typedef boost::scoped_array<ElementHolder> ElementStorage;
size_t level_;
size_t capacity_;
ElementStorage elements_;
void
__ensureSufficientCapacity()
{
if (level_ >= capacity_)
throw error::State ("ScopedCollection exceeding the initially defined capacity"
, LUMIERA_ERROR_CAPACITY);
}
/* ==== internal callback API for the iterator ==== */
/** Iteration-logic: switch to next position
* @note assuming here that the start address of the embedded object
* coincides with the start of an array element (ElementHolder)
*/
friend void
iterNext (const ScopedCollection*, I* & pos)
{
ElementHolder* & storageLocation = reinterpret_cast<ElementHolder* &> (pos);
++storageLocation;
}
friend void
iterNext (const ScopedCollection*, const I* & pos)
{
const ElementHolder* & storageLocation = reinterpret_cast<const ElementHolder* &> (pos);
++storageLocation;
}
/** Iteration-logic: detect iteration end. */
template<typename POS>
friend bool
hasNext (const ScopedCollection* src, POS & pos)
{
REQUIRE (src);
if ((pos) && (pos < src->_access_end()))
return true;
else
{
pos = 0;
return false;
} }
I* _access_begin() const { return & elements_[0].accessObj(); }
I* _access_end() const { return & elements_[level_].accessObj(); }
};
/* === Supplement: pre-defined element builders === */
/** \par usage
* Pass an instance of this builder functor as 2nd parameter
* to ScopedCollections's ctor. (an anonymous instance is OK).
* Using this variant of the compiler switches the collection to RAII-style:
* It will immediately try to create all the embedded objects, invoking this
* builder functor for each "slot" to hold such an embedded object. Actually,
* this "slot" is an ElementHolder instance, which provides functions for
* placement-creating objects into this embedded buffer.
*/
template<class I, size_t siz>
class ScopedCollection<I,siz>::FillAll
{
public:
void
operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
{
storage.template create<I>();
}
};
template<class I, size_t siz>
template<typename TY>
class ScopedCollection<I,siz>::FillWith
{
public:
void
operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
{
storage.template create<TY>();
}
};
/** \par usage
* This variant allows to "pull" elements from an iterator.
* Actually, the collection will try to create each element right away,
* by invoking the copy ctor and passing the value yielded by the iterator.
* @note anything in accordance to the Lumera Forward Iterator pattern is OK.
* This rules out just passing a plain STL iterator (because these can't
* tell for themselves when they're exhausted). Use an suitable iter-adapter
* instead, e.g. by invoking lib::iter_stl::eachElm(stl_container)
*/
template<class I, size_t siz>
template<typename IT>
class ScopedCollection<I,siz>::PullFrom
{
IT iter_;
typedef typename iter::TypeBinding<IT>::value_type ElementType;
public:
PullFrom (IT source)
: iter_(source)
{ }
void
operator() (typename ScopedCollection<I,siz>::ElementHolder& storage)
{
storage.template create<ElementType> (*iter_);
++iter_;
}
};
} // namespace lib
#endif

View file

@ -35,6 +35,8 @@
** - TODO: detaching of objects...
** - TODO: retro-fit with RefArray interface
**
** @warning deliberately \em not threadsafe
**
** @see scoped-ptrvect-test.cpp
** @see scoped-holder.hpp
** @see gui::DisplayService usage example

View file

@ -46,11 +46,10 @@
#ifndef LIB_SIMPLE_ALLOCATOR_H
#define LIB_SIMPLE_ALLOCATOR_H
//#include "pre.hpp"
#include "lib/error.hpp"
#include "lib/meta/generator.hpp"
#include "lib/meta/typelist-util.hpp"
#include "lib/format.hpp"
#include "lib/format-util.hpp"
#include "lib/typed-counter.hpp"
#include "include/logging.h"
@ -61,9 +60,9 @@
namespace lib {
using lumiera::typelist::Types;
using lumiera::typelist::IsInList;
using lumiera::typelist::InstantiateForEach;
using lib::meta::Types;
using lib::meta::IsInList;
using lib::meta::InstantiateForEach;
@ -144,7 +143,7 @@ namespace lib {
: InstantiateForEach< typename TYPES::List // for each of those types...
, CustomAllocator // ...mix in the custom allocator
>
, COUNTER
, COUNTER // ...Instantiation accounting policy
{
/** forward plain memory allocation */

View file

@ -46,7 +46,7 @@
#ifndef LIB_SUB_ID_H
#define LIB_SUB_ID_H
#include "lib/format.hpp"
#include "lib/format-util.hpp"
//#include <functional>
#include <boost/functional/hash.hpp> /////TODO better push the hash implementation into a cpp file (and btw, do it more seriously!)

View file

@ -130,8 +130,8 @@ namespace test{
namespace mock {
using boost::enable_if;
using lumiera::Yes_t;
using lumiera::No_t;
using lib::meta::Yes_t;
using lib::meta::No_t;
/**
* Metafunction: does the Type in question

View file

@ -36,15 +36,12 @@
#ifndef TESTHELPER_RUN_H
#define TESTHELPER_RUN_H
#include "pre.hpp"
#include "proc/common.hpp"
#include "include/logging.h"
#include "lib/test/suite.hpp"
#include "lib/util.hpp"
#include <vector>
#include <string>

View file

@ -1,8 +1,8 @@
/*
test.h - macros for running tests
TEST.h - support macros for plain-C tests
Copyright (C)
2008, 2009, 2010, Christian Thaeter <ct@pipapo.org>
Copyright (C) Lumiera.org
2008, 2010 Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -17,10 +17,21 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TEST_H
#define TEST_H
/** @file test.h
** Helpers and support macros for defining test executables in C.
** These macros provide some building blocks to assemble a \c main() function,
** which checks a test name parameter and invokes the matching embedded code block.
**
** @see test-mpool.c C test example
** @see HelloWorld_test C++ test example
*/
#ifndef LIB_TEST_TEST_H
#define LIB_TEST_TEST_H
#include <stdio.h>
#include <stdlib.h>
@ -51,10 +62,10 @@ main (int argc, const char** argv) \
fprintf (stderr, " "#name" (planned)\n"); \
else if (!++testcnt)
#define TESTS_END \
if (!testcnt && argc !=1) \
fprintf (stderr,"no such test: %s\n", argv[1]); \
return ret; \
#define TESTS_END \
if (!testcnt && argc !=1) \
fprintf (stderr,"no such test: %s\n", argv[1]); \
return ret; \
}

View file

@ -48,14 +48,22 @@ namespace test{
: val_(v)
{ init(); }
~Dummy()
virtual ~Dummy()
{
checksum() -= val_;
}
long add (int i) { return val_+i; }
virtual long
acc (int i) ///< dummy API operation
{
return val_+i;
}
int getVal() const { return val_; }
int
getVal() const
{
return val_;
}
void
setVal (int newVal)

View file

@ -95,7 +95,7 @@ namespace lib {
private:
TAR*
accessChecked()
accessChecked() const
{
TAR *p(get());
if (!p)

View file

@ -115,7 +115,7 @@ namespace time {
namespace mutation {
using boost::disable_if;
using lumiera::typelist::is_sameType;
using lib::meta::is_sameType;
using std::tr1::placeholders::_1;
using std::tr1::function;
using std::tr1::bind;

View file

@ -162,9 +162,9 @@ namespace time {
/* == Descriptor to define Support for specific formats == */
using lumiera::typelist::Types;
using lumiera::typelist::Node;
using lumiera::typelist::NullType;
using lib::meta::Types;
using lib::meta::Node;
using lib::meta::NullType;
/**
* Descriptor to denote support for a specific (timecode) format.
@ -187,7 +187,7 @@ namespace time {
std::bitset<MAXID> flags_;
template<class F>
size_t
IxID
typeID() const
{
return TypedContext<Supported>::ID<F>::get();

View file

@ -46,7 +46,7 @@ namespace time {
* grid point, usable for grid aligning values.
*
* \par usage
* For one there is the lib::time::Quantiser, which directly
* First off, there is the lib::time::Quantiser, which directly
* implements this interface and plays a central role when it comes
* to converting continuous time into any kind of frame based timecode.
* Besides that, the session stores asset::TimeGrid definitions, which

View file

@ -41,6 +41,9 @@ namespace time {
const Time Time::MIN ( TimeValue::buildRaw_(-_raw(Time::MAX) ) );
const Time Time::ZERO;
const Time Time::ANYTIME(Time::MAX);
const Time Time::NEVER (Time::MIN);
const Offset Offset::ZERO (Time::ZERO);

Some files were not shown because too many files have changed in this diff Show more