Add files via upload
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| CSVReader.mqh |
|
||||
//| Copyright (c) 2019, Marketeer |
|
||||
//| https://www.mql5.com/ru/articles/5913 |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#include <Marketeer/IndexMap.mqh>
|
||||
#include <Marketeer/GroupSettings.mqh>
|
||||
|
||||
|
||||
input GroupSettings SCV_Settings; // C S V S E T T I N G S
|
||||
|
||||
input string CSVDelimiter = ";" /*mql5 signals use ';' instead of ','*/; // · Delimiter
|
||||
|
||||
|
||||
class CSVConverter
|
||||
{
|
||||
private:
|
||||
class File
|
||||
{
|
||||
int file;
|
||||
|
||||
public:
|
||||
File(const string name, const int flags, const short delimiter)
|
||||
{
|
||||
file = FileOpen(name, flags, delimiter, CP_UTF8);
|
||||
}
|
||||
|
||||
File(const string name, const int flags)
|
||||
{
|
||||
file = FileOpen(name, flags);
|
||||
}
|
||||
|
||||
bool isOpened()
|
||||
{
|
||||
return (file != INVALID_HANDLE);
|
||||
}
|
||||
|
||||
int handle()
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
~File()
|
||||
{
|
||||
if(file != INVALID_HANDLE) FileClose(file);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
static IndexMap *ReadCSV(const string inputFileName)
|
||||
{
|
||||
// history.csv - 13 columns, positions.csv - 10 columns
|
||||
int columns = StringFind(inputFileName, ".history.csv") > 0 ? 13 : (StringFind(inputFileName, ".positions.csv") > 0 ? 10 : 0);
|
||||
if(columns == 0)
|
||||
{
|
||||
Print("Supported files: *.history.csv and .positions.csv");
|
||||
return NULL;
|
||||
}
|
||||
Print("Reading csv-file ", inputFileName);
|
||||
uchar delimiter = (uchar)CSVDelimiter[0];
|
||||
File f(inputFileName, FILE_READ|FILE_TXT|FILE_ANSI|FILE_SHARE_READ|FILE_SHARE_WRITE, delimiter);
|
||||
if(!f.isOpened())
|
||||
{
|
||||
Alert("Can't read file " + inputFileName);
|
||||
return NULL;
|
||||
}
|
||||
int file = f.handle();
|
||||
|
||||
bool headerLine = true;
|
||||
IndexMap *data = new IndexMap();
|
||||
string headers[];
|
||||
uint count = 0;
|
||||
|
||||
while(!FileIsEnding(file))
|
||||
{
|
||||
string stLine = "";
|
||||
string stParts[];
|
||||
|
||||
stLine = FileReadString(file);
|
||||
|
||||
int nParts = StringSplit(stLine, delimiter, stParts);
|
||||
if(nParts != columns)
|
||||
{
|
||||
Print("File " + inputFileName + " contains " + (string)nParts + " columns (" + (string)(columns) + "+ required)");
|
||||
Print("Line: ", stLine);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(headerLine)
|
||||
{
|
||||
headerLine = false;
|
||||
ArrayCopy(headers, stParts);
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexMap *row = new IndexMap();
|
||||
|
||||
for(int i = 0; i < nParts; i++)
|
||||
{
|
||||
row.setValue((string)i + "." + headers[i], stParts[i]);
|
||||
}
|
||||
|
||||
data.add((string)count, row);
|
||||
++count;
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
#define CSV_COLUMN_TIME1 0
|
||||
#define CSV_COLUMN_TYPE 1
|
||||
#define CSV_COLUMN_VOLUME 2
|
||||
#define CSV_COLUMN_SYMBOL 3
|
||||
#define CSV_COLUMN_PRICE1 4
|
||||
#define CSV_COLUMN_TIME2 5 // 7
|
||||
#define CSV_COLUMN_PRICE2 6 // 8
|
||||
#define CSV_COLUMN_COMMISSION 7 // 9
|
||||
#define CSV_COLUMN_SWAP 8 // 10
|
||||
#define CSV_COLUMN_PROFIT 9 // 11
|
||||
#define CSV_COLUMN_COMMENT 12
|
||||
@@ -0,0 +1,24 @@
|
||||
template<typename T1,typename T2>
|
||||
class Converter
|
||||
{
|
||||
private:
|
||||
union _L2D
|
||||
{
|
||||
T1 L;
|
||||
T2 D;
|
||||
}
|
||||
L2D;
|
||||
|
||||
public:
|
||||
T2 operator[](const T1 L)
|
||||
{
|
||||
L2D.L = L;
|
||||
return L2D.D;
|
||||
}
|
||||
|
||||
T1 operator[](const T2 D)
|
||||
{
|
||||
L2D.D = D;
|
||||
return L2D.L;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
enum GroupSettings {};
|
||||
@@ -0,0 +1,15 @@
|
||||
#define COLUMNS_COUNT 13
|
||||
|
||||
#define COLUMN_TIME 0
|
||||
#define COLUMN_DEAL 1
|
||||
#define COLUMN_SYMBOL 2
|
||||
#define COLUMN_TYPE 3
|
||||
#define COLUMN_DIRECTION 4
|
||||
#define COLUMN_VOLUME 5
|
||||
#define COLUMN_PRICE 6
|
||||
#define COLUMN_ORDER 7
|
||||
#define COLUMN_COMISSION 8
|
||||
#define COLUMN_SWAP 9
|
||||
#define COLUMN_PROFIT 10
|
||||
#define COLUMN_BALANCE 11
|
||||
#define COLUMN_COMMENT 12
|
||||
@@ -0,0 +1,401 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| IndexMapT.mqh |
|
||||
//| https://www.mql5.com/ru/articles/5706/ |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#define EMPTY ((int)EMPTY_VALUE)
|
||||
|
||||
#ifdef HASHMAP_WARNING
|
||||
#define NULL_PLACEHOLDER "n/a"
|
||||
#else
|
||||
#define NULL_PLACEHOLDER ""
|
||||
#endif
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual string asString() const
|
||||
{
|
||||
return(__FUNCSIG__);
|
||||
}
|
||||
|
||||
virtual string asCSVString() const
|
||||
{
|
||||
return(__FUNCSIG__);
|
||||
}
|
||||
|
||||
virtual string getTypeName() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base container for indexed map. Can contain plain types and pointers.
|
||||
*/
|
||||
class Container: public Object
|
||||
{
|
||||
protected:
|
||||
enum datatype
|
||||
{
|
||||
null,
|
||||
s,
|
||||
d,
|
||||
t,
|
||||
i,
|
||||
o,
|
||||
u
|
||||
};
|
||||
|
||||
datatype type;
|
||||
|
||||
public:
|
||||
datatype getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
// helper method to access plain type values from the base class
|
||||
template<typename R>
|
||||
R get() const;
|
||||
|
||||
// helper method to access object pointers from the base class
|
||||
template<typename R>
|
||||
Object *getObject() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Variable type data for indexed map; plain types only.
|
||||
*/
|
||||
template<typename T>
|
||||
class TypeContainer: public Container
|
||||
{
|
||||
private:
|
||||
int digits;
|
||||
int flags;
|
||||
|
||||
protected:
|
||||
T v;
|
||||
|
||||
TypeContainer()
|
||||
{
|
||||
digits = _Digits;
|
||||
flags = TIME_DATE | TIME_MINUTES;
|
||||
}
|
||||
|
||||
public:
|
||||
TypeContainer(T _v, int precision = INT_MIN, int timeflags = TIME_DATE | TIME_MINUTES)
|
||||
{
|
||||
v = _v;
|
||||
digits = precision == INT_MIN ? _Digits : precision;
|
||||
flags = timeflags;
|
||||
|
||||
if(typename(T) == "string")
|
||||
{
|
||||
type = datatype::s;
|
||||
}
|
||||
else
|
||||
if(typename(T) == "double" || typename(T) == "float")
|
||||
{
|
||||
type = datatype::d;
|
||||
}
|
||||
else
|
||||
if(typename(T) == "datetime")
|
||||
{
|
||||
type = datatype::t;
|
||||
}
|
||||
else
|
||||
if(typename(T) == "char" || typename(T) == "short" || typename(T) == "int" || typename(T) == "long")
|
||||
{
|
||||
type = datatype::i;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = datatype::u;
|
||||
}
|
||||
}
|
||||
|
||||
virtual T getValue() const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
// represent data as a string, convert if necessary
|
||||
virtual string asString() const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case datatype::s: return (string)v;
|
||||
case datatype::d: return DoubleToString((double)v, digits);
|
||||
case datatype::t: return TimeToString((datetime)v, flags);
|
||||
case datatype::i: return IntegerToString((long)v);
|
||||
default: return (string)v;
|
||||
}
|
||||
}
|
||||
|
||||
virtual string asCSVString() const
|
||||
{
|
||||
return asString();
|
||||
}
|
||||
|
||||
virtual string getTypeName() const override
|
||||
{
|
||||
return typename(this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Object pointer types for indexed map.
|
||||
* Pointer will be deleted automatically.
|
||||
*/
|
||||
template<typename T>
|
||||
class ObjectContainer: public Container
|
||||
{
|
||||
protected:
|
||||
Object *o;
|
||||
|
||||
public:
|
||||
ObjectContainer(T _v)
|
||||
{
|
||||
o = _v;
|
||||
type = datatype::o;
|
||||
}
|
||||
|
||||
~ObjectContainer()
|
||||
{
|
||||
if(CheckPointer(o) == POINTER_DYNAMIC)
|
||||
{
|
||||
delete(o);
|
||||
}
|
||||
}
|
||||
|
||||
T getObject() const
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
virtual string asString() const override
|
||||
{
|
||||
return o.asString();
|
||||
}
|
||||
|
||||
virtual string asCSVString() const
|
||||
{
|
||||
return o.asCSVString();
|
||||
}
|
||||
|
||||
virtual string getTypeName() const override
|
||||
{
|
||||
return typename(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename R>
|
||||
R Container::get() const
|
||||
{
|
||||
const TypeContainer<R> *ptr = dynamic_cast<const TypeContainer<R> *>(&this);
|
||||
if(ptr != NULL) return (R)ptr.getValue();
|
||||
return (R)NULL;
|
||||
}
|
||||
|
||||
template<typename R> // R is supposed to be an object pointer
|
||||
Object *Container::getObject() const
|
||||
{
|
||||
const ObjectContainer<R> *obj = dynamic_cast<const ObjectContainer<R> *>(&this);
|
||||
if(obj != NULL) return obj.getObject();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indexed map with random access by key and index.
|
||||
*/
|
||||
template<typename T>
|
||||
class IndexMapT: public Container // Object
|
||||
{
|
||||
private:
|
||||
T keys[];
|
||||
Container *values[];
|
||||
int count;
|
||||
string id;
|
||||
uchar delimiter;
|
||||
|
||||
public:
|
||||
IndexMapT(): count(0), delimiter(',') {}
|
||||
IndexMapT(string obj): id (obj), count(0), delimiter(',') {}
|
||||
IndexMapT(uchar d): count(0), delimiter(d) {}
|
||||
|
||||
~IndexMapT()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
virtual string getTypeName() const override
|
||||
{
|
||||
return typename(this);
|
||||
}
|
||||
|
||||
void add(const T key, Container *value)
|
||||
{
|
||||
ArrayResize(keys, count + 1);
|
||||
ArrayResize(values, count + 1);
|
||||
keys[count] = key;
|
||||
values[count] = value;
|
||||
count++;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
if(CheckPointer(values[i]) == POINTER_DYNAMIC)
|
||||
{
|
||||
delete(values[i]);
|
||||
}
|
||||
}
|
||||
ArrayResize(keys, 0);
|
||||
ArrayResize(values, 0);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
bool isKeyExisting(const T key) const
|
||||
{
|
||||
return (getIndex(key) != EMPTY);
|
||||
}
|
||||
|
||||
int getIndex(const T key) const
|
||||
{
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
if(keys[i] == key) return(i);
|
||||
}
|
||||
#ifdef HASHMAP_VERBOSE
|
||||
Print(__FUNCSIG__, ": no key=", key);
|
||||
#endif
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
Container *operator[](const int index) const
|
||||
{
|
||||
if(index < 0 || index >= count)
|
||||
{
|
||||
#ifdef HASHMAP_VERBOSE
|
||||
Print(__FUNCSIG__, ": index=", index);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
return(GetPointer(values[index]));
|
||||
}
|
||||
|
||||
Container *operator[](const T key) const
|
||||
{
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
if(keys[i] == key) return(GetPointer(values[i]));
|
||||
}
|
||||
#ifdef HASHMAP_VERBOSE
|
||||
Print(__FUNCSIG__, ": no key=", key);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
T getKey(const int index) const
|
||||
{
|
||||
if(index < 0 || index >= count)
|
||||
{
|
||||
Print(__FUNCSIG__, ": index=", index);
|
||||
}
|
||||
return(keys[index]);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void setValue(const T key, R value)
|
||||
{
|
||||
// NB: implementation specific
|
||||
// in HTML every attribute can occur only once in a tag,
|
||||
// all successive assignments are ignored
|
||||
if(!isKeyExisting(key))
|
||||
{
|
||||
set(key, new TypeContainer<R>(value));
|
||||
}
|
||||
}
|
||||
|
||||
void set(const T key, Container *value)
|
||||
{
|
||||
int index = getIndex(key);
|
||||
if(index != EMPTY)
|
||||
{
|
||||
#ifdef HASHMAP_WARNING
|
||||
Print(__FUNCSIG__, ": overwritten key=", key, ", old value=", (values[index] != NULL ? values[index].asString() : "null"), ", new value=", (value != NULL ? value.asString() : "null"));
|
||||
#endif
|
||||
values[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void set(const T key)
|
||||
{
|
||||
int index = getIndex(key);
|
||||
if(index == EMPTY)
|
||||
{
|
||||
add(key, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int getSize() const
|
||||
{
|
||||
return(count);
|
||||
}
|
||||
|
||||
virtual string asString() const
|
||||
{
|
||||
string result = "";
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
result += (string)keys[i] + "=" + (CheckPointer(values[i]) == POINTER_INVALID ? NULL_PLACEHOLDER : values[i].asString()) + ";";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual string asCSVString() const
|
||||
{
|
||||
string result = "";
|
||||
string d = CharToString(delimiter);
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
string v = NULL_PLACEHOLDER;
|
||||
|
||||
if(CheckPointer(values[i]) != POINTER_INVALID)
|
||||
{
|
||||
v = values[i].asCSVString();
|
||||
StringReplace(v, d, "");
|
||||
}
|
||||
|
||||
if(i < count - 1)
|
||||
{
|
||||
result += v + d;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += v;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class IndexMap: public IndexMapT<string>
|
||||
{
|
||||
public:
|
||||
IndexMap(): IndexMapT() {}
|
||||
IndexMap(string obj): IndexMapT(obj) {}
|
||||
IndexMap(uchar d): IndexMapT(d) {}
|
||||
string get(const string key)
|
||||
{
|
||||
Container *c = this[key];
|
||||
if(c == NULL) return NULL;
|
||||
return c.get<string>();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,195 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RubbArray.mqh |
|
||||
//| Copyright (c) 2019, Marketeer |
|
||||
//| https://www.mql5.com/en/users/marketeer |
|
||||
//| https://www.mql5.com/ru/articles/5638 |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
template <typename T>
|
||||
interface Clonable
|
||||
{
|
||||
T clone();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class BaseArray
|
||||
{
|
||||
protected:
|
||||
T data[];
|
||||
|
||||
public:
|
||||
virtual ~BaseArray()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
ArrayResize(data, 0);
|
||||
}
|
||||
|
||||
T operator[](int i) const
|
||||
{
|
||||
return get(i);
|
||||
}
|
||||
|
||||
T get(int i) const
|
||||
{
|
||||
if(i < 0 || i >= ArraySize(data))
|
||||
{
|
||||
Print("Array size=", ArraySize(data), ", index=", i);
|
||||
return NULL;
|
||||
}
|
||||
return data[i];
|
||||
}
|
||||
|
||||
T top() const
|
||||
{
|
||||
if(ArraySize(data) == 0)
|
||||
{
|
||||
Print("Array size=0");
|
||||
return NULL;
|
||||
}
|
||||
return data[ArraySize(data) - 1];
|
||||
}
|
||||
|
||||
T peek() const
|
||||
{
|
||||
return top();
|
||||
}
|
||||
|
||||
BaseArray *add(T d)
|
||||
{
|
||||
int n = ArraySize(data);
|
||||
ArrayResize(data, n + 1);
|
||||
data[n] = d;
|
||||
return &this;
|
||||
}
|
||||
|
||||
BaseArray *operator<<(T d)
|
||||
{
|
||||
return add(d);
|
||||
}
|
||||
|
||||
BaseArray *operator<<(const BaseArray<T> *x)
|
||||
{
|
||||
for(int i = 0; i < x.size(); i++)
|
||||
{
|
||||
Clonable<T> *clone = dynamic_cast<Clonable<T> *>(x[i]);
|
||||
if(clone != NULL)
|
||||
{
|
||||
add(clone.clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
add(x[i]);
|
||||
}
|
||||
}
|
||||
return &this;
|
||||
}
|
||||
|
||||
BaseArray *push(T d)
|
||||
{
|
||||
return add(d);
|
||||
}
|
||||
|
||||
void operator=(const BaseArray &d)
|
||||
{
|
||||
int i, n = d.size();
|
||||
ArrayResize(data, n);
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
data[i] = d[i];
|
||||
}
|
||||
}
|
||||
|
||||
T operator>>(int i)
|
||||
{
|
||||
T d = this[i];
|
||||
if(d == NULL) return NULL;
|
||||
int n = ArraySize(data) - 1;
|
||||
if(i < n)
|
||||
{
|
||||
ArrayCopy(data, data, i, i + 1);
|
||||
}
|
||||
ArrayResize(data, n);
|
||||
return d;
|
||||
}
|
||||
|
||||
T pop()
|
||||
{
|
||||
int _size = ArraySize(data) - 1;
|
||||
T d = this[_size];
|
||||
ArrayResize(data, _size);
|
||||
return d;
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return ArraySize(data);
|
||||
}
|
||||
|
||||
|
||||
string toString() const
|
||||
{
|
||||
static string formats[4][2] = {{"double", "%f"}, {"long", "%i"}, {"string", "%s"}, {"int", "%i"}};
|
||||
string fmt = "%x";
|
||||
for(int k = 0; k < ArrayRange(formats, 0); k++)
|
||||
{
|
||||
if(typename(T) == formats[k][0])
|
||||
{
|
||||
fmt = formats[k][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i, n = ArraySize(data);
|
||||
string s;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
s += StringFormat(fmt, data[i]) + ",";
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class RubbArray: public BaseArray<T>
|
||||
{
|
||||
public:
|
||||
RubbArray()
|
||||
{
|
||||
}
|
||||
|
||||
~RubbArray()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
virtual void clear() override
|
||||
{
|
||||
int i, n = ArraySize(data);
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
if(CheckPointer(data[i]) == POINTER_DYNAMIC) delete data[i];
|
||||
}
|
||||
ArrayResize(data, 0);
|
||||
}
|
||||
|
||||
T replace(const int i, T v)
|
||||
{
|
||||
int n = ArraySize(data);
|
||||
if(i < n)
|
||||
{
|
||||
if(CheckPointer(data[i]) == POINTER_DYNAMIC) delete data[i];
|
||||
data[i] = v;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#define List RubbArray
|
||||
#define Stack RubbArray
|
||||
@@ -0,0 +1,43 @@
|
||||
//#define DATETIME_PLACEHOLDER ((datetime)0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
class DateTime
|
||||
{
|
||||
private:
|
||||
MqlDateTime mdtstruct;
|
||||
|
||||
public:
|
||||
DateTime(){TimeToStruct(0, mdtstruct);}
|
||||
DateTime *assign(datetime dt) {TimeToStruct(dt, mdtstruct); return &this;}
|
||||
int __TimeDayOfWeek() {return mdtstruct.day_of_week;}
|
||||
int __TimeDayOfYear() {return mdtstruct.day_of_year;}
|
||||
int __TimeYear() {return mdtstruct.year;}
|
||||
int __TimeMonth() {return mdtstruct.mon;}
|
||||
int __TimeDay() {return mdtstruct.day;}
|
||||
int __TimeHour() {return mdtstruct.hour;}
|
||||
int __TimeMinute() {return mdtstruct.min;}
|
||||
int __TimeSeconds() {return mdtstruct.sec;}
|
||||
};
|
||||
|
||||
DateTime _DateTime;
|
||||
|
||||
#define TimeDayOfWeek(T) _DateTime.assign(T).__TimeDayOfWeek()
|
||||
#define TimeYear(T) _DateTime.assign(T).__TimeYear()
|
||||
#define TimeMonth(T) _DateTime.assign(T).__TimeMonth()
|
||||
#define TimeDay(T) _DateTime.assign(T).__TimeDay()
|
||||
#define TimeHour(T) _DateTime.assign(T).__TimeHour()
|
||||
#define TimeMinute(T) _DateTime.assign(T).__TimeMinute()
|
||||
#define TimeSeconds(T) _DateTime.assign(T).__TimeSeconds()
|
||||
|
||||
#define _TimeYear _DateTime.__TimeYear
|
||||
#define _TimeMonth _DateTime.__TimeMonth
|
||||
#define _TimeDay _DateTime.__TimeDay
|
||||
#define _TimeHour _DateTime.__TimeHour
|
||||
#define _TimeMinute _DateTime.__TimeMinute
|
||||
#define _TimeSeconds _DateTime.__TimeSeconds
|
||||
|
||||
#define Year _DateTime.assign(TimeCurrent()).__TimeYear
|
||||
#define Month _DateTime.assign(TimeCurrent()).__TimeMonth
|
||||
#define Day _DateTime.assign(TimeCurrent()).__TimeDay
|
||||
#define Hour _DateTime.assign(TimeCurrent()).__TimeHour
|
||||
#define Minute _DateTime.assign(TimeCurrent()).__TimeMinute
|
||||
#define Seconds _DateTime.assign(TimeCurrent()).__TimeSeconds
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
// header
|
||||
"isindex",
|
||||
"base",
|
||||
"meta",
|
||||
"link",
|
||||
"nextid",
|
||||
"range",
|
||||
// elsewhere
|
||||
"img",
|
||||
"br",
|
||||
"hr",
|
||||
"frame",
|
||||
"wbr",
|
||||
"basefont",
|
||||
"spacer",
|
||||
"area",
|
||||
"param",
|
||||
"keygen",
|
||||
"col",
|
||||
"limittext"
|
||||
Reference in New Issue
Block a user