summaryrefslogtreecommitdiffstats
path: root/tcllib/modules/pt/rde_critcl/ot.c
diff options
context:
space:
mode:
Diffstat (limited to 'tcllib/modules/pt/rde_critcl/ot.c')
-rw-r--r--tcllib/modules/pt/rde_critcl/ot.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/tcllib/modules/pt/rde_critcl/ot.c b/tcllib/modules/pt/rde_critcl/ot.c
new file mode 100644
index 0000000..3b99b04
--- /dev/null
+++ b/tcllib/modules/pt/rde_critcl/ot.c
@@ -0,0 +1,236 @@
+/*
+ * = = == === ===== ======== ============= =====================
+ * == pt::rde (critcl) - Data Structures - Tcl_ObjType for interned strings.
+ *
+ */
+
+#include <ot.h> /* Our public API */
+#include <util.h> /* Allocation macros */
+#include <pInt.h> /* API to basic intern(ing) of strings */
+#include <string.h>
+
+/*
+ * = = == === ===== ======== ============= =====================
+ */
+
+static void ot_free_rep (Tcl_Obj* obj);
+static void ot_dup_rep (Tcl_Obj* obj, Tcl_Obj* dup);
+static void ot_string_rep (Tcl_Obj* obj);
+static int ot_from_any (Tcl_Interp* ip, Tcl_Obj* obj);
+
+static Tcl_ObjType ot_type = {
+ "tcllib/pt::rde/critcl",
+ ot_free_rep,
+ ot_dup_rep,
+ ot_string_rep,
+ ot_from_any
+};
+
+static int IsCached (RDE_STATE p, Tcl_Obj* obj, long int* id);
+static long int Make (RDE_STATE p, Tcl_Obj* obj, const char* str);
+
+
+/*
+ * = = == === ===== ======== ============= =====================
+ */
+
+long int
+rde_ot_intern0 (RDE_STATE p,
+ Tcl_Obj* detail)
+{
+ long int id;
+
+ TRACE (("rde_ot_intern0 (%p, %p = '%s')", p, detail, Tcl_GetString(detail)));
+ if (IsCached (p, detail, &id)) {
+ return id;
+ }
+
+ TRACE (("INTERNALIZE"));
+ return Make (p, detail, Tcl_GetString (detail));
+}
+
+long int
+rde_ot_intern1 (RDE_STATE p,
+ const char* operator,
+ Tcl_Obj* detail)
+{
+ long int id;
+ Tcl_DString buf;
+
+ TRACE (("rde_ot_intern1 (%p, '%s' %p = '%s')", p, operator, detail, Tcl_GetString(detail)));
+ if (IsCached (p, detail, &id)) {
+ return id;
+ }
+
+ TRACE (("INTERNALIZE"));
+
+ /* Create a list of operator + detail.
+ * Using a DString.
+ */
+
+ Tcl_DStringInit (&buf);
+ Tcl_DStringAppendElement (&buf, operator);
+ Tcl_DStringAppendElement (&buf, Tcl_GetString (detail));
+
+ id = Make (p, detail, Tcl_DStringValue (&buf));
+
+ Tcl_DStringFree (&buf);
+ return id;
+}
+
+long int
+rde_ot_intern2 (RDE_STATE p,
+ const char* operator,
+ Tcl_Obj* detail1,
+ Tcl_Obj* detail2)
+{
+ long int id;
+ Tcl_DString buf;
+
+ TRACE (("rde_ot_intern2 (%p, '%s' %p = '%s', %p = '%s')", p, operator,
+ detail1, Tcl_GetString(detail1)
+ detail2, Tcl_GetString(detail2)));
+ if (IsCached (p, detail1, &id)) {
+ return id;
+ }
+
+ TRACE (("INTERNALIZE"));
+
+ /* Create a list of operator + detail1 + detail2.
+ * Using a DString.
+ */
+
+ Tcl_DStringInit (&buf);
+ Tcl_DStringAppendElement (&buf, operator);
+ Tcl_DStringAppendElement (&buf, Tcl_GetString (detail1));
+ Tcl_DStringAppendElement (&buf, Tcl_GetString (detail2));
+
+ id = Make (p, detail1, Tcl_DStringValue (&buf));
+
+ Tcl_DStringFree (&buf);
+ return id;
+}
+
+/*
+ * = = == === ===== ======== ============= =====================
+ */
+
+static int
+IsCached (RDE_STATE p, Tcl_Obj* obj, long int* id)
+{
+ /*
+ * Quick exit if we have a cached and valid value.
+ */
+
+ if ((obj->typePtr == &ot_type) &&
+ (obj->internalRep.twoPtrValue.ptr1 == p)) {
+ RDE_STRING* rs = (RDE_STRING*) obj->internalRep.twoPtrValue.ptr2;
+ TRACE (("CACHED %p = %d", rs, rs->id));
+ *id = rs->id;
+ return 1;
+ }
+
+ return 0;
+}
+
+static long int
+Make (RDE_STATE p, Tcl_Obj* obj, const char* str)
+{
+ long int id = param_intern (p, str);
+ RDE_STRING* rs = ALLOC (RDE_STRING);
+
+ rs->next = p->sfirst;
+ rs->self = obj;
+ rs->id = id;
+ p->sfirst = rs;
+
+ /* Invalidate previous int.rep before setting our own.
+ * Inlined copy of TclFreeIntRep() macro (tclInt.h)
+ */
+
+ if ((obj)->typePtr &&
+ (obj)->typePtr->freeIntRepProc) {
+ (obj)->typePtr->freeIntRepProc(obj);
+ }
+
+ obj->internalRep.twoPtrValue.ptr1 = p;
+ obj->internalRep.twoPtrValue.ptr2 = rs;
+ obj->typePtr = &ot_type;
+
+ return id;
+}
+
+/*
+ * = = == === ===== ======== ============= =====================
+ */
+
+static void
+ot_free_rep(Tcl_Obj* obj)
+{
+ RDE_STATE p = (RDE_STATE) obj->internalRep.twoPtrValue.ptr1;
+ RDE_STRING* rs = (RDE_STRING*) obj->internalRep.twoPtrValue.ptr2;
+
+ /* Take structure out of the tracking list. */
+ if (p->sfirst == rs) {
+ p->sfirst = rs->next;
+ } else {
+ RDE_STRING* iter = p->sfirst;
+ while (iter->next != rs) {
+ iter = iter->next;
+ }
+ iter->next = rs->next;
+ }
+
+ /* Drop the now un-tracked structure */
+ ckfree ((char*) rs);
+
+ /* Nothing to release in the obj itself, just resetting references. */
+ obj->internalRep.twoPtrValue.ptr1 = NULL;
+ obj->internalRep.twoPtrValue.ptr2 = NULL;
+}
+
+static void
+ot_dup_rep(Tcl_Obj* obj, Tcl_Obj* dup)
+{
+ RDE_STRING* ors = (RDE_STRING*) obj->internalRep.twoPtrValue.ptr2;
+ RDE_STRING* drs;
+ RDE_STATE p = ((RDE_STATE) obj->internalRep.twoPtrValue.ptr1);
+
+ drs = ALLOC (RDE_STRING);
+ drs->next = p->sfirst;
+ drs->self = dup;
+ drs->id = ors->id;
+ p->sfirst = drs;
+
+ dup->internalRep.twoPtrValue.ptr1 = obj->internalRep.twoPtrValue.ptr1;
+ dup->internalRep.twoPtrValue.ptr2 = drs;
+ dup->typePtr = &ot_type;
+}
+
+static void
+ot_string_rep(Tcl_Obj* obj)
+{
+ (void) obj;
+ ASSERT (0, "Attempted reconversion of rde string to string rep");
+}
+
+static int
+ot_from_any(Tcl_Interp* ip, Tcl_Obj* obj)
+{
+ (void) ip;
+ (void) obj;
+ ASSERT (0, "Illegal conversion into rde string");
+ return TCL_ERROR;
+}
+/*
+ * = = == === ===== ======== ============= =====================
+ */
+
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */