34 Commits
0.9.0 ... 0.9.5

Author SHA1 Message Date
c6b4db0aa9 added: methods Begin() and End() to Functions<>
we can iterate through the whole functions table


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@360 e52654a7-88a9-db11-a3e9-0013d4bc506e
2012-01-06 12:05:10 +00:00
b4f7d4b8de added: size_t UTF8ToInt(const char * utf8, int & res, bool & correct)
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@359 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-08-27 19:14:20 +00:00
542587e5e8 deleted debug log
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@358 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-07-15 02:09:40 +00:00
fb05eb6860 added some debug log
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@357 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-07-13 23:15:12 +00:00
8df9aa86a0 small changes in Makefile
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@356 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-06-06 20:36:19 +00:00
2d304a9714 changed to UTF-8: added support for UTF-16 when wchar_t is 2 bytes long
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@345 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-05-25 21:43:40 +00:00
861269383e changed: [is...] statements use only the output string now (when comparing)
previously they used FunInfo::res, now they use FunInfo::out
         and the out string is not put to the main output stream
added:   FunInfo<>::case_sensitive (default true)
         when false then [is] statement is comparing in case insensitive manner
changed: the out stream in [if...] [for] statements
         the output text is ingored now



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@344 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-04-26 17:17:06 +00:00
542e50d757 added filters:
a new statement [filter]
 syntax:
 [filter funcion_name]....[end]
 everything which is between [filter] and [end] is processed normally and
 at the end it is passed to the function (function_name)
 FunInfo struct has 'in' input stream now



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@333 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-01-26 12:42:49 +00:00
3c85fa1a75 fixed: the exception for if-index in pattern (when caching is used)
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@332 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-01-23 14:16:49 +00:00
fd2194623a changed: now [for] statements with the same function can be nested
sample:
[for my_function]
 [for my_function]
   foo
 [end]
[end]

changed: FunInfo::iter has a value from the last [for] statement now
sample:
[for my_function]
 [other_function]
[end]

void other_function(Info &i)
{
// here i.iter is the number of iteration
// previously was always zero
}

changed: small optimization in [for]
the proper function is being looking for only once at the beginning
previously it was searched in each iteration



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@331 e52654a7-88a9-db11-a3e9-0013d4bc506e
2011-01-14 23:59:30 +00:00
c4f5f79218 fixed: Item::Item(const Item & i) should clear the item table
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@330 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-12-06 00:22:38 +00:00
0b09b5454f added: Pattern::CacheFunctions(Functions<StreamType> & fun)
you can cache all functions (their addresses) in the pattern

changed: now we have two methods for generating content:
       Generator<>::Generate(StreamType & o, Pattern & p, Functions<StreamType> & f);
       similar like previous -- Set(...) methods were removed as well as the second ctor 

       and a second one:
       Generate(StreamType & o, Pattern & p);
       without functions, the functions should be cached beforehand in the pattern
       by calling CacheFunctions() method on the pattern
       this gives O(1) complexity when looking for a specific function
       previously was O(log n) 
       


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@329 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-11-25 22:39:58 +00:00
5108495540 changed in Generator<>:
StreamType
 we use method write where the content should not be escaped (html escaping)
 we use operator<< where the content can be escaped (such as error messages)

PrintSpecialText() and PrintNormalText() are a little faster now
we use 'write' for a whole text instead of printing each character



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@328 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-11-25 01:55:32 +00:00
33c86d494b fixed: performance (memcpy used too often)
in some places there were reserve() method used (on std::wstring/std::string objects)
         especially in AssignString() methods
         if we add a new string we should check the new size
         and only call reserve() if the new size will be greater than existing one
         (plus some constant)
added:   Functions<>::Size() method



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@327 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-11-23 21:59:52 +00:00
8f94937ed1 added: support for UTF-8 (files utf8.h utf8.cpp)
they can be even used without the rest library
         as only a library for converting between wide characters and UTF-8
changed: everywhere we use std::wstring instead of std::string
changed: Generator and Functions are templates now
         they take a stream type
renamed: Info to FunInfo and it is a template too
         taking a stream type

now you can use other kind of streams with the library
previous was only std::ostringstream



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@326 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-11-22 01:23:32 +00:00
b5ea2514e2 added to Generator:
void RecognizeSpecialChars(bool spec);
  recognizing some special characters in text patterns (item_text in Patterns)
  \r will be a carriage return (13)
  \n will be a new line (10)
  \t will be a tabulator (9)
  \s will be a space
  \\ will be one '\'
  default: false

void TrimWhite(bool trim);
  trimming white characters (at the beginning and at the end of an item_text)
  (special char \s if enabled is not treated as a white character here)
  default: false 

void SkipNewLine(bool skip);
  skipping new line characters (from the whole string in an item_text)
  but you can use a new line character written as "\n" (if special chars are turn on)
  default: false
						       


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@305 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-09-07 23:52:41 +00:00
376fe414f8 small refactoring: changed item_table to item_tab
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@300 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-08-17 23:22:55 +00:00
7554630395 changed: testing file names
now it is allowed to use a slash (we can use directories)
only ".." is not allowed (you cannot go up in a directory structure)


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@299 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-08-02 18:47:19 +00:00
573d241dc1 changed:
functions can have more than one parameter and the parameters can be used in [if...] statements too

sample:
[normal_function "par1" "par2" "par3"]
[if-one function "par1" "par2" "par3"]...[end]

each function can have its own parameters:
[if-one function1 "par1" "par2" "par3" function2 "par" "par2"]...[end]

changed:
[is] is now [if] (not exactly but very similar)
[is-no] is now [if-no] (the same)

[if] and [if-no] are taking one function (with or without arguments)
sample:
[if function]...[end]
[if function "par1"]...[end]
[if function "par1" "par2" "par3" "par4"]...[end]

[is] is taking two functions now and evaluates them to boolean value
(variables are also evaluated to boolean - if not empty that means true)

[is function1 function2]...[end]
[is variable1 variable2] either variable1 and variable2 are empty or both are not empty
(they don't have to be equal)[end]

added:
[if-any-no fun1 fun2 fun3] the three functions have to return false [end] 
[if-one-no fun1 fun2 fun3] one the the three functions have to return false [end]

removed:
extracting the unix directory from the file name (in patterns)
you have to call Pattern::Directory() method first to set directories



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@298 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-07-19 23:07:00 +00:00
c807d1c9b3 as a white character can be ascii 160 code (nonbreakable space)
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@297 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-06-30 18:43:33 +00:00
b89c6daa7d added: an optional string parameter to normal statement e.g. [function "parameter"]
parameters to "for" statement  [for function "parameter"]
changed: in Info struct there is a "par" std::string reference now
changed: Info::result to Info::res
removed: Info::is


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@295 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-05-30 21:07:15 +00:00
f65178dd0e fixed: when Pattern::allow_include was false then nothing was read
added: ezc can use the logger from winix
added: we check how many [include] directive was called
       (if more than 100 then we break - supposing infinite loop)
added: in Pattern we read from two directories
       if a file is not in the first directory then we try to read
       from the other one




git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@292 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-15 00:19:31 +00:00
bb00f23f29 changed: limits in generator
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@291 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-13 19:55:51 +00:00
31156d33f3 added: directive [is-no ...] negative to [is ...]
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@290 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-02-11 20:03:51 +00:00
e71c213ad1 added: Pattern::Clear()
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@282 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-01-28 16:14:47 +00:00
b2aacc2da3 changed: [is ...] command
struct Info doesn't have out_string now



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@281 e52654a7-88a9-db11-a3e9-0013d4bc506e
2010-01-25 05:19:54 +00:00
dbe91a6d91 added: Patter::delete_all_white flag
if true all text-items which have only white characters (with new lines as well)
       will be deleted
       this not actually delete the whole item but only the string
       the item will be present with an empty string
       default: false



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@260 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-12-09 00:34:17 +00:00
9b4586d7be small changes in Makefile
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@241 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-11-13 21:10:06 +00:00
141e1f67b3 added: Pattern::allow_include flag (default true)
if false there is no allowed [include ...] directive
       (this directive will be skipped)
added: Pattern::ParseString(const std::string & str);
       Pattern::ParseString(const char * str);
       can create the pattern from a string


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@94 e52654a7-88a9-db11-a3e9-0013d4bc506e
2009-01-23 23:18:54 +00:00
f8f55eae77 added: src/Makefile and src/Makefile.dep
the ezc.a library is built now


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@93 e52654a7-88a9-db11-a3e9-0013d4bc506e
2008-12-30 01:21:30 +00:00
0b88257e08 added: directive [if-no fun1 fun2 ...]
if fun1 fun2 ... return false
       then the content is evaluated
changed: [if-one fun1 fun2 ...]
       when a function (from left to right) returns true 
       then the content is evaluated
       (previous all functions were called)


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@91 e52654a7-88a9-db11-a3e9-0013d4bc506e
2008-12-23 20:08:11 +00:00
0760313ec3 changing version info to: 0.9.1
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@89 e52654a7-88a9-db11-a3e9-0013d4bc506e
2008-12-10 01:59:39 +00:00
54be9c0489 changed: the interface in this version is not the same as previous
added: class Functions, you can define your own set of functions and then
       put them into the Generator
added: variables
       parser is able to parse the "def" directive:
       [def variable "value"]
       [def variable another_variable]
       [def variable another_function]
       variables are put into a Functions object
added: class Info has a reference to std::ostringstream (out)
added: limit for a "for" directive
       limit for the whole tree (when genereting)
       this is to protect for a case when someone makes an infinite loop
changed: many small changes


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@88 e52654a7-88a9-db11-a3e9-0013d4bc506e
2008-12-10 01:46:10 +00:00
bf585d3716 moving cgi/ezc into /
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@86 e52654a7-88a9-db11-a3e9-0013d4bc506e
2008-12-10 00:56:56 +00:00
17 changed files with 4370 additions and 1137 deletions

View File

@@ -1,4 +1,4 @@
Copyright (c) 2007, Tomasz Sowa Copyright (c) 2007-2010, Tomasz Sowa
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

26
src/Makefile Executable file
View File

@@ -0,0 +1,26 @@
include Makefile.o.dep
all: ezc.a
ezc.a: $(o)
ar rcs ezc.a $(o)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $<
depend:
makedepend $(CXXFLAGS) -Y. -f- *.cpp > Makefile.dep
echo -n "o = " > Makefile.o.dep
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep
clean:
rm -f *.o
rm -f *.a
include Makefile.dep

28
src/Makefile.dep Executable file
View File

@@ -0,0 +1,28 @@
# DO NOT DELETE
edanticitem.o: item.h funinfo.h
edanticpattern.o: pattern.h item.h funinfo.h functions.h stringconv.h utf8.h
edanticpattern.o: /home/tomek/roboczy/winix/core/log.h
edanticpattern.o: /home/tomek/roboczy/winix/core/textstream.h
edanticpattern.o: /home/tomek/roboczy/winix/core/misc.h
edanticpattern.o: /home/tomek/roboczy/winix/core/requesttypes.h
edanticpattern.o: /home/tomek/roboczy/winix/core/logmanipulators.h
edanticpattern.o: /home/tomek/roboczy/winix/core/slog.h
edanticpattern.o: /home/tomek/roboczy/winix/core/cur.h
edanticpattern.o: /home/tomek/roboczy/winix/core/request.h
edanticpattern.o: /usr/local/include/fcgiapp.h
edanticpattern.o: /home/tomek/roboczy/winix/core/error.h
edanticpattern.o: /home/tomek/roboczy/winix/core/config.h
edanticpattern.o: /home/tomek/roboczy/winix/core/confparser.h
edanticpattern.o: /home/tomek/roboczy/winix/core/htmlfilter.h
edanticpattern.o: /home/tomek/roboczy/winix/templates/htmltextstream.h
edanticpattern.o: /home/tomek/roboczy/winix/core/textstream.h
edanticpattern.o: /home/tomek/roboczy/winix/core/session.h
edanticpattern.o: /home/tomek/roboczy/winix/core/user.h
edanticpattern.o: /home/tomek/roboczy/winix/core/plugindata.h
edanticpattern.o: /home/tomek/roboczy/winix/core/rebus.h
edanticpattern.o: /home/tomek/roboczy/winix/core/mount.h
edanticpattern.o: /home/tomek/roboczy/winix/templates/locale.h
edanticpattern.o: /home/tomek/roboczy/winix/core/confparser.h
edanticstringconv.o: stringconv.h
edanticutf8.o: utf8.h

1
src/Makefile.o.dep Executable file
View File

@@ -0,0 +1 @@
o = item.o pattern.o stringconv.o utf8.o

View File

@@ -1,982 +0,0 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
/*
* Copyright (c) 2007, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#include "ezc.h"
namespace Ezc
{
std::string CreateMsg(const char * type, const char * arg)
{
std::ostringstream buffer;
buffer << "<!-- ezc: " << type << " ";
if( arg )
buffer << arg << " ";
buffer << "-->";
return buffer.str();
}
/*
this method splits the input file name into a directory and a file name
e.g
if 'name' is "/this/is/dummy/file.ezc"
the result will be:
dir = "/this/is/dummy"
file = "file.ezc"
*/
void SplitUnixDirectory(const char * name, std::string & dir, std::string & file)
{
dir.clear();
file.clear();
int i;
for( i=0 ; name[i] != 0 ; ++i );
if( i == 0 )
return;
for( --i ; i>=0 && name[i]!='\\' && name[i]!='/' ; --i );
if( i < 0 )
{
file.assign(name);
}
else
{
if( i == 0 )
// we're leaving one '/' in the directory
// (we have only the root directory)
dir.assign(name, 1);
else
dir.assign(name, i);
file.assign(name + i + 1 );
}
return;
}
void SplitUnixDirectory(const std::string & name, std::string & dir, std::string & file)
{
SplitUnixDirectory(name.c_str(), dir, file);
}
/*
*
* Pattern
*
*
*/
void Pattern::ParseFile(const std::string & file_name)
{
ParseFile( file_name.c_str() );
}
void Pattern::ParseFile(const char * file_name)
{
std::string file;
if( directory.empty() )
SplitUnixDirectory(file_name, directory, file);
else
file = file_name;
file.insert(file.begin(), '\"');
item_root.directives.clear();
item_root.directives.push_back( file );
CreateTreeReadInclude(item_root);
}
void Pattern::Directory(const char * d)
{
directory = d;
}
void Pattern::Directory(const std::string & d)
{
directory = d;
}
bool Pattern::CheckFileName(const char * name)
{
// very simple testing -- this path 'some..name' is incorrect as well
// (in the future it can be changed)
for( ; *name ; ++name )
{
if( *name=='.' && *(name+1)=='.' )
return false;
}
return true;
}
/*
'name' must be a relative path
*/
std::string Pattern::ReadFile(const char * name)
{
// for security reason we can't open a file which has two dots
// somewhere in its name '..'
if( !CheckFileName(name) )
return CreateMsg("incorrect file name:", name);
std::string file_name(directory);
if( !file_name.empty() )
file_name += '/';
file_name += name;
std::ifstream file(file_name.c_str());
if( !file )
return CreateMsg("can't open:", name);
// or we can give the whole path here (file_name)
else
{
std::string result;
std::getline(file, result, '\0');
return result;
}
}
int Pattern::ReadCharInText()
{
if( *itext==0 || *itext=='[' )
return -1;
if( *itext == '\\' )
{
if( *(itext+1)=='\\' || *(itext+1)=='[' || *(itext+1)==']' )
++itext;
}
return *(itext++);
}
void Pattern::SkipWhiteCharacters()
{
while( *itext==' ' || *itext=='\t' )
++itext;
}
std::string Pattern::ReadDirective()
{
std::string directive;
SkipWhiteCharacters();
while( (*itext>='a' && *itext<='z') ||
(*itext>='A' && *itext<='Z') ||
(*itext>='0' && *itext<='9') ||
*itext=='_' || *itext=='-' || *itext=='.' || *itext=='#' )
{
directive += *itext;
++itext;
}
return directive;
}
std::string Pattern::ReadString()
{
std::string directive;
SkipWhiteCharacters();
if( *itext != '\"' )
return directive;
// string is signed by its first character equal (")
directive += '\"';
for( ++itext ; *itext && *itext!='\"' && *itext!='\n' ; ++itext )
directive += *itext;
if( *itext != '\"' )
// the second quotation mark (") is missing
directive.clear();
else
++itext;
// the second quotation mark (") we don't add into the 'directive'
return directive;
}
std::string Pattern::ReadDirectiveOrString()
{
SkipWhiteCharacters();
if( *itext == '\"' )
{
// we've got string
return ReadString();
}
else
{
return ReadDirective();
}
}
void Pattern::CreateTreeReadItemDirectiveCheckEnding(Item & item)
{
SkipWhiteCharacters();
if( *itext != ']' )
{
item.type = Item::item_err;
while( *itext!=0 && *itext!=']' )
++itext;
}
if( *itext == ']' )
++itext;
}
void Pattern::ReadDirectiveIfany(Item & item)
{
item.type = Item::item_ifany;
while( true )
{
std::string directive = ReadDirective();
if( directive.empty() )
break;
item.directives.push_back(directive);
}
if( item.directives.empty() )
item.type = Item::item_err;
}
void Pattern::ReadDirectiveIfone(Item & item)
{
ReadDirectiveIfany(item);
if( item.type == Item::item_ifany )
item.type = Item::item_ifone;
}
void Pattern::ReadDirectiveIs(Item & item)
{
item.type = Item::item_is;
std::string directive = ReadDirective();
if( !directive.empty() )
{
item.directives.push_back(directive);
directive = ReadDirectiveOrString();
if( !directive.empty() )
item.directives.push_back(directive);
}
if( item.directives.size() != 2 )
item.type = Item::item_err;
}
void Pattern::ReadDirectiveIfindex(Item & item)
{
item.type = Item::item_ifindex;
std::string directive = ReadDirective();
if( !directive.empty() )
{
item.directives.push_back(directive);
directive = ReadDirective();
if( !directive.empty() )
item.directives.push_back(directive);
}
if( item.directives.size() != 2 )
item.type = Item::item_err;
}
void Pattern::ReadDirectiveFor(Item & item)
{
item.type = Item::item_for;
std::string directive = ReadDirective();
if( !directive.empty() )
item.directives.push_back(directive);
else
item.type = Item::item_err;
}
void Pattern::ReadDirectiveComment(Item & item)
{
item.type = Item::item_comment;
while( *itext && *itext!=']' && *itext!='\n' )
++itext;
}
void Pattern::ReadDirectiveInclude(Item & item)
{
item.type = Item::item_include;
std::string directive = ReadString();
if( !directive.empty() )
item.directives.push_back(directive);
else
item.type = Item::item_err;
}
void Pattern::CreateTreeReadItemDirective(Item & item)
{
++itext;
std::string directive = ReadDirective();
if( directive == "if-any" )
ReadDirectiveIfany(item);
else
if( directive == "if-one" )
ReadDirectiveIfone(item);
else
if( directive == "is" )
ReadDirectiveIs(item);
else
if( directive == "if-index" )
ReadDirectiveIfindex(item);
else
if( directive == "end" )
item.type = Item::item_end;
else
if( directive == "else" )
item.type = Item::item_else;
else
if( directive == "for" )
ReadDirectiveFor(item);
else
if( directive == "include" )
ReadDirectiveInclude(item);
else
if( directive == "#" )
ReadDirectiveComment(item);
else
{
// user defined
item.directives.push_back(directive);
item.type = Item::item_normal;
}
CreateTreeReadItemDirectiveCheckEnding(item);
}
void Pattern::CreateTreeReadItemText(Item & item)
{
int c;
while( (c = ReadCharInText()) != -1 )
item.text += c;
item.type = Item::item_text;
}
bool Pattern::CreateTreeReadItem(Item & item)
{
item.Clear();
if( *itext == '[' )
{
CreateTreeReadItemDirective(item);
return true;
}
else
if( *itext )
{
CreateTreeReadItemText(item);
return true;
}
// the end of the string
return false;
}
void Pattern::CreateTreeReadInclude(Item & item)
{
if( item.directives.empty() || item.directives[0].empty() || item.directives[0][0]!='\"' )
return;
std::string file_text = ReadFile( item.directives[0].c_str()+1 );
const char * itext_copy = itext;
itext = file_text.c_str();
CreateTree(item);
itext = itext_copy;
}
void Pattern::CreateTreeReadIf(Item & item)
{
Item * pitem = item.AddItem();
CreateTree(*pitem);
if( pitem->LastItemType() == Item::item_else )
{
pitem->DeleteLastItem();
pitem = item.AddItem();
CreateTree(*pitem);
}
pitem->DeleteLastItem(); // it deletes [end] from the tree
}
void Pattern::CreateTreeReadFor(Item & item)
{
Item * pitem = item.AddItem();
CreateTree(*pitem);
pitem->DeleteLastItem(); // it deletes [end] from the tree
}
void Pattern::CreateTree(Item & item)
{
item.Clear();
item.type = Item::item_container;
Item item_temp;
while( CreateTreeReadItem(item_temp) )
{
if( item_temp.type == Item::item_comment )
continue;
Item * pitem = item.AddItem(item_temp);
if( item_temp.type==Item::item_end || item_temp.type==Item::item_else )
return;
if( pitem->type == Item::item_ifany ||
pitem->type == Item::item_ifone ||
pitem->type == Item::item_ifindex ||
pitem->type == Item::item_is )
CreateTreeReadIf(*pitem);
if( pitem->type == Item::item_for )
CreateTreeReadFor(*pitem);
if( pitem->type == Item::item_include )
CreateTreeReadInclude(*pitem);
}
}
/*
*
* Pattern::Item
*
*
*/
Pattern::Item * Pattern::Item::AddItem(const Pattern::Item * porg)
{
Item * pitem;
if( porg )
pitem = new Item(*porg);
else
pitem = new Item();
item_table.push_back(pitem);
return pitem;
}
Pattern::Item * Pattern::Item::AddItem(const Pattern::Item & porg)
{
return AddItem(&porg);
}
void Pattern::Item::ClearItems()
{
std::vector<Item*>::iterator i = item_table.begin();
for( ; i != item_table.end() ; ++i )
delete *i;
item_table.clear();
}
void Pattern::Item::Clear()
{
ClearItems();
type = item_none;
text.clear();
directives.clear();
}
Pattern::Item::ItemType Pattern::Item::LastItemType()
{
if( item_table.empty() )
return item_none;
return item_table.back()->type;
}
void Pattern::Item::DeleteLastItem()
{
if( item_table.empty() )
return;
delete item_table.back();
item_table.erase( item_table.end() - 1 );
}
Pattern::Item::Item()
{
type = item_none;
}
Pattern::Item::Item(const Pattern::Item & i) : type(i.type), text(i.text), directives(i.directives)
{
CopyItemTable(i);
}
Pattern::Item & Pattern::Item::operator=(const Pattern::Item & i)
{
type = i.type;
text = i.text;
directives = i.directives;
CopyItemTable(i);
return *this;
}
void Pattern::Item::CopyItemTable(const Pattern::Item & item)
{
std::vector<Item*>::const_iterator i = item.item_table.begin();
for( ; i != item.item_table.end() ; ++i)
AddItem( *i );
}
Pattern::Item::~Item()
{
ClearItems();
}
/*
*
* Info
*
*
*/
Info::Info()
{
result = false;
iter = 0;
}
/*
*
* Generator
*
*
*/
std::string & Generator::Generate(Pattern & data)
{
otext.clear();
MakeText( data.item_root );
return otext;
}
std::string & Generator::String()
{
return otext;
}
void Generator::Insert(const std::string & key, UserFunction ufunction)
{
UserInfo ui;
ui.user_function = ufunction;
ui.iter = 0;
user_info_table.insert( std::make_pair(key, ui) );
}
void Generator::MakeTextContainer(Pattern::Item & item)
{
std::vector<Pattern::Item*>::iterator i = item.item_table.begin();
for( ; i != item.item_table.end() ; ++i )
MakeText(**i);
}
bool Generator::Find(const std::string & key, UserInfo ** user_info)
{
UserInfoTable::iterator i = user_info_table.find( key );
if( i == user_info_table.end() )
{
otext += CreateMsg("can't find", key.c_str() );
return false;
}
*user_info = &(i->second);
return true;
}
void Generator::MakeTextNormal(Pattern::Item & item)
{
if( item.directives.size() != 1 )
return;
UserInfo * user_info;
if( Find(item.directives[0], &user_info) )
{
Info info;
(user_info->user_function)(info);
otext += info.text;
}
}
void Generator::MakeTextIf_go(Pattern::Item & item, bool result)
{
if( result )
{
if( item.item_table.size() > 0 )
MakeText( *item.item_table[0] );
}
else
{
// second element can be (or not -- it's from [else])
if( item.item_table.size() > 1 )
MakeText( *item.item_table[1] );
}
}
void Generator::MakeTextIfany(Pattern::Item & item)
{
std::vector<std::string>::iterator d = item.directives.begin();
unsigned how_many_true = 0;
for( ; d != item.directives.end() ; ++d )
{
UserInfo * user_info;
if( !Find(*d, &user_info) )
return;
Info info;
(user_info->user_function)(info);
if( !info.text.empty() || info.result )
++how_many_true;
}
MakeTextIf_go(item, how_many_true == item.directives.size() );
}
void Generator::MakeTextIfone(Pattern::Item & item)
{
std::vector<std::string>::iterator d = item.directives.begin();
int how_many_true = 0;
for( ; d != item.directives.end() ; ++d )
{
UserInfo * user_info;
if( !Find(*d, &user_info) )
return;
Info info;
(user_info->user_function)(info);
if( !info.text.empty() || info.result )
++how_many_true;
}
MakeTextIf_go(item, how_many_true > 0 );
}
void Generator::MakeTextIs(Pattern::Item & item)
{
if( item.directives.size() != 2 )
return;
UserInfo * user_info;
if( !Find(item.directives[0], &user_info) )
return;
bool result = false;
Info info1, info2;
(user_info->user_function)(info1);
if( !item.directives[1].empty() && item.directives[1][0]=='\"' )
{
if( std::strcmp(info1.text.c_str(), item.directives[1].c_str()+1) == 0 )
result = true;
}
else
{
if( Find(item.directives[1], &user_info) )
{
(user_info->user_function)(info2);
if( info1.result==info2.result && info1.text==info2.text )
result = true;
}
}
MakeTextIf_go(item, result);
}
bool Generator::MakeTextIfindexnumber(Pattern::Item & item, UserInfo * user_info, bool & result)
{
if( item.directives.size() != 2 )
return false;
const char * number_text = item.directives[1].c_str();
char * last_char;
int number = (int)strtol(number_text, &last_char, 10);
if( *last_char == '\0' )
{
if( user_info->iter == number )
result = true;
}
else
{
otext += CreateMsg("if-index: syntax error");
return false;
}
return true;
}
void Generator::MakeTextIfindex(Pattern::Item & item)
{
if( item.directives.size() != 2 )
return;
UserInfo * user_info;
bool result = false;
if( !Find(item.directives[0], &user_info) )
return;
if( item.directives[1] == "odd" )
{
if( ( user_info->iter & 1) == 1 )
result = true;
}
else
if( item.directives[1] == "even" )
{
if( ( user_info->iter & 1) == 0 )
result = true;
}
else
if( item.directives[1] == "first" )
{
if( user_info->iter == 0 )
result = true;
}
else
{
if( !MakeTextIfindexnumber(item, user_info, result) )
return;
}
MakeTextIf_go(item, result);
}
void Generator::MakeTextFor(Pattern::Item & item)
{
if( item.directives.size() != 1 )
return;
UserInfo * user_info;
if( !Find(item.directives[0], &user_info) )
return;
Info info;
user_info->iter = 0;
while( true )
{
(user_info->user_function)(info);
if( info.text.empty() && !info.result )
break;
if( item.item_table.size() > 0 )
MakeText( *item.item_table[0] );
++info.iter;
user_info->iter = info.iter;
}
}
void Generator::MakeText(Pattern::Item & item)
{
switch( item.type )
{
case Pattern::Item::item_text:
otext += item.text;
break;
case Pattern::Item::item_container:
MakeTextContainer(item);
break;
case Pattern::Item::item_normal:
MakeTextNormal(item);
break;
case Pattern::Item::item_ifany:
MakeTextIfany(item);
break;
case Pattern::Item::item_ifone:
MakeTextIfone(item);
break;
case Pattern::Item::item_ifindex:
MakeTextIfindex(item);
break;
case Pattern::Item::item_is:
MakeTextIs(item);
break;
case Pattern::Item::item_for:
MakeTextFor(item);
break;
case Pattern::Item::item_err:
otext += CreateMsg("a wrong directive");
break;
default:
break;
}
}
void Generator::Clear()
{
user_info_table.clear();
otext.clear();
}
} // namespace Ezc

161
src/ezc.h
View File

@@ -1,11 +1,11 @@
/* /*
* This file is a part of EZC -- Easy templating in C++ * This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@ttmath.org>
*/ */
/* /*
* Copyright (c) 2007, Tomasz Sowa * Copyright (c) 2007-2010, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -35,160 +35,13 @@
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* version 0.9.0 #ifndef headerfile_ezc_ezc
* #define headerfile_ezc_ezc
*/
#ifndef headerfileezc #include "utf8.h"
#define headerfileezc #include "generator.h"
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
#include <cstdlib>
#include <cstring>
namespace Ezc
{
std::string CreateMsg(const char * type, const char * arg = 0);
void SplitUnixDirectory(const char * name, std::string & dir, std::string & file);
void SplitUnixDirectory(const std::string & name, std::string & dir, std::string & file);
class Pattern
{
public:
void ParseFile(const std::string & file_name);
void ParseFile(const char * file_name);
void Directory(const char * d);
void Directory(const std::string & d);
struct Item
{
enum ItemType
{
item_none, item_container, item_text, item_ifany, item_for,
item_else, item_end, item_err, item_normal, item_ifindex,
item_include, item_is, item_ifone, item_comment
};
ItemType type;
std::string text;
std::vector<Item*> item_table;
std::vector<std::string> directives;
Item();
Item(const Item & i);
Item & operator=(const Item & i);
void CopyItemTable(const Item & i);
~Item();
Item * AddItem(const Item * porg = 0);
Item * AddItem(const Item & porg);
void ClearItems();
ItemType LastItemType();
void DeleteLastItem();
void Clear();
};
Item item_root;
private:
const char * itext;
std::string directory;
bool CheckFileName(const char * name);
std::string ReadFile(const char * name);
int ReadCharInText();
void SkipWhiteCharacters();
std::string ReadDirective();
std::string ReadString();
std::string ReadDirectiveOrString();
void CreateTreeReadItemDirectiveCheckEnding(Item & item);
void ReadDirectiveIfany(Item & item);
void ReadDirectiveIfone(Item & item);
void ReadDirectiveIs(Item & item);
void ReadDirectiveIfindex(Item & item);
void ReadDirectiveFor(Item & item);
void ReadDirectiveComment(Item & item);
void ReadDirectiveInclude(Item & item);
void CreateTreeReadItemDirective(Item & item);
void CreateTreeReadItemText(Item & item);
bool CreateTreeReadItem(Item & item);
void CreateTreeReadIf(Item & item);
void CreateTreeReadFor(Item & item);
void CreateTree(Item & item);
void CreateTreeReadInclude(Item & item);
}; // Pattern
struct Info
{
std::string text;
bool result;
int iter;
Info();
};
class Generator
{
private:
typedef void (*UserFunction)(Info &);
struct UserInfo
{
UserFunction user_function;
int iter;
};
typedef std::map<std::string, UserInfo> UserInfoTable;
public:
void Insert(const std::string & key, UserFunction ufunction);
std::string & Generate(Pattern & data);
std::string & String();
void Clear();
private:
UserInfoTable user_info_table;
std::string otext;
bool Find(const std::string & key, UserInfo ** user_info);
void MakeTextIf_go(Pattern::Item & item, bool result);
bool MakeTextIfindexnumber(Pattern::Item & item, UserInfo * user_info, bool & result);
void MakeTextIfany(Pattern::Item & item);
void MakeTextIfone(Pattern::Item & item);
void MakeTextIfindex(Pattern::Item & item);
void MakeTextFor(Pattern::Item & item);
void MakeTextContainer(Pattern::Item & item);
void MakeTextNormal(Pattern::Item & item);
void MakeTextIs(Pattern::Item & item);
void MakeText(Pattern::Item & item);
}; // Generator
} // namespace Ezc
#endif #endif

265
src/functions.h Executable file
View File

@@ -0,0 +1,265 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2012, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef headerfile_ezc_functions
#define headerfile_ezc_functions
#include <map>
#include "funinfo.h"
#include "stringconv.h"
namespace Ezc
{
// functions or variables
template<class StreamType>
class Functions
{
public:
typedef void (*UserFunction)(FunInfo<StreamType> &);
enum Type { function, variable };
struct Function
{
Function();
Type type;
UserFunction user_function; // used when type is 'function'
std::wstring variable; // used when type is 'variable'
};
typedef std::map<std::wstring, Function> FunctionsTable;
typedef typename FunctionsTable::iterator Iterator;
void Insert(const char * key, UserFunction ufunction); // inserting a function
void Insert(const char * key, const char * var); // inserting a variable
void Insert(const char * key, const std::string & var); // inserting a variable
void Insert(const std::string & key, UserFunction ufunction); // inserting a function
void Insert(const std::string & key, const char * var); // inserting a variable
void Insert(const std::string & key, const std::string & var); // inserting a variable
void Insert(const std::wstring & key, UserFunction ufunction);
void Insert(const std::wstring & key, const wchar_t * var);
void Insert(const std::wstring & key, const std::wstring & var);
bool Find(const std::string & key, Function ** fun);
bool Find(const std::wstring & key, Function ** fun);
Iterator Begin();
Iterator End();
size_t Size() const;
void Clear();
private:
FunctionsTable functions_tab;
std::wstring temp_key;
};
template<class StreamType>
Functions<StreamType>::Function::Function()
{
type = Functions::variable;
user_function = 0;
}
template<class StreamType>
void Functions<StreamType>::Insert(const char * key, UserFunction ufunction)
{
Function f;
f.type = function;
f.user_function = ufunction;
AssignString(key, temp_key);
functions_tab[temp_key] = f;
}
template<class StreamType>
void Functions<StreamType>::Insert(const char * key, const char * var)
{
Function f;
f.type = variable;
AssignString(var, f.variable);
AssignString(key, temp_key);
functions_tab[temp_key] = f;
}
template<class StreamType>
void Functions<StreamType>::Insert(const char * key, const std::string & var)
{
Function f;
f.type = variable;
AssignString(var, f.variable);
AssignString(key, temp_key);
functions_tab[temp_key] = f;
}
template<class StreamType>
void Functions<StreamType>::Insert(const std::string & key, UserFunction ufunction)
{
Insert(key.c_str(), ufunction);
}
template<class StreamType>
void Functions<StreamType>::Insert(const std::string & key, const char * var)
{
Insert(key.c_str(), var);
}
template<class StreamType>
void Functions<StreamType>::Insert(const std::string & key, const std::string & var)
{
Insert(key.c_str(), var);
}
template<class StreamType>
void Functions<StreamType>::Insert(const std::wstring & key, UserFunction ufunction)
{
Function f;
f.type = function;
f.user_function = ufunction;
functions_tab[key] = f;
}
template<class StreamType>
void Functions<StreamType>::Insert(const std::wstring & key, const wchar_t * var)
{
Function f;
f.type = variable;
f.variable = var;
functions_tab[key] = f;
}
template<class StreamType>
void Functions<StreamType>::Insert(const std::wstring & key, const std::wstring & var)
{
Function f;
f.type = variable;
f.variable = var;
functions_tab[key] = f;
}
template<class StreamType>
bool Functions<StreamType>::Find(const std::string & key, Function ** fun)
{
AssignString(key, temp_key);
return Find(temp_key, fun);
}
template<class StreamType>
bool Functions<StreamType>::Find(const std::wstring & key, Function ** fun)
{
typename FunctionsTable::iterator i = functions_tab.find( key );
if( i == functions_tab.end() )
return false;
*fun = &(i->second);
return true;
}
template<class StreamType>
void Functions<StreamType>::Clear()
{
functions_tab.clear();
}
template<class StreamType>
typename Functions<StreamType>::Iterator Functions<StreamType>::Begin()
{
return functions_tab.begin();
}
template<class StreamType>
typename Functions<StreamType>::Iterator Functions<StreamType>::End()
{
return functions_tab.end();
}
template<class StreamType>
size_t Functions<StreamType>::Size() const
{
return functions_tab.size();
}
} // namespace Ezc
#endif

107
src/funinfo.h Executable file
View File

@@ -0,0 +1,107 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef headerfile_ezc_funinfo
#define headerfile_ezc_funinfo
#include <vector>
namespace Ezc
{
template<class StreamType>
struct FunInfo
{
// output stream
StreamType & out;
// the out stream is treated in case sensitive
// used only in [is...] statements
// default: true
bool case_sensitive;
// table of parameters
// the table can be empty
std::vector<std::wstring> & params;
// the first parameter
// you can always use it even if there is not any parameters (params is empty)
// in such a way the reference points to an empty string
const std::wstring & par;
// an input stream used in [filter] statement
// if there is other statement than [filter] then this is an empty stream
const StreamType & in;
// this is set by Generator
// it indicates the number of a current iteration in the last [for] statement (the first is 0)
// if there was not any [for] before the value is zero
int iter;
// return value from a user function (default false if not set directly by the user function)
// for a variable it is set to true if the variable is not empty
bool res;
// arguments: output_stream, table_of_parameters, the_first_parameter
FunInfo(StreamType & o,
std::vector<std::wstring> & pars,
const std::wstring & first_par,
const StreamType & i) : out(o), params(pars), par(first_par), in(i)
{
Clear();
}
void Clear()
{
res = false; // false by default
iter = 0;
case_sensitive = true;
}
};
} // namespace Ezc
#endif

1195
src/generator.h Executable file

File diff suppressed because it is too large Load Diff

165
src/item.cpp Executable file
View File

@@ -0,0 +1,165 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#include "item.h"
namespace Ezc
{
Item * Item::AddItem(const Item * porg)
{
Item * pitem;
if( porg )
pitem = new Item(*porg);
else
pitem = new Item();
item_tab.push_back(pitem);
return pitem;
}
Item * Item::AddItem(const Item & porg)
{
return AddItem(&porg);
}
void Item::ClearItems()
{
std::vector<Item*>::iterator i = item_tab.begin();
for( ; i != item_tab.end() ; ++i )
delete *i;
item_tab.clear();
}
void Item::Clear()
{
ClearItems();
type = item_none;
text.clear();
file_name.clear();
functions.clear();
}
Item::Type Item::LastItemType()
{
if( item_tab.empty() )
return item_none;
return item_tab.back()->type;
}
void Item::DeleteLastItem()
{
if( item_tab.empty() )
return;
delete item_tab.back();
item_tab.pop_back();
}
Item::Item()
{
type = item_none;
}
Item::Item(const Item & i) : type(i.type), text(i.text), file_name(i.file_name), functions(i.functions)
{
CopyItemTable(i);
}
Item & Item::operator=(const Item & i)
{
type = i.type;
text = i.text;
file_name = i.file_name;
functions = i.functions;
ClearItems();
CopyItemTable(i);
return *this;
}
void Item::CopyItemTable(const Item & item)
{
std::vector<Item*>::const_iterator i = item.item_tab.begin();
for( ; i != item.item_tab.end() ; ++i)
AddItem(*i);
}
Item::~Item()
{
ClearItems();
}
} // namespace Ezc

98
src/item.h Executable file
View File

@@ -0,0 +1,98 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef headerfile_ezc_item
#define headerfile_ezc_item
#include <vector>
#include <string>
#include "funinfo.h"
namespace Ezc
{
struct Item
{
enum Type
{
item_none, item_container, item_text, item_normal, item_is, item_isno,
item_if, item_ifno, item_ifany, item_ifone, item_ifanyno, item_ifoneno, item_ifindex,
item_for, item_else, item_end, item_err, item_include, item_comment, item_def, item_filter
};
struct Function
{
std::wstring name; // function name
std::vector<std::wstring> params; // function parameters
void * fun_cache;
Function()
{
fun_cache = 0;
}
};
Type type;
std::wstring text; // used in: item_text
std::wstring file_name; // used in: item_include (as a file name)
std::vector<Item*> item_tab; // childs
std::vector<Function> functions;
Item();
Item(const Item & i);
Item & operator=(const Item & i);
void CopyItemTable(const Item & i);
~Item();
Item * AddItem(const Item * porg = 0);
Item * AddItem(const Item & porg);
void ClearItems();
Type LastItemType();
void DeleteLastItem();
void Clear();
};
} // namespace Ezc
#endif

1041
src/pattern.cpp Executable file

File diff suppressed because it is too large Load Diff

261
src/pattern.h Executable file
View File

