27bc862691948186b0b766f090c1e578219a179e
[SXSI/XMLTree.git] / XMLTreeBuilder.cpp
1 \r
2 #include "XMLTreeBuilder.h"\r
3 #include "basics.h"\r
4 \r
5 // OpenDocument(empty_texts): it starts the construction of the data structure for\r
6 // the XML document. Parameter empty_texts indicates whether we index empty texts\r
7 // in document or not. Returns a non-zero value upon success, NULLT in case of error.\r
8 int XMLTreeBuilder::OpenDocument(bool empty_texts, int sample_rate_text, bool dtc)\r
9  {\r
10     found_attributes = false;\r
11     npar = 0;\r
12     parArraySize = 1;\r
13     ntagnames = 4;    \r
14     disable_tc = dtc;\r
15     \r
16     indexing_empty_texts = empty_texts;\r
17     \r
18     par_aux = (pb *)umalloc(sizeof(pb)*parArraySize);\r
19     \r
20     tags_aux = (TagType *) umalloc(sizeof(TagType));\r
21     \r
22     TagName = (unsigned char **) umalloc(4*sizeof(unsigned char*));\r
23     TagName[0] = (unsigned char *) umalloc(4*sizeof(unsigned char));\r
24     strcpy((char *) TagName[0], "<@>");\r
25     TagName[1] = (unsigned char *) umalloc(4*sizeof(unsigned char));\r
26     strcpy((char *) TagName[1], "<$>");\r
27     TagName[2] = (unsigned char *) umalloc(5*sizeof(unsigned char));\r
28     strcpy((char *) TagName[2], "/<@>");\r
29     TagName[3] = (unsigned char *) umalloc(5*sizeof(unsigned char));\r
30     strcpy((char *) TagName[3], "/<$>");\r
31 \r
32     if (!indexing_empty_texts) \r
33       empty_texts_aux = (unsigned int *)umalloc(sizeof(unsigned int));\r
34        \r
35     if (disable_tc)\r
36         TextBuilder = 0;\r
37     else \r
38         TextBuilder = new TextCollectionBuilder((unsigned)sample_rate_text);\r
39     Text = 0;\r
40     \r
41     return 1;  // indicates success in the initialization of the data structure\r
42  }\r
43 \r
44 // CloseDocument(): it finishes the construction of the data structure for the XML\r
45 // document. Tree and tags are represented in the final form, dynamic data \r
46 // structures are made static, and the flag "finished" is set to true. After that, \r
47 // the data structure can be queried.\r
48 XMLTree *XMLTreeBuilder::CloseDocument()\r
49  {    \r
50     // closing parenthesis for the tree root\r
51     par_aux = (pb *)urealloc(par_aux, sizeof(pb)*(1+npar/(8*sizeof(pb))));\r
52     setbit(par_aux, npar, CP);\r
53     npar++;\r
54     \r
55     // makes the text collection static\r
56     if (!disable_tc) {\r
57        assert(Text == 0);\r
58        assert(TextBuilder != 0);\r
59        Text = TextBuilder->InitTextCollection();\r
60        delete TextBuilder;\r
61        TextBuilder = 0;\r
62     }\r
63 \r
64     XMLTree *T = new XMLTree(par_aux, npar, TagName, ntagnames, empty_texts_aux, tags_aux, \r
65               Text, CachedText, indexing_empty_texts, disable_tc);\r
66     return T; \r
67  }\r
68 \r
69 \r
70 // NewOpenTag(tagname): indicates the event of finding a new opening tag in the document.\r
71 // Tag name is given. Returns a non-zero value upon success, and returns NULLT\r
72 // in case of failing when trying to insert the new tag.\r
73 int XMLTreeBuilder::NewOpenTag(unsigned char *tagname)\r
74  {\r
75     int i;\r
76     \r
77     // inserts a new opening parentheses in the bit sequence\r
78     if (sizeof(pb)*8*parArraySize == npar) { // no space left for the new parenthesis\r
79        par_aux = (pb *)urealloc(par_aux, sizeof(pb)*2*parArraySize);\r
80        parArraySize *= 2;\r
81     }\r
82     \r
83     setbit(par_aux,npar,OP);  // marks a new opening parenthesis\r
84 \r
85     // transforms the tagname into a tag identifier. If the tag is new, we insert\r
86     // it in the table.\r
87     for (i=0; i<ntagnames; i++)\r
88       if (strcmp((const char *)tagname,(const char *)TagName[i])==0) break;\r
89  \r
90 \r
91     // NewOpenTag("<@>") was called\r
92     if (i==0) \r
93       found_attributes=true;\r
94 \r
95     if (i==ntagnames) { // the tag is a new one, then we insert it\r
96        TagName = (unsigned char **)urealloc(TagName, sizeof(char *)*(ntagnames+1));\r
97        \r
98        if (!TagName) {\r
99           fprintf(stderr, "Error: not enough memory\n");\r
100           return NULLT;\r
101        }\r
102        \r
103        ntagnames++;\r
104        TagName[i] = (unsigned char *)umalloc(sizeof(unsigned char)*(strlen((const char *)tagname)+1));\r
105        strcpy((char *)TagName[i], (const char *)tagname);\r
106     } \r
107     tags_aux = (TagType *) urealloc(tags_aux, sizeof(TagType)*(npar + 1));\r
108 \r
109     tags_aux[npar] = i; // inserts the new tag id within the preorder sequence of tags\r
110     \r
111     npar++;\r
112     \r
113     return 1; // success    \r
114  }\r
115 \r
116 \r
117 // NewClosingTag(tagname): indicates the event of finding a new closing tag in the document.\r
118 // Tag name is given. Returns a non-zero value upon success, and returns NULLT\r
119 // in case of failing when trying to insert the new tag.\r
120 int XMLTreeBuilder::NewClosingTag(unsigned char *tagname)\r
121  {\r
122     int i;\r
123     \r
124     // inserts a new closing parentheses in the bit sequence\r
125     if (sizeof(pb)*8*parArraySize == npar) { // no space left for the new parenthesis\r
126        par_aux = (pb *)urealloc(par_aux, sizeof(pb)*2*parArraySize);\r
127        parArraySize *= 2;\r
128     }\r
129     \r
130     setbit(par_aux,npar,CP);  // marks a new closing parenthesis\r
131 \r
132     // transforms the tagname into a tag identifier. If the tag is new, we insert\r
133     // it in the table.\r
134     for (i=0; i<ntagnames; i++)\r
135        if ((strcmp((const char *)tagname,(const char *)(TagName[i]+1))==0) && (TagName[i][0]=='/')) break;\r
136  \r
137     if (i==ntagnames) { // the tag is a new one, then we insert it\r
138        TagName = (unsigned char **)urealloc(TagName, sizeof(char *)*(ntagnames+1));\r
139        \r
140        ntagnames++;\r
141        TagName[i] = (unsigned char *)umalloc(sizeof(char)*(strlen((const char *)tagname)+2));\r
142        TagName[i][0] = '/';\r
143        strcpy((char *)&(TagName[i][1]), (const char *)tagname);\r
144     } \r
145 \r
146     tags_aux = (TagType *)urealloc(tags_aux, sizeof(TagType)*(npar + 1));\r
147 \r
148     tags_aux[npar] = i; // inserts the new tag id within the preorder sequence of tags\r
149     \r
150     npar++;\r
151 \r
152     return 1; // success\r
153  }\r
154 \r
155 \r
156 // NewText(s): indicates the event of finding a new (non-empty) text s in the document.\r
157 // The new text is inserted within the text collection. Returns a non-zero value upon\r
158 // success, NULLT in case of error.\r
159 int XMLTreeBuilder::NewText(unsigned char *s)\r
160  {\r
161     if (disable_tc) {\r
162       XMLTreeBuilder::NewEmptyText();\r
163       return 1;\r
164     }\r
165 \r
166     if (!indexing_empty_texts) {\r
167        empty_texts_aux = (unsigned int *)urealloc(empty_texts_aux, sizeof(pb)*(1+(npar-1)/(8*sizeof(pb))));\r
168               bitset(empty_texts_aux, npar-1);  // marks the non-empty text with a 1 in the bit vector\r
169     }\r
170     \r
171     TextBuilder->InsertText(s);\r
172     string cpps = (char*) s;\r
173     CachedText.push_back(cpps); \r
174     \r
175     return 1; // success\r
176  }\r
177 \r
178 // NewEmptyText(): indicates the event of finding a new empty text in the document.\r
179 // In case of indexing empty and non-empty texts, we insert the empty texts into the\r
180 // text collection. In case of indexing only non-empty texts, it just indicates an\r
181 // empty text in the bit vector of empty texts. Returns a non-zero value upon\r
182 // success, NULLT in case of error.\r
183 int XMLTreeBuilder::NewEmptyText() \r
184  {\r
185     unsigned char c = 0;\r
186 \r
187     if (!indexing_empty_texts) {\r
188        empty_texts_aux = (unsigned int *)urealloc(empty_texts_aux, sizeof(pb)*(1+(npar-1)/(8*sizeof(pb))));\r
189        \r
190        bitclean(empty_texts_aux, npar-1);  // marks the empty text with a 0 in the bit vector\r
191     }\r
192     else TextBuilder->InsertText(&c); // we insert the empty text just in case we index all the texts\r
193     \r
194     return 1; // success    \r
195  }\r
196 \r