summaryrefslogtreecommitdiffstats
path: root/generic/tclClockFmt.c
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-01-10 22:30:24 (GMT)
committersebres <sebres@users.sourceforge.net>2017-01-10 22:30:24 (GMT)
commit40520b8606111adeab272cb9d2fa4c7acca3e406 (patch)
treed0b0160f1b83e719ad0ec41239e7b2a98aea16cd /generic/tclClockFmt.c
parent5afae758b98de2da47b30d6aa4b40a5d5a604fbc (diff)
downloadtcl-40520b8606111adeab272cb9d2fa4c7acca3e406.zip
tcl-40520b8606111adeab272cb9d2fa4c7acca3e406.tar.gz
tcl-40520b8606111adeab272cb9d2fa4c7acca3e406.tar.bz2
improve LocalizeFormat, internal caching of localized formats inside msgcat for locale and format objects
smart reference introduced in dict (smart pointer with 0 object reference but increase dict-reference, provide changeable locale dict) code review
Diffstat (limited to 'generic/tclClockFmt.c')
-rw-r--r--generic/tclClockFmt.c229
1 files changed, 149 insertions, 80 deletions
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index 184b52a..daedb26 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -233,65 +233,6 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType;
/*
- *----------------------------------------------------------------------
- */
-
-static ClockFmtScnStorage *
-FindOrCreateFmtScnStorage(
- Tcl_Interp *interp,
- const char *strFmt)
-{
- ClockFmtScnStorage *fss = NULL;
- int new;
- Tcl_HashEntry *hPtr;
-
- Tcl_MutexLock(&ClockFmtMutex);
-
- /* if not yet initialized */
- if (!initialized) {
- /* initialize type */
- memcpy(&ClockFmtScnStorageHashKeyType, &tclStringHashKeyType, sizeof(tclStringHashKeyType));
- ClockFmtScnStorageHashKeyType.allocEntryProc = ClockFmtScnStorageAllocProc;
- ClockFmtScnStorageHashKeyType.freeEntryProc = ClockFmtScnStorageFreeProc;
-
- /* initialize hash table */
- Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS,
- &ClockFmtScnStorageHashKeyType);
-
- initialized = 1;
- Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL);
- }
-
- /* get or create entry (and alocate storage) */
- hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &new);
- if (hPtr != NULL) {
-
- fss = FmtScn4HashEntry(hPtr);
-
- #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
- /* unlink if it is currently in GC */
- if (new == 0 && fss->objRefCount == 0) {
- ClockFmtScnStorage_GC_Out(fss);
- }
- #endif
-
- /* new reference, so increment in lock right now */
- fss->objRefCount++;
- }
-
- Tcl_MutexUnlock(&ClockFmtMutex);
-
- if (fss == NULL && interp != NULL) {
- Tcl_AppendResult(interp, "retrieve clock format failed \"",
- strFmt ? strFmt : "", "\"", NULL);
- Tcl_SetErrorCode(interp, "TCL", "EINVAL", NULL);
- }
-
- return fss;
-}
-
-
-/*
* Type definition.
*/
@@ -303,20 +244,11 @@ Tcl_ObjType ClockFmtObjType = {
ClockFmtObj_SetFromAny /* setFromAnyProc */
};
-#define SetObjClockFmtScn(objPtr, fss) \
- objPtr->internalRep.twoPtrValue.ptr1 = fss
#define ObjClockFmtScn(objPtr) \
- (ClockFmtScnStorage *)objPtr->internalRep.twoPtrValue.ptr1;
+ (*((ClockFmtScnStorage **)&(objPtr)->internalRep.twoPtrValue.ptr1))
-#define SetObjLocFmtKey(objPtr, key) \
- Tcl_InitObjRef((Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr2, key)
#define ObjLocFmtKey(objPtr) \
- ((Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr2)
-
-#define ClockFmtObj_SetObjIntRep(objPtr, fss, key) \
- objPtr->internalRep.twoPtrValue.ptr1 = fss; \
- Tcl_InitObjRef((Tcl_Obj *)objPtr->internalRep.twoPtrValue.ptr2, key); \
- objPtr->typePtr = &ClockFmtObjType;
+ (*((Tcl_Obj **)&(objPtr)->internalRep.twoPtrValue.ptr2))
/*
*----------------------------------------------------------------------
@@ -334,7 +266,15 @@ ClockFmtObj_DupInternalRep(srcPtr, copyPtr)
Tcl_MutexUnlock(&ClockFmtMutex);
}
- ClockFmtObj_SetObjIntRep(copyPtr, fss, ObjLocFmtKey(srcPtr));
+ ObjClockFmtScn(copyPtr) = fss;
+ /* regards special case - format not localizable */
+ if (ObjLocFmtKey(srcPtr) != srcPtr) {
+ Tcl_InitObjRef(ObjLocFmtKey(copyPtr), ObjLocFmtKey(srcPtr));
+ } else {
+ ObjLocFmtKey(copyPtr) = copyPtr;
+ }
+ copyPtr->typePtr = &ClockFmtObjType;
+
/* if no format representation, dup string representation */
if (fss == NULL) {
@@ -365,8 +305,12 @@ ClockFmtObj_FreeInternalRep(objPtr)
}
Tcl_MutexUnlock(&ClockFmtMutex);
}
- SetObjClockFmtScn(objPtr, NULL);
- Tcl_UnsetObjRef(ObjLocFmtKey(objPtr));
+ ObjClockFmtScn(objPtr) = NULL;
+ if (ObjLocFmtKey(objPtr) != objPtr) {
+ Tcl_UnsetObjRef(ObjLocFmtKey(objPtr));
+ } else {
+ ObjLocFmtKey(objPtr) = NULL;
+ }
objPtr->typePtr = NULL;
};
/*
@@ -385,8 +329,8 @@ ClockFmtObj_SetFromAny(interp, objPtr)
objPtr->typePtr->freeIntRepProc(objPtr);
/* initial state of format object */
- objPtr->internalRep.twoPtrValue.ptr1 = NULL;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ ObjClockFmtScn(objPtr) = NULL;
+ ObjLocFmtKey(objPtr) = NULL;
objPtr->typePtr = &ClockFmtObjType;
return TCL_OK;
@@ -435,13 +379,74 @@ ClockFrmObjGetLocFmtKey(
}
keyObj = Tcl_ObjPrintf("FMT_%s", TclGetString(objPtr));
- SetObjLocFmtKey(objPtr, keyObj);
+ Tcl_InitObjRef(ObjLocFmtKey(objPtr), keyObj);
return keyObj;
}
/*
*----------------------------------------------------------------------
+ */
+
+static ClockFmtScnStorage *
+FindOrCreateFmtScnStorage(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
+{
+ const char *strFmt = TclGetString(objPtr);
+ ClockFmtScnStorage *fss = NULL;
+ int new;
+ Tcl_HashEntry *hPtr;
+
+ Tcl_MutexLock(&ClockFmtMutex);
+
+ /* if not yet initialized */
+ if (!initialized) {
+ /* initialize type */
+ memcpy(&ClockFmtScnStorageHashKeyType, &tclStringHashKeyType, sizeof(tclStringHashKeyType));
+ ClockFmtScnStorageHashKeyType.allocEntryProc = ClockFmtScnStorageAllocProc;
+ ClockFmtScnStorageHashKeyType.freeEntryProc = ClockFmtScnStorageFreeProc;
+
+ /* initialize hash table */
+ Tcl_InitCustomHashTable(&FmtScnHashTable, TCL_CUSTOM_TYPE_KEYS,
+ &ClockFmtScnStorageHashKeyType);
+
+ initialized = 1;
+ Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL);
+ }
+
+ /* get or create entry (and alocate storage) */
+ hPtr = Tcl_CreateHashEntry(&FmtScnHashTable, strFmt, &new);
+ if (hPtr != NULL) {
+
+ fss = FmtScn4HashEntry(hPtr);
+
+ #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
+ /* unlink if it is currently in GC */
+ if (new == 0 && fss->objRefCount == 0) {
+ ClockFmtScnStorage_GC_Out(fss);
+ }
+ #endif
+
+ /* new reference, so increment in lock right now */
+ fss->objRefCount++;
+
+ ObjClockFmtScn(objPtr) = fss;
+ }
+
+ Tcl_MutexUnlock(&ClockFmtMutex);
+
+ if (fss == NULL && interp != NULL) {
+ Tcl_AppendResult(interp, "retrieve clock format failed \"",
+ strFmt ? strFmt : "", "\"", NULL);
+ Tcl_SetErrorCode(interp, "TCL", "EINVAL", NULL);
+ }
+
+ return fss;
+}
+
+/*
+ *----------------------------------------------------------------------
*
* Tcl_GetClockFrmScnFromObj --
*
@@ -475,8 +480,7 @@ Tcl_GetClockFrmScnFromObj(
fss = ObjClockFmtScn(objPtr);
if (fss == NULL) {
- const char *strFmt = TclGetString(objPtr);
- fss = FindOrCreateFmtScnStorage(interp, strFmt);
+ fss = FindOrCreateFmtScnStorage(interp, objPtr);
}
return fss;
@@ -772,7 +776,7 @@ ClockGetOrParseScanFormat(
fss = ObjClockFmtScn(formatObj);
if (fss == NULL) {
- fss = FindOrCreateFmtScnStorage(interp, TclGetString(formatObj));
+ fss = FindOrCreateFmtScnStorage(interp, formatObj);
if (fss == NULL) {
return NULL;
}
@@ -898,6 +902,72 @@ done:
return fss->scnTok;
}
+MODULE_SCOPE Tcl_Obj *
+ClockLocalizeFormat(
+ ClockFmtScnCmdArgs *opts)
+{
+ ClockClientData *dataPtr = opts->clientData;
+ Tcl_Obj *valObj = NULL, *keyObj;
+
+ keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj);
+
+ /* special case - format object is not localizable */
+ if (keyObj == opts->formatObj) {
+ return opts->formatObj;
+ }
+
+ if (opts->mcDictObj == NULL) {
+ ClockMCDict(opts);
+ if (opts->mcDictObj == NULL)
+ return NULL;
+ }
+
+ /* try to find in cache within locale mc-catalog */
+ if (Tcl_DictObjGet(NULL, opts->mcDictObj,
+ keyObj, &valObj) != TCL_OK) {
+ return NULL;
+ }
+
+ /* call LocalizeFormat locale format fmtkey */
+ if (valObj == NULL) {
+ Tcl_Obj *callargs[4];
+ callargs[0] = dataPtr->literals[LIT_LOCALIZE_FORMAT];
+ callargs[1] = opts->localeObj;
+ callargs[2] = opts->formatObj;
+ callargs[3] = keyObj;
+ Tcl_IncrRefCount(keyObj);
+ if (Tcl_EvalObjv(opts->interp, 4, callargs, 0) != TCL_OK
+ ) {
+ goto clean;
+ }
+
+ valObj = Tcl_GetObjResult(opts->interp);
+
+ /* cache it inside mc-dictionary (this incr. ref count of keyObj/valObj) */
+ if (Tcl_DictObjPut(opts->interp, opts->mcDictObj,
+ keyObj, valObj) != TCL_OK
+ ) {
+ valObj = NULL;
+ goto clean;
+ }
+
+ /* check special case - format object is not localizable */
+ if (valObj == opts->formatObj) {
+ /* mark it as unlocalizable, by setting self as key (without refcount incr) */
+ if (opts->formatObj->typePtr == &ClockFmtObjType) {
+ Tcl_UnsetObjRef(ObjLocFmtKey(opts->formatObj));
+ ObjLocFmtKey(opts->formatObj) = opts->formatObj;
+ }
+ }
+clean:
+
+ Tcl_UnsetObjRef(keyObj);
+ Tcl_ResetResult(opts->interp);
+ }
+
+ return (opts->formatObj = valObj);
+}
+
/*
*----------------------------------------------------------------------
*/
@@ -917,7 +987,6 @@ ClockScan(
int ret = TCL_ERROR;
/* get localized format */
-
if (ClockLocalizeFormat(opts) == NULL) {
return TCL_ERROR;
}