示例#1
0
/*! This method checks if [this] AP and the given AP are functionally equivalent.
    In contrast to is isExactMatch this function will return true if
    the attrs and props are same even if they are in different order;
    it is computationally much more involved than isExactMatch().
	 On that note, it may be worth looking into putting some more explicit collision
	 guarantees into the checksum computation algorithm, such to take advantage of
	 those checksums here.  IOW, make it such to be trusted that if checksums match,
	 APs are equivalent (but not necessarily exact matches).
	 \retval TRUE if equivalent to given AP (regardless of order), FALSE otherwise.
*/
bool PP_AttrProp::isEquivalent(const PP_AttrProp * pAP2) const
{
	if(!pAP2)
		return false;
	
	if(   getAttributeCount() != pAP2->getAttributeCount()
	   || getPropertyCount()  != pAP2->getPropertyCount())
		return false;
	
	UT_uint32 i;
	const gchar * pName, * pValue, * pValue2;
	
	for(i =  0; i < getAttributeCount(); ++i)
	{
		UT_return_val_if_fail(getNthAttribute(i,pName,pValue),false);

		if(!pAP2->getAttribute(pName,pValue2))
			return false;

		// ignore property attribute
		if(0 == strcmp(pValue, PT_PROPS_ATTRIBUTE_NAME))
			continue;

		// handle revision attribute correctly
		if(0 == strcmp(pValue, PT_REVISION_ATTRIBUTE_NAME))
		{
			// requires special treatment
			PP_RevisionAttr r1(pValue);
			PP_RevisionAttr r2 (pValue2);

			if(!(r1 == r2))
			{
				return false;
			}
		}
		else if(0 != strcmp(pValue,pValue2))
			return false;
	}

	for(i =  0; i < getPropertyCount(); ++i)
	{
		UT_return_val_if_fail(getNthProperty(i,pName,pValue),false);

		if(!pAP2->getProperty(pName,pValue2))
			return false;

		if(0 != strcmp(pValue,pValue2))
			return false;
	}

	return true;
}
示例#2
0
bool PP_Revision::operator == (const PP_Revision &op2) const
{
	// this is quite involved, but we will start with the simple
	// non-equality cases

	if(getId() != op2.getId())
		return false;

	if(getType() != op2.getType())
		return false;


	// OK, so we have the same type and id, do we have the same props ???
	UT_uint32 iPCount1 = getPropertyCount();
	UT_uint32 iPCount2 = op2.getPropertyCount();
	UT_uint32 iACount1 = getAttributeCount();
	UT_uint32 iACount2 = op2.getAttributeCount();

	if((iPCount1 != iPCount2) || (iACount1 != iACount2))
		return false;

	// now the lengthy comparison
	UT_uint32 i;
	const gchar * n;
	const gchar * v1, * v2;

	for(i = 0; i < iPCount1; i++)
	{

		getNthProperty(i,n,v1);
		op2.getProperty(n,v2);

		if(strcmp(v1,v2))
			return false;
	}

	for(i = 0; i < iACount1; i++)
	{

		getNthAttribute(i,n,v1);
		op2.getAttribute(n,v2);

		if(strcmp(v1,v2))
			return false;
	}
	return true;
}
示例#3
0
void PP_Revision::_refreshString() const
{
	m_sXMLProps.clear();
	m_sXMLAttrs.clear();

	UT_uint32 i;
	UT_uint32 iCount = getPropertyCount();
	const gchar * n, *v;

	for(i = 0; i < iCount; i++)
	{
		if(!getNthProperty(i,n,v))
		{
			// UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
			continue;
		}
		
		if(!v || !*v) v = "-/-";
		
		m_sXMLProps += n;
		m_sXMLProps += ":";
		m_sXMLProps += v;
		if(i < iCount - 1)
			m_sXMLProps += ";";
	}

	iCount = getAttributeCount();
	for(i = 0; i < iCount; i++)
	{
		if(!getNthAttribute(i,n,v))
		{
			// UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
			continue;
		}
		
		if(!v || !*v) v = "-/-";

		m_sXMLAttrs += n;
		m_sXMLAttrs += ":";
		m_sXMLAttrs += v;
		if(i < iCount - 1)
			m_sXMLAttrs += ";";
	}

	m_bDirty = false;
}
示例#4
0
/*! This is a debugging tool which serves to dump in readable form (as UT_DEBUGMSGs)
	 the contents of [this] AP.
*/
void PP_AttrProp::miniDump(const PD_Document * pDoc) const
{
#ifdef DEBUG
	const gchar * pName, * pValue;
	UT_uint32 i = 0;
	
	UT_DEBUGMSG(("--------------------- PP_AttrProp mini dump --------------------------------\n"));
	UT_DEBUGMSG(("Attributes:\n"));
	while(getNthAttribute(i,pName,pValue))
	{
		UT_DEBUGMSG(("%s : %s\n", pName, pValue));
		++i;
	}
		  
	UT_DEBUGMSG(("Properties:\n"));
	i = 0;
	while(getNthProperty(i,pName,pValue))
	{
		UT_DEBUGMSG(("%s : %s\n", pName, pValue));
		++i;
	}

	if(m_iRevisedIndex != 0xffffffff && pDoc)
	{
		UT_DEBUGMSG(("Attached revised AP:\n"));
		const PP_AttrProp * pRevAP;
		pDoc->getAttrProp(m_iRevisedIndex, const_cast<const PP_AttrProp **>(&pRevAP));

		// avoid endless loop on circular reference
		if(pRevAP && pRevAP->getRevisedIndex() != m_iRevisedIndex)
			pRevAP->miniDump(pDoc);
	}
	
	UT_DEBUGMSG(("----------------------------------------------------------------------------\n"));
#else
	UT_UNUSED(pDoc);
#endif
}
示例#5
0
/*! Create a new AttrProp based upon the given one, adding or replacing the items given.
	 \return NULL on failure, the newly-created PP_AttrProp clone otherwise.
*/
PP_AttrProp * PP_AttrProp::cloneWithReplacements(const gchar ** attributes,
												 const gchar ** properties,
												 bool bClearProps) const
{
	bool bIgnoreProps = false; // see below

	// first, create a new AttrProp using just the values given.

	PP_AttrProp * papNew = new PP_AttrProp();
	if (!papNew)
		goto Failed;
	if (!papNew->setAttributes(attributes) || !papNew->setProperties(properties))
		goto Failed;

	// next, add any items that we have that are not present
	// (have not been overridden) in the new one.

	UT_uint32 k;
	const gchar * n;
	const gchar * v;
	const gchar * vNew;

	k = 0;
	while (getNthAttribute(k++,n,v))
	{
		// TODO decide if/whether to allow PT_PROPS_ATTRIBUTE_NAME here.
		// TODO The issue is: we use it to store the CSS properties and
		// TODO when we see it, we expand the value into one or more
		// TODO properties.  if we allow it to be given here, should
		// TODO we blowaway all of the existing properties and create
		// TODO them from this?  or should we expand it and override
		// TODO individual properties?
		// TODO for now, we just barf on it.
		UT_return_val_if_fail (strcmp(n,PT_PROPS_ATTRIBUTE_NAME)!=0, false); // cannot handle PROPS here
		if (!papNew->getAttribute(n,vNew))
			if (!papNew->setAttribute(n,v))
				goto Failed;
	}

	// we want to be able to remove all properties by setting the
	// props attribute to ""; in order for that to work, we need to
	// skip the following loop if props is set to ""
	const gchar * szValue;

	if(papNew->getAttribute("props", szValue) && !*szValue)
		bIgnoreProps = true;

	if (!bClearProps && !bIgnoreProps)
	{
		k = 0;
		while (getNthProperty(k++,n,v))
		{
			if (!papNew->getProperty(n,vNew))
				if (!papNew->setProperty(n,v))
					goto Failed;
		}
	}

	// the following will remove all properties set to ""; this allows us
	// to remove properties by setting them to ""
	papNew->_clearEmptyProperties();
	papNew->_clearEmptyAttributes();

	return papNew;

Failed:
	DELETEP(papNew);
	return NULL;
}
示例#6
0
/*! Create a new AttrProp based upon the given one, removing the items given
	 if their value is equal to that given.  See also PP_AttrProp::cloneWithElimination,
	 which does similarly but removes the items given regardless of whether or not
	 their value is equal to the value given.
	 \return NULL on failure, the newly-created PP_AttrProp clone otherwise.
*/
PP_AttrProp * PP_AttrProp::cloneWithEliminationIfEqual(const gchar ** attributes,
												const gchar ** properties) const
{
	// first, create an empty AttrProp.
	PP_AttrProp * papNew = new PP_AttrProp();
	if (!papNew)
		goto Failed;

	UT_uint32 k;
	const gchar * n;
	const gchar * v;

	k = 0;
	while (getNthAttribute(k++,n,v))
	{
		// for each attribute in the old set, add it to the
		// new set only if it is not present in the given array.

		if (attributes && *attributes)
		{
			const gchar ** p = attributes;
			while (*p)
			{
				if(strcmp(p[0],PT_PROPS_ATTRIBUTE_NAME)!=0)
					goto DoNotIncludeAttribute; // cannot handle PROPS here
				if (strcmp(n,p[0])==0 && strcmp(n,p[1])==0)		// found it, so we don't put it in the result.
					goto DoNotIncludeAttribute;
				p += 2;								// skip over value
			}
		}

		// we didn't find it in the given array, add it to the new set.

		if (!papNew->setAttribute(n,v))
			goto Failed;

	DoNotIncludeAttribute:
		;
	}

	k = 0;
	while (getNthProperty(k++,n,v))
	{
		// for each property in the old set, add it to the
		// new set only if it is not present in the given array.

		if (properties && *properties)
		{
			const gchar ** p = properties;
			while (*p)
			{
				if (strcmp(n,p[0])==0 && strcmp(n,p[1])==0)		// found it, so we don't put it in the result.
					goto DoNotIncludeProperty;
				p += 2;
			}
		}

		// we didn't find it in the given array, add it to the new set.

		if (!papNew->setProperty(n,v))
			goto Failed;

	DoNotIncludeProperty:
		;
	}

	return papNew;

Failed:
	DELETEP(papNew);
	return NULL;
}