diff options
Diffstat (limited to 'include')
35 files changed, 5662 insertions, 0 deletions
diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..242b83d --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = ixion + diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..7797335 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,666 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ +BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ +BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ +BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ +BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX17 = @HAVE_CXX17@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IXION_API_VERSION = @IXION_API_VERSION@ +IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ +IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ +IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ +IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ +IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ +IXION_VERSION = @IXION_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MDDS_CFLAGS = @MDDS_CFLAGS@ +MDDS_LIBS = @MDDS_LIBS@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POW_LIB = @POW_LIB@ +PYTHON = @PYTHON@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VULKAN_CFLAGS = @VULKAN_CFLAGS@ +VULKAN_LIBS = @VULKAN_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = ixion +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/ixion/Makefile.am b/include/ixion/Makefile.am new file mode 100644 index 0000000..364bd6a --- /dev/null +++ b/include/ixion/Makefile.am @@ -0,0 +1,31 @@ +SUBDIRS = interface + +libixiondir = $(includedir)/libixion-@IXION_API_VERSION@/ixion +libixion_HEADERS = \ + address.hpp \ + address_iterator.hpp \ + cell.hpp \ + cell_access.hpp \ + compute_engine.hpp \ + config.hpp \ + dirty_cell_tracker.hpp \ + document.hpp \ + env.hpp \ + exceptions.hpp \ + formula_function_opcode.hpp \ + formula.hpp \ + formula_name_resolver.hpp \ + formula_opcode.hpp \ + formula_result.hpp \ + formula_tokens.hpp \ + formula_tokens_fwd.hpp \ + global.hpp \ + info.hpp \ + macros.hpp \ + matrix.hpp \ + model_context.hpp \ + model_iterator.hpp \ + module.hpp \ + named_expressions_iterator.hpp \ + table.hpp \ + types.hpp diff --git a/include/ixion/Makefile.in b/include/ixion/Makefile.in new file mode 100644 index 0000000..faab7a8 --- /dev/null +++ b/include/ixion/Makefile.in @@ -0,0 +1,752 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include/ixion +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(libixion_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libixiondir)" +HEADERS = $(libixion_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ +BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ +BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ +BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ +BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX17 = @HAVE_CXX17@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IXION_API_VERSION = @IXION_API_VERSION@ +IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ +IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ +IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ +IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ +IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ +IXION_VERSION = @IXION_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MDDS_CFLAGS = @MDDS_CFLAGS@ +MDDS_LIBS = @MDDS_LIBS@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POW_LIB = @POW_LIB@ +PYTHON = @PYTHON@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VULKAN_CFLAGS = @VULKAN_CFLAGS@ +VULKAN_LIBS = @VULKAN_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = interface +libixiondir = $(includedir)/libixion-@IXION_API_VERSION@/ixion +libixion_HEADERS = \ + address.hpp \ + address_iterator.hpp \ + cell.hpp \ + cell_access.hpp \ + compute_engine.hpp \ + config.hpp \ + dirty_cell_tracker.hpp \ + document.hpp \ + env.hpp \ + exceptions.hpp \ + formula_function_opcode.hpp \ + formula.hpp \ + formula_name_resolver.hpp \ + formula_opcode.hpp \ + formula_result.hpp \ + formula_tokens.hpp \ + formula_tokens_fwd.hpp \ + global.hpp \ + info.hpp \ + macros.hpp \ + matrix.hpp \ + model_context.hpp \ + model_iterator.hpp \ + module.hpp \ + named_expressions_iterator.hpp \ + table.hpp \ + types.hpp + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/ixion/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/ixion/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-libixionHEADERS: $(libixion_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libixion_HEADERS)'; test -n "$(libixiondir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libixiondir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libixiondir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libixiondir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libixiondir)" || exit $$?; \ + done + +uninstall-libixionHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libixion_HEADERS)'; test -n "$(libixiondir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libixiondir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libixiondir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-libixionHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-libixionHEADERS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libixionHEADERS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libixionHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/ixion/address.hpp b/include/ixion/address.hpp new file mode 100644 index 0000000..aed09a2 --- /dev/null +++ b/include/ixion/address.hpp @@ -0,0 +1,347 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_ADDRESS_HPP +#define INCLUDED_IXION_ADDRESS_HPP + +#include "types.hpp" + +#include <string> +#include <vector> +#include <ostream> +#include <unordered_set> + +namespace ixion { + +/** + * Row address not specified. This is used to reference an entire column + * when a specific column address is given. + */ +IXION_DLLPUBLIC_VAR const row_t row_unset; + +/** + * Highest number that can be used to reference a row address. Numbers + * higher than this number are all used as special indices. + */ +IXION_DLLPUBLIC_VAR const row_t row_upper_bound; + +/** + * Column address not specified. This is used to reference an entire row + * when a specific row address is given. + */ +IXION_DLLPUBLIC_VAR const col_t column_unset; + +/** + * Highest number that can be used to reference a column address. Numbers + * higher than this number are all used as special indices. + */ +IXION_DLLPUBLIC_VAR const col_t column_upper_bound; + +/** + * Stores absolute address, and absolute address only. + */ +struct IXION_DLLPUBLIC abs_address_t +{ + enum init_invalid { invalid }; + + sheet_t sheet; + row_t row; + col_t column; + + abs_address_t(); + abs_address_t(init_invalid); + abs_address_t(sheet_t _sheet, row_t _row, col_t _column); + abs_address_t(const abs_address_t& r); + + bool valid() const; + ::std::string get_name() const; + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const abs_address_t& addr) const; + }; +}; + +IXION_DLLPUBLIC bool operator==(const abs_address_t& left, const abs_address_t& right); +IXION_DLLPUBLIC bool operator!=(const abs_address_t& left, const abs_address_t& right); +IXION_DLLPUBLIC bool operator<(const abs_address_t& left, const abs_address_t& right); + +/** + * Stores either absolute or relative address. + */ +struct IXION_DLLPUBLIC address_t +{ + sheet_t sheet; + row_t row; + col_t column; + bool abs_sheet:1; + bool abs_row:1; + bool abs_column:1; + + address_t(); + address_t(sheet_t _sheet, row_t _row, col_t _column, + bool _abs_sheet=true, bool _abs_row=true, bool _abs_column=true); + address_t(const address_t& r); + address_t(const abs_address_t& r); + + bool valid() const; + abs_address_t to_abs(const abs_address_t& origin) const; + ::std::string get_name() const; + + void set_absolute(bool abs); + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const address_t& addr) const; + }; +}; + +IXION_DLLPUBLIC bool operator==(const address_t& left, const address_t& right); +IXION_DLLPUBLIC bool operator!=(const address_t& left, const address_t& right); +IXION_DLLPUBLIC bool operator<(const address_t& left, const address_t& right); + +struct IXION_DLLPUBLIC abs_rc_address_t +{ + enum init_invalid { invalid }; + + row_t row; + col_t column; + + abs_rc_address_t(); + abs_rc_address_t(init_invalid); + abs_rc_address_t(row_t _row, col_t _column); + abs_rc_address_t(const abs_rc_address_t& r); + abs_rc_address_t(const abs_address_t& r); + + bool valid() const; + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const abs_rc_address_t& addr) const; + }; +}; + +IXION_DLLPUBLIC bool operator==(const abs_rc_address_t& left, const abs_rc_address_t& right); +IXION_DLLPUBLIC bool operator!=(const abs_rc_address_t& left, const abs_rc_address_t& right); +IXION_DLLPUBLIC bool operator<(const abs_rc_address_t& left, const abs_rc_address_t& right); + +/** + * Stores either absolute or relative address, but unlike the address_t + * counterpart, this struct only stores row and column positions. + */ +struct IXION_DLLPUBLIC rc_address_t +{ + row_t row; + col_t column; + bool abs_row:1; + bool abs_column:1; + + rc_address_t(); + rc_address_t(row_t _row, col_t _column, bool _abs_row=true, bool _abs_column=true); + rc_address_t(const rc_address_t& r); + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const rc_address_t& addr) const; + }; +}; + +/** + * Stores absolute range address. + */ +struct IXION_DLLPUBLIC abs_range_t +{ + enum init_invalid { invalid }; + + abs_address_t first; + abs_address_t last; + + abs_range_t(); + abs_range_t(init_invalid); + abs_range_t(sheet_t _sheet, row_t _row, col_t _col); + + /** + * @param _sheet 0-based sheet index. + * @param _row 0-based row position of the top-left cell of the range. + * @param _col 0-based column position of the top-left cell of the range. + * @param _row_span row length of the range. It must be 1 or greater. + * @param _col_span column length of the range. It must be 1 or greater. + */ + abs_range_t(sheet_t _sheet, row_t _row, col_t _col, row_t _row_span, col_t _col_span); + abs_range_t(const abs_address_t& addr); + abs_range_t(const abs_address_t& addr, row_t row_span, col_t col_span); + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const abs_range_t& range) const; + }; + + bool valid() const; + + /** + * Expand the range horizontally to include all columns. The row range + * will remain unchanged. + */ + void set_all_columns(); + + /** + * Expand the range vertically to include all rows. The column range will + * remain unchanged. + */ + void set_all_rows(); + + /** + * @return true if the range is unspecified in the horizontal direction + * i.e. all columns are selected, false otherwise. + */ + bool all_columns() const; + + /** + * @return true if the range is unspecified in the vertical direction i.e. + * all rows are selected, false otherwise. + */ + bool all_rows() const; + + /** + * Check whether or not a given address is contained within this range. + */ + bool contains(const abs_address_t& addr) const; + + /** + * Reorder range values as needed to ensure the range is valid. + */ + void reorder(); +}; + +IXION_DLLPUBLIC bool operator==(const abs_range_t& left, const abs_range_t& right); +IXION_DLLPUBLIC bool operator!=(const abs_range_t& left, const abs_range_t& right); +IXION_DLLPUBLIC bool operator<(const abs_range_t& left, const abs_range_t& right); + +struct IXION_DLLPUBLIC abs_rc_range_t +{ + enum init_invalid { invalid }; + + abs_rc_address_t first; + abs_rc_address_t last; + + abs_rc_range_t(); + abs_rc_range_t(init_invalid); + abs_rc_range_t(const abs_rc_range_t& other); + abs_rc_range_t(const abs_range_t& other); + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const abs_rc_range_t& range) const; + }; + + bool valid() const; + + /** + * Expand the range horizontally to include all columns. The row range + * will remain unchanged. + */ + void set_all_columns(); + + /** + * Expand the range vertically to include all rows. The column range will + * remain unchanged. + */ + void set_all_rows(); + + /** + * @return true if the range is unspecified in the horizontal direction + * i.e. all columns are selected, false otherwise. + */ + bool all_columns() const; + + /** + * @return true if the range is unspecified in the vertical direction i.e. + * all rows are selected, false otherwise. + */ + bool all_rows() const; + + /** + * Check whether or not a given address is contained within this range. + */ + bool contains(const abs_rc_address_t& addr) const; +}; + +IXION_DLLPUBLIC bool operator==(const abs_rc_range_t& left, const abs_rc_range_t& right); +IXION_DLLPUBLIC bool operator!=(const abs_rc_range_t& left, const abs_rc_range_t& right); +IXION_DLLPUBLIC bool operator<(const abs_rc_range_t& left, const abs_rc_range_t& right); + +/** + * Stores range whose component may be relative or absolute. + */ +struct IXION_DLLPUBLIC range_t +{ + address_t first; + address_t last; + + range_t(); + range_t(const address_t& _first, const address_t& _last); + range_t(const range_t& r); + range_t(const abs_range_t& r); + + bool valid() const; + + /** + * Expand the range horizontally to include all columns. The row range + * will remain unchanged. + */ + void set_all_columns(); + + /** + * Expand the range vertically to include all rows. The column range will + * remain unchanged. + */ + void set_all_rows(); + + /** + * @return true if the range is unspecified in the horizontal direction + * i.e. all columns are selected, false otherwise. + */ + bool all_columns() const; + + /** + * @return true if the range is unspecified in the vertical direction i.e. + * all rows are selected, false otherwise. + */ + bool all_rows() const; + + abs_range_t to_abs(const abs_address_t& origin) const; + + void set_absolute(bool abs); + + struct hash + { + IXION_DLLPUBLIC size_t operator() (const range_t& range) const; + }; +}; + +IXION_DLLPUBLIC bool operator==(const range_t& left, const range_t& right); +IXION_DLLPUBLIC bool operator!=(const range_t& left, const range_t& right); + +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_address_t& addr); +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_rc_address_t& addr); +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const address_t& addr); +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_range_t& range); +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_rc_range_t& range); +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const range_t& range); + +/** + * Type that represents a collection of multiple absolute cell addresses. + */ +using abs_address_set_t = std::unordered_set<abs_address_t, abs_address_t::hash>; +using abs_range_set_t = std::unordered_set<abs_range_t, abs_range_t::hash>; +using abs_rc_range_set_t = std::unordered_set<abs_rc_range_t, abs_rc_range_t::hash>; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/address_iterator.hpp b/include/ixion/address_iterator.hpp new file mode 100644 index 0000000..9250444 --- /dev/null +++ b/include/ixion/address_iterator.hpp @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_ADDRESS_ITERATOR_HPP +#define INCLUDED_IXION_ADDRESS_ITERATOR_HPP + +#include "types.hpp" + +#include <memory> + +namespace ixion { + +struct abs_range_t; +struct abs_address_t; + +class IXION_DLLPUBLIC abs_address_iterator +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + class IXION_DLLPUBLIC const_iterator + { + friend class abs_address_iterator; + + struct impl_node; + std::unique_ptr<impl_node> mp_impl; + + const_iterator(const abs_range_t& range, rc_direction_t dir, bool end); + public: + using value_type = abs_address_t; + + const_iterator(); + const_iterator(const const_iterator& r); + const_iterator(const_iterator&& r); + ~const_iterator(); + + const_iterator& operator++(); + const_iterator operator++(int); + const_iterator& operator--(); + const_iterator operator--(int); + + const value_type& operator*() const; + const value_type* operator->() const; + + bool operator== (const const_iterator& r) const; + bool operator!= (const const_iterator& r) const; + }; + + abs_address_iterator(const abs_range_t& range, rc_direction_t dir); + ~abs_address_iterator(); + + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/cell.hpp b/include/ixion/cell.hpp new file mode 100644 index 0000000..59f09bb --- /dev/null +++ b/include/ixion/cell.hpp @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_CELL_HPP +#define INCLUDED_IXION_CELL_HPP + +#include "types.hpp" +#include "formula_tokens_fwd.hpp" + +#include <memory> +#include <vector> +#include <string> + +namespace ixion { + +class formula_result; +class formula_cell; +class model_context; +struct abs_address_t; +struct rc_address_t; + +// calc_status is internal. +struct calc_status; +using calc_status_ptr_t = boost::intrusive_ptr<calc_status>; + +class IXION_DLLPUBLIC formula_cell +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + formula_cell(const formula_cell&) = delete; + formula_cell& operator= (formula_cell) = delete; + + formula_cell(); + formula_cell(const formula_tokens_store_ptr_t& tokens); + + formula_cell( + row_t group_row, col_t group_col, + const calc_status_ptr_t& cs, + const formula_tokens_store_ptr_t& tokens); + + ~formula_cell(); + + const formula_tokens_store_ptr_t& get_tokens() const; + void set_tokens(const formula_tokens_store_ptr_t& tokens); + + double get_value(formula_result_wait_policy_t policy) const; + std::string_view get_string(formula_result_wait_policy_t policy) const; + + void interpret(model_context& context, const abs_address_t& pos); + + /** + * Determine if this cell contains circular reference by walking through + * all its reference tokens. + */ + void check_circular(const model_context& cxt, const abs_address_t& pos); + + /** + * Reset cell's internal state. + */ + void reset(); + + /** + * Get a series of all reference tokens included in the formula + * expression stored in this cell. + * + * @param cxt model context instance. + * @param pos position of the cell. + * + * @return an array of reference formula tokens. Each element is a + * pointer to the actual token instance stored in the cell object. + * Be aware that the pointer is valid only as long as the actual + * token instance is alive. + */ + std::vector<const formula_token*> get_ref_tokens( + const model_context& cxt, const abs_address_t& pos) const; + + /** + * Get the cached result without post-processing in case of a grouped + * formula cell. + * + * @param policy action to take in case the result is not yet available. + * + * @return formula result. + */ + const formula_result& get_raw_result_cache(formula_result_wait_policy_t policy) const; + + /** + * Get the cached result as a single cell. For a non-grouped formula + * cell, it should be identical to the value from the get_raw_result_cache() + * call. For a grouped formula cell, you'll get a single value assigned to + * the position of the cell in case the original result is a matrix value. + * + * @param policy action to take in case the result is not yet available. + * + * @return formula result. + */ + formula_result get_result_cache(formula_result_wait_policy_t policy) const; + + /** + * Set a cached result to this formula cell instance. + * + * + * @param result cached result. + */ + void set_result_cache(formula_result result); + + formula_group_t get_group_properties() const; + + /** + * Get the absolute parent position of a grouped formula cell. If the + * cell is not grouped, it simply returns the original position passed to + * this method. + * + * @param pos original position from which to calculate the parent + * position. + * + * @return parent position of the grouped formula cell. + */ + abs_address_t get_parent_position(const abs_address_t& pos) const; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/cell_access.hpp b/include/ixion/cell_access.hpp new file mode 100644 index 0000000..63c5323 --- /dev/null +++ b/include/ixion/cell_access.hpp @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_CELL_ACCESS_HPP +#define INCLUDED_IXION_CELL_ACCESS_HPP + +#include "types.hpp" + +#include <memory> +#include <string> + +namespace ixion { + +class model_context; +class formula_cell; +class formula_result; +struct abs_address_t; + +/** + * This class provides a read-only access to a single cell. It's more + * efficient to use this class if you need to make multiple successive + * queries to the same cell. + * + * Note that an instance of this class will get invalidated when the content + * of ixion::model_context is modified. + */ +class IXION_DLLPUBLIC cell_access +{ + friend class model_context; + + struct impl; + std::unique_ptr<impl> mp_impl; + + cell_access(const model_context& cxt, const abs_address_t& addr); +public: + cell_access(cell_access&& other); + cell_access& operator= (cell_access&& other); + ~cell_access(); + + celltype_t get_type() const; + + cell_value_t get_value_type() const; + + const formula_cell* get_formula_cell() const; + + formula_result get_formula_result() const; + + double get_numeric_value() const; + + bool get_boolean_value() const; + + std::string_view get_string_value() const; + + string_id_t get_string_identifier() const; + + formula_error_t get_error_value() const; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/compute_engine.hpp b/include/ixion/compute_engine.hpp new file mode 100644 index 0000000..6e5bbd7 --- /dev/null +++ b/include/ixion/compute_engine.hpp @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_COMPUTE_ENGINE_HPP +#define INCLUDED_IXION_COMPUTE_ENGINE_HPP + +#include "env.hpp" +#include "module.hpp" + +#include <memory> +#include <string> + +namespace ixion { namespace draft { + +enum class array_type { unknown, float32, float64, uint32 }; + +struct array +{ + union + { + float* float32; + double* float64; + uint32_t* uint32; + void* data; + }; + + array_type type = array_type::unknown; + std::size_t size = 0u; +}; + +/** + * Default compute engine class that uses CPU for all its computations. + * + * <p>This class also serves as the fallback for its child classes in case + * they don't support the function being requested or the function doesn't + * meet the criteria that it requires.</p> + * + * <p>Each function of this class should not modify the state of the class + * instance.</p> + */ +class IXION_DLLPUBLIC compute_engine +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + /** + * Create a compute engine instance. + * + * @param name name of the compute engine, or an empty name for the default + * one. + * + * @return compute engine instance associted with the specified name. Note + * that if no compute engine is registered with the specified + * name, the default one is created. + */ + static std::shared_ptr<compute_engine> create(std::string_view name = std::string_view()); + + /** + * Add a new compute engine class. + * + * @param hdl handler for the dynamically-loaded module in which the + * compute engine being registered resides. + * @param name name of the compute engine. + * @param func_create function that creates a new instance of this compute + * engine class. + * @param func_destroy function that destroyes the instance of this + * compute engine class. + */ + static void add_class( + void* hdl, std::string_view name, create_compute_engine_t func_create, destroy_compute_engine_t func_destroy); + + compute_engine(); + virtual ~compute_engine(); + + virtual std::string_view get_name() const; + + virtual void compute_fibonacci(array& io); +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/config.hpp b/include/ixion/config.hpp new file mode 100644 index 0000000..9575ac3 --- /dev/null +++ b/include/ixion/config.hpp @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_CONFIG_HPP +#define INCLUDED_IXION_CONFIG_HPP + +#include "types.hpp" + +namespace ixion { + +/** + * This structure store parameters that influence various aspects of the + * ixion formula engine. + */ +struct IXION_DLLPUBLIC config +{ + /** + * Function argument separator. By default it's ','. + */ + char sep_function_arg; + + /** + * Matrix column separator. + */ + char sep_matrix_column; + + /** + * Matrix row separator. + */ + char sep_matrix_row; + + /** + * Precision to use when converting a numeric value to a string + * representation. A negative value indicates an unspecified precision. + */ + int8_t output_precision; + + config(); + config(const config& r); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/dirty_cell_tracker.hpp b/include/ixion/dirty_cell_tracker.hpp new file mode 100644 index 0000000..b701044 --- /dev/null +++ b/include/ixion/dirty_cell_tracker.hpp @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_DIRTY_CELL_TRACKER_HPP +#define INCLUDED_IXION_DIRTY_CELL_TRACKER_HPP + +#include "address.hpp" + +#include <memory> + +namespace ixion { + +/** + * This class is designed to track in-direct dependencies of dirty formula + * cells. A "dirty" formula cell is a formula cell whose result needs to be + * re-calculated because at least one of its references have their values + * updated. + * + * This class also takes volatile functions into account when determining + * the status of the formula cel result. A volatile function is a cell + * function whose value needs to get re-calculated unconditionally on every + * re-calculation. One example of a volatile function is NOW(), which + * returns the current time at the time of calculation. + */ +class IXION_DLLPUBLIC dirty_cell_tracker +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + dirty_cell_tracker(const dirty_cell_tracker&) = delete; + dirty_cell_tracker& operator= (const dirty_cell_tracker&) = delete; + + dirty_cell_tracker(); + ~dirty_cell_tracker(); + + /** + * Add a tracking relationship from a source cell or cell range to a + * destination cell or cell range. + * + * @param src source cell or cell range that includes reference to + * (therefore listens to) the range. + * @param dest destination cell or range referenced tracked by the source + * cell. + */ + void add(const abs_range_t& src, const abs_range_t& dest); + + /** + * Remove an existing tracking relationship from a source cell or cell + * range to a destination cell or cell range. If no such relationship + * exists, it does nothing. + * + * @param src cell or cell range that includes reference to the range. + * @param dest cell or range referenced by the cell. + */ + void remove(const abs_range_t& src, const abs_range_t& dest); + + /** + * Register a formula cell located at the specified position as volatile. + * Note that the caller should ensure that the cell at the specified + * position is indeed a formula cell. + * + * @param pos position of the cell to register as a volatile cell. + */ + void add_volatile(const abs_range_t& pos); + + /** + * Remove the specified cell position from the internal set of registered + * volatile formula cells. + * + * @param pos position of the cell to unregister as a volatile cell. + */ + void remove_volatile(const abs_range_t& pos); + + abs_range_set_t query_dirty_cells(const abs_range_t& modified_cell) const; + + abs_range_set_t query_dirty_cells(const abs_range_set_t& modified_cells) const; + + std::vector<abs_range_t> query_and_sort_dirty_cells(const abs_range_t& modified_cell) const; + + std::vector<abs_range_t> query_and_sort_dirty_cells( + const abs_range_set_t& modified_cells, const abs_range_set_t* dirty_formula_cells = nullptr) const; + + std::string to_string() const; + + bool empty() const; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/document.hpp b/include/ixion/document.hpp new file mode 100644 index 0000000..a612898 --- /dev/null +++ b/include/ixion/document.hpp @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_DOCUMENT_HPP +#define INCLUDED_IXION_DOCUMENT_HPP + +#include "types.hpp" +#include "address.hpp" + +#include <memory> +#include <string> +#include <variant> + +namespace ixion { + +class cell_access; + +/** + * Higher level document representation designed to handle both cell value + * storage as well as formula cell calculations. + */ +class IXION_DLLPUBLIC document +{ + struct impl; + std::unique_ptr<impl> mp_impl; +public: + document(); + + /** + * Constructor with custom cell address type. + * + * @param cell_address_type cell address type to use for cell addresses + * represented by string values. + */ + document(formula_name_resolver_t cell_address_type); + ~document(); + + struct IXION_DLLPUBLIC cell_pos + { + enum class cp_type { string, address }; + cp_type type; + + std::variant<std::string_view, ixion::abs_address_t> value; + + cell_pos(const char* p); + cell_pos(const char* p, size_t n); + cell_pos(const std::string& s); + cell_pos(const abs_address_t& addr); + }; + + void append_sheet(std::string name); + + /** + * Set a new name to an existing sheet. + * + * @param sheet 0-based sheet index. + * @param name New name of a sheet. + */ + void set_sheet_name(sheet_t sheet, std::string name); + + cell_access get_cell_access(cell_pos pos) const; + + void set_numeric_cell(cell_pos pos, double val); + + void set_string_cell(cell_pos pos, std::string_view s); + + void set_boolean_cell(cell_pos pos, bool val); + + void empty_cell(cell_pos pos); + + double get_numeric_value(cell_pos pos) const; + + std::string_view get_string_value(cell_pos pos) const; + + void set_formula_cell(cell_pos pos, std::string_view formula); + + /** + * Calculate all the "dirty" formula cells in the document. + * + * @param thread_count number of threads to use to perform calculation. + * When 0 is specified, it only uses the main thread. + */ + void calculate(size_t thread_count); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/env.hpp b/include/ixion/env.hpp new file mode 100644 index 0000000..c164a1d --- /dev/null +++ b/include/ixion/env.hpp @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_ENV_HPP +#define INCLUDED_IXION_ENV_HPP + +#if defined _WIN32 || defined __CYGWIN__ + #if defined __MINGW32__ + #define IXION_DLLPUBLIC + #define IXION_DLLPUBLIC_VAR extern + #elif defined IXION_BUILD + #ifdef DLL_EXPORT + #define IXION_DLLPUBLIC __declspec(dllexport) + #define IXION_DLLPUBLIC_VAR extern __declspec(dllexport) + #else + #define IXION_DLLPUBLIC + #define IXION_DLLPUBLIC_VAR extern + #endif + #else + #define IXION_DLLPUBLIC __declspec(dllimport) + #define IXION_DLLPUBLIC_VAR extern __declspec(dllimport) + #endif + #define IXION_DLLLOCAL +#else + #if defined __GNUC__ && __GNUC__ >= 4 + #define IXION_DLLPUBLIC __attribute__ ((visibility ("default"))) + #define IXION_DLLLOCAL __attribute__ ((visibility ("hidden"))) + #else + #define IXION_DLLPUBLIC + #define IXION_DLLLOCAL + #endif + #define IXION_DLLPUBLIC_VAR IXION_DLLPUBLIC extern +#endif + +#if _WIN32 +#define IXION_MOD_EXPORT __declspec(dllexport) +#else +#define IXION_MOD_EXPORT __attribute__ ((visibility ("default"))) +#endif + +#if defined(IXION_TRACE_ON) || defined(IXION_DEBUG_ON) +#define IXION_LOGGING 1 +#else +#define IXION_LOGGING 0 +#endif + +#ifdef __GNUC__ + #define IXION_DEPRECATED __attribute__ ((deprecated)) +#elif defined(_MSC_VER) + #define IXION_DEPRECATED __declspec(deprecated) +#else + #define IXION_DEPRECATED +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/exceptions.hpp b/include/ixion/exceptions.hpp new file mode 100644 index 0000000..bccceb1 --- /dev/null +++ b/include/ixion/exceptions.hpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_EXCEPTIONS_HPP +#define INCLUDED_IXION_EXCEPTIONS_HPP + +#include "env.hpp" +#include "types.hpp" + +#include <exception> +#include <string> +#include <memory> + +namespace ixion { + +class IXION_DLLPUBLIC general_error : public std::exception +{ +public: + general_error(); + explicit general_error(const std::string& msg); + virtual ~general_error(); + virtual const char* what() const noexcept override; + +protected: + void set_message(const std::string& msg); + +private: + std::string m_msg; +}; + +class IXION_DLLPUBLIC formula_error : public std::exception +{ + struct impl; + std::unique_ptr<impl> mp_impl; +public: + explicit formula_error(formula_error_t fe); + explicit formula_error(formula_error_t fe, std::string msg); + formula_error(formula_error&& other); + + virtual ~formula_error(); + virtual const char* what() const noexcept override; + + formula_error_t get_error() const; +}; + +class IXION_DLLPUBLIC file_not_found : public general_error +{ +public: + explicit file_not_found(const std::string& fpath); + virtual ~file_not_found() override; +}; + +class IXION_DLLPUBLIC formula_registration_error : public general_error +{ +public: + explicit formula_registration_error(const std::string& msg); + virtual ~formula_registration_error() override; +}; + +/** + * This exception is thrown typically from the ixion::model_context class. + */ +class IXION_DLLPUBLIC model_context_error: public general_error +{ +public: + enum error_type + { + circular_dependency, + invalid_named_expression, + sheet_name_conflict, + sheet_size_locked, + not_implemented + }; + + explicit model_context_error(const std::string& msg, error_type type); + virtual ~model_context_error() override; + + error_type get_error_type() const; + +private: + error_type m_type; +}; + +class IXION_DLLPUBLIC not_implemented_error : public general_error +{ +public: + explicit not_implemented_error(const std::string& msg); + virtual ~not_implemented_error() override; +}; + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula.hpp b/include/ixion/formula.hpp new file mode 100644 index 0000000..f15c72d --- /dev/null +++ b/include/ixion/formula.hpp @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_FORMULA_HPP +#define INCLUDED_IXION_FORMULA_HPP + +#include "formula_tokens.hpp" +#include "types.hpp" +#include "env.hpp" + +#include <string> + +namespace ixion { + +class formula_cell; +class formula_name_resolver; +class model_context; + +/** + * Parse a raw formula expression string into formula tokens. + * + * @param cxt model context. + * @param pos address of the cell that has the formula expression. + * @param resolver name resolver object used to resolve name tokens. + * @param formula raw formula expression string to parse. + * + * @return formula tokens representing the parsed formula expression. + */ +IXION_DLLPUBLIC formula_tokens_t parse_formula_string( + model_context& cxt, const abs_address_t& pos, + const formula_name_resolver& resolver, std::string_view formula); + +/** + * Create a set of tokens that represent an invalid formula. + * + * This can be used for a cell containing an invalid formula expression, and + * the error information needs to be preserved. + * + * @param cxt model context. + * @param src_formula original formula string. + * @param error error string. + * + * @return a set of tokens, the first of which is a token of type fop_error, + * followed by two string tokens. The second token stores the + * original formula string, whereas the third one stores the error + * string. The first token stores the number of tokens that follows + * as its value of type std::size_t, which is always 2 in the current + * implementation. + */ +IXION_DLLPUBLIC formula_tokens_t create_formula_error_tokens( + model_context& cxt, std::string_view src_formula, + std::string_view error); + +/** + * Convert formula tokens into a human-readable string representation. + * + * @param cxt model context. + * @param pos address of the cell that has the formula tokens. + * @param resolver name resolver object used to print name tokens. + * @param tokens formula tokens. + * + * @return string representation of the formula tokens. + */ +IXION_DLLPUBLIC std::string print_formula_tokens( + const model_context& cxt, const abs_address_t& pos, + const formula_name_resolver& resolver, const formula_tokens_t& tokens); + +/** + * Convert formula tokens into a human-readable string representation. + * + * @param config Configuration options for printing preferences. + * @param cxt Model context. + * @param pos Address of the cell that has the formula tokens. + * @param resolver Name resolver object used to print name tokens. + * @param tokens Formula tokens to print. + * + * @return string representation of the formula tokens. + */ +IXION_DLLPUBLIC std::string print_formula_tokens( + const print_config& config, const model_context& cxt, const abs_address_t& pos, + const formula_name_resolver& resolver, const formula_tokens_t& tokens); + +/** + * Convert an individual formula token into a human-readable string + * representation. + * + * @param cxt model context. + * @param pos address of the cell that has the formula tokens. + * @param resolver name resolver object used to print name tokens. + * @param token formula token to convert. + * + * @return string representation of the formula token. + */ +IXION_DLLPUBLIC std::string print_formula_token( + const model_context& cxt, const abs_address_t& pos, + const formula_name_resolver& resolver, const formula_token& token); + +/** + * Convert an individual formula token into a human-readable string + * representation. + * + * @param config Configuration options for printing preferences. + * @param cxt Model context. + * @param pos Address of the cell that has the formula tokens. + * @param resolver Name resolver object used to print name tokens. + * @param token Formula token to convert. + * + * @return string representation of the formula token. + */ +IXION_DLLPUBLIC std::string print_formula_token( + const print_config& config, const model_context& cxt, const abs_address_t& pos, + const formula_name_resolver& resolver, const formula_token& token); + +/** + * Regisiter a formula cell with cell dependency tracker. + * + * @param cxt model context. + * @param pos address of the cell being registered. In case of grouped + * cells, the position must be that of teh top-left cell of that + * group. + * @param cell (optional) pointer to the formula cell object to register. + * You can skip this parameter, in which case the formula cell + * object will be fetched from the address of the cell. But + * passing a pointer will save the overhead of fetching. + */ +void IXION_DLLPUBLIC register_formula_cell( + model_context& cxt, const abs_address_t& pos, const formula_cell* cell = nullptr); + +/** + * Unregister a formula cell with cell dependency tracker if a formula cell + * exists at specified cell address. If there is no existing cell at the + * specified address, or the cell is not a formula cell, this function is a + * no-op. + * + * @param cxt model context. + * @param pos address of the cell being unregistered. + */ +void IXION_DLLPUBLIC unregister_formula_cell( + model_context& cxt, const abs_address_t& pos); + +/** + * Get the positions of those formula cells that directly or indirectly + * depend on the specified source cells. + * + * @param cxt model context. + * @param modified_cells collection of the postiions of cells that have been + * modified. + * + * @return collection of the positions of formula cells that directly or + * indirectly depend on at least one of the specified source cells. + */ +IXION_DLLPUBLIC abs_address_set_t query_dirty_cells( + model_context& cxt, const abs_address_set_t& modified_cells); + +/** + * Get a sequence of the positions of all formula cells that track at least + * one of the specified modified cells either directly or indirectly. Such + * formula cells are referred to as "dirty" formula cells. The sequence + * returned from this function is already sorted in topological order based + * on the dependency relationships between the affected formula cells. Note + * that if the model contains volatile formula cells, they will be included + * in the returned sequence each and every time. + * + * Use query_dirty_cells() instead if you don't need the results to be sorted + * in order of dependency, to avoid the extra overhead incurred by the + * sorting. + * + * @param cxt model context. + * @param modified_cells a collection of non-formula cells whose values have + * been updated. You can specify one or more ranges + * of cells rather than individual cell positions. + * @param dirty_formula_cells (optional) a collection of formula cells that + * are already known to be dirty. These formula + * cells will be added to the list of the + * affected formula cells returned from this + * function. Note that even though this + * parameter is a set of cell ranges, regular + * formula cell positions must be given as single + * cell addresses. Only the positions of grouped + * formula cells must be given as ranges. + * + * @return an sequence containing the positions of the formula cells that + * track at least one of the modified cells, as well as those + * formula cells that are already known to be dirty. + */ +IXION_DLLPUBLIC std::vector<abs_range_t> query_and_sort_dirty_cells( + model_context& cxt, const abs_range_set_t& modified_cells, + const abs_range_set_t* dirty_formula_cells = nullptr); + +/** + * Calculate all specified formula cells in the order they occur in the + * sequence. + * + * @param cxt model context. + * @param formula_cells formula cells to be calculated. The cells will be + * calculated in the order they appear in the sequence. + * In a typical use case, this will be the returned + * value from query_and_sort_dirty_cells. + * @param thread_count number of calculation threads to use. Note that + * passing 0 will make the process use the main thread + * only, while passing any number greater than 0 will + * make the process spawn specified number of + * calculation threads plus one additional thread to + * manage the calculation threads. + */ +void IXION_DLLPUBLIC calculate_sorted_cells( + model_context& cxt, const std::vector<abs_range_t>& formula_cells, size_t thread_count); + +} // namespace ixion + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula_function_opcode.hpp b/include/ixion/formula_function_opcode.hpp new file mode 100644 index 0000000..ddfabc3 --- /dev/null +++ b/include/ixion/formula_function_opcode.hpp @@ -0,0 +1,370 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_FORMULA_FUNCTION_OPCODE_HPP +#define INCLUDED_IXION_FORMULA_FUNCTION_OPCODE_HPP + +#include "env.hpp" + +#include <cstdint> +#include <string_view> + +namespace ixion { + +/** + * Enum that represents built-in formula functions. + */ +enum class formula_function_t : uint16_t +{ + func_unknown = 0, + func_abs, + func_acos, + func_acosh, + func_acot, + func_acoth, + func_address, + func_aggregate, + func_and, + func_arabic, + func_areas, + func_asc, + func_asin, + func_asinh, + func_atan, + func_atan2, + func_atanh, + func_avedev, + func_average, + func_averagea, + func_averageif, + func_averageifs, + func_b, + func_bahttext, + func_base, + func_betadist, + func_betainv, + func_binomdist, + func_bitand, + func_bitlshift, + func_bitor, + func_bitrshift, + func_bitxor, + func_ceiling, + func_cell, + func_char, + func_chidist, + func_chiinv, + func_chisqdist, + func_chisqinv, + func_chitest, + func_choose, + func_clean, + func_code, + func_color, + func_column, + func_columns, + func_combin, + func_combina, + func_concat, + func_concatenate, + func_confidence, + func_correl, + func_cos, + func_cosh, + func_cot, + func_coth, + func_count, + func_counta, + func_countblank, + func_countif, + func_countifs, + func_covar, + func_critbinom, + func_csc, + func_csch, + func_cumipmt, + func_cumprinc, + func_current, + func_date, + func_datedif, + func_datevalue, + func_daverage, + func_day, + func_days, + func_days360, + func_db, + func_dcount, + func_dcounta, + func_ddb, + func_dde, + func_decimal, + func_degrees, + func_devsq, + func_dget, + func_dmax, + func_dmin, + func_dollar, + func_dproduct, + func_dstdev, + func_dstdevp, + func_dsum, + func_dvar, + func_dvarp, + func_eastersunday, + func_effect, + func_encodeurl, + func_errortype, + func_euroconvert, + func_even, + func_exact, + func_exp, + func_expondist, + func_fact, + func_false, + func_fdist, + func_filterxml, + func_find, + func_findb, + func_finv, + func_fisher, + func_fisherinv, + func_fixed, + func_floor, + func_forecast, + func_formula, + func_fourier, + func_frequency, + func_ftest, + func_fv, + func_gamma, + func_gammadist, + func_gammainv, + func_gammaln, + func_gauss, + func_gcd, + func_geomean, + func_getpivotdata, + func_goalseek, + func_growth, + func_harmean, + func_hlookup, + func_hour, + func_hyperlink, + func_hypgeomdist, + func_if, + func_iferror, + func_ifna, + func_ifs, + func_index, + func_indirect, + func_info, + func_int, + func_intercept, + func_ipmt, + func_irr, + func_isblank, + func_iserr, + func_iserror, + func_iseven, + func_isformula, + func_islogical, + func_isna, + func_isnontext, + func_isnumber, + func_isodd, + func_isoweeknum, + func_ispmt, + func_isref, + func_istext, + func_jis, + func_kurt, + func_large, + func_lcm, + func_left, + func_leftb, + func_len, + func_lenb, + func_linest, + func_ln, + func_log, + func_log10, + func_logest, + func_loginv, + func_lognormdist, + func_lookup, + func_lower, + func_match, + func_max, + func_maxa, + func_maxifs, + func_mdeterm, + func_median, + func_mid, + func_midb, + func_min, + func_mina, + func_minifs, + func_minute, + func_minverse, + func_mirr, + func_mmult, + func_mod, + func_mode, + func_month, + func_multirange, + func_munit, + func_mvalue, + func_n, + func_na, + func_neg, + func_negbinomdist, + func_networkdays, + func_nominal, + func_normdist, + func_norminv, + func_normsdist, + func_normsinv, + func_not, + func_now, + func_nper, + func_npv, + func_numbervalue, + func_odd, + func_offset, + func_or, + func_pduration, + func_pearson, + func_percentile, + func_percentrank, + func_permut, + func_permutationa, + func_phi, + func_pi, + func_pmt, + func_poisson, + func_power, + func_ppmt, + func_prob, + func_product, + func_proper, + func_pv, + func_quartile, + func_radians, + func_rand, + func_rank, + func_rate, + func_rawsubtract, + func_regex, + func_replace, + func_replaceb, + func_rept, + func_right, + func_rightb, + func_roman, + func_round, + func_rounddown, + func_roundsig, + func_roundup, + func_row, + func_rows, + func_rri, + func_rsq, + func_search, + func_searchb, + func_sec, + func_sech, + func_second, + func_sheet, + func_sheets, + func_sign, + func_sin, + func_sinh, + func_skew, + func_skewp, + func_sln, + func_slope, + func_small, + func_sqrt, + func_standardize, + func_stdev, + func_stdeva, + func_stdevp, + func_stdevpa, + func_steyx, + func_style, + func_substitute, + func_subtotal, + func_sum, + func_sumif, + func_sumifs, + func_sumproduct, + func_sumsq, + func_sumx2my2, + func_sumx2py2, + func_sumxmy2, + func_switch, + func_syd, + func_t, + func_tan, + func_tanh, + func_tdist, + func_text, + func_textjoin, + func_time, + func_timevalue, + func_tinv, + func_today, + func_transpose, + func_trend, + func_trim, + func_trimmean, + func_true, + func_trunc, + func_ttest, + func_type, + func_unichar, + func_unicode, + func_upper, + func_value, + func_var, + func_vara, + func_varp, + func_varpa, + func_vdb, + func_vlookup, + func_wait, + func_webservice, + func_weekday, + func_weeknum, + func_weibull, + func_xor, + func_year, + func_ztest, +}; + +/** + * Get a string representation of a formula function opcode. + * + * @param func formula function opcode. + * + * @return string representation of the opcode. + */ +IXION_DLLPUBLIC std::string_view get_formula_function_name(formula_function_t func); + +/** + * Get a formula function opcode from a formula function name. + * + * @param s formula function name. + * + * @return formula function opcode representing the specified name. + */ +IXION_DLLPUBLIC formula_function_t get_formula_function_opcode(std::string_view s); + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula_name_resolver.hpp b/include/ixion/formula_name_resolver.hpp new file mode 100644 index 0000000..eb2a8a9 --- /dev/null +++ b/include/ixion/formula_name_resolver.hpp @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_FORMULA_NAME_RESOLVER_HPP +#define INCLUDED_IXION_FORMULA_NAME_RESOLVER_HPP + +#include "address.hpp" +#include "formula_function_opcode.hpp" + +#include <string> +#include <memory> +#include <variant> + +namespace ixion { + +class model_context; +struct table_t; + +/** + * Structure that represents the type of a 'name' in a formula expression. + * + * A name can be either one of: + * <ul> + * <li>cell reference</li> + * <li>range reference</li> + * <li>table reference</li> + * <li>named expression</li> + * <li>function</li> + * </ul> + */ +struct IXION_DLLPUBLIC formula_name_t +{ + enum name_type + { + invalid = 0, + cell_reference, + range_reference, + table_reference, + named_expression, + function + }; + + /** + * Table information for a table reference name. Unlike the ixion::table_t + * counterpart, we store strings as string views as the resolver doesn't + * have access to the string pool. + */ + struct table_type + { + std::string_view name; + std::string_view column_first; + std::string_view column_last; + table_areas_t areas; + }; + + using value_type = std::variant<address_t, range_t, table_type, formula_function_t>; + + name_type type; + value_type value; + + formula_name_t(); + + /** + * Return a string that represents the data stored internally. Useful for + * debugging. + */ + std::string to_string() const; +}; + +/** + * Formula name resolvers resolves a name in a formula expression to a more + * concrete name type. + */ +class formula_name_resolver +{ +public: + formula_name_resolver(); + virtual ~formula_name_resolver() = 0; + + /** + * Parse and resolve a reference string. + * + * @param s reference string to be parsed. + * @param pos base cell position, which influences the resolved reference + * position(s) containing relative address(es). When the + * reference string does not contain an explicit sheet name, + * the sheet address of the base cell position is used. + * + * @return result of the resovled reference. + */ + virtual formula_name_t resolve(std::string_view s, const abs_address_t& pos) const = 0; + virtual std::string get_name(const address_t& addr, const abs_address_t& pos, bool sheet_name) const = 0; + virtual std::string get_name(const range_t& range, const abs_address_t& pos, bool sheet_name) const = 0; + virtual std::string get_name(const table_t& table) const = 0; + + /** + * Given a numerical representation of column position, return its + * textural representation. + * + * @param col numerical column position. + * + * @return textural representation of column position. + */ + virtual std::string get_column_name(col_t col) const = 0; + + /** + * Create a formula name resolver instance according to the requested + * type. + * + * @param type type formula name resolver being requested. + * @param cxt document model context for resolving sheet names, or nullptr + * in case names being resolved don't contain sheet names. + * + * @return formula name resolver instance created on the heap. The caller + * is responsible for managing its life cycle. + */ + IXION_DLLPUBLIC static std::unique_ptr<formula_name_resolver> + get(formula_name_resolver_t type, const model_context* cxt); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula_opcode.hpp b/include/ixion/formula_opcode.hpp new file mode 100644 index 0000000..1f3d71b --- /dev/null +++ b/include/ixion/formula_opcode.hpp @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_FORMULA_OPCODE_HPP +#define INCLUDED_IXION_FORMULA_OPCODE_HPP + +namespace ixion { + +/** formula opcode type */ +enum fopcode_t +{ + fop_unknown = 0, + + // data types + fop_single_ref, + fop_range_ref, + fop_table_ref, + fop_named_expression, + fop_string, + fop_value, + fop_function, + + // arithmetic operators + fop_plus, + fop_minus, + fop_divide, + fop_multiply, + fop_exponent, + + // string operators + fop_concat, + + // relational operators + fop_equal, + fop_not_equal, + fop_less, + fop_greater, + fop_less_equal, + fop_greater_equal, + + // parentheses, separators + fop_open, + fop_close, + fop_sep, + fop_array_row_sep, + fop_array_open, + fop_array_close, + + // special conditions + fop_error, //< used to signify a special set of tokens representing formula cell with error. +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula_result.hpp b/include/ixion/formula_result.hpp new file mode 100644 index 0000000..551af18 --- /dev/null +++ b/include/ixion/formula_result.hpp @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_FORMULA_RESULT_HPP +#define INCLUDED_IXION_FORMULA_RESULT_HPP + +#include "global.hpp" + +#include <string> +#include <memory> +#include <iosfwd> + +namespace ixion { + +class matrix; +class model_context; + +/** + * Store formula result which may be either numeric, textural, or error. In + * case the result is textural, it owns the instance of the string. + */ +class IXION_DLLPUBLIC formula_result +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + enum class result_type { boolean, value, string, error, matrix }; + + formula_result(); + formula_result(const formula_result& r); + formula_result(formula_result&& r); + formula_result(bool b); + formula_result(double v); + formula_result(std::string str); + formula_result(formula_error_t e); + formula_result(matrix mtx); + ~formula_result(); + + void reset(); + void set_boolean(bool b); + void set_value(double v); + void set_string_value(std::string str); + void set_error(formula_error_t e); + void set_matrix(matrix mtx); + + /** + * Get a boolean result value. The caller must make sure the result is of + * boolean type, else the behavior is undefined. + * + * @return boolean result value. + */ + bool get_boolean() const; + + /** + * Get a numeric result value. The caller must make sure the result is of + * numeric type, else the behavior is undefined. + * + * @return numeric result value. + */ + double get_value() const; + + /** + * Get a string value for textural result. The caller must make + * sure the result is of textural type, else the behavior is undefined. + * + * @return string value. + */ + const std::string& get_string() const; + + /** + * Get an error value of the result. The caller must make sure that the + * result is of error type, else the behavior is undefined. + * + * @return enum value representing the error. + * @see ixion::get_formula_error_name + */ + formula_error_t get_error() const; + + /** + * Get a matrix value of the result. The caller must make sure that the + * result is of matrix type, else the behavior is undefined. + * + * @return matrix result value. + */ + const matrix& get_matrix() const; + + /** + * Get a matrix value of the result. The caller must make sure that the + * result is of matrix type, else the behavior is undefined. + * + * @return matrix result value. + */ + matrix& get_matrix(); + + /** + * Get the type of result. + * + * @return enum value representing the result type. + */ + result_type get_type() const; + + /** + * Get a string representation of the result value no matter what the + * result type is. + * + * @param cxt model context object. + * + * @return string representation of the result value. + */ + std::string str(const model_context& cxt) const; + + /** + * Parse a textural representation of a formula result, and set result + * value of appropriate type. + * + * @param s formula result as a string. + */ + void parse(std::string_view s); + + formula_result& operator= (formula_result r); + bool operator== (const formula_result& r) const; + bool operator!= (const formula_result& r) const; +}; + +IXION_DLLPUBLIC std::ostream& operator<< (std::ostream& os, formula_result::result_type v); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula_tokens.hpp b/include/ixion/formula_tokens.hpp new file mode 100644 index 0000000..d843dbd --- /dev/null +++ b/include/ixion/formula_tokens.hpp @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_FORMULA_TOKENS_HPP +#define INCLUDED_FORMULA_TOKENS_HPP + +#include "address.hpp" +#include "table.hpp" +#include "formula_opcode.hpp" +#include "formula_function_opcode.hpp" +#include "formula_tokens_fwd.hpp" + +#include <string> +#include <variant> + +namespace ixion { + +/** + * Get a printable name for a formula opcode. The printable name is to be + * used only for informational purposes. + * + * @param oc formula opcode + * + * @return printable name for a formula opcode. + */ +IXION_DLLPUBLIC std::string_view get_opcode_name(fopcode_t oc); + +/** + * Get the string representation of a simple formula opcode. This function + * will return a non-empty string only for operator opcodes. + * + * @param oc formula opcode + * + * @return string representation of a formula opcode. + */ +IXION_DLLPUBLIC std::string_view get_formula_opcode_string(fopcode_t oc); + +/** + * Represents a single formula token. + */ +struct IXION_DLLPUBLIC formula_token final +{ + using value_type = std::variant< + address_t, range_t, table_t, formula_function_t, + double, string_id_t, std::string>; + + /** + * Opcode that specifies the type of token. The value of this data member + * should <i>not</i> be modified after construction. + */ + const fopcode_t opcode; + + /** + * Value stored in the token. The type of this value varies depending on the + * token opcode value. + */ + value_type value; + + formula_token() = delete; + + /** + * Constructor for opcode-only token. + * + * @param op formula opcode. + */ + formula_token(fopcode_t op); + + /** + * Constructor for a single-cell reference token. The opcode will be + * implicitly set to fop_single_ref. + * + * @param addr single-cell reference. + */ + formula_token(const address_t& addr); + + /** + * Constructor for a range reference token. The opcode will be + * implicitly set to fop_range_ref. + * + * @param range range reference. + */ + formula_token(const range_t& range); + + /** + * Constructor for a table reference token. The opcode will be implicitly + * set to fop_table_ref. + * + * @param table table reference. + */ + formula_token(const table_t& table); + + /** + * Constructor for a formula function token. The opcode will be implicitly + * set to fop_function. + * + * @param func function name enum value. + */ + formula_token(formula_function_t func); + + /** + * Constructor for a numeric value token. The opcode will be implicitly set + * to fop_value. + * + * @param v numeric value to be stored in the token. + */ + formula_token(double v); + + /** + * Constructor for a string value token. The opcode will be implicitly + * set to fop_string. + * + * @param sid string ID to be stored in the token. + */ + formula_token(string_id_t sid); + + /** + * Constructor for a named-expression token. The opcode will be implicitly + * set to fop_named_expression. + * + * @param name named expression to be stored in the token. + */ + formula_token(std::string name); + + /** + * Copy constructor. + */ + formula_token(const formula_token& r); + + /** + * Move constructor. + * + * @note This will be the same as the copy constructor if the stored value + * is not movable. + */ + formula_token(formula_token&& r); + + ~formula_token(); + + bool operator== (const formula_token& r) const; + bool operator!= (const formula_token& r) const; +}; + +/** + * Storage for a series of formula tokens. + */ +class IXION_DLLPUBLIC formula_tokens_store +{ + friend void intrusive_ptr_add_ref(formula_tokens_store*); + friend void intrusive_ptr_release(formula_tokens_store*); + + struct impl; + std::unique_ptr<impl> mp_impl; + + void add_ref(); + void release_ref(); + + formula_tokens_store(); + +public: + + static formula_tokens_store_ptr_t create(); + + ~formula_tokens_store(); + + formula_tokens_store(const formula_tokens_store&) = delete; + formula_tokens_store& operator= (const formula_tokens_store&) = delete; + + size_t get_reference_count() const; + + formula_tokens_t& get(); + const formula_tokens_t& get() const; +}; + +inline void intrusive_ptr_add_ref(formula_tokens_store* p) +{ + p->add_ref(); +} + +inline void intrusive_ptr_release(formula_tokens_store* p) +{ + p->release_ref(); +} + +/** + * Represents a named expression which stores a series of formula tokens. + */ +struct IXION_DLLPUBLIC named_expression_t +{ + /** + * Origin cell position which affects any relative references stored in + * the named expression. + */ + abs_address_t origin; + + /** Formula tokens. */ + formula_tokens_t tokens; + + named_expression_t(); + named_expression_t(const abs_address_t& _origin, formula_tokens_t _tokens); + named_expression_t(const named_expression_t&) = delete; + named_expression_t(named_expression_t&& other); + ~named_expression_t(); +}; + +IXION_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const formula_token& ft); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/formula_tokens_fwd.hpp b/include/ixion/formula_tokens_fwd.hpp new file mode 100644 index 0000000..4e8dd50 --- /dev/null +++ b/include/ixion/formula_tokens_fwd.hpp @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_FORMULA_TOKENS_FWD_HPP +#define INCLUDED_IXION_FORMULA_TOKENS_FWD_HPP + +#include <boost/intrusive_ptr.hpp> +#include <vector> +#include <memory> + +namespace ixion { + +struct formula_token; +class formula_tokens_store; +using formula_tokens_store_ptr_t = boost::intrusive_ptr<formula_tokens_store>; +using formula_tokens_t = std::vector<formula_token>; +struct named_expression_t; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/global.hpp b/include/ixion/global.hpp new file mode 100644 index 0000000..4f8aa46 --- /dev/null +++ b/include/ixion/global.hpp @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_GLOBAL_HPP +#define INCLUDED_IXION_GLOBAL_HPP + +#include "types.hpp" +#include "env.hpp" + +#include <memory> +#include <string> + +namespace ixion { + +/** + * Get current time in seconds since epoch. Note that the value + * representing a time may differ from platform to platform. Use this + * value only to measure relative time. + * + * @return current time in seconds since epoch. + */ +IXION_DLLPUBLIC double get_current_time(); + +IXION_DLLPUBLIC double to_double(std::string_view s); + +IXION_DLLPUBLIC bool to_bool(std::string_view s); + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/info.hpp b/include/ixion/info.hpp new file mode 100644 index 0000000..1d7a41f --- /dev/null +++ b/include/ixion/info.hpp @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_INFO_HPP +#define INCLUDED_IXION_INFO_HPP + +#include "env.hpp" + +namespace ixion { + +IXION_DLLPUBLIC int get_version_major(); +IXION_DLLPUBLIC int get_version_minor(); +IXION_DLLPUBLIC int get_version_micro(); + +IXION_DLLPUBLIC int get_api_version_major(); +IXION_DLLPUBLIC int get_api_version_minor(); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/interface/Makefile.am b/include/ixion/interface/Makefile.am new file mode 100644 index 0000000..8b3fdc3 --- /dev/null +++ b/include/ixion/interface/Makefile.am @@ -0,0 +1,6 @@ + +libixiondir = $(includedir)/libixion-@IXION_API_VERSION@/ixion/interface + +libixion_HEADERS = \ + session_handler.hpp \ + table_handler.hpp diff --git a/include/ixion/interface/Makefile.in b/include/ixion/interface/Makefile.in new file mode 100644 index 0000000..f17c341 --- /dev/null +++ b/include/ixion/interface/Makefile.in @@ -0,0 +1,611 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include/ixion/interface +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(libixion_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libixiondir)" +HEADERS = $(libixion_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ +BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ +BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ +BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ +BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX17 = @HAVE_CXX17@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IXION_API_VERSION = @IXION_API_VERSION@ +IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ +IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ +IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ +IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ +IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ +IXION_VERSION = @IXION_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MDDS_CFLAGS = @MDDS_CFLAGS@ +MDDS_LIBS = @MDDS_LIBS@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POW_LIB = @POW_LIB@ +PYTHON = @PYTHON@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VULKAN_CFLAGS = @VULKAN_CFLAGS@ +VULKAN_LIBS = @VULKAN_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +libixiondir = $(includedir)/libixion-@IXION_API_VERSION@/ixion/interface +libixion_HEADERS = \ + session_handler.hpp \ + table_handler.hpp + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/ixion/interface/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/ixion/interface/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-libixionHEADERS: $(libixion_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libixion_HEADERS)'; test -n "$(libixiondir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libixiondir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libixiondir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libixiondir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libixiondir)" || exit $$?; \ + done + +uninstall-libixionHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libixion_HEADERS)'; test -n "$(libixiondir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libixiondir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libixiondir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-libixionHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libixionHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libixionHEADERS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-libixionHEADERS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/ixion/interface/session_handler.hpp b/include/ixion/interface/session_handler.hpp new file mode 100644 index 0000000..7ed2a8e --- /dev/null +++ b/include/ixion/interface/session_handler.hpp @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef __IXION_INTERFACE_SESSION_HANDLER_HPP__ +#define __IXION_INTERFACE_SESSION_HANDLER_HPP__ + +#include "../formula_opcode.hpp" +#include "../formula_function_opcode.hpp" +#include "../env.hpp" + +#include <cstdlib> + +namespace ixion { + +class formula_cell; +class formula_result; +struct address_t; +struct range_t; +struct abs_address_t; +struct table_t; + +namespace iface { + +class IXION_DLLPUBLIC session_handler +{ +public: + virtual ~session_handler(); + + virtual void begin_cell_interpret(const abs_address_t& pos) = 0; + virtual void end_cell_interpret() = 0; + virtual void set_result(const formula_result& result) = 0; + virtual void set_invalid_expression(std::string_view msg) = 0; + virtual void set_formula_error(std::string_view msg) = 0; + virtual void push_token(fopcode_t fop) = 0; + virtual void push_value(double val) = 0; + virtual void push_string(size_t sid) = 0; + virtual void push_single_ref(const address_t& addr, const abs_address_t& pos) = 0; + virtual void push_range_ref(const range_t& range, const abs_address_t& pos) = 0; + virtual void push_table_ref(const table_t& table) = 0; + virtual void push_function(formula_function_t foc) = 0; +}; + +}} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/interface/table_handler.hpp b/include/ixion/interface/table_handler.hpp new file mode 100644 index 0000000..0971d2e --- /dev/null +++ b/include/ixion/interface/table_handler.hpp @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef IXION_INTERFACE_TABLE_HANDLER_HPP +#define IXION_INTERFACE_TABLE_HANDLER_HPP + +#include "../types.hpp" + +namespace ixion { + +struct abs_address_t; +struct abs_range_t; + +namespace iface { + +class IXION_DLLPUBLIC table_handler +{ +public: + virtual ~table_handler(); + + /** + * Get the data range associated with a given column name. The current + * position is used to infer which table to use. + * + * @param pos current cell position. + * @param column_first name of the starting column within the table. + * @param column_last name of the ending column within the table, or + * empty_string_id if it's a single column. + * @param areas area specifiter value, which may consist of one or more + * values of table_area_t. + * + * @return referenced data range. + */ + virtual abs_range_t get_range( + const abs_address_t& pos, string_id_t column_first, string_id_t column_last, + table_areas_t areas) const = 0; + + /** + * Get the data range associated with given table and column names. + * + * @param table string identifier representing the table name. + * @param column_first name of the starting column within the table. + * @param column_last name of the ending column within the table, or + * empty_string_id if it's a single column. + * @param areas area specifiter value, which may consist of one or more + * values of table_area_t. + * + * @return referenced data range. + */ + virtual abs_range_t get_range( + string_id_t table, string_id_t column_first, string_id_t column_last, + table_areas_t areas) const = 0; +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/macros.hpp b/include/ixion/macros.hpp new file mode 100644 index 0000000..1ac84c1 --- /dev/null +++ b/include/ixion/macros.hpp @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef __IXION_MACROS_HPP__ +#define __IXION_MACROS_HPP__ + +/** + * Use this macro with a literal string and it returns the literal string + * followed by its length. + */ +#define IXION_ASCII(literal) literal, sizeof(literal)-1 + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/matrix.hpp b/include/ixion/matrix.hpp new file mode 100644 index 0000000..d001f92 --- /dev/null +++ b/include/ixion/matrix.hpp @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_MATRIX_HPP +#define INCLUDED_IXION_MATRIX_HPP + +#include "types.hpp" + +#include <memory> +#include <vector> +#include <string> +#include <variant> + +namespace ixion { + +class numeric_matrix; + +/** + * 2-dimensional matrix consisting of elements of variable types. Each + * element can be numeric, string, or empty. This class is used to + * represent range values or in-line matrices. + */ +class IXION_DLLPUBLIC matrix +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + + enum class element_type { numeric, string, boolean, error, empty }; + + struct element + { + using value_type = std::variant<double, bool, std::string_view, formula_error_t>; + + element_type type; + value_type value; + }; + + matrix(); + matrix(size_t rows, size_t cols); + matrix(size_t rows, size_t cols, double numeric); + matrix(size_t rows, size_t cols, bool boolean); + matrix(size_t rows, size_t cols, const std::string& str); + matrix(size_t rows, size_t cols, formula_error_t error); + matrix(const matrix& other); + matrix(matrix&& other); + matrix(const numeric_matrix& other); + ~matrix(); + + matrix& operator= (matrix other); + + /** + * Determine if the entire matrix consists only of numeric value elements. + * + * @return true if the entire matrix consits only of numeric value + * elements, false otherwise. + */ + bool is_numeric() const; + + bool get_boolean(size_t row, size_t col) const; + bool is_numeric(size_t row, size_t col) const; + double get_numeric(size_t row, size_t col) const; + void set(size_t row, size_t col, double val); + void set(size_t row, size_t col, bool val); + void set(size_t row, size_t col, const std::string& str); + void set(size_t row, size_t col, formula_error_t val); + + element get(size_t row, size_t col) const; + + size_t row_size() const; + size_t col_size() const; + + void swap(matrix& r); + + numeric_matrix as_numeric() const; + + bool operator== (const matrix& r) const; + bool operator!= (const matrix& r) const; +}; + +class IXION_DLLPUBLIC numeric_matrix +{ + friend class matrix; + + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + numeric_matrix(); + numeric_matrix(size_t rows, size_t cols); + + /** + * Constructor with initial values. + * + * @param array Array of initial values stored in column-major order. + * @param rows Number of rows. + * @param cols Number of columns. + */ + numeric_matrix(std::vector<double> array, size_t rows, size_t cols); + numeric_matrix(numeric_matrix&& r); + ~numeric_matrix(); + + numeric_matrix& operator= (numeric_matrix other); + + double& operator() (size_t row, size_t col); + const double& operator() (size_t row, size_t col) const; + + void swap(numeric_matrix& r); + + size_t row_size() const; + size_t col_size() const; +}; + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/model_context.hpp b/include/ixion/model_context.hpp new file mode 100644 index 0000000..b9d0987 --- /dev/null +++ b/include/ixion/model_context.hpp @@ -0,0 +1,446 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_MODEL_CONTEXT_HPP +#define INCLUDED_IXION_MODEL_CONTEXT_HPP + +#include "env.hpp" +#include "formula_tokens_fwd.hpp" +#include "types.hpp" + +#include <string> +#include <memory> +#include <variant> + +namespace ixion { + +class cell_access; +class dirty_cell_tracker; +class formula_cell; +class formula_name_resolver; +class formula_result; +class matrix; +class model_iterator; +class named_expressions_iterator; +struct abs_address_t; +struct abs_range_t; +struct abs_rc_range_t; +struct config; +struct named_expression_t; + +namespace iface { + +class session_handler; +class table_handler; + +} + +namespace detail { + +class model_context_impl; + +} + +/** + * This class stores all data relevant to current session. You can think of + * this like a document model for each formula calculation run. Note that + * only those methods called from the formula interpreter are specified in + * the interface; this explains why accessors for the most part only have + * the 'get' method not paired with its 'set' counterpart. + */ +class IXION_DLLPUBLIC model_context final +{ + friend class named_expressions_iterator; + friend class cell_access; + + std::unique_ptr<detail::model_context_impl> mp_impl; + +public: + class IXION_DLLPUBLIC session_handler_factory + { + public: + virtual std::unique_ptr<iface::session_handler> create(); + virtual ~session_handler_factory(); + }; + + /** + * Cell value only to be used to input a collection of cells to sheet. + * Formula cells are not supported. + */ + struct IXION_DLLPUBLIC input_cell + { + using value_type = std::variant<bool, double, std::string_view>; + + celltype_t type; + value_type value; + + /** Initializes the cell to be empty. */ + input_cell(std::nullptr_t); + /** Boolean cell value. */ + input_cell(bool b); + /** The char array must be null-terminated. */ + input_cell(const char* s); + /** Numeric cell value. */ + input_cell(double v); + + input_cell(const input_cell& other); + }; + + class IXION_DLLPUBLIC input_row + { + std::initializer_list<input_cell> m_cells; + public: + input_row(std::initializer_list<input_cell> cells); + + const std::initializer_list<input_cell>& cells() const; + }; + + model_context(); + model_context(const rc_size_t& sheet_size); + ~model_context(); + + /** + * Query the current policy on what to do when a formula cell result is + * being requested while the result has not yet been computed. + */ + formula_result_wait_policy_t get_formula_result_wait_policy() const; + + /** + * This method is used to notify the model access implementer of formula + * events. + * + * @param event event type. + */ + void notify(formula_event_t event); + + const config& get_config() const; + dirty_cell_tracker& get_cell_tracker(); + const dirty_cell_tracker& get_cell_tracker() const; + + bool is_empty(const abs_address_t& addr) const; + bool is_empty(const abs_range_t& range) const; + celltype_t get_celltype(const abs_address_t& addr) const; + cell_value_t get_cell_value_type(const abs_address_t& addr) const; + + /** + * Get a numeric representation of the cell value at specified position. + * If the cell at the specified position is a formula cell and its result + * has not yet been computed, it will block until the result becomes + * available. + * + * @param addr position of the cell. + * + * @return numeric representation of the cell value. + */ + double get_numeric_value(const abs_address_t& addr) const; + bool get_boolean_value(const abs_address_t& addr) const; + string_id_t get_string_identifier(const abs_address_t& addr) const; + + /** + * Get a string value associated with the cell at the specified position. + * It returns a valid string value only when the cell is a string cell, or + * is a formula cell containing a string result. Otherwise, it returns a + * nullptr. + * + * @param addr position of the cell. + * + * @return pointer to a string value if the cell stores a valid string + * value, else nullptr. + */ + std::string_view get_string_value(const abs_address_t& addr) const; + const formula_cell* get_formula_cell(const abs_address_t& addr) const; + formula_cell* get_formula_cell(const abs_address_t& addr); + + formula_result get_formula_result(const abs_address_t& addr) const; + + /** + * Get a named expression token set associated with specified name if + * present. It first searches the local sheet scope for the name, then if + * it's not present, it searches the global scope. + * + * @param sheet index of the sheet scope to search in. + * @param name name of the expression. + * + * @return const pointer to the token set if exists, nullptr otherwise. + */ + const named_expression_t* get_named_expression(sheet_t sheet, std::string_view name) const; + + double count_range(const abs_range_t& range, values_t values_type) const; + + /** + * Obtain range value in matrix form. Multi-sheet ranges are not + * supported. If the specified range consists of multiple sheets, it + * throws an exception. + * + * @param range absolute, single-sheet range address. Multi-sheet ranges + * are not allowed. + * + * @return range value represented as matrix. + */ + matrix get_range_value(const abs_range_t& range) const; + + /** + * Session handler instance receives various events from the formula + * interpretation run, in order to respond to those events. This is + * optional; the model context implementation is not required to provide a + * handler. + * + * @return a new session handler instance. It may be nullptr. + */ + std::unique_ptr<iface::session_handler> create_session_handler(); + + /** + * Table interface provides access to all table ranges stored in the + * document model. A table is a 2-dimensional range of cells that include + * named columns. It is used when resolving a table reference that refers + * to a cell or a range of cells by the table name and/or column name. + * + * @return non-null pointer to the table storage inside the model, or + * nullptr if no table is present or supported by the model + * implementation. + */ + iface::table_handler* get_table_handler(); + const iface::table_handler* get_table_handler() const; + + /** + * Try to add a new string to the string pool. If the same string already + * exists in the pool, the new string won't be added to the pool. + * + * @param s string to try to add to the pool. + * + * @return string_id_t integer value representing the string. + */ + string_id_t add_string(std::string_view s); + const std::string* get_string(string_id_t identifier) const; + + /** + * Get the index of sheet from sheet name. If the sheet name doesn't exist, + * it returns a value equal to <code>ixion::invalid_sheet</code>. + * + * @param name sheet name. + * + * @return 0-based sheet index, or <code>ixion::invalid_sheet</code> in case + * the document doesn't have a sheet by the specified name. + */ + sheet_t get_sheet_index(std::string_view name) const; + std::string get_sheet_name(sheet_t sheet) const; + + /** + * Set a new name to an existing sheet. + * + * @param sheet 0-based sheet index. + * @param name New name of a sheet. + */ + void set_sheet_name(sheet_t sheet, std::string name); + + /** + * Get the size of a sheet. + * + * @return sheet size. + */ + rc_size_t get_sheet_size() const; + + /** + * Return the number of sheets. + * + * @return number of sheets. + */ + size_t get_sheet_count() const; + + string_id_t append_string(std::string_view s); + + void set_sheet_size(const rc_size_t& sheet_size); + void set_config(const config& cfg); + + void empty_cell(const abs_address_t& addr); + + void set_numeric_cell(const abs_address_t& addr, double val); + void set_boolean_cell(const abs_address_t& adr, bool val); + void set_string_cell(const abs_address_t& addr, std::string_view s); + void set_string_cell(const abs_address_t& addr, string_id_t identifier); + + cell_access get_cell_access(const abs_address_t& addr) const; + + /** + * Duplicate the value of the source cell to one or more cells located + * immediately below it. + * + * @param src position of the source cell to copy the value from. + * @param n_dst number of cells below to copy the value to. It must be at + * least one. + */ + void fill_down_cells(const abs_address_t& src, size_t n_dst); + + /** + * Set a formula cell at a specified address. + * + * @param addr address at which to set a formula cell. + * @param tokens formula tokens to put into the formula cell. + * + * @return pointer to the formula cell instance inserted into the model. + */ + formula_cell* set_formula_cell(const abs_address_t& addr, formula_tokens_t tokens); + + /** + * Set a formula cell at a specified address. This variant takes a + * formula tokens store that can be shared between multiple formula cell + * instances. + * + * @param addr address at which to set a formula cell. + * @param tokens formula tokens to put into the formula cell. + * + * @return pointer to the formula cell instance inserted into the model. + */ + formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens); + + /** + * Set a formula cell at a specified address. This variant takes a + * formula tokens store that can be shared between multiple formula cell + * instances. + * + * @param addr address at which to set a formula cell. + * @param tokens formula tokens to put into the formula cell. + * @param result cached result of this formula cell. + * + * @return pointer to the formula cell instance inserted into the model. + */ + formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens, formula_result result); + + void set_grouped_formula_cells(const abs_range_t& group_range, formula_tokens_t tokens); + + void set_grouped_formula_cells(const abs_range_t& group_range, formula_tokens_t tokens, formula_result result); + + abs_range_t get_data_range(sheet_t sheet) const; + + /** + * Set a named expression associated with a string name in the global + * scope. + * + * @param name name of the expression. + * @param expr formula tokens to use for the named expression. + */ + void set_named_expression(std::string name, formula_tokens_t expr); + + /** + * Set a named expression associated with a string name in the global + * scope. + * + * @param name name of the expression. + * @param origin position of the origin cell. Origin cell is relevant + * only when you need to convert the tokens into a string + * representation. + * @param expr formula tokens to use for the named expression. + */ + void set_named_expression(std::string name, const abs_address_t& origin, formula_tokens_t expr); + + /** + * Set a named expression associated with a string name in a sheet-local + * scope. + * + * @param sheet 0-based index of the sheet to register this expression + * with. + * @param name name of the expression. + * @param expr formula tokens to use for the named expression. + */ + void set_named_expression(sheet_t sheet, std::string name, formula_tokens_t expr); + + /** + * Set a named expression associated with a string name in a sheet-local + * scope. + * + * @param sheet 0-based index of the sheet to register this expression + * with. + * @param name name of the expression. + * @param origin position of the origin cell. Origin cell is relevant + * only when you need to convert the tokens into a string + * representation. + * @param expr formula tokens to use for the named expression. + */ + void set_named_expression(sheet_t sheet, std::string name, const abs_address_t& origin, formula_tokens_t expr); + + /** + * Append a new sheet to the model. The caller must ensure that the name + * of the new sheet is unique within the model context. When the name + * being used for the new sheet already exists, it throws a + * model_context_error exception. + * + * @param name name of the sheet to be inserted. + * + * @return sheet index of the inserted sheet. + * + * @throw model_context_error + */ + sheet_t append_sheet(std::string name); + + /** + * A convenient way to mass-insert a range of cell values. You can + * use a nested initializet list representing a range of cell values. The + * outer list represents rows. + * + * @param sheet sheet index. + * @param rows nested list of cell values. The outer list represents + * rows. + */ + void set_cell_values(sheet_t sheet, std::initializer_list<input_row> rows); + + void set_session_handler_factory(session_handler_factory* factory); + + void set_table_handler(iface::table_handler* handler); + + size_t get_string_count() const; + + void dump_strings() const; + + /** + * Get an integer string ID from a string value. If the string value + * doesn't exist in the pool, the value equal to empty_string_id gets + * returned. + * + * @param s string value. + * + * @return string_id_t integer string ID associated with the string value + * given. + */ + string_id_t get_identifier_from_string(std::string_view s) const; + + /** + * Get an immutable iterator that lets you iterate cell values in one + * sheet one at a time. <i>The caller has to ensure that the model + * content does not change for the duration of the iteration.</i> + * + * @param sheet sheet index. + * @param dir direction of the iteration. + * @param range range on the specified sheet to iterate over. + * + * @return model iterator instance. + */ + model_iterator get_model_iterator( + sheet_t sheet, rc_direction_t dir, const abs_rc_range_t& range) const; + + /** + * Get an iterator for global named expressions. + */ + named_expressions_iterator get_named_expressions_iterator() const; + + /** + * Get an interator for sheet-local named expressions. + * + * @param sheet 0-based index of the sheet where the named expressions are + * stored. + */ + named_expressions_iterator get_named_expressions_iterator(sheet_t sheet) const; + + void walk( + sheet_t sheet, const abs_rc_range_t& range, column_block_callback_t cb) const; + + bool empty() const; +}; + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/model_iterator.hpp b/include/ixion/model_iterator.hpp new file mode 100644 index 0000000..dcebc8c --- /dev/null +++ b/include/ixion/model_iterator.hpp @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_MODEL_ITERATOR_HPP +#define INCLUDED_IXION_MODEL_ITERATOR_HPP + +#include "types.hpp" + +#include <memory> +#include <iosfwd> +#include <variant> + +namespace ixion { + +namespace detail { class model_context_impl; } +class formula_cell; +struct abs_rc_range_t; + +class IXION_DLLPUBLIC model_iterator +{ +public: + class impl; + +private: + friend class detail::model_context_impl; + std::unique_ptr<model_iterator::impl> mp_impl; + + model_iterator(const detail::model_context_impl& cxt, sheet_t sheet, const abs_rc_range_t& range, rc_direction_t dir); +public: + + struct IXION_DLLPUBLIC cell + { + using value_type = std::variant<bool, double, string_id_t, const formula_cell*>; + + row_t row; + col_t col; + celltype_t type; + value_type value; + + cell(); + cell(row_t _row, col_t _col); + cell(row_t _row, col_t _col, bool _b); + cell(row_t _row, col_t _col, string_id_t _s); + cell(row_t _row, col_t _col, double _v); + cell(row_t _row, col_t _col, const formula_cell* _f); + + bool operator== (const cell& other) const; + bool operator!= (const cell& other) const; + }; + + model_iterator(); + model_iterator(const model_iterator&) = delete; + model_iterator(model_iterator&& other); + ~model_iterator(); + + model_iterator& operator= (const model_iterator&) = delete; + model_iterator& operator= (model_iterator&& other); + + bool has() const; + + void next(); + + const cell& get() const; +}; + +IXION_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const model_iterator::cell& c); + +} // namespace ixion + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/module.hpp b/include/ixion/module.hpp new file mode 100644 index 0000000..3f0fbc2 --- /dev/null +++ b/include/ixion/module.hpp @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_MODULE_HPP +#define INCLUDED_IXION_MODULE_HPP + +#include "env.hpp" + +namespace ixion { namespace draft { + +/** + * Initialize modules if exists. + */ +IXION_DLLPUBLIC void init_modules(); + +IXION_DLLPUBLIC void unload_module(void* handler); + +class compute_engine; + +using create_compute_engine_t = compute_engine* (*)(); +using destroy_compute_engine_t = void (*)(const compute_engine*); + +struct module_def +{ + create_compute_engine_t create_compute_engine; + destroy_compute_engine_t destroy_compute_engine; +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/named_expressions_iterator.hpp b/include/ixion/named_expressions_iterator.hpp new file mode 100644 index 0000000..7511fef --- /dev/null +++ b/include/ixion/named_expressions_iterator.hpp @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_NAMED_EXPRESSIONS_ITERATOR_HPP +#define INCLUDED_IXION_NAMED_EXPRESSIONS_ITERATOR_HPP + +#include "types.hpp" +#include "formula_tokens_fwd.hpp" + +#include <memory> +#include <iosfwd> +#include <string> + +namespace ixion { + +class model_context; +struct abs_address_t; + +class IXION_DLLPUBLIC named_expressions_iterator +{ + friend class model_context; + + struct impl; + std::unique_ptr<impl> mp_impl; + + named_expressions_iterator(const model_context& cxt, sheet_t scope); + +public: + named_expressions_iterator(); + named_expressions_iterator(const named_expressions_iterator& other); + named_expressions_iterator(named_expressions_iterator&& other); + ~named_expressions_iterator(); + + struct named_expression + { + const std::string* name; + const named_expression_t* expression; + }; + + size_t size() const; + bool has() const; + void next(); + + named_expression get() const; + + named_expressions_iterator& operator= (const named_expressions_iterator& other); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/table.hpp b/include/ixion/table.hpp new file mode 100644 index 0000000..c0e556e --- /dev/null +++ b/include/ixion/table.hpp @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_TABLE_HPP +#define INCLUDED_IXION_TABLE_HPP + +#include "types.hpp" + +namespace ixion { + +struct IXION_DLLPUBLIC table_t +{ + string_id_t name; + string_id_t column_first; + string_id_t column_last; + table_areas_t areas; + + table_t(); + + bool operator== (const table_t& r) const; + bool operator!= (const table_t& r) const; +}; + +IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const table_t& table); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/ixion/types.hpp b/include/ixion/types.hpp new file mode 100644 index 0000000..5933646 --- /dev/null +++ b/include/ixion/types.hpp @@ -0,0 +1,373 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_TYPES_HPP +#define INCLUDED_IXION_TYPES_HPP + +#include "env.hpp" + +#include <cstdlib> +#include <cstdint> +#include <string_view> +#include <functional> + +namespace ixion { + +/** Column index type. */ +using col_t = int32_t; + +/** Row index type. */ +using row_t = int32_t; + +/** Sheet index type.*/ +using sheet_t = int32_t; + +/** + * Integer type that is large enough to store either a row or a column + * index. + */ +using rc_t = row_t; + +/** + * String ID type. + * + * All string values are converted into integer tokens. You need to call the + * get_string() method of ixion::model_context to get the + * actual string value. + */ +using string_id_t = uint32_t; + +/** + * Special sheet ID that represents a global scope, as opposed to a + * sheet-local scope. + */ +IXION_DLLPUBLIC_VAR const sheet_t global_scope; + +/** + * Special sheet ID that represents an invalid sheet. + */ +IXION_DLLPUBLIC_VAR const sheet_t invalid_sheet; + +/** + * Determine whether or not a given sheet index is valid. + * + * @param sheet sheet index to test. + * + * @return true if the sheet index is valid, false otherwise. + */ +IXION_DLLPUBLIC bool is_valid_sheet(sheet_t sheet); + +/** Global string ID representing an empty string. */ +IXION_DLLPUBLIC_VAR const string_id_t empty_string_id; + +/** + * This type represents a raw cell type as stored in ixion::model_context. + */ +enum class celltype_t : uint8_t +{ + /** unknown cell type.*/ + unknown = 0, + /** cell contains a raw string value.*/ + string, + /** cell contains a raw numeric value.*/ + numeric, + /** cell contains a formula object. */ + formula, + /** cell contains a raw boolean value. */ + boolean, + /** cell is empty and contains absolutely nothing. */ + empty +}; + +/** + * Similar to celltype_t, except that it does not include a formula type. + * Instead it uses the formula result type to classify its type. The error + * type refers to an error value in formula cell. + */ +enum class cell_value_t : uint8_t +{ + /** unknown cell value type. */ + unknown = 0, + /** + * either the cell contains a raw string value, or a calculated formula + * cell whose result is of string type. + */ + string, + /** + * either the cell contains a raw numeric value, or a calculated formula + * cell whose result is of numeric type. + */ + numeric, + /** + * this type corresponds with a formula cell whose result contains an + * error. + */ + error, + /** + * either the cell contains a raw boolean value type, or a calculated + * formula cell whose result is of boolean type. + */ + boolean, + /** + * the cell is empty and contains nothing whatsoever. + */ + empty +}; + +enum value_t +{ + value_none = 0x00, + value_string = 0x01, + value_numeric = 0x02, + value_boolean = 0x04, + value_empty = 0x08 +}; + +/** type that stores a mixture of value_t values. */ +class values_t +{ + int m_val; +public: + values_t(int val) : m_val(val) {} + bool is_numeric() const { return (m_val & value_numeric) == value_numeric; } + bool is_boolean() const { return (m_val & value_boolean) == value_boolean; } + bool is_string() const { return (m_val & value_string) == value_string; } + bool is_empty() const { return (m_val & value_empty) == value_empty; } +}; + +/** Value that specifies the area inside a table. */ +enum table_area_t +{ + table_area_none = 0x00, + table_area_data = 0x01, + table_area_headers = 0x02, + table_area_totals = 0x04, + table_area_all = 0x07 +}; + +/** type that stores a mixture of ixion::table_area_t values. */ +using table_areas_t = int32_t; + +/** + * Formula name resolver type specifies how name tokens are resolved. + */ +enum class formula_name_resolver_t +{ + /** Unknown syntax. */ + unknown = 0, + /** Default A1 syntax used in Excel */ + excel_a1 = 1, + /** R1C1 syntax available in Excel */ + excel_r1c1 = 2, + /** Default A1 syntax used in Calc */ + calc_a1 = 3, + /** OpenFormula syntax */ + odff = 4, + /** ODF cell-range-address syntax */ + odf_cra = 5, +}; + +/** + * Formula error types. Note that only the official (i.e. non-internal) + * error types have their corresponding error strings. Use the + * get_formula_error_name() function to convert an enum member value of this + * type to its string representation. + */ +enum class formula_error_t : uint8_t +{ + no_error = 0, + ref_result_not_available = 1, + division_by_zero = 2, + invalid_expression = 3, + name_not_found = 4, + no_range_intersection = 5, + invalid_value_type = 6, + no_value_available = 7, + + no_result_error = 253, // internal only error + stack_error = 254, // internal only error + general_error = 255, // internal only error +}; + +/** + * Type of policy on what to do when querying for the result of a formula + * cell whose result has not yet been calculated. + */ +enum class formula_result_wait_policy_t +{ + /** + * Querying for the result of a formula cell will block until the + * calculation is complete. + */ + block_until_done, + + /** + * Querying for the result of a formula cell that has not yet been + * calculated will throw an exception. + */ + throw_exception, +}; + +/** + * Formula event type used for event notification during calculation of + * formula cells. + * + * @see ixion::model_context::notify + */ +enum class formula_event_t +{ + /** Start of the calculations of formula cells. */ + calculation_begins, + /** End of the calculations of formula cells. */ + calculation_ends, +}; + +/** + * Specifies iterator direction of a ixion::model_context. + */ +enum class rc_direction_t +{ + /** Flows left to right first then top to bottom. */ + horizontal, + /** Flows top to bottom first then left to right. */ + vertical +}; + +/** + * This structure stores a 2-dimensional size information. + */ +struct IXION_DLLPUBLIC rc_size_t +{ + row_t row; + col_t column; + + rc_size_t(); + rc_size_t(const rc_size_t& other); + rc_size_t(row_t _row, col_t _column); + ~rc_size_t(); + + rc_size_t& operator= (const rc_size_t& other); +}; + +/** + * This strcuture stores information about grouped formula cells. All + * formula cells belonging to the same group shares the same set of values. + */ +struct IXION_DLLPUBLIC formula_group_t +{ + /** Size of the formula group. */ + rc_size_t size; + /** + * Unique value identifying the group a cell belongs to. Cells belonging + * to the same formula group should have the same value. + */ + uintptr_t identity; + /** Boolean value indicating whether or not a cell is grouped. */ + bool grouped; + + formula_group_t(); + formula_group_t(const formula_group_t& r); + formula_group_t(const rc_size_t& _group_size, uintptr_t _identity, bool _grouped); + ~formula_group_t(); + + formula_group_t& operator= (const formula_group_t& other); +}; + +/** + * Get a string representation of a formula error type. + * + * @param fe enum value representing a formula error type. + * @return null-terminated string representation of the formula error type. + */ +IXION_DLLPUBLIC std::string_view get_formula_error_name(formula_error_t fe); + +/** + * Parse a formula error string and convert it to a corresponding enum value. + * + * @param s string representation of a formula error type. + * @return enum value for a formula error type. + */ +IXION_DLLPUBLIC formula_error_t to_formula_error_type(std::string_view s); + +using column_block_handle = void*; + +/** + * Type of a column block that stores a series of adjacent cell values of the + * same type. + */ +enum class column_block_t : int +{ + unknown = 0, + empty, + boolean, + numeric, + string, + formula +}; + +/** + * Data that represents the shape of a column block. + */ +struct IXION_DLLPUBLIC column_block_shape_t +{ + std::size_t position; + std::size_t size; + std::size_t offset; + column_block_t type; + column_block_handle data; + + column_block_shape_t(); + + column_block_shape_t( + std::size_t _position, std::size_t _size, std::size_t _offset, + column_block_t _type, column_block_handle _data); + + column_block_shape_t(const column_block_shape_t& other); + + column_block_shape_t& operator=(const column_block_shape_t& other); +}; + +/** + * Callback function type to be used during traversal of column data. + */ +using column_block_callback_t = std::function<bool(col_t, row_t, row_t, const column_block_shape_t&)>; + +IXION_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const column_block_shape_t& v); + +/** + * Specifies how to determine whether or not to display a sheet name of a cell + * or range reference. + */ +enum class display_sheet_t +{ + /** Sheet name display preference is not specified. */ + unspecified, + /** Sheet name should be always displayed. */ + always, + /** Sheet name should never be displayed. */ + never, + /** + * Sheet name should be displayed only when the sheet index of a reference + * is different from that of the position of a referencing cell. + */ + only_if_different, +}; + +struct IXION_DLLPUBLIC print_config +{ + display_sheet_t display_sheet = display_sheet_t::only_if_different; + + print_config(); + print_config(const print_config& other); + ~print_config(); +}; + +} // namespace ixion + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |