summaryrefslogtreecommitdiffstats
path: root/generic/tclClock.c
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2008-02-06 01:13:05 (GMT)
committerKevin B Kenny <kennykb@acm.org>2008-02-06 01:13:05 (GMT)
commiteac924b26e7181f5813720bf155fab400ab61ddd (patch)
treebe5a6d0b626bcdb3317039a70e784f6f94952bed /generic/tclClock.c
parentbfae64345f6b96ef2ed77b4975b22edb8bf8688e (diff)
downloadtcl-eac924b26e7181f5813720bf155fab400ab61ddd.zip
tcl-eac924b26e7181f5813720bf155fab400ab61ddd.tar.gz
tcl-eac924b26e7181f5813720bf155fab400ab61ddd.tar.bz2
* generic/tclClock.c (ClockParseformatargsObjCmd):
* library/clock.tcl (::tcl::clock::format): * tests/clock.test (clock-1.0, clock-1.4): Performance enhancements in [clock format] (moving the analysis of $args into C code, holding on to Tcl_Objs with resolved command names, [lassign] in place of [foreach], avoiding [namespace which] for command resolution).
Diffstat (limited to 'generic/tclClock.c')
-rw-r--r--generic/tclClock.c140
1 files changed, 135 insertions, 5 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index 26a8662..dd006b4 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclClock.c,v 1.63 2007/12/13 15:23:15 dgp Exp $
+ * RCS: @(#) $Id: tclClock.c,v 1.64 2008/02/06 01:13:07 kennykb Exp $
*/
#include "tclInt.h"
@@ -58,9 +58,13 @@ static const int daysInPriorMonths[2][13] = {
*/
typedef enum ClockLiteral {
- LIT_BCE, LIT_CE,
+ LIT__NIL,
+ LIT__DEFAULT_FORMAT,
+ LIT_BCE, LIT_C,
+ LIT_CANNOT_USE_GMT_AND_TIMEZONE,
+ LIT_CE,
LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
- LIT_ERA, LIT_GREGORIAN,
+ LIT_ERA, LIT_GMT, LIT_GREGORIAN,
LIT_ISO8601WEEK, LIT_ISO8601YEAR,
LIT_JULIANDAY, LIT_LOCALSECONDS,
LIT_MONTH,
@@ -69,9 +73,13 @@ typedef enum ClockLiteral {
LIT__END
} ClockLiteral;
static const char *const literals[] = {
- "BCE", "CE",
+ "",
+ "%a %b %d %H:%M:%S %Z %Y",
+ "BCE", "C",
+ "cannot use -gmt and -timezone in same call",
+ "CE",
"dayOfMonth", "dayOfWeek", "dayOfYear",
- "era", "gregorian",
+ "era", ":GMT", "gregorian",
"iso8601Week", "iso8601Year",
"julianDay", "localSeconds",
"month",
@@ -176,6 +184,9 @@ static int ClockMicrosecondsObjCmd(
static int ClockMillisecondsObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
+static int ClockParseformatargsObjCmd(
+ ClientData clientData, Tcl_Interp* interp,
+ int objc, Tcl_Obj *const objv[]);
static int ClockSecondsObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
@@ -209,6 +220,7 @@ static const struct ClockCommand clockCommands[] = {
ClockGetjuliandayfromerayearmonthdayObjCmd },
{ "GetJulianDayFromEraYearWeekDay",
ClockGetjuliandayfromerayearweekdayObjCmd },
+ { "ParseFormatArgs", ClockParseformatargsObjCmd },
{ NULL, NULL }
};
@@ -1779,6 +1791,124 @@ ClockMicrosecondsObjCmd(
return TCL_OK;
}
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * ClockParseformatargsObjCmd --
+ *
+ * Parses the arguments for [clock format].
+ *
+ * Results:
+ * Returns a standard Tcl result, whose value is a four-element
+ * list comprising the time format, the locale, and the timezone.
+ *
+ * This function exists because the loop that parses the [clock format]
+ * options is a known performance "hot spot", and is implemented in an
+ * effort to speed that particular code up.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+ClockParseformatargsObjCmd(
+ ClientData clientData, /* Client data containing literal pool */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ int objc, /* Parameter count */
+ Tcl_Obj *const objv[] /* Parameter vector */
+) {
+
+ ClockClientData* dataPtr = (ClockClientData*) clientData;
+ Tcl_Obj** litPtr = dataPtr->literals;
+
+ /* Format, locale and timezone */
+
+ Tcl_Obj* results[3];
+#define formatObj results[0]
+#define localeObj results[1]
+#define timezoneObj results[2]
+ int gmtFlag = 0;
+
+ /* Command line options expected */
+
+ const static char* options[] = {
+ "-format", "-gmt", "-locale",
+ "-timezone", NULL };
+ enum optionInd {
+ CLOCK_FORMAT_FORMAT, CLOCK_FORMAT_GMT, CLOCK_FORMAT_LOCALE,
+ CLOCK_FORMAT_TIMEZONE
+ };
+ int optionIndex; /* Index of an option */
+ int saw = 0; /* Flag == 1 if option was seen already */
+ Tcl_WideInt clockVal; /* Clock value - just used to parse */
+ int i;
+
+ /* Args consist of a time followed by keyword-value pairs */
+
+ if (objc < 2 || (objc % 2) != 0) {
+ Tcl_WrongNumArgs(interp, 0, objv,
+ "clock format clockval ?-format string? "
+ "?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?");
+ Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", NULL);
+ return TCL_ERROR;
+ }
+
+ /* Extract values for the keywords */
+
+ formatObj = litPtr[LIT__DEFAULT_FORMAT];
+ localeObj = litPtr[LIT_C];
+ timezoneObj = litPtr[LIT__NIL];
+ for (i = 2; i < objc; i+=2) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", 0,
+ &optionIndex) != TCL_OK) {
+ Tcl_SetErrorCode(interp, "CLOCK", "badSwitch",
+ Tcl_GetString(objv[i]), NULL);
+ return TCL_ERROR;
+ }
+ switch (optionIndex) {
+ case CLOCK_FORMAT_FORMAT:
+ formatObj = objv[i+1];
+ break;
+ case CLOCK_FORMAT_GMT:
+ if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+ case CLOCK_FORMAT_LOCALE:
+ localeObj = objv[i+1];
+ break;
+ case CLOCK_FORMAT_TIMEZONE:
+ timezoneObj = objv[i+1];
+ break;
+ }
+ saw |= (1 << optionIndex);
+ }
+
+ /* Check options */
+
+ if (Tcl_GetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((saw & (1 << CLOCK_FORMAT_GMT))
+ && (saw & (1 << CLOCK_FORMAT_TIMEZONE))) {
+ Tcl_SetObjResult(interp, litPtr[LIT_CANNOT_USE_GMT_AND_TIMEZONE]);
+ Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL);
+ return TCL_ERROR;
+ }
+ if (gmtFlag) {
+ timezoneObj = litPtr[LIT_GMT];
+ }
+
+ /* Return options as a list */
+
+ Tcl_SetObjResult(interp, Tcl_NewListObj(3, results));
+ return TCL_OK;
+
+#undef timezoneObj
+#undef localeObj
+#undef formatObj
+
+}
+
/*----------------------------------------------------------------------
*
* ClockSecondsObjCmd -