--- /dev/null
+*~
+*.bak
+stamp-h1
+Makefile.in
+configure
+aclocal.m4
+*.cache
+config.guess
+config.h.in
+config.sub
+compile
+depcomp
+install-sh
+missing
-coolrain-0.3.1
-================
-
- * Add new plugin tags to manipulate keyfile 'CR:KF:with', 'CR:KF:withLocale' and 'CR:KF:value'.
- See examples/greeting.template
+coolrain-0.3.x
+=================
+ == 0.3.2 ==
+ * Add template loader. The loader manage set of templates.
+ * Add new tags 'CR:include' and 'CR:param' to include other template module.
-coolrain-0.3.0
-=================
+ == 0.3.1 ==
+ * Add new tags to manipulate keyfile 'CR:KF:with', 'CR:KF:withLocale' and 'CR:KF:value'.
+ See examples/greeting.template
+ == 0.3.0 ==
* Fix bugs.
* Add builtin tag
'CR:pass', 'CR:ignore', 'CR:loop', 'CR:let' and 'CR:var' is present.
New subsystem
==============
-* Template repository (Template factory)
-* I18N message catalog. (gettext / keyfile)
* Global error handler.
* C++ class wrapper
+Test
+============
+* マルチスレッド動作の検証を行う。
--- /dev/null
+--
+--
+--
+module Text.TemplateEngine.CoolRain.Internal (
+ isArch32, dptrsize, cptrsize, archAlignmentSize,
+ ) where
+
+import Foreign.Ptr
+
+{-# INLINE #-}
+isArch32 = case dptrsize of
+ 4 -> True
+ 8 -> False
+ otherwise -> error "Unknown architecture"
+
+{-# INLINE #-}
+dptrsize = sizeOf nullPtr
+
+{-# INLINE #-}
+cptrsize = sizeOf nullFunPtr
+
+{-# INLINE #-}
+archAlignmentSize = dptrsize
+
+
--- /dev/null
+--
+--
+--
+--
+module Text.TemplateEngine.CoolRain.Loader (
+ --
+ LoaderOps,
+
+ --
+ Loader,
+ newFileLoader,
+ getTagset, loadTemplate, processTemplate
+
+ ) where
+--
+
+import Control.Monad
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.Storable
+import Foreign.Type
+
+import Text.TemplateEngine.CoolRain.Internal
+import Text.TemplateEngine.CoolRain.Tagset
+import Text.TemplateEngine.CoolRain.Stash
+import Text.TemplateEngine.CoolRain.Writer
+
+
+--
+data LoaderOps =
+ LoaderOps {
+ loader_ops_load : FunPtr (Ptr Loader' -> Ptr Template -> CString -> IO Int),
+ loader_ops_destroy : FunPtr (Ptr Loader' -> IO ())
+ }
+
+instance Storable LoaderOps where
+ sizeOf _ = dptrsize * 2
+ alignment _ = archAlignmentSize
+ peek x = return LoadOps
+ `ap` peekElementOf x 0
+ `ap` peekElementOf x 1
+ poke x y = do
+ pokeElementOf x 0 $ loader_ops_loader y
+ pokeElementOf x 1 $ loader_ops_destroy y
+
+
+--
+--
+--
+newtype Loader = Loader ForeignPtr ()
+
+
+mallocLoader :: IO Loader
+mallocLoader = do
+ x <- mallocForeignPtrBytes (if isArch32 then 16 else 28)
+ return $ Loader x
+
+withLoaderPtr (Loader x) = withForeignPtr x
+
+
+
+
+newFileLoader :: Maybe Tagset -> String -> IO (Either Loader Int)
+newFileLoader tagset basedir = do
+ x <- mallocLoader
+ r <- withCString basedir (\c_basedir -> withForeignPtr x (\p ->
+ coolrain_file_loader_initialize p (maybe nullPtr unsafeForeignPtrToPtr tagset) c_basedir))
+ if r == 0
+ then do
+ addForeignPtrFinalizer coolrain_loader_destroy x
+ return $ Left $ Loader x
+ else Right r
+
+
+
+getTagset :: Loader -> Tagset
+getTagset loader = withLoaderPtr loader (\loader' -> unsafePerformIO $ newForepginPtr $ peekByteOff loader' (isArch32 12 24))
+
+
+
+loadTemplate :: Loader -> Template -> String -> IO Int
+loadTemplate loader tmpl name =
+ return $ withCString name $ withForeignPtr template $ withLoaderPtr loader coolrain_loader_load_template
+
+
+processTemplate :: Loader -> String -> Stash -> Writer -> IO Int
+processTemplate loader name stash writer =
+ return $ withForeignPtr writer $ withForeignPtr stash $ withCString name $ withLoaderPtr loader coolrain_loader_process_template
+
+
+--
+--
+--
+
+-- Foreign import ccall "CoolRain/CoolRain.h coolrain_loader_initialize" coolrain_file_loader_initialize :: Ptr () -> Ptr () -> Ptr () -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_loader_destroy" coolrain_loader_destroy :: Ptr () -> IO ()
+
+
+-- Foreign import ccall "CoolRain/CoolRain.h coolrain_file_loader_set_error_handler" coolrain_file_loader_initialize :: Ptr () ->
+
+Foreign import ccall "CoolRain/CoolRain.h coolrain_loader_load_template" coolrain_loader_load_template :: Ptr () -> Ptr () -> CString -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_loader_process_template" coolrain_loader_process_template :: Ptr () -> CString -> Ptr () -> Ptr () -> IO CInt
+
+Foreign import ccall "CoolRain/CoolRain.h coolrain_file_loader_initialize" coolrain_file_loader_initialize :: Ptr () -> Ptr () -> CString -> IO CInt
+
+
+
--- /dev/null
+--
+--
+--
+module Text.TemplateEngine.CoolRain.Writer (
+ ) where
+
+
+--
+import Foreing.Ptr
+import Foreign.ForeignPtr
+
+
+import Text.TemplateEngine.CoolRain.Internal
+
+--
+newtype Writer = Writer (ForeignPtr ())
+
+type WriterBufferFullHandler = Writer -> IO Int
+type WriterBufferFullHandler' = Ptr () -> IO Int
+type WriterDestroyHandler = Writer -> IO ()
+type WriterDestroyHandler' = Ptr () -> IO ()
+type WriterWriteHandler = Writer -> CString -> CUInt -> IO Int
+type WriterWriteHandler' = Ptr () -> CString -> CUInt -> IO Int
+
+
+mallocWriter : IO ForeignPtr ()
+mallocWriter = mallocForeignPtr (isArch32
+
+newBufferWriter : CString -> CUInt -> IO Writer
+newBufferWriter buffer len =
+
+newFDWriter : CUInt -> Bool -> IO Writer
+newFDWriter fd autoclose =
+
+
+--
+
+
+
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_initialize" coolrain_writer_initialize : Ptr () -> Char () -> CUInt -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_destroy" coolrain_writer_destroy : Ptr () -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_chain" coolrain_writer_chain : Ptr () -> Ptr () -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_write" coolrain_writer_write : Ptr () -> CString -> CUInt -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_flush" coolrain_writer_flush : Ptr () -> IO CInt
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_drop" coolrain_writer_drop : Ptr () -> CUInt -> IO CInt
+
+Foreign import ccall "CoolRain/CoolRain.h coolrain_writer_reserve" coolrain_writer_resetve : Ptr () -> CUInt -> IO CString
+
+Foreign import ccall "CoolRain/CoolRain.h coolrain_fd_writer_initialize" coolrain_fd_writer_initialize : Ptr () -> CInt -> CInt -> IO CInt
+-- Foreign import ccall "CoolRain/CoolRain.h coolrain_FCGI_writer_initialize" coolrain_FCGI_writer_initialize :
+
AC_DEFINE(COOLRAIN_ENABLE_DEBUG, 1, [Enable debug build])
CFLAGS="$CFLAGS -O0 -g"
else
-CFLAGS="$CFLAGS -O99"
+CFLAGS="$CFLAGS -O3 -fno-schedule-insns2"
fi
dnl
if test "$GCC" = "yes"; then
- CFLAGS="$CFLAGS -Wall -Wextra -ffunction-sections"
+ CFLAGS="$CFLAGS -Wall -Wextra -ffunction-sections -Wstrict-prototypes"
LDFLAGS="-Wl,--gc-sections"
fi
--- /dev/null
+<CR:loop from="0" to="10" step="1">
+
+ <CR:KF:value name="Greeting.Say" />, <CR:KF:value name="Greeting.Ack" />
+ <CR:KF:value name='Visible.Colors' />
+
+ <CR:KF:withLocale lang="ja">
+ <CR:KF:value name="Greeting.Say" />, <CR:KF:value name="Greeting.Ack" />
+ <CR:KF:value name='Visible.Colors' />
+ </CR:KF:withLocale>
+
+ <CR:KF:withLocale lang="en">
+ <CR:KF:value name="Greeting.Say" />, <CR:KF:value name="Greeting.Ack" />
+ <CR:KF:value name='Visible.Colors' />
+ </CR:KF:withLocale>
+
+</CR:loop>
+
--- /dev/null
+<CR:let foo="OOF" bar="RAB" baz="ZAB">
+<CR:include href="inctest_1.template" />
+</CR:let>
+
+<CR:let hoge="I love lexycal scopeing rule.">
+<CR:include href="inctest_1.template">
+ <CR:param name="foo">FOO_1</CR:param>
+ <CR:param name="bar"><CR:include href="inctest_2.template" /></CR:param>
+ <CR:param name="baz">${hoge}</CR:param>
+</CR:include>
+</CR:let>
--- /dev/null
+-------< BEGIN inctest_1.template
+${foo}
+${bar}
+<CR:let hoge="Fuckin dynamic scoping!">${baz}</CR:let>
+-------< END inctest_1.template
--- /dev/null
+<<INCTEST_2.TEMPLATE>>
int main(int argc, char *argv[])
{
int r;
+ struct coolrain_loader loader;
+
struct coolrain_template tmpl;
- struct coolrain_tagset tagset;
struct coolrain_stash stash;
struct coolrain_writer writer;
struct coolrain_stash_value_list *gkeyfile_vl = NULL;
return EXIT_FAILURE;
}
- coolrain_tagset_initialize(&tagset);
- coolrain_tagset_register_tags(&tagset, coolrain_tagset_default_tags);
- coolrain_tagset_register_tags(&tagset, coolrain_tagset_gkeyfile_tags);
- coolrain_tagset_register_filters(&tagset, coolrain_tagset_default_filters);
- coolrain_template_initialize(&tmpl, &tagset);
+ coolrain_file_loader_initialize(&loader, NULL, ".");
+
+ coolrain_tagset_register_tags(loader.tagset, coolrain_tagset_default_tags);
+ coolrain_tagset_register_tags(loader.tagset, coolrain_tagset_gkeyfile_tags);
+ coolrain_tagset_register_filters(loader.tagset, coolrain_tagset_default_filters);
+
+ coolrain_template_initialize(&tmpl, loader.tagset);
coolrain_template_set_error_handler(&tmpl, my_error_handler, NULL);
- if (coolrain_template_compile(&tmpl, argv[1]) != COOLRAIN_SUCCESS) {
+ if (coolrain_loader_load_template(&loader, &tmpl, argv[1]) != COOLRAIN_SUCCESS) {
coolrain_template_destroy(&tmpl);
- coolrain_tagset_destroy(&tagset);
return EXIT_FAILURE;
}
if (gkeyfile_vl == NULL) {
fprintf(stderr, "%s: Could'nt open file.", argv[2]);
coolrain_template_destroy(&tmpl);
- coolrain_tagset_destroy(&tagset);
coolrain_stash_destroy(&stash);
return EXIT_FAILURE;
}
coolrain_writer_destroy(&writer);
coolrain_stash_destroy(&stash);
coolrain_template_destroy(&tmpl);
- coolrain_tagset_destroy(&tagset);
+ coolrain_loader_destroy(&loader);
return (r == COOLRAIN_SUCCESS)? EXIT_SUCCESS : EXIT_FAILURE;
}
*
*/
-#if !defined(__COOLRAIN__COOLRAIN__H__)
-#define __COOLRAIN__COOLRAIN__H__
+#if !defined(COOLRAIN__COOLRAIN__H__)
+#define COOLRAIN__COOLRAIN__H__
#include <CoolRain/thread.h>
#include <CoolRain/error.h>
#include <CoolRain/template.h>
#include <CoolRain/stash.h>
#include <CoolRain/writer.h>
+#include <CoolRain/loader.h>
#endif
* \brief C++ wrapper of CoolRain templat engine.
*
*/
-#if !defined(__COORAIN__COOLRAIN__HXX__)
-#define __COOLRAIN__COOLRAIN__HXX__
+#if !defined(COORAIN__COOLRAIN__HXX__)
+#define COOLRAIN__COOLRAIN__HXX__
#include <boost/noncopyable.hxx>
#include <stdarg.h>
variant.h \
memory.h \
version.h \
+ loader.h \
CoolRain.h
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#if !defined(__COOLRAIN__ERROR__H__)
-#define __COOLRAIN__ERROR__H__
+#if !defined(COOLRAIN__ERROR__H__)
+#define COOLRAIN__ERROR__H__
/** @{ \name Error codes */
#define COOLRAIN_SUCCESS (0) /*!< No error */
#define COOLRAIN_ERROR_UNBUFFERED (-8) /*!< Target buffer is unbuffered */
#define COOLRAIN_ERROR_IO (-9) /*!< IO Error */
#define COOLRAIN_ERROR_RUNTIME (-10) /*!< Runtime error */
+#define COOLRAIN_ERROR_NO_LOADER (-11) /*!< Template has no loader. (Loaded as standalone) */
+#define COOLRAIN_ERROR_NO_ATTRIBUTE (-12) /*!< Missing required attribute */
/** @} */
#endif
/**
*
*/
-#if !defined(__COOLRAIN__FRAGMENT__H__)
-#define __COOLRAIN__FRAGMENT__H__
+#if !defined(COOLRAIN__FRAGMENT__H__)
+#define COOLRAIN__FRAGMENT__H__
+#include <glib/gmacros.h>
#include <CoolRain/refstring.h>
+G_BEGIN_DECLS;
struct coolrain_tag_desc;
/*
*
*/
+#define COOLRAIN_FRAGMENT_ATTR_FLAGS_CSTRING (1)
+
struct coolrain_fragment_attribute {
struct coolrain_fragment_attribute *next;
coolrain_refstring_t name;
coolrain_refstring_t value;
+ unsigned long flags;
};
};
-struct coolrain_fragment_attribute *coolrain_fragment_attribute_alloc();
+struct coolrain_fragment_attribute *coolrain_fragment_attribute_alloc(void);
void coolrain_fragment_attribute_free(struct coolrain_fragment_attribute *attrs);
struct coolrain_fragment *coolrain_fragment_alloc(coolrain_fragment_type type);
void coolrain_fragment_free(struct coolrain_fragment *fragment);
-coolrain_refstring_t const *coolrain_fragment_find_attribute(struct coolrain_fragment const* fragment, char const *name);
+coolrain_refstring_t const *coolrain_fragment_find_attribute(struct coolrain_fragment const* __restrict fragment, char const * __restrict name);
+char const* coolrain_fragment_find_attribute_as_cstring(struct coolrain_fragment const * __restrict fragment, char const * __restrict name);
+
+G_END_DECLS;
#endif
--- /dev/null
+/**
+ * \brief Template repository and loader module for CoolRain template engine.
+ *
+ * Copyright (c) HATTORI, Hiroki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#if !defined(COOLRAIN__LOADER__H__)
+#define COOLRAIN__LOADER__H__
+
+#include <glib/gmacros.h>
+
+#include <CoolRain/thread.h>
+#include <CoolRain/template.h>
+
+G_BEGIN_DECLS;
+
+
+struct coolrain_stash;
+struct coolrain_writer;
+struct coolrain_tagset;
+struct coolrain_loader;
+
+
+
+struct coolrain_loader_ops {
+ int (*load)(struct coolrain_loader * __restrict loader, struct coolrain_template * __restrict tmpl, char const * __restrict name);
+ void (*destroy)(struct coolrain_loader *loader);
+};
+
+
+#define COOLRAIN_LOADER_FLAGS_AUTO_FREE_TAGSET (0)
+#define COOLRAIN_LOADER_FLAGS_BINNARY_LOADER (1)
+
+
+struct coolrain_loader {
+ struct coolrain_loader_ops *ops;
+ void *driver_data;
+ unsigned long flags;
+
+ struct coolrain_tagset *tagset;
+ coolrain_template_error_handler_t error_handler;
+ void *error_user_data;
+
+ void *user_data;
+ int (*preprocess)(struct coolrain_eval_context * __restrict cntx, void ** __restrict preproc_data);
+ void (*postprocess)(struct coolrain_eval_context * __restrict cntx, void * __restrict preproc_data);
+};
+
+
+int coolrain_loader_initialize(struct coolrain_loader * __restrict loader, struct coolrain_loader_ops * __restrict ops, struct coolrain_tagset * __restrict tagset);
+void coolrain_loader_destroy(struct coolrain_loader *loader);
+
+
+static inline void coolrain_loader_set_error_handler(
+ struct coolrain_loader * __restrict loader,
+ coolrain_template_error_handler_t handler,
+ void * __restrict user_data)
+{
+ loader->error_handler = handler;
+ loader->error_user_data = user_data;
+}
+
+int coolrain_loader_load_template(struct coolrain_loader * __restrict loader, struct coolrain_template * __restrict tmpl, char const * __restrict name);
+int coolrain_loader_process_template(struct coolrain_loader * __restrict loader, char const * __restrict name, struct coolrain_stash * __restrict stash, struct coolrain_writer * __restrict writer);
+
+
+int coolrain_file_loader_initialize(struct coolrain_loader * __restrict loader, struct coolrain_tagset * __restrict tagset, char const * __restrict base_dir);
+
+
+G_END_DECLS;
+
+#endif
+
+
* \brief Memory management module for CoolRain template engine.
*
*/
-#if !defined(__COOLRAIN__MEMORY__H__)
-#define __COOLRAIN__MEMORY__H__
+#if !defined(COOLRAIN__MEMORY__H__)
+#define COOLRAIN__MEMORY__H__
# if COOLRAIN_USE_GLIB
# include <glib/gstrfuncs.h>
-#define coolrain_malloc g_malloc
-#define coolrain_free g_free
-#define coolrain_strdup g_strdup
+# define coolrain_malloc g_malloc
+# define coolrain_free g_free
+# define coolrain_strdup g_strdup
+# define coolrain_strfreev g_strfeev
# else
-# error "No memory library."
+
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+
+static inline void *coolrain_malloc(size_t n)
+{
+ void *p = malloc(n);
+ if (p == NULL) {
+ perror("coolrain_malloc:");
+ abort();
+ }
+ return p;
+}
+
+# define coolrain_free free
+
+static inline char *coolrain_strdup(char const* str)
+{
+ char *p = strdup(str);
+ if (p == NULL) {
+ perror("coolrain_strdup:");
+ abort();
+ }
+ return p;
+}
+
+static inline void coolrain_strfreev(char** p)
+{
+ if (p != NULL) {
+ char **tmp = p;
+ while (*tmp != NULL) {
+ coolrain_free(*tmp);
+ tmp++;
+ }
+ coolrain_free(p);
+ }
+}
+
#endif
/**
* \brief RefString object module for CoolRain.
*/
-#if !defined(__COOLRAIN__REFSTRING__H__)
-#define __COOLRAIN__REFSTRING__H__
+#if !defined(COOLRAIN__REFSTRING__H__)
+#define COOLRAIN__REFSTRING__H__
#include <string.h>
#include <stdlib.h>
#include <CoolRain/memory.h>
+G_BEGIN_DECLS;
+
/**
*
*/
{
if (str != NULL) {
size_t len = coolrain_refstring_length(str);
- char *r = coolrain_malloc(len + 1);
+ char *r = (char*)coolrain_malloc(len + 1);
memcpy(r, str->begin, len);
r[len] = '\0';
return r;
return NULL;
}
+G_END_DECLS;
+
#endif
* \par Threading:
* The stash object is no thread safe.
*/
-#if !defined(__COOLRAIN__STASH__H__)
-#define __COOLRAIN__STASH__H__
+#if !defined(COOLRAIN__STASH__H__)
+#define COOLRAIN__STASH__H__
#include <glib/gtypes.h>
#include <glib/ghash.h>
#include <CoolRain/error.h>
#include <CoolRain/variant.h>
+G_BEGIN_DECLS;
+
/**
*
*/
-typedef int (*coolrain_stash_lookup_handler_t)(coolrain_variant_t * restrict value, coolrain_refstring_t const * restrict key);
+typedef int (*coolrain_stash_lookup_handler_t)(coolrain_variant_t * __restrict value, coolrain_refstring_t const * __restrict key);
struct coolrain_stash {
coolrain_mutex_t mutex;
-coolrain_variant_t const *coolrain_stash_get_value(struct coolrain_stash * restrict stash, coolrain_refstring_t const * restrict key);
+coolrain_variant_t const *coolrain_stash_get_value(struct coolrain_stash * __restrict stash, coolrain_refstring_t const * __restrict key);
-static inline coolrain_variant_t const *coolrain_stash_get_value_(struct coolrain_stash * restrict stash, char const * restrict key)
+static inline coolrain_variant_t const *coolrain_stash_get_value_(struct coolrain_stash * __restrict stash, char const * __restrict key)
{
coolrain_refstring_t k;
k.begin = key;
};
#define COOLRAIN_STASH_VALUE_INITIALIZER { { NULL, NULL }, COOLRAIN_VARIANT_INITIALIZER, NULL }
-void coolrain_stash_set_values(struct coolrain_stash * restrict stash, struct coolrain_stash_value_list * restrict values, size_t count);
-void coolrain_stash_restore(struct coolrain_stash * restrict stash, struct coolrain_stash_value_list * restrict values, size_t count);
+void coolrain_stash_set_values(struct coolrain_stash * __restrict stash, struct coolrain_stash_value_list * __restrict values, size_t count);
+void coolrain_stash_restore(struct coolrain_stash * __restrict stash, struct coolrain_stash_value_list * __restrict values, size_t count);
-static inline void coolrain_stash_set_lookup_handler(struct coolrain_stash * restrict stash, coolrain_stash_lookup_handler_t handler)
+static inline void coolrain_stash_set_lookup_handler(struct coolrain_stash * __restrict stash, coolrain_stash_lookup_handler_t handler)
{
stash->lookup_handler = handler;
}
+
+void coolrain_stash_value_list_unset(struct coolrain_stash_value_list * __restrict values, size_t count);
+
+
+G_END_DECLS;
+
#endif
/**
*
*/
-#if !defined(__COOLRAIN__TAGSET__H__)
-#define __COOLRAIN__TAGSET__H__
+#if !defined(COOLRAIN__TAGSET__H__)
+#define COOLRAIN__TAGSET__H__
#include <glib/ghash.h>
+#include <glib/gmacros.h>
#include <CoolRain/error.h>
#include <CoolRain/thread.h>
#include <CoolRain/stash.h>
#include <CoolRain/writer.h>
+G_BEGIN_DECLS;
struct coolrain_fragment;
struct coolrain_template;
int coolrain_builtin_tag_handler_let(struct coolrain_eval_context const *cntx);
int coolrain_builtin_tag_handler_var(struct coolrain_eval_context const *cntx);
int coolrain_builtin_tag_handler_loop(struct coolrain_eval_context const *cntx);
+int coolrain_builtin_tag_handler_include(struct coolrain_eval_context const *cntx);
+int coolrain_builtin_tag_handler_include_param(struct coolrain_eval_context const *cntx);
/* !} */
struct coolrain_stash *stash,
struct coolrain_stash_value_list *vl);
+G_END_DECLS;
+
#endif
/**
*
*/
-#if !defined(__COOLRAIN__TEMPLATE__H__)
-#define __COOLRAIN__TEMPLATE__H__
+#if !defined(COOLRAIN__TEMPLATE__H__)
+#define COOLRAIN__TEMPLATE__H__
#include <limits.h>
#include <stdarg.h>
+#include <glib/gmacros.h>
#include <CoolRain/refstring.h>
#include <CoolRain/thread.h>
#include <CoolRain/stash.h>
#include <CoolRain/fragment.h>
+G_BEGIN_DECLS;
+
typedef void (*coolrain_template_error_handler_t)(
struct coolrain_template *tmpl, char const *message);
+struct coolrain_loader;
+
struct coolrain_template {
coolrain_mutex_t mutex;
struct coolrain_fragment *root;
struct coolrain_tagset *tagset;
- char name[PATH_MAX];
+ struct coolrain_loader *loader;
+ char const *name;
coolrain_refstring_t source;
struct {
struct coolrain_writer *writer;
};
-static inline void coolrain_eval_context_copy(struct coolrain_eval_context *dst, struct coolrain_eval_context const *src)
-{
- dst->tmpl = src->tmpl;
- dst->stash = src->stash;
- dst->fragment = src->fragment;
- dst->writer = src->writer;
-}
-
-
int coolrain_template_initialize(struct coolrain_template *tmpl, struct coolrain_tagset *tagset);
int coolrain_template_destroy(struct coolrain_template *tmpl);
int coolrain_template_clear(struct coolrain_template *tmpl);
+
+void coolrain_template_set_name(
+ struct coolrain_template * __restrict templ,
+ char const * __restrict name);
+
int coolrain_template_set_error_handler(
struct coolrain_template *tmpl,
coolrain_template_error_handler_t handler,
void* destroy_data);
int coolrain_template_eval_block(struct coolrain_eval_context const *cntx);
-int coolrain_template_eval_content(struct coolrain_eval_context const *cntx);
+
+
+static inline int coolrain_template_eval_content(struct coolrain_eval_context const *cntx)
+{
+ struct coolrain_eval_context new_cntx = *cntx;
+ new_cntx.fragment = new_cntx.fragment->data.tag.content;
+ return coolrain_template_eval_block(&new_cntx);
+}
+
int coolrain_template_run(
struct coolrain_template *tmpl,
struct coolrain_stash *stash,
struct coolrain_writer *writer);
+G_END_DECLS;
+
#endif
* Threading wrapper module of CoolRain
*
*/
-#if !defined(__COOLRAIN__THREAD__H__)
-#define __COOLRAIN__THREAD__H__
+#if !defined(COOLRAIN__THREAD__H__)
+#define COOLRAIN__THREAD__H__
#include <stdbool.h>
+#include <glib/gmacros.h>
+G_BEGIN_DECLS;
#if COOLRAIN_USE_GTHREAD
#endif
+G_END_DECLS;
#endif
*
*
*/
-#if !defined(__COOLRAIN__VARIANT__H__)
-#define __COOLRAIN__VARIANT__H__
+#if !defined(COOLRAIN__VARIANT__H__)
+#define COOLRAIN__VARIANT__H__
+#include <glib/gmacros.h>
#include <CoolRain/refstring.h>
#include <CoolRain/memory.h>
+G_BEGIN_DECLS;
+
struct coolrain_writer;
#define COOLRAIN_VARIANT_TYPE_STATIC_STRING (4)
#define COOLRAIN_VARIANT_TYPE_DYNAMIC_STRING (5)
#define COOLRAIN_VARIANT_TYPE_POINTER (6)
+#define COOLRAIN_VARIANT_TYPE_STATIC_CONTEXT (7)
+#define COOLRAIN_VARIANT_TYPE_DYNAMIC_CONTEXT (8)
+
+
typedef struct {
int type;
void *p;
void (*destroy_handler)(void *data);
} v_pointer;
+ struct coolrain_eval_context *v_cntx;
} data;
} coolrain_variant_t;
}
+
+void coolrain_variant_set_static_context(coolrain_variant_t *v, struct coolrain_eval_context *cntx);
+void coolrain_variant_set_dynamic_context(coolrain_variant_t *v, struct coolrain_eval_context const *cntx);
+
+
+
+/* */
void coolrain_variant_copy(coolrain_variant_t *dst, coolrain_variant_t const *src);
/* */
int coolrain_variant_write(coolrain_variant_t const *v, struct coolrain_writer *writer);
+G_END_DECLS;
+
#endif
*
*
*/
-#if !defined(__COOLRAIN__VERSION__H__)
-#define __COOLRAIN__VERSION__H__
+#if !defined(COOLRAIN__VERSION__H__)
+#define COOLRAIN__VERSION__H__
-#define COOLRAIN_NAME @PACKAGE_NAME@
+#define COOLRAIN_NAME "@PACKAGE_NAME@"
#define COOLRAIN_VERSION @PACKAGE_VERSION@
#endif
*
*
*/
-#if !defined(__COOLRAIN__WRITER__H__)
-#define __COOLRAIN__WRITER__H__
+#if !defined(COOLRAIN__WRITER__H__)
+#define COOLRAIN__WRITER__H__
#include <stddef.h>
#include <stdbool.h>
#include <stdbool.h>
+#include <glib/gmacros.h>
+
#include <CoolRain/error.h>
#include <CoolRain/thread.h>
+G_BEGIN_DECLS;
+
struct coolrain_writer;
typedef int (*coolrain_writer_buffer_full_handler_t)(struct coolrain_writer *writer);
int coolrain_url_filter(struct coolrain_writer *writer, char const **pbufferr, size_t length);
int coolrain_javascript_filter(struct coolrain_writer *writer, char const **pbuffer, size_t length);
+G_END_DECLS;
+
#endif
lib_LIBRARIES=
-SOURCES= builtin_tag_gkeyfile.c builtin_tag.c template.c fragment.c tagset.c stash.c variant.c writer_fd.c writer_fcgi.c writer.c filter.c
+SOURCES= builtin_tag_gkeyfile.c builtin_tag.c loader.c template.c fragment.c tagset.c stash.c variant.c writer_fd.c writer_fcgi.c writer.c filter.c
if HAVE_GLIB
lib_LIBRARIES+= libcoolrain-glib-nonthread.a
r = coolrain_template_eval_content(cntx);
coolrain_stash_restore(cntx->stash, vl, count);
+ coolrain_stash_value_list_unset(vl, count);
- for (i = 0; i < count; i++)
- coolrain_variant_destroy(&vl[i].value);
coolrain_free(vl);
return r;
}
}
coolrain_stash_restore(cntx->stash, vlist, 1);
+ coolrain_stash_value_list_unset(vlist, 1);
return COOLRAIN_SUCCESS;
}
+
+
+
+
+int coolrain_builtin_tag_handler_include_param(struct coolrain_eval_context const *cntx G_GNUC_UNUSED)
+{
+ return COOLRAIN_SUCCESS;
+}
+
+
+
+
+/**
+ *
+ */
+int coolrain_builtin_tag_handler_include(struct coolrain_eval_context const *cntx)
+{
+ char *href_cstr;
+ int r;
+ int param_count = 0;
+ struct coolrain_stash_value_list *vlist = NULL;
+ char* tagname;
+
+ if (cntx->tmpl->loader == NULL) {
+ coolrain_template_raise_error(cntx->tmpl, "Template %s has no loader.\n", cntx->tmpl->name);
+ return COOLRAIN_ERROR_NO_LOADER;
+ }
+
+
+ /* */
+ {
+ coolrain_refstring_t const* href = coolrain_fragment_find_attribute(cntx->fragment, "href");
+ if (href == NULL) {
+ tagname = coolrain_refstring_dup(&cntx->fragment->data.tag.tagdesc->name);
+ coolrain_template_raise_error(cntx->tmpl, "No 'href' attribute on %s tag\n", tagname);
+ coolrain_free(tagname);
+ return COOLRAIN_ERROR_NO_ATTRIBUTE;
+ }
+ href_cstr = coolrain_refstring_dup(href);
+ }
+
+
+ /* Bind all parameters */
+ {
+ struct coolrain_fragment *child;
+ coolrain_refstring_t const* name;
+ int n;
+
+ for (child = cntx->fragment->data.tag.content; child != NULL; child = child->next) {
+ if (child->type != COOLRAIN_FRAGMENT_TYPE_TAG ||
+ child->data.tag.tagdesc->handler != coolrain_builtin_tag_handler_include_param)
+ continue;
+ param_count++;
+ }
+
+ if (param_count > 0) {
+ vlist = coolrain_malloc(sizeof(struct coolrain_stash_value_list) * param_count);
+
+ n = 0;
+ for (child = cntx->fragment->data.tag.content; n < param_count && child != NULL; child = child->next) {
+ if (child->type != COOLRAIN_FRAGMENT_TYPE_TAG ||
+ child->data.tag.tagdesc->handler != coolrain_builtin_tag_handler_include_param)
+ continue;
+
+ name = coolrain_fragment_find_attribute(child, "name");
+ if (name == NULL) continue;
+
+ vlist[n].name = *name;
+ coolrain_variant_initialize(&vlist[n].value);
+ coolrain_variant_set_dynamic_context(&vlist[n].value, cntx);
+ vlist[n].value.data.v_cntx->fragment = child;
+ vlist[n].old_value = NULL;
+ n++;
+ }
+
+ param_count = n;
+ coolrain_stash_set_values(cntx->stash, vlist, param_count);
+ }
+ }
+
+
+ /* Process included template */
+ r = coolrain_loader_process_template(cntx->tmpl->loader, href_cstr, cntx->stash, cntx->writer);
+ coolrain_free(href_cstr);
+ if (r != 0) {
+ coolrain_template_raise_error(cntx->tmpl, " include from %s\n", cntx->tmpl->name);
+ }
+
+
+ /* Reelase memories */
+ if (vlist != NULL) {
+ if (param_count > 0)
+ coolrain_stash_restore(cntx->stash, vlist, param_count);
+ coolrain_stash_value_list_unset(vlist, param_count);
+
+ coolrain_free(vlist);
+ }
+
+ return r;
+}
+
+
static int coolrain_builtin_tag_gkeyfile_with_locale_tag_handler(struct coolrain_eval_context const *cntx)
{
- coolrain_refstring_t const *locale;
int r;
struct coolrain_stash_value_list vl[1] = {
{ { ".CR.Keyfile.locale", NULL }, COOLRAIN_VARIANT_INITIALIZER, NULL }
struct coolrain_fragment_attribute *attr =
coolrain_malloc(sizeof(struct coolrain_fragment_attribute));
if (attr != NULL){
- attr->next = NULL;
+ attr->next = NULL;
+ attr->flags = 0;
}
return attr;
}
{
while (attrs != NULL) {
struct coolrain_fragment_attribute *next = attrs->next;
+ if (attrs->flags & (1 << COOLRAIN_FRAGMENT_ATTR_FLAGS_CSTRING))
+ coolrain_free((char*)attrs->value.begin);
coolrain_free(attrs);
attrs = next;
}
-coolrain_refstring_t const *coolrain_fragment_find_attribute(struct coolrain_fragment const* fragment, char const *name)
+coolrain_refstring_t const *coolrain_fragment_find_attribute(
+ struct coolrain_fragment const * restrict fragment,
+ char const * restrict name)
{
struct coolrain_fragment_attribute const *attr;
coolrain_refstring_t tmp;
}
+
+char const *coolrain_fragment_find_attribute_as_cstring(
+ struct coolrain_fragment const * restrict fragment,
+ char const * restrict name)
+{
+ struct coolrain_fragment_attribute *attr;
+ coolrain_refstring_t tmp;
+
+ if (fragment->type != COOLRAIN_FRAGMENT_TYPE_TAG)
+ return NULL;
+
+ tmp.begin = name;
+ tmp.end = name + strlen(name);
+
+ attr = fragment->data.tag.attrs;
+ for (attr = fragment->data.tag.attrs; attr != NULL; attr = attr->next) {
+ if (! coolrain_refstring_equal(&attr->name, &tmp)) continue;
+
+ if (! (attr->flags & (1 << COOLRAIN_FRAGMENT_ATTR_FLAGS_CSTRING)) ) {
+ /* Create duplicate string */
+ size_t len = coolrain_refstring_length(&attr->value);
+ char * newstr = coolrain_malloc(len + 1);
+ memcpy(newstr, attr->value.begin, len);
+ newstr[len] = '\0';
+
+ /* Replace pointer */
+ attr->value.begin = newstr;
+ attr->value.end = newstr + len;
+ attr->flags |= 1 << COOLRAIN_FRAGMENT_ATTR_FLAGS_CSTRING;
+ }
+ return &attr->value.begin;
+ }
+
+ return NULL;
+}
+
+
+
+
--- /dev/null
+/**
+ * \brief Template repository and loader module for CoolRain template engine.
+ *
+ * Copyright (c) HATTORI, Hiroki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(HAVE_CONFIG_H)
+# include "../config.h"
+#endif
+
+#include <CoolRain/loader.h>
+#include <CoolRain/template.h>
+#include <CoolRain/tagset.h>
+#include <CoolRain/memory.h>
+
+
+
+/**
+ * Initialize loader
+ * \param loader Pointer to memory for New loader object.
+ * \param ops VTBL of template class.
+ * \param tagset Tagset object for templates on repository.
+ * \return Error code.
+ */
+int coolrain_loader_initialize(
+ struct coolrain_loader * restrict loader,
+ struct coolrain_loader_ops * restrict ops,
+ struct coolrain_tagset * restrict tagset)
+{
+ loader->ops = ops;
+ loader->driver_data = NULL;
+ loader->flags = 0;
+
+ if (tagset == NULL) {
+ loader->tagset = coolrain_malloc(sizeof(struct coolrain_tagset));
+ coolrain_tagset_initialize(loader->tagset);
+ loader->flags |= 1 << COOLRAIN_LOADER_FLAGS_AUTO_FREE_TAGSET;
+ } else {
+ loader->tagset = tagset;
+ }
+
+ loader->error_handler = NULL;
+ loader->error_user_data = NULL;
+
+ loader->user_data = NULL;
+ loader->preprocess = NULL;
+ loader->postprocess = NULL;
+
+ return COOLRAIN_SUCCESS;
+}
+
+
+
+/**
+ * Destroy loader.
+ * \param loader Loader object.
+ */
+void coolrain_loader_destroy(struct coolrain_loader *loader)
+{
+ loader->ops->destroy(loader);
+ if (loader->flags & (1 << COOLRAIN_LOADER_FLAGS_AUTO_FREE_TAGSET)) {
+ coolrain_tagset_destroy(loader->tagset);
+ coolrain_free(loader->tagset);
+ }
+}
+
+
+
+/**
+ * Load template from repository.
+ * \param loader Loader object.
+ * \param tmpl Template object
+ * \param name Name of template to load.
+ * \return Error code
+ */
+int coolrain_loader_load_template(
+ struct coolrain_loader * restrict loader,
+ struct coolrain_template * restrict tmpl,
+ char const * restrict name)
+{
+ int r = loader->ops->load(loader, tmpl, name);
+ tmpl->loader = loader;
+ return r;
+}
+
+
+
+/**
+ * Load template and run it.
+ * \param loader Template object.
+ * \param name Name of template to load.
+ * \param stash Stash object
+ * \param write Writer object to output.
+ * \return Error code
+ */
+int coolrain_loader_process_template(
+ struct coolrain_loader * restrict loader,
+ char const * restrict name,
+ struct coolrain_stash * restrict stash,
+ struct coolrain_writer * restrict writer)
+{
+ int r;
+ struct coolrain_template tmpl;
+
+ r = coolrain_template_initialize(&tmpl, loader->tagset);
+ if (r == COOLRAIN_SUCCESS) {
+ coolrain_template_set_error_handler(&tmpl, loader->error_handler, loader->error_user_data);
+
+ r = coolrain_loader_load_template(loader, &tmpl, name);
+ if (r == COOLRAIN_SUCCESS)
+ r = coolrain_template_run(&tmpl, stash, writer);
+
+ coolrain_template_destroy(&tmpl);
+ }
+
+ return r;
+}
+
+
+
+
+
+static int file_loader_load(
+ struct coolrain_loader * restrict loader,
+ struct coolrain_template * restrict tmpl,
+ char const* restrict name)
+{
+ char path[PATH_MAX];
+ size_t dirlen = strlen(loader->driver_data);
+
+ memcpy(path, loader->driver_data, dirlen);
+ path[dirlen] = '/';
+ strcpy(path + dirlen + 1, name);
+
+ return coolrain_template_compile(tmpl, path);
+}
+
+
+
+
+static void file_loader_destroy(struct coolrain_loader *loader)
+{
+ coolrain_free(loader->driver_data);
+}
+
+
+static struct coolrain_loader_ops file_loader_ops = {
+ .load = file_loader_load,
+ .destroy = file_loader_destroy,
+};
+
+
+
+/**
+ * Initialize file based template loader.
+ * \param loader Pointer to memory for new loader object.
+ * \param tagset Tagset object.
+ * \param base_dir Base directory of templates.
+ * \return Error code.
+ */
+int coolrain_file_loader_initialize(
+ struct coolrain_loader * restrict loader,
+ struct coolrain_tagset * restrict tagset,
+ char const * restrict base_dir)
+{
+ int r = coolrain_loader_initialize(loader, &file_loader_ops, tagset);
+ if (r == COOLRAIN_SUCCESS)
+ loader->driver_data = coolrain_strdup(base_dir);
+
+ return r;
+}
+
+
/**
+ * \brief Stash variable module for CoolRain template engine.
*
+ * Copyright (c) HATTORI, Hiroki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#if defined(HAVE_CONFIG_H)
# include "../config.h"
while (count--) {
coolrain_variant_t const *v = g_hash_table_lookup(stash->hash, (gpointer)&values->name);
+ g_assert(values->old_value == NULL);
+
values->old_value = v;
g_hash_table_insert(stash->hash, &values->name, (gpointer)&values->value);
while (count--) {
if (values->old_value == NULL)
g_hash_table_remove(stash->hash, &values->name);
- else
+ else {
g_hash_table_insert(stash->hash, &values->name, (gpointer)values->old_value);
+ values->old_value = NULL;
+ }
values++;
}
}
+
+
+/**
+ *
+ */
+void coolrain_stash_value_list_unset(struct coolrain_stash_value_list * restrict values, size_t count)
+{
+ while (count--) {
+ coolrain_variant_unset(&values->value);
+ values++;
+ }
+}
+
+
{ { "CR:let", NULL }, coolrain_builtin_tag_handler_let, 0 },
{ { "CR:var", NULL }, coolrain_builtin_tag_handler_var, 0 },
{ { "CR:loop", NULL }, coolrain_builtin_tag_handler_loop, 0 },
+ { { "CR:include", NULL }, coolrain_builtin_tag_handler_include, 0 },
+ { { "CR:param", NULL }, coolrain_builtin_tag_handler_include_param, 0 },
{ { NULL, NULL }, NULL, 0 }
};
#include <CoolRain/tagset.h>
#include <CoolRain/template.h>
#include <CoolRain/memory.h>
+#include <CoolRain/loader.h>
+static char dummy_empty_str[] = "<UNTITLED>";
+
/**
* Initialize template object
{
coolrain_mutex_init(&tmpl->mutex);
- tmpl->root = NULL;
+ tmpl->root = NULL;
- tmpl->name[0] = '\0';
- tmpl->source.begin = NULL;
- tmpl->source.end = NULL;
+ tmpl->loader = NULL;
+ tmpl->name = dummy_empty_str;
+ tmpl->source.begin = NULL;
+ tmpl->source.end = NULL;
tmpl->parser_state.lineno = 0;
- tmpl->destroy_callback = NULL;
- tmpl->destroy_data = NULL;
+ tmpl->destroy_callback = NULL;
+ tmpl->destroy_data = NULL;
- tmpl->tagset = tagset;
+ tmpl->tagset = tagset;
- tmpl->error_handler = default_error_handler;
- tmpl->error_user_data = NULL;
+ tmpl->error_handler = default_error_handler;
+ tmpl->error_user_data = NULL;
return COOLRAIN_SUCCESS;
}
if (tmpl->destroy_callback != NULL)
(*tmpl->destroy_callback)(tmpl);
- tmpl->name[0] = '\0';
+ coolrain_template_set_name(tmpl, NULL);
+
tmpl->source.begin = NULL;
tmpl->source.end = NULL;
tmpl->parser_state.lineno = 0;
+void coolrain_template_set_name(
+ struct coolrain_template * restrict tmpl,
+ char const * restrict new_name)
+{
+ if (tmpl->name != dummy_empty_str)
+ coolrain_free((void*)tmpl->name);
+ tmpl->name = (new_name == NULL)? dummy_empty_str : coolrain_strdup(new_name);
+}
+
+
/**
* Assign error callback handler.
*/
int coolrain_template_compile(struct coolrain_template *tmpl, char const *path)
{
- off_t length;
- char *p;
- int fd = open(path, O_RDONLY);
- int r;
- if (fd < 0) return COOLRAIN_ERROR_NOFILE;
-
- length = lseek(fd, 0, SEEK_END);
- if (length < 0) {
+ int r = COOLRAIN_ERROR_NOFILE;
+ int fd = open(path, O_RDONLY);
+
+ if (fd >= 0) {
+ off_t length = lseek(fd, 0, SEEK_END);
+ r = COOLRAIN_ERROR_CANT_READ;
+ if (length > 0) {
+ char *p = mmap(0, (size_t)length, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (p != NULL)
+ r = coolrain_template_parse(tmpl, path, p, (size_t)length, munmap_handler, NULL);
+ }
+
close(fd);
- return COOLRAIN_ERROR_BAD_LENGTH;
}
-
- p = mmap(0, (size_t)length, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
- if (p == NULL) return COOLRAIN_ERROR_CANT_READ;
-
- r = coolrain_template_parse(tmpl, path, p, (size_t)length, munmap_handler, NULL);
-
return r;
}
coolrain_template_clear_(tmpl);
- strncpy(tmpl->name, name, PATH_MAX);
+ coolrain_template_set_name(tmpl, name);
+
tmpl->source.begin = source;
tmpl->source.end = source + length;
tmpl->destroy_callback = destroy_callback;
{
int r;
struct coolrain_eval_context cntx;
+ void *preproc_data = NULL;
cntx.tmpl = tmpl;
cntx.fragment = tmpl->root;
// FIXME: Check recursive call
coolrain_mutex_lock(&tmpl->mutex);
+
+ if (tmpl->loader != NULL && tmpl->loader->preprocess != NULL) {
+ r = tmpl->loader->preprocess(&cntx, &preproc_data);
+ if (r != COOLRAIN_SUCCESS) {
+ coolrain_mutex_unlock(&tmpl->mutex);
+ return r;
+ }
+ }
+
r = coolrain_template_eval_block(&cntx);
+
+ if (tmpl->loader != NULL && tmpl->loader->postprocess != NULL)
+ tmpl->loader->postprocess(&cntx, preproc_data);
+
coolrain_mutex_unlock(&tmpl->mutex);
return r;
int r = COOLRAIN_SUCCESS;
struct coolrain_eval_context my_cntx;
- coolrain_eval_context_copy(&my_cntx, cntx);
-
+ my_cntx = *cntx;
for (; my_cntx.fragment != NULL && r >= 0; my_cntx.fragment = my_cntx.fragment->next) {
switch (my_cntx.fragment->type) {
return COOLRAIN_SUCCESS;
}
-
+#if 0
int coolrain_template_eval_content(struct coolrain_eval_context const *cntx)
{
- struct coolrain_eval_context new_cntx;
- coolrain_eval_context_copy(&new_cntx, cntx);
+ struct coolrain_eval_context new_cntx = *cntx;
new_cntx.fragment = new_cntx.fragment->data.tag.content;
return coolrain_template_eval_block(&new_cntx);
}
-
+#endif
#include <glib/gmessages.h>
+#include <CoolRain/template.h>
#include <CoolRain/variant.h>
#include <CoolRain/memory.h>
#include <CoolRain/writer.h>
case COOLRAIN_VARIANT_TYPE_POINTER:
v->data.v_pointer.destroy_handler(v->data.v_pointer.p);
break;
+ case COOLRAIN_VARIANT_TYPE_DYNAMIC_CONTEXT:
+ coolrain_free(v->data.v_cntx);
+ break;
}
v->type = COOLRAIN_VARIANT_TYPE_NULL;
+void coolrain_variant_set_static_context(coolrain_variant_t *v, struct coolrain_eval_context *cntx)
+{
+ coolrain_variant_unset(v);
+ v->type = COOLRAIN_VARIANT_TYPE_STATIC_CONTEXT;
+ v->data.v_cntx = cntx;
+}
+
+
+void coolrain_variant_set_dynamic_context(coolrain_variant_t *v, struct coolrain_eval_context const *cntx)
+{
+ coolrain_variant_unset(v);
+ v->type = COOLRAIN_VARIANT_TYPE_STATIC_CONTEXT;
+ v->data.v_cntx = coolrain_malloc(sizeof(struct coolrain_eval_context));
+ *v->data.v_cntx = *cntx;
+}
+
+
+
+
+
/**
*
*/
case COOLRAIN_VARIANT_TYPE_POINTER:
dst->data.v_pointer = src->data.v_pointer;
break;
+ case COOLRAIN_VARIANT_TYPE_STATIC_CONTEXT:
+ dst->data.v_cntx = src->data.v_cntx;
+ break;
+ case COOLRAIN_VARIANT_TYPE_DYNAMIC_CONTEXT:
+ dst->data.v_cntx = coolrain_malloc(sizeof(struct coolrain_eval_context));
+ *dst->data.v_cntx = *src->data.v_cntx;
+ break;
default:
g_assert_not_reached();
}
return coolrain_writer_write(writer, v->data.v_static_string, -1);
case COOLRAIN_VARIANT_TYPE_DYNAMIC_STRING:
return coolrain_writer_write(writer, v->data.v_dynamic_string, -1);
+ case COOLRAIN_VARIANT_TYPE_POINTER:
+#if 0
+ if (v->data.v_pointer.rendering_handler != NULL)
+ return v->data.v_pointer.rendering_handler(writer, v->data.v_pointer.p);
+ else
+ return COOLRAIN_SUCCESS;
+#else
+ return COOLRAIN_SUCCESS;
+#endif
+
+ case COOLRAIN_VARIANT_TYPE_STATIC_CONTEXT:
+ case COOLRAIN_VARIANT_TYPE_DYNAMIC_CONTEXT:
+ return coolrain_template_eval_content(v->data.v_cntx);
}
return COOLRAIN_SUCCESS;
}
--- /dev/null
+/**
+ *
+ */
+#if HAVE_CONFIG_H
+# include "../config.h"
+#endif
+
+#include <glib/gmessages.h>
+#include <glib/gmacros.h>
+
+#include <CoolRain/error.h>
+#include <CoolRain/thread.h>
+#include <CoolRain/writer.h>
+
+
+static char dummy_buffer[1];
+
+static int dummy_handler(struct coolrain_writer *writer G_GNUC_UNUSED)
+{
+ return COOLRAIN_SUCCESS;
+}
+
+
+static int write_handler(struct coolrain_writer *writer, char const **buffer, size_t length)
+{
+ int r = (length == (size_t)-1)?
+ FCGX_PutS(*buffer, writer->write_handler_data.pointee) :
+ FCGX_PutStr(*buffer, length, writer->write_handler_data.pointee);
+
+ if (r == -1) return COOLRAIN_ERROR_IO;
+
+ *buffer += r;
+ return COOLRAIN_SUCCESS;
+}
+
+int coolrain_FCGI_writer_initialize(struct coolrain_writer *writer, FCGX_Stream *stream)
+{
+ int r = coolrain_writer_initialize(writer, dummy_buffer, 1);
+ if (r == COOLRAIN_SUCCESS) {
+ writer->write_handler_data.pointee = stream;
+ writer->write_handler = write_handler;
+ writer->buffer_full_handler = dummy_handler;
+ writer->destroy_handler = dummy_handler;
+ }
+
+ return COOLRAIN_SUCCESS;
+}
+
+
+
check_PROGRAMS=
TESTS=${check_PROGRAMS}
-SOURCES= runtest.c test_writer.c test_tagset.c test_stash.c test_template.c
+SOURCES= runtest.c test_writer.c test_tagset.c test_stash.c test_template.c test_loader.c
LIBS= -L${top_builddir}/src -lcunit
CONFIG_CLEAN_FILES=CUnitAutomated-Listing.xml CUnitAutomated-Results.xml
extern bool setup_test_tagset(void);
extern bool setup_test_template(void);
extern bool setup_test_stash(void);
+extern bool setup_test_loader(void);
int main(int argc, char *argv[])
{
if (! setup_test_writer() ||
! setup_test_tagset() ||
! setup_test_stash() ||
- ! setup_test_template()
+ ! setup_test_template() ||
+ ! setup_test_loader()
) {
CU_cleanup_registry();
return CU_get_error();
--- /dev/null
+This is t1.template.
+foo=${foo}
+bar=${bar}
+<CR:loop name="i" from="0" to="10">#${i} </CR:loop>
+
--- /dev/null
+/*
+ */
+#include <stdbool.h>
+#include <CUnit/Basic.h>
+#include <CoolRain/CoolRain.h>
+
+
+
+static struct coolrain_loader loader;
+
+
+static int preproc(struct coolrain_eval_context * restrict cntx, void ** restrict preproc_data)
+{
+ return COOLRAIN_SUCCESS;
+}
+
+static void postproc(struct coolrain_eval_context * restrict cntx, void * restrict preproc_data)
+{
+}
+
+
+int init_test_loader(void)
+{
+ int r;
+ r = coolrain_file_loader_initialize(&loader, NULL, "templates");
+ if (r != 0) return r;
+
+ loader.user_data = NULL;
+ loader.preprocess = preproc;
+ loader.postprocess = postproc;
+
+ coolrain_tagset_register_filters(loader.tagset, coolrain_tagset_default_filters);
+ coolrain_tagset_register_tags(loader.tagset, coolrain_tagset_default_tags);
+ coolrain_tagset_register_tags(loader.tagset, coolrain_tagset_gkeyfile_tags);
+
+ return 0;
+}
+
+int clean_test_loader(void)
+{
+ coolrain_loader_destroy(&loader);
+ return 0;
+}
+
+
+static char obuffer[4096];
+
+
+
+void test_loader_simple(void)
+{
+ struct coolrain_stash stash;
+ struct coolrain_writer writer;
+ static char result[] = "This is t1.template.\nfoo=\nbar=\n#0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 \n\n";
+
+ CU_ASSERT_EQUAL_FATAL(coolrain_stash_initialize(&stash), COOLRAIN_SUCCESS);
+ CU_ASSERT_EQUAL_FATAL(coolrain_writer_initialize(&writer, obuffer, sizeof(obuffer)), COOLRAIN_SUCCESS);
+
+ CU_ASSERT_EQUAL(coolrain_loader_process_template(&loader, "t1.template", &stash, &writer), COOLRAIN_SUCCESS);
+
+ coolrain_stash_destroy(&stash);
+ coolrain_writer_destroy(&writer);
+
+ CU_ASSERT_NSTRING_EQUAL(obuffer, result, strlen(result));
+}
+
+
+
+
+bool setup_test_loader(void)
+{
+
+ CU_pSuite s = CU_add_suite("Loader", init_test_loader, clean_test_loader);
+ if (NULL == s) return false;
+
+ if (NULL == CU_add_test(s, "parse", test_loader_simple)
+ )
+ return false;
+ return true;
+}
+
+
coolrain_stash_restore(&stash, vl, sizeof(vl) / sizeof(vl[0]));
coolrain_stash_destroy(&stash);
+
+ coolrain_variant_unset(&v[2]);
}