Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added an optimization in case of serveral easily distinguished choices in a choice content particle.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: 19b4a5d0ea2705b866665853e00ba04489039cd8e83266c54e7cf21f79e21a35
User & Date: rolf 2020-02-01 01:22:30
Context
2020-02-04
01:11
Fasten work. check-in: 121b7f42ad user: rolf tags: schema
2020-02-01
01:22
Added an optimization in case of serveral easily distinguished choices in a choice content particle. check-in: 19b4a5d0ea user: rolf tags: schema
01:12
Added a configurable threshold for the optimization. Closed-Leaf check-in: 3ae775c452 user: rolf tags: mixedoptimization
2020-01-21
00:57
Added the schema definition command associate and the requesting method info stack associated, tests and doc. check-in: 254c84e47d user: rolf tags: schema
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/schema.c.

32
33
34
35
36
37
38



39
40
41
42
43
44
45
...
527
528
529
530
531
532
533




534
535
536
537
538
539
540
...
585
586
587
588
589
590
591

592
593
594
595
596
597
598
....
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
....
1221
1222
1223
1224
1225
1226
1227














1228
1229
1230
1231
1232
1233
1234
....
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
....
3956
3957
3958
3959
3960
3961
3962
3963

3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980








3981
3982
3983
3984
3985
3986
3987
....
4542
4543
4544
4545
4546
4547
4548



























4549
4550
4551
4552
4553
4554
4555
....
4765
4766
4767
4768
4769
4770
4771
4772

4773
4774
4775
4776
4777
4778
4779
....
4799
4800
4801
4802
4803
4804
4805

4806





4807
4808
4809
4810
4811
4812


























4813
4814
4815
4816
4817
4818
4819

#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#endif




#ifndef TDOM_EXPAT_READ_SIZE
# define TDOM_EXPAT_READ_SIZE (1024*8)
#endif
#ifndef O_BINARY
#ifdef _O_BINARY
#define O_BINARY _O_BINARY
#else
................................................................................
        if (pattern->attrs) {
            for (i = 0; i < pattern->numAttr; i++) {
                FREE (pattern->attrs[i]);
            }
            FREE (pattern->attrs);
        }
        freedomKeyConstraints (pattern->domKeys);




        break;
    }
    if (pattern->defScript) {
        Tcl_DecrRefCount (pattern->defScript);
    }
    if (pattern->associated) {
        Tcl_DecrRefCount (pattern->associated);
................................................................................
    Tcl_IncrRefCount (sdata->textStub[2]);
    sdata->cdata = TMALLOC (Tcl_DString);
    Tcl_DStringInit (sdata->cdata);
    Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS);
    sdata->unknownIDrefs = 0;
    Tcl_InitHashTable (&sdata->idTables, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->keySpaces, TCL_STRING_KEYS);

    return sdata;
}

static void schemaInstanceDelete (
    ClientData clientData
    )
{
................................................................................
    char *namespace
    )
{
    SchemaCP *cp, *candidate, *icp;
    int hm, ac, i, mayskip, rc;
    int isName = 0;
    SchemaValidationStack *se;


    if (!sdata->stack) return 0;
    se = sdata->stack;
    getContext (cp, ac, hm);

    switch (cp->type) {
    case SCHEMA_CTYPE_NAME:
................................................................................
                    pushToStack (sdata, candidate);
                    updateStack (se, cp, ac);
                    return 1;
                }
                break;

            case SCHEMA_CTYPE_CHOICE:














                for (i = 0; i < candidate->nc; i++) {
                    icp = candidate->content[i];
                    switch (icp->type) {
                    case SCHEMA_CTYPE_TEXT:
                        break;

                    case SCHEMA_CTYPE_ANY:
................................................................................
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    int            methodIndex, keywordIndex, hnew, hnew1, patternIndex;
    int            result = TCL_OK, forwardDef = 0, i = 0, j, mode;
    int            savedDefineToplevel, type, len;
    unsigned int   savedNumPatternList;
    SchemaData    *savedsdata = NULL, *sdata = (SchemaData *) clientData;
    Tcl_HashTable *hashTable;
    Tcl_HashEntry *h, *h1;
    SchemaCP      *pattern, *thiscp, *current = NULL;
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
................................................................................
    Tcl_Obj       *attData;
    Tcl_Channel  chan = NULL;

    static const char *schemaInstanceMethods[] = {
        "defelement", "defpattern", "start",    "event",        "delete",
        "reset",      "define",     "validate", "domvalidate",  "deftext",
        "info",       "reportcmd",  "prefixns", "validatefile",
        "validatechannel",          "defelementtype", NULL

    };
    enum schemaInstanceMethod {
        m_defelement, m_defpattern, m_start,    m_event,        m_delete,
        m_reset,      m_define,     m_validate, m_domvalidate,  m_deftext,
        m_info,       m_reportcmd,  m_prefixns, m_validatefile,
        m_validatechannel,          m_defelementtype
    };

    static const char *eventKeywords[] = {
        "start", "end", "text", NULL
    };

    enum eventKeyword
    {
        k_elementstart, k_elementend, k_text
    };









    if (sdata == NULL) {
        /* Inline defined defelement, defelementtype, defpattern,
         * deftext, start or prefixns */
        sdata = GETASI;
        CHECK_SI;
        if (!sdata->defineToplevel && sdata->currentEvals > 1) {
            SetResult ("Method not allowed in nested schema define script");
................................................................................
        sdata->defineToplevel = savedDefineToplevel;
        sdata->currentNamespace = savedNamespacePtr;
        if (!savedDefineToplevel) {
            SETASI(savedsdata);
        }
        break;
            



























    default:
        Tcl_SetResult (interp, "unknown method", NULL);
        result = TCL_ERROR;
        break;

    }
    if (sdata->cleanupAfterUse && sdata->currentEvals == 0
................................................................................
    int m
    )
{
    SchemaCP *savedCP;
    SchemaAttr **savedCurrentAttrs;
    unsigned int savedContenSize;
    unsigned int savedAttrSize, savedNumAttr, savedNumReqAttr;
    int result, i;


    /* Save some state of sdata .. */
    savedCP = sdata->cp;
    savedContenSize = sdata->contentSize;
    savedNumAttr = sdata->numAttr;
    savedNumReqAttr = sdata->numReqAttr;
    savedAttrSize = sdata->attrSize;
................................................................................
    sdata->numAttr = savedNumAttr;
    sdata->numReqAttr = savedNumReqAttr;
    sdata->currentAttrs = savedCurrentAttrs;
    sdata->attrSize = savedAttrSize;

    if (result == TCL_OK) {
        REMEMBER_PATTERN (pattern);

        for (i = 0; i < pattern->nc; i++) {





            if (pattern->content[i]->type == SCHEMA_CTYPE_PATTERN) {
                if (pattern->content[i]->flags & CONSTRAINT_TEXT_CHILD) {
                    pattern->flags |= CONSTRAINT_TEXT_CHILD;
                    break;
                }
            }


























        }
        addToContent (sdata, pattern, quant, n, m);
    } else {
        freeSchemaCP (pattern);
    }
    return result;
}







>
>
>







 







>
>
>
>







 







>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|
>





|





<





>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>







 







>

>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
...
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
....
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
....
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
....
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
....
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998

3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
....
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
....
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
....
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910

#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#endif

#ifndef TDOM_CHOICE_HASH_THRESHOLD
# define TDOM_CHOICE_HASH_THRESHOLD 5
#endif
#ifndef TDOM_EXPAT_READ_SIZE
# define TDOM_EXPAT_READ_SIZE (1024*8)
#endif
#ifndef O_BINARY
#ifdef _O_BINARY
#define O_BINARY _O_BINARY
#else
................................................................................
        if (pattern->attrs) {
            for (i = 0; i < pattern->numAttr; i++) {
                FREE (pattern->attrs[i]);
            }
            FREE (pattern->attrs);
        }
        freedomKeyConstraints (pattern->domKeys);
        if (pattern->childs) {
            Tcl_DeleteHashTable (pattern->childs);
            FREE (pattern->childs);
        }
        break;
    }
    if (pattern->defScript) {
        Tcl_DecrRefCount (pattern->defScript);
    }
    if (pattern->associated) {
        Tcl_DecrRefCount (pattern->associated);
................................................................................
    Tcl_IncrRefCount (sdata->textStub[2]);
    sdata->cdata = TMALLOC (Tcl_DString);
    Tcl_DStringInit (sdata->cdata);
    Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS);
    sdata->unknownIDrefs = 0;
    Tcl_InitHashTable (&sdata->idTables, TCL_STRING_KEYS);
    Tcl_InitHashTable (&sdata->keySpaces, TCL_STRING_KEYS);
    sdata->choiceHashThreshold = TDOM_CHOICE_HASH_THRESHOLD;
    return sdata;
}

static void schemaInstanceDelete (
    ClientData clientData
    )
{
................................................................................
    char *namespace
    )
{
    SchemaCP *cp, *candidate, *icp;
    int hm, ac, i, mayskip, rc;
    int isName = 0;
    SchemaValidationStack *se;
    Tcl_HashEntry *h;

    if (!sdata->stack) return 0;
    se = sdata->stack;
    getContext (cp, ac, hm);

    switch (cp->type) {
    case SCHEMA_CTYPE_NAME:
................................................................................
                    pushToStack (sdata, candidate);
                    updateStack (se, cp, ac);
                    return 1;
                }
                break;

            case SCHEMA_CTYPE_CHOICE:
                if (candidate->childs) {
                    h = Tcl_FindHashEntry (candidate->childs, name);
                    if (h) {
                        icp = Tcl_GetHashValue (h);
                        if (icp->namespace == namespace) {
                            pushToStack (sdata, icp);
                            updateStack (se, cp, ac);
                            return 1;
                        }
                    }
                    /* TODO: Short-cut in case of no match (looking
                     * for emtpy match, recovering). For now fall
                     * throu to simple, serial approach. */
                }
                for (i = 0; i < candidate->nc; i++) {
                    icp = candidate->content[i];
                    switch (icp->type) {
                    case SCHEMA_CTYPE_TEXT:
                        break;

                    case SCHEMA_CTYPE_ANY:
................................................................................
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[]
    )
{
    int            methodIndex, keywordIndex, hnew, hnew1, patternIndex;
    int            result = TCL_OK, forwardDef = 0, i = 0, j, mode;
    int            savedDefineToplevel, type, len, n;
    unsigned int   savedNumPatternList;
    SchemaData    *savedsdata = NULL, *sdata = (SchemaData *) clientData;
    Tcl_HashTable *hashTable;
    Tcl_HashEntry *h, *h1;
    SchemaCP      *pattern, *thiscp, *current = NULL;
    void          *namespacePtr, *savedNamespacePtr;
    char          *xmlstr, *errMsg;
................................................................................
    Tcl_Obj       *attData;
    Tcl_Channel  chan = NULL;

    static const char *schemaInstanceMethods[] = {
        "defelement", "defpattern", "start",    "event",        "delete",
        "reset",      "define",     "validate", "domvalidate",  "deftext",
        "info",       "reportcmd",  "prefixns", "validatefile",
        "validatechannel",          "defelementtype",           "set",
        NULL
    };
    enum schemaInstanceMethod {
        m_defelement, m_defpattern, m_start,    m_event,        m_delete,
        m_reset,      m_define,     m_validate, m_domvalidate,  m_deftext,
        m_info,       m_reportcmd,  m_prefixns, m_validatefile,
        m_validatechannel,          m_defelementtype,           m_set
    };

    static const char *eventKeywords[] = {
        "start", "end", "text", NULL
    };

    enum eventKeyword
    {
        k_elementstart, k_elementend, k_text
    };

    static const char *setKeywords[] = {
        "choiceHashThreshold",  NULL
    };
    enum setKeyword
    {
        s_choiceHashThreshold
    };
        
    if (sdata == NULL) {
        /* Inline defined defelement, defelementtype, defpattern,
         * deftext, start or prefixns */
        sdata = GETASI;
        CHECK_SI;
        if (!sdata->defineToplevel && sdata->currentEvals > 1) {
            SetResult ("Method not allowed in nested schema define script");
................................................................................
        sdata->defineToplevel = savedDefineToplevel;
        sdata->currentNamespace = savedNamespacePtr;
        if (!savedDefineToplevel) {
            SETASI(savedsdata);
        }
        break;
            
    case m_set:
        if (objc < 3 || objc > 4) {
            Tcl_WrongNumArgs (interp, 2, objv, "setting ?value?");
            return TCL_ERROR;
        }        
        if (Tcl_GetIndexFromObj (interp, objv[2], setKeywords,
                                 "setting", 0, &keywordIndex)
            != TCL_OK) {
            return TCL_ERROR;
        }
        switch ((enum setKeyword) keywordIndex) {
        case s_choiceHashThreshold:
            if (objc == 4) {
                if (Tcl_GetIntFromObj (interp, objv[3], &n) != TCL_OK) {
                    SetResult ("Invalid threshold value");
                    return TCL_ERROR;
                }
                if (n < 0) {
                    SetResult ("Invalid threshold value");
                    return TCL_ERROR;
                }
                sdata->choiceHashThreshold = n;
            }
            SetIntResult (sdata->choiceHashThreshold);
        }
        break;
        
    default:
        Tcl_SetResult (interp, "unknown method", NULL);
        result = TCL_ERROR;
        break;

    }
    if (sdata->cleanupAfterUse && sdata->currentEvals == 0
................................................................................
    int m
    )
{
    SchemaCP *savedCP;
    SchemaAttr **savedCurrentAttrs;
    unsigned int savedContenSize;
    unsigned int savedAttrSize, savedNumAttr, savedNumReqAttr;
    int result, i, onlyName, hnew;
    Tcl_HashEntry *h;

    /* Save some state of sdata .. */
    savedCP = sdata->cp;
    savedContenSize = sdata->contentSize;
    savedNumAttr = sdata->numAttr;
    savedNumReqAttr = sdata->numReqAttr;
    savedAttrSize = sdata->attrSize;
................................................................................
    sdata->numAttr = savedNumAttr;
    sdata->numReqAttr = savedNumReqAttr;
    sdata->currentAttrs = savedCurrentAttrs;
    sdata->attrSize = savedAttrSize;

    if (result == TCL_OK) {
        REMEMBER_PATTERN (pattern);
        onlyName = 1;
        for (i = 0; i < pattern->nc; i++) {
            if (onlyName
                && pattern->content[i]->type != SCHEMA_CTYPE_NAME
                && pattern->content[i]->type != SCHEMA_CTYPE_TEXT) {
                onlyName = 0;
            }
            if (pattern->content[i]->type == SCHEMA_CTYPE_PATTERN) {
                if (pattern->content[i]->flags & CONSTRAINT_TEXT_CHILD) {
                    pattern->flags |= CONSTRAINT_TEXT_CHILD;
                    break;
                }
            }
        }
        if (pattern->type == SCHEMA_CTYPE_CHOICE
            && onlyName
            && pattern->nc > sdata->choiceHashThreshold) {
            pattern->childs = TMALLOC (Tcl_HashTable);
            Tcl_InitHashTable (pattern->childs, TCL_ONE_WORD_KEYS);
            hnew = 1;
            for (i = 0; i < pattern->nc; i++) {
                if (pattern->content[i]->type != SCHEMA_CTYPE_NAME) {
                    continue;
                }
                h = Tcl_CreateHashEntry (pattern->childs,
                                         pattern->content[i]->name, &hnew);
                if (!hnew) {
                    break;
                }
                Tcl_SetHashValue (h, pattern->content[i]);
            }
            if (!hnew) {
                /* No simple lookup possible because of more than one
                 * elements with the same local name belong to the
                 * choices. Rewind. */
                Tcl_DeleteHashTable (pattern->childs);
                FREE (pattern->childs);
                pattern->childs = NULL;
            }
        }
        addToContent (sdata, pattern, quant, n, m);
    } else {
        freeSchemaCP (pattern);
    }
    return result;
}

Changes to generic/schema.h.

102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
186
187
188
189
190
191
192

193
194
195
196
197
198
199
    char             *name;
    char             *typeName;
    struct SchemaCP  *next;
    SchemaFlags       flags;
    struct SchemaCP **content;
    SchemaQuant      *quants;
    unsigned int      nc;

    SchemaAttr      **attrs;
    unsigned int      numAttr;
    unsigned int      numReqAttr;
    domKeyConstraint *domKeys;
    SchemaKeySpace   *keySpace;
    Tcl_Obj          *defScript;
    Tcl_Obj          *associated;
................................................................................
    Tcl_DString *cdata;
    Tcl_HashTable ids;
    int unknownIDrefs;
    Tcl_HashTable idTables;
    Tcl_HashTable keySpaces;
    XML_Parser parser;
    domNode *node;

} SchemaData;

int 
schemaInstanceCmd (
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,







>







 







>







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
    char             *name;
    char             *typeName;
    struct SchemaCP  *next;
    SchemaFlags       flags;
    struct SchemaCP **content;
    SchemaQuant      *quants;
    unsigned int      nc;
    Tcl_HashTable    *childs;
    SchemaAttr      **attrs;
    unsigned int      numAttr;
    unsigned int      numReqAttr;
    domKeyConstraint *domKeys;
    SchemaKeySpace   *keySpace;
    Tcl_Obj          *defScript;
    Tcl_Obj          *associated;
................................................................................
    Tcl_DString *cdata;
    Tcl_HashTable ids;
    int unknownIDrefs;
    Tcl_HashTable idTables;
    Tcl_HashTable keySpaces;
    XML_Parser parser;
    domNode *node;
    int choiceHashThreshold;
} SchemaData;

int 
schemaInstanceCmd (
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,