├── tests ├── templates │ ├── django │ │ ├── empty.tpl │ │ ├── A.tpl │ │ ├── variables.tpl │ │ ├── X.tpl │ │ ├── B.tpl │ │ ├── C.tpl │ │ ├── D.tpl │ │ ├── derived.tpl │ │ ├── base.tpl │ │ ├── blog │ │ │ ├── home.html │ │ │ ├── base.html │ │ │ └── index.html │ │ ├── messages.html │ │ └── layout.html │ ├── tmpl │ │ ├── variables.tmpl │ │ └── example.tmpl │ └── ssi │ │ ├── 1338 │ │ ├── variables.shtml │ │ └── example.shtml ├── debug.gdb ├── data │ └── variables.json ├── python │ ├── __init__.py │ ├── caching_tests.py │ ├── directory_tests.py │ └── binding_tests.py ├── harness.sh ├── harness.cpp ├── groups │ ├── templates.cpp │ └── adapters.cpp ├── timings.py └── harness.py ├── synth.gif ├── .gitattributes ├── MANIFEST.in ├── examples ├── simple_django.sh ├── simple_tmpl.py ├── simple_ssi.cpp └── simple_ssi_wide.cpp ├── ide └── vs2013 │ ├── Tool │ ├── Tool.vcxproj.user │ ├── Tool.vcxproj.filters │ └── Tool.vcxproj │ ├── Harness │ ├── Harness.vcxproj.user │ ├── Harness.vcxproj.filters │ └── Harness.vcxproj │ ├── Synth.props │ └── synth.sln ├── .gitmodules ├── ajg ├── synth │ ├── engines │ │ ├── ssi.hpp │ │ ├── null.hpp │ │ ├── tmpl.hpp │ │ ├── django.hpp │ │ └── null │ │ │ ├── engine.hpp │ │ │ └── resolver.hpp │ ├── adapters │ │ ├── utility.hpp │ │ ├── smart_ptr.hpp │ │ ├── container.hpp │ │ ├── list.hpp │ │ ├── deque.hpp │ │ ├── stack.hpp │ │ ├── vector.hpp │ │ ├── bool.hpp │ │ ├── none.hpp │ │ ├── scoped_array.hpp │ │ ├── shared_array.hpp │ │ ├── variant.hpp │ │ ├── optional.hpp │ │ ├── shared_ptr.hpp │ │ ├── set.hpp │ │ ├── memory.hpp │ │ ├── complex.hpp │ │ ├── numeric_adapter.hpp │ │ ├── pointer.hpp │ │ ├── scoped_ptr.hpp │ │ ├── container_adapter.hpp │ │ ├── adapter.hpp │ │ ├── numeric.hpp │ │ ├── array.hpp │ │ ├── map.hpp │ │ ├── ptree.hpp │ │ ├── ptime.hpp │ │ ├── ref.hpp │ │ ├── string.hpp │ │ ├── forwarding_adapter.hpp │ │ ├── pair.hpp │ │ └── base_adapter.hpp │ ├── engines.hpp │ ├── templates.hpp │ ├── detail │ │ ├── if_c.hpp │ │ ├── advance_to.hpp │ │ ├── drop.hpp │ │ ├── clone_ptr.hpp │ │ ├── has_fraction.hpp │ │ ├── range.hpp │ │ ├── unmangle.hpp │ │ ├── pipe.hpp │ │ ├── standard_environment.hpp │ │ ├── mutable_atomic_singleton.hpp │ │ ├── find.hpp │ │ ├── bidirectional_input_stream.hpp │ │ └── filesystem.hpp │ ├── version.hpp │ ├── adapters.hpp │ ├── bindings │ │ ├── command_line │ │ │ ├── tool.cpp │ │ │ └── binding.hpp │ │ └── python │ │ │ ├── converter.hpp │ │ │ ├── loader.hpp │ │ │ ├── module.cpp │ │ │ └── resolver.hpp │ ├── templates │ │ ├── string_template.hpp │ │ ├── stream_template.hpp │ │ ├── buffer_template.hpp │ │ └── path_template.hpp │ ├── config.hpp │ └── value_iterator.hpp └── synth.hpp ├── scripts ├── python-dist.sh └── python-dist.bat ├── .gitignore ├── synth.rb ├── .travis.yml ├── synth.nuspec ├── LICENSE_1_0.txt ├── synth.sublime-project └── SConstruct /tests/templates/django/empty.tpl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /synth.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajg/synth/HEAD/synth.gif -------------------------------------------------------------------------------- /tests/templates/django/A.tpl: -------------------------------------------------------------------------------- 1 | '{% block x %}A{% endblock x %}' 2 | -------------------------------------------------------------------------------- /tests/debug.gdb: -------------------------------------------------------------------------------- 1 | set env MALLOC_CHECK_=3 2 | run 3 | backtrace full 4 | -------------------------------------------------------------------------------- /tests/data/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": 1, 3 | "bar": 2, 4 | "qux": 3 5 | } 6 | -------------------------------------------------------------------------------- /tests/templates/django/variables.tpl: -------------------------------------------------------------------------------- 1 | foo: {{ foo }} 2 | bar: {{ bar }} 3 | qux: {{ qux }} 4 | -------------------------------------------------------------------------------- /tests/templates/tmpl/variables.tmpl: -------------------------------------------------------------------------------- 1 | foo: 2 | bar: 3 | qux: 4 | -------------------------------------------------------------------------------- /tests/templates/django/X.tpl: -------------------------------------------------------------------------------- 1 | {% extends "tests/templates/django/A.tpl" %} 2 | {% block x %}X{% endblock x %} 3 | -------------------------------------------------------------------------------- /tests/templates/django/B.tpl: -------------------------------------------------------------------------------- 1 | {% extends "tests/templates/django/A.tpl" %} 2 | {% block x %}{{ block.super }}B{% endblock x %} 3 | -------------------------------------------------------------------------------- /tests/templates/django/C.tpl: -------------------------------------------------------------------------------- 1 | {% extends "tests/templates/django/B.tpl" %} 2 | {% block x %}{{ block.super }}C{% endblock x %} 3 | -------------------------------------------------------------------------------- /tests/templates/django/D.tpl: -------------------------------------------------------------------------------- 1 | {% extends "tests/templates/django/C.tpl" %} 2 | {% block x %}{{ block.super }}D{% endblock x %} 3 | -------------------------------------------------------------------------------- /tests/templates/ssi/variables.shtml: -------------------------------------------------------------------------------- 1 | foo: 2 | bar: 3 | qux: 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | *.html -crlf 4 | *.shtml -crlf 5 | *.tmpl -crlf 6 | *.tpl -crlf 7 | -------------------------------------------------------------------------------- /tests/templates/django/derived.tpl: -------------------------------------------------------------------------------- 1 | {% extends "tests/templates/django/base.tpl" %} 2 | Derived template 3 | {% block content %}{{ block.super }} + {{ numbers }}{% endblock content %} 4 | -------------------------------------------------------------------------------- /tests/templates/tmpl/example.tmpl: -------------------------------------------------------------------------------- 1 | ============ 2 | | 3 | 4 | ============ 5 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include ajg *.hpp 2 | recursive-include external/boost *.hpp *.h *.ipp 3 | recursive-include external/other *.hpp *.h 4 | recursive-include examples *.py 5 | -------------------------------------------------------------------------------- /examples/simple_django.sh: -------------------------------------------------------------------------------- 1 | 2 | echo '{"user": "Dolph Lundgren"}' > 'context.json' 3 | echo 'Howdy, {{ user }}!' > 'template.txt' 4 | 5 | cat template.txt | ./synth -e django -c context.json 6 | -------------------------------------------------------------------------------- /tests/templates/django/base.tpl: -------------------------------------------------------------------------------- 1 | Base template 2 | {% block header %}Base header{% endblock header %} 3 | {% block content %}Base content{% endblock content %} 4 | {% block footer %}Base footer{% endblock footer %} 5 | -------------------------------------------------------------------------------- /tests/templates/ssi/example.shtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ============ 5 | 6 | ============ 7 | -------------------------------------------------------------------------------- /ide/vs2013/Tool/Tool.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/boost"] 2 | path = external/boost 3 | url = https://github.com/ajg/external-boost 4 | branch = 1_55_0 5 | [submodule "external/tut-framework"] 6 | path = external/tut-framework 7 | url = https://github.com/mrzechonek/tut-framework 8 | -------------------------------------------------------------------------------- /tests/templates/django/blog/home.html: -------------------------------------------------------------------------------- 1 | {% extends 'index.html' %} 2 | {% block head_title %}Welcome to {{ user }}'s blog{% endblock %} 3 | 4 | {% block content %} 5 | 6 | This is what I've blogged about: 7 | 8 | {{ block.super }} 9 | 10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /tests/python/__init__.py: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | -------------------------------------------------------------------------------- /examples/simple_tmpl.py: -------------------------------------------------------------------------------- 1 | 2 | import synth, sys 3 | 4 | def simple_tmpl_example(): 5 | t = synth.Template('Howdy, !', 'tmpl') 6 | c = {'user': 'Dolph Lundgren'} 7 | 8 | # Render to different destinations: 9 | t.render_to_path("greeting.txt", c) 10 | t.render_to_file(sys.stdout, c) 11 | print(t.render_to_string(c)) 12 | -------------------------------------------------------------------------------- /tests/templates/django/blog/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% block head_title %}Welcome to my blog{% endblock %} 4 | 5 | 6 |

{% block title %}Welcome to my blog{% endblock %}

7 |

{{ subtitle }}

8 | {% block content %} 9 | 10 | {% endblock %} 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/templates/django/messages.html: -------------------------------------------------------------------------------- 1 | {% regroup messages by category as type_list %} 2 | 3 | {% for type in type_list %} 4 |
    5 | {% for message in type.list %} 6 |
  • {{ message|safe }}
  • 7 | {% endfor %} 8 |
9 | {% endfor %} 10 | 11 | {% for message in messages %} 12 |
    13 |
  • {{ message|safe }}
  • 14 |
15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /ajg/synth/engines/ssi.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_SSI_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_SSI_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #endif // AJG_SYNTH_ENGINES_SSI_HPP_INCLUDED 12 | -------------------------------------------------------------------------------- /scripts/python-dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eux 2 | 3 | python2 ./setup.py clean --all 4 | python2 ./setup.py bdist upload 5 | python2 ./setup.py bdist_egg upload 6 | python2 ./setup.py bdist_wheel upload 7 | 8 | python3 ./setup.py clean --all 9 | python3 ./setup.py bdist upload 10 | python3 ./setup.py bdist_egg upload 11 | python3 ./setup.py bdist_wheel upload 12 | 13 | python2 ./setup.py clean --all 14 | python2 ./setup.py sdist upload 15 | python2 ./setup.py sdist --format=zip upload 16 | -------------------------------------------------------------------------------- /ajg/synth/engines/null.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_NULL_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_NULL_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #endif // AJG_SYNTH_ENGINES_NULL_HPP_INCLUDED 12 | -------------------------------------------------------------------------------- /ajg/synth/engines/tmpl.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_TMPL_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_TMPL_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #endif // AJG_SYNTH_ENGINES_TMPL_HPP_INCLUDED 12 | -------------------------------------------------------------------------------- /ajg/synth/adapters/utility.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_UTILITY_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_UTILITY_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | #endif // AJG_SYNTH_ADAPTERS_UTILITY_HPP_INCLUDED 13 | 14 | -------------------------------------------------------------------------------- /ajg/synth/engines/django.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_DJANGO_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_DJANGO_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #endif // AJG_SYNTH_ENGINES_DJANGO_HPP_INCLUDED 12 | -------------------------------------------------------------------------------- /ajg/synth/engines.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #endif // AJG_SYNTH_ENGINES_HPP_INCLUDED 15 | -------------------------------------------------------------------------------- /ajg/synth.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_HPP_INCLUDED 6 | #define AJG_SYNTH_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #endif // AJG_SYNTH_HPP_INCLUDED 17 | -------------------------------------------------------------------------------- /ajg/synth/adapters/smart_ptr.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_SMART_PTR_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_SMART_PTR_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #endif // AJG_SYNTH_ADAPTERS_SMART_PTR_HPP_INCLUDED 14 | 15 | -------------------------------------------------------------------------------- /tests/harness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 3 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 4 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 5 | 6 | function main { 7 | expect=$(echo -e -n 'foo: 1\nbar: 2\nqux: 3\n') 8 | actual=$(cat tests/templates/django/variables.tpl | ./synth -e django -c tests/data/variables.json) 9 | 10 | if [[ "$expect" == "$actual" ]] 11 | then echo -e 'Success'; 12 | else echo -e 'Failure\nExpect: `'"$expect"'`\nActual: `'"$actual"'`'; 13 | fi 14 | } 15 | 16 | main 17 | -------------------------------------------------------------------------------- /ajg/synth/templates.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_TEMPLATE_HPP_INCLUDED 6 | #define AJG_SYNTH_TEMPLATE_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #endif // AJG_SYNTH_TEMPLATE_HPP_INCLUDED 15 | -------------------------------------------------------------------------------- /ide/vs2013/Harness/Harness.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | 7 | $(ProjectDir)\..\..\..\.. 8 | WindowsLocalDebugger 9 | 10 | 11 | $(ProjectDir)\..\..\..\.. 12 | WindowsLocalDebugger 13 | 14 | -------------------------------------------------------------------------------- /tests/templates/django/blog/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block title %}Welcome to my blog{% endblock %} 3 | 4 | {% block content %} 5 |

Categories

6 | {% if categories %} 7 | 12 | {% else %} 13 |

There are no posts.

14 | {% endif %} 15 | 16 |

Posts

17 | {% if posts %} 18 | 23 | {% else %} 24 |

There are no posts.

