1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-09 18:50:54 +03:00
occt/src/XmlObjMgt/XmlObjMgt.cxx

406 lines
14 KiB
C++

// Created on: 2001-07-18
// Created by: Julia DOROVSKIKH
// Copyright (c) 2001-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <XmlObjMgt.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
#include <XmlObjMgt_Document.hxx>
#include <errno.h>
#include <stdio.h>
#include <limits>
static const char aRefPrefix [] = "/document/label";
static const char aRefElem1 [] = "/label[@tag=";
static const char aRefElem2 [] = "]";
//=======================================================================
//function : IdString
//purpose : return name of ID attribute to be used everywhere
//=======================================================================
const XmlObjMgt_DOMString& XmlObjMgt::IdString ()
{
static const LDOMString aString ("id");
return aString;
}
//=======================================================================
//function : SetStringValue
//purpose : Add theData as the last child text node to theElement
//remark : Set isClearText to True if only you guarantee that the string
// does not contain '&', '<', '>', '\"', '\'', etc.
//=======================================================================
void XmlObjMgt::SetStringValue (XmlObjMgt_Element& theElement,
const XmlObjMgt_DOMString& theData,
const Standard_Boolean isClearText)
{
XmlObjMgt_Document aDocument = theElement.getOwnerDocument();
LDOM_Text aText = aDocument.createTextNode (theData);
if (isClearText) aText.SetValueClear();
theElement.appendChild (aText);
}
//=======================================================================
//function : GetStringValue
//purpose : returns the first child text node
//=======================================================================
XmlObjMgt_DOMString XmlObjMgt::GetStringValue
(const XmlObjMgt_Element& theElement)
{
XmlObjMgt_DOMString aString;
for (LDOM_Node aNode = theElement.getFirstChild();
aNode != NULL;
aNode = aNode.getNextSibling())
{
if (aNode.getNodeType() == LDOM_Node::TEXT_NODE) {
aString = ((const LDOM_Text&)aNode).getData();
break;
}
}
return aString;
}
//=======================================================================
//function : SprintfExtStr
//purpose : Converts theString to hex printable representation and put it
// : to the out buffer
//=======================================================================
void SprintfExtStr(char * out, const TCollection_ExtendedString& theString) {
unsigned short * p = (unsigned short *)theString.ToExtString();
int len = theString.Length();
int i = 0;
unsigned short mask[4] = {0xf000,0x0f00,0x00f0,0x000f};
while (len) {
for(int j = 0,k=3; j<4; j++,k--) {
unsigned short v = *(p+i) & mask[j];//x000
v = (unsigned short)(v >> (4*k));
if(v < 10)
v |= 0x30;
else
v += 87;
out[4*i+j] = (char)v;
}
i++;len--;
}
out[4*theString.Length()] = 0x00;
}
//=======================================================================
//function : SetExtendedString
//purpose : Add text node to element and initialize it with string
//=======================================================================
Standard_Boolean XmlObjMgt::SetExtendedString
(XmlObjMgt_Element& theElement,
const TCollection_ExtendedString& theString)
{
TCollection_AsciiString anAString;
if (theString.IsAscii()) {
anAString = TCollection_AsciiString (theString, '?');
SetStringValue (theElement, anAString.ToCString());
} else {
const Standard_Integer aLen = theString.Length();
// const Standard_ExtCharacter * aString = theString.ToExtString();
char * buf0 = new char [4 * (aLen + 1) + 3];
Sprintf (&buf0[0], "##%04x", 0xfeff); // set UNICODE header
char * buf = &buf0[6];
// Standard_Integer i = 0;
// while (i <= (aLen - 4)) {
// Sprintf (&buf[i*4], "%04x%04x%04x%04x", aString[i], aString[i+1],
// aString[i+2], aString[i+3]);
// i += 4;
// }
// while (i < aLen) {
// Sprintf (&buf[i*4], "%04x", aString[i]);
// ++i;
// }
// buf[4*aLen] = '\0';
SprintfExtStr(buf, theString);
SetStringValue (theElement, buf0);
delete [] buf0;
}
return Standard_True;
}
//=======================================================================
//function : GetExtendedString
//purpose : Get the first text node in theElement and convert to ExtendedStr
//=======================================================================
Standard_Boolean XmlObjMgt::GetExtendedString
(const XmlObjMgt_Element& theElement,
TCollection_ExtendedString& theString)
{
theString = GetStringValue (theElement);
return Standard_True;
}
//=======================================================================
//function : GetTagEntryString
//purpose : Convert XPath expression (DOMString) into TagEntry string
// Returns False on error
//=======================================================================
Standard_Boolean XmlObjMgt::GetTagEntryString
(const XmlObjMgt_DOMString& theSource,
TCollection_AsciiString& theTagEntry)
{
// Check the prefix
const size_t aPrefixSize = sizeof(aRefPrefix) - 1;
const char * aSource = theSource.GetString();
if (strncmp (aSource, aRefPrefix, aPrefixSize))
return Standard_False;
// Beging aTagEntry string
char * aTagEntry =
(char *) Standard::Allocate (strlen(aSource)/2); // quite enough to hold it
char * aTagEntryPtr = aTagEntry + 1;
* aTagEntry = '0';
aSource += aPrefixSize;
// Find all individual tags in a loop
const size_t anElem1Size = sizeof(aRefElem1) - 1;
const size_t anElem2Size = sizeof(aRefElem2) - 1;
while (aSource[0] != '\0') {
// Check the first part of individual tag: "/label[@tag="
if (strncmp (aSource, aRefElem1, anElem1Size))
return Standard_False;
aSource += anElem1Size;
const char aQuote = aSource[0];
if (aQuote != '\'' && aQuote != '\"')
return Standard_False;
// Check the integer value of the tag
errno = 0;
char * aPtr;
long aTagValue = strtol (&aSource[1], &aPtr, 10);
Standard_Integer aLen = (Standard_Integer)(aPtr - &aSource[1]);
if (aTagValue < 0 || aLen == 0 || aPtr[0] != aQuote ||
errno == ERANGE || errno == EINVAL)
return Standard_False;
aTagEntryPtr[0] = ':';
memcpy (&aTagEntryPtr[1], &aSource[1], aLen);
aTagEntryPtr += (aLen + 1);
// Check the final part of individual tag : "]"
if (strncmp (aPtr + 1, aRefElem2, anElem2Size))
return Standard_False;
aSource = aPtr + 1 + anElem2Size;
}
aTagEntryPtr[0] = '\0';
theTagEntry = aTagEntry;
Standard::Free (aTagEntry);
return Standard_True;
}
//=======================================================================
//function : SetTagEntryString
//purpose : Form an XPath string corresponding to the input TagEntry
//=======================================================================
void XmlObjMgt::SetTagEntryString (XmlObjMgt_DOMString& theTarget,
const TCollection_AsciiString& theTagEntry)
{
// Begin parsing theTagEntry
const char * aTagEntry = (const char*) theTagEntry.ToCString() + 1;
if (aTagEntry[-1] != '0')
return;
// Count the number of tags in the label entry string
const char * aPtr = aTagEntry;
Standard_Integer aTagCount = 0;
while (* aPtr) if (* aPtr++ == ':') aTagCount ++;
// Create a buffer to accumulate the XPath reference
const size_t anElem1Size = sizeof(aRefElem1) - 1;
const size_t anElem2Size = sizeof(aRefElem2) - 1;
char * aTarget =
(char *) Standard::Allocate (sizeof(aRefPrefix) + aTagCount *
(anElem1Size + anElem2Size + 12));
memcpy (aTarget, aRefPrefix, sizeof (aRefPrefix) - 1);
char * aTargetPtr = aTarget + (sizeof (aRefPrefix) - 1);
for(;;) {
// Check for the end-of-string; find the delimiter ':'
aPtr = strchr (aTagEntry, ':');
if (aPtr == NULL) break;
aTagEntry = aPtr + 1;
// Find the range of characters for an integer number
errno = 0;
char * ptr;
long aTagValue = strtol (aTagEntry, &ptr, 10);
Standard_Integer aTagSize = (Standard_Integer)(ptr - aTagEntry);
if (aTagValue < 0 || aTagSize == 0 ||
errno == ERANGE || errno == EINVAL)
return; // error
// Add one XPath level to the expression in aTarget
memcpy (&aTargetPtr[0], aRefElem1, anElem1Size);
aTargetPtr[anElem1Size] = '\"';
memcpy (&aTargetPtr[anElem1Size+1], aTagEntry, aTagSize);
aTargetPtr[anElem1Size+aTagSize+1] = '\"';
memcpy (&aTargetPtr[anElem1Size+aTagSize+2],aRefElem2, anElem2Size);
aTargetPtr += (anElem1Size + aTagSize + anElem2Size + 2);
}
* aTargetPtr = '\0';
theTarget = aTarget;
Standard::Free (aTarget);
}
//=======================================================================
//function : FindChildElement
//purpose :
//=======================================================================
XmlObjMgt_Element XmlObjMgt::FindChildElement
(const XmlObjMgt_Element& theSource,
const Standard_Integer theId)
{
LDOM_Node aNode = theSource.getFirstChild();
Standard_Integer anId;
while ( !aNode.isNull() )
{
if ( aNode.getNodeType() == LDOM_Node::ELEMENT_NODE )
{
LDOM_Element anElem = (LDOM_Element &) aNode;
if (anElem.getAttribute (IdString()).GetInteger(anId))
if (anId == theId) return anElem;
}
aNode = aNode.getNextSibling();
}
// find in all the document // to be done
// LDOM_Document aDoc = theSource.getOwnerDocument();
return LDOM_Element();
}
//=======================================================================
//function : FindChildByRef
//purpose :
//=======================================================================
XmlObjMgt_Element XmlObjMgt::FindChildByRef
(const XmlObjMgt_Element& theSource,
const XmlObjMgt_DOMString& theRefName)
{
Standard_Integer anID;
if (theSource.getAttribute (theRefName).GetInteger (anID))
return FindChildElement (theSource, anID);
return LDOM_Element();
}
//=======================================================================
//function : FindChildByName
//purpose :
//=======================================================================
XmlObjMgt_Element XmlObjMgt::FindChildByName
(const XmlObjMgt_Element& theSource,
const XmlObjMgt_DOMString& theName)
{
return theSource.GetChildByTagName(theName);
}
//=======================================================================
//function : GetInteger
//purpose :
//=======================================================================
Standard_Boolean XmlObjMgt::GetInteger (Standard_CString& theString,
Standard_Integer& theValue)
{
char * ptr;
errno = 0;
long aValue = strtol (theString, &ptr, 10);
if (ptr == theString || errno == ERANGE || errno == EINVAL)
return Standard_False;
theValue = Standard_Integer (aValue);
theString = ptr;
return Standard_True;
}
//=======================================================================
//function : GetReal
//purpose :
//=======================================================================
Standard_Boolean XmlObjMgt::GetReal (Standard_CString& theString,
Standard_Real& theValue)
{
char * ptr;
errno = 0;
theValue = Strtod (theString, &ptr);
if (ptr == theString || errno == ERANGE || errno == EINVAL)
return Standard_False;
theString = ptr;
// detect NAN or infinite values written by old MSVC run-time as -1. with
// suffix "#QNAN" or "#SNAN" or "#INF"
if (*ptr == '#')
{
if (! strncmp (ptr, "#QNAN", 5) || ! strncmp (ptr, "#SNAN", 5))
{
theString = ptr + 5;
theValue = std::numeric_limits<double>::quiet_NaN();
return Standard_True;
}
else if (! strncmp (ptr, "#INF", 4))
{
theString = ptr + 4;
theValue = (theValue < 0 ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
return Standard_True;
}
else
return Standard_False;
}
else if (*ptr && ! IsSpace (*ptr))
{
// report failure if reading stopped not at the end of the string or space
return Standard_False;
}
return Standard_True;
}
//=======================================================================
//function : GetReal
//purpose : Convert LDOMString to Real
//=======================================================================
Standard_Boolean XmlObjMgt::GetReal (const XmlObjMgt_DOMString& theString,
Standard_Real& theValue)
{
switch (theString.Type()) {
case LDOMBasicString::LDOM_NULL:
return Standard_False;
case LDOMBasicString::LDOM_Integer:
{
Standard_Integer anIntValue;
theString.GetInteger(anIntValue);
theValue = Standard_Real(anIntValue);
break;
}
default: // LDOM_Ascii*
{
const char * aString = theString.GetString();
return GetReal (aString, theValue);
}
}
return Standard_True;
}