Ejemplo n.º 1
0
void SequenceNode::deleteChildNodes()
{
    Sequence::iterator it;
    for (it = seq.begin(); it != seq.end(); ++it) {
        YamlNode *yamlNode = static_cast<YamlNode *> (*it);

        switch (yamlNode->getType()) {
            case DOCUMENT:
                break;
            case SEQUENCE: {
                SequenceNode *sequence = static_cast<SequenceNode *> (yamlNode);
                sequence->deleteChildNodes();
                delete sequence;
            }
            break;
            case MAPPING: {
                MappingNode *mapping = static_cast<MappingNode *> (yamlNode);
                mapping->deleteChildNodes();
                delete mapping;
            }
            break;
            case SCALAR: {
                ScalarNode *scalar = static_cast<ScalarNode *> (yamlNode);
                delete scalar;
            }
            break;
            default:
                break;
        }
    }
}
Ejemplo n.º 2
0
SequenceNode* handleStencilAssignment(FuncCallLikeNode* lhs, ExpressionNode* rhs)
{
    SequenceNode* retval = new SequenceNode();
    retval->setLocation(FileLocation(yylineno));

    StencilNode* stencil = dynamic_cast<StencilNode*>(lhs);
    if (stencil == nullptr) {
        std::string err_msg = "Internal error: The stencil \"" + lhs->name() + "\" does not appear to be properly defined";
        yyerror(err_msg.c_str());
    }

#if 0
    // If the type is a collection of invalids (no pun intended)
    // we can safely set it to the type of the rhs
    EquelleType lhs_et = SymbolTable::variableType(stencil->name());
    if (lhs_et.basicType() == Invalid
        && lhs_et.compositeType() == Collection
        && lhs_et.isStencil()) {
        EquelleType lhs_et = rhs->type();
        lhs_et.setMutable(true);
        SymbolTable::setVariableType(stencil->name(), lhs_et);
        // TODO: set dimensions correctly here
        TypeNode* lhs_type = new TypeNode(lhs_et);
        retval->pushNode(new VarDeclNode(stencil->name(), lhs_type));
    }
#endif
    retval->pushNode(new StencilAssignmentNode(stencil, rhs));
    return retval;
}
Ejemplo n.º 3
0
Node* handleDeclarationAssign(const std::string& name, TypeNode* type, ExpressionNode* expr)
{
    SequenceNode* seq = new SequenceNode;
    seq->pushNode(handleDeclaration(name, type));
    seq->pushNode(handleAssignment(name, expr));
    seq->setLocation(FileLocation(yylineno));
    return seq;
}
Ejemplo n.º 4
0
void YamlDocument::deleteChildNodes()
{
    Sequence::iterator it = doc.begin();

    while (it != doc.end()) {
        YamlNode *yamlNode = static_cast<YamlNode *> (*it);

        switch (yamlNode->getType()) {
            case DOCUMENT:
                break;
            case SEQUENCE: {
                SequenceNode *sequence = static_cast<SequenceNode *> (yamlNode);
                sequence->deleteChildNodes();
                delete sequence;
                sequence = NULL;
            }
            break;
            case MAPPING: {
                MappingNode *mapping = static_cast<MappingNode *> (yamlNode);
                mapping->deleteChildNodes();
                delete mapping;
                mapping = NULL;
            }
            break;
            case SCALAR: {
                ScalarNode *scalar = static_cast<ScalarNode *> (yamlNode);
                delete scalar;
                scalar = NULL;
            }
            break;
            default:
                break;
        }

        it++;
    }
}
Ejemplo n.º 5
0
void MappingNode::deleteChildNodes()
{
    Mapping::iterator it;

    for (it = map.begin(); it != map.end(); ++it) {
        YamlNode *yamlNode = static_cast<YamlNode *> (it->second);
        if (!yamlNode)
            continue;

        switch (yamlNode->getType()) {
            case DOCUMENT:
                break;
            case SEQUENCE: {
                SequenceNode *sequence = static_cast<SequenceNode *> (yamlNode);
                sequence->deleteChildNodes();
                delete sequence;
                sequence = NULL;
            }
            break;
            case MAPPING: {
                MappingNode *mapping = static_cast<MappingNode *> (yamlNode);
                mapping->deleteChildNodes();
                delete mapping;
                mapping = NULL;
            }
            break;
            case SCALAR: {
                ScalarNode *scalar = static_cast<ScalarNode *> (yamlNode);
                delete scalar;
                scalar = NULL;
            }
            break;
            default:
                break;
        }
    }
}
Ejemplo n.º 6
0
TurnTowardsTypeNode::TurnTowardsTypeNode() {
    
    //Search and turn for the current Target    
    SequenceNode *cSequence = new SequenceNode();
    cSequence->addChild(new SearchNode());
    cSequence->addChild(new InverterNode(new IsTurnedOnTargetNode(1)));
    cSequence->addChild(new TurnNode());
    cSequence->addChild(new TurnNeckToCenterNode());
    cSequence->addChild(new WaitSeeStateUpdateNode());
    cSequence->addChild(new WaitBodyStateUpdateNode());
    cSequence->addChild(new EndActNode());
    addChild(new SuccessNode(new RepeatUntilFailNode(cSequence)));

    
    addChild(new SuccessNode(new PushTargetToStackNode()));
    addChild(new SetTargetToNode(new BehaviorTarget(WidthTypeNarrow, QualityTypeHigh, NODE_NAME)));
    addChild(new ChangeViewNode());
    addChild(new SuccessNode(new PopFromStackNode()));
    
    //Update variables and body state
    addChild(new EndActNode());
    
}
Ejemplo n.º 7
0
void SlGeneratorInstance::RegisterNode(Node* node)
{
	// if registration of node already began
	if(registeredNodes.find(node) != registeredNodes.end())
	{
		// if node is not registered yet
		if(nodeInitIndices.find(node) == nodeInitIndices.end())
			// than it's a loop
			THROW("Node cyclic dependency");
		// else it's ok, it's just another use of node
		return;
	}
	// register node
	registeredNodes.insert(node);

	switch(node->GetType())
	{
	case Node::typeFloatConst:
	case Node::typeIntConst:
		break;
	case Node::typeAttribute:
		{
			if(shaderType != ShaderTypes::vertex)
				THROW("Only vertex shader can have attribute nodes");

			attributes.push_back(fast_cast<AttributeNode*>(node));
		}
		break;
	case Node::typeUniform:
		{
			UniformNode* uniformNode = fast_cast<UniformNode*>(node);
			uniforms.push_back(std::make_pair(uniformNode->GetGroup(), uniformNode));
		}
		break;
	case Node::typeSampler:
		samplers.push_back(fast_cast<SamplerNode*>(node));
		break;
	case Node::typeReadUniform:
		RegisterNode(fast_cast<ReadUniformNode*>(node)->GetUniformNode());
		break;
	case Node::typeIndexUniformArray:
		{
			IndexUniformArrayNode* indexUniformArrayNode = fast_cast<IndexUniformArrayNode*>(node);
			RegisterNode(indexUniformArrayNode->GetUniformNode());
			RegisterNode(indexUniformArrayNode->GetIndexNode());
		}
		break;
	case Node::typeTransformed:
		transformedNodes.push_back(fast_cast<TransformedNode*>(node));
		break;
	case Node::typeInterpolate:
		{
			InterpolateNode* interpolateNode = fast_cast<InterpolateNode*>(node);
			interpolateNodes.push_back(interpolateNode);
			RegisterNode(interpolateNode->GetNode());
		}
		break;
	case Node::typeSequence:
		{
			SequenceNode* sequenceNode = fast_cast<SequenceNode*>(node);
			RegisterNode(sequenceNode->GetA());
			RegisterNode(sequenceNode->GetB());
		}
		break;
	case Node::typeSwizzle:
		RegisterNode(fast_cast<SwizzleNode*>(node)->GetA());
		break;
	case Node::typeOperation:
		{
			OperationNode* operationNode = fast_cast<OperationNode*>(node);
			int argumentsCount = operationNode->GetArgumentsCount();
			for(int i = 0; i < argumentsCount; ++i)
				RegisterNode(operationNode->GetArgument(i));
		}
		break;
	case Node::typeAction:
		{
			ActionNode* actionNode = fast_cast<ActionNode*>(node);
			int argumentsCount = actionNode->GetArgumentsCount();
			for(int i = 0; i < argumentsCount; ++i)
				RegisterNode(actionNode->GetArgument(i));
		}
		break;
	case Node::typeSample:
		{
			SampleNode* sampleNode = fast_cast<SampleNode*>(node);

			RegisterNode(sampleNode->GetSamplerNode());
			RegisterNode(sampleNode->GetCoordsNode());

			ValueNode* lodNode = sampleNode->GetLodNode();
			if(lodNode)
				RegisterNode(lodNode);

			ValueNode* biasNode = sampleNode->GetBiasNode();
			if(biasNode)
				RegisterNode(biasNode);

			ValueNode* gradXNode = sampleNode->GetGradXNode();
			if(gradXNode)
				RegisterNode(gradXNode);
			ValueNode* gradYNode = sampleNode->GetGradYNode();
			if(gradYNode)
				RegisterNode(gradYNode);

			ValueNode* offsetNode = sampleNode->GetOffsetNode();
			if(offsetNode)
				RegisterNode(offsetNode);
		}
		break;
	case Node::typeFragment:
		{
			if(shaderType != ShaderTypes::pixel)
				THROW("Only pixel shader can do fragment output");
			FragmentNode* fragmentNode = fast_cast<FragmentNode*>(node);

			// register maximum number of fragment outputs
			fragmentTargetsCount = std::max(fragmentTargetsCount, fragmentNode->GetTarget() + 1);
			RegisterNode(fragmentNode->GetNode());
		}
		break;
	case Node::typeDualFragment:
		{
			if(shaderType != ShaderTypes::pixel)
				THROW("Only pixel shader can do dual fragment output");
			DualFragmentNode* dualFragmentNode = fast_cast<DualFragmentNode*>(node);

			dualFragmentTarget = true;

			// register maximum number of fragment outputs
			fragmentTargetsCount = std::max(fragmentTargetsCount, 2);
			RegisterNode(dualFragmentNode->GetNode0());
			RegisterNode(dualFragmentNode->GetNode1());
		}
		break;
	case Node::typeCast:
		RegisterNode(fast_cast<CastNode*>(node)->GetA());
		break;
	default:
		THROW("Unknown node type");
	}

	// add initialization of node
	THROW_ASSERT(nodeInitIndices.find(node) == nodeInitIndices.end());
	nodeInitIndices[node] = (int)nodeInits.size();
	nodeInits.push_back(node);
}
Ejemplo n.º 8
0
void YamlEmitter::addMappingItem(int mappingid, const std::string &key, YamlNode *node)
{
    if (node->getType() == SCALAR) {
        ScalarNode *sclr = static_cast<ScalarNode *>(node);

        int temp1;
        if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0)
            throw YamlEmitterException("Could not add scalar to document");

        int temp2;
        if ((temp2 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) sclr->getValue().c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0)
            throw YamlEmitterException("Could not add scalar to document");

        if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0)
            throw YamlEmitterException("Could not append mapping pair to mapping");

    } else if (node->getType() == MAPPING) {
        MappingNode *map = static_cast<MappingNode *>(node);

        int temp1;
        if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0)
            throw YamlEmitterException("Could not add scalar to document");

        int temp2;
        if ((temp2 = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0)
            throw YamlEmitterException("Could not add scalar to document");

        if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0)
            throw YamlEmitterException("Could not add mapping pair to mapping");

        addMappingItems(temp2, map->getMapping());

    } else if (node->getType() == SEQUENCE) {
        SequenceNode *seqnode = static_cast<SequenceNode *>(node);

        int temp1;
        if ((temp1 = yaml_document_add_scalar(&document_, NULL, (yaml_char_t *) key.c_str(), -1, YAML_PLAIN_SCALAR_STYLE)) == 0)
            throw YamlEmitterException("Could not add scalar to document");

        int temp2;
        if ((temp2 = yaml_document_add_sequence(&document_, NULL, YAML_BLOCK_SEQUENCE_STYLE)) == 0)
            throw YamlEmitterException("Could not add scalar to document");

        if (yaml_document_append_mapping_pair(&document_, mappingid, temp1, temp2) == 0)
            throw YamlEmitterException("Could not append mapping pair to mapping");

        Sequence *seq = seqnode->getSequence();
        for (const auto &it : *seq) {
            YamlNode *yamlNode = it;
            int id;
            if ((id = yaml_document_add_mapping(&document_, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0)
                throw YamlEmitterException("Could not add account mapping to document");

            if (yaml_document_append_sequence_item(&document_, temp2, id) == 0)
                throw YamlEmitterException("Could not append account mapping to sequence");

            MappingNode *mapnode = static_cast<MappingNode*>(yamlNode);
            addMappingItems(id, mapnode->getMapping());
        }
    } else
        throw YamlEmitterException("Unknown node type while adding mapping node");
}
Ejemplo n.º 9
0
void SIPAccount::unserialize(const Conf::MappingNode &map)
{
    using namespace Conf;

    map.getValue(ALIAS_KEY, &alias_);
    map.getValue(TYPE_KEY, &type_);
    map.getValue(USERNAME_KEY, &username_);
    map.getValue(HOSTNAME_KEY, &hostname_);
    map.getValue(ACCOUNT_ENABLE_KEY, &enabled_);
    map.getValue(MAILBOX_KEY, &mailBox_);
    map.getValue(CODECS_KEY, &codecStr_);
    // Update codec list which one is used for SDP offer
    setActiveCodecs(ManagerImpl::split_string(codecStr_));

    map.getValue(RINGTONE_PATH_KEY, &ringtonePath_);
    map.getValue(RINGTONE_ENABLED_KEY, &ringtoneEnabled_);
    map.getValue(Preferences::REGISTRATION_EXPIRE_KEY, &registrationExpire_);
    map.getValue(INTERFACE_KEY, &interface_);
    int port = DEFAULT_SIP_PORT;
    map.getValue(PORT_KEY, &port);
    localPort_ = port;
    map.getValue(PUBLISH_ADDR_KEY, &publishedIpAddress_);
    map.getValue(PUBLISH_PORT_KEY, &port);
    publishedPort_ = port;
    map.getValue(SAME_AS_LOCAL_KEY, &publishedSameasLocal_);
    map.getValue(KEEP_ALIVE_ENABLED, &keepAliveEnabled_);

    std::string dtmfType;
    map.getValue(DTMF_TYPE_KEY, &dtmfType);
    dtmfType_ = dtmfType;

    map.getValue(SERVICE_ROUTE_KEY, &serviceRoute_);
    map.getValue(UPDATE_CONTACT_HEADER_KEY, &contactUpdateEnabled_);

    // stun enabled
    map.getValue(STUN_ENABLED_KEY, &stunEnabled_);
    map.getValue(STUN_SERVER_KEY, &stunServer_);

    // Init stun server name with default server name
    stunServerName_ = pj_str((char*) stunServer_.data());

    map.getValue(DISPLAY_NAME_KEY, &displayName_);

    std::vector<std::map<std::string, std::string> > creds;

    YamlNode *credNode = map.getValue(CRED_KEY);

    /* We check if the credential key is a sequence
     * because it was a mapping in a previous version of
     * the configuration file.
     */
    if (credNode && credNode->getType() == SEQUENCE) {
        SequenceNode *credSeq = static_cast<SequenceNode *>(credNode);
        Sequence::iterator it;
        Sequence *seq = credSeq->getSequence();

        for (it = seq->begin(); it != seq->end(); ++it) {
            MappingNode *cred = static_cast<MappingNode *>(*it);
            std::string user;
            std::string pass;
            std::string realm;
            cred->getValue(CONFIG_ACCOUNT_USERNAME, &user);
            cred->getValue(CONFIG_ACCOUNT_PASSWORD, &pass);
            cred->getValue(CONFIG_ACCOUNT_REALM, &realm);
            std::map<std::string, std::string> credentialMap;
            credentialMap[CONFIG_ACCOUNT_USERNAME] = user;
            credentialMap[CONFIG_ACCOUNT_PASSWORD] = pass;
            credentialMap[CONFIG_ACCOUNT_REALM] = realm;
            creds.push_back(credentialMap);
        }
    }

    if (creds.empty()) {
        // migration from old file format
        std::map<std::string, std::string> credmap;
        std::string password;
        map.getValue(PASSWORD_KEY, &password);

        credmap[CONFIG_ACCOUNT_USERNAME] = username_;
        credmap[CONFIG_ACCOUNT_PASSWORD] = password;
        credmap[CONFIG_ACCOUNT_REALM] = "*";
        creds.push_back(credmap);
    }

    setCredentials(creds);

    // get srtp submap
    MappingNode *srtpMap = static_cast<MappingNode *>(map.getValue(SRTP_KEY));

    if (srtpMap) {
        srtpMap->getValue(SRTP_ENABLE_KEY, &srtpEnabled_);
        srtpMap->getValue(KEY_EXCHANGE_KEY, &srtpKeyExchange_);
        srtpMap->getValue(RTP_FALLBACK_KEY, &srtpFallback_);
    }

    // get zrtp submap
    MappingNode *zrtpMap = static_cast<MappingNode *>(map.getValue(ZRTP_KEY));

    if (zrtpMap) {
        zrtpMap->getValue(DISPLAY_SAS_KEY, &zrtpDisplaySas_);
        zrtpMap->getValue(DISPLAY_SAS_ONCE_KEY, &zrtpDisplaySasOnce_);
        zrtpMap->getValue(HELLO_HASH_ENABLED_KEY, &zrtpHelloHash_);
        zrtpMap->getValue(NOT_SUPP_WARNING_KEY, &zrtpNotSuppWarning_);
    }

    // get tls submap
    MappingNode *tlsMap = static_cast<MappingNode *>(map.getValue(TLS_KEY));

    if (tlsMap) {
        tlsMap->getValue(TLS_ENABLE_KEY, &tlsEnable_);
        std::string tlsPort;
        tlsMap->getValue(TLS_PORT_KEY, &tlsPort);
        tlsListenerPort_ = atoi(tlsPort.c_str());
        tlsMap->getValue(CERTIFICATE_KEY, &tlsCertificateFile_);
        tlsMap->getValue(CALIST_KEY, &tlsCaListFile_);
        tlsMap->getValue(CIPHERS_KEY, &tlsCiphers_);
        tlsMap->getValue(METHOD_KEY, &tlsMethod_);
        tlsMap->getValue(TLS_PASSWORD_KEY, &tlsPassword_);
        tlsMap->getValue(PRIVATE_KEY_KEY, &tlsPrivateKeyFile_);
        tlsMap->getValue(REQUIRE_CERTIF_KEY, &tlsRequireClientCertificate_);
        tlsMap->getValue(SERVER_KEY, &tlsServerName_);
        tlsMap->getValue(VERIFY_CLIENT_KEY, &tlsVerifyServer_);
        tlsMap->getValue(VERIFY_SERVER_KEY, &tlsVerifyClient_);
        // FIXME
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutSec_);
        tlsMap->getValue(TIMEOUT_KEY, &tlsNegotiationTimeoutMsec_);
    }
}
Ejemplo n.º 10
0
SearchNode::SearchNode() : InverterNode(new SequenceNode()) {
    
    //Take the existing child into a pointer
    SequenceNode *cCheckingSequence = static_cast<SequenceNode*>(&getChild());
    
    /********************************************
     * Checks if the target is visible, if not  *
     * changes the view settings for search.    *
     *******************************************/
    
    /*
     * First check if the object is already visible.
     * if not continue the sequence, otherwise
     * stop the sequence once found. For the sequence to
     * continue, a successful answer must be received from
     * not seeing the target. We will use an Inverter.
     */
        
    InverterNode *cInvert = new InverterNode(new IsTargetVisibleNode());
    cCheckingSequence->addChild(cInvert);
    
    /*
     * When searching, first we need to change the view quality to low,
     * and the width angle to wide. Because we are searching
     * for a specific target in context, we save it onto
     * the stack, load our target, pop the stack and continue.
     */
    
    //Push the current target to the stack - dont care if there isnt a target
    cCheckingSequence->addChild(new SuccessNode(new PushTargetToStackNode()));
    
    //Create our required target for view changing
    cCheckingSequence->addChild(new SetTargetToNode(new BehaviorTarget(WidthTypeWide, QualityTypeLow, NODE_NAME)));
    
    //Change the view
    cCheckingSequence->addChild(new ChangeViewNode());
    
    //Pop the previous target back to the context - dont care if there isnt a target
    cCheckingSequence->addChild(new SuccessNode(new PopFromStackNode()));
    
    //Call the EndAct node to update the view settings
    cCheckingSequence->addChild(new ExecuteActNode());
    
    
    /*
     * This next section will be repeated 
     * until the target is found.
     */
    
    SequenceNode *cSequence = new SequenceNode();
    
    /********************************************
     *  Rotate the head - check center,         *
     *  left and right.                         *
     *******************************************/
    
    cSequence->addChild(new InverterNode(new SearchTurnNeckNode()));
    
    /********************************************
     *  Turn the body, and check again. The     *
     *  turning of the body is decided by       *
     *  the maximum angle.                      *
     *******************************************/
    
    cSequence->addChild(new TurnTwiceMaximumHeadAngleNode());
    
    //Implement the repeater
    cCheckingSequence->addChild(new RepeatUntilFailNode(cSequence));
        
}
Ejemplo n.º 11
0
SearchTurnNeckNode::SearchTurnNeckNode() : InverterNode(new SequenceNode()) {
    
    /************************************************
     * Check if visibile on center, otherwise turn  *
     * to right, check again, and if not turn left. *
     ***********************************************/
    
    //Take the existing child into a pointer
    SequenceNode *cCheckingSequence = static_cast<SequenceNode*>(&getChild());
    
    /*
     * If not visible, we need to continue the sequence,
     * thus we will use an Inverter. The addVisibilityCheck
     * does this process for us.
     */
    
    addVisibilityCheck(cCheckingSequence);
    
    /*
     * If not found, the sequence continues and we need to turn the neck.
     * Need to repeat the positive rotation until maximum, at which it
     * will fail. Thus we need to repeat until fail.
     */

    TurnNeckNegativeNode *cTurnNegative = new TurnNeckNegativeNode();
    
    //Also check visibility at each turn
    addVisibilityCheck(cTurnNegative);
    
    //Repeat the node until it fails
    RepeatUntilFailNode *cRepeatUntilFailNeg = new RepeatUntilFailNode(cTurnNegative);
    
    //Dont want to stop sequence here if found node or just cant proceed - it will always be true
    SuccessNode *cSuccessRepeatNeg = new SuccessNode(cRepeatUntilFailNeg);
    
    cCheckingSequence->addChild(cSuccessRepeatNeg);

    
    /*
     * At this section, we would have already turned the neck
     * to the maximum angle. We need to check again if the 
     * target is visible using an inverter just like before.
     */

    addVisibilityCheck(cCheckingSequence);
    
    
    TurnNeckPositiveNode *cTurnPositive = new TurnNeckPositiveNode();
    
    //Also check visibility at each turn
    addVisibilityCheck(cTurnPositive);
    
    //Repeat the node until it fails
    RepeatUntilFailNode *cRepeatUntilFailPos = new RepeatUntilFailNode(cTurnPositive);
    
    //Dont want to stop sequence here if found node or just cant proceed - it will always be true
    SuccessNode *cSuccessRepeatPos = new SuccessNode(cRepeatUntilFailPos);
    
    cCheckingSequence->addChild(cSuccessRepeatPos);

    /*
     * At this section, we would have already turned the neck
     * to the minimum angle. We need to check again if the
     * target is visible using an inverter just like before.
     */
    
    addVisibilityCheck(cCheckingSequence);
    
    
    /*
     * If the sequence still continues, it means that we
     * havnt found the target. Thus, turn the neck back to
     * the center.
     */

    //The result of this node should be disregarded, thus always succedes
    cCheckingSequence->addChild(new SuccessNode(new TurnNeckToCenterNode()));
    cCheckingSequence->addChild(new ExecuteActNode());
    
}