From f204719e8ef0ffbdd1752cd300b24f3ba095748d Mon Sep 17 00:00:00 2001 From: tajmone Date: Sun, 3 Nov 2019 06:40:09 +0100 Subject: [PATCH 1/3] Fix EOLs This commit fixes some text files being indexed with CRLF or mixed EOLs, which might create problems on non-Windows OSs. * Add `.gitattributes` with optimal EOL normalization settings for Nim projects (from_ tajmone/nim-repository-template) and cover all file extensions used in this repository. * Enforce the new EOL normalization rules via `git add --renormalize`, thus fixing those files that were indexed with CRLF or mixed EOLs. --- .gitattributes | 40 + include/aux-asset.h | 466 +-- include/aux-cvt.h | 1598 +++++----- include/aux-platform.h | 110 +- include/aux-slice.h | 984 +++--- include/behaviors/behavior_camera_capture.cpp | 188 +- include/behaviors/behavior_drawing-gdi.cpp | 326 +- include/behaviors/behavior_drawing.cpp | 290 +- include/behaviors/behavior_tabs.cpp | 466 +-- .../behaviors/behavior_video_generator.cpp | 246 +- include/behaviors/camera/camera-capture.cpp | 1208 ++++---- include/behaviors/camera/camera-capture.h | 290 +- include/sciter-gtk-main.cpp | 118 +- include/sciter-osx-main.mm | 182 +- include/sciter-win-main.cpp | 238 +- include/sciter-x-api.h | 1434 ++++----- include/sciter-x-behavior.h | 1790 +++++------ include/sciter-x-debug.h | 324 +- include/sciter-x-def.h | 766 ++--- include/sciter-x-dom.h | 656 ++-- include/sciter-x-dom.hpp | 2716 ++++++++--------- include/sciter-x-graphics.h | 862 +++--- include/sciter-x-graphics.hpp | 1258 ++++---- include/sciter-x-host-callback.h | 610 ++-- include/sciter-x-lite.hpp | 220 +- include/sciter-x-request.h | 476 +-- include/sciter-x-request.hpp | 238 +- include/sciter-x-script.h | 94 +- include/sciter-x-threads.h | 494 +-- include/sciter-x-types.h | 578 ++-- include/sciter-x-value.h | 64 +- include/sciter-x-video-api.h | 166 +- include/sciter-x-window.hpp | 176 +- include/sciter-x.h | 72 +- include/tiscript-streams.hpp | 262 +- include/tiscript.h | 714 ++--- include/tiscript.hpp | 1016 +++--- include/value.h | 762 ++--- include/value.hpp | 1258 ++++---- xdef.nim | 586 ++-- xgraphics.nim | 558 ++-- xrequest.nim | 238 +- xtiscript.nim | 586 ++-- xvalue.nim | 178 +- 44 files changed, 12971 insertions(+), 12931 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..88571ab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,40 @@ +* text=auto + +## Nim files +############ +*.nim text eol=lf +*.nim.cfg text eol=lf +*.nimble text eol=lf +*.nimf text eol=lf linguist-language=Nim +*.nims text eol=lf + +## C++ includes +############### +*.cpp text +*.h text +*.hpp text +*.mm text + +## Shell/CMD scripts +#################### +*.bat text eol=crlf +*.sh text eol=lf + +## Documentation +################ +*.md text +*.rst text +LICENSE text + +## Miscellanea +############## +*.html text +Makefile text eol=lf + +## Repository settings +###################### +.editorconfig text eol=lf +.gitattributes text eol=lf +.gitconfig text eol=lf +.gitignore text eol=lf +.gitmodules text eol=lf diff --git a/include/aux-asset.h b/include/aux-asset.h index 50dac08..f601e36 100644 --- a/include/aux-asset.h +++ b/include/aux-asset.h @@ -1,233 +1,233 @@ -#pragma once - -#if defined(_WIN32) - - #define WIN32_LEAN_AND_MEAN - #include - //#include -#else - #include -#endif - -namespace aux { - - namespace atomic { - - #if defined(_WINDOWS) || defined(WINDOWS) - - typedef volatile long counter_t; - inline long _inc(counter_t& v) { return InterlockedIncrement((LPLONG)&v); } - inline long _inc(counter_t& v,long by) { return InterlockedExchangeAdd((LPLONG)&v,by); } - inline long _dec(counter_t& v) { return InterlockedDecrement((LPLONG)&v); } - inline long _set(counter_t& v, long nv) { return InterlockedExchange((LPLONG)&v, nv); } - inline long _set_when_eq(counter_t& v, long to_set, long eq_to) { return InterlockedCompareExchange ((LPLONG)&v,to_set,eq_to); } - - #elif defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8) ) - - typedef long counter_t; - inline long _inc(counter_t& v) { return __sync_add_and_fetch(&v,1); } - inline long _inc(counter_t& v,long by) { return __sync_add_and_fetch(&v,by); } - inline long _dec(counter_t& v) { return __sync_add_and_fetch(&v,-1); } - inline long _set(counter_t& v, long nv) { return __sync_lock_test_and_set(&v,nv); } - inline long _set_when_eq(counter_t& v, long to_set, long eq_to) { return __sync_val_compare_and_swap(&v,eq_to,to_set); - /*long t(v); if(t == eq_to) v = to_set; return t;*/ } - #else - - typedef std::atomic counter_t; - inline long _inc(counter_t& v) { return ++v; } - inline long _inc(counter_t& v,long by) { return v += by; } - inline long _dec(counter_t& v) { return --v; } - inline long _set(counter_t& v, long nv) { return v.exchange(nv); } - inline long _set_when_eq(counter_t& v, long to_set, long eq_to) { long t(v); v.compare_exchange_strong(eq_to,to_set); return t; } - - #endif - - struct counter - { - counter_t cv; - counter():cv(0) {} - counter(long iv):cv(iv) {} - counter& operator=(long nv) { _set(cv,nv); return *this; } - operator long() const { return cv; } - long operator++() { return _inc(cv); } - long operator--() { return _dec(cv); } - }; - } // atomic - - - // COM::IUnknown alike thing: - class iasset { - public: - // mandatory: - virtual long add_ref() = 0; - virtual long release() = 0; - // optional: - virtual bool get_interface(const char* name, iasset** out) = 0; - }; - - - // intrusive add_ref/release counter - class asset: public virtual iasset - { - atomic::counter _ref_cntr; - public: - asset ():_ref_cntr(0) {} - asset (const asset&/*r*/):_ref_cntr(0) {} - - virtual ~asset () - { - assert ( _ref_cntr == 0 ); - } - - virtual long release() - { - assert(_ref_cntr > 0); - long t = --_ref_cntr; - if(t == 0) - finalize(); - return t; - } - virtual long add_ref() { return ++_ref_cntr; } - - // "name" here is an arbitrary name that includes domain name in reversed order: - // "element.dom.sciter.com" - // "video-renderer.dom.sciter.com" - virtual bool get_interface(const char* name, iasset** out) { return false; } - - virtual void finalize() - { - delete this; - } - }; - - //asset - yet another shared_ptr - // R here is something derived from the asset above - template - class asset_ptr - { - protected: - R* p; - - public: - typedef R asset_t; - - asset_ptr():p(0) {} - asset_ptr(R* lp):p(0) { if (lp) (p = lp)->add_ref(); } - asset_ptr(const asset_ptr& cp):p(0) { if (cp.p) (p = cp.p)->add_ref(); } - - ~asset_ptr() { if (p) p->release();} - operator R*() const { return p; } - R* operator->() const { assert(p != 0); return p; } - - bool operator!() const { return p == 0; } - operator bool() const { return p != 0; } - bool operator!=(R* pR) const { return p != pR; } - bool operator==(R* pR) const { return p == pR; } - - // release the interface and set it to NULL - void release() { if (p) { R* pt = p; p = 0; pt->release(); }} - - // attach to an existing interface (does not AddRef) - void attach(R* p2) { release(); p = p2; } - // detach the interface (does not Release) - R* detach() { R* pt = p; p = 0; return pt; } - - static R* assign(R* &pp, R* lp) - { - if (lp != 0) lp->add_ref(); - if (pp) pp->release(); - pp = lp; - return lp; - } - - R* operator=(R* lp) { if(p != lp) return assign(p, lp); return p; } - R* operator=(const asset_ptr& lp) { if(p != lp) return assign(p, lp.p); return p; } - - R** target() { release(); return &p; } - - }; - -} - -#if defined(_WINDOWS) - -namespace com { - - //asset - yet another smart pointer - template - class ptr - { - protected: - T* p; - - public: - typedef T asset_t; - - ptr():p(0) {} - ptr(T* lp):p(0) { if (lp) (p = lp)->AddRef(); } - ptr(const ptr& cp):p(0) { if (cp.p) (p = cp.p)->AddRef(); } - - ~ptr() - { - ULONG c = 0; - if (p) - c = p->Release(); - } - operator T*() const { return p; } - T* operator->() const { assert(p != 0); return p; } - - // used as target T** pointer to pointer - in places receiving newly created objects (initially add-refed) - T** target() { release(); return &p; } - - bool operator!() const { return p == 0; } - operator bool() const { return p != 0; } - bool operator!=(T* pT) const { return p != pT; } - bool operator==(T* pT) const { return p == pT; } - - // release the interface and set it to NULL - void release() { if (p) { T* pt = p; p = 0; pt->Release(); }} - - // attach to an existing interface (does not AddRef) - void attach(T* p2) { release(); p = p2; } - // detach the interface (does not Release) - T* detach() { T* pt = p; p = 0; return pt; } - - static T* assign(T* &pp, T* lp) - { - if (lp != 0) lp->AddRef(); - if (pp) pp->Release(); - pp = lp; - return lp; - } - - T* operator=(T* lp) { if(p != lp) return assign(p, lp); return p; } - T* operator=(const ptr& lp) { if(p != lp) return assign(p, lp.p); return p; } - - T* acquire() { if( p ) p->AddRef(); return p; } - - HRESULT CoCreateInstance (REFCLSID classUUID, DWORD dwClsContext = CLSCTX_INPROC_SERVER) - { - HRESULT hr = ::CoCreateInstance (classUUID, 0, dwClsContext, __uuidof (T), (void**) target()); - assert (hr != CO_E_NOTINITIALIZED); // You haven't called CoInitialize for the current thread! - return hr; - } - - template - HRESULT QueryInterface (REFCLSID classUUID, ptr& dest_object) const - { - if (p == 0) - return E_POINTER; - return p->QueryInterface (classUUID, (void**) dest_object.target()); - } - - template - HRESULT QueryInterface (ptr& dest_object) const - { - return this->QueryInterface (__uuidof (OTHER_COM_CLASS), dest_object); - } - - }; - -} - -#endif +#pragma once + +#if defined(_WIN32) + + #define WIN32_LEAN_AND_MEAN + #include + //#include +#else + #include +#endif + +namespace aux { + + namespace atomic { + + #if defined(_WINDOWS) || defined(WINDOWS) + + typedef volatile long counter_t; + inline long _inc(counter_t& v) { return InterlockedIncrement((LPLONG)&v); } + inline long _inc(counter_t& v,long by) { return InterlockedExchangeAdd((LPLONG)&v,by); } + inline long _dec(counter_t& v) { return InterlockedDecrement((LPLONG)&v); } + inline long _set(counter_t& v, long nv) { return InterlockedExchange((LPLONG)&v, nv); } + inline long _set_when_eq(counter_t& v, long to_set, long eq_to) { return InterlockedCompareExchange ((LPLONG)&v,to_set,eq_to); } + + #elif defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8) ) + + typedef long counter_t; + inline long _inc(counter_t& v) { return __sync_add_and_fetch(&v,1); } + inline long _inc(counter_t& v,long by) { return __sync_add_and_fetch(&v,by); } + inline long _dec(counter_t& v) { return __sync_add_and_fetch(&v,-1); } + inline long _set(counter_t& v, long nv) { return __sync_lock_test_and_set(&v,nv); } + inline long _set_when_eq(counter_t& v, long to_set, long eq_to) { return __sync_val_compare_and_swap(&v,eq_to,to_set); + /*long t(v); if(t == eq_to) v = to_set; return t;*/ } + #else + + typedef std::atomic counter_t; + inline long _inc(counter_t& v) { return ++v; } + inline long _inc(counter_t& v,long by) { return v += by; } + inline long _dec(counter_t& v) { return --v; } + inline long _set(counter_t& v, long nv) { return v.exchange(nv); } + inline long _set_when_eq(counter_t& v, long to_set, long eq_to) { long t(v); v.compare_exchange_strong(eq_to,to_set); return t; } + + #endif + + struct counter + { + counter_t cv; + counter():cv(0) {} + counter(long iv):cv(iv) {} + counter& operator=(long nv) { _set(cv,nv); return *this; } + operator long() const { return cv; } + long operator++() { return _inc(cv); } + long operator--() { return _dec(cv); } + }; + } // atomic + + + // COM::IUnknown alike thing: + class iasset { + public: + // mandatory: + virtual long add_ref() = 0; + virtual long release() = 0; + // optional: + virtual bool get_interface(const char* name, iasset** out) = 0; + }; + + + // intrusive add_ref/release counter + class asset: public virtual iasset + { + atomic::counter _ref_cntr; + public: + asset ():_ref_cntr(0) {} + asset (const asset&/*r*/):_ref_cntr(0) {} + + virtual ~asset () + { + assert ( _ref_cntr == 0 ); + } + + virtual long release() + { + assert(_ref_cntr > 0); + long t = --_ref_cntr; + if(t == 0) + finalize(); + return t; + } + virtual long add_ref() { return ++_ref_cntr; } + + // "name" here is an arbitrary name that includes domain name in reversed order: + // "element.dom.sciter.com" + // "video-renderer.dom.sciter.com" + virtual bool get_interface(const char* name, iasset** out) { return false; } + + virtual void finalize() + { + delete this; + } + }; + + //asset - yet another shared_ptr + // R here is something derived from the asset above + template + class asset_ptr + { + protected: + R* p; + + public: + typedef R asset_t; + + asset_ptr():p(0) {} + asset_ptr(R* lp):p(0) { if (lp) (p = lp)->add_ref(); } + asset_ptr(const asset_ptr& cp):p(0) { if (cp.p) (p = cp.p)->add_ref(); } + + ~asset_ptr() { if (p) p->release();} + operator R*() const { return p; } + R* operator->() const { assert(p != 0); return p; } + + bool operator!() const { return p == 0; } + operator bool() const { return p != 0; } + bool operator!=(R* pR) const { return p != pR; } + bool operator==(R* pR) const { return p == pR; } + + // release the interface and set it to NULL + void release() { if (p) { R* pt = p; p = 0; pt->release(); }} + + // attach to an existing interface (does not AddRef) + void attach(R* p2) { release(); p = p2; } + // detach the interface (does not Release) + R* detach() { R* pt = p; p = 0; return pt; } + + static R* assign(R* &pp, R* lp) + { + if (lp != 0) lp->add_ref(); + if (pp) pp->release(); + pp = lp; + return lp; + } + + R* operator=(R* lp) { if(p != lp) return assign(p, lp); return p; } + R* operator=(const asset_ptr& lp) { if(p != lp) return assign(p, lp.p); return p; } + + R** target() { release(); return &p; } + + }; + +} + +#if defined(_WINDOWS) + +namespace com { + + //asset - yet another smart pointer + template + class ptr + { + protected: + T* p; + + public: + typedef T asset_t; + + ptr():p(0) {} + ptr(T* lp):p(0) { if (lp) (p = lp)->AddRef(); } + ptr(const ptr& cp):p(0) { if (cp.p) (p = cp.p)->AddRef(); } + + ~ptr() + { + ULONG c = 0; + if (p) + c = p->Release(); + } + operator T*() const { return p; } + T* operator->() const { assert(p != 0); return p; } + + // used as target T** pointer to pointer - in places receiving newly created objects (initially add-refed) + T** target() { release(); return &p; } + + bool operator!() const { return p == 0; } + operator bool() const { return p != 0; } + bool operator!=(T* pT) const { return p != pT; } + bool operator==(T* pT) const { return p == pT; } + + // release the interface and set it to NULL + void release() { if (p) { T* pt = p; p = 0; pt->Release(); }} + + // attach to an existing interface (does not AddRef) + void attach(T* p2) { release(); p = p2; } + // detach the interface (does not Release) + T* detach() { T* pt = p; p = 0; return pt; } + + static T* assign(T* &pp, T* lp) + { + if (lp != 0) lp->AddRef(); + if (pp) pp->Release(); + pp = lp; + return lp; + } + + T* operator=(T* lp) { if(p != lp) return assign(p, lp); return p; } + T* operator=(const ptr& lp) { if(p != lp) return assign(p, lp.p); return p; } + + T* acquire() { if( p ) p->AddRef(); return p; } + + HRESULT CoCreateInstance (REFCLSID classUUID, DWORD dwClsContext = CLSCTX_INPROC_SERVER) + { + HRESULT hr = ::CoCreateInstance (classUUID, 0, dwClsContext, __uuidof (T), (void**) target()); + assert (hr != CO_E_NOTINITIALIZED); // You haven't called CoInitialize for the current thread! + return hr; + } + + template + HRESULT QueryInterface (REFCLSID classUUID, ptr& dest_object) const + { + if (p == 0) + return E_POINTER; + return p->QueryInterface (classUUID, (void**) dest_object.target()); + } + + template + HRESULT QueryInterface (ptr& dest_object) const + { + return this->QueryInterface (__uuidof (OTHER_COM_CLASS), dest_object); + } + + }; + +} + +#endif diff --git a/include/aux-cvt.h b/include/aux-cvt.h index 6dfe2de..056d3eb 100644 --- a/include/aux-cvt.h +++ b/include/aux-cvt.h @@ -1,799 +1,799 @@ -#ifndef __sciter_aux_h__ -#define __sciter_aux_h__ - -#if defined(__cplusplus) && !defined( PLAIN_API_ONLY ) - -/* - * Terra Informatica Sciter and HTMLayout Engines - * http://terrainformatica.com/sciter, http://terrainformatica.com/htmlayout - * - * basic primitives. - * - * The code and information provided "as-is" without - * warranty of any kind, either expressed or implied. - * - * (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com) - */ - -/**\file - * \brief primitives - **/ - -/* - - pod::copy - memcpy wrapper - pod::move - memmove wrapper - pod::buffer - dynamic buffer, string builder, etc. - - utf8::towcs() - utf8 to WCHAR* converter - utf8::fromwcs() - WCHAR* to utf8 converter - utf8::ostream - raw ASCII/UNICODE -> UTF8 converter - utf8::oxstream - ASCII/UNICODE -> UTF8 converter with XML support - - inline bool streq(const char* s, const char* s1) - NULL safe string comparison function - inline bool wcseq(const WCHAR* s, const WCHAR* s1) - NULL safe wide string comparison function - inline bool streqi(const char* s, const char* s1) - the same, but case independent - inline bool wcseqi(const WCHAR* s, const WCHAR* s1) - the same, but case independent - - w2a - helper object for const WCHAR* to const char* conversion - a2w - helper object for const char* to const WCHAR* conversion - w2utf - helper object for const WCHAR* to utf8 conversion - utf2w - helper object for utf8 to const WCHAR* conversion - - t2w - const TCHAR* to const WCHAR* conversion, #definition - w2t - const WCHAR* to const TCHAR* conversion, #definition - - itoa, itow - int to const char* converter - atoi, wtoi - const char* to int converter (parser) - ftoa, ftow - double to const char* converter - - - */ - -#pragma once - -#include -#include -#include -#include -#include -#include // std::reverse -#include "aux-platform.h" -#include "aux-slice.h" - -#include -#include - -// disable that warnings in VC 2005 -#pragma warning(disable:4786) //identifier was truncated... -#pragma warning(disable:4100) //unreferenced formal parameter - -#ifndef BYTE - typedef unsigned char BYTE; -#endif - -//#include "aux-slice.h" - -// WARNING: macros below must be used only for passing parameters to functions! - -/* -#if !defined(W2A) // WCHAR to multi-BYTE string converter (current locale) -#define W2A aux::w2a -#endif - -#if !defined(A2W) // multi-BYTE to WCHAR string converter (current locale) -#define A2W aux::a2w -#endif - -#if !defined(UTF2W) // utf-8 to WCHAR string converter -#define UTF2W aux::utf2w -#endif - -#if !defined(W2UTF) // WCHAR to utf-8 string converter -#define W2UTF aux::w2utf -#endif - -#if !defined(W2T) -#if !defined(UNICODE) -#define W2T(S) aux::w2a(S) -#else -#define W2T(S) (S) -#endif -#endif - -#if !defined(T2W) -#if !defined(UNICODE) -#define T2W(S) aux::a2w(S) -#else -#define T2W(S) (S) -#endif -#endif - -#if !defined(A2T) -#if !defined(UNICODE) -#define A2T(S) (S) -#else -#define A2T(S) aux::a2w(S) -#endif -#endif - -#if !defined(T2A) -#if !defined(UNICODE) -#define T2A(S) (S) -#else -#define T2A(S) aux::w2a(S) -#endif -#endif - -*/ - -#ifdef UNICODE -#define a2t( S ) aux::a2w(S) -#define t2a( S ) aux::w2a(S) -#define w2t( S ) (S) -#define t2w( S ) (S) -#define t2i( S ) aux::wtoi(S,0) -#define i2t( S ) aux::itow(S) -#else -#define a2t( S ) (S) -#define t2a( S ) (S) -#define w2t( S ) aux::w2a(S) -#define t2w( S ) aux::a2w(S) -#define t2i( S ) aux::atoi(S,0) -#define i2t( S ) aux::itoa(S) -#endif - -#define w2u( S ) aux::w2utf(S) -#define u2w( S ) aux::utf2w(S) - -#define i2a( I ) aux::itoa(I) -#define i2w( I ) aux::itow(I) - -inline void* zalloc ( size_t sz) -{ - void* p = malloc(sz); - if(p) memset(p,0,sz); - return p; -} - -//elements in array literal -#define ITEMS_IN(a) (sizeof(a)/sizeof(a[0])) -//chars in sting literal -#define CHARS_IN(s) (sizeof(s) / sizeof(s[0]) - 1) - -/**pod namespace - POD primitives. **/ -namespace pod -{ - template void copy ( T* dst, const T* src, size_t nelements) - { - memcpy(dst,src,nelements*sizeof(T)); - } - template void move ( T* dst, const T* src, size_t nelements) - { - memmove(dst,src,nelements*sizeof(T)); - } - - /** buffer - in-memory dynamic buffer implementation. **/ - template - class buffer - { - T* _body; - size_t _allocated; - size_t _size; - - T* reserve(size_t size) - { - size_t newsize = _size + size; - if( newsize > _allocated ) - { - _allocated = (_allocated * 3) / 2; - if(_allocated < newsize) _allocated = newsize; - T *newbody = new T[_allocated]; - copy(newbody,_body,_size); - delete[] _body; - _body = newbody; - } - return _body + _size; - } - - public: - - buffer():_size(0) { _body = new T[_allocated = 256]; } - ~buffer() { delete[] _body; } - - const T * data() const - { - buffer* self = const_cast(this); - if(_size == _allocated) self->reserve(1); - self->_body[_size] = 0; return _body; - } - - size_t length() const { return _size; } - - void push(T c) { *reserve(1) = c; ++_size; } - void push(const T *pc, size_t sz) { copy(reserve(sz),pc,sz); _size += sz; } - - void clear() { _size = 0; } - - }; - - typedef buffer byte_buffer; - typedef buffer wchar_buffer; - typedef buffer char_buffer; -} - -namespace utf8 -{ - // convert utf8 code unit sequence to WCHAR sequence - - inline bool towcs(const BYTE *utf8, size_t length, pod::wchar_buffer& outbuf) - { - if(!utf8 || length == 0) return true; - const BYTE* pc = (const BYTE*)utf8; - const BYTE* last = pc + length; - unsigned int b; - unsigned int num_errors = 0; - while (pc < last) - { - b = *pc++; - - if( !b ) break; // 0 - is eos in all utf encodings - - if ((b & 0x80) == 0) - { - // 1-BYTE sequence: 000000000xxxxxxx = 0xxxxxxx - ; - } - else if ((b & 0xe0) == 0xc0) - { - // 2-BYTE sequence: 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx - if(pc == last) { outbuf.push('?'); ++num_errors; break; } - b = (b & 0x1f) << 6; - b |= (*pc++ & 0x3f); - } - else if ((b & 0xf0) == 0xe0) - { - // 3-BYTE sequence: zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx - if(pc >= last - 1) { outbuf.push('?'); ++num_errors; break; } - - b = (b & 0x0f) << 12; - b |= (*pc++ & 0x3f) << 6; - b |= (*pc++ & 0x3f); - if(b == 0xFEFF && - outbuf.length() == 0) // bom at start - continue; // skip it - } - else if ((b & 0xf8) == 0xf0) - { - // 4-BYTE sequence: 11101110wwwwzzzzyy + 110111yyyyxxxxxx = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx - if(pc >= last - 2) { outbuf.push('?'); break; } - - b = (b & 0x07) << 18; - b |= (*pc++ & 0x3f) << 12; - b |= (*pc++ & 0x3f) << 6; - b |= (*pc++ & 0x3f); - // b shall contain now full 21-bit unicode code point. - assert((b & 0x1fffff) == b); - if((b & 0x1fffff) != b) - { - outbuf.push('?'); - ++num_errors; - continue; - } -#pragma warning( push ) -#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant - //warning C4127: conditional expression is constant - if( sizeof(WCHAR) == 16 ) // Seems like Windows, WCHAR is utf16 code units sequence there. - { - outbuf.push( WCHAR(0xd7c0 + (b >> 10)) ); - outbuf.push( WCHAR(0xdc00 | (b & 0x3ff)) ); - } - else if( sizeof(WCHAR) >= 21 ) // WCHAR is full ucs-4 - { - outbuf.push( WCHAR(b) ); - } - else - { - assert(0); // what? WCHAR is single BYTE here? - } -#pragma warning( pop ) - } - else - { - assert(0); //bad start for UTF-8 multi-BYTE sequence" - ++num_errors; - b = '?'; - } - outbuf.push( WCHAR(b) ); - } - return num_errors == 0; - } - - inline bool fromwcs(const WCHAR* wcs, size_t length, pod::byte_buffer& outbuf) - { - const WCHAR *pc = wcs; - const WCHAR *end = pc + length; - unsigned int num_errors = 0; - for(unsigned int c = *pc; pc < end ; c = *(++pc)) - { - if (c < (1 << 7)) - { - outbuf.push(BYTE(c)); - } - else if (c < (1 << 11)) - { - outbuf.push(BYTE((c >> 6) | 0xc0)); - outbuf.push(BYTE((c & 0x3f) | 0x80)); - } - else if (c < (1 << 16)) - { - outbuf.push(BYTE((c >> 12) | 0xe0)); - outbuf.push(BYTE(((c >> 6) & 0x3f) | 0x80)); - outbuf.push(BYTE((c & 0x3f) | 0x80)); - } - else if (c < (1 << 21)) - { - outbuf.push(BYTE((c >> 18) | 0xf0)); - outbuf.push(BYTE(((c >> 12) & 0x3f) | 0x80)); - outbuf.push(BYTE(((c >> 6) & 0x3f) | 0x80)); - outbuf.push(BYTE((c & 0x3f) | 0x80)); - } - else - ++num_errors; - } - return num_errors == 0; - } - - // UTF8 stream - - // class T must have two methods: - // void push(unsigned char c) - // void push(const unsigned char *pc, size_t sz) - - // bool X - true - XML markup character conversion (characters '<','>',etc). - // false - no conversion at all. - - template - class ostream_t : public T - { - public: - ostream_t() - { - // utf8 BYTE order mark - static unsigned char BOM[] = { 0xEF, 0xBB, 0xBF }; - T::push(BOM, sizeof(BOM)); - } - - // intended to handle only ascii-7 strings - // use this for markup output - ostream_t& operator << (const char* str) - { - T::push((const unsigned char*)str,strlen(str)); return *this; - } - - ostream_t& operator << (char c) - { - T::push((unsigned char)c); return *this; - } - - // use UNICODE chars for value output - ostream_t& operator << (const WCHAR* wstr) - { - const WCHAR *pc = wstr; - for(unsigned int c = *pc; c ; c = *(++pc)) - { - if(X) - switch(c) - { - case '<': *this << "<"; continue; - case '>': *this << ">"; continue; - case '&': *this << "&"; continue; - case '"': *this << """; continue; - case '\'': *this << "'"; continue; - } - if (c < (1 << 7)) - { - T::push (BYTE(c)); - } - else if (c < (1 << 11)) { - T::push (BYTE((c >> 6) | 0xc0)); - T::push (BYTE((c & 0x3f) | 0x80)); - } - else if (c < (1 << 16)) { - T::push (BYTE((c >> 12) | 0xe0)); - T::push (BYTE(((c >> 6) & 0x3f) | 0x80)); - T::push (BYTE((c & 0x3f) | 0x80)); - } - else if (c < (1 << 21)) - { - T::push (BYTE((c >> 18) | 0xf0)); - T::push (BYTE(((c >> 12) & 0x3f) | 0x80)); - T::push (BYTE(((c >> 6) & 0x3f) | 0x80)); - T::push (BYTE((c & 0x3f) | 0x80)); - } - } - return *this; - } - ostream_t& operator << (const std::wstring& str) - { - return *this << (str.c_str()); - } - - }; - - // raw ASCII/UNICODE -> UTF8 converter - typedef ostream_t ostream; - // ASCII/UNICODE -> UTF8 converter with XML support - typedef ostream_t oxstream; - - -} // namespace utf8 - -namespace aux -{ - template struct slice; - - template - inline T - limit ( T v, T minv, T maxv ) - { - assert(minv < maxv); - if (minv >= maxv) - return minv; - if (v > maxv) return maxv; - if (v < minv) return minv; - return v; - } - - // safe string comparison - inline bool streq(const char* s, const char* s1) - { - if( s && s1 ) - return strcmp(s,s1) == 0; - return false; - } - - // safe wide string comparison -/* inline bool wcseq(const WCHAR* s, const WCHAR* s1) - { - if( s && s1 ) - return std::wcscmp(s,s1) == 0; - return false; - } */ - - // safe case independent string comparison - inline bool streqi(const char* s, const char* s1) - { - if( s && s1 ) - - return stricmp(s,s1) == 0; - return false; - } - - // safe case independent wide string comparison -/* inline bool wcseqi(const WCHAR* s, const WCHAR* s1) - { - if( s && s1 ) - return wcsicmp(s,s1) == 0; - return false; - } */ - - // helper convertor objects WCHAR to utf8 and vice versa - class utf2w - { - pod::wchar_buffer buffer; - public: - explicit utf2w(const BYTE* utf8, size_t length = 0) - { - if(utf8) - { - if( length == 0) length = strlen((const char*)utf8); - utf8::towcs(utf8, length ,buffer); - } - } - explicit utf2w(const char* utf8, size_t length = 0) - { - if(utf8) - { - if( length == 0) length = strlen(utf8); - utf8::towcs((const BYTE*)utf8, length ,buffer); - } - } - explicit utf2w(const std::string& utf8) - { - utf8::towcs((const BYTE*)utf8.c_str(), utf8.length() ,buffer); - } - - ~utf2w() {} - - operator const WCHAR*() const { return buffer.data(); } - const WCHAR* c_str() const { return buffer.data(); } - size_t length() const { return buffer.length(); } - - pod::wchar_buffer& get_buffer() { return buffer; } - - operator aux::wchars() const { return aux::wchars(buffer.data(),buffer.length()); } - aux::wchars chars() const { return aux::wchars(buffer.data(),buffer.length()); } - //operator std::basic_string() const { return std::basic_string(buffer.data(),buffer.length()); } - - }; - - class w2utf - { - pod::byte_buffer buffer; - public: - explicit w2utf(const WCHAR* wstr) - { - if(wstr) - { - size_t nu = wcslen(wstr); - utf8::fromwcs(wstr,nu,buffer); - } - } - explicit w2utf(const std::basic_string& str) - { - utf8::fromwcs(str.c_str(),str.length(),buffer); - } - explicit w2utf(wchars str) - { - utf8::fromwcs(str.start,str.length,buffer); - } - ~w2utf() {} - operator const BYTE*() { return buffer.data(); } - operator const char*() { return (const char*)buffer.data(); } - const char* c_str() const { return (const char*)buffer.data(); } - chars operator()() const { return chars(c_str(),length()); } - - size_t length() const { return buffer.length(); } - }; - -#ifdef WINDOWS - - // helper convertor objects WCHAR to ANSI string and vice versa - class w2a - { - char local[16]; - char* buffer; - size_t n; - - void init(const WCHAR* wstr, size_t nu) - { - n = WideCharToMultiByte(CP_ACP,0,wstr,int(nu),0,0,0,0); - buffer = (n < (16-1))? local:new char[n+1]; - WideCharToMultiByte(CP_ACP,0,wstr,int(nu),buffer,int(n),0,0); - buffer[n] = 0; - } - public: - explicit w2a(const WCHAR* wstr):buffer(0),n(0) - { - if(wstr) - init(wstr,wcslen(wstr)); - } - explicit w2a(const std::basic_string& wstr):buffer(0),n(0) - { - init(wstr.c_str(),wstr.length()); - } - explicit w2a(slice s):buffer(0), n(0) - { - init(s.start,s.length); - } - ~w2a() { if(buffer != local) delete[] buffer; } - size_t length() const { return n; } - operator const char*() { return buffer; } - const char* c_str() const { return buffer; } - }; - - class a2w - { - WCHAR local[16]; - WCHAR* buffer; - size_t nu; - void init(const char* str, size_t n) - { -#ifdef _WIN32_WCE - nu = MultiByteToWideChar(CP_ACP,0,str,n,0,0); -#else - nu = MultiByteToWideChar(CP_THREAD_ACP,0,str,int(n),0,0); -#endif - buffer = ( nu < (16-1) )? local: new WCHAR[nu+1]; -#ifdef _WIN32_WCE - MultiByteToWideChar(CP_ACP,0,str,n,buffer,nu); -#else - MultiByteToWideChar(CP_THREAD_ACP,0,str,int(n),buffer,int(nu)); -#endif - buffer[nu] = 0; - } - public: - explicit a2w(const char* str):buffer(0), nu(0) - { - if(str) - init(str, strlen(str)); - } - explicit a2w(slice s):buffer(0), nu(0) - { - init(s.start,s.length); - } - explicit a2w(const std::string& s):buffer(0), nu(0) - { - init(s.c_str(),s.length()); - } - - ~a2w() { if(buffer != local) delete[] buffer; } - size_t length() const { return nu; } - operator const WCHAR*() const { return buffer; } - const WCHAR* c_str() const { return buffer; } - operator aux::wchars() const { return aux::wchars(buffer,nu); } - aux::wchars chars() const { return aux::wchars(buffer,nu); } - //operator std::basic_string() const { return std::basic_string(buffer,nu); } - - }; - - class w2oem - { - char local[64]; - char* buffer; - size_t n; - - void init(const WCHAR* wstr, size_t nu) - { - n = WideCharToMultiByte(CP_OEMCP,0,wstr,int(nu),0,0,0,0); - buffer = (n < (64-1))? local : new char[n+1]; - WideCharToMultiByte(CP_OEMCP,0,wstr,int(nu),buffer,int(n),0,0); - buffer[n] = 0; - } - - w2oem(const w2oem &); - w2oem& operator=(const w2oem &); - - public: - explicit w2oem(const WCHAR* wstr):buffer(0),n(0) - { - local[0] = 0; - if(wstr) - init(wstr,wcslen(wstr)); - } - explicit w2oem(const std::wstring& wstr):buffer(0),n(0) - { - local[0] = 0; - init(wstr.c_str(),wstr.length()); - } - explicit w2oem(slice s); - - ~w2oem() { if(buffer != local) delete[] buffer; } - size_t length() const { return n; } - operator const char*() { return buffer; } - const char* c_str() const { return buffer; } - }; - -#elif defined(UTF8_CHARS) - typedef utf2w a2w; - typedef w2utf w2a; - typedef utf2w oem2w; - typedef w2utf w2oem; -#else - #error "unknown char string representation" -#endif - - /** Integer to string converter. - Use it as wostream << itow(234) - **/ - -template - class itot - { - CT buffer[38]; - public: - itot(int n, int radix = 10) - { - static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - CT* wstr = buffer; - if (radix < 2 || radix > 35) { *wstr = 0; return; } // validate radix - int sign = n; if (sign < 0) n = -n; - do { *wstr++ = num[n % radix]; } while( n /= radix ); // conversion. number is reversed. - if(sign<0) *wstr++ ='-'; - *wstr = 0; - // reverse the string - std::reverse(buffer,wstr); - } - operator const CT*() { return buffer; } - }; - - typedef itot itoa; - typedef itot itow; - - - /** Float to string converter. - Use it as ostream << ftoa(234.1); or - Use it as ostream << ftoa(234.1,"pt"); or - **/ - class ftoa - { - char buffer[64]; - public: - ftoa(double d, const char* units = "", int fractional_digits = 1) - { - snprintf(buffer, sizeof(buffer), "%.*f%s", fractional_digits, d, units ); - buffer[63] = 0; - } - operator const char*() { return buffer; } - }; - - /** Float to wstring converter. - Use it as wostream << ftow(234.1); or - Use it as wostream << ftow(234.1,"pt"); or - **/ - /*class ftow - { - WCHAR buffer[64]; - public: - ftow(double d, const WCHAR* units = "", int fractional_digits = 1) - { -#ifdef WINDOWS - _snwprintf_s(buffer, 64, L"%.*f%s", fractional_digits, d, units ); -#else - swprintf(buffer, 64, L"%.*f%s", fractional_digits, d, units ); -#endif - buffer[63] = 0; - } - operator const WCHAR*() { return buffer; } - };*/ - - /** string to integer parser. **/ - inline int atoi(const char *s, int default_value = 0) - { - if( !s ) return default_value; - char *lastptr; - long i = strtol( s, &lastptr, 10 ); - return (lastptr != s)? (int)i : default_value; - } - - /** wstring to integer parser. **/ - inline int wtoi(const WCHAR *s, int default_value = 0) - { - w2a at(s); - return atoi(at.c_str(),default_value); - } - - // class T must have two methods: - // void push(WCHAR c) - // void push(const WCHAR *pc, size_t sz) - template - class ostream_t : public T - { - public: - ostream_t() {} - - // intended to handle only ascii-7 strings - // use this for markup output - ostream_t& operator << (const char* str) - { - if(!str) return *this; - while( *str ) T::push(*str++); - return *this; - } - - ostream_t& operator << (char c) - { - T::push(c); return *this; - } - - // intended to handle only ascii-7 strings - // use this for markup output - ostream_t& operator << (const WCHAR* str) - { - if(!str || !str[0]) return *this; - T::push(str,wcslen(str)); return *this; - } - - ostream_t& operator << (WCHAR c) - { - T::push(c); return *this; - } - }; - - // wostream - a.k.a. wstring builder - buffer for dynamic composition of WCHAR strings - typedef ostream_t wostream; -} - -#endif -#endif +#ifndef __sciter_aux_h__ +#define __sciter_aux_h__ + +#if defined(__cplusplus) && !defined( PLAIN_API_ONLY ) + +/* + * Terra Informatica Sciter and HTMLayout Engines + * http://terrainformatica.com/sciter, http://terrainformatica.com/htmlayout + * + * basic primitives. + * + * The code and information provided "as-is" without + * warranty of any kind, either expressed or implied. + * + * (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com) + */ + +/**\file + * \brief primitives + **/ + +/* + + pod::copy - memcpy wrapper + pod::move - memmove wrapper + pod::buffer - dynamic buffer, string builder, etc. + + utf8::towcs() - utf8 to WCHAR* converter + utf8::fromwcs() - WCHAR* to utf8 converter + utf8::ostream - raw ASCII/UNICODE -> UTF8 converter + utf8::oxstream - ASCII/UNICODE -> UTF8 converter with XML support + + inline bool streq(const char* s, const char* s1) - NULL safe string comparison function + inline bool wcseq(const WCHAR* s, const WCHAR* s1) - NULL safe wide string comparison function + inline bool streqi(const char* s, const char* s1) - the same, but case independent + inline bool wcseqi(const WCHAR* s, const WCHAR* s1) - the same, but case independent + + w2a - helper object for const WCHAR* to const char* conversion + a2w - helper object for const char* to const WCHAR* conversion + w2utf - helper object for const WCHAR* to utf8 conversion + utf2w - helper object for utf8 to const WCHAR* conversion + + t2w - const TCHAR* to const WCHAR* conversion, #definition + w2t - const WCHAR* to const TCHAR* conversion, #definition + + itoa, itow - int to const char* converter + atoi, wtoi - const char* to int converter (parser) + ftoa, ftow - double to const char* converter + + + */ + +#pragma once + +#include +#include +#include +#include +#include +#include // std::reverse +#include "aux-platform.h" +#include "aux-slice.h" + +#include +#include + +// disable that warnings in VC 2005 +#pragma warning(disable:4786) //identifier was truncated... +#pragma warning(disable:4100) //unreferenced formal parameter + +#ifndef BYTE + typedef unsigned char BYTE; +#endif + +//#include "aux-slice.h" + +// WARNING: macros below must be used only for passing parameters to functions! + +/* +#if !defined(W2A) // WCHAR to multi-BYTE string converter (current locale) +#define W2A aux::w2a +#endif + +#if !defined(A2W) // multi-BYTE to WCHAR string converter (current locale) +#define A2W aux::a2w +#endif + +#if !defined(UTF2W) // utf-8 to WCHAR string converter +#define UTF2W aux::utf2w +#endif + +#if !defined(W2UTF) // WCHAR to utf-8 string converter +#define W2UTF aux::w2utf +#endif + +#if !defined(W2T) +#if !defined(UNICODE) +#define W2T(S) aux::w2a(S) +#else +#define W2T(S) (S) +#endif +#endif + +#if !defined(T2W) +#if !defined(UNICODE) +#define T2W(S) aux::a2w(S) +#else +#define T2W(S) (S) +#endif +#endif + +#if !defined(A2T) +#if !defined(UNICODE) +#define A2T(S) (S) +#else +#define A2T(S) aux::a2w(S) +#endif +#endif + +#if !defined(T2A) +#if !defined(UNICODE) +#define T2A(S) (S) +#else +#define T2A(S) aux::w2a(S) +#endif +#endif + +*/ + +#ifdef UNICODE +#define a2t( S ) aux::a2w(S) +#define t2a( S ) aux::w2a(S) +#define w2t( S ) (S) +#define t2w( S ) (S) +#define t2i( S ) aux::wtoi(S,0) +#define i2t( S ) aux::itow(S) +#else +#define a2t( S ) (S) +#define t2a( S ) (S) +#define w2t( S ) aux::w2a(S) +#define t2w( S ) aux::a2w(S) +#define t2i( S ) aux::atoi(S,0) +#define i2t( S ) aux::itoa(S) +#endif + +#define w2u( S ) aux::w2utf(S) +#define u2w( S ) aux::utf2w(S) + +#define i2a( I ) aux::itoa(I) +#define i2w( I ) aux::itow(I) + +inline void* zalloc ( size_t sz) +{ + void* p = malloc(sz); + if(p) memset(p,0,sz); + return p; +} + +//elements in array literal +#define ITEMS_IN(a) (sizeof(a)/sizeof(a[0])) +//chars in sting literal +#define CHARS_IN(s) (sizeof(s) / sizeof(s[0]) - 1) + +/**pod namespace - POD primitives. **/ +namespace pod +{ + template void copy ( T* dst, const T* src, size_t nelements) + { + memcpy(dst,src,nelements*sizeof(T)); + } + template void move ( T* dst, const T* src, size_t nelements) + { + memmove(dst,src,nelements*sizeof(T)); + } + + /** buffer - in-memory dynamic buffer implementation. **/ + template + class buffer + { + T* _body; + size_t _allocated; + size_t _size; + + T* reserve(size_t size) + { + size_t newsize = _size + size; + if( newsize > _allocated ) + { + _allocated = (_allocated * 3) / 2; + if(_allocated < newsize) _allocated = newsize; + T *newbody = new T[_allocated]; + copy(newbody,_body,_size); + delete[] _body; + _body = newbody; + } + return _body + _size; + } + + public: + + buffer():_size(0) { _body = new T[_allocated = 256]; } + ~buffer() { delete[] _body; } + + const T * data() const + { + buffer* self = const_cast(this); + if(_size == _allocated) self->reserve(1); + self->_body[_size] = 0; return _body; + } + + size_t length() const { return _size; } + + void push(T c) { *reserve(1) = c; ++_size; } + void push(const T *pc, size_t sz) { copy(reserve(sz),pc,sz); _size += sz; } + + void clear() { _size = 0; } + + }; + + typedef buffer byte_buffer; + typedef buffer wchar_buffer; + typedef buffer char_buffer; +} + +namespace utf8 +{ + // convert utf8 code unit sequence to WCHAR sequence + + inline bool towcs(const BYTE *utf8, size_t length, pod::wchar_buffer& outbuf) + { + if(!utf8 || length == 0) return true; + const BYTE* pc = (const BYTE*)utf8; + const BYTE* last = pc + length; + unsigned int b; + unsigned int num_errors = 0; + while (pc < last) + { + b = *pc++; + + if( !b ) break; // 0 - is eos in all utf encodings + + if ((b & 0x80) == 0) + { + // 1-BYTE sequence: 000000000xxxxxxx = 0xxxxxxx + ; + } + else if ((b & 0xe0) == 0xc0) + { + // 2-BYTE sequence: 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx + if(pc == last) { outbuf.push('?'); ++num_errors; break; } + b = (b & 0x1f) << 6; + b |= (*pc++ & 0x3f); + } + else if ((b & 0xf0) == 0xe0) + { + // 3-BYTE sequence: zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx + if(pc >= last - 1) { outbuf.push('?'); ++num_errors; break; } + + b = (b & 0x0f) << 12; + b |= (*pc++ & 0x3f) << 6; + b |= (*pc++ & 0x3f); + if(b == 0xFEFF && + outbuf.length() == 0) // bom at start + continue; // skip it + } + else if ((b & 0xf8) == 0xf0) + { + // 4-BYTE sequence: 11101110wwwwzzzzyy + 110111yyyyxxxxxx = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx + if(pc >= last - 2) { outbuf.push('?'); break; } + + b = (b & 0x07) << 18; + b |= (*pc++ & 0x3f) << 12; + b |= (*pc++ & 0x3f) << 6; + b |= (*pc++ & 0x3f); + // b shall contain now full 21-bit unicode code point. + assert((b & 0x1fffff) == b); + if((b & 0x1fffff) != b) + { + outbuf.push('?'); + ++num_errors; + continue; + } +#pragma warning( push ) +#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant + //warning C4127: conditional expression is constant + if( sizeof(WCHAR) == 16 ) // Seems like Windows, WCHAR is utf16 code units sequence there. + { + outbuf.push( WCHAR(0xd7c0 + (b >> 10)) ); + outbuf.push( WCHAR(0xdc00 | (b & 0x3ff)) ); + } + else if( sizeof(WCHAR) >= 21 ) // WCHAR is full ucs-4 + { + outbuf.push( WCHAR(b) ); + } + else + { + assert(0); // what? WCHAR is single BYTE here? + } +#pragma warning( pop ) + } + else + { + assert(0); //bad start for UTF-8 multi-BYTE sequence" + ++num_errors; + b = '?'; + } + outbuf.push( WCHAR(b) ); + } + return num_errors == 0; + } + + inline bool fromwcs(const WCHAR* wcs, size_t length, pod::byte_buffer& outbuf) + { + const WCHAR *pc = wcs; + const WCHAR *end = pc + length; + unsigned int num_errors = 0; + for(unsigned int c = *pc; pc < end ; c = *(++pc)) + { + if (c < (1 << 7)) + { + outbuf.push(BYTE(c)); + } + else if (c < (1 << 11)) + { + outbuf.push(BYTE((c >> 6) | 0xc0)); + outbuf.push(BYTE((c & 0x3f) | 0x80)); + } + else if (c < (1 << 16)) + { + outbuf.push(BYTE((c >> 12) | 0xe0)); + outbuf.push(BYTE(((c >> 6) & 0x3f) | 0x80)); + outbuf.push(BYTE((c & 0x3f) | 0x80)); + } + else if (c < (1 << 21)) + { + outbuf.push(BYTE((c >> 18) | 0xf0)); + outbuf.push(BYTE(((c >> 12) & 0x3f) | 0x80)); + outbuf.push(BYTE(((c >> 6) & 0x3f) | 0x80)); + outbuf.push(BYTE((c & 0x3f) | 0x80)); + } + else + ++num_errors; + } + return num_errors == 0; + } + + // UTF8 stream + + // class T must have two methods: + // void push(unsigned char c) + // void push(const unsigned char *pc, size_t sz) + + // bool X - true - XML markup character conversion (characters '<','>',etc). + // false - no conversion at all. + + template + class ostream_t : public T + { + public: + ostream_t() + { + // utf8 BYTE order mark + static unsigned char BOM[] = { 0xEF, 0xBB, 0xBF }; + T::push(BOM, sizeof(BOM)); + } + + // intended to handle only ascii-7 strings + // use this for markup output + ostream_t& operator << (const char* str) + { + T::push((const unsigned char*)str,strlen(str)); return *this; + } + + ostream_t& operator << (char c) + { + T::push((unsigned char)c); return *this; + } + + // use UNICODE chars for value output + ostream_t& operator << (const WCHAR* wstr) + { + const WCHAR *pc = wstr; + for(unsigned int c = *pc; c ; c = *(++pc)) + { + if(X) + switch(c) + { + case '<': *this << "<"; continue; + case '>': *this << ">"; continue; + case '&': *this << "&"; continue; + case '"': *this << """; continue; + case '\'': *this << "'"; continue; + } + if (c < (1 << 7)) + { + T::push (BYTE(c)); + } + else if (c < (1 << 11)) { + T::push (BYTE((c >> 6) | 0xc0)); + T::push (BYTE((c & 0x3f) | 0x80)); + } + else if (c < (1 << 16)) { + T::push (BYTE((c >> 12) | 0xe0)); + T::push (BYTE(((c >> 6) & 0x3f) | 0x80)); + T::push (BYTE((c & 0x3f) | 0x80)); + } + else if (c < (1 << 21)) + { + T::push (BYTE((c >> 18) | 0xf0)); + T::push (BYTE(((c >> 12) & 0x3f) | 0x80)); + T::push (BYTE(((c >> 6) & 0x3f) | 0x80)); + T::push (BYTE((c & 0x3f) | 0x80)); + } + } + return *this; + } + ostream_t& operator << (const std::wstring& str) + { + return *this << (str.c_str()); + } + + }; + + // raw ASCII/UNICODE -> UTF8 converter + typedef ostream_t ostream; + // ASCII/UNICODE -> UTF8 converter with XML support + typedef ostream_t oxstream; + + +} // namespace utf8 + +namespace aux +{ + template struct slice; + + template + inline T + limit ( T v, T minv, T maxv ) + { + assert(minv < maxv); + if (minv >= maxv) + return minv; + if (v > maxv) return maxv; + if (v < minv) return minv; + return v; + } + + // safe string comparison + inline bool streq(const char* s, const char* s1) + { + if( s && s1 ) + return strcmp(s,s1) == 0; + return false; + } + + // safe wide string comparison +/* inline bool wcseq(const WCHAR* s, const WCHAR* s1) + { + if( s && s1 ) + return std::wcscmp(s,s1) == 0; + return false; + } */ + + // safe case independent string comparison + inline bool streqi(const char* s, const char* s1) + { + if( s && s1 ) + + return stricmp(s,s1) == 0; + return false; + } + + // safe case independent wide string comparison +/* inline bool wcseqi(const WCHAR* s, const WCHAR* s1) + { + if( s && s1 ) + return wcsicmp(s,s1) == 0; + return false; + } */ + + // helper convertor objects WCHAR to utf8 and vice versa + class utf2w + { + pod::wchar_buffer buffer; + public: + explicit utf2w(const BYTE* utf8, size_t length = 0) + { + if(utf8) + { + if( length == 0) length = strlen((const char*)utf8); + utf8::towcs(utf8, length ,buffer); + } + } + explicit utf2w(const char* utf8, size_t length = 0) + { + if(utf8) + { + if( length == 0) length = strlen(utf8); + utf8::towcs((const BYTE*)utf8, length ,buffer); + } + } + explicit utf2w(const std::string& utf8) + { + utf8::towcs((const BYTE*)utf8.c_str(), utf8.length() ,buffer); + } + + ~utf2w() {} + + operator const WCHAR*() const { return buffer.data(); } + const WCHAR* c_str() const { return buffer.data(); } + size_t length() const { return buffer.length(); } + + pod::wchar_buffer& get_buffer() { return buffer; } + + operator aux::wchars() const { return aux::wchars(buffer.data(),buffer.length()); } + aux::wchars chars() const { return aux::wchars(buffer.data(),buffer.length()); } + //operator std::basic_string() const { return std::basic_string(buffer.data(),buffer.length()); } + + }; + + class w2utf + { + pod::byte_buffer buffer; + public: + explicit w2utf(const WCHAR* wstr) + { + if(wstr) + { + size_t nu = wcslen(wstr); + utf8::fromwcs(wstr,nu,buffer); + } + } + explicit w2utf(const std::basic_string& str) + { + utf8::fromwcs(str.c_str(),str.length(),buffer); + } + explicit w2utf(wchars str) + { + utf8::fromwcs(str.start,str.length,buffer); + } + ~w2utf() {} + operator const BYTE*() { return buffer.data(); } + operator const char*() { return (const char*)buffer.data(); } + const char* c_str() const { return (const char*)buffer.data(); } + chars operator()() const { return chars(c_str(),length()); } + + size_t length() const { return buffer.length(); } + }; + +#ifdef WINDOWS + + // helper convertor objects WCHAR to ANSI string and vice versa + class w2a + { + char local[16]; + char* buffer; + size_t n; + + void init(const WCHAR* wstr, size_t nu) + { + n = WideCharToMultiByte(CP_ACP,0,wstr,int(nu),0,0,0,0); + buffer = (n < (16-1))? local:new char[n+1]; + WideCharToMultiByte(CP_ACP,0,wstr,int(nu),buffer,int(n),0,0); + buffer[n] = 0; + } + public: + explicit w2a(const WCHAR* wstr):buffer(0),n(0) + { + if(wstr) + init(wstr,wcslen(wstr)); + } + explicit w2a(const std::basic_string& wstr):buffer(0),n(0) + { + init(wstr.c_str(),wstr.length()); + } + explicit w2a(slice s):buffer(0), n(0) + { + init(s.start,s.length); + } + ~w2a() { if(buffer != local) delete[] buffer; } + size_t length() const { return n; } + operator const char*() { return buffer; } + const char* c_str() const { return buffer; } + }; + + class a2w + { + WCHAR local[16]; + WCHAR* buffer; + size_t nu; + void init(const char* str, size_t n) + { +#ifdef _WIN32_WCE + nu = MultiByteToWideChar(CP_ACP,0,str,n,0,0); +#else + nu = MultiByteToWideChar(CP_THREAD_ACP,0,str,int(n),0,0); +#endif + buffer = ( nu < (16-1) )? local: new WCHAR[nu+1]; +#ifdef _WIN32_WCE + MultiByteToWideChar(CP_ACP,0,str,n,buffer,nu); +#else + MultiByteToWideChar(CP_THREAD_ACP,0,str,int(n),buffer,int(nu)); +#endif + buffer[nu] = 0; + } + public: + explicit a2w(const char* str):buffer(0), nu(0) + { + if(str) + init(str, strlen(str)); + } + explicit a2w(slice s):buffer(0), nu(0) + { + init(s.start,s.length); + } + explicit a2w(const std::string& s):buffer(0), nu(0) + { + init(s.c_str(),s.length()); + } + + ~a2w() { if(buffer != local) delete[] buffer; } + size_t length() const { return nu; } + operator const WCHAR*() const { return buffer; } + const WCHAR* c_str() const { return buffer; } + operator aux::wchars() const { return aux::wchars(buffer,nu); } + aux::wchars chars() const { return aux::wchars(buffer,nu); } + //operator std::basic_string() const { return std::basic_string(buffer,nu); } + + }; + + class w2oem + { + char local[64]; + char* buffer; + size_t n; + + void init(const WCHAR* wstr, size_t nu) + { + n = WideCharToMultiByte(CP_OEMCP,0,wstr,int(nu),0,0,0,0); + buffer = (n < (64-1))? local : new char[n+1]; + WideCharToMultiByte(CP_OEMCP,0,wstr,int(nu),buffer,int(n),0,0); + buffer[n] = 0; + } + + w2oem(const w2oem &); + w2oem& operator=(const w2oem &); + + public: + explicit w2oem(const WCHAR* wstr):buffer(0),n(0) + { + local[0] = 0; + if(wstr) + init(wstr,wcslen(wstr)); + } + explicit w2oem(const std::wstring& wstr):buffer(0),n(0) + { + local[0] = 0; + init(wstr.c_str(),wstr.length()); + } + explicit w2oem(slice s); + + ~w2oem() { if(buffer != local) delete[] buffer; } + size_t length() const { return n; } + operator const char*() { return buffer; } + const char* c_str() const { return buffer; } + }; + +#elif defined(UTF8_CHARS) + typedef utf2w a2w; + typedef w2utf w2a; + typedef utf2w oem2w; + typedef w2utf w2oem; +#else + #error "unknown char string representation" +#endif + + /** Integer to string converter. + Use it as wostream << itow(234) + **/ + +template + class itot + { + CT buffer[38]; + public: + itot(int n, int radix = 10) + { + static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + CT* wstr = buffer; + if (radix < 2 || radix > 35) { *wstr = 0; return; } // validate radix + int sign = n; if (sign < 0) n = -n; + do { *wstr++ = num[n % radix]; } while( n /= radix ); // conversion. number is reversed. + if(sign<0) *wstr++ ='-'; + *wstr = 0; + // reverse the string + std::reverse(buffer,wstr); + } + operator const CT*() { return buffer; } + }; + + typedef itot itoa; + typedef itot itow; + + + /** Float to string converter. + Use it as ostream << ftoa(234.1); or + Use it as ostream << ftoa(234.1,"pt"); or + **/ + class ftoa + { + char buffer[64]; + public: + ftoa(double d, const char* units = "", int fractional_digits = 1) + { + snprintf(buffer, sizeof(buffer), "%.*f%s", fractional_digits, d, units ); + buffer[63] = 0; + } + operator const char*() { return buffer; } + }; + + /** Float to wstring converter. + Use it as wostream << ftow(234.1); or + Use it as wostream << ftow(234.1,"pt"); or + **/ + /*class ftow + { + WCHAR buffer[64]; + public: + ftow(double d, const WCHAR* units = "", int fractional_digits = 1) + { +#ifdef WINDOWS + _snwprintf_s(buffer, 64, L"%.*f%s", fractional_digits, d, units ); +#else + swprintf(buffer, 64, L"%.*f%s", fractional_digits, d, units ); +#endif + buffer[63] = 0; + } + operator const WCHAR*() { return buffer; } + };*/ + + /** string to integer parser. **/ + inline int atoi(const char *s, int default_value = 0) + { + if( !s ) return default_value; + char *lastptr; + long i = strtol( s, &lastptr, 10 ); + return (lastptr != s)? (int)i : default_value; + } + + /** wstring to integer parser. **/ + inline int wtoi(const WCHAR *s, int default_value = 0) + { + w2a at(s); + return atoi(at.c_str(),default_value); + } + + // class T must have two methods: + // void push(WCHAR c) + // void push(const WCHAR *pc, size_t sz) + template + class ostream_t : public T + { + public: + ostream_t() {} + + // intended to handle only ascii-7 strings + // use this for markup output + ostream_t& operator << (const char* str) + { + if(!str) return *this; + while( *str ) T::push(*str++); + return *this; + } + + ostream_t& operator << (char c) + { + T::push(c); return *this; + } + + // intended to handle only ascii-7 strings + // use this for markup output + ostream_t& operator << (const WCHAR* str) + { + if(!str || !str[0]) return *this; + T::push(str,wcslen(str)); return *this; + } + + ostream_t& operator << (WCHAR c) + { + T::push(c); return *this; + } + }; + + // wostream - a.k.a. wstring builder - buffer for dynamic composition of WCHAR strings + typedef ostream_t wostream; +} + +#endif +#endif diff --git a/include/aux-platform.h b/include/aux-platform.h index 30e995f..97dd011 100644 --- a/include/aux-platform.h +++ b/include/aux-platform.h @@ -1,55 +1,55 @@ -#ifndef __aux_platform_h__ -#define __aux_platform_h__ - -/* - * Terra Informatica Sciter and HTMLayout Engines - * http://terrainformatica.com/sciter, http://terrainformatica.com/htmlayout - * - * platform primitives. - * - * The code and information provided "as-is" without - * warranty of any kind, either expressed or implied. - * - * (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com) - */ - - -#if defined(_WIN32_WCE) || defined(UNDER_CE) - #define PLATFORM_WINCE - #define WINDOWS -#elif defined(WIN64) || defined(_WIN64) || defined(_M_X64) - #define PLATFORM_DESKTOP - #define WINDOWS - #define X64BITS -#elif defined(WIN32) || defined(_WIN32) - #define PLATFORM_DESKTOP - #define WINDOWS -#elif defined(__APPLE__) - #define PLATFORM_OSX - #define OSX - #define UTF8_CHARS // const char* is UTF8 sequence - #ifdef __x86_64__ - #define X64BITS - #endif - #define POSIX -#elif defined( __linux__ ) - #define PLATFORM_LINUX - #define LINUX - #ifdef __x86_64__ - #define X64BITS - #endif - #define POSIX - #define UTF8_CHARS // const char* is UTF8 sequence -#else - #error "Unknown platform" -#endif - -#if defined(WINDOWS) - #define stricmp _stricmp - #define wcsicmp _wcsicmp -#elif defined(POSIX) - #define stricmp strcasecmp - #define wcsicmp wcscasecmp -#endif - -#endif +#ifndef __aux_platform_h__ +#define __aux_platform_h__ + +/* + * Terra Informatica Sciter and HTMLayout Engines + * http://terrainformatica.com/sciter, http://terrainformatica.com/htmlayout + * + * platform primitives. + * + * The code and information provided "as-is" without + * warranty of any kind, either expressed or implied. + * + * (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com) + */ + + +#if defined(_WIN32_WCE) || defined(UNDER_CE) + #define PLATFORM_WINCE + #define WINDOWS +#elif defined(WIN64) || defined(_WIN64) || defined(_M_X64) + #define PLATFORM_DESKTOP + #define WINDOWS + #define X64BITS +#elif defined(WIN32) || defined(_WIN32) + #define PLATFORM_DESKTOP + #define WINDOWS +#elif defined(__APPLE__) + #define PLATFORM_OSX + #define OSX + #define UTF8_CHARS // const char* is UTF8 sequence + #ifdef __x86_64__ + #define X64BITS + #endif + #define POSIX +#elif defined( __linux__ ) + #define PLATFORM_LINUX + #define LINUX + #ifdef __x86_64__ + #define X64BITS + #endif + #define POSIX + #define UTF8_CHARS // const char* is UTF8 sequence +#else + #error "Unknown platform" +#endif + +#if defined(WINDOWS) + #define stricmp _stricmp + #define wcsicmp _wcsicmp +#elif defined(POSIX) + #define stricmp strcasecmp + #define wcsicmp wcscasecmp +#endif + +#endif diff --git a/include/aux-slice.h b/include/aux-slice.h index 92f489e..cc8744f 100644 --- a/include/aux-slice.h +++ b/include/aux-slice.h @@ -1,492 +1,492 @@ -#ifndef __aux_slice_h__ -#define __aux_slice_h__ - -#if defined(__cplusplus) && !defined( PLAIN_API_ONLY ) - -/* - * Terra Informatica Sciter and HTMLayout Engines - * http://terrainformatica.com/sciter, http://terrainformatica.com/htmlayout - * - * slice - range of elements, start/length. That is what is known in D as array. - * - * The code and information provided "as-is" without - * warranty of any kind, either expressed or implied. - * - * (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com) - */ - -/**\file - * \brief range of elements - **/ - -#include -#include "limits.h" -#include -#include "sciter-x-types.h" - -namespace aux -{ - - inline bool is_space( char c ) { return isspace(c & 0xff) != 0; } - inline bool is_space( WCHAR c ) { return iswspace(c) != 0; } - - inline bool is_digit( char c ) { return isdigit(c & 0xff) != 0; } - inline bool is_digit( WCHAR c ) { return iswdigit(c) != 0; } - - inline bool is_xdigit( char c ) { return isdigit(c & 0xff) != 0; } - inline bool is_xdigit( WCHAR c ) { return iswxdigit(c) != 0; } - - inline bool is_alpha( char c ) { return isalpha(c & 0xff) != 0; } - inline bool is_alpha( WCHAR c ) { return iswalpha(c) != 0; } - - inline bool is_alnum( char c ) { return isalnum(c & 0xff) != 0; } - inline bool is_alnum( WCHAR c ) { return iswalnum(c) != 0; } - - template - inline size_t wcslen( const CT* s ) { const CT *p = s; while (*p) p++; return p - s; } - -template - struct slice - { - const T* start; - unsigned int length; - - slice(): start(0), length(0) {} - slice(const T* start_, size_t length_) { start = start_; length = (unsigned int)length_; } - slice(const slice& src): start(src.start), length(src.length) {} - slice(const std::basic_string& src): start(src.c_str()), length((unsigned int)src.length()) {} - //slice(const T* start_, const T* end_): start(start_), length( max(end_-start_,0)) {} - - slice& operator = (const slice& src) { start = src.start; length = src.length; return *this; } - - const T* end() const { return start + length; } - - bool operator == ( const slice& r ) const - { - if( length != r.length ) - return false; - if( start == r.start ) - return true; - for( unsigned int i = 0; i < length; ++i ) - if( start[i] != r.start[i] ) - return false; - return true; - } - - bool operator != ( const slice& r ) const { return !operator==(r); } - - T operator[] ( unsigned int idx ) const - { - assert( idx < length ); - if(idx < length) - return start[idx]; - return 0; - } - - T last() const - { - if(length) - return start[length-1]; - return 0; - } - - // [idx1..length) - slice operator() ( unsigned int idx1 ) const - { - assert( idx1 < length ); - if ( idx1 < length ) - return slice( start + idx1, length - idx1 ); - return slice(); - } - // [idx1..idx2) - slice operator() ( unsigned int idx1, unsigned int idx2 ) const - { - assert( idx1 < length ); - assert( idx2 <= length ); - assert( idx1 <= idx2 ); - if ( idx1 < idx2 ) - return slice( start + idx1, idx2 - idx1 ); - return slice(); - } - - int index_of( T e ) const - { - for( unsigned int i = 0; i < length; ++i ) if( start[i] == e ) return i; - return -1; - } - - int last_index_of( T e ) const - { - for( unsigned int i = length; i > 0 ;) if( start[--i] == e ) return i; - return -1; - } - - int index_of( const slice& s ) const - { - if( s.length > length ) return -1; - if( s.length == 0 ) return -1; - unsigned int l = length - s.length; - for( unsigned int i = 0; i < l ; ++i) - if( start[i] == *s.start ) - { - const T* p = s.start; - unsigned int last = i + s.length; - for( unsigned int j = i + 1; j < last; ++j ) - if( *(++p) != start[j]) - goto next_i; - return i; - next_i: continue; - } - return -1; - } - - int last_index_of( const slice& s ) const - { - if( s.length > length ) return -1; - if( s.length == 0 ) return -1; - const T* ps = s.end() - 1; - for( unsigned int i = length; i > 0 ; ) - if( start[--i] == *ps ) - { - const T* p = ps; - unsigned int j, first = i - s.length + 1; - for( j = i; j > first; ) - if( *(--p) != start[--j]) - goto next_i; - return j; - next_i: continue; - } - return -1; - } - - void prune(unsigned int from_start, unsigned int from_end = 0) - { - unsigned int s = from_start >= length? length : from_start; - unsigned int e = length - (from_end >= length? length: from_end); - start += s; - if( s < e ) length = e-s; - else length = 0; - } - - - bool like(const T* pattern) const; - - }; - - #define MAKE_SLICE( T, D ) slice(D, sizeof(D) / sizeof(D[0])) - - #ifdef _DEBUG - - inline void slice_unittest() - { - int v1[] = { 0,1,2,3,4,5,6,7,8,9 }; - int v2[] = { 3,4,5 }; - int v3[] = { 0,1,2 }; - int v4[] = { 0,1,2,4 }; - int v5[] = { 1,1,2,3 }; - - slice s1 = MAKE_SLICE( int, v1 ); - slice s2 = MAKE_SLICE( int, v2 ); - slice s3 = MAKE_SLICE( int, v3 ); - slice s4 = MAKE_SLICE( int, v4 ); - slice s5 = MAKE_SLICE( int, v5 ); - - assert( s1 != s2 ); - assert( s1(3,6) == s2 ); - assert( s1.index_of(3) == 3 ); - assert( s1.index_of(s2) == 3 ); - assert( s1.last_index_of(3) == 3 ); - assert( s1.last_index_of(s2) == 3 ); - - assert( s1.index_of(s3) == 0 ); - assert( s1.last_index_of(s3) == 0 ); - - assert( s1.index_of(s4) == -1 ); - assert( s1.last_index_of(s4) == -1 ); - - assert( s1.index_of(s5) == -1 ); - assert( s1.last_index_of(s5) == -1 ); - - } - - #endif - - template - inline slice trim_left(slice str) - { - for( unsigned i = 0; i < str.length; ++i ) - if( is_space(str[0]) ) { ++str.start; --str.length; } - else break; - return str; - } - - template - inline slice trim_right(slice str) - { - for( int j = int(str.length) - 1; j >= 0; --j ) - if( is_space(str[j]) ) --str.length; - else break; - return str; - } - - template - inline slice trim(slice str) - { - return trim_right(trim_left(str)); - } - - typedef slice chars; - typedef slice wchars; - typedef slice bytes; - - - // Note: CS here is a string literal! - #define const_chars(CS) aux::slice(CS,CHARS_IN(CS)) - #define const_wchars(CS) aux::slice(WSTR(CS),CHARS_IN(_WSTR(CS))) - - inline wchars chars_of( const WCHAR *t ) { return t? wchars(t,(unsigned int)wcslen(t)):wchars(); } - inline chars chars_of( const char *t ) { return t? chars(t,(unsigned int)strlen(t)):chars(); } - - - - template - slice chars_of( const std::basic_string &s ) { return slice(s.c_str(), s.length()); } - - template - slice elements_of( const std::vector &s ) { return slice(s.cbegin(), s.size()); } - - template - slice elements_of(T (& arr)[size]){ return slice(&arr[0],size);} - - template - slice elements_of(const T (& arr)[size]){ return slice(&arr[0],size);} - - template - std::basic_string make_string( aux::slice s ) { return std::basic_string(s.start, s.length); } - - // simple tokenizer - template - class tokens - { - const T* delimeters; - const T* p; - const T* tail; - const T* start; - const T* end; - const bool is_delimeter(T el) { for(const T* t = delimeters;t && *t; ++t) if(el == *t) return true; return false; } - const T* tok() { for(;p < tail; ++p) if(is_delimeter(*p)) return p++; return p; } - public: - - tokens(const T *text, size_t text_length, const T* separators): delimeters(separators) - { - start = p = text; - tail = p + text_length; - end = tok(); - } - - tokens(const aux::slice s, const T* separators): delimeters(separators) - { - start = p = s.start; - tail = p + s.length; - end = tok(); - } - - bool next(slice& v) - { - if(start < tail) - { - v.start = start; - v.length = unsigned(end - start); - start = p; - end = tok(); - return true; - } - return false; - } - }; - - typedef tokens atokens; - typedef tokens wtokens; - - - /****************************************************************************/ - // - // idea was taken from Konstantin Knizhnik's FastDB - // see http://www.garret.ru/ - // extended by [] operations - // - - template - struct charset - { - #define SET_SIZE (1 << (sizeof(CT) * CHAR_BIT)) - #define SIGNIFICANT_BITS_MASK unsigned( SET_SIZE - 1 ) - - unsigned char codes[ SET_SIZE / CHAR_BIT ]; - - unsigned charcode(CT c) // proper unsigned_cast - { - return SIGNIFICANT_BITS_MASK & unsigned(c); - } - - private: - void set ( CT from, CT to, bool v ) - { - for ( unsigned i = charcode(from); i <= charcode(to); ++i ) - { - unsigned int bit = i & 7; - unsigned int octet = i >> 3; - if( v ) codes[octet] |= 1 << bit; else codes[octet] &= ~(1 << bit); - } - } - void init ( unsigned char v ) { memset(codes,v,(SET_SIZE >> 3)); } - public: - - void parse ( const CT* &pp ) - { - //assert( sizeof(codes) == sizeof(CT) * sizeof(bool)); - const CT *p = (const CT *) pp; - unsigned char inv = *p == '^'? 0xff:0; - if ( inv ) { ++p; } - init ( inv ); - if ( *p == sep ) set(sep,sep,inv == 0); - while ( *p ) - { - if ( p[0] == end ) { p++; break; } - if ( p[1] == sep && p[2] != 0 ) { set (p[0], p[2], inv == 0 ); p += 3; } - else { CT t = *p++; set(t,t, inv == 0); } - } - pp = (const CT *) p; - } - - bool valid ( CT c ) - { - unsigned int bit = charcode(c) & 7; - unsigned int octet = charcode(c) >> 3; - return (codes[octet] & (1 << bit)) != 0; - } - #undef SET_SIZE - #undef SIGNIFICANT_BITS_MASK - }; - - template - inline int match ( slice cr, const CT *pattern ) - { - const CT AnySubstring = '*'; - const CT AnyOneChar = '?'; - const CT AnyOneDigit = '#'; - - const CT *str = cr.start; - const CT *wildcard = 0; - const CT *strpos = 0; - const CT *matchpos = 0; - - charset cset; - - for (;;) - { - if ( *pattern == AnySubstring ) - { - wildcard = ++pattern; - strpos = str; - if ( !matchpos ) matchpos = str; - } - else if ( *str == '\0' || str >= cr.end() ) - { - return ( *pattern == '\0' ) ? int( matchpos - cr.start ) : -1; - } - else if ( *pattern == '[' ) - { - pattern++; - cset.parse ( pattern ); - if ( !cset.valid ( *str ) ) - return -1; - if ( !matchpos ) - matchpos = str; - str += 1; - } - else if ( *str == *pattern || *pattern == AnyOneChar ) - { - if ( !matchpos ) matchpos = str; - str += 1; - pattern += 1; - } - else if ( *str == *pattern || *pattern == AnyOneDigit ) - { - if ( !is_digit(*str )) return -1; - if ( !matchpos ) matchpos = str; - str += 1; - pattern += 1; - } - else if ( wildcard ) - { - str = ++strpos; - pattern = wildcard; - } - else - break; - } - return -1; - } - - template - inline bool slice::like ( const T *pattern ) const - { - return match(*this,pattern) >= 0; - } - - // chars to unsigned int - // chars to int - - template - inline unsigned int to_uint(slice& span, unsigned int base = 10) - { - unsigned int result = 0,value; - const T *cp = span.start; - const T *pend = span.end(); - - while ( cp < pend && is_space(*cp) ) ++cp; - - if (!base) - { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((toupper(*cp) == 'X') && is_xdigit(cp[1])) { - cp++; - base = 16; - } - } - } - else if (base == 16) - { - if (cp[0] == '0' && toupper(cp[1]) == 'X') - cp += 2; - } - while ( cp < pend && is_xdigit(*cp) && - (value = is_digit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - span.length = (unsigned int)(cp - span.start); - return result; - } - - template - int to_int(slice& span, unsigned int base = 10) - { - - while (span.length > 0 && is_space(span[0]) ) { ++span.start; --span.length; } - if(span[0] == '-') - { - ++span.start; --span.length; - return - int(to_uint(span,base)); - } - return to_uint(span,base); - } - -} - -#endif -#endif +#ifndef __aux_slice_h__ +#define __aux_slice_h__ + +#if defined(__cplusplus) && !defined( PLAIN_API_ONLY ) + +/* + * Terra Informatica Sciter and HTMLayout Engines + * http://terrainformatica.com/sciter, http://terrainformatica.com/htmlayout + * + * slice - range of elements, start/length. That is what is known in D as array. + * + * The code and information provided "as-is" without + * warranty of any kind, either expressed or implied. + * + * (C) 2003-2015, Andrew Fedoniouk (andrew@terrainformatica.com) + */ + +/**\file + * \brief range of elements + **/ + +#include +#include "limits.h" +#include +#include "sciter-x-types.h" + +namespace aux +{ + + inline bool is_space( char c ) { return isspace(c & 0xff) != 0; } + inline bool is_space( WCHAR c ) { return iswspace(c) != 0; } + + inline bool is_digit( char c ) { return isdigit(c & 0xff) != 0; } + inline bool is_digit( WCHAR c ) { return iswdigit(c) != 0; } + + inline bool is_xdigit( char c ) { return isdigit(c & 0xff) != 0; } + inline bool is_xdigit( WCHAR c ) { return iswxdigit(c) != 0; } + + inline bool is_alpha( char c ) { return isalpha(c & 0xff) != 0; } + inline bool is_alpha( WCHAR c ) { return iswalpha(c) != 0; } + + inline bool is_alnum( char c ) { return isalnum(c & 0xff) != 0; } + inline bool is_alnum( WCHAR c ) { return iswalnum(c) != 0; } + + template + inline size_t wcslen( const CT* s ) { const CT *p = s; while (*p) p++; return p - s; } + +template + struct slice + { + const T* start; + unsigned int length; + + slice(): start(0), length(0) {} + slice(const T* start_, size_t length_) { start = start_; length = (unsigned int)length_; } + slice(const slice& src): start(src.start), length(src.length) {} + slice(const std::basic_string& src): start(src.c_str()), length((unsigned int)src.length()) {} + //slice(const T* start_, const T* end_): start(start_), length( max(end_-start_,0)) {} + + slice& operator = (const slice& src) { start = src.start; length = src.length; return *this; } + + const T* end() const { return start + length; } + + bool operator == ( const slice& r ) const + { + if( length != r.length ) + return false; + if( start == r.start ) + return true; + for( unsigned int i = 0; i < length; ++i ) + if( start[i] != r.start[i] ) + return false; + return true; + } + + bool operator != ( const slice& r ) const { return !operator==(r); } + + T operator[] ( unsigned int idx ) const + { + assert( idx < length ); + if(idx < length) + return start[idx]; + return 0; + } + + T last() const + { + if(length) + return start[length-1]; + return 0; + } + + // [idx1..length) + slice operator() ( unsigned int idx1 ) const + { + assert( idx1 < length ); + if ( idx1 < length ) + return slice( start + idx1, length - idx1 ); + return slice(); + } + // [idx1..idx2) + slice operator() ( unsigned int idx1, unsigned int idx2 ) const + { + assert( idx1 < length ); + assert( idx2 <= length ); + assert( idx1 <= idx2 ); + if ( idx1 < idx2 ) + return slice( start + idx1, idx2 - idx1 ); + return slice(); + } + + int index_of( T e ) const + { + for( unsigned int i = 0; i < length; ++i ) if( start[i] == e ) return i; + return -1; + } + + int last_index_of( T e ) const + { + for( unsigned int i = length; i > 0 ;) if( start[--i] == e ) return i; + return -1; + } + + int index_of( const slice& s ) const + { + if( s.length > length ) return -1; + if( s.length == 0 ) return -1; + unsigned int l = length - s.length; + for( unsigned int i = 0; i < l ; ++i) + if( start[i] == *s.start ) + { + const T* p = s.start; + unsigned int last = i + s.length; + for( unsigned int j = i + 1; j < last; ++j ) + if( *(++p) != start[j]) + goto next_i; + return i; + next_i: continue; + } + return -1; + } + + int last_index_of( const slice& s ) const + { + if( s.length > length ) return -1; + if( s.length == 0 ) return -1; + const T* ps = s.end() - 1; + for( unsigned int i = length; i > 0 ; ) + if( start[--i] == *ps ) + { + const T* p = ps; + unsigned int j, first = i - s.length + 1; + for( j = i; j > first; ) + if( *(--p) != start[--j]) + goto next_i; + return j; + next_i: continue; + } + return -1; + } + + void prune(unsigned int from_start, unsigned int from_end = 0) + { + unsigned int s = from_start >= length? length : from_start; + unsigned int e = length - (from_end >= length? length: from_end); + start += s; + if( s < e ) length = e-s; + else length = 0; + } + + + bool like(const T* pattern) const; + + }; + + #define MAKE_SLICE( T, D ) slice(D, sizeof(D) / sizeof(D[0])) + + #ifdef _DEBUG + + inline void slice_unittest() + { + int v1[] = { 0,1,2,3,4,5,6,7,8,9 }; + int v2[] = { 3,4,5 }; + int v3[] = { 0,1,2 }; + int v4[] = { 0,1,2,4 }; + int v5[] = { 1,1,2,3 }; + + slice s1 = MAKE_SLICE( int, v1 ); + slice s2 = MAKE_SLICE( int, v2 ); + slice s3 = MAKE_SLICE( int, v3 ); + slice s4 = MAKE_SLICE( int, v4 ); + slice s5 = MAKE_SLICE( int, v5 ); + + assert( s1 != s2 ); + assert( s1(3,6) == s2 ); + assert( s1.index_of(3) == 3 ); + assert( s1.index_of(s2) == 3 ); + assert( s1.last_index_of(3) == 3 ); + assert( s1.last_index_of(s2) == 3 ); + + assert( s1.index_of(s3) == 0 ); + assert( s1.last_index_of(s3) == 0 ); + + assert( s1.index_of(s4) == -1 ); + assert( s1.last_index_of(s4) == -1 ); + + assert( s1.index_of(s5) == -1 ); + assert( s1.last_index_of(s5) == -1 ); + + } + + #endif + + template + inline slice trim_left(slice str) + { + for( unsigned i = 0; i < str.length; ++i ) + if( is_space(str[0]) ) { ++str.start; --str.length; } + else break; + return str; + } + + template + inline slice trim_right(slice str) + { + for( int j = int(str.length) - 1; j >= 0; --j ) + if( is_space(str[j]) ) --str.length; + else break; + return str; + } + + template + inline slice trim(slice str) + { + return trim_right(trim_left(str)); + } + + typedef slice chars; + typedef slice wchars; + typedef slice bytes; + + + // Note: CS here is a string literal! + #define const_chars(CS) aux::slice(CS,CHARS_IN(CS)) + #define const_wchars(CS) aux::slice(WSTR(CS),CHARS_IN(_WSTR(CS))) + + inline wchars chars_of( const WCHAR *t ) { return t? wchars(t,(unsigned int)wcslen(t)):wchars(); } + inline chars chars_of( const char *t ) { return t? chars(t,(unsigned int)strlen(t)):chars(); } + + + + template + slice chars_of( const std::basic_string &s ) { return slice(s.c_str(), s.length()); } + + template + slice elements_of( const std::vector &s ) { return slice(s.cbegin(), s.size()); } + + template + slice elements_of(T (& arr)[size]){ return slice(&arr[0],size);} + + template + slice elements_of(const T (& arr)[size]){ return slice(&arr[0],size);} + + template + std::basic_string make_string( aux::slice s ) { return std::basic_string(s.start, s.length); } + + // simple tokenizer + template + class tokens + { + const T* delimeters; + const T* p; + const T* tail; + const T* start; + const T* end; + const bool is_delimeter(T el) { for(const T* t = delimeters;t && *t; ++t) if(el == *t) return true; return false; } + const T* tok() { for(;p < tail; ++p) if(is_delimeter(*p)) return p++; return p; } + public: + + tokens(const T *text, size_t text_length, const T* separators): delimeters(separators) + { + start = p = text; + tail = p + text_length; + end = tok(); + } + + tokens(const aux::slice s, const T* separators): delimeters(separators) + { + start = p = s.start; + tail = p + s.length; + end = tok(); + } + + bool next(slice& v) + { + if(start < tail) + { + v.start = start; + v.length = unsigned(end - start); + start = p; + end = tok(); + return true; + } + return false; + } + }; + + typedef tokens atokens; + typedef tokens wtokens; + + + /****************************************************************************/ + // + // idea was taken from Konstantin Knizhnik's FastDB + // see http://www.garret.ru/ + // extended by [] operations + // + + template + struct charset + { + #define SET_SIZE (1 << (sizeof(CT) * CHAR_BIT)) + #define SIGNIFICANT_BITS_MASK unsigned( SET_SIZE - 1 ) + + unsigned char codes[ SET_SIZE / CHAR_BIT ]; + + unsigned charcode(CT c) // proper unsigned_cast + { + return SIGNIFICANT_BITS_MASK & unsigned(c); + } + + private: + void set ( CT from, CT to, bool v ) + { + for ( unsigned i = charcode(from); i <= charcode(to); ++i ) + { + unsigned int bit = i & 7; + unsigned int octet = i >> 3; + if( v ) codes[octet] |= 1 << bit; else codes[octet] &= ~(1 << bit); + } + } + void init ( unsigned char v ) { memset(codes,v,(SET_SIZE >> 3)); } + public: + + void parse ( const CT* &pp ) + { + //assert( sizeof(codes) == sizeof(CT) * sizeof(bool)); + const CT *p = (const CT *) pp; + unsigned char inv = *p == '^'? 0xff:0; + if ( inv ) { ++p; } + init ( inv ); + if ( *p == sep ) set(sep,sep,inv == 0); + while ( *p ) + { + if ( p[0] == end ) { p++; break; } + if ( p[1] == sep && p[2] != 0 ) { set (p[0], p[2], inv == 0 ); p += 3; } + else { CT t = *p++; set(t,t, inv == 0); } + } + pp = (const CT *) p; + } + + bool valid ( CT c ) + { + unsigned int bit = charcode(c) & 7; + unsigned int octet = charcode(c) >> 3; + return (codes[octet] & (1 << bit)) != 0; + } + #undef SET_SIZE + #undef SIGNIFICANT_BITS_MASK + }; + + template + inline int match ( slice cr, const CT *pattern ) + { + const CT AnySubstring = '*'; + const CT AnyOneChar = '?'; + const CT AnyOneDigit = '#'; + + const CT *str = cr.start; + const CT *wildcard = 0; + const CT *strpos = 0; + const CT *matchpos = 0; + + charset cset; + + for (;;) + { + if ( *pattern == AnySubstring ) + { + wildcard = ++pattern; + strpos = str; + if ( !matchpos ) matchpos = str; + } + else if ( *str == '\0' || str >= cr.end() ) + { + return ( *pattern == '\0' ) ? int( matchpos - cr.start ) : -1; + } + else if ( *pattern == '[' ) + { + pattern++; + cset.parse ( pattern ); + if ( !cset.valid ( *str ) ) + return -1; + if ( !matchpos ) + matchpos = str; + str += 1; + } + else if ( *str == *pattern || *pattern == AnyOneChar ) + { + if ( !matchpos ) matchpos = str; + str += 1; + pattern += 1; + } + else if ( *str == *pattern || *pattern == AnyOneDigit ) + { + if ( !is_digit(*str )) return -1; + if ( !matchpos ) matchpos = str; + str += 1; + pattern += 1; + } + else if ( wildcard ) + { + str = ++strpos; + pattern = wildcard; + } + else + break; + } + return -1; + } + + template + inline bool slice::like ( const T *pattern ) const + { + return match(*this,pattern) >= 0; + } + + // chars to unsigned int + // chars to int + + template + inline unsigned int to_uint(slice& span, unsigned int base = 10) + { + unsigned int result = 0,value; + const T *cp = span.start; + const T *pend = span.end(); + + while ( cp < pend && is_space(*cp) ) ++cp; + + if (!base) + { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((toupper(*cp) == 'X') && is_xdigit(cp[1])) { + cp++; + base = 16; + } + } + } + else if (base == 16) + { + if (cp[0] == '0' && toupper(cp[1]) == 'X') + cp += 2; + } + while ( cp < pend && is_xdigit(*cp) && + (value = is_digit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + span.length = (unsigned int)(cp - span.start); + return result; + } + + template + int to_int(slice& span, unsigned int base = 10) + { + + while (span.length > 0 && is_space(span[0]) ) { ++span.start; --span.length; } + if(span[0] == '-') + { + ++span.start; --span.length; + return - int(to_uint(span,base)); + } + return to_uint(span,base); + } + +} + +#endif +#endif diff --git a/include/behaviors/behavior_camera_capture.cpp b/include/behaviors/behavior_camera_capture.cpp index 69546dd..ddd8aad 100644 --- a/include/behaviors/behavior_camera_capture.cpp +++ b/include/behaviors/behavior_camera_capture.cpp @@ -1,95 +1,95 @@ -#include "stdafx.h" -#include "sciter-x-dom.hpp" -#include "sciter-x-behavior.h" - -#if TRUE // change it to FALSE to disable camera functionality - -#include "camera/camera-capture.h" -#include "camera/camera-capture.cpp" - -namespace sciter -{ -/* - -BEHAVIOR: camera_stream - provides video frames from camera -COMMENTS: -