@@ -0,0 +1,261 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef headerfile_ezc_pattern
#define headerfile_ezc_pattern
#include <string>
#include "item.h"
#include "functions.h"
#include "stringconv.h"
#include "utf8.h"
#ifdef EZC_USE_WINIX_LOGGER
#include "core/log.h"
#endif
namespace Ezc
{
class Pattern
{
public:
Pattern();
/*!
clearing only the tree
*/
void Clear();
// first we're trying to read a file from directory dir
// if there is no such a file there then we try read from dir2
// (the second dir2 can be empty - it will not be used)
void Directory(const char * dir, const char * dir2 = 0);
void Directory(const std::string & dir);
void Directory(const std::string & dir, const std::string & dir2);
void Directory(const wchar_t * dir, const wchar_t * dir2 = 0);
void Directory(const std::wstring & dir);
void Directory(const std::wstring & dir, const std::wstring & dir2);
void ParseFile(const char * file_name);
void ParseFile(const std::string & file_name);
void ParseFile(const wchar_t * file_name);
void ParseFile(const std::wstring & file_name);
void ParseString(const char * str);
void ParseString(const std::string & str);
void ParseString(const wchar_t * str);
void ParseString(const std::wstring & str);
void AllowInclude(bool allow);
void DeleteWhiteTextItems(bool del);
void SetIncludeMax(int include_max);
// files and strings (only char* and std::string) are treated
// as UTF-8
void UTF8(bool utf8);
void SetCommentary(const char * com_start, const char * com_stop);
void SetCommentary(const std::string & com_start, const std::string & com_stop);
void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop);
void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop);
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
static bool IsWhite(wchar_t c);
Item item_root;
template<class StreamType>
void CacheFunctions(Functions<StreamType> & fun)
{
CacheFunctions(item_root, fun);
}
void ClearCache();
private:
// the main pointer to the parsed text
const wchar_t * itext;
// allowing include tag
// default: true
bool allow_include;
// if true all text-items which have only white characters (with new lines as well)
// will be deleted - useful in *.txt templates
// this not actually delete the whole item but only the string
// the item will be present with an empty string
// default: false
bool delete_white_text_items;
// first we're trying to read a file from 'directory'
// if there is no such a file there then we try read from 'directory2'
// we read from these directories only if they are not empty
std::wstring directory, directory2;
bool input_as_utf8;
int include_level, include_level_max;
std::wstring commentary_start, commentary_stop;
// temporary content for ParseString(const char*) method
std::wstring string_content;
// temporary object for a file name
std::wstring file_name;
// temporary object for a file name
std::string afile_name;
// temporary object for a EZC function's parameter
std::wstring temp_param;
// temporary object for a EZC function
Item::Function temp_function;
void ReadFile(const std::wstring & name, std::wstring & result);
void ReadFile(const wchar_t * name, std::wstring & result);
bool HasFileAtBeginning(const wchar_t * path, const wchar_t * file);
bool IsFileCorrect(const wchar_t * name);
bool ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result);
void ReadFile(std::ifstream & file, std::wstring & result);
void ReadFileContent(std::ifstream & file, std::wstring & result);
int ReadCharInText();
void SkipWhite();
void CheckWhiteAndDelete(std::wstring & s);
bool IsNameChar(wchar_t c);
bool IsDigit(wchar_t c);
bool IsPositiveNumber(const std::wstring & str);
bool ReadName(std::wstring & name);
bool ReadString(std::wstring & str);
bool ReadParams(Item::Function & function);
bool ReadFunction(Item::Function & function);
bool ReadFunctions(Item & item);
void ReadDirectiveIf(Item & item);
void ReadDirectiveIfno(Item & item);
void ReadDirectiveIfany(Item & item);
void ReadDirectiveIfone(Item & item);
void ReadDirectiveIfanyno(Item & item);
void ReadDirectiveIfoneno(Item & item);
void ReadDirectiveIs(Item & item);
void ReadDirectiveIsno(Item & item);
void ReadDirectiveIfindex(Item & item);
void ReadDirectiveFor(Item & item);
void ReadDirectiveComment(Item & item);
void ReadDirectiveInclude(Item & item);
void ReadDirectiveDef(Item & item);
void ReadDirectiveFilter(Item & item);
void ReadDirectiveNormal(const std::wstring & name, Item & item);
void CreateTreeReadItemDirectiveCheckEnding(Item & item);
void CreateTreeReadItemDirective(Item & item);
void CreateTreeReadItemText(Item & item);
bool CreateTreeReadItem(Item & item);
void CreateTreeReadIf(Item & item);
void CreateTreeReadFor(Item & item);
void CreateTree(Item & item);
void CreateTreeReadInclude(Item & item);
void CreateTreeReadIncludeSkipAllowFlag(Item & item);
template<class StreamType>
void CacheFunctions(Item & item, Functions<StreamType> & fun)
{
typename Functions<StreamType>::Function * ezc_fun;
// one exception (if_index is putting its argument on the functions stack)
if( item.type != Item::item_ifindex )
{
for(size_t f=0; f < item.functions.size() ; ++f)
{
if( fun.Find(item.functions[f].name, &ezc_fun) )
{
item.functions[f].fun_cache = ezc_fun;
}
else
{
item.functions[f].fun_cache = 0;
#ifdef EZC_USE_WINIX_LOGGER
log << log1 << "Ezc: unknown function: " << item.functions[f].name << logend;
#endif
}
}
}
for(size_t i=0; i < item.item_tab.size() ; ++i)
CacheFunctions(*item.item_tab[i], fun);
}
void ClearCache(Item & item);
}; // class Pattern
} // namespace Ezc
#endif

108
src/stringconv.cpp Executable file
View File

@@ -0,0 +1,108 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#include "stringconv.h"
namespace Ezc
{
void AssignString(const char * src, std::wstring & dst, bool clear)
{
size_t len;
if( clear )
dst.clear();
for(len=0 ; src[len] ; ++len){}
if( dst.capacity() < dst.size() + len )
dst.reserve(dst.size() + len + 128);
for( ; *src ; ++src )
dst += static_cast<unsigned char>(*src);
}
void AssignString(const std::string & src, std::wstring & dst, bool clear)
{
if( clear )
dst.clear();
if( dst.capacity() < dst.size() + src.size() )
dst.reserve(dst.size() + src.size() + 128);
for(size_t i=0 ; i<src.size() ; ++i )
dst += static_cast<unsigned char>(src[i]);
}
void AssignString(const wchar_t * src, std::string & dst, bool clear)
{
size_t len;
if( clear )
dst.clear();
for(len=0 ; src[len] ; ++len){}
if( dst.capacity() < dst.size() + len )
dst.reserve(dst.size() + len + 128);
for( ; *src ; ++src )
dst += static_cast<char>(*src);
}
void AssignString(const std::wstring & src, std::string & dst, bool clear)
{
if( clear )
dst.clear();
if( dst.capacity() < dst.size() + src.size() )
dst.reserve(dst.size() + src.size() + 128);
for(size_t i=0 ; i<src.size() ; ++i )
dst += static_cast<char>(src[i]);
}
} // namespace Ezc

60
src/stringconv.h Executable file
View File

@@ -0,0 +1,60 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2007-2010, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef headerfile_ezc_stringconv
#define headerfile_ezc_stringconv
#include <string>
namespace Ezc
{
void AssignString(const char * src, std::wstring & dst, bool clear = true);
void AssignString(const std::string & src, std::wstring & dst, bool clear = true);
void AssignString(const wchar_t * src, std::string & dst, bool clear = true);
void AssignString(const std::wstring & src, std::string & dst, bool clear = true);
} // namespace Ezc
#endif

896
src/utf8.cpp Executable file
View File

