2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
12 * The Original Code is the Sablotron XSLT Processor.
14 * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15 * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16 * Ginger Alliance Ltd. All Rights Reserved.
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU General Public License Version 2 or later (the
22 * "GPL"), in which case the provisions of the GPL are applicable
23 * instead of those above. If you wish to allow use of your
24 * version of this file only under the terms of the GPL and not to
25 * allow others to use your version of this file under the MPL,
26 * indicate your decision by deleting the provisions above and
27 * replace them with the notice and other provisions required by
28 * the GPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under either the MPL or the
38 // GP: clean (only 1 eFlag routine)
40 // #include <malloc.h> - not needed and deprecated anyway
42 /* const Str* theEmptyString = new Str(""); */
44 // implementations for List are in datastr.h (List is a template)
47 /*****************************************************************
50 is a class for "dynamic memory blocks", i.e. blocks that can
52 *****************************************************************/
60 inline void DynBlock::remove()
62 DynBlockItem *d, *d_was;
69 delete [] d_was -> data;
82 inline Bool DynBlock::isEmpty() const
87 void DynBlock::nadd(const char *data, int bytes)
89 DynBlockItem *newitem = new DynBlockItem;
90 newitem -> data = new char[bytes];
91 memcpy(newitem -> data, data, bytes);
92 newitem -> byteCount = bytes;
93 newitem -> next = NULL;
95 last -> next = newitem;
102 char* DynBlock::getPointer() const
108 return (first -> data);
111 // compactToBuffer() joins the parts in a buffer. Returns buf+byteCount.
112 // if kill_ then the parts will be deallocated
114 int DynBlock::compactToBuffer_(char* buf, Bool kill_)
116 int compactedBytes = 0;
120 DynBlockItem *d, *d_was;
123 memcpy(p, d -> data, d -> byteCount);
125 compactedBytes += d -> byteCount;
126 d = (d_was = d) -> next;
129 delete[] d_was -> data;
139 return compactedBytes;
143 #define thisNoConst (const_cast<DynBlock*>(this))
146 char* DynBlock::compactToBuffer() const
148 char *newdata = new char[byteCount+1];
149 newdata[thisNoConst -> compactToBuffer_(newdata, FALSE)] = 0;
153 void DynBlock::compact() const
155 if (!first || !(first -> next)) return;
156 int byteCountWas = byteCount;
157 char *newdata = new char[byteCount];
158 thisNoConst -> compactToBuffer_(newdata, TRUE);
159 thisNoConst -> first = thisNoConst -> last = new DynBlockItem;
160 thisNoConst -> first -> data = newdata;
161 thisNoConst -> byteCount = first -> byteCount = byteCountWas;
162 thisNoConst -> first -> next = NULL;
169 // a flavour of DynBlock for use in dynamic strings
171 // compactString() allocates a new buffer to hold 'firstPart'
172 // plus the concat of all the DynStrBlock's parts. Kills the parts
173 // of the DynStrBlock.
175 char* DynStrBlock::compactString_(const char *firstPart, int firstLen)
177 int newLength = firstLen + byteCount;
178 char *newdata = new char[newLength + 1];
180 memcpy(newdata, firstPart, firstLen);
182 compactToBuffer_(newdata + firstLen, TRUE);
183 newdata[newLength] = 0;
202 Str::Str(const Str& string)
226 Str::Str(const char *chars)
234 Str::Str(const DStr &dstring)
240 Str& Str::operator=(const Str& string)
243 int hisByteLen = string.length();
244 byteLength_ = hisByteLen;
245 text_ = claimMemory(hisByteLen + 1);
246 memcpy(operator char*(), string.operator char*(), hisByteLen+1);
250 Str& Str::operator=(const DStr& dynamic)
253 nset((char*) dynamic, dynamic.length());
257 Str& Str::operator=(const char* chars)
259 nset(NZ(chars), strlen(chars));
263 Str& Str::operator= (char c)
267 *(p = claimMemory(2)) = c;
274 Str& Str::operator= (int num)
278 sprintf(buf,"%d",num);
283 Str& Str::operator= (double num)
287 sprintf(buf,"%.13g",num);
292 void Str::nset(const char* chars, int len)
297 text_ = claimMemory(len + 1);
298 memcpy(text_, chars, len);
302 char Str::operator[] (int index) const
304 assert(index >= 0 && index <= length());
309 Bool Str::isEmpty() const
311 return !length(); // this is virtual
314 int Str::length() const
319 Str::operator char*() const
322 const_cast<Str*>(this) -> empty();
330 *(text_ = claimMemory(1)) = 0;
333 int Str::compare(const char* otherChars) const
335 int cmp = strcmp(operator char*(), otherChars);
338 else return (cmp > 0 ? 1 : -1);
341 int Str::compare(const Str& other) const
343 return compare((const char*) other);
346 Bool Str::operator== (const Str& other) const
348 return (Bool) !strcmp(operator char*(), (char*) other);
351 Bool Str::operator== (const char* otherChars) const
353 return (Bool) !strcmp(operator char*(), otherChars);
356 Bool Str::operator== (char* otherChars) const
358 return (Bool) !strcmp(operator char*(), otherChars);
361 Bool Str::eqNoCase (const Str& other) const
363 return (strEqNoCase(operator char*(), (char*) other) ? TRUE : FALSE);
366 Bool Str::eqNoCase (const char* other) const
368 return (strEqNoCase(operator char*(), other) ? TRUE : FALSE);
371 Bool Str::operator< (const char* other)
373 return compare(other) < 0;
376 Bool Str::operator< (const Str &other)
378 return operator<((const char*) other);
381 Bool Str::toDouble(double &d) const
384 d = strtod(operator char*(),&stopper);
393 DStr& Str::appendSelf(DStr& other)
395 other.nadd(operator char*(), length());
400 DStr Str::operator+ (const Str& other) const
409 DStr Str::operator+ (const char* otherChars) const
417 DStr Str::operator+ (int num) const
426 // pack_() is overridden in DStr to put the pieces of the dynamic
429 void Str::pack_() const
432 const_cast<Str*>(this) -> empty();
436 // a ridiculous old function (almost dead)
437 // FIXME: do away with it and namechar() too
439 void Str::speakTerse(DStr &ret)
444 for (i = 0; i < length(); i++)
446 switch(c = (*this)[i])
449 ret += " "; break;
451 ret += "	"; break;
458 char* Str::cloneData()
461 char *ret = new char[length() + 1];
482 // which leaks memory since Str::Str() is called
486 DStr::DStr(const char *chars)
489 // which leaks memory since Str::Str() is called
494 DStr::DStr(const Str& string)
497 // which leaks memory since Str::Str() is called
502 DStr::DStr(const DStr& dstring)
506 // which leaks memory since Str::Str() is called
511 DStr& DStr::operator=(const DStr& other)
519 DStr& DStr::nadd(const char *adding, int len)
523 blocks.nadd(adding, len);
530 DStr& DStr::operator+= (const char *adding)
532 if (!text_ || *adding)
533 nadd(adding, strlen(adding));
537 DStr& DStr::operator+= (const Str& addingStr)
539 nadd((char*) addingStr, addingStr.length());
543 DStr& DStr::operator+=(const DStr& other)
545 if (!other.text_) return *this;
546 nadd(other.text_, other.byteLength_);
548 for (b = other.blocks.first; b; b = b -> next)
549 nadd(b -> data, b -> byteCount);
553 DStr& DStr::operator+= (int addingnum)
555 Str temp = addingnum;
556 return operator +=(temp);
559 DStr& DStr::operator+= (char addingc)
562 return operator +=(temp);
565 DStr& DStr::appendSelf(DStr& other)
567 other.nadd(text_, byteLength_);
569 for (b = blocks.first; b; b = b -> next)
570 other.nadd(b -> data, b -> byteCount);
587 void DStr::pack_() const
589 // if not needed leave asap
590 if (blocks.isEmpty()) return;
591 int blocksLen = blocks.byteCount;
592 // concat text_ with the contents of all blocks
593 char *oldText_ = const_cast<DStr*>(this) -> text_;
594 const_cast<DStr*>(this) -> text_ =
595 const_cast<DynStrBlock*>(&blocks) ->
596 compactString_(text_, byteLength_);
597 returnMemory(oldText_);
598 const_cast<DStr*>(this) -> byteLength_ += blocksLen;
599 // the length stays the same
602 int DStr::length() const
604 return byteLength_ + blocks.byteCount;
607 DStr::operator char* () const
610 return Str::operator char*();
621 void escapeChars(DStr& result, const Str& what,
622 const char* toEscape, const char** substitutes)
624 char *pStart = what, *p = pStart;
628 p = strpbrk(pStart, toEscape);
631 if ((chunkLength = (int)(p - pStart)))
632 result.nadd(pStart, chunkLength);
633 result += substitutes[(int) (NZ(strchr(toEscape, *p)) - toEscape)];
648 // holds a qname as in the XML spec
654 local = UNDEF_PHRASE;
656 prefix = UNDEF_PHRASE;
659 QName::QName(const QName &other)
663 prefix = other.prefix;
666 QName& QName::operator =(const QName& other)
670 prefix = other.prefix;
674 Bool QName::isEmpty() const
676 return (uri == UNDEF_PHRASE && local == UNDEF_PHRASE);
681 prefix = UNDEF_PHRASE;
682 local = UNDEF_PHRASE;
687 void QName::speak(DStr &s, SpeakMode mode) const
689 if (prefix != UNDEF_PHRASE)
691 s += dict().getKey(prefix);
694 s += dict().getKey(local);
699 Bool QName::prefixIsNS(const Str &uri2) const
702 dict().insert(uri2, uri2Id);
703 return (uri == uri2Id);
707 void QName::setPrefix(Phrase prefix_)
710 // dict().insert(pref, prefix);
714 void QName::setLocal(Phrase local_)
717 // dict().insert(loc, local);
720 void QName::setUri(Phrase uri_)
723 // dict().insert(u, uri);
727 Bool QName::operator== (const QName &other) const
729 return local == other.local && uri == other.uri;
733 Str QName::getname() const
741 Phrase QName::getLocal() const
744 // return dict().getKey(local);
747 Phrase QName::getUri() const
750 // return dict().getKey(uri);
753 Phrase QName::getPrefix() const
756 // return dict().getKey(prefix);
759 Bool QName::hasPrefix() const
761 return (prefix != UNDEF_PHRASE);
771 int QNameList::findNdx(const QName &what) const
773 int count = number();
774 for (int i = 0; i < count; i++)
775 // checking for equality of local and uri
776 if ((*this)[i] -> operator==(what))
789 EQName::EQName(const EQName& other)
791 prefix = other.getPrefix();
792 uri = other.getUri();
793 local = other.getLocal();
796 Bool EQName::isEmpty() const
798 return prefix.isEmpty() && uri.isEmpty() && local.isEmpty();
808 void EQName::set(const QName& q, const HashTable& dict)
810 prefix = dict.getKey(q.getPrefix());
811 uri = dict.getKey(q.getUri());
812 local = dict.getKey(q.getLocal());
815 void EQName::setPrefix(const Str& prefix_)
820 void EQName::setLocal(const Str& local_)
825 void EQName::setUri(const Str& uri_)
830 void EQName::getname(Str& fullName) const
833 if (!prefix.isEmpty())
842 const Str& EQName::getLocal() const
847 const Str& EQName::getUri() const
852 const Str& EQName::getPrefix() const
857 Bool EQName::hasPrefix() const
859 return !prefix.isEmpty();
862 Bool EQName::operator==(const EQName &other) const
864 return (uri == other.getUri()
865 && local == other.getLocal()
866 && uri == other.getUri());
879 int StrStrList::findNum(const Str &key_) const
881 int i, count = number();
882 for (i = 0; (i < count) && !(key_ == ((*this)[i] -> key)); i++) {};
883 return (i < count) ? i : -1;
886 Str* StrStrList::find(const Str &_key) const
888 int ndx = findNum(_key);
889 return (ndx != -1) ? &((*this)[ndx] -> value) : NULL;
892 void StrStrList::appendConstruct(const Str &key, const Str& value)
894 StrStr* newItem = new StrStr;
895 newItem -> key = key;
896 newItem -> value = value;
906 int NamespaceStack::findNum(const Str &prefix_) const
908 int i, count = number();
909 for (i = count-1; (i >= 0) && !(prefix_ == ((*this)[i] -> prefix)); i--) {};
913 const Str* NamespaceStack::getUri(const Str &_prefix) const
915 int ndx = findNum(_prefix);
916 return (ndx != -1) ? &((*this)[ndx] -> uri) : NULL;
920 Bool NamespaceStack::isHidden(const Str &_prefix) const
922 int ndx = findNum(_prefix);
923 return (ndx != -1) ? ((*this)[ndx] -> hidden) : TRUE;
926 void NamespaceStack::appendConstruct(const Str &prefix, const Str& uri,
929 NamespaceStackObj* newItem = new NamespaceStackObj;
930 newItem -> prefix = prefix;
931 newItem -> uri = uri;
932 newItem -> hidden = _hidden;
944 const EQName* EQNameList::find(const EQName &what) const
946 int i, count = number();
947 for (i = 0; (i < count) && !(what == (*operator[](i))); i++) {};
948 return (i < count) ? operator[](i) : NULL;
959 // returns -1 if the EQName was not found
960 int EQNameStrList::findNdx(const EQName &what) const
962 int i, count = number();
963 for (i = 0; i < count && !(what == operator[](i) -> key); i++) {};
964 return (i < count) ? i : -1;
967 const Str* EQNameStrList::find(const EQName &what) const
969 int i = findNdx(what);
970 return (i != -1 ? &(operator[](i) -> value) : NULL);
973 void EQNameStrList::appendConstruct(const EQName &key, const Str& value)
975 EQNameStr* newItem = new EQNameStr(key, value);
981 /************************************/
983 int UriList::findNdx(Phrase what) {
984 for (int i = 0; i < number(); i++) {
985 Phrase foo = (*this)[i];
986 if (foo == what) return i;
991 void UriList::addUri(Phrase what) {
992 int i = findNdx(what);
993 if (i == -1) append(what);