summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-01-10 22:12:07 (GMT)
committersebres <sebres@users.sourceforge.net>2017-01-10 22:12:07 (GMT)
commit3f06a6ec89b41434fe38bede870563e35b809019 (patch)
tree7aa11fe69ef1ddc9696c271d75cbf19796ba01f6
parent68f320e5ffddc67ee02c233c1b8396b198bde577 (diff)
downloadtcl-3f06a6ec89b41434fe38bede870563e35b809019.zip
tcl-3f06a6ec89b41434fe38bede870563e35b809019.tar.gz
tcl-3f06a6ec89b41434fe38bede870563e35b809019.tar.bz2
[temp-commit]: rewrite scan token map handling
-rw-r--r--generic/tclClock.c2
-rw-r--r--generic/tclClockFmt.c102
-rw-r--r--tests-perf/clock.perf.tcl12
3 files changed, 93 insertions, 23 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index 3c296b5..e00d6a2 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -2576,6 +2576,7 @@ ClockScanObjCmd(
}
ret = ClockFreeScan(clientData, interp, info, objv[1], &opts);
}
+#if 0
else
if (1) {
/* TODO: Tcled Scan proc - */
@@ -2588,6 +2589,7 @@ ClockScanObjCmd(
Tcl_DecrRefCount(callargs[0]);
return ret;
}
+#endif
else {
/* Use compiled version of Scan - */
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index 356965d..93416af 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -392,19 +392,32 @@ Tcl_GetClockFrmScnFromObj(
}
-#define AllocTokenInChain(tok, chain, tokC) \
- if ((tok) >= (chain) + (tokC)) { \
+#define AllocTokenInChain(tok, chain, tokCnt) \
+ if (++(tok) >= (chain) + (tokCnt)) { \
(char *)(chain) = ckrealloc((char *)(chain), \
- (tokC) + sizeof((**(tok))) * CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE); \
- if ((chain) == NULL) { return NULL; }; \
- (tok) = (chain) + (tokC); \
- (tokC) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \
- }
-
-const char *ScnSTokenChars = "dmyYHMS";
-static ClockScanToken ScnSTokens[] = {
+ (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \
+ if ((chain) == NULL) { goto done; }; \
+ (tok) = (chain) + (tokCnt); \
+ (tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \
+ } \
+ *(tok) = NULL;
+
+const char *ScnSTokenMapChars =
+ "dmyYHMS";
+static ClockScanToken ScnSTokenMap[] = {
+ {CTOKT_DIGIT, 1, 2, 0},
+ {CTOKT_DIGIT, 1, 2, 0},
+ {CTOKT_DIGIT, 1, 2, 0},
+ {CTOKT_DIGIT, 1, 4, 0},
+ {CTOKT_DIGIT, 1, 2, 0},
+ {CTOKT_DIGIT, 1, 2, 0},
{CTOKT_DIGIT, 1, 2, 0},
};
+const char *ScnSpecTokenMapChars =
+ " %";
+static ClockScanToken ScnSpecTokenMap[] = {
+ {CTOKT_SPACE, 1, 0xffff, 0},
+};
/*
*----------------------------------------------------------------------
@@ -435,31 +448,73 @@ ClockGetOrParseScanFormat(
/* if first time scanning - tokenize format */
if (fss->scnTok == NULL) {
const char *strFmt;
- register const char *p, *e;
+ register const char *p, *e, *cp, *word_start = NULL;
+
+ Tcl_MutexLock(&ClockFmtMutex);
fss->scnTokC = CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE;
fss->scnTok =
- tok = ckalloc(sizeof(**tok) * CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE);
- (*tok)->type = CTOKT_EOB;
+ tok = ckalloc(sizeof(*tok) * CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE);
+ *tok = NULL;
strFmt = TclGetString(formatObj);
for (e = p = strFmt, e += formatObj->length; p != e; p++) {
switch (*p) {
case '%':
- if (p+1 >= e)
- goto word_tok;
- AllocTokenInChain(tok, fss->scnTok, fss->scnTokC);
+ if (p+1 >= e) {
+ word_start = p;
+ continue;
+ }
p++;
- // *tok =
+ /* try to find modifier: */
+ switch (*p) {
+ case '%':
+ word_start = p-1;
+ continue;
+ break;
+ case 'E':
+ goto ext_tok_E;
+ break;
+ case 'O':
+ goto ext_tok_O;
+ break;
+ default:
+ cp = strchr(ScnSTokenMapChars, *p);
+ if (!cp || *cp == '\0') {
+ word_start = p-1;
+ continue;
+ }
+ *tok = &ScnSTokenMap[cp - ScnSTokenMapChars];
+ AllocTokenInChain(tok, fss->scnTok, fss->scnTokC);
+ break;
+ }
break;
case ' ':
+ cp = strchr(ScnSpecTokenMapChars, *p);
+ if (!cp || *cp == '\0') {
+ p--;
+ goto word_tok;
+ }
+ *tok = &ScnSpecTokenMap[cp - ScnSpecTokenMapChars];
AllocTokenInChain(tok, fss->scnTok, fss->scnTokC);
- // *tok =
break;
default:
word_tok:
- break;
+
+ continue;
}
+
+ continue;
+ext_tok_E:
+
+ext_tok_O:
+
+ /*******************/
+ continue;
+
}
+
+done:
+ Tcl_MutexUnlock(&ClockFmtMutex);
}
return fss->scnTok;
@@ -478,11 +533,16 @@ ClockScan(
{
ClockScanToken **tok;
- if (ClockGetOrParseScanFormat(interp, opts->formatObj) == NULL) {
+ if ((tok = ClockGetOrParseScanFormat(interp, opts->formatObj)) == NULL) {
return TCL_ERROR;
}
- // Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)fss));
+ //***********************************
+
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)tok));
+ return TCL_OK;
+
+
return TCL_ERROR;
}
diff --git a/tests-perf/clock.perf.tcl b/tests-perf/clock.perf.tcl
index 7994428..969e279 100644
--- a/tests-perf/clock.perf.tcl
+++ b/tests-perf/clock.perf.tcl
@@ -28,8 +28,16 @@ proc _test_get_commands {lst} {
proc test-scan {{reptime 1000}} {
foreach _(c) [_test_get_commands {
# Scan : date
- #{clock scan "25.11.2015" -format "%d.%m.%Y" -base 0 -gmt 1}
- #{**STOP** : Wed Nov 25 01:00:00 CET 2015}
+ {clock scan "25.11.2015" -format "%d.%m.%Y" -base 0 -gmt 1}
+ {clock scan "1111" -format "%d%m%y" -base 0 -gmt 1}
+ {**STOP** : Wed Nov 25 01:00:00 CET 2015}
+ # Scan : long format test (allock chain)
+ {clock scan "25.11.2015" -format "%d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y %d.%m.%Y" -base 0 -gmt 1}
+ # Scan : dynamic, very long format test (create obj representation, allock chain, GC, etc):
+ {clock scan "25.11.2015" -format [string repeat "[incr i] %d.%m.%Y %d.%m.%Y" 10] -base 0 -gmt 1}
+ # Scan : again:
+ {clock scan "25.11.2015" -format [string repeat "[incr i -1] %d.%m.%Y %d.%m.%Y" 10] -base 0 -gmt 1}
+
# FreeScan : relative date
{clock scan "5 years 18 months 385 days" -base 0 -gmt 1}
# FreeScan : relative date with relative weekday