@@ -0,0 +1,896 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2010-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#include "utf8.h"
namespace Ezc
{
/*!
an auxiliary function for converting from UTF-8 string
*/
static bool UTF8ToInt_FirstOctet(unsigned char uz, size_t & len, int & res)
{
for(len=0 ; (uz & 0x80) != 0 ; ++len)
uz <<= 1;
if( len == 1 )
return false;
res = uz;
if( len > 0 )
res >>= len;
if( res == 0 )
return false;
if( len == 0 )
len = 1;
return true;
}
/*!
an auxiliary function for converting from UTF-8 string
*/
static bool UTF8ToInt_AddNextOctet(unsigned char uz, int & res)
{
if( (uz & 0xc0) != 0x80 )
return false;
res <<= 6;
res |= (uz & 0x3F);
return true;
}
/*!
returns true if 'c' is a correct unicode character
*/
bool UTF8_CheckRange(int c)
{
return c>=0 && c<=0x10FFFF && !(c>=0xD800 && c<=0xDFFF);
}
/*!
this function converts one UTF-8 character into one wide-character
input:
utf8 - an input UTF-8 string
utf8_len - size of the input string,
the string should be at least 4 bytes length for correctly
recognized the utf-8 sequence
output:
res - an output character
correct - true if it is a correct character
the function returns how many characters have been used from the input string
(returns zero only if utf8_len is zero)
even if there are errors the functions returns a different from zero value
*/
size_t UTF8ToInt(const char * utf8, size_t utf8_len, int & res, bool & correct)
{
size_t i, len;
res = 0;
correct = false;
if( utf8_len == 0 )
return 0;
if( !UTF8ToInt_FirstOctet(utf8[0], len, res) )
return 1;
if( utf8_len < len )
return utf8_len;
for(i=1 ; i<len ; ++i)
if( !UTF8ToInt_AddNextOctet(utf8[i], res) )
return i;
if( UTF8_CheckRange(res) )
correct = true;
return len;
}
/*!
this function converts one UTF-8 character into one wide-character
input:
utf8 - an input UTF-8 string (null terminated)
output:
res - an output character
correct - true if it is a correct character
the function returns how many characters have been used from the input string
(returns zero only if the string has '\0' at the first character)
even if there are errors the functions returns a different from zero value
*/
size_t UTF8ToInt(const char * utf8, int & res, bool & correct)
{
size_t i, len;
res = 0;
correct = false;
if( *utf8 == 0 )
return 0;
if( !UTF8ToInt_FirstOctet(utf8[0], len, res) )
return 1;
for(i=1 ; i<len ; ++i)
{
if( utf8[i] == 0 )
return i;
if( !UTF8ToInt_AddNextOctet(utf8[i], res) )
return i;
}
if( UTF8_CheckRange(res) )
correct = true;
return len;
}
/*!
this function converts one UTF-8 character into one wide-character
input:
utf8 - an input UTF-8 string
output:
res - an output character
correct - true if it is a correct character
the function returns how many characters have been used from the input string
(returns zero only if utf8 is empty)
even if there are errors the functions returns a different from zero value
*/
size_t UTF8ToInt(const std::string & utf8, int & res, bool & correct)
{
return UTF8ToInt(utf8.c_str(), utf8.size(), res, correct);
}
/*!
this function converts one UTF-8 character into one wide-character
input:
utf8 - an input UTF-8 stream
output:
res - an output character
correct - true if it is a correct character
the function returns how many characters have been used from the input stream
*/
size_t UTF8ToInt(std::istream & utf8, int & res, bool & correct)
{
size_t i, len;
unsigned char uz;
res = 0;
correct = false;
uz = utf8.get();
if( !utf8 )
return 0;
if( !UTF8ToInt_FirstOctet(uz, len, res) )
return 1;
for(i=1 ; i<len ; ++i)
{
uz = utf8.get();
if( !utf8 )
return i;
if( !UTF8ToInt_AddNextOctet(uz, res) )
return i;
}
if( UTF8_CheckRange(res) )
correct = true;
return len;
}
/*
*/
static void IntToWide(int c, std::wstring & res)
{
if( sizeof(wchar_t)==2 && c>0xffff )
{
c -= 0x10000;
res += static_cast<wchar_t>(((c >> 10) & 0x3FF) + 0xD800);
res += static_cast<wchar_t>((c & 0x3FF) + 0xDC00);
}
else
{
res += static_cast<wchar_t>(c);
}
}
/*!
this function converts an utf8 string into wide string (std::wstring)
input:
utf8 - an input utf8 string
utf8_len - size of the input string
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
res - an output wide string
the function returns false if there were some errors when converting
*/
bool UTF8ToWide(const char * utf8, size_t utf8_len, std::wstring & res, bool clear, int mode)
{
int z;
size_t len;
bool correct, was_error = false;
if( clear )
res.clear();
while( utf8_len > 0 )
{
if( (unsigned char)*utf8 <= 0x7f )
{
// small optimization
len = 1;
correct = true;
z = static_cast<unsigned char>(*utf8);
}
else
{
len = UTF8ToInt(utf8, utf8_len, z, correct); // the len will be different from zero
}
if( !correct )
{
if( mode == 1 )
res += 0xFFFD; // U+FFFD "replacement character"
was_error = true;
}
else
{
IntToWide(z, res);
}
utf8 += len;
utf8_len -= len;
}
return !was_error;
}
/*!
this function converts an utf8 string into wide string (std::wstring)
input:
utf8 - an input utf8 null terminated string
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
res - an output wide string
the function returns false if there were some errors when converting
*/
bool UTF8ToWide(const char * utf8, std::wstring & res, bool clear, int mode)
{
size_t utf8_len = 0;
while( utf8[utf8_len] != 0 )
utf8_len += 1;
return UTF8ToWide(utf8, utf8_len, res, clear, mode);
}
/*!
this function converts an utf8 string into wide string (std::wstring)
input:
utf8 - an input utf8 string
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
res - an output wide string
the function returns false if there were some errors when converting
*/
bool UTF8ToWide(const std::string & utf8, std::wstring & res, bool clear, int mode)
{
return UTF8ToWide(utf8.c_str(), utf8.size(), res, clear, mode);
}
/*!
this function converts an utf8 stream into wide string (std::wstring)
input:
utf8 - an input utf8 stream
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
res - an output wide string
the function returns false if there were some errors when converting
*/
bool UTF8ToWide(std::istream & utf8, std::wstring & res, bool clear, int mode)
{
int z;
bool correct, was_error = false;
if( clear )
res.clear();
while( UTF8ToInt(utf8, z, correct) > 0 )
{
if( !correct )
{
if( mode == 1 )
res += 0xFFFD; // U+FFFD "replacement character"
was_error = true;
}
else
{
IntToWide(z, res);
}
}
return !was_error;
}
/*!
this function converts one wide character into UTF-8 sequence
input:
z - wide character
output:
utf8 - a buffer for the output sequence
utf8_len - the size of the buffer
the function returns how many characters have been written to the utf8,
zero means the utf8 buffer is too small or 'z' is an incorrect unicode character
*/
size_t IntToUTF8(int z, char * utf8, size_t utf8_max_len)
{
char buf[10];
int i = 0;
int mask = 0x3f; // 6 first bits set
if( utf8_max_len==0 || !UTF8_CheckRange(z) )
return 0;
if( z <= 0x7f )
{
utf8[0] = static_cast<char>(z);
return 1;
}
do
{
buf[i] = 0x80 | (z & 0x3f);
i += 1;
z >>= 6;
mask >>= 1;
}
while( (z & (~mask)) != 0 );
unsigned int first = -1;
first <<= (7 - i);
first |= (z & mask);
if( size_t(i+1) > utf8_max_len )
return 0;
utf8[0] = static_cast<char>(first);
int a = 1;
for(--i; i>=0 ; --i, ++a)
utf8[a] = buf[i];
return a;
}
/*!
this function converts one wide character into UTF-8 string
input:
z - wide character
output:
utf8 - a UTF-8 string for the output sequence (the string is not cleared)
the function returns how many characters have been written to the utf8 string,
zero means that 'z' is an incorrect unicode character
*/
size_t IntToUTF8(int z, std::string & utf8, bool clear)
{
char buf[10];
if( clear )
utf8.clear();
size_t len = IntToUTF8(z, buf, sizeof(buf)/sizeof(char));
size_t i;
for(i=0 ; i<len ; ++i)
utf8 += buf[i];
return len;
}
/*!
this function converts one wide character into UTF-8 stream
input:
z - wide character
output:
utf8 - a UTF-8 stream for the output sequence
the function returns how many characters have been written to the utf8 stream,
zero means that 'z' is an incorrect unicode character
*/
size_t IntToUTF8(int z, std::ostream & utf8)
{
char buf[10];
size_t len = IntToUTF8(z, buf, sizeof(buf)/sizeof(char));
size_t i;
for(i=0 ; i<len ; ++i)
utf8 << buf[i];
return len;
}
/*
an auxiliary function for converting from wide characters to UTF-8
converting a wide character into one int
returns how many wide characters were used
if string_len is greater than 0 then the return value is always greater than zero too
*/
static size_t WideToInt(const wchar_t * wide_string, size_t string_len, int & z, bool & correct)
{
if( string_len == 0 )
{
z = 0;
correct = false;
return 0;
}
z = static_cast<int>(*wide_string);
correct = true;
if( sizeof(wchar_t) == 2 && (z>=0xD800 && z<=0xDFFF) )
{
if( z>=0xD800 && z<=0xDBFF && string_len>1 )
{
int z2 = *(wide_string+1);
if( z2>=0xDC00 && z2<=0xDFFF )
{
z = 0x10000 + (((z & 0x3FF) << 10) | (z2 & 0x3FF));
return 2;
}
else
{
correct = false;
return 2;
}
}
else
{
correct = false;
return 1;
}
}
else
{
return 1;
}
}
/*
an auxiliary function for converting from wide characters to UTF-8
converting a wide character into one int
returns how many wide characters were used
if wide_string has at least one character then the return value is always greater than zero too
*/
static size_t WideToInt(const wchar_t * wide_string, int & z, bool & correct)
{
size_t min_str_len = 1;
if( *wide_string == 0 )
{
z = 0;
correct = false;
return 0;
}
if( *(wide_string+1) != 0 )
min_str_len = 2;
return WideToInt(wide_string, min_str_len, z, correct);
}
/*!
an auxiliary function for converting from wide characters to UTF-8
returns how many wide characters were used
if string_len is greater than 0 then the return value is always greater than zero too
*/
static size_t WideOneToUTF8(const wchar_t * wide_string, size_t string_len, std::string & utf8, bool & was_error, int mode)
{
int z;
bool correct;
size_t chars;
chars = WideToInt(wide_string, string_len, z, correct);
if( correct )
correct = IntToUTF8(z, utf8, false) != 0;
if( !correct )
{
if( mode == 1 )
IntToUTF8(0xFFFD, utf8, false); // U+FFFD "replacement character"
was_error = true;
}
return chars;
}
/*!
an auxiliary function for converting from wide characters to UTF-8
returns how many wide characters were used
if wide_string has at least one character then the return value is always greater than zero too
*/
static size_t WideOneToUTF8(const wchar_t * wide_string, std::string & utf8, bool & was_error, int mode)
{
int z;
bool correct;
size_t chars;
chars = WideToInt(wide_string, z, correct);
if( correct )
correct = IntToUTF8(z, utf8, false) != 0;
if( !correct )
{
if( mode == 1 )
IntToUTF8(0xFFFD, utf8, false); // U+FFFD "replacement character"
was_error = true;
}
return chars;
}
/*!
an auxiliary function for converting from wide characters to UTF-8
returns how many wide characters were used
if string_len is greater than 0 then the return value is always greater than zero too
*/
static size_t WideOneToUTF8(const wchar_t * wide_string, size_t string_len, std::ostream & utf8, bool & was_error, int mode)
{
int z;
bool correct;
size_t chars;
chars = WideToInt(wide_string, string_len, z, correct);
if( correct )
correct = IntToUTF8(z, utf8) != 0;
if( !correct )
{
if( mode == 1 )
IntToUTF8(0xFFFD, utf8); // U+FFFD "replacement character"
was_error = true;
}
return chars;
}
/*!
an auxiliary function for converting from wide characters to UTF-8
*/
static size_t WideOneToUTF8(const wchar_t * wide_string, std::ostream & utf8, bool & was_error, int mode)
{
size_t min_str_len = 1;
if( *wide_string == 0 )
return 0;
if( *(wide_string+1) != 0 )
min_str_len = 2;
return WideOneToUTF8(wide_string, min_str_len, utf8, was_error, mode);
}
/*!
this function converts a wide string into UTF-8 string
input:
wide_string - a wide string for converting
string_len - the size of the string
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
utf8 - a UTF-8 string for the output sequence (the string is not cleared)
this function returns false if there were some errors when converting
*/
bool WideToUTF8(const wchar_t * wide_string, size_t string_len, std::string & utf8, bool clear, int mode)
{
bool was_error = false;
size_t chars;
if( clear )
utf8.clear();
while( string_len > 0 )
{
chars = WideOneToUTF8(wide_string, string_len, utf8, was_error, mode);
wide_string += chars;
string_len -= chars;
}
return !was_error;
}
/*!
this function converts a wide string into UTF-8 string
input:
wide_string - a null terminated wide string for converting
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
utf8 - a UTF-8 string for the output sequence (the string is not cleared)
this function returns false if there were some errors when converting
*/
bool WideToUTF8(const wchar_t * wide_string, std::string & utf8, bool clear, int mode)
{
bool was_error = false;
if( clear )
utf8.clear();
while( *wide_string )
wide_string += WideOneToUTF8(wide_string, utf8, was_error, mode);
return !was_error;
}
/*!
this function converts a wide string (std::wstring) into UTF-8 string
input:
wide_string - a wide string for converting
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
utf8 - a UTF-8 string for the output sequence (the string is not cleared)
this function returns false if there were some errors when converting
*/
bool WideToUTF8(const std::wstring & wide_string, std::string & utf8, bool clear, int mode)
{
return WideToUTF8(wide_string.c_str(), wide_string.size(), utf8, clear, mode);
}
/*!
this function converts a wide string into UTF-8 stream
input:
wide_string - a wide string for converting
string_len - size of the string
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
utf8 - a UTF-8 stream for the output sequence
this function returns false if there were some errors when converting
*/
bool WideToUTF8(const wchar_t * wide_string, size_t string_len, std::ostream & utf8, int mode)
{
bool was_error = false;
size_t chars;
while( string_len > 0 )
{
chars = WideOneToUTF8(wide_string, string_len, utf8, was_error, mode);
wide_string += chars;
string_len -= chars;
}
return !was_error;
}
/*!
this function converts a wide string into UTF-8 stream
input:
wide_string - a null terminated wide string for converting
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
utf8 - a UTF-8 stream for the output sequence
this function returns false if there were some errors when converting
*/
bool WideToUTF8(const wchar_t * wide_string, std::ostream & utf8, int mode)
{
bool was_error = false;
while( *wide_string )
wide_string += WideOneToUTF8(wide_string, utf8, was_error, mode);
return !was_error;
}
/*!
this function converts a wide string (std::wstring) into UTF-8 stream
input:
wide_string - a wide string for converting
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
utf8 - a UTF-8 stream for the output sequence
this function returns false if there were some errors when converting
*/
bool WideToUTF8(const std::wstring & wide_string, std::ostream & utf8, int mode)
{
return WideToUTF8(wide_string.c_str(), wide_string.size(), utf8, mode);
}
} // namespace Ezc

111
src/utf8.h Executable file
View File

@@ -0,0 +1,111 @@
/*
* This file is a part of EZC -- Easy templating in C++
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2010-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef headerfile_ezc_utf8
#define headerfile_ezc_utf8
#include <fstream>
#include <string>
namespace Ezc
{
/*!
UTF-8, a transformation format of ISO 10646
http://tools.ietf.org/html/rfc3629
when wchar_t is 4 bytes length we use UTF-32
when wchar_t is 2 bytes length we use UTF-16 (with surrogate pairs)
UTF-16
http://www.ietf.org/rfc/rfc2781.txt
*/
/*!
returns true if 'c' is a correct unicode character
*/
bool UTF8_CheckRange(int c);
/*!
converting one character from UTF-8 to an int
*/
size_t UTF8ToInt(const char * utf8, size_t utf8_len, int & res, bool & correct);
size_t UTF8ToInt(const char * utf8, int & res, bool & correct);
size_t UTF8ToInt(const std::string & utf8, int & res, bool & correct);
size_t UTF8ToInt(std::istream & utf8, int & res, bool & correct);
/*!
converting UTF-8 string to a wide string
*/
bool UTF8ToWide(const char * utf8, size_t utf8_len, std::wstring & res, bool clear = true, int mode = 1);
bool UTF8ToWide(const char * utf8, std::wstring & res, bool clear = true, int mode = 1);
bool UTF8ToWide(const std::string & utf8, std::wstring & res, bool clear = true, int mode = 1);
bool UTF8ToWide(std::istream & utf8, std::wstring & res, bool clear = true, int mode = 1);
/*!
converting one int character to UTF-8
*/
size_t IntToUTF8(int z, char * utf8, size_t utf8_max_len);
size_t IntToUTF8(int z, std::string & utf8, bool clear = true );
size_t IntToUTF8(int z, std::ostream & utf8);
/*!
converting a wide string to UTF-8 string
*/
bool WideToUTF8(const wchar_t * wide_string, size_t string_len, std::string & utf8, bool clear = true, int mode = 1);
bool WideToUTF8(const wchar_t * wide_string, std::string & utf8, bool clear = true, int mode = 1);
bool WideToUTF8(const std::wstring & wide_string, std::string & utf8, bool clear = true, int mode = 1);
bool WideToUTF8(const wchar_t * wide_string, size_t string_len, std::ostream & utf8, int mode = 1);
bool WideToUTF8(const wchar_t * wide_string, std::ostream & utf8, int mode = 1);
bool WideToUTF8(const std::wstring & wide_string, std::ostream & utf8, int mode = 1);
} // namespace Ezc
#endif