Esempio n. 1
0
C4FindObject *C4FindObject::CreateByValue(const C4Value &DataVal,
                                          C4SortObject **ppSortObj) {
  // Must be an array
  C4ValueArray *pArray = C4Value(DataVal).getArray();
  if (!pArray) return NULL;

  const C4ValueArray &Data = *pArray;
  int32_t iType = Data[0].getInt();
  if (Inside<int32_t>(iType, C4SO_First, C4SO_Last)) {
    // this is not a FindObject but a sort condition!
    // sort condition not desired here?
    if (!ppSortObj) return NULL;
    // otherwise, create it!
    *ppSortObj = C4SortObject::CreateByValue(iType, Data);
    // done
    return NULL;
  }

  switch (iType) {
    case C4FO_Not: {
      // Create child condition
      C4FindObject *pCond = C4FindObject::CreateByValue(Data[1]);
      if (!pCond) return NULL;
      // wrap
      return new C4FindObjectNot(pCond);
    }

    case C4FO_And:
    case C4FO_Or: {
      // Trivial case (one condition)
      if (Data.GetSize() == 2) return C4FindObject::CreateByValue(Data[1]);
      // Create all childs
      int32_t i;
      C4FindObject **ppConds = new C4FindObject *[Data.GetSize() - 1];
      for (i = 0; i < Data.GetSize() - 1; i++)
        ppConds[i] = C4FindObject::CreateByValue(Data[i + 1]);
      // Count real entries, move them to start of list
      int32_t iSize = 0;
      for (i = 0; i < Data.GetSize() - 1; i++)
        if (ppConds[i])
          if (iSize++ != i) ppConds[iSize - 1] = ppConds[i];
      // Create
      if (iType == C4FO_And)
        return new C4FindObjectAnd(iSize, ppConds);
      else
        return new C4FindObjectOr(iSize, ppConds);
    }

    case C4FO_Exclude:
      return new C4FindObjectExclude(Data[1].getObj());

    case C4FO_ID:
      return new C4FindObjectID(Data[1].getC4ID());

    case C4FO_InRect:
      return new C4FindObjectInRect(C4Rect(Data[1].getInt(), Data[2].getInt(),
                                           Data[3].getInt(), Data[4].getInt()));

    case C4FO_AtPoint:
      return new C4FindObjectAtPoint(Data[1].getInt(), Data[2].getInt());

    case C4FO_AtRect:
      return new C4FindObjectAtRect(Data[1].getInt(), Data[2].getInt(),
                                    Data[3].getInt(), Data[4].getInt());

    case C4FO_OnLine:
      return new C4FindObjectOnLine(Data[1].getInt(), Data[2].getInt(),
                                    Data[3].getInt(), Data[4].getInt());

    case C4FO_Distance:
      return new C4FindObjectDistance(Data[1].getInt(), Data[2].getInt(),
                                      Data[3].getInt());

    case C4FO_OCF:
      return new C4FindObjectOCF(Data[1].getInt());

    case C4FO_Category:
      return new C4FindObjectCategory(Data[1].getInt());

    case C4FO_Action: {
      C4String *pStr = Data[1].getStr();
      if (!pStr) return NULL;
      // Don't copy, it should be safe
      return new C4FindObjectAction(pStr->Data.getData());
    }

    case C4FO_Func: {
      // Get function name
      C4String *pStr = Data[1].getStr();
      if (!pStr) return NULL;
      // Construct
      C4FindObjectFunc *pFO = new C4FindObjectFunc(pStr->Data.getData());
      // Add parameters
      for (int i = 2; i < Data.GetSize(); i++) pFO->SetPar(i - 2, Data[i]);
      // Done
      return pFO;
    }

    case C4FO_ActionTarget: {
      int index = 0;
      if (Data.GetSize() >= 3) index = BoundBy(Data[2].getInt(), 0, 1);
      return new C4FindObjectActionTarget(Data[1].getObj(), index);
    }

    case C4FO_Container:
      return new C4FindObjectContainer(Data[1].getObj());

    case C4FO_AnyContainer:
      return new C4FindObjectAnyContainer();

    case C4FO_Owner:
      return new C4FindObjectOwner(Data[1].getInt());

    case C4FO_Controller:
      return new C4FindObjectController(Data[1].getInt());

    case C4FO_Layer:
      return new C4FindObjectLayer(Data[1].getObj());
  }
  return NULL;
}
Esempio n. 2
0
C4FindObject *C4FindObject::CreateByValue(const C4Value &DataVal, C4SortObject **ppSortObj, const C4Object *context, bool *has_layer_check)
{
	// Must be an array
	C4ValueArray *pArray = C4Value(DataVal).getArray();
	if (!pArray) return NULL;

	const C4ValueArray &Data = *pArray;
	int32_t iType = Data[0].getInt();
	if (Inside<int32_t>(iType, C4SO_First, C4SO_Last))
	{
		// this is not a FindObject but a sort condition!
		// sort condition not desired here?
		if (!ppSortObj) return NULL;
		// otherwise, create it!
		*ppSortObj = C4SortObject::CreateByValue(iType, Data, context);
		// done
		return NULL;
	}

	switch (iType)
	{
	case C4FO_Not:
	{
		// Create child condition
		C4FindObject *pCond = C4FindObject::CreateByValue(Data[1], nullptr, context, has_layer_check);
		if (!pCond) return NULL;
		// wrap
		return new C4FindObjectNot(pCond);
	}

	case C4FO_And: case C4FO_Or:
	{
		// Trivial case (one condition)
		if (Data.GetSize() == 2)
			return C4FindObject::CreateByValue(Data[1], nullptr, context, has_layer_check);
		// Create all childs
		int32_t i;
		C4FindObject **ppConds = new C4FindObject *[Data.GetSize() - 1];
		for (i = 0; i < Data.GetSize() - 1; i++)
			ppConds[i] = C4FindObject::CreateByValue(Data[i + 1], nullptr, context, has_layer_check);
		// Count real entries, move them to start of list
		int32_t iSize = 0;
		for (i = 0; i < Data.GetSize() - 1; i++)
			if (ppConds[i])
				if (iSize++ != i)
					ppConds[iSize-1] = ppConds[i];
		// Create
		if (iType == C4FO_And)
			return new C4FindObjectAnd(iSize, ppConds);
		else
			return new C4FindObjectOr(iSize, ppConds);
	}

	case C4FO_Exclude:
		return new C4FindObjectExclude(Data[1].getObj());

	case C4FO_ID:
		return new C4FindObjectDef(Data[1].getPropList());


	// #973: For all criteria using coordinates: If FindObject et al. are called in object context, offset by object center
	case C4FO_InRect:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		int32_t w = Data[3].getInt();
		int32_t h = Data[4].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectInRect(C4Rect(x, y, w, h));
	}

	case C4FO_AtPoint:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectAtPoint(x, y);
	}

	case C4FO_AtRect:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		int32_t w = Data[3].getInt();
		int32_t h = Data[4].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectAtRect(x, y, w, h);
	}

	case C4FO_OnLine:
	{
		int32_t x1 = Data[1].getInt();
		int32_t y1 = Data[2].getInt();
		int32_t x2 = Data[3].getInt();
		int32_t y2 = Data[4].getInt();
		if (context)
		{
			x1 += context->GetX();
			x2 += context->GetX();
			y1 += context->GetY();
			y2 += context->GetY();
		}
		return new C4FindObjectOnLine(x1, y1, x2, y2);
	}

	case C4FO_Distance:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectDistance(x, y, Data[3].getInt());
	}

	case C4FO_OCF:
		return new C4FindObjectOCF(Data[1].getInt());

	case C4FO_Category:
		return new C4FindObjectCategory(Data[1].getInt());

	case C4FO_Action:
	{
		C4String *pStr = Data[1].getStr();
		if (!pStr) return NULL;
		// Don't copy, it should be safe
		return new C4FindObjectAction(pStr->GetCStr());
	}

	case C4FO_Func:
	{
		// Get function name
		C4String *pStr = Data[1].getStr();
		if (!pStr) return NULL;
		// Construct
		C4FindObjectFunc *pFO = new C4FindObjectFunc(pStr);
		// Add parameters
		for (int i = 2; i < Data.GetSize(); i++)
			pFO->SetPar(i - 2, Data[i]);
		// Done
		return pFO;
	}

	case C4FO_ActionTarget:
	{
		int index = 0;
		if (Data.GetSize() >= 3)
			index = Clamp(Data[2].getInt(), 0, 1);
		return new C4FindObjectActionTarget(Data[1].getObj(), index);
	}

	case C4FO_Procedure:
		return new C4FindObjectProcedure(Data[1].getStr());

	case C4FO_Container:
		return new C4FindObjectContainer(Data[1].getObj());

	case C4FO_AnyContainer:
		return new C4FindObjectAnyContainer();

	case C4FO_Owner:
		return new C4FindObjectOwner(Data[1].getInt());

	case C4FO_Controller:
		return new C4FindObjectController(Data[1].getInt());

	case C4FO_Layer:
		// explicit layer check given. do not add implicit layer check
		if (has_layer_check) *has_layer_check = true;
		return new C4FindObjectLayer(Data[1].getObj());

	case C4FO_InArray:
		return new C4FindObjectInArray(Data[1].getArray());

	case C4FO_Property:
	{
		// Get property name
		C4String *pStr = Data[1].getStr();
		if (!pStr) return NULL;
		// Construct
		C4FindObjectProperty *pFO = new C4FindObjectProperty(pStr);
		// Done
		return pFO;
	}

	case C4FO_AnyLayer:
		// do not add implicit layer check
		if (has_layer_check) *has_layer_check = true;
		return NULL;

	}
	return NULL;
}