+Ole: SAFEARRAY constructor helpers

+TCore: SQL-style extensions to calculator parser

git-svn-id: svn://ultimatepp.org/upp/trunk@2546 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
rylek 2010-07-19 09:13:47 +00:00
parent 0a4c6b19d4
commit b8050edebb
6 changed files with 217 additions and 66 deletions

View file

@ -258,7 +258,7 @@ bool OcxTypeInfo::CanUnload() const
RDUMP(object_count);
RDUMP(refcount);
RDUMP(lock_count);
return object_count == 0 && refcount <= 1 && lock_count <= 0;
return object_count == 0 && refcount <= 2 && lock_count <= 0;
}
int OcxTypeInfo::IncRef()
@ -718,10 +718,16 @@ void ExeRunServer()
}
LOGSYSOCX("-> registration OK");
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
int ms = msecs();
bool quit = false;
while(!quit) {
if(msecs(ms) >= 2000) {
if(OcxTypeLib::Get().CanUnload())
break;
ms = msecs();
}
if(!Ctrl::ProcessEvent(&quit))
Sleep(10);
}
LOGSYSOCX("end of message loop");
OcxTypeLib::Get().RevokeObjects();

View file

@ -247,12 +247,24 @@ ValueArray SAFEARRAYToValueArray(SAFEARRAY *array)
return SAFEARRAYToValueArrayPart(array, indices.Begin(), ndims - 1);
}
SAFEARRAY * ValueArrayToSAFEARRAY(const ValueArray& varray)
Vector<WString> SAFEARRAYToWStringVector(SAFEARRAY *array)
{
SAFEARRAYBOUND rgsabound;
rgsabound.lLbound = 0;
rgsabound.cElements = varray.GetCount();
SAFEARRAY *a = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
Vector<WString> out;
out.SetCount(array->rgsabound[0].cElements);
Vector<long> indices;
indices.SetCount(array->cDims, 0);
for(int i = 0; i < out.GetCount(); i++) {
OleBstr s;
indices[0] = i;
HRESULT hr = SafeArrayGetElement(array, indices.Begin(), s.Set());
out[i] = s;
}
return out;
}
SAFEARRAY *ToSAFEARRAY(const ValueArray& varray)
{
SAFEARRAY *a = SafeArrayCreateVector(VT_VARIANT, 0, varray.GetCount());
if(!a)
return NULL;
for(long index = 0; index < varray.GetCount(); index++) {
@ -262,6 +274,18 @@ SAFEARRAY * ValueArrayToSAFEARRAY(const ValueArray& varray)
return a;
}
SAFEARRAY *ToSAFEARRAY(const Vector<WString>& vstr)
{
SAFEARRAY *a = SafeArrayCreateVector(VT_BSTR, 0, vstr.GetCount());
if(!a)
return NULL;
for(long index = 0; index < vstr.GetCount(); index++) {
OleBstr var = vstr[(int)index];
SafeArrayPutElement(a, &index, ~var);
}
return a;
}
//////////////////////////////////////////////////////////////////////
// special types

View file

@ -84,6 +84,24 @@ inline String AsString(const Guid& guid) { return Format(~guid); }
inline bool operator == (const Guid& a, const Guid& b) { return ~a == ~b; }
inline bool operator != (const Guid& a, const Guid& b) { return ~a != ~b; }
class OleExc : public Exc
{
public:
OleExc(HRESULT hresult);
OleExc(HRESULT hresult, const char *text);
public:
HRESULT hresult;
};
HRESULT LogResult(HRESULT hr);
HRESULT LogError(HRESULT hr);
inline void OleVerify(HRESULT hr) { if(FAILED(hr)) throw OleExc(hr); }
inline void OleVerify(HRESULT hr, const char *text) { if(FAILED(hr)) throw OleExc(hr, text); }
#define OLE_VERIFY(c) OleVerify(c, #c)
class OleVariant : public VARIANT
{
public:
@ -124,9 +142,29 @@ void ReturnWString(BSTR *dest, WString s);
HRESULT CheckReturnWString(BSTR *bstr, WString s);
ValueArray SAFEARRAYToValueArray(SAFEARRAY *array);
SAFEARRAY *ValueArrayToSAFEARRAY(const ValueArray& varray);
void ReturnValueArray(SAFEARRAY *dest, const ValueArray& array);
HRESULT CheckReturnString(BSTR *bstr, String s);
Vector<WString> SAFEARRAYToWStringVector(SAFEARRAY *array);
SAFEARRAY *ToSAFEARRAY(const ValueArray& varray);
SAFEARRAY *ToSAFEARRAY(const Vector<WString>& varray);
void ReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array);
void ReturnSAFEARRAY(SAFEARRAY *dest, const Vector<WString>& array);
HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array);
HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const Vector<WString>& array);
class OleSafeArray {
public:
OleSafeArray() : array(NULL) {}
OleSafeArray(const ValueArray& va) { array = ToSAFEARRAY(va); }
OleSafeArray(const Vector<WString>& vs) { array = ToSAFEARRAY(vs); }
OleSafeArray(const OleSafeArray& a) { array = NULL; if(a.array) OleVerify(SafeArrayCopy(a.array, &array)); }
~OleSafeArray() { if(array) SafeArrayDestroy(array); }
operator ValueArray () const { return SAFEARRAYToValueArray(array); }
operator Vector<WString> () const { return SAFEARRAYToWStringVector(array); }
SAFEARRAY *operator ~ () const { return array; }
private:
SAFEARRAY *array;
};
class OleBstr
{
@ -157,24 +195,6 @@ Color PackColor(long rgb);
long UnpackColor(Color c);
HRESULT CheckReturnColor(long *ptr, Color c);
class OleExc : public Exc
{
public:
OleExc(HRESULT hresult);
OleExc(HRESULT hresult, const char *text);
public:
HRESULT hresult;
};
HRESULT LogResult(HRESULT hr);
HRESULT LogError(HRESULT hr);
inline void OleVerify(HRESULT hr) { if(FAILED(hr)) throw OleExc(hr); }
inline void OleVerify(HRESULT hr, const char *text) { if(FAILED(hr)) throw OleExc(hr, text); }
#define OLE_VERIFY(c) OleVerify(c, #c)
template <class T>
class IRefBase : Moveable< IRefBase<T> >
{

View file

@ -1108,9 +1108,10 @@ void CalcFunctionNode::ScanArgs(CalcPacket& packet) const
//////////////////////////////////////////////////////////////////////
// CalcParser::
CalcParser::CalcParser()
CalcParser::CalcParser(bool sql_style_)
: start(0), pos(0)
, op_begin(0), op_end(0), op_last(OP_NONE)
, sql_style(sql_style_)
{
}
@ -1322,8 +1323,7 @@ CalcNodePtr CalcParser::ScanSequence()
CalcNodePtr CalcParser::ScanSelect()
{
CalcNodePtr node = ScanLogOr();
if(Check(OP_QUESTION))
{ // ?:
if(Check(OP_QUESTION)) { // ?:
CalcNodePtr when1 = ScanSelect();
Force(OP_COLON, ":");
CalcNodePtr when0 = ScanSelect();
@ -1372,8 +1372,52 @@ CalcNodePtr CalcParser::ScanCompare()
node = new CalcFunctionNode("<", node, ScanBitOr());
else if(Check(OP_GT))
node = new CalcFunctionNode(">", node, ScanBitOr());
else
return node;
else {
bool isnot = Check(OP_SQL_NOT);
bool isbtw = Check(OP_SQL_BETWEEN);
bool isin = !isbtw && Check(OP_SQL_IN);
bool islike = !isbtw && !isin && Check(OP_SQL_LIKE);
bool isis = !isbtw && !isin && Check(OP_SQL_IS);
CalcNodePtr out_node;
if(isbtw) {
CalcNodePtr lbound = ScanBitOr();
Force(OP_LOG_AND, "and");
CalcNodePtr ubound = ScanBitOr();
out_node = new CalcLogAndNode(
new CalcFunctionNode(">=", node, lbound),
new CalcFunctionNode("<=", node, ubound));
}
else if(isin) {
Vector<CalcNodePtr> lov;
if(Check(OP_LPAR)) {
do
lov.Add() = ScanSelect();
while(Check(OP_COMMA));
Force(OP_RPAR, ")");
out_node = new CalcFunctionNode("in", node,
new CalcFunctionNode("[,,]", lov));
}
else
out_node = new CalcConstNode(Value());
}
else if(islike) {
CalcNodePtr lexpr = ScanSelect();
out_node = new CalcFunctionNode("like", node, lexpr);
}
else if(isis) {
Force(OP_SQL_NULL, "NULL");
out_node = new CalcFunctionNode("is_null", node);
}
else if(isnot)
throw Exc(t_("expected 'between', 'in' or 'like'"));
else
return node;
if(!isnot)
return out_node;
return new CalcFunctionNode("!", out_node);
}
}
CalcNodePtr CalcParser::ScanBitOr()
@ -1562,34 +1606,87 @@ int CalcParser::GetOperator()
return op_last;
Skip();
op_begin = op_end = pos;
switch(*op_end++)
{
case '?': op_last = OP_QUESTION; break;
case ':': op_last = OP_COLON; break;
case ';': op_last = OP_SEMICOLON; break;
case '&': op_last = (*op_end == '&' ? op_end++, OP_LOG_AND : OP_BIT_AND); break;
case '|': op_last = (*op_end == '|' ? op_end++, OP_LOG_OR : OP_BIT_OR); break;
case '^': op_last = OP_BIT_XOR; break;
case '<': op_last = (*op_end == '=' ? op_end++, OP_LE : *op_end == '<' ? op_end++, OP_LSHIFT : OP_LT); break;
case '>': op_last = (*op_end == '=' ? op_end++, OP_GE : *op_end == '>' ? op_end++, OP_RSHIFT : OP_GT); break;
case '!': op_last = (*op_end == '=' ? op_end++, OP_NE : OP_LOG_NOT); break;
case '=': op_last = (*op_end == '=' ? op_end++, OP_EQ : (op_end--, OP_NONE)); break;
case '+': op_last = OP_ADD; break;
case '-': op_last = OP_SUB; break;
case '*': op_last = (*op_end == '*' ? op_end++, OP_POW : OP_MUL); break;
case '/': op_last = OP_DIV; break;
case '%': op_last = OP_MOD; break;
case '~': op_last = OP_BIT_NOT; break;
case '#': op_last = OP_LAMBDA; break;
case '(': op_last = OP_LPAR; break;
case ')': op_last = OP_RPAR; break;
case '[': op_last = OP_LBRACKET; break;
case ']': op_last = OP_RBRACKET; break;
case '{': op_last = OP_LBRACE; break;
case '}': op_last = OP_RBRACE; break;
case ',': op_last = OP_COMMA; break;
case '.': op_last = (*op_end == '.' ? op_end++, OP_DOTS : OP_DOT); break;
default: op_end--; op_last = OP_NONE; break;
switch(*op_end++) {
case '?': op_last = OP_QUESTION; break;
case ':': op_last = OP_COLON; break;
case ';': op_last = OP_SEMICOLON; break;
case '&': op_last = (*op_end == '&' ? op_end++, OP_LOG_AND : OP_BIT_AND); break;
case '|': op_last = (*op_end == '|' ? op_end++, OP_LOG_OR : OP_BIT_OR); break;
case '^': op_last = OP_BIT_XOR; break;
case '<': {
if(*op_end == '=') {
op_end++;
op_last = OP_LE;
}
else if(*op_end == '<') {
op_end++;
op_last = OP_LSHIFT;
}
else if(sql_style && *op_end == '>') {
op_end++;
op_last = OP_NE;
}
else
op_last = OP_LT;
break;
}
case '>': op_last = (*op_end == '=' ? op_end++, OP_GE : *op_end == '>' ? op_end++, OP_RSHIFT : OP_GT); break;
case '!': op_last = (*op_end == '=' ? op_end++, OP_NE : OP_LOG_NOT); break;
case '=': {
if(*op_end == '=') {
op_end++;
op_last = OP_EQ;
}
else if(sql_style)
op_last = OP_EQ;
else {
op_end--;
op_last = OP_NONE;
}
break;
}
case '+': op_last = OP_ADD; break;
case '-': op_last = OP_SUB; break;
case '*': op_last = (*op_end == '*' ? op_end++, OP_POW : OP_MUL); break;
case '/': op_last = OP_DIV; break;
case '%': op_last = OP_MOD; break;
case '~': op_last = OP_BIT_NOT; break;
case '#': op_last = OP_LAMBDA; break;
case '(': op_last = OP_LPAR; break;
case ')': op_last = OP_RPAR; break;
case '[': op_last = OP_LBRACKET; break;
case ']': op_last = OP_RBRACKET; break;
case '{': op_last = OP_LBRACE; break;
case '}': op_last = OP_RBRACE; break;
case ',': op_last = OP_COMMA; break;
case '.': op_last = (*op_end == '.' ? op_end++, OP_DOTS : OP_DOT); break;
default: {
op_end--;
op_last = OP_NONE;
if(sql_style && IsAlpha(*op_end)) {
const char *b = op_end;
while(IsAlNum(*++op_end) || *op_end == '_')
op_end++;
int len = (int)(op_end - b);
if(len == 3 && !MemICmp(b, "and", 3))
op_last = OP_LOG_AND;
else if(len == 2 && !MemICmp(b, "or", 2))
op_last = OP_LOG_OR;
else if(len == 7 && !MemICmp(b, "between", 7))
op_last = OP_SQL_BETWEEN;
else if(len == 2 && !MemICmp(b, "in", 2))
op_last = OP_SQL_IN;
else if(len == 4 && !MemICmp(b, "like", 4))
op_last = OP_SQL_LIKE;
else if(len == 3 && !MemICmp(b, "not", 3))
op_last = OP_SQL_NOT;
else if(len == 2 && !MemICmp(b, "is", 2))
op_last = OP_SQL_IS;
else
op_end = b;
}
break;
}
}
return op_last;
}

View file

@ -407,7 +407,7 @@ struct CalcType<CalcNodePtr> : public CalcRawType<CalcNodePtr>
class CalcParser
{
public:
CalcParser();
CalcParser(bool sql_style = false);
virtual CalcNodePtr Scan(const char *text);
virtual CalcNodePtr ScanVoid(const char *text);
@ -460,6 +460,8 @@ protected:
OP_LBRACE, OP_RBRACE,
OP_COMMA,
OP_DOT, OP_DOTS,
OP_SQL_BETWEEN, OP_SQL_IN, OP_SQL_LIKE,
OP_SQL_IS, OP_SQL_NOT, OP_SQL_NULL,
OP_LAST,
};
@ -470,6 +472,8 @@ protected:
bool Force(int op, const char *expect);
protected:
bool sql_style;
const char *start;
const char *pos;

View file

@ -3,7 +3,7 @@
#include "Core/init"
#include "Web/init"
#include "plugin\dbf/init"
#define BLITZ_INDEX__ FD099C670A4F9F921B7251BA8CFD143CC
#define BLITZ_INDEX__ F86AECB90B8BCD14D16E5FB9629D58AB4
#include "TCore_init.icpp"
#undef BLITZ_INDEX__
#endif