25 | {% endif %} 26 | 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /tests/python/caching_tests.py: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | directory = 'tests/templates/django/' 6 | 7 | import synth 8 | 9 | def get(): 10 | return (data, golden, source, 'django', { 11 | 'directories': [directory], 12 | 'caching': (synth.CACHE_ALL | synth.CACHE_PER_PROCESS), 13 | 'directories': [directory], 14 | }) 15 | 16 | data = {'foo': 1, 'bar': 2, 'qux': 3} 17 | source = """Foo Bar Qux; {% include "variables.tpl" %}; {% include "variables.tpl" %}""" 18 | golden = """Foo Bar Qux; \ 19 | foo: 1\nbar: 2\nqux: 3\n; \ 20 | foo: 1\nbar: 2\nqux: 3\n""" 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Scons 2 | .scons 3 | .sconsign.dblite 4 | 5 | # Binaries 6 | *.o 7 | *.o-* 8 | *.os 9 | *.os-* 10 | *.so 11 | *.so-* 12 | *.dll 13 | *.dll-* 14 | *.exe 15 | *.exe-* 16 | *.lib 17 | *.lib-* 18 | 19 | # Executables 20 | /a.out 21 | /synth 22 | /tests/harness.out 23 | /examples/all 24 | 25 | # Sublime Text 26 | *.sublime-workspace 27 | 28 | # Code Blocks 29 | /ide/cb**/*.depend 30 | /ide/cb**/*.layout 31 | 32 | # Visual Studio 33 | /ide/vs**/ipch/ 34 | /ide/vs**/Debug/ 35 | /ide/vs**/Release/ 36 | /ide/vs**/*.log 37 | /ide/vs**/*.tlog 38 | /ide/vs**/*.ncb 39 | /ide/vs**/*.idb 40 | /ide/vs**/*.obj 41 | /ide/vs**/*.opensdf 42 | /ide/vs**/*.sbr 43 | /ide/vs**/*.sdf 44 | /ide/vs**/*.suo 45 | 46 | # Python 47 | /build/ 48 | /dist/ 49 | *.pyc 50 | *.pyd 51 | *.egg-info 52 | /vc*.idb 53 | 54 | # Misc. 55 | SCRATCH 56 | -------------------------------------------------------------------------------- /tests/harness.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #include 6 | 7 | #include 8 | 9 | int main(int const argc, char const *const argv[]) { 10 | bool success = true; 11 | ajg::synth::test_suite suite("synth"); 12 | 13 | if (argc <= 1) { 14 | // Run entire suite. 15 | success = suite.run(); 16 | } 17 | else { 18 | // Run specific groups. 19 | for (int i = 1; i < argc; ++i) { 20 | success = success && suite.run(argv[i]); 21 | } 22 | } 23 | 24 | return success ? EXIT_SUCCESS : EXIT_FAILURE; 25 | } 26 | -------------------------------------------------------------------------------- /ajg/synth/detail/if_c.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_IF_C_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_IF_C_HPP_INCLUDED 7 | 8 | namespace ajg { 9 | namespace synth { 10 | namespace detail { 11 | 12 | // 13 | // if_c 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | template struct if_c { typedef X type; }; 17 | template struct if_c { typedef Y type; }; 18 | 19 | }}} // namespace ajg::synth::detail 20 | 21 | #endif // AJG_SYNTH_DETAIL_IF_C_HPP_INCLUDED 22 | -------------------------------------------------------------------------------- /ajg/synth/adapters/container.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_CONTAINER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_CONTAINER_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // TODO: unordered_[multi]map/hash_[multi]map 16 | // TODO: unordered_[multi]set/hash_[multi]set 17 | 18 | // TODO: ptr_containers 19 | // TODO: bitset 20 | 21 | #endif // AJG_SYNTH_ADAPTERS_CONTAINER_HPP_INCLUDED 22 | 23 | -------------------------------------------------------------------------------- /synth.rb: -------------------------------------------------------------------------------- 1 | require "formula" 2 | 3 | class Synth < Formula 4 | homepage "https://github.com/ajg/synth" 5 | head "https://github.com/ajg/synth.git" 6 | url "https://github.com/ajg/synth/releases/download/v1.0.3/archive.tar.gz" 7 | sha1 "8a5c9d09c9b95b5c4e72af94cedb9e53924fd933" 8 | version "1.0.3" 9 | 10 | depends_on "scons" => :build 11 | depends_on "python" => :optional 12 | # TODO: Add debug flag 13 | 14 | def install 15 | scons "synth", "debug=0", "boost=local" 16 | bin.install "synth" 17 | # TODO: include.install "ajg/synth.hpp", Dir["ajg/**/synth.hpp"] 18 | # See http://stackoverflow.com/q/23307205/1272391 19 | 20 | if build.with? "python" 21 | system "python", "setup.py", "install", "--prefix=#{prefix}" 22 | end 23 | end 24 | 25 | # TODO: bottle do ... 26 | 27 | test do 28 | system "#{bin}/synth", "--version" 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /examples/simple_ssi.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef ajg::synth::default_traits traits_type; 8 | typedef ajg::synth::engines::ssi::engine engine_type; 9 | typedef ajg::synth::templates::string_template template_type; 10 | 11 | int main() { 12 | // Parse the template. 13 | template_type const t( 14 | "Howdy, ! " 15 | "Your balance is ."); 16 | 17 | // Create some data. 18 | std::map m; 19 | m["user"] = "Dolph Lundgren"; 20 | m["points"] = 42; 21 | 22 | // Render to different destinations: 23 | t.render_to_stream(std::cout, m); 24 | t.render_to_path("greeting.txt", m); 25 | std::cout << t.render_to_string(m); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /examples/simple_ssi_wide.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 8 | 9 | typedef ajg::synth::default_traits traits_type; 10 | typedef ajg::synth::engines::ssi::engine engine_type; 11 | typedef ajg::synth::templates::string_template template_type; 12 | 13 | int wmain() { 14 | // Parse the template. 15 | template_type const t( 16 | L"Howdy, ! " 17 | L"Your balance is ."); 18 | 19 | // Create some data. 20 | std::map m; 21 | m[L"user"] = L"Dolph Lundgren"; 22 | m[L"points"] = 42; 23 | 24 | // Render to different destinations: 25 | t.render_to_stream(std::wcout, m); 26 | t.render_to_path(L"greeting.txt", m); 27 | std::wcout << t.render_to_string(m); 28 | return 0; 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ajg/synth/adapters/list.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_LIST_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_LIST_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::list 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : container_adapter, sequential> { 22 | adapter(std::list const& adapted) : container_adapter, sequential>(adapted) {} 23 | }; 24 | 25 | }}} // namespace ajg::synth::adapters 26 | 27 | #endif // AJG_SYNTH_ADAPTERS_LIST_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /ajg/synth/adapters/deque.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_DEQUE_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_DEQUE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::deque 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : container_adapter, sequential> { 22 | adapter(std::deque const& adapted) : container_adapter, sequential>(adapted) {} 23 | }; 24 | 25 | }}} // namespace ajg::synth::adapters 26 | 27 | #endif // AJG_SYNTH_ADAPTERS_DEQUE_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /ajg/synth/adapters/stack.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_STACK_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_STACK_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::stack 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : container_adapter, sequential> { 22 | adapter(std::stack const& adapted) : container_adapter, sequential>(adapted) {} 23 | }; 24 | 25 | }}} // namespace ajg::synth::adapters 26 | 27 | #endif // AJG_SYNTH_ADAPTERS_STACK_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /ajg/synth/detail/advance_to.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_ADVANCE_TO_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_ADVANCE_TO_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace detail { 13 | 14 | // 15 | // advance_to: 16 | // Simulates operator + for iterators which lack it. 17 | // NOTE: Doesn't do any bounds checking; ensure distance is valid. 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | inline Iterator advance_to(Iterator iterator, Distance const distance) { 22 | std::advance(iterator, distance); 23 | return iterator; 24 | } 25 | 26 | }}} // namespace ajg::synth::detail 27 | 28 | #endif // AJG_SYNTH_DETAIL_ADVANCE_TO_HPP_INCLUDED 29 | -------------------------------------------------------------------------------- /ide/vs2013/Synth.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\external;..\..\..\external\boost;..\..\..\external\tut-framework\include;..\..\.. 7 | 8 | 9 | 10 | _CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;BOOST_ALL_NO_LIB;_MBCS;%(PreprocessorDefinitions) 11 | 4100;4127;4180;4244;4245;4503;4510;4512;4610;4668;4800;4820 12 | CompileAsCpp 13 | true 14 | /bigobj %(AdditionalOptions) 15 | Level4 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ajg/synth/adapters/vector.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_VECTOR_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_VECTOR_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::vector 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : container_adapter, sequential> { 22 | adapter(std::vector const& adapted) : container_adapter, sequential>(adapted) {} 23 | }; 24 | 25 | }}} // namespace ajg::synth::adapters 26 | 27 | #endif // AJG_SYNTH_ADAPTERS_VECTOR_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /ajg/synth/adapters/bool.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_BOOL_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_BOOL_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace adapters { 13 | 14 | // 15 | // specialization for bool 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | template 19 | struct adapter : concrete_adapter { 20 | adapter(bool const& adapted) : concrete_adapter(adapted) {} 21 | 22 | virtual optional get_boolean() const { return this->adapted(); } 23 | }; 24 | 25 | }}} // namespace ajg::synth::adapters 26 | 27 | #endif // AJG_SYNTH_ADAPTERS_BOOL_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /ajg/synth/detail/drop.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_DROP_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_DROP_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace ajg { 14 | namespace synth { 15 | namespace detail { 16 | 17 | // 18 | // drop 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | template 22 | inline pair_range drop(Container const& container, Number const number) { 23 | return pair_range(advance_to(container.begin(), number), container.end()); 24 | } 25 | 26 | }}} // namespace ajg::synth::detail 27 | 28 | #endif // AJG_SYNTH_DETAIL_DROP_HPP_INCLUDED 29 | -------------------------------------------------------------------------------- /ajg/synth/adapters/none.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_NONE_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_NONE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for boost::none_t 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter : concrete_adapter_without_operators { 22 | adapter(boost::none_t const& adapted) : concrete_adapter_without_operators(adapted) {} 23 | }; 24 | 25 | }}} // namespace ajg::synth::adapters 26 | 27 | #endif // AJG_SYNTH_ADAPTERS_NONE_HPP_INCLUDED 28 | 29 | -------------------------------------------------------------------------------- /ajg/synth/version.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_VERSION_HPP_INCLUDED 6 | #define AJG_SYNTH_VERSION_HPP_INCLUDED 7 | 8 | #define AJG_SYNTH_VERSION_MAJOR 2 9 | #define AJG_SYNTH_VERSION_MINOR 0 10 | #define AJG_SYNTH_VERSION_PATCH 0 11 | 12 | #define AJG_SYNTH_VERSION AJG_SYNTH_VERSION_MAJOR.AJG_SYNTH_VERSION_MINOR.AJG_SYNTH_VERSION_PATCH 13 | #define AJG_SYNTH_VERSION_SEQ (AJG_SYNTH_VERSION_MAJOR)(AJG_SYNTH_VERSION_MINOR)(AJG_SYNTH_VERSION_PATCH) 14 | #define AJG_SYNTH_VERSION_TUPLE (AJG_SYNTH_VERSION_MAJOR, AJG_SYNTH_VERSION_MINOR, AJG_SYNTH_VERSION_PATCH) 15 | #define AJG_SYNTH_VERSION_ARRAY (3, AJG_SYNTH_VERSION_TUPLE) 16 | #define AJG_SYNTH_VERSION_STRING AJG_SYNTH_STRINGIZE(AJG_SYNTH_VERSION) 17 | 18 | #define AJG_SYNTH_STRINGIZE_(e) #e 19 | #define AJG_SYNTH_STRINGIZE(e) AJG_SYNTH_STRINGIZE_(e) 20 | 21 | #endif // AJG_SYNTH_VERSION_HPP_INCLUDED 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | language: cpp 6 | 7 | compiler: 8 | - g++ 9 | - clang++ 10 | 11 | # TODO: 12 | # os: 13 | # - linux 14 | # - osx 15 | # 16 | matrix: 17 | allow_failures: 18 | - compiler: g++ 19 | # - os: osx 20 | 21 | branches: 22 | only: 23 | - master 24 | - v1 25 | 26 | # before_install: 27 | 28 | install: 29 | - sudo apt-get update 30 | - sudo apt-get install valgrind 31 | # TODO: Build environment with boost available. 32 | # - sudo apt-get install libboost-dev libboost-python-dev 33 | 34 | # before_script: 35 | 36 | script: 37 | - travis_wait scons 38 | - tests/harness.out 39 | - valgrind --track-origins=yes tests/harness.out 40 | - bash tests/harness.sh 41 | - python tests/harness.py 42 | # TODO: Re-enable once Travis bumps memory limits. 43 | # - travis_wait python setup.py build 44 | # - sudo python setup.py install 45 | -------------------------------------------------------------------------------- /ajg/synth/detail/clone_ptr.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_CLONE_PTR_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_CLONE_PTR_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace detail { 13 | 14 | template 15 | struct clone_ptr : boost::scoped_ptr { 16 | public: 17 | 18 | clone_ptr(T *const t = 0) : boost::scoped_ptr(t) {} 19 | clone_ptr(clone_ptr const& c) : boost::scoped_ptr(c ? &c->clone() : 0) {} 20 | 21 | inline clone_ptr& operator =(clone_ptr const& c) { 22 | this->reset(c ? &c->clone() : 0); 23 | return *this; 24 | } 25 | 26 | inline operator bool() const { 27 | return boost::scoped_ptr::get() != 0; 28 | } 29 | }; 30 | 31 | }}} // namespace ajg::synth::detail 32 | 33 | #endif // AJG_SYNTH_DETAIL_CLONE_PTR_HPP_INCLUDED 34 | -------------------------------------------------------------------------------- /synth.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | synth 6 | synth 7 | 1.0.3 8 | Alvaro J. Genial 9 | ajg 10 | synth 11 | A template parser and renderer 12 | https://github.com/ajg/synth 13 | synth admin template django html ssi parse render 14 | Alvaro J. Genial 15 | https://raw.github.com/ajg/synth/master/LICENSE_1_0.txt 16 | false 17 | https://raw.github.com/ajg/synth/master/synth.gif 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ajg/synth/adapters.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #endif // AJG_SYNTH_ADAPTERS_HPP_INCLUDED 27 | -------------------------------------------------------------------------------- /ajg/synth/bindings/command_line/tool.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #include // Must come ahead of everything else. 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | 14 | namespace { 15 | 16 | namespace s = ajg::synth; 17 | 18 | typedef s::default_traits traits_type; 19 | typedef s::bindings::command_line::binding binding_type; 20 | typedef s::bindings::command_line::command command_type; 21 | 22 | } // namespace 23 | 24 | int main(int const argc, char const* argv[]) 25 | try { 26 | command_type::run(argc - 1, argv + 1); 27 | return EXIT_SUCCESS; 28 | } 29 | catch (std::exception const& e) { 30 | std::cerr << "synth: " << e.what() << std::endl; 31 | return EXIT_FAILURE; 32 | } 33 | -------------------------------------------------------------------------------- /ajg/synth/adapters/scoped_array.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_SCOPED_ARRAY_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_SCOPED_ARRAY_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace boost { 13 | template class scoped_array; 14 | } 15 | 16 | namespace ajg { 17 | namespace synth { 18 | namespace adapters { 19 | 20 | // 21 | // specialization for boost::scoped_array 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | template 25 | struct adapter > : adapter { 26 | adapter(boost::scoped_array const& adapted, std::size_t const length) : adapter(adapted.get(), length) {} 27 | }; 28 | 29 | }}} // namespace ajg::synth::adapters 30 | 31 | #endif // AJG_SYNTH_ADAPTERS_SCOPED_ARRAY_HPP_INCLUDED 32 | 33 | -------------------------------------------------------------------------------- /ajg/synth/adapters/shared_array.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_SHARED_ARRAY_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_SHARED_ARRAY_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace boost { 13 | template class shared_array; 14 | } 15 | 16 | namespace ajg { 17 | namespace synth { 18 | namespace adapters { 19 | 20 | // 21 | // specialization for boost::shared_array 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | template 25 | struct adapter > : adapter { 26 | adapter(boost::shared_array const& adapted, std::size_t const length) : adapter(adapted.get(), length) {} 27 | }; 28 | 29 | }}} // namespace ajg::synth::adapters 30 | 31 | #endif // AJG_SYNTH_ADAPTERS_SHARED_ARRAY_HPP_INCLUDED 32 | 33 | -------------------------------------------------------------------------------- /ajg/synth/detail/has_fraction.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_IS_INTEGER_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_IS_INTEGER_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace ajg { 14 | namespace synth { 15 | namespace detail { 16 | 17 | // 18 | // has_fraction: 19 | // Determines whether a floating-point number has a fractional part ("decimals"). 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | template 23 | inline typename boost::enable_if, bool>::type has_fraction(T const) { return false; } 24 | 25 | template 26 | inline typename boost::disable_if, bool>::type has_fraction(T const t) { 27 | T integral_part; 28 | return (std::modf)(t, &integral_part) != static_cast(0.0); 29 | } 30 | 31 | }}} // namespace ajg::synth::detail 32 | 33 | #endif // AJG_SYNTH_DETAIL_IS_INTEGER_HPP_INCLUDED 34 | -------------------------------------------------------------------------------- /ajg/synth/adapters/variant.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_VARIANT_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_VARIANT_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for boost::variant 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | // TODO: Use forwarding_adapter or forward the actual value elsehow. 21 | template 22 | struct adapter > : concrete_adapter, container> { 23 | adapter(boost::variant const& adapted) : concrete_adapter, container>(adapted) {} 24 | }; 25 | 26 | }}} // namespace ajg::synth::adapters 27 | 28 | #endif // AJG_SYNTH_ADAPTERS_OPTIONAL_HPP_INCLUDED 29 | 30 | -------------------------------------------------------------------------------- /tests/templates/ssi/1338: -------------------------------------------------------------------------------- 1 | 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 -------------------------------------------------------------------------------- /ajg/synth/detail/range.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_RANGE_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_RANGE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace detail { 13 | 14 | // 15 | // pair_range 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | template 19 | struct pair_range : std::pair { 20 | explicit pair_range() : std::pair() {} 21 | explicit pair_range(I const& b, I const& e) : std::pair(b, e) {} 22 | inline I const& begin() const { return this->first; } 23 | inline I const& end() const { return this->second; } 24 | }; 25 | 26 | // 27 | // make_range 28 | //////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | template 31 | inline pair_range make_range(I const& begin, I const& end) { 32 | return pair_range(begin, end); 33 | } 34 | 35 | }}} // namespace ajg::synth::detail 36 | 37 | #endif // AJG_SYNTH_DETAIL_RANGE_HPP_INCLUDED 38 | -------------------------------------------------------------------------------- /ajg/synth/detail/unmangle.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_UNMANGLE_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_UNMANGLE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #if AJG_SYNTH_HAS_CXXABI_H 16 | #include 17 | #endif 18 | 19 | namespace ajg { 20 | namespace synth { 21 | namespace detail { 22 | 23 | // 24 | // unmangle 25 | //////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | inline std::string unmangle(std::string const& mangled) { 28 | #if AJG_SYNTH_HAS_CXXABI_H 29 | 30 | // TODO[c++11]: unique_ptr. 31 | int status = 0; 32 | boost::shared_ptr unmangled(abi::__cxa_demangle(mangled.c_str(), 0, 0, &status), std::free); 33 | return unmangled && status == 0 ? std::string(unmangled.get()) : mangled; 34 | 35 | #else 36 | 37 | return mangled; 38 | 39 | #endif 40 | } 41 | 42 | }}} // namespace ajg::synth::detail 43 | 44 | #endif // AJG_SYNTH_DETAIL_UNMANGLE_HPP_INCLUDED 45 | -------------------------------------------------------------------------------- /ajg/synth/adapters/optional.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_OPTIONAL_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_OPTIONAL_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for boost::optional 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : forwarding_adapter > { 22 | adapter(boost::optional const& adapted) : forwarding_adapter >(adapted) {} 23 | 24 | template A forward() { return A(boost::ref(*this->adapted())); } 25 | template A forward() const { return A(boost::cref(*this->adapted())); } 26 | bool valid() const { return this->adapted(); } 27 | }; 28 | 29 | }}} // namespace ajg::synth::adapters 30 | 31 | #endif // AJG_SYNTH_ADAPTERS_OPTIONAL_HPP_INCLUDED 32 | 33 | -------------------------------------------------------------------------------- /ide/vs2013/Tool/Tool.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /ajg/synth/adapters/shared_ptr.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_SHARED_PTR_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_SHARED_PTR_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | namespace boost { 12 | template class shared_ptr; 13 | } 14 | 15 | namespace ajg { 16 | namespace synth { 17 | namespace adapters { 18 | 19 | // 20 | // specialization for boost::shared_ptr 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | template 24 | struct adapter > : forwarding_adapter > { 25 | adapter(boost::shared_ptr const& adapted) : forwarding_adapter >(adapted) {} 26 | 27 | template A forward() { return A(boost::ref(*this->adapted())); } 28 | template A forward() const { return A(boost::cref(*this->adapted())); } 29 | bool valid() const { return this->adapted().get() != 0; } 30 | }; 31 | 32 | }}} // namespace ajg::synth::adapters 33 | 34 | #endif // AJG_SYNTH_ADAPTERS_SHARED_PTR_HPP_INCLUDED 35 | 36 | -------------------------------------------------------------------------------- /ajg/synth/adapters/set.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_SET_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_SET_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::set 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : container_adapter, associative> { 22 | adapter(std::set const& adapted) : container_adapter, associative>(adapted) {} 23 | }; 24 | 25 | // 26 | // specialization for std::multiset 27 | //////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | template 30 | struct adapter > : container_adapter, associative> { 31 | adapter(std::multiset const& adapted) : container_adapter, associative>(adapted) {} 32 | }; 33 | 34 | }}} // namespace ajg::synth::adapters 35 | 36 | #endif // AJG_SYNTH_ADAPTERS_SET_HPP_INCLUDED 37 | -------------------------------------------------------------------------------- /ajg/synth/adapters/memory.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_MEMORY_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_MEMORY_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::auto_ptr 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template // NOTE: Adapted as a const reference since scoped_ptr is noncopyable. 21 | struct adapter > : forwarding_adapter const*, adapter > > { 22 | adapter(std::auto_ptr const& adapted) : forwarding_adapter const*, adapter > >(&adapted) {} 23 | 24 | template A forward() { return A(boost::ref(*this->adapted()->get())); } 25 | template A forward() const { return A(boost::cref(*this->adapted()->get())); } 26 | bool valid() const { return this->adapted()->get() != 0; } 27 | }; 28 | 29 | }}} // namespace ajg::synth::adapters 30 | 31 | #endif // AJG_SYNTH_ADAPTERS_MEMORY_HPP_INCLUDED 32 | 33 | -------------------------------------------------------------------------------- /ide/vs2013/synth.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30110.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tool", "Tool\Tool.vcxproj", "{4930EC20-223C-4182-9A63-6235DFC1EBC5}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Harness", "Harness\Harness.vcxproj", "{D362CE4E-F28E-4436-8742-48CE405D5831}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4930EC20-223C-4182-9A63-6235DFC1EBC5}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {4930EC20-223C-4182-9A63-6235DFC1EBC5}.Debug|Win32.Build.0 = Debug|Win32 18 | {4930EC20-223C-4182-9A63-6235DFC1EBC5}.Release|Win32.ActiveCfg = Release|Win32 19 | {4930EC20-223C-4182-9A63-6235DFC1EBC5}.Release|Win32.Build.0 = Release|Win32 20 | {D362CE4E-F28E-4436-8742-48CE405D5831}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {D362CE4E-F28E-4436-8742-48CE405D5831}.Debug|Win32.Build.0 = Debug|Win32 22 | {D362CE4E-F28E-4436-8742-48CE405D5831}.Release|Win32.ActiveCfg = Release|Win32 23 | {D362CE4E-F28E-4436-8742-48CE405D5831}.Release|Win32.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /ajg/synth/bindings/python/converter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_BINDINGS_PYTHON_CONVERTER_HPP_INCLUDED 6 | #define AJG_SYNTH_BINDINGS_PYTHON_CONVERTER_HPP_INCLUDED 7 | 8 | #if AJG_SYNTH_OBSOLETE 9 | 10 | // ---- adapter.hpp 11 | 12 | typedef typename py::stl_input_iterator stl_iterator; 13 | 14 | // ---- module.cpp 15 | 16 | template 17 | static void* convertible(PyObject* obj) { 18 | return obj; 19 | } 20 | 21 | template 22 | static void construct(PyObject* obj, py::converter::rvalue_from_python_stage1_data* data) { 23 | void* storage = ((py::converter::rvalue_from_python_storage*) data)->storage.bytes; 24 | 25 | // Use borrowed to construct the object so that a reference count will be properly handled. 26 | py::handle<> hndl(py::borrowed(obj)); 27 | new (storage) T(py::object(hndl)); 28 | 29 | data->convertible = storage; 30 | } 31 | 32 | // ---- BOOST_PYTHON_MODULE 33 | 34 | // TODO: ssi values, tmpl values 35 | typedef binding_type::django_template_type::value_type value_type; 36 | py::converter::registry::push_back(&convertible, &construct, py::type_id()); 37 | 38 | #endif // AJG_SYNTH_OBSOLETE 39 | 40 | #endif // AJG_SYNTH_BINDINGS_PYTHON_CONVERTER_HPP_INCLUDED 41 | -------------------------------------------------------------------------------- /ajg/synth/adapters/complex.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_COMPLEX_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_COMPLEX_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // Specialization for std::complex 18 | // TODO: Have is_numeric return true. 19 | // TODO: Use numeric_adapter as base? 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | template // TODO: Set floating, integral etc. flags based on T. 23 | struct adapter > : concrete_adapter, numeric> { 24 | adapter(std::complex const& adapted) : concrete_adapter, numeric>(adapted) {} 25 | 26 | virtual optional get_number() const { return static_cast(this->adapted().real()); } 27 | }; 28 | 29 | }}} // namespace ajg::synth::adapters 30 | 31 | namespace std { 32 | 33 | template 34 | struct less > { 35 | bool operator()(complex const& a, complex const& b) const { 36 | return a.real() < b.real() && a.imag() < b.imag(); 37 | } 38 | }; 39 | 40 | } // namespace std 41 | 42 | #endif // AJG_SYNTH_ADAPTERS_COMPLEX_HPP_INCLUDED 43 | 44 | -------------------------------------------------------------------------------- /ajg/synth/adapters/numeric_adapter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_NUMERIC_ADAPTER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_NUMERIC_ADAPTER_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace ajg { 14 | namespace synth { 15 | namespace adapters { 16 | 17 | // 18 | // numeric_adapter: 19 | // Base adapter implementation for primitive numeric types 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | template 23 | struct numeric_adapter : concrete_adapter::value ? integral : 0) | (boost::is_floating_point::value ? floating : 0))> { 24 | numeric_adapter(Adapted const& adapted) : concrete_adapter::value ? integral : 0) | (boost::is_floating_point::value ? floating : 0))>(adapted) {} 25 | 26 | virtual optional get_number() const { return static_cast(this->adapted()); } 27 | }; 28 | 29 | }}} // namespace ajg::synth::adapters 30 | 31 | #endif // AJG_SYNTH_ADAPTERS_NUMERIC_ADAPTER_HPP_INCLUDED 32 | 33 | -------------------------------------------------------------------------------- /ide/vs2013/Harness/Harness.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | -------------------------------------------------------------------------------- /ajg/synth/bindings/python/loader.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_BINDINGS_PYTHON_LOADER_HPP_INCLUDED 6 | #define AJG_SYNTH_BINDINGS_PYTHON_LOADER_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | namespace ajg { 12 | namespace synth { 13 | namespace bindings { 14 | namespace python { 15 | 16 | // 17 | // loader 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct loader : Options::abstract_loader { 22 | typedef Options options_type; 23 | typedef typename options_type::library_type library_type; 24 | typedef typename options_type::traits_type traits_type; 25 | 26 | typedef typename traits_type::string_type string_type; 27 | 28 | explicit loader(py::object const& object) : object_(object) {} 29 | virtual ~loader() {} 30 | 31 | virtual library_type load_library(string_type const& name) { 32 | return library_type(new library(object_(name))); 33 | } 34 | 35 | 36 | private: 37 | 38 | py::object /*const*/ object_; 39 | }; 40 | 41 | }}}} // namespace ajg::synth::bindings::python 42 | 43 | #endif // AJG_SYNTH_BINDINGS_PYTHON_LOADER_HPP_INCLUDED 44 | -------------------------------------------------------------------------------- /ajg/synth/detail/pipe.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_PIPE_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_PIPE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | namespace ajg { 15 | namespace synth { 16 | namespace detail { 17 | 18 | // 19 | // pipe: 20 | // Nicer, safer interface to popen/pclose. 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | struct pipe : boost::noncopyable { 24 | public: 25 | 26 | explicit pipe(std::string const& command, bool const reading = true) { 27 | if ((file_ = AJG_SYNTH_IF_MSVC(_popen, popen)(command.c_str(), reading ? "r" : "w")) == 0) { 28 | AJG_SYNTH_THROW(error("open")); 29 | } 30 | } 31 | 32 | ~pipe() { 33 | if (AJG_SYNTH_IF_MSVC(_pclose, pclose)(file_) == -1) { 34 | AJG_SYNTH_THROW(error("close")); 35 | } 36 | } 37 | 38 | public: 39 | 40 | // TODO: Move this into exceptions.hpp 41 | struct error : public std::runtime_error { 42 | error(std::string const& action) 43 | : std::runtime_error("could not " + action + " pipe (" + std::strerror(errno) + ")") {} 44 | }; 45 | 46 | public: 47 | 48 | template 49 | void read_into(Stream& stream) { 50 | read_file_to_stream(file_, stream); 51 | } 52 | 53 | private: 54 | 55 | FILE* file_; 56 | }; 57 | }}} // namespace ajg::synth::detail 58 | 59 | #endif // AJG_SYNTH_DETAIL_PIPE_HPP_INCLUDED 60 | -------------------------------------------------------------------------------- /ajg/synth/adapters/pointer.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_POINTER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_POINTER_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | namespace ajg { 12 | namespace synth { 13 | namespace adapters { 14 | 15 | // 16 | // specialization for void* 17 | //////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | template 20 | struct adapter : concrete_adapter { 21 | adapter(void* const adapted) : concrete_adapter(adapted) {} 22 | }; 23 | 24 | template 25 | struct adapter : concrete_adapter { 26 | adapter(void const* const adapted) : concrete_adapter(adapted) {} 27 | }; 28 | 29 | // 30 | // specialization for native pointers 31 | //////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | template 34 | struct adapter : forwarding_adapter { 35 | adapter(T* const adapted) : forwarding_adapter(adapted) {} 36 | 37 | template A forward() { return A(boost::ref(*this->adapted())); } 38 | template A forward() const { return A(boost::cref(*this->adapted())); } 39 | bool valid() const { return this->adapted() != 0; } 40 | }; 41 | 42 | }}} // namespace ajg::synth::adapters 43 | 44 | #endif // AJG_SYNTH_ADAPTERS_POINTER_HPP_INCLUDED 45 | -------------------------------------------------------------------------------- /ajg/synth/adapters/scoped_ptr.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_SCOPED_PTR_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_SCOPED_PTR_HPP_INCLUDED 7 | 8 | // #include 9 | #include 10 | #include 11 | 12 | namespace boost { 13 | template class scoped_ptr; 14 | } 15 | 16 | namespace ajg { 17 | namespace synth { 18 | namespace adapters { 19 | 20 | // 21 | // specialization for boost::scoped_ptr 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | template // NOTE: Adapted as a const reference since scoped_ptr is noncopyable. 25 | struct adapter > : forwarding_adapter const*, adapter > > { 26 | adapter(boost::scoped_ptr const& adapted) : forwarding_adapter const*, adapter > >(&adapted) {} 27 | 28 | template A forward() { return A(boost::ref(*this->adapted()->get())); } 29 | template A forward() const { return A(boost::cref(*this->adapted()->get())); } 30 | bool valid() const { return this->adapted()->get() != 0; } 31 | }; 32 | 33 | /* 34 | template 35 | struct adapter > : adapter { 36 | adapter(boost::scoped_ptr const& adapted) : adapter(adapted.get()) {} 37 | }; 38 | */ 39 | 40 | }}} // namespace ajg::synth::adapters 41 | 42 | #endif // AJG_SYNTH_ADAPTERS_SCOPED_PTR_HPP_INCLUDED 43 | 44 | -------------------------------------------------------------------------------- /ajg/synth/detail/standard_environment.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_STANDARD_ENVIRONMENT_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_STANDARD_ENVIRONMENT_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | #if !AJG_SYNTH_IS_PLATFORM_WINDOWS 13 | # include 14 | extern char **environ; 15 | #endif 16 | 17 | namespace ajg { 18 | namespace synth { 19 | namespace detail { 20 | 21 | // 22 | // standard_environment: 23 | // Safer and iterable interface to the program's environment. 24 | //////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | struct standard_environment { 27 | public: 28 | 29 | typedef boost::environment_iterator iterator; 30 | typedef boost::environment_iterator const_iterator; 31 | typedef iterator::value_type value_type; 32 | typedef value_type::first_type key_type; 33 | typedef value_type::second_type mapped_type; 34 | 35 | public: 36 | 37 | const_iterator begin() const { 38 | return const_iterator(environ); 39 | } 40 | 41 | const_iterator end() const { 42 | return const_iterator(); 43 | } 44 | 45 | const_iterator find(key_type const& name) const { 46 | const_iterator const end = this->end(); 47 | 48 | for (const_iterator it = begin(); it != end; ++it) { 49 | if (it->first == name) { 50 | return it; 51 | } 52 | } 53 | 54 | return end; 55 | } 56 | }; 57 | 58 | }}} // namespace ajg::synth::detail 59 | 60 | #endif // AJG_SYNTH_DETAIL_STANDARD_ENVIRONMENT_HPP_INCLUDED 61 | -------------------------------------------------------------------------------- /ajg/synth/detail/mutable_atomic_singleton.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_MUTABLE_ATOMIC_SINGLETON_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_MUTABLE_ATOMIC_SINGLETON_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace ajg { 14 | namespace synth { 15 | namespace detail { 16 | 17 | // Note: In theory header-safe due to extern inline [per 7.1.2/4]. 18 | // 19 | // extern inline T getset(boost::optional const v = boost::none) { 20 | // static T value = 0; 21 | // return v ? (value = *v) : value; 22 | // } 23 | 24 | // Note: In theory header-safe and atomic. 25 | // 26 | // extern inline T getset(boost::optional const v = boost::none) { 27 | // static boost::atomic value = 0; 28 | // return v ? value.store(*v, MemoryOrder), *v : value.load(MemoryOrder); 29 | // } 30 | 31 | /// 32 | /// mutable_atomic_singleton 33 | //////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | // The S parameter is so that every concrete derived type is unique. 36 | template 37 | struct mutable_atomic_singleton { 38 | public: 39 | 40 | inline static void set(T const& t) { getset(t); } 41 | inline static T get() { return getset(boost::none); } 42 | 43 | private: 44 | 45 | /* XXX: extern */ inline static T getset(boost::optional const& v) { 46 | static boost::atomic value; 47 | return v ? value.store(*v, MemoryOrder), *v : value.load(MemoryOrder); 48 | } 49 | }; 50 | 51 | }}} // namespace ajg::synth::detail 52 | 53 | #endif // AJG_SYNTH_DETAIL_MUTABLE_ATOMIC_SINGLETON_HPP_INCLUDED 54 | -------------------------------------------------------------------------------- /ajg/synth/adapters/container_adapter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_CONTAINER_ADAPTER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_CONTAINER_ADAPTER_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace adapters { 13 | 14 | // TODO: Move to own file. 15 | template 16 | struct range_adapter : concrete_adapter { 17 | range_adapter(Adapted const& adapted) : concrete_adapter(adapted) {} 18 | 19 | virtual optional get_range() const override { return typename Value::range_type(this->begin(), this->end()); } // TODO[c++11]: Use std::begin & std::end. 20 | 21 | protected: 22 | 23 | // TODO: Use CRTP to eliminate virtual call. 24 | // TODO[c++11]: Use std::begin & std::end instead. 25 | virtual Iterator begin() const = 0; 26 | virtual Iterator end() const = 0; 27 | }; 28 | 29 | // TODO: Use range_adapter. 30 | template 31 | struct container_adapter : concrete_adapter { 32 | container_adapter(Adapted const& adapted) : concrete_adapter(adapted) {} 33 | 34 | virtual optional get_range() const override { return typename Value::range_type(this->adapted().begin(), this->adapted().end()); } // TODO[c++11]: Use std::begin & std::end. 35 | }; 36 | 37 | }}} // namespace ajg::synth::adapters 38 | 39 | #endif // AJG_SYNTH_ADAPTERS_CONTAINER_ADAPTER_HPP_INCLUDED 40 | 41 | -------------------------------------------------------------------------------- /scripts/python-dist.bat: -------------------------------------------------------------------------------- 1 | REM ================== Starting 2 | :: Pre-requirements: 3 | :: cinst python 4 | :: cinst python2 5 | :: cinst python-x86_32 6 | :: cinst python2-x86_32 7 | :: 8 | :: c:\tools\python2\python.exe get-pip.py 9 | :: c:\tools\python2-x86_32\python.exe get-pip.py 10 | :: 11 | :: c:\tools\python\Scripts\pip.exe install setuptools wheel --upgrade 12 | :: c:\tools\python2\Scripts\pip.exe install setuptools wheel --upgrade 13 | :: c:\tools\python-x86_32\Scripts\pip.exe install setuptools wheel --upgrade 14 | :: c:\tools\python2-x86_32\Scripts\pip.exe install setuptools wheel --upgrade 15 | 16 | REM ================== Building and Uploading Synth for Python 3 (x64) 17 | c:\tools\python\python.exe .\setup.py clean --all 18 | c:\tools\python\python.exe .\setup.py bdist upload 19 | c:\tools\python\python.exe .\setup.py bdist_egg upload 20 | c:\tools\python\python.exe .\setup.py bdist_wininst upload 21 | c:\tools\python\python.exe .\setup.py bdist_wheel upload 22 | REM ================== Done 23 | 24 | REM ================== Building and Uploading Synth for Python 2 (x64) 25 | c:\tools\python2\python.exe .\setup.py clean --all 26 | c:\tools\python2\python.exe .\setup.py bdist upload 27 | c:\tools\python2\python.exe .\setup.py bdist_egg upload 28 | c:\tools\python2\python.exe .\setup.py bdist_wininst upload 29 | c:\tools\python2\python.exe .\setup.py bdist_wheel upload 30 | REM ================== Done 31 | 32 | REM ================== Building and Uploading Synth for Python 3 (x86) 33 | c:\tools\python-x86_32\python.exe .\setup.py clean --all 34 | c:\tools\python-x86_32\python.exe .\setup.py bdist upload 35 | c:\tools\python-x86_32\python.exe .\setup.py bdist_egg upload 36 | c:\tools\python-x86_32\python.exe .\setup.py bdist_wininst upload 37 | c:\tools\python-x86_32\python.exe .\setup.py bdist_wheel upload 38 | REM ================== Done 39 | 40 | REM ================== Building and Uploading Synth for Python 2 (x86) 41 | c:\tools\python2-x86_32\python.exe .\setup.py clean --all 42 | c:\tools\python2-x86_32\python.exe .\setup.py bdist upload 43 | c:\tools\python2-x86_32\python.exe .\setup.py bdist_egg upload 44 | c:\tools\python2-x86_32\python.exe .\setup.py bdist_wininst upload 45 | c:\tools\python2-x86_32\python.exe .\setup.py bdist_wheel upload 46 | REM ================== Done 47 | 48 | REM ================== Finishing 49 | -------------------------------------------------------------------------------- /synth.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "build_systems": 3 | [ 4 | /* TODO: Use variants instead of this mess. */ 5 | { 6 | "cmd": "scons && python setup.py clean --all install", 7 | "shell": true, 8 | "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$", 9 | "name": "Synth: Build All (release)", 10 | "path": "/usr/local/bin:$PATH", 11 | "working_dir": "${project_path}" 12 | }, 13 | { 14 | "cmd": "scons debug=1 synth", 15 | "shell": true, 16 | "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$", 17 | "name": "Synth: Build Command-Line Tool (debug)", 18 | "path": "/usr/local/bin:$PATH", 19 | "working_dir": "${project_path}" 20 | }, 21 | { 22 | /* TODO: Build python module in debug mode (but without debugging symbols) which is usually faster. */ 23 | "cmd": "scons debug=1 tests/harness.out && tests/harness.out && python setup.py clean --all install && python tests/harness.py && scons debug=1 synth", 24 | "shell": true, 25 | "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$", 26 | "name": "Synth: Build All & Run Tests (debug)", 27 | "path": "/usr/local/bin:$PATH", 28 | "working_dir": "${project_path}" 29 | } 30 | ], 31 | "folders": 32 | [ 33 | { 34 | "file_exclude_patterns": 35 | [ 36 | ".sconsign.dblite", 37 | "synth", 38 | "tests/harness.out", 39 | "examples/all", 40 | "*.ilk", 41 | "*.log", 42 | "*.tlog", 43 | "*.opensdf", 44 | "*.o", 45 | "*.o-*", 46 | "*.os", 47 | "*.os-*", 48 | "*.pyc", 49 | "*.so" 50 | ], 51 | "folder_exclude_patterns": 52 | [ 53 | "build", 54 | "dist", 55 | "external", 56 | "*.egg-info" 57 | ], 58 | "follow_symlinks": true, 59 | "path": "." 60 | } 61 | ], 62 | "settings": 63 | { 64 | "rulers": 65 | [ 66 | 100 67 | ], 68 | "tab_size": 4, 69 | "word_wrap": false 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ajg/synth/bindings/command_line/binding.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_BINDINGS_COMMAND_LINE_BINDING_HPP_INCLUDED 6 | #define AJG_SYNTH_BINDINGS_COMMAND_LINE_BINDING_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace ajg { 15 | namespace synth { 16 | namespace bindings { 17 | namespace command_line { 18 | 19 | namespace pt = boost::property_tree; 20 | 21 | template 22 | struct binding : bindings::base_binding< Traits 23 | // TODO: Use value_type 24 | , pt::basic_ptree 25 | , templates::stream_template 26 | , engines::django::engine 27 | , engines::ssi::engine 28 | , engines::tmpl::engine 29 | > { 30 | public: 31 | 32 | typedef binding binding_type; 33 | typedef Traits traits_type; 34 | typedef typename binding::base_binding_type base_type; 35 | 36 | typedef typename base_type::source_type source_type; 37 | typedef typename base_type::options_type options_type; 38 | 39 | typedef typename traits_type::string_type string_type; 40 | 41 | public: 42 | 43 | binding( source_type source 44 | , string_type const& engine 45 | , options_type const& options 46 | ) : base_type(source, engine, options) {} 47 | 48 | public: 49 | 50 | using base_type::render_to_stream; 51 | using base_type::render_to_string; 52 | using base_type::render_to_path; 53 | }; 54 | 55 | }}}} // namespace ajg::synth::bindings::command_line 56 | 57 | #endif // AJG_SYNTH_BINDINGS_COMMAND_LINE_BINDING_HPP_INCLUDED 58 | -------------------------------------------------------------------------------- /ajg/synth/adapters/adapter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_ADAPTER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_ADAPTER_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace adapters { 13 | 14 | // 15 | // Shortcut macros 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// 17 | 18 | #define AJG_SYNTH_ADAPTER_TYPEDEFS(value) \ 19 | public: \ 20 | typedef value value_type; \ 21 | typedef typename value_type::iterator iterator; \ 22 | typedef typename value_type::const_iterator const_iterator; \ 23 | typedef typename value_type::range_type range_type; \ 24 | typedef typename value_type::attribute_type attribute_type; \ 25 | typedef typename value_type::attributes_type attributes_type; \ 26 | typedef typename value_type::adapter_type adapter_type; \ 27 | typedef typename value_type::traits_type traits_type; \ 28 | \ 29 | typedef typename traits_type::boolean_type boolean_type; \ 30 | typedef typename traits_type::char_type char_type; \ 31 | typedef typename traits_type::size_type size_type; \ 32 | typedef typename traits_type::integer_type integer_type; \ 33 | typedef typename traits_type::floating_type floating_type; \ 34 | typedef typename traits_type::number_type number_type; \ 35 | typedef typename traits_type::string_type string_type; \ 36 | typedef typename traits_type::datetime_type datetime_type; \ 37 | typedef typename traits_type::duration_type duration_type; \ 38 | typedef typename traits_type::istream_type istream_type; \ 39 | typedef typename traits_type::ostream_type ostream_type 40 | 41 | // 42 | // adapter (unspecialized) 43 | //////////////////////////////////////////////////////////////////////////////////////////////////// 44 | 45 | template 46 | struct adapter; 47 | 48 | template 49 | struct adapter >; // Left undefined. 50 | 51 | }}} // namespace ajg::synth::adapters 52 | 53 | #endif // AJG_SYNTH_ADAPTERS_ADAPTER_HPP_INCLUDED 54 | 55 | -------------------------------------------------------------------------------- /ajg/synth/bindings/python/module.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | // TODO? #include 6 | #include // This prevents a strange macro issue in pyport.h. 7 | #include // Not included by default by Python.h. 8 | #include // Must come ahead of everything except Python.h. 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | BOOST_PYTHON_MODULE(synth) { 16 | PyDateTime_IMPORT; 17 | namespace s = ajg::synth; 18 | namespace py = boost::python; 19 | 20 | typedef s::default_traits traits_type; 21 | typedef s::bindings::python::binding binding_type; 22 | 23 | binding_type::prime(); 24 | 25 | py::def("version", s::bindings::python::version); 26 | 27 | py::scope().attr("CACHE_NONE") = static_cast(s::caching_none); 28 | py::scope().attr("CACHE_ALL") = static_cast(s::caching_all); 29 | py::scope().attr("CACHE_PATHS") = static_cast(s::caching_paths); 30 | py::scope().attr("CACHE_BUFFERS") = static_cast(s::caching_buffers); 31 | py::scope().attr("CACHE_STRINGS") = static_cast(s::caching_strings); 32 | py::scope().attr("CACHE_PER_THREAD") = static_cast(s::caching_per_thread); 33 | py::scope().attr("CACHE_PER_PROCESS") = static_cast(s::caching_per_process); 34 | 35 | /* XXX: Doesn't work with flag-like (bitwise) enums. 36 | py::enum_("caching") 37 | .value("NONE", s::caching_none) 38 | ; 39 | */ 40 | 41 | py::class_("Template", binding_type::constructor_type()) 42 | .def("render_to_file", &binding_type::render_to_file) 43 | .def("render_to_path", &binding_type::render_to_path) 44 | .def("render_to_string", &binding_type::render_to_string) 45 | // TODO: Use a property instead. 46 | .def("set_default_options", &binding_type::set_default_options).staticmethod("set_default_options") 47 | ; 48 | } 49 | -------------------------------------------------------------------------------- /ajg/synth/templates/string_template.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_TEMPLATES_STRING_TEMPLATE_HPP_INCLUDED 6 | #define AJG_SYNTH_TEMPLATES_STRING_TEMPLATE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | namespace ajg { 11 | namespace synth { 12 | namespace templates { 13 | 14 | template 15 | struct string_template : base_template { 16 | public: 17 | 18 | typedef string_template template_type; 19 | typedef Engine engine_type; 20 | typedef typename engine_type::options_type options_type; 21 | typedef typename options_type::traits_type traits_type; 22 | 23 | typedef typename traits_type::boolean_type boolean_type; 24 | typedef typename traits_type::size_type size_type; 25 | typedef typename traits_type::string_type string_type; 26 | 27 | typedef string_type const source_type; 28 | typedef size_type key_type; 29 | 30 | public: 31 | 32 | string_template(string_type const& source, options_type const& options = options_type()) : source_(source) { 33 | this->reset(this->source_.begin(), this->source_.end(), options); 34 | } 35 | 36 | template 37 | string_template(I const& begin, I const& end, options_type const& options = options_type()) : source_(begin, end) { 38 | this->reset(this->source_.begin(), this->source_.end(), options); 39 | } 40 | 41 | public: 42 | 43 | inline string_type const& source() const { return this->source_; } 44 | 45 | inline static key_type const key(string_type const& source) { return source.size(); } 46 | 47 | inline boolean_type same(string_type const& source, options_type const& options) const { 48 | return this->source_ == source; 49 | } 50 | 51 | inline boolean_type stale(string_type const& source, options_type const& options) const { 52 | AJG_SYNTH_ASSERT(this->same(source, options)); 53 | return false; 54 | } 55 | 56 | private: 57 | 58 | source_type source_; 59 | }; 60 | 61 | }}} // namespace ajg::synth::templates 62 | 63 | #endif // AJG_SYNTH_TEMPLATES_STRING_TEMPLATE_HPP_INCLUDED 64 | -------------------------------------------------------------------------------- /ajg/synth/templates/stream_template.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_TEMPLATES_STREAM_TEMPLATE_HPP_INCLUDED 6 | #define AJG_SYNTH_TEMPLATES_STREAM_TEMPLATE_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | namespace ajg { 12 | namespace synth { 13 | namespace templates { 14 | 15 | template 16 | struct stream_template : base_template::iterator> { 19 | 20 | public: 21 | 22 | typedef stream_template template_type; 23 | typedef Engine engine_type; 24 | typedef typename engine_type::options_type options_type; 25 | typedef typename options_type::traits_type traits_type; 26 | 27 | typedef typename traits_type::boolean_type boolean_type; 28 | typedef typename traits_type::size_type size_type; 29 | typedef typename traits_type::istream_type istream_type; 30 | 31 | typedef istream_type& source_type; 32 | typedef size_type key_type; 33 | 34 | private: 35 | 36 | typedef detail::bidirectional_input_stream bidi_istream_type; 37 | 38 | public: 39 | 40 | stream_template(istream_type& source, options_type const& options = options_type()) : source_(source), bidi_istream_(source_) { 41 | this->reset(this->bidi_istream_.begin(), this->bidi_istream_.end(), options); 42 | } 43 | 44 | public: 45 | 46 | istream_type const& source() const { return this->source_; } 47 | 48 | inline static key_type const key(istream_type const& source) { return key_type(0); } 49 | 50 | inline boolean_type same(istream_type const& source, options_type const& options) const { 51 | return false; 52 | } 53 | 54 | inline boolean_type stale(istream_type const& source, options_type const& options) const { 55 | AJG_SYNTH_ASSERT(this->same(source, options)); 56 | return true; 57 | } 58 | private: 59 | 60 | source_type source_; 61 | bidi_istream_type bidi_istream_; 62 | }; 63 | 64 | }}} // namespace ajg::synth::templates 65 | 66 | #endif // AJG_SYNTH_TEMPLATES_STREAM_TEMPLATE_HPP_INCLUDED 67 | -------------------------------------------------------------------------------- /ajg/synth/adapters/numeric.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_NUMERIC_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_NUMERIC_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | namespace ajg { 20 | namespace synth { 21 | namespace adapters { 22 | 23 | #define AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER_(type, flags) \ 24 | template \ 25 | struct adapter : numeric_adapter { \ 26 | adapter(type const value) : numeric_adapter(value) {} \ 27 | } \ 28 | 29 | #define AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(type) \ 30 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER_(type, unspecified) 31 | 32 | // 33 | // Integral specializations 34 | //////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | // XXX: These should probably be adapted as character/textual rather than numerically. 37 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER_(char, textual | character); 38 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER_(char signed, textual | character); 39 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER_(char unsigned, textual | character); 40 | 41 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 42 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER_(wchar_t, textual | character); 43 | #endif 44 | 45 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(short); 46 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(short unsigned); 47 | 48 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(int); 49 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(int unsigned); 50 | 51 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(long); 52 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(long unsigned); 53 | 54 | #ifndef AJG_SYNTH_CONFIG_NO_LONG_LONG 55 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(long long); 56 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(long long unsigned); 57 | #elif AJG_SYNTH_IS_COMPILER_MSVC 58 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(__int64); 59 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(__int64 unsigned); 60 | #endif 61 | 62 | // 63 | // Floating-point specializations 64 | //////////////////////////////////////////////////////////////////////////////////////////////////// 65 | 66 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(float); 67 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(double); 68 | AJG_SYNTH_SPECIALIZE_NUMERIC_ADAPTER(long double); 69 | 70 | 71 | }}} // namespace ajg::synth::adapters 72 | 73 | #endif // AJG_SYNTH_ADAPTERS_NUMERIC_HPP_INCLUDED 74 | 75 | -------------------------------------------------------------------------------- /ajg/synth/engines/null/engine.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_NULL_ENGINE_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_NULL_ENGINE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace engines { 15 | namespace null { 16 | 17 | template 18 | struct engine : base_engine { 19 | public: 20 | 21 | typedef engine engine_type; 22 | typedef Traits traits_type; 23 | 24 | typedef typename traits_type::boolean_type boolean_type; 25 | typedef typename traits_type::char_type char_type; 26 | typedef typename traits_type::size_type size_type; 27 | typedef typename traits_type::path_type path_type; 28 | typedef typename traits_type::string_type string_type; 29 | typedef typename traits_type::ostream_type ostream_type; 30 | 31 | typedef typename engine_type::value_type value_type; 32 | typedef typename engine_type::options_type options_type; 33 | 34 | typedef typename options_type::context_type context_type; 35 | 36 | template 37 | struct kernel; 38 | 39 | public: 40 | 41 | inline static char const* name() { return "null"; } 42 | 43 | }; // engine 44 | 45 | 46 | template 47 | template 48 | struct engine::kernel : base_engine::AJG_SYNTH_TEMPLATE base_kernel { 49 | public: 50 | 51 | typedef kernel kernel_type; 52 | typedef Iterator iterator_type; 53 | typedef engine engine_type; 54 | typedef typename kernel_type::state_type state_type; 55 | typedef typename kernel_type::range_type range_type; 56 | 57 | public: 58 | 59 | kernel() {} 60 | 61 | public: 62 | 63 | inline void parse(state_type*) const {} 64 | inline void render(ostream_type&, options_type const&, state_type const&, context_type&) const {} 65 | 66 | }; // kernel 67 | 68 | }}}} // namespace ajg::synth::engines::null 69 | 70 | #endif // AJG_SYNTH_ENGINES_NULL_ENGINE_HPP_INCLUDED 71 | 72 | -------------------------------------------------------------------------------- /tests/templates/django/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% block title %}{{ title }}{% endblock %}{% block title_extra %}{% endblock %} 5 | 6 | {% block site_meta %} 7 | {% endblock %} 8 | 9 | {% block meta %} 10 | {% endblock %} 11 | 12 | 13 | {% if not request.user.is_staff %} 14 | 25 | {% endif %} 26 | 27 | 28 |
29 |
30 |
31 | 39 |
40 |
41 |
42 | {% if messages %}
{% include "messages.html" %}
{% endif %} 43 | {% block prefix %}{% endblock %} 44 | {% block content %}{% endblock %} 45 | {% block suffix %}{% endblock %} 46 |
47 |
48 |
49 | {% block left %}{% endblock %} 50 |
51 | 54 |
{% block columns_suffix %}{% endblock %}
55 |
56 |
57 |
58 |
59 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /ajg/synth/adapters/array.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_ARRAY_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_ARRAY_HPP_INCLUDED 7 | 8 | namespace boost { 9 | 10 | // Forward declaration. 11 | template class array; 12 | 13 | } 14 | 15 | #include 16 | #include 17 | 18 | namespace ajg { 19 | namespace synth { 20 | namespace adapters { 21 | 22 | // 23 | // specialization for native arrays of statically known size 24 | //////////////////////////////////////////////////////////////////////////////////////////////////// 25 | 26 | // NOTE: A reference is stored and not a copy because initializing an array within a constructor's 27 | // initializer list ranges from difficult to impossible in C++03. 28 | // TODO[c++11]: Store array by value. 29 | 30 | 31 | template 32 | struct adapter : range_adapter, T const*, sequential> { 33 | adapter(T const (&adapted)[N]) : range_adapter, T const*, sequential>(adapted) {} 34 | 35 | virtual T const* begin() const { return static_cast(this->adapted()); } 36 | virtual T const* end() const { return static_cast(this->adapted()) + N; } 37 | }; 38 | 39 | // 40 | // specialization for native arrays of statically unknown size 41 | // TODO[c++14]: Remove support for this nastiness and defer to std::dynarray. 42 | //////////////////////////////////////////////////////////////////////////////////////////////////// 43 | 44 | template 45 | struct adapter : range_adapter, T const*, sequential> { 46 | adapter(T* const adapted, std::size_t const length) : range_adapter, T const*, sequential>(adapted), length_(length) {} 47 | 48 | virtual T const* begin() const { return static_cast(this->adapted()); } 49 | virtual T const* end() const { return static_cast(this->adapted()) + this->length_; } 50 | 51 | private: 52 | 53 | std::size_t length_; 54 | }; 55 | 56 | // 57 | // specialization for boost::array 58 | //////////////////////////////////////////////////////////////////////////////////////////////////// 59 | 60 | template 61 | struct adapter > : container_adapter, sequential> { 62 | adapter(boost::array const& adapted) : container_adapter, sequential>(adapted) {} 63 | }; 64 | 65 | }}} // namespace ajg::synth::adapters 66 | 67 | #endif // AJG_SYNTH_ADAPTERS_ARRAY_HPP_INCLUDED 68 | 69 | -------------------------------------------------------------------------------- /ajg/synth/config.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_CONFIG_HPP_INCLUDED 6 | #define AJG_SYNTH_CONFIG_HPP_INCLUDED 7 | 8 | #include 9 | 10 | // 11 | // AJG_SYNTH_CONFIG_DEFAULT_CHAR_TYPE 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | #ifndef AJG_SYNTH_CONFIG_DEFAULT_CHAR_TYPE 15 | #define AJG_SYNTH_CONFIG_DEFAULT_CHAR_TYPE char 16 | #endif 17 | 18 | // 19 | // AJG_SYNTH_CONFIG_MAX_TEMPLATE_DEPTH: 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | #ifndef AJG_SYNTH_CONFIG_MAX_TEMPLATE_DEPTH 23 | #define AJG_SYNTH_CONFIG_MAX_TEMPLATE_DEPTH 1024 24 | #endif 25 | 26 | // 27 | // AJG_SYNTH_CONFIG_MAX_FRAMES: 28 | //////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | #ifndef AJG_SYNTH_CONFIG_MAX_FRAMES 31 | #define AJG_SYNTH_CONFIG_MAX_FRAMES 1024 32 | #endif 33 | 34 | // 35 | // AJG_SYNTH_CONFIG_NO_WCHAR_T 36 | // FIXME: Needs boost/config.hpp, which is not yet available here. 37 | //////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | #if defined(BOOST_NO_INTRINSIC_WCHAR_T) \ 40 | || defined(BOOST_NO_STD_WSTREAMBUF) \ 41 | || defined(BOOST_NO_STD_WSTRING) \ 42 | || defined(DISABLE_WIDE_CHAR_SUPPORT) 43 | # ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 44 | # define AJG_SYNTH_CONFIG_NO_WCHAR_T 45 | # endif 46 | #endif 47 | 48 | // 49 | // AJG_SYNTH_CONFIG_NO_LONG_LONG 50 | // FIXME: Needs boost/config.hpp, which is not yet available here. 51 | //////////////////////////////////////////////////////////////////////////////////////////////////// 52 | 53 | #if !defined(BOOST_HAS_LONG_LONG) 54 | # ifndef AJG_SYNTH_CONFIG_NO_LONG_LONG 55 | # define AJG_SYNTH_CONFIG_NO_LONG_LONG 56 | # endif 57 | #endif 58 | 59 | // 60 | // AJG_SYNTH_CONFIG_NO_DEBUG 61 | //////////////////////////////////////////////////////////////////////////////////////////////////// 62 | 63 | #if defined(NDEBUG) 64 | # ifndef AJG_SYNTH_CONFIG_NO_DEBUG 65 | # define AJG_SYNTH_CONFIG_NO_DEBUG 66 | # endif 67 | #endif 68 | 69 | // 70 | // AJG_SYNTH_CONFIG_HANDLE_EXCEPTION 71 | //////////////////////////////////////////////////////////////////////////////////////////////////// 72 | 73 | #ifndef AJG_SYNTH_CONFIG_HANDLE_EXCEPTION 74 | #define AJG_SYNTH_CONFIG_HANDLE_EXCEPTION(e) (::boost::throw_exception(e)) 75 | #include 76 | #endif 77 | 78 | // 79 | // AJG_SYNTH_CONFIG_HANDLE_ASSERT: 80 | //////////////////////////////////////////////////////////////////////////////////////////////////// 81 | 82 | #ifndef AJG_SYNTH_CONFIG_HANDLE_ASSERT 83 | #define AJG_SYNTH_CONFIG_HANDLE_ASSERT(e) (BOOST_ASSERT(e)) 84 | #include 85 | #endif 86 | 87 | #endif // AJG_SYNTH_CONFIG_HPP_INCLUDED 88 | -------------------------------------------------------------------------------- /ajg/synth/adapters/map.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_MAP_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_MAP_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::map 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct adapter > : container_adapter, associative> { 22 | adapter(std::map const& adapted) : container_adapter, associative>(adapted) {} 23 | 24 | AJG_SYNTH_ADAPTER_TYPEDEFS(Value); 25 | 26 | virtual attribute_type attribute(value_type const& key) const { 27 | K const k = key.template to(); 28 | typename std::map::const_iterator const it = this->adapted().find(k); 29 | if (it == this->adapted().end()) { 30 | return boost::none; 31 | } 32 | return value_type(it->second); 33 | } 34 | 35 | virtual void attribute(value_type const& key, attribute_type const& attr) const { 36 | K const k = key.template to(); 37 | this->adapted().erase(k); 38 | 39 | if (attr) { 40 | V const v = attr->template to(); 41 | this->adapted().insert(typename std::map::value_type(k, v)); 42 | } 43 | } 44 | 45 | virtual attributes_type attributes() const { 46 | attributes_type attributes; 47 | typedef typename std::map::value_type pair_type; 48 | for (auto const& kv : this->adapted()) { 49 | attributes.insert(kv.first); 50 | } 51 | return attributes; 52 | } 53 | }; 54 | 55 | // 56 | // specialization for std::multimap 57 | //////////////////////////////////////////////////////////////////////////////////////////////////// 58 | 59 | template 60 | struct adapter > : container_adapter, associative> { 61 | adapter(std::multimap const& adapted) : container_adapter, associative>(adapted) {} 62 | 63 | AJG_SYNTH_ADAPTER_TYPEDEFS(Value); 64 | 65 | // TODO: Implement attribute(k), but returning a sequence or set of values, or the first one? 66 | // TODO: Implement attribute(k, v) 67 | 68 | virtual attributes_type attributes() const { 69 | attributes_type attributes; 70 | typedef typename std::multimap::value_type pair_type; 71 | for (auto const& kv : this->adapted()) { 72 | attributes.insert(kv.first); 73 | } 74 | return attributes; 75 | } 76 | }; 77 | 78 | }}} // namespace ajg::synth::adapters 79 | 80 | #endif // AJG_SYNTH_ADAPTERS_MAP_HPP_INCLUDED 81 | 82 | 83 | -------------------------------------------------------------------------------- /tests/groups/templates.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace { 13 | 14 | namespace s = ajg::synth; 15 | 16 | using s::detail::read_path_to_string; 17 | 18 | typedef s::engines::null::engine > char_engine; 19 | 20 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 21 | 22 | typedef s::engines::null::engine > wchar_t_engine; 23 | 24 | #endif 25 | 26 | AJG_SYNTH_TEST_GROUP("templates"); 27 | 28 | } // namespace 29 | 30 | AJG_SYNTH_TEST_UNIT(buffer_template::str char array) { 31 | s::templates::buffer_template const t("foo bar qux"); 32 | MUST_EQUAL(t.str(), "foo bar qux"); 33 | }}} 34 | 35 | AJG_SYNTH_TEST_UNIT(buffer_template::str char pointer) { 36 | char const *const s = "foo bar qux"; 37 | s::templates::buffer_template const t(s); 38 | MUST_EQUAL(t.str(), "foo bar qux"); 39 | }}} 40 | 41 | AJG_SYNTH_TEST_UNIT(path_template::str char) { 42 | s::templates::path_template const t("tests/templates/tmpl/variables.tmpl"); 43 | MUST_EQUAL(t.str(), read_path_to_string("tests/templates/tmpl/variables.tmpl")); 44 | }}} 45 | 46 | AJG_SYNTH_TEST_UNIT(stream_template::str char) { 47 | std::istringstream stream("foo bar qux"); 48 | s::templates::stream_template const t(stream); 49 | MUST_EQUAL(t.str(), "foo bar qux"); 50 | }}} 51 | 52 | AJG_SYNTH_TEST_UNIT(string_template::str char) { 53 | s::templates::string_template const t("foo bar qux"); 54 | MUST_EQUAL(t.str(), "foo bar qux"); 55 | }}} 56 | 57 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 58 | 59 | AJG_SYNTH_TEST_UNIT(buffer_template::str wchar_t array) { 60 | s::templates::buffer_template const t(L"foo bar qux"); 61 | MUST_EQUAL(t.str(), L"foo bar qux"); 62 | }}} 63 | 64 | AJG_SYNTH_TEST_UNIT(buffer_template::str wchar_t pointer) { 65 | wchar_t const *const s = L"foo bar qux"; 66 | s::templates::buffer_template const t(s); 67 | MUST_EQUAL(t.str(), L"foo bar qux"); 68 | }}} 69 | 70 | AJG_SYNTH_TEST_UNIT(path_template::str wchar_t) { 71 | s::templates::path_template const t(L"tests/templates/tmpl/variables.tmpl"); 72 | MUST_EQUAL(t.str(), read_path_to_string("tests/templates/tmpl/variables.tmpl")); 73 | }}} 74 | 75 | AJG_SYNTH_TEST_UNIT(stream_template::str wchar_t) { 76 | std::wistringstream stream(L"foo bar qux"); 77 | s::templates::stream_template const t(stream); 78 | MUST_EQUAL(t.str(), L"foo bar qux"); 79 | }}} 80 | 81 | AJG_SYNTH_TEST_UNIT(string_template::str wchar_t) { 82 | s::templates::string_template const t(L"foo bar qux"); 83 | MUST_EQUAL(t.str(), L"foo bar qux"); 84 | }}} 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /ajg/synth/engines/null/resolver.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ENGINES_NULL_RESOLVER_HPP_INCLUDED 6 | #define AJG_SYNTH_ENGINES_NULL_RESOLVER_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace ajg { 14 | namespace synth { 15 | namespace engines { 16 | namespace null { 17 | 18 | template 19 | struct resolver : Options::abstract_resolver { 20 | public: 21 | 22 | typedef Options options_type; 23 | typedef typename options_type::traits_type traits_type; 24 | typedef typename options_type::size_type size_type; 25 | typedef typename options_type::string_type string_type; 26 | typedef typename options_type::value_type value_type; 27 | typedef typename options_type::context_type context_type; 28 | typedef typename options_type::url_type url_type; 29 | typedef typename options_type::arguments_type arguments_type; 30 | typedef std::map patterns_type; 31 | 32 | private: 33 | 34 | typedef detail::text text; 35 | 36 | public: 37 | 38 | virtual url_type resolve( string_type const& path 39 | , context_type const& context 40 | , options_type const& options 41 | ) { 42 | return url_type(); 43 | } 44 | 45 | virtual url_type reverse( string_type const& name 46 | , arguments_type const& arguments 47 | , context_type const& context 48 | , options_type const& options 49 | ) { 50 | // NOTE: This resolver is only meant to be used in tests, as it does no escaping. 51 | typename patterns_type::const_iterator it = patterns_.find(name); 52 | if (it == patterns_.end()) { 53 | return url_type(); 54 | } 55 | 56 | string_type path, query; 57 | for (auto const& arg : arguments.first) { 58 | path += text::literal("/") + arg.to_string(); 59 | } 60 | size_type i = 0; 61 | for (auto const& karg : arguments.second) { 62 | query += i++ ? text::literal("&") : text::literal("?"); 63 | query += karg.first + text::literal("=") + karg.second.to_string(); 64 | } 65 | return url_type(it->second + path + query); 66 | } 67 | 68 | explicit resolver(patterns_type patterns) : patterns_(patterns) {} 69 | virtual ~resolver() {} 70 | 71 | private: 72 | 73 | patterns_type patterns_; 74 | }; // resolver 75 | 76 | }}}} // namespace ajg::synth::engines::null 77 | 78 | #endif // AJG_SYNTH_ENGINES_NULL_RESOLVER_HPP_INCLUDED 79 | 80 | -------------------------------------------------------------------------------- /ajg/synth/bindings/python/resolver.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_BINDINGS_PYTHON_RESOLVER_HPP_INCLUDED 6 | #define AJG_SYNTH_BINDINGS_PYTHON_RESOLVER_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | namespace ajg { 12 | namespace synth { 13 | namespace bindings { 14 | namespace python { 15 | 16 | // 17 | // resolver 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template 21 | struct resolver : Options::abstract_resolver { 22 | public: 23 | 24 | typedef Options options_type; 25 | 26 | typedef typename options_type::value_type value_type; 27 | typedef typename options_type::context_type context_type; 28 | typedef typename options_type::traits_type traits_type; 29 | 30 | typedef typename value_type::arguments_type arguments_type; 31 | 32 | typedef typename traits_type::string_type string_type; 33 | typedef typename traits_type::url_type url_type; 34 | 35 | private: 36 | 37 | typedef conversions c; 38 | 39 | public: 40 | 41 | virtual url_type resolve( string_type const& path 42 | , context_type const& context 43 | , options_type const& options 44 | ) { 45 | try { 46 | // TODO: Pass the context and have django-synth handle eliding it. 47 | return url_type(c::make_string(this->resolver_(path))); 48 | } 49 | catch (...) { // TODO: Catch only Resolver404? 50 | return url_type(); 51 | } 52 | } 53 | 54 | 55 | virtual url_type reverse( string_type const& name 56 | , arguments_type const& arguments 57 | , context_type const& context 58 | , options_type const& options 59 | ) { 60 | try { 61 | std::pair const args = c::make_args(arguments); 62 | // TODO: Pass the context instead and let django-synth handle the mapping. 63 | return url_type(c::make_string(this->reverser_(name, c::make_none(), // == urlconf 64 | args.first, args.second, context.application()))); 65 | } 66 | catch (...) { // TODO: Catch only NoReverseMatch? 67 | return url_type(); 68 | } 69 | } 70 | 71 | explicit resolver(py::object const& obj) 72 | : resolver_(obj.attr("resolve")) 73 | , reverser_(obj.attr("reverse")) {} 74 | virtual ~resolver() {} 75 | 76 | private: 77 | 78 | py::object /*const*/ resolver_; 79 | py::object /*const*/ reverser_; 80 | }; 81 | 82 | }}}} // namespace ajg::synth::bindings::python 83 | 84 | #endif // AJG_SYNTH_BINDINGS_PYTHON_RESOLVER_HPP_INCLUDED 85 | -------------------------------------------------------------------------------- /ajg/synth/adapters/ptree.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_PTREE_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_PTREE_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace ajg { 16 | namespace synth { 17 | namespace adapters { 18 | 19 | // 20 | // specialization for boost::property_tree::basic_ptree 21 | // TODO: Factor out a common associative_adapter and share it with map/multimap. 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// 23 | 24 | template 25 | struct adapter > : container_adapter, type_flags(sequential | associative)> { 26 | adapter(boost::property_tree::basic_ptree const& adapted) : container_adapter, type_flags(sequential | associative)>(adapted) {} 27 | 28 | AJG_SYNTH_ADAPTER_TYPEDEFS(Value); 29 | 30 | virtual optional get_boolean() const override { 31 | return !this->adapted().empty() || boolean_type(value_type(this->adapted().data())); 32 | } 33 | 34 | virtual attribute_type attribute(value_type const& key) const override { 35 | K const k = key.template to(); 36 | typename boost::property_tree::basic_ptree::const_assoc_iterator const it = this->adapted().find(k); 37 | if (it == this->adapted().not_found()) { 38 | return boost::none; 39 | } 40 | return value_type(it->second); 41 | } 42 | 43 | // TODO: attribute(k, v) 44 | // TODO: attributes() 45 | 46 | virtual boolean_type output(ostream_type& ostream) const override { 47 | if (this->adapted().empty()) { 48 | ostream << value_type(this->adapted().data()); 49 | } 50 | else { 51 | value_type::delimited(ostream, range_type(this->adapted().begin(), this->adapted().end())); 52 | } 53 | return true; 54 | } 55 | }; 56 | 57 | }}} // namespace ajg::synth::adapters 58 | 59 | namespace boost { 60 | namespace property_tree { 61 | 62 | template 63 | inline bool operator <( basic_ptree const& a 64 | , basic_ptree const& b 65 | ) { 66 | return a.data() < b.data() && std::lexicographical_compare( a.ordered_begin(), a.not_found() 67 | , b.ordered_begin(), b.not_found() 68 | ); 69 | } 70 | 71 | // Seems needed by the command_line binding. 72 | // TODO: Determine whether it's actually used, otherwise leave it undefined. 73 | template 74 | inline std::basic_ostream& operator <<(std::basic_ostream& ostream 75 | , basic_ptree const& 76 | ) { 77 | return ostream << "TODO"; 78 | } 79 | 80 | }} // namespace boost::property_tree 81 | 82 | #endif // AJG_SYNTH_ADAPTERS_PTREE_HPP_INCLUDED 83 | 84 | 85 | -------------------------------------------------------------------------------- /ajg/synth/adapters/ptime.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_PTIME_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_PTIME_HPP_INCLUDED 7 | 8 | // TODO: Move local_time adapters to own files and add a date_time group header. 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace ajg { 15 | namespace synth { 16 | namespace adapters { 17 | 18 | // 19 | // specialization for boost::posix_time::ptime 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | template 23 | struct adapter : concrete_adapter { 24 | adapter( boost::posix_time::ptime const& adapted) : concrete_adapter(adapted) {} 25 | 26 | virtual optional get_boolean() const { return !this->adapted().is_not_a_date_time(); } 27 | virtual optional get_datetime() const { return Value::traits_type::to_datetime(this->adapted()); } 28 | }; 29 | 30 | // 31 | // specialization for boost::local_time::local_date_time 32 | //////////////////////////////////////////////////////////////////////////////////////////////////// 33 | 34 | template 35 | struct adapter : concrete_adapter { 36 | adapter( boost::local_time::local_date_time const& adapted) : concrete_adapter(adapted) {} 37 | 38 | virtual optional get_boolean() const { return !this->adapted().is_not_a_date_time(); } 39 | virtual optional get_datetime() const { return this->adapted(); } 40 | }; 41 | 42 | // 43 | // specialization for boost::local_time::time_zone_ptr 44 | //////////////////////////////////////////////////////////////////////////////////////////////////// 45 | 46 | template 47 | struct adapter : concrete_adapter { 48 | adapter( boost::local_time::time_zone_ptr const& adapted) : concrete_adapter(adapted) {} 49 | 50 | virtual optional get_boolean() const { return this->adapted().get() != 0; } 51 | virtual optional get_string() const { return this->adapted() ? this->adapted()->to_posix_string() : typename Value::string_type(); } 52 | }; 53 | 54 | /* 55 | // 56 | // specialization for boost::date_time::time_zone_base 57 | //////////////////////////////////////////////////////////////////////////////////////////////////// 58 | 59 | template 60 | struct adapter > : concrete_adapter > { 61 | adapter( boost::date_time::time_zone_base const& adapted) : concrete_adapter >(adapted) {} 62 | }; 63 | */ 64 | 65 | }}} // namespace ajg::synth::adapters 66 | 67 | #endif // AJG_SYNTH_ADAPTERS_PTREE_HPP_INCLUDED 68 | 69 | 70 | -------------------------------------------------------------------------------- /ajg/synth/adapters/ref.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_REF_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_REF_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace ajg { 15 | namespace synth { 16 | namespace adapters { 17 | 18 | // 19 | // specialization for boost::reference_wrapper 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// 21 | 22 | /* 23 | TODO: 24 | template 25 | struct adapter > : forwarding_adapter > { 26 | adapter(boost::reference_wrapper const& adapted) : forwarding_adapter >(adapted) {} 27 | template A forward() const { ? } 28 | boolean_type valid() const { return true; } 29 | }; 30 | */ 31 | 32 | template 33 | struct adapter > : base_adapter { // TODO: Use concrete_adapter or forwarding_adapter. 34 | public: 35 | 36 | adapter(boost::reference_wrapper const& adapted) : adapted_(adapted) {} 37 | 38 | template 39 | adapter(boost::reference_wrapper const& adapted, const U& u) : adapted_(adapted, u) {} 40 | 41 | template 42 | adapter(boost::reference_wrapper const& adapted, const U& u, const V& v) : adapted_(adapted, u, v) {} 43 | 44 | AJG_SYNTH_ADAPTER_TYPEDEFS(Value); 45 | 46 | typedef adapter::type> wrapped_adapter_type; 47 | 48 | public: 49 | 50 | virtual std::type_info const& type() const { return typeid(T); } // XXX: this->adapted_.type(); ? 51 | virtual void* data() const { return this->adapted_.data(); } 52 | virtual type_flags flags() const { return this->adapted_.flags(); } 53 | 54 | virtual optional get_boolean() const { return this->adapted_.get_boolean(); } 55 | virtual optional get_number() const { return this->adapted_.get_number(); } 56 | virtual optional get_datetime() const { return this->adapted_.get_datetime(); } 57 | virtual optional get_string() const { return this->adapted_.get_string(); } 58 | virtual optional get_range() const { return this->adapted_.get_range(); } 59 | 60 | virtual boolean_type input (istream_type& istream) const { return this->adapted_.input(istream); } 61 | virtual boolean_type output(ostream_type& ostream) const { return this->adapted_.output(ostream); } 62 | 63 | virtual boolean_type equal_to(value_type const& that) const { return this->adapted_.equal_to(that); } 64 | virtual boolean_type less (value_type const& that) const { return this->adapted_.less(that); } 65 | 66 | virtual attribute_type attribute(value_type const& key) const { return this->adapted_.attribute(key); } 67 | virtual void attribute(value_type const& key, attribute_type const& attribute) const { this->adapted_.attribute(key, attribute); } 68 | virtual attributes_type attributes() const { return this->adapted_.attributes(); } 69 | 70 | virtual const_iterator find(value_type const& value) const { return this->adapted_.find(value); } 71 | 72 | private: 73 | 74 | wrapped_adapter_type adapted_; 75 | }; 76 | 77 | }}} // namespace ajg::synth::adapters 78 | 79 | #endif // AJG_SYNTH_ADAPTERS_REF_HPP_INCLUDED 80 | 81 | -------------------------------------------------------------------------------- /ajg/synth/adapters/string.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_STRING_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_STRING_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | // 17 | // specialization for std::basic_string 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | template < class Value 21 | , class Traits 22 | , class Allocator 23 | > 24 | struct adapter > : container_adapter, type_flags(textual | sequential)> { 25 | adapter(std::basic_string const& adapted) : container_adapter, type_flags(textual | sequential)>(adapted) {} 26 | virtual optional get_string() const { return this->adapted(); } 27 | }; 28 | 29 | // 30 | // specializations for [const] char_type* and [const] char_type[N]. 31 | //////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | template 34 | struct adapter : adapter > { 35 | adapter(typename Value::char_type const *const value) : adapter >(value) {} 36 | }; 37 | 38 | template 39 | struct adapter : adapter > { 40 | adapter(typename Value::char_type const value[N]) : adapter >( 41 | std::basic_string(value, N ? N - 1 : 0)) {} 42 | }; 43 | 44 | template 45 | struct adapter : adapter > { 46 | adapter(typename Value::char_type *const value) : adapter >(value) {} 47 | }; 48 | 49 | template 50 | struct adapter : adapter > { 51 | adapter(typename Value::char_type const value[N]) : adapter >( 52 | std::basic_string(value, N ? N - 1 : 0)) {} 53 | }; 54 | 55 | #if AJG_SYNTH_IS_COMPILER_MSVC 56 | 57 | // MSVC seems to need these more specific specializations, 58 | // otherwise string literals specialize as char arrays. 59 | template 60 | struct adapter : adapter > { 61 | adapter(char const value[N]) : adapter >( 62 | std::basic_string(value, N ? N - 1 : 0)) {} 63 | }; 64 | 65 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 66 | 67 | template 68 | struct adapter : adapter > { 69 | adapter(wchar_t const value[N]) : adapter >( 70 | std::basic_string(value, N ? N - 1 : 0)) {} 71 | }; 72 | 73 | #endif 74 | #endif 75 | 76 | }}} // namespace ajg::synth::adapters 77 | 78 | #endif // AJG_SYNTH_ADAPTERS_STRING_HPP_INCLUDED 79 | 80 | -------------------------------------------------------------------------------- /ajg/synth/adapters/forwarding_adapter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_FORWARDING_ADAPTER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_FORWARDING_ADAPTER_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace adapters { 15 | 16 | template > 17 | struct forwarding_adapter : concrete_adapter { 18 | forwarding_adapter(Adapted const& adapted) : concrete_adapter(adapted) {} 19 | 20 | AJG_SYNTH_ADAPTER_TYPEDEFS(Value); 21 | 22 | virtual std::type_info const& type() const { return this->valid() ? this->forward().type() : typeid(void); } 23 | virtual void* data() const { return this->valid() ? this->forward().data() : 0; } 24 | virtual type_flags flags() const { return this->valid() ? this->forward().flags() : unspecified; } 25 | 26 | virtual optional get_boolean() const { return this->valid() ? this->forward().get_boolean() : boost::none; } 27 | virtual optional get_number() const { return this->valid() ? this->forward().get_number() : boost::none; } 28 | virtual optional get_datetime() const { return this->valid() ? this->forward().get_datetime() : boost::none; } 29 | virtual optional get_string() const { return this->valid() ? this->forward().get_string() : boost::none; } 30 | virtual optional get_range() const { return this->valid() ? this->forward().get_range() : boost::none; } 31 | 32 | virtual attribute_type attribute(value_type const& key) const { return this->valid() ? this->forward().attribute(key) : attribute_type(); } 33 | virtual void attribute(value_type const& key, attribute_type const& attribute) const { if (this->valid()) this->forward().attribute(key, attribute); } 34 | virtual attributes_type attributes() const { return this->valid() ? this->forward().attributes() : attributes_type(); } 35 | 36 | virtual const_iterator find(value_type const& value) const { return this->valid() ? this->forward().find(value) : const_iterator(); } 37 | 38 | virtual boolean_type input (istream_type& istream) const { return this->valid() ? this->forward().input(istream) : false; } 39 | virtual boolean_type output(ostream_type& ostream) const { return this->valid() ? this->forward().output(ostream) : false; } 40 | 41 | virtual boolean_type equal_to(value_type const& that) const { return this->valid() ? this->forward().equal_to(that) : false; } 42 | virtual boolean_type less (value_type const& that) const { return this->valid() ? this->forward().less(that) : false; } 43 | 44 | private: 45 | 46 | typedef typename boost::remove_reference::type bare_type; 47 | typedef adapter > ref_type; 48 | typedef adapter > cref_type; 49 | 50 | private: 51 | 52 | inline ref_type forward() { return static_cast(this)->template forward(); } 53 | inline cref_type forward() const { return static_cast(this)->template forward(); } 54 | inline boolean_type valid() const { return static_cast(this)->valid(); } 55 | }; 56 | 57 | }}} // namespace ajg::synth::adapters 58 | 59 | #endif // AJG_SYNTH_ADAPTERS_FORWARDING_ADAPTER_HPP_INCLUDED 60 | 61 | -------------------------------------------------------------------------------- /ide/vs2013/Harness/Harness.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {D362CE4E-F28E-4436-8742-48CE405D5831} 15 | Harness 16 | 17 | 18 | 19 | Application 20 | true 21 | v120 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | v120 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | Disabled 47 | 48 | 49 | true 50 | 51 | 52 | 53 | 54 | MaxSpeed 55 | true 56 | true 57 | /U"_DEBUG" /D "NDEBUG" %(AdditionalOptions) 58 | 59 | 60 | true 61 | true 62 | true 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /tests/timings.py: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | 3 | from __future__ import print_function 4 | 5 | import django.template as django 6 | import synth 7 | import sys 8 | 9 | from django.template.loader import * # Fixes missing block & extends tags. 10 | from django.conf import settings 11 | from timeit import timeit 12 | 13 | print('Loaded synth; version: %s' % synth.version(), file=sys.stderr) 14 | 15 | if not settings.configured: 16 | settings.configure() 17 | 18 | def main(): 19 | print('=== Prepping ===') 20 | print('Directories:', directories) 21 | print('Data:', data) 22 | print('Files:', files) 23 | print('Debug:', debug) 24 | 25 | # Set the right directories: 26 | settings.TEMPLATE_DEBUG = debug 27 | settings.TEMPLATE_DIRS += directories 28 | synth.Template.set_default_options({ 29 | 'debug': debug, 30 | 'directories': directories, 31 | }) 32 | 33 | print('=== Starting ===') 34 | print('Iterations:', iterations) 35 | for name in files: bench(name) 36 | print('Average: %2.1fx' % (sum(changes) / len(changes))) 37 | print('=== Finished ===') 38 | 39 | debug = False 40 | iterations = 1000 41 | directories = ( 42 | 'tests/templates/django/blog', 43 | 'tests/templates/django', 44 | '.', 45 | ) 46 | files = [ 47 | 'base.html', 48 | 'home.html', 49 | 'index.html', 50 | 'A.tpl', 51 | 'B.tpl', 52 | 'base.tpl', 53 | 'C.tpl', 54 | 'D.tpl', 55 | 'derived.tpl', 56 | 'empty.tpl', 57 | 'layout.html', 58 | 'messages.html', 59 | 'variables.tpl', 60 | 'X.tpl', 61 | ] 62 | data = { 63 | 'foo': 1, 64 | 'bar': 2, 65 | 'qux': 3, 66 | 'user': 'Dolph Lundgren', 67 | 'subtitle': 'A blog about movies and TV shows', 68 | 'categories': [ 69 | {'title': 'Movies', 'url': 'http://example.org/categories/movies'}, 70 | {'title': 'Shows', 'url': 'http://example.org/categories/shows'}, 71 | ], 72 | 'posts': [ 73 | {'title': 'Rocky', 'url': 'http://example.org/posts/1', 'category': 'movies'}, 74 | {'title': 'Blackjack', 'url': 'http://example.org/posts/2', 'category': 'shows'}, 75 | ], 76 | } 77 | 78 | source = None 79 | changes = [] 80 | 81 | def print_diff(a, b): 82 | import sys, subprocess, tempfile 83 | 84 | f = tempfile.NamedTemporaryFile(mode='w+') 85 | g = tempfile.NamedTemporaryFile(mode='w+') 86 | f.write(a) 87 | f.flush() 88 | g.write(b) 89 | g.flush() 90 | command = ['git', 'diff', '--no-index', '--color-words', f.name, g.name] 91 | try: 92 | subprocess.call(command, stdout=sys.stdout, stderr=sys.stderr) 93 | except subprocess.CalledProcessError as e: 94 | print('[Diff unavailable; please install git]') 95 | return 96 | 97 | def bench(name): 98 | global source, changes 99 | source = '{% include "' + name + '" %}' 100 | 101 | # Ensure the output is the same: 102 | a = django.Template(source).render(django.Context(data)) 103 | b = synth.Template(source, 'django').render_to_string(data) 104 | 105 | if a != b: 106 | print('WARNING: Outputs were not equal for file %s', repr(name)) 107 | print(' - Django Output: %s' % repr(a)) 108 | print(' - Synth Output: %s' % repr(b)) 109 | print_diff(a, b) 110 | 111 | x = timeit("bench_django()", number=iterations, setup="from __main__ import bench_django") 112 | y = timeit("bench_synth()", number=iterations, setup="from __main__ import bench_synth") 113 | change = x / y 114 | changes.append(change) 115 | print('Django: %.3fs; Synth: %.3fs; +/-: %2.1fx; File: %s' % (x, y, change, repr(name))) 116 | 117 | def bench_django(): 118 | django_template = django.Template(source) 119 | django_template.render(django.Context(data)) 120 | 121 | def bench_synth(): 122 | synth_template = synth.Template(source, 'django') 123 | synth_template.render_to_string(data) 124 | 125 | main() 126 | -------------------------------------------------------------------------------- /ajg/synth/value_iterator.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_VALUE_ITERATOR_HPP_INCLUDED 6 | #define AJG_SYNTH_VALUE_ITERATOR_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | 15 | // 16 | // value_iterator 17 | //////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | template 20 | struct value_iterator 21 | : boost::iterator_facade< value_iterator 22 | , Value 23 | , boost::forward_traversal_tag 24 | , Value // This forces the 'reference' type to be 25 | > { // a real Value, not an actual reference. 26 | public: 27 | 28 | // typedef std::size_t size_type; 29 | // typedef Value value_type; 30 | 31 | public: 32 | 33 | value_iterator() : iterator_() {} 34 | 35 | // explicit value_iterator(Value *const value) : value_(value) {} 36 | 37 | template 38 | value_iterator(ForwardIterator const& iterator) 39 | : iterator_(new polymorphic_iterator(iterator)) {} 40 | 41 | /*template 42 | value_iterator(value_iterator const& other) : iterator_(new ...) {} 43 | */ 44 | 45 | 46 | 47 | // private: 48 | 49 | template 50 | bool equal(value_iterator const& that) const { 51 | bool const a = this->iterator_, b = that.iterator_; 52 | return (!a && !b) || (a && b && this->iterator_->equal(*that.iterator_)); 53 | } 54 | 55 | void increment() { AJG_SYNTH_ASSERT(iterator_); iterator_->increment(); } 56 | Value dereference() const { AJG_SYNTH_ASSERT(iterator_); return iterator_->dereference(); } 57 | // value_iterator advance(size_type const distance) const; 58 | 59 | private: 60 | 61 | struct virtual_iterator { 62 | virtual void increment() = 0; 63 | virtual Value dereference() const = 0; 64 | virtual virtual_iterator& clone() const = 0; 65 | virtual bool equal(virtual_iterator const& that) const = 0; 66 | virtual ~virtual_iterator() {} 67 | }; 68 | 69 | template 70 | struct polymorphic_iterator : virtual_iterator { 71 | polymorphic_iterator(ForwardIterator const& iterator) : iterator_(iterator) {} 72 | 73 | virtual void increment() { iterator_++; } 74 | virtual Value dereference() const { return *iterator_; } 75 | virtual polymorphic_iterator& clone() const { return *new polymorphic_iterator(iterator_); } 76 | virtual bool equal(virtual_iterator const& that) const { 77 | // AJG_SYNTH_ASSERT(typeid(polymorphic_iterator) == typeid(that)); 78 | AJG_SYNTH_ASSERT(dynamic_cast(&that)); 79 | return static_cast(that).iterator_ == this->iterator_; 80 | } 81 | 82 | private: 83 | ForwardIterator iterator_; 84 | }; 85 | 86 | private: 87 | 88 | friend class boost::iterator_core_access; 89 | template friend struct value_iterator; 90 | detail::clone_ptr iterator_; 91 | }; 92 | 93 | 94 | /* 95 | 96 | template 97 | adaptable_iterator make_adaptable_iterator(ForwardIterator const& iterator) { 98 | return adaptable_iterator(iterator); 99 | } 100 | 101 | template 102 | ValueIterator adapt(ForwardIterator const& iterator) { 103 | return ValueIterator(iterator); 104 | } 105 | */ 106 | 107 | }} // namespace ajg::synth 108 | 109 | #endif // AJG_SYNTH_VALUE_ITERATOR_HPP_INCLUDED 110 | -------------------------------------------------------------------------------- /tests/python/directory_tests.py: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | directory = 'tests/templates/django/' 6 | 7 | def get(): 8 | return (data, golden, source, 'django', { 9 | 'formats': {'TEMPLATE_STRING_IF_INVALID': 'INVALID_VALUE'}, 10 | 'debug': False, 11 | 'directories': [directory], 12 | }) 13 | 14 | class User(object): 15 | def __init__(self): 16 | self.is_staff = False 17 | self.is_authenticated = True 18 | 19 | class Message(object): 20 | def __init__(self, category, message): 21 | self.category = category 22 | self.message = message 23 | 24 | def __str__(self): 25 | return self.message 26 | 27 | data = { 28 | 'request': { 29 | 'user': User(), 30 | }, 31 | 'STATIC_URL': '/static/', 32 | 'title': 'Default Title', 33 | 'messages': [Message('category-a', 'Foo'), Message('category-b', 'Bar'), Message('category-c', 'Qux')], 34 | } 35 | source = open(directory + 'layout.html').read() 36 | golden = """ 37 | 38 | 39 | Default Title 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 60 | 61 | 62 | 63 |
64 |
65 |
66 | 74 |
75 |
76 |
77 |
78 | 79 | 80 |
    81 | 82 |
  • Foo
  • 83 | 84 |
85 | 86 |
    87 | 88 |
  • Bar
  • 89 | 90 |
91 | 92 |
    93 | 94 |
  • Qux
  • 95 | 96 |
97 | 98 | 99 | 100 |
    101 |
  • Foo
  • 102 |
103 | 104 |
    105 |
  • Bar
  • 106 |
107 | 108 |
    109 |
  • Qux
  • 110 |
111 | 112 |
113 | 114 | 115 | 116 |
117 |
118 |
119 | 120 |
121 | 124 |
125 |
126 |
127 |
128 |
129 | 134 | 135 | 136 | """ 137 | -------------------------------------------------------------------------------- /ide/vs2013/Tool/Tool.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {4930EC20-223C-4182-9A63-6235DFC1EBC5} 15 | Tool 16 | 17 | 18 | 19 | Application 20 | true 21 | v120 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | v120 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | synth 45 | 46 | 47 | synth 48 | 49 | 50 | 51 | Disabled 52 | 53 | 54 | true 55 | 56 | 57 | 58 | 59 | MaxSpeed 60 | true 61 | true 62 | /U"_DEBUG" /D "NDEBUG" %(AdditionalOptions) 63 | 64 | 65 | true 66 | true 67 | true 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /ajg/synth/detail/find.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_FIND_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_FIND_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace detail { 15 | 16 | // 17 | // has_mapped_type 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | struct one { char c[1]; }; 21 | struct two { char c[2]; }; 22 | 23 | template one has_mapped_type_(...); 24 | template two has_mapped_type_(typename T::mapped_type const volatile *); 25 | 26 | template struct has_mapped_type { 27 | static bool const value = sizeof(has_mapped_type_(0)) == sizeof(two); 28 | }; 29 | 30 | // 31 | // find: 32 | // Uniform interface for mapped and non-mapped containers. 33 | //////////////////////////////////////////////////////////////////////////////////////////////////// 34 | 35 | template 36 | inline boost::optional find 37 | ( Needle const& needle 38 | , Container const& container 39 | , typename boost::disable_if >::type* = 0 40 | ) { 41 | typename Container::const_iterator const it = std::find(container.begin(), container.end(), needle); 42 | if (it == container.end()) return boost::none; else return *it; 43 | } 44 | 45 | template 46 | inline boost::optional find 47 | ( typename Container::key_type const& needle 48 | , Container const& container 49 | , typename boost::enable_if >::type* = 0 50 | ) { 51 | typename Container::const_iterator const it = container.find(needle); 52 | if (it == container.end()) return boost::none; else return it->second; 53 | } 54 | 55 | /* 56 | template 57 | inline typename Container::value_type find 58 | ( Needle const& needle 59 | , Container const& container 60 | , typename Container::value_type const& default_ 61 | , typename boost::disable_if >::type* = 0 62 | ) { 63 | typename Container::const_iterator const it = std::find(container.begin(), container.end(), needle); 64 | if (it == container.end()) return default_; else return *it; 65 | } 66 | 67 | template 68 | inline typename Container::mapped_type find 69 | ( typename Container::key_type const& needle 70 | , Container const& container 71 | , typename Container::mapped_type const& default_ 72 | , typename boost::enable_if >::type* = 0 73 | ) { 74 | typename Container::const_iterator const it = container.find(needle); 75 | if (it == container.end()) return default_; else return it->second; 76 | } 77 | */ 78 | 79 | // 80 | // contains: 81 | // TODO: Move to own file. 82 | //////////////////////////////////////////////////////////////////////////////////////////////////// 83 | 84 | template 85 | inline bool contains 86 | ( Needle const& needle 87 | , Container const& container 88 | , typename boost::disable_if >::type* = 0 89 | ) { 90 | return std::find(container.begin(), container.end(), needle) != container.end(); 91 | } 92 | 93 | template 94 | inline bool contains 95 | ( typename Container::key_type const& needle 96 | , Container const& container 97 | , typename boost::enable_if >::type* = 0 98 | ) { 99 | return container.find(needle) != container.end(); 100 | } 101 | 102 | }}} // namespace ajg::synth::detail 103 | 104 | #endif // AJG_SYNTH_DETAIL_FIND_HPP_INCLUDED 105 | -------------------------------------------------------------------------------- /ajg/synth/adapters/pair.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_PAIR_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_PAIR_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace ajg { 16 | namespace synth { 17 | namespace adapters { 18 | 19 | // 20 | // specialization for std::pair 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | template 24 | struct adapter > : concrete_adapter, type_flags(container | sequential)> { 25 | adapter(std::pair const& adapted) : concrete_adapter, type_flags(container | sequential)>(adapted) {} 26 | 27 | AJG_SYNTH_ADAPTER_TYPEDEFS(Value); 28 | 29 | virtual optional get_boolean() const { return boolean_type(true); } 30 | virtual optional get_range() const { 31 | return range_type( const_pair_iterator(this->adapted(), first) 32 | , const_pair_iterator(this->adapted(), past) 33 | ); 34 | } 35 | 36 | /* TODO: 37 | virtual boolean_type input(istream_type& istream) const { 38 | value_type f(this->adapted().first); 39 | value_type s(this->adapted().second); 40 | char_type a = 0, b = 0; 41 | istream >> f >> a >> b >> s; 42 | return true; 43 | } 44 | */ 45 | 46 | virtual boolean_type output(ostream_type& ostream) const { 47 | value_type const f(this->adapted().first); 48 | value_type const s(this->adapted().second); 49 | ostream << f << ": " << s; 50 | return true; 51 | } 52 | 53 | private: 54 | 55 | typedef std::pair pair_type; 56 | typedef boost::variant variant_type; 57 | 58 | enum position { first, second, past }; 59 | 60 | template 61 | struct pair_iterator : boost::iterator_facade< pair_iterator 62 | , /* XXX: V */variant_type 63 | , boost::forward_traversal_tag 64 | , /* XXX: V */variant_type 65 | > { 66 | public: 67 | pair_iterator( pair_type const& pair 68 | , position const position 69 | ) 70 | : pair_(pair), position_(position) {} 71 | 72 | template 73 | pair_iterator(pair_iterator const& other) 74 | : pair_(other.pair_), position_(other.position_) {} 75 | 76 | template 77 | bool equal(pair_iterator const& that) const { 78 | return this->pair_ == that.pair_ 79 | && this->position_ == that.position_; 80 | } 81 | 82 | void increment() { 83 | if (position_ == first) position_ = second; 84 | else if (position_ == second) position_ = past; 85 | else AJG_SYNTH_THROW(std::logic_error("invalid operation")); 86 | } 87 | 88 | variant_type dereference() const { 89 | if (position_ == first) return pair_.first; 90 | else if (position_ == second) return pair_.second; 91 | else AJG_SYNTH_THROW(std::logic_error("invalid iterator")); 92 | } 93 | 94 | private: 95 | friend class iterator_core_access; 96 | template friend struct pair_iterator; 97 | 98 | pair_type const& pair_; 99 | position position_; 100 | }; 101 | 102 | typedef pair_iterator const_pair_iterator; 103 | }; 104 | 105 | }}} // namespace ajg::synth::adapters 106 | 107 | #endif // AJG_SYNTH_ADAPTERS_PAIR_HPP_INCLUDED 108 | -------------------------------------------------------------------------------- /tests/python/binding_tests.py: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | from datetime import datetime 6 | 7 | def get(): 8 | return (data, golden, source, 'django') 9 | 10 | data = { 11 | 'bool_true': True, 12 | 'bool_false': False, 13 | 'int_0': 0, 14 | 'int_42': 42, 15 | 'str_empty': "", 16 | 'str_test': "test", 17 | 'list_empty': [], 18 | 'list_12345': [1, 2, 3, 4, 5], 19 | 'dict_empty': {}, 20 | 'dict_foo': {'foo': 'Foo'}, 21 | 'datetime_one': datetime(1, 1, 1), 22 | 'datetime_id4': datetime(1776, 7, 4), 23 | 'datetime_1984': datetime(1984, 11, 2), 24 | } 25 | source = u""" 26 | True: {{ True }}; {% if True %}Good{% else %}Bad{% endif %} 27 | False: {{ False }}; {% if False %}Bad{% else %}Good{% endif %} 28 | 29 | 0: {{ 0 }}; {% if 0 %}Bad{% else %}Good{% endif %} 30 | 42: {{ 42 }}; {% if 42 %}Good{% else %}Bad{% endif %} 31 | 32 | "": {{ "" }}; {% if "" %}Bad{% else %}Good{% endif %} 33 | "test": {{ "test" }}; {% if "test" %}Good{% else %}Bad{% endif %} 34 | 35 | bool_true: {{ bool_true }}; {% if bool_true %}Good{% else %}Bad{% endif %} 36 | bool_false: {{ bool_false }}; {% if bool_false %}Bad{% else %}Good{% endif %} 37 | 38 | int_0: {{ int_0 }}; {% if int_0 %}Bad{% else %}Good{% endif %} 39 | int_42: {{ int_42 }}; {% if int_42 %}Good{% else %}Bad{% endif %} 40 | 41 | str_empty: {{ str_empty }}; {% if str_empty %}Bad{% else %}Good{% endif %} 42 | str_test: {{ str_test }}; {% if str_test %}Good{% else %}Bad{% endif %} 43 | 44 | list_empty: {{ list_empty }}; {% if list_empty %}Bad{% else %}Good{% endif %} 45 | list_12345: {{ list_12345 }}; {% if list_12345 %}Good{% else %}Bad{% endif %} 46 | 47 | dict_empty: {{ dict_empty }}; {% if dict_empty %}Bad{% else %}Good{% endif %} 48 | dict_foo: {{ dict_foo }}; {% if dict_foo %}Good{% else %}Bad{% endif %} 49 | 50 | {% for k, v in str_empty %}Bad{% empty %}Good{% endfor %} 51 | {% for k, v in list_empty %}Bad{% empty %}Good{% endfor %} 52 | {% for k, v in dict_empty %}Bad{% empty %}Good{% endfor %} 53 | 54 | "literal": {% for v in "literal" %}{{ v }}{% endfor %} 55 | str_test: {% for v in str_test %}{{ v }}{% endfor %} 56 | list_12345: {% for v in list_12345 %}{{ v }}{% endfor %} 57 | dict_foo: {% for v in dict_foo %}{{ v }}{% endfor %} 58 | 59 | dict_foo: {% for k, v in dict_foo.items %}{{ k }}:{{ v }}{% endfor %} 60 | 61 | {{ 0 or 0 }} 62 | {{ 0 and 0 }} 63 | {{ 0 or "foo" }} 64 | {{ 0 and "foo" }} 65 | {{ "foo" or 0 }} 66 | {{ "foo" and 0 }} 67 | {{ "foo" or "bar" }} 68 | {{ "foo" and "bar" }} 69 | 70 | {{ datetime_one }} 71 | {{ datetime_id4 }} 72 | {{ datetime_1984 }} 73 | 74 | {{ datetime_1984|timesince:datetime_id4 }} 75 | {{ datetime_id4|timesince:datetime_1984 }} 76 | {{ datetime_id4|timesince:datetime_id4 }} 77 | {{ datetime_1984|timesince:datetime_1984 }} 78 | 79 | {{ datetime_1984|timeuntil:datetime_id4 }} 80 | {{ datetime_id4|timeuntil:datetime_1984 }} 81 | {{ datetime_id4|timeuntil:datetime_id4 }} 82 | {{ datetime_1984|timeuntil:datetime_1984 }} 83 | 84 | """ 85 | golden = u""" 86 | True: True; Good 87 | False: False; Good 88 | 89 | 0: 0; Good 90 | 42: 42; Good 91 | 92 | "": ; Good 93 | "test": test; Good 94 | 95 | bool_true: True; Good 96 | bool_false: False; Good 97 | 98 | int_0: 0; Good 99 | int_42: 42; Good 100 | 101 | str_empty: ; Good 102 | str_test: test; Good 103 | 104 | list_empty: []; Good 105 | list_12345: [1, 2, 3, 4, 5]; Good 106 | 107 | dict_empty: {}; Good 108 | dict_foo: {'foo': 'Foo'}; Good 109 | 110 | Good 111 | Good 112 | Good 113 | 114 | "literal": literal 115 | str_test: test 116 | list_12345: 12345 117 | dict_foo: foo 118 | 119 | dict_foo: foo:Foo 120 | 121 | 0 122 | 0 123 | foo 124 | 0 125 | foo 126 | 0 127 | foo 128 | bar 129 | 130 | 0001-01-01 00:00:00 131 | 1776-07-04 00:00:00 132 | 1984-11-02 00:00:00 133 | 134 | 0\u00a0minutes 135 | 208\u00a0years, 5\u00a0months 136 | 0\u00a0minutes 137 | 0\u00a0minutes 138 | 139 | 208\u00a0years, 5\u00a0months 140 | 0\u00a0minutes 141 | 0\u00a0minutes 142 | 0\u00a0minutes 143 | 144 | """ 145 | -------------------------------------------------------------------------------- /ajg/synth/templates/buffer_template.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_TEMPLATES_CHAR_TEMPLATE_HPP_INCLUDED 6 | #define AJG_SYNTH_TEMPLATES_CHAR_TEMPLATE_HPP_INCLUDED 7 | 8 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 9 | # include 10 | #endif 11 | 12 | #include 13 | 14 | namespace ajg { 15 | namespace synth { 16 | namespace templates { 17 | 18 | /// 19 | /// buffer_template: 20 | /// A sibling of string_template that doesn't keep a local copy of the source, only a pointer 21 | /// to it. This means the source MUST outlive the template or Bad Things will happen. 22 | /// 23 | /// In general, prefer string_template over buffer_template unless you know what you're doing and 24 | /// you've determined the latter provides a tangible net performance advantage over the former. 25 | //////////////////////////////////////////////////////////////////////////////////////////////////// 26 | 27 | template 28 | struct buffer_template : base_template { 29 | public: 30 | 31 | typedef buffer_template template_type; 32 | typedef Engine engine_type; 33 | typedef typename engine_type::options_type options_type; 34 | typedef typename options_type::traits_type traits_type; 35 | 36 | typedef typename traits_type::boolean_type boolean_type; 37 | typedef typename traits_type::char_type char_type; 38 | typedef typename traits_type::size_type size_type; 39 | typedef typename traits_type::buffer_type buffer_type; 40 | 41 | typedef buffer_type source_type; 42 | typedef size_type key_type; 43 | 44 | public: 45 | 46 | buffer_template(source_type const& source, options_type const& options = options_type()) : source_(source) { 47 | this->reset(this->source_.first, this->source_.first + this->source_.second, options); 48 | } 49 | 50 | buffer_template(char_type const* data, size_type const size, options_type const& options = options_type()) : source_(data, size) { 51 | this->reset(data, data + size, options); 52 | } 53 | 54 | buffer_template(char_type const* data, options_type const& options = options_type()) : source_(data, infer_size(data)) { 55 | this->reset(data, data + this->source_.second, options); 56 | } 57 | 58 | template 59 | buffer_template(char_type const (&data)[N], options_type const& options = options_type()): source_(data, N) { 60 | this->reset(data, data + N, options); 61 | } 62 | 63 | public: 64 | 65 | inline buffer_type const& source() const { return this->source_; } 66 | 67 | inline static key_type const key(buffer_type const& source) { return source.second; } 68 | 69 | inline boolean_type same(buffer_type const& source, options_type const& options) const { 70 | return this->source_ == source; 71 | } 72 | 73 | inline boolean_type stale(buffer_type const& buffer, options_type const& options) const { 74 | AJG_SYNTH_ASSERT(this->same(buffer, options)); 75 | return false; 76 | } 77 | 78 | private: 79 | 80 | inline static size_type infer_size(char const *const data) { return (std::strlen)(data); } 81 | 82 | #ifndef AJG_SYNTH_CONFIG_NO_WCHAR_T 83 | inline static size_type infer_size(wchar_t const *const data) { return (std::wcslen)(data); } 84 | #endif 85 | 86 | template 87 | inline static size_type infer_size(C const *const data) { 88 | size_type size = 0; 89 | while (*data++) size++; 90 | return size; 91 | } 92 | 93 | private: 94 | 95 | source_type const source_; 96 | }; 97 | 98 | }}} // namespace ajg::synth::templates 99 | 100 | #endif // AJG_SYNTH_TEMPLATES_CHAR_TEMPLATE_HPP_INCLUDED 101 | -------------------------------------------------------------------------------- /ajg/synth/detail/bidirectional_input_stream.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_BIDIRECTIONAL_INPUT_STREAM_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_BIDIRECTIONAL_INPUT_STREAM_HPP_INCLUDED 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace ajg { 13 | namespace synth { 14 | namespace detail { 15 | 16 | template 17 | struct bidirectional_input_stream { 18 | public: 19 | 20 | typedef InputStream input_stream_type; 21 | typedef typename input_stream_type::char_type char_type; 22 | typedef typename input_stream_type::off_type position_type; 23 | 24 | public: 25 | 26 | struct iterator { 27 | 28 | public: 29 | typedef char_type value_type; 30 | typedef char_type const* pointer; 31 | typedef char_type const& reference; 32 | typedef position_type difference_type; 33 | typedef std::bidirectional_iterator_tag iterator_category; 34 | 35 | iterator() : stream_(0), position_(0) {} // For Xpressive. 36 | iterator(bidirectional_input_stream* const stream, position_type const position) 37 | : stream_(stream), position_(position) {} 38 | 39 | bool operator==(iterator const& other) const { return this->at(other.position_); } 40 | bool operator< (iterator const& other) const { return this->position_ < other.position_; } 41 | bool operator!=(iterator const& other) const { return !(*this == other); } 42 | iterator& operator++() { ++this->position_; return *this; } 43 | iterator operator++(int) { iterator rc(*this); this->operator++(); return rc; } 44 | iterator operator--(int) { iterator rc(*this); this->operator--(); return rc; } 45 | iterator& operator--() { this->maybe_read(); --this->position_; return *this; } 46 | char_type operator*() const { return this->stream_->get(this->position_); } 47 | 48 | private: 49 | 50 | inline bool at(position_type const position) const { 51 | return this->position_ == position || (this->position_ == this->stream_->current_size() 52 | && !this->stream_->expand() && position == (std::numeric_limits::max)()); 53 | } 54 | 55 | inline void maybe_read() { 56 | if (this->position_ == (std::numeric_limits::max)()) { 57 | this->position_ = this->stream_->read_all(); 58 | } 59 | } 60 | 61 | bidirectional_input_stream* stream_; 62 | position_type position_; 63 | }; 64 | 65 | typedef iterator const_iterator; 66 | typedef std::reverse_iterator reverse_iterator; 67 | typedef std::reverse_iterator const_reverse_iterator; 68 | 69 | public: 70 | 71 | bidirectional_input_stream(input_stream_type& stream): stream_(stream) {} 72 | 73 | iterator begin() { return iterator(this, 0); } 74 | iterator end() { return iterator(this, (std::numeric_limits::max)()); } 75 | reverse_iterator rbegin() { return reverse_iterator(this->begin()); } 76 | reverse_iterator rend() { return reverse_iterator(this->end()); } 77 | 78 | bool expand() { 79 | static std::size_t const N = 1024; 80 | char_type buffer[N]; 81 | this->stream_.read(buffer, N); 82 | this->buffer_.insert(this->buffer_.end(), buffer, buffer + this->stream_.gcount()); 83 | return 0 < this->stream_.gcount(); 84 | } 85 | 86 | position_type read_all() { 87 | this->buffer_.insert(this->buffer_.end(), 88 | std::istreambuf_iterator(this->stream_), 89 | std::istreambuf_iterator()); 90 | return this->buffer_.size(); 91 | } 92 | 93 | position_type current_size() const { return this->buffer_.size(); } 94 | 95 | char_type get(position_type const index) { 96 | return this->buffer_[static_cast(index)]; 97 | } 98 | 99 | private: 100 | 101 | input_stream_type& stream_; 102 | std::vector buffer_; 103 | }; 104 | 105 | }}} // namespace ajg::synth::detail 106 | 107 | #endif // AJG_SYNTH_DETAIL_BIDIRECTIONAL_INPUT_STREAM_HPP_INCLUDED 108 | -------------------------------------------------------------------------------- /tests/harness.py: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | from __future__ import print_function 6 | 7 | import synth 8 | import sys 9 | import tempfile 10 | from difflib import unified_diff 11 | 12 | print('Loaded synth; version: ' + synth.version()) 13 | 14 | # TODO: Golden-file tests like these are brittle and ugly; 15 | # refactor and figure out how to reuse the native unit tests. 16 | 17 | def main(): 18 | import python.binding_tests as binding_tests 19 | import python.directory_tests as directory_tests 20 | import python.library_tests as library_tests 21 | import python.caching_tests as caching_tests 22 | 23 | print('Running test harness...') 24 | if sys.platform != 'win32': 25 | run_test('binding_tests', *binding_tests.get()) 26 | run_test('directory_tests', *directory_tests.get()) 27 | run_test('library_tests', *library_tests.get()) 28 | run_test('caching_tests', *caching_tests.get()) 29 | 30 | if failures != 0: 31 | raise Exception('One or more tests failed') 32 | 33 | print('...done.') 34 | 35 | total, failures = 0, 0 36 | 37 | def run_test(name, data, golden, source, engine, options=None): 38 | run_test_as('default', name, data, golden, source, engine, options) 39 | run_test_as('utf-8', name, data, golden, source.encode('utf-8'), engine, options) 40 | # TODO: run_test_as('utf-16', name, data, golden, source.encode('utf-16'), engine, options) 41 | # TODO: run_test_as('utf-32', name, data, golden, source.encode('utf-32'), engine, options) 42 | run_test_as('str', name, data, golden, str(source), engine, options) 43 | 44 | if sys.version_info < (3, 0): 45 | run_test_as('unicode', name, data, golden, unicode(source), engine, options) 46 | #else: 47 | # run_test_as('bytes', name, data, golden, bytes(source.encode('utf-8')), engine, options) 48 | 49 | def run_test_as(type, name, data, golden, source, engine, options=None): 50 | global total, failures 51 | total += + 1 52 | print(' Test #%d [%s] [%s]' % (total, name, type)) 53 | 54 | if sys.version_info < (3, 0): 55 | golden = golden.encode('utf-8') 56 | 57 | try: 58 | template = synth.Template(source, engine, options) 59 | print(' - Parsing succeeded') 60 | except Exception as e: 61 | failures += 1 62 | print(' x Parsing failed:\n' + str(e)) 63 | return 64 | 65 | try: 66 | string = template.render_to_string(data) 67 | print(' - Rendering to string succeeded') 68 | except Exception as e: 69 | failures += 1 70 | print(' x Rendering to string failed:\n' + str(e)) 71 | return 72 | 73 | with tempfile.TemporaryFile(mode='w+') as file: 74 | try: 75 | template.render_to_file(file, data) 76 | print(' - Rendering to file succeeded') 77 | except Exception as e: 78 | failures += 1 79 | print(' x Rendering to file failed:\n' + str(e)) 80 | return 81 | else: 82 | file.flush() 83 | file.seek(0) 84 | 85 | result = string 86 | if sys.platform == 'win32': 87 | result = result.replace('\r\n', '\n\n') 88 | 89 | if result != file.read(): 90 | print(' x Rendering to file failed: mismatch') 91 | 92 | # Note: Windows doesn't support reading from an already open 93 | # temporary file and has stupid newline conventions. 94 | if sys.platform == 'win32': 95 | string = string.replace('\r\n', '\n') 96 | golden = golden.replace('\r\n', '\n') 97 | print(' # Rendering to path excluded on this platform') 98 | else: 99 | with tempfile.NamedTemporaryFile(mode='w+') as file: 100 | try: 101 | template.render_to_path(file.name, data) 102 | print(' - Rendering to path succeeded') 103 | except Exception as e: 104 | failures += 1 105 | print(' x Rendering to path failed:\n' + str(e)) 106 | return 107 | else: 108 | file.flush() 109 | file.seek(0) 110 | if string != file.read(): 111 | print(' x Rendering to path failed: mismatch') 112 | 113 | if string == golden: 114 | print(' - Matching succeeded') 115 | else: 116 | failures += 1 117 | diff = ''.join(unified_diff(golden.splitlines(True), string.splitlines(True))) 118 | print(' x Matching failed:\n' + diff) 119 | return 120 | 121 | if __name__ == "__main__": 122 | main() 123 | -------------------------------------------------------------------------------- /ajg/synth/adapters/base_adapter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_ADAPTERS_BASE_ADAPTER_HPP_INCLUDED 6 | #define AJG_SYNTH_ADAPTERS_BASE_ADAPTER_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | 21 | namespace ajg { 22 | namespace synth { 23 | namespace adapters { 24 | 25 | // TODO[c++11]: ensure the underlying type is wide enough. 26 | enum type_flags 27 | { unspecified 28 | , unit = 1 << 0 29 | , boolean = 1 << 1 30 | , textual = 1 << 2 31 | , character = 1 << 3 32 | , numeric = 1 << 4 33 | , floating = 1 << 5 34 | , integral = 1 << 6 35 | // , signed = 1 << 7 36 | // , unsigned = 1 << 8 37 | , chronologic = 1 << 9 38 | , sequential = 1 << 10 39 | , associative = 1 << 11 40 | , container = 1 << 12 41 | }; 42 | 43 | template 44 | struct adapter; 45 | 46 | using boost::optional; 47 | 48 | // 49 | // base_adapter 50 | //////////////////////////////////////////////////////////////////////////////////////////////////// 51 | 52 | template 53 | struct base_adapter { 54 | public: 55 | 56 | typedef Value value_type; 57 | typedef base_adapter base_type; 58 | 59 | typedef typename value_type::iterator iterator; 60 | typedef typename value_type::const_iterator const_iterator; 61 | typedef typename value_type::range_type range_type; 62 | typedef typename value_type::attribute_type attribute_type; 63 | typedef typename value_type::attributes_type attributes_type; 64 | typedef typename value_type::adapter_type adapter_type; 65 | typedef typename value_type::traits_type traits_type; 66 | 67 | typedef typename traits_type::char_type char_type; 68 | typedef typename traits_type::size_type size_type; 69 | typedef typename traits_type::boolean_type boolean_type; 70 | typedef typename traits_type::integer_type integer_type; 71 | typedef typename traits_type::floating_type floating_type; 72 | typedef typename traits_type::number_type number_type; 73 | typedef typename traits_type::string_type string_type; 74 | typedef typename traits_type::datetime_type datetime_type; 75 | typedef typename traits_type::duration_type duration_type; 76 | typedef typename traits_type::istream_type istream_type; 77 | typedef typename traits_type::ostream_type ostream_type; 78 | 79 | 80 | public: 81 | 82 | base_adapter() {} 83 | virtual ~base_adapter() {} 84 | 85 | public: 86 | 87 | virtual std::type_info const& type() const = 0; 88 | virtual void* data() const = 0; 89 | virtual type_flags flags() const = 0; 90 | 91 | virtual optional get_boolean() const = 0; 92 | virtual optional get_number() const = 0; 93 | virtual optional get_datetime() const = 0; 94 | virtual optional get_string() const = 0; 95 | virtual optional get_range() const = 0; 96 | 97 | virtual boolean_type input (istream_type& istream) const = 0; 98 | virtual boolean_type output(ostream_type& ostream) const = 0; 99 | 100 | virtual boolean_type equal_to(value_type const& that) const = 0; 101 | virtual boolean_type less (value_type const& that) const = 0; 102 | 103 | virtual attribute_type attribute(value_type const& key) const = 0; 104 | virtual void attribute(value_type const& key, attribute_type const& attribute) const = 0; 105 | virtual attributes_type attributes() const = 0; 106 | 107 | virtual const_iterator find(value_type const& value) const = 0; 108 | 109 | template 110 | inline T* get() const { 111 | void* data = this->data(); 112 | AJG_SYNTH_ASSERT(data); 113 | AJG_SYNTH_ASSERT(this->type() == typeid(T)); 114 | return static_cast(data); 115 | } 116 | }; 117 | 118 | }}} // namespace ajg::synth::adapters 119 | 120 | #endif // AJG_SYNTH_ADAPTERS_BASE_ADAPTER_HPP_INCLUDED 121 | 122 | -------------------------------------------------------------------------------- /ajg/synth/detail/filesystem.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_DETAIL_FILESYSTEM_HPP_INCLUDED 6 | #define AJG_SYNTH_DETAIL_FILESYSTEM_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #if AJG_SYNTH_IS_COMPILER_MSVC 25 | # include // For MAX_PATH 26 | #endif 27 | 28 | #include 29 | 30 | #include 31 | 32 | namespace ajg { 33 | namespace synth { 34 | namespace detail { 35 | 36 | // 37 | // is_absolute: 38 | // Returns whether a path is considered absolute, even on Windows. 39 | //////////////////////////////////////////////////////////////////////////////////////////////////// 40 | 41 | template 42 | inline bool is_absolute(Path path) { 43 | static bool const check_drive_letter = AJG_SYNTH_IF_WINDOWS(true, false); 44 | return (!path.empty() && path[0] == '/') || (check_drive_letter && path.size() >= 3 45 | && (std::isalpha)(path[0]) && path[1] == ':' && (path[2] == '/' || path[2] == '\\')); 46 | } 47 | 48 | // 49 | // stat_file 50 | //////////////////////////////////////////////////////////////////////////////////////////////////// 51 | 52 | inline struct stat stat_file(std::string const& path) { 53 | struct stat stats; 54 | 55 | if (stat(path.c_str(), &stats) != 0) { 56 | AJG_SYNTH_THROW(read_error(path, std::strerror(errno))); 57 | } 58 | 59 | return stats; 60 | } 61 | 62 | // 63 | // get_current_working_directory 64 | //////////////////////////////////////////////////////////////////////////////////////////////////// 65 | 66 | inline std::string get_current_working_directory() { 67 | char buffer[AJG_SYNTH_IF_MSVC(MAX_PATH, PATH_MAX)] = {}; 68 | return AJG_SYNTH_IF_MSVC(_getcwd, getcwd)(buffer, sizeof(buffer)); 69 | } 70 | 71 | // 72 | // read_buffer_size 73 | //////////////////////////////////////////////////////////////////////////////////////////////////// 74 | 75 | #if defined(PIPE_BUF) 76 | std::size_t const read_buffer_size = PIPE_BUF; 77 | #elif defined(BUFSIZ) 78 | std::size_t const read_buffer_size = BUFSIZ; 79 | #else 80 | std::size_t const read_buffer_size = 4096; 81 | #endif 82 | 83 | // 84 | // read_file_to_stream: 85 | // Slurps a whole FILE* into a stream, using a buffer. 86 | //////////////////////////////////////////////////////////////////////////////////////////////////// 87 | 88 | template // TODO[c++11]: Make buffer_size a (defaulted) template parameter. 89 | void read_file_to_stream(FILE *const file, Stream& stream) { 90 | typedef typename Stream::char_type char_type; 91 | char_type buffer[read_buffer_size]; 92 | AJG_SYNTH_ASSERT(file != 0); 93 | 94 | while (std::size_t const items = std::fread(buffer, sizeof(char_type), read_buffer_size, file)) { 95 | stream.write(buffer, items); 96 | } 97 | } 98 | 99 | // 100 | // read_path_to_string: 101 | // Slurps a whole file into a string. 102 | //////////////////////////////////////////////////////////////////////////////////////////////////// 103 | 104 | template 105 | inline std::basic_string read_path_to_string(char const* const path) { 106 | FILE* const file = (std::fopen)(path, "rb"); 107 | std::basic_ostringstream stream; 108 | read_file_to_stream(file, stream); 109 | (std::fclose)(file); // FIXME: Not exception safe, but unlikely to be a problem. 110 | return stream.str(); 111 | } 112 | 113 | //////////////////////////////////////////////////////////////////////////////////////////////////// 114 | 115 | #if AJG_SYNTH_UNUSED 116 | 117 | template 118 | std::basic_string read_path_to_string(std::string const& path) const { 119 | std::basic_ifstream file; 120 | 121 | try { 122 | file.open(path.c_str(), std::ios::binary); 123 | return read_stream_to_string >(file); 124 | } 125 | catch (std::exception const& e) { 126 | AJG_SYNTH_THROW(read_error(path, e.what())); 127 | } 128 | } 129 | 130 | template 131 | inline String read_stream_to_string 132 | ( Stream& stream 133 | , boost::optional const size = boost::none 134 | ) { 135 | static typename String::size_type const buffer_size = 4096; 136 | 137 | if (!stream.good()) { 138 | AJG_SYNTH_THROW(std::runtime_error("bad stream")); 139 | } 140 | 141 | String result; 142 | if (size) result.reserve(*size); 143 | typename String::value_type buffer[buffer_size]; 144 | 145 | while (!stream.eof()) { 146 | stream.read(buffer, buffer_size); 147 | result.append(buffer, stream.gcount()); 148 | } 149 | 150 | if (stream.bad()) { 151 | AJG_SYNTH_THROW(std::runtime_error("bad stream")); 152 | } 153 | 154 | return result; 155 | } 156 | 157 | #endif // AJG_SYNTH_UNUSED 158 | 159 | }}} // namespace ajg::synth::detail 160 | 161 | #endif // AJG_SYNTH_DETAIL_FILESYSTEM_HPP_INCLUDED 162 | -------------------------------------------------------------------------------- /ajg/synth/templates/path_template.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #ifndef AJG_SYNTH_TEMPLATES_PATH_TEMPLATE_HPP_INCLUDED 6 | #define AJG_SYNTH_TEMPLATES_PATH_TEMPLATE_HPP_INCLUDED 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | namespace ajg { 21 | namespace synth { 22 | namespace templates { 23 | 24 | template 25 | struct path_template : base_template > { 26 | public: 27 | 28 | typedef path_template template_type; 29 | typedef Engine engine_type; 30 | typedef typename path_template::kernel_type kernel_type; 31 | typedef typename kernel_type::iterator_type iterator_type; 32 | typedef typename kernel_type::range_type range_type; 33 | typedef typename engine_type::options_type options_type; 34 | typedef typename options_type::traits_type traits_type; 35 | 36 | typedef typename traits_type::char_type char_type; 37 | typedef typename traits_type::size_type size_type; 38 | typedef typename traits_type::boolean_type boolean_type; 39 | typedef typename traits_type::string_type string_type; 40 | typedef typename traits_type::path_type path_type; 41 | typedef typename traits_type::paths_type paths_type; 42 | 43 | // TODO: source() 44 | typedef path_type source_type; 45 | typedef path_type key_type; 46 | typedef std::pair info_type; 47 | 48 | private: 49 | 50 | typedef detail::text text; 51 | 52 | public: 53 | 54 | path_template(path_type const& path, options_type const& options = options_type()) 55 | : source_(path), info_(locate_file(path, options.directories)) { 56 | if (this->info_.second.st_size == 0) { // Empty file. 57 | this->reset(options); 58 | } 59 | else { 60 | iterator_type begin(text::narrow(this->info_.first)); 61 | iterator_type end = begin ? begin.make_end() : iterator_type(); 62 | this->reset(begin, end, options); 63 | } 64 | } 65 | 66 | private: 67 | 68 | inline static info_type locate_file(path_type const& path, paths_type const& directories) { 69 | struct stat stats; 70 | 71 | // First try looking in the directories specified. 72 | for (auto const& directory : directories) { 73 | path_type const& base = detail::text::trim_right(directory, text::literal("/")); 74 | path_type const& full = base + char_type('/') + path; 75 | if (stat(text::narrow(full).c_str(), &stats) == 0) { // Found it. 76 | return info_type(full, stats); 77 | } 78 | } 79 | 80 | std::string const narrow_path = text::narrow(path); 81 | 82 | // Then try the current directory. 83 | if (stat(narrow_path.c_str(), &stats) != 0) { // TODO: Use wstat where applicable. 84 | AJG_SYNTH_THROW(read_error(narrow_path, std::strerror(errno))); 85 | } 86 | 87 | return info_type(path, stats); 88 | } 89 | 90 | // 91 | // Using fopen: 92 | // if (FILE *const file = std::fopen(filename, "rb")) { 93 | // std::fclose(file); 94 | // } 95 | // else { throw } 96 | 97 | // Using access: 98 | // if (access(path.c_str(), R_OK | F_OK) != 0) { 99 | // AJG_SYNTH_THROW(read_error(path, std::strerror(errno))); 100 | // } 101 | // 102 | 103 | public: 104 | 105 | inline info_type const& info() const { return this->info_; } 106 | 107 | // inline path_type const& source() const { return this->info_.first; } 108 | inline path_type const& source() const { return this->source_; } 109 | 110 | inline static key_type const key(path_type const& source) { return source; } 111 | 112 | inline boolean_type same(path_type const& path, options_type const& options) const { 113 | // return this->info_.first == path && this->options().directories == options.directories; 114 | return this->source_ == path && this->options().directories == options.directories; 115 | } 116 | 117 | inline boolean_type stale(path_type const& path, options_type const& options) const { 118 | AJG_SYNTH_ASSERT(this->same(path, options)); 119 | struct stat stats; 120 | 121 | if (stat(text::narrow(this->info_.first).c_str(), &stats) == 0) { 122 | return this->info_.second.st_mtime < stats.st_mtime 123 | || this->info_.second.st_size != stats.st_size; 124 | } 125 | 126 | return true; // File may have been deleted, etc. 127 | } 128 | 129 | private: 130 | 131 | source_type const source_; 132 | info_type const info_; 133 | }; 134 | 135 | }}} // namespace ajg::synth::templates 136 | 137 | #endif // AJG_SYNTH_TEMPLATES_PATH_TEMPLATE_HPP_INCLUDED 138 | -------------------------------------------------------------------------------- /tests/groups/adapters.cpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | // Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace { 20 | 21 | namespace s = ajg::synth; 22 | 23 | typedef s::default_traits traits_type; 24 | typedef s::engines::null::engine engine_type; 25 | typedef s::templates::string_template template_type; 26 | 27 | typedef engine_type::context_type context_type; 28 | typedef engine_type::value_type value_type; 29 | 30 | typedef traits_type::char_type char_type; 31 | typedef traits_type::string_type string_type; 32 | typedef s::detail::text text; 33 | 34 | AJG_SYNTH_TEST_GROUP("adapter"); 35 | 36 | } // namespace 37 | 38 | AJG_SYNTH_TEST_UNIT(assignments) { 39 | context_type context((std::map())); 40 | 41 | string_type const X = text::literal("this"); 42 | string_type const Y = text::literal("that"); 43 | string_type const Two = text::literal("2"); 44 | std::vector some_strings; 45 | some_strings.push_back(text::literal("foo")); 46 | some_strings.push_back(text::literal("bar")); 47 | some_strings.push_back(text::literal("qux")); 48 | std::vector doodoo; 49 | doodoo.push_back(1); 50 | doodoo.push_back(2); 51 | doodoo.push_back(3); 52 | doodoo.push_back(4); 53 | doodoo.push_back(5); 54 | doodoo.push_back(6); 55 | doodoo.push_back(7); 56 | doodoo.push_back(8); 57 | doodoo.push_back(9); 58 | 59 | context.set(text::literal("this_value"), 175); 60 | context.set(text::literal("max_value"), 200); 61 | 62 | context.set(text::literal("xml_var"), text::literal("&")); 63 | context.set(text::literal("a_few_lines"), text::literal("this\nhas\nlines")); 64 | context.set(text::literal("more_lines"), text::literal("this\nhas\nlines\n\r\nand\nsome\nmore")); 65 | context.set(text::literal("a_bin_string"), text::literal("this \f string \t contains \b binary \0 indeed")); 66 | 67 | string_type const string_array[5] = { text::literal("sa0"), text::literal("sa1"), text::literal("sa2"), text::literal("sa3"), text::literal("sa4") }; 68 | string_type const tag_list[5] = { text::literal(""), text::literal(""), text::literal(""), text::literal(""), text::literal("") }; 69 | float const float_array[6] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f }; 70 | 71 | /// float const* float_pointer = float_array; 72 | /// context.set(text::literal("a_float_pointer"), value(float_pointer, 6)); 73 | 74 | boost::scoped_ptr > scoped_(new std::vector(3, 3)); 75 | std::auto_ptr > auto_ptr_(new std::vector(4, 4)); 76 | 77 | context.set(text::literal("X"), text::literal("this")); // X; 78 | context.set(text::literal("Y"), boost::ref(Y)); 79 | context.set(text::literal("Z"), Two); 80 | context.set(text::literal("some_strings"), some_strings); 81 | // TODO: context.set(text::literal("a_set", set()); 82 | context.set(text::literal("an_int_vector"), doodoo); 83 | context.set(text::literal("a_shared_ptr"), boost::shared_ptr >(new std::vector(6, 6))); 84 | context.set(text::literal("a_scoped_ptr"), scoped_); 85 | context.set(text::literal("a_string_array"), string_array); 86 | context.set(text::literal("tag_list"), tag_list); 87 | context.set(text::literal("a_float_array"), float_array); 88 | context.set(text::literal("an_auto_ptr"), auto_ptr_); 89 | context.set(text::literal("a_char"), char_type('z')); 90 | context.set(text::literal("an_int"), 12); 91 | 92 | boost::scoped_array a_scoped_array(new int[5]); 93 | a_scoped_array[0] = 666; 94 | a_scoped_array[1] = 667; 95 | a_scoped_array[2] = 668; 96 | a_scoped_array[3] = 669; 97 | a_scoped_array[4] = 670; 98 | context.set(text::literal("a_scoped_array"), value_type(a_scoped_array, 5)); 99 | 100 | std::map a_map = boost::assign::map_list_of(1, 2)(3, 4); 101 | context.set(text::literal("a_deque"), std::deque()); 102 | context.set(text::literal("a_map"), a_map); 103 | 104 | std::vector > > _vectors; 105 | context.set(text::literal("some_vectors"), _vectors); 106 | context.set(text::literal("shared_array"), value_type(boost::shared_array(), 0)); 107 | 108 | context.set(text::literal("a_complex_float"), std::complex()); 109 | context.set(text::literal("a_pair"), std::make_pair(1, 2.5)); 110 | context.set(text::literal("a_boost_array"), boost::array()); 111 | context.set(text::literal("an_optional_float"), boost::optional(4.5)); 112 | 113 | // FIXME: 114 | // std::auto_ptr > bools_(new std::vector(2, false)); 115 | // std::vector *const bools = bools_.get(); 116 | // context.set(text::literal("a_pointer"), bools); 117 | 118 | context.set(text::literal("a_true"), true); 119 | context.set(text::literal("a_false"), false); 120 | 121 | string_type sss = text::literal("This should be a string."); 122 | char_type const *const ccc = sss.c_str(); 123 | context.set(text::literal("char_pointer"), ccc); 124 | }}} 125 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | ## (C) Copyright 2014 Alvaro J. Genial (http://alva.ro) 2 | ## Use, modification and distribution are subject to the Boost Software License, Version 1.0. 3 | ## (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). 4 | 5 | import os 6 | import re 7 | import subprocess 8 | import sys 9 | 10 | DEBUG = int(ARGUMENTS.get('debug', 0)) 11 | GROUP = str(ARGUMENTS.get('group', '')) 12 | BOOST = str(ARGUMENTS.get('boost', 'local')) 13 | 14 | if BOOST not in ('local', 'system'): 15 | sys.exit('Argument `boost` must be `local` or `system`') 16 | 17 | def run(): 18 | cxx = ARGUMENTS.get('CXX', os.environ.get('CXX', 'c++')) 19 | env = make_environment(cxx) 20 | create_targets(env) 21 | 22 | def make_environment(cxx): 23 | return Environment( 24 | CXX = cxx, 25 | CPPPATH = get_cpp_path(), 26 | CPPFLAGS = get_cpp_flags(cxx), 27 | ENV = {'PATH' : os.environ['PATH']}, 28 | # TODO: VariantDir('build' / 'stage', '?', duplicate=0) 29 | ) 30 | 31 | def create_targets(env): 32 | harness = env.Clone() 33 | harness.Append(CPPPATH = ['external/tut-framework/include']) 34 | harness.Program( 35 | target = 'tests/harness.out', 36 | source = ['tests/harness.cpp'] + find_test_sources(), 37 | ) 38 | 39 | examples = env.Clone() 40 | examples.Program( 41 | target = 'examples/all', 42 | source = ['examples/simple_ssi.cpp', 'examples/simple_ssi_wide.cpp'], 43 | ) 44 | 45 | tool = env.Clone() 46 | tool.Program( 47 | target = 'synth', 48 | source = ['ajg/synth/bindings/command_line/tool.cpp'], 49 | ) 50 | 51 | # Note: For development only; normally use setup.py instead. 52 | from distutils import sysconfig 53 | python_module = env.Clone() 54 | python_module.LoadableModule( 55 | target = 'tests/synth.so', 56 | source = ['ajg/synth/bindings/python/module.cpp'] + find_boost_sources(), 57 | CPPPATH = [sysconfig.get_python_inc()] + get_cpp_path(), 58 | LIBPATH = [sysconfig.get_config_var('LIBDIR')], 59 | LIBPREFIX = '', 60 | LIBS = ['python' + sysconfig.get_config_var('VERSION')], 61 | ) 62 | 63 | return [harness, examples, tool] 64 | 65 | def find_test_sources(): 66 | if GROUP: 67 | return ['tests/groups/%s.cpp' % GROUP] 68 | else: 69 | return Glob('tests/groups/*.cpp') 70 | 71 | def find_boost_sources(): 72 | boost_path = find_boost_path() 73 | return (Glob(boost_path + '/libs/python/src/*.cpp') 74 | + Glob(boost_path + '/libs/python/src/*/*.cpp')) 75 | 76 | def find_cxx_version(cxx): 77 | try: 78 | # NOTE: '--version' alone doesn't always work with g++ 79 | return subprocess.check_output([cxx, '--version', '--verbose'], stderr=subprocess.STDOUT) 80 | except OSError as e: 81 | sys.exit('Unable to find compiler (%s) version: ' % cxx + e.strerror) 82 | 83 | def find_boost_path(): 84 | if BOOST == 'local': 85 | return 'external/boost' 86 | elif BOOST == 'system': 87 | return None 88 | else: 89 | sys.exit('Unknown value for option `boost`') 90 | 91 | def get_cpp_path(): 92 | boost_path = find_boost_path() 93 | cpp_path = ['.'] 94 | cpp_path += [boost_path] if boost_path else [] 95 | return cpp_path 96 | 97 | def get_cpp_flags(cxx): 98 | # TODO: Handle MSVC. 99 | 100 | cpp_flags = [] 101 | 102 | # Common flags: 103 | cpp_flags += ['-Wall'] 104 | cpp_flags += ['-Woverloaded-virtual'] 105 | cpp_flags += ['-Wsign-promo'] 106 | cpp_flags += ['-Wno-long-long'] 107 | # TODO: cpp_flags += ['-Wsurprising'] 108 | # TODO: cpp_flags += ['-Weffc++'] 109 | cpp_flags += ['-Wextra'] 110 | cpp_flags += ['-Wno-unused-parameter'] 111 | # XXX: Not including -Wold-style-cast due to optionparser.h. 112 | 113 | cxx_version = find_cxx_version(cxx) 114 | template_depth = '768' 115 | 116 | # Conditional flags: 117 | if BOOST != 'system': 118 | cpp_flags += ['-DBOOST_ALL_NO_LIB'] 119 | 120 | if 'clang' in cxx_version: 121 | cpp_flags += ['-std=c++11'] 122 | cpp_flags += ['-stdlib=libc++'] 123 | cpp_flags += ['-pedantic'] 124 | cpp_flags += ['-Wuninitialized'] 125 | cpp_flags += ['-Wc++11-narrowing'] 126 | cpp_flags += ['-ferror-limit=1'] 127 | # cpp_flags += ['-ftemplate-backtrace-limit=1'] 128 | 129 | # TODO: Only version 3.3+: 130 | cpp_flags += ['-ftemplate-depth=' + template_depth] 131 | cpp_flags += ['-DAJG_SYNTH_CONFIG_MAX_TEMPLATE_DEPTH=' + template_depth] 132 | 133 | if BOOST != 'system': 134 | cpp_flags += ['-Wno-newline-eof'] 135 | cpp_flags += ['-Wno-nested-anon-types'] 136 | cpp_flags += ['-Wno-language-extension-token'] 137 | 138 | elif 'g++' in cxx_version or 'gcc' in cxx_version: 139 | if not DEBUG: 140 | cpp_flags += ['-Wuninitialized'] # g++ doesn't support this without -O 141 | 142 | # FIXME: Triggers "warning: non-standard suffix on floating constant [-pedantic]": 143 | # cpp_flags += ['-pedantic'] 144 | cpp_flags += ['-Wfatal-errors'] 145 | cpp_flags += ['-Wstrict-null-sentinel'] 146 | cpp_flags += ['-Wno-sign-promo'] 147 | 148 | triple = re.search(r'\s(\d+)[.](\d+)[.](\d+)\s', cxx_version) 149 | if triple: 150 | major = int(triple.group(1)) 151 | minor = int(triple.group(2)) 152 | patch = int(triple.group(3)) 153 | gcc_version = (major, minor, patch) 154 | 155 | if gcc_version < (4, 5): 156 | cpp_flags += ['-ftemplate-depth-' + template_depth] # Note the dash 157 | cpp_flags += ['-DAJG_SYNTH_CONFIG_MAX_TEMPLATE_DEPTH=' + template_depth] 158 | else: 159 | cpp_flags += ['-ftemplate-depth=' + template_depth] 160 | cpp_flags += ['-DAJG_SYNTH_CONFIG_MAX_TEMPLATE_DEPTH=' + template_depth] 161 | 162 | if gcc_version >= (4, 8): 163 | cpp_flags += ['-Wmaybe-uninitialized'] 164 | cpp_flags += ['-Wnarrowing'] 165 | cpp_flags += ['-fmax-errors=1'] 166 | cpp_flags += ['-ftemplate-backtrace-limit=1'] 167 | 168 | if gcc_version >= (4, 7): 169 | cpp_flags += ['-std=c++11'] 170 | else: 171 | cpp_flags += ['-std=c++0x'] 172 | 173 | if DEBUG: 174 | cpp_flags += ['-g'] # '-fstack-protector-all' 175 | else: 176 | cpp_flags += ['-O3', '-DNDEBUG'] 177 | 178 | return cpp_flags 179 | 180 | run() 181 | --------------------------------------------------------------------------------