/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvAccessCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include using namespace epics::pvData; using namespace std; using std::tr1::static_pointer_cast; namespace epics { namespace pvAccess { const int8 IntrospectionRegistry::NULL_TYPE_CODE = (int8)-1; const int8 IntrospectionRegistry::ONLY_ID_TYPE_CODE = (int8)-2; const int8 IntrospectionRegistry::FULL_WITH_ID_TYPE_CODE = (int8)-3; FieldCreatePtr IntrospectionRegistry::_fieldCreate(getFieldCreate()); IntrospectionRegistry::IntrospectionRegistry() { reset(); } IntrospectionRegistry::~IntrospectionRegistry() { reset(); } void IntrospectionRegistry::reset() { _pointer = 1; _registry.clear(); } FieldConstPtr IntrospectionRegistry::getIntrospectionInterface(const int16 id) { registryMap_t::iterator registryIter = _registry.find(id); if(registryIter == _registry.end()) { return FieldConstPtr(); } return registryIter->second; } void IntrospectionRegistry::registerIntrospectionInterface(const int16 id, FieldConstPtr const & field) { _registry[id] = field; } int16 IntrospectionRegistry::registerIntrospectionInterface(FieldConstPtr const & field, bool& existing) { int16 key; // TODO this is slow if(registryContainsValue(field, key)) { existing = true; } else { existing = false; key = _pointer++; _registry[key] = field; } return key; } void IntrospectionRegistry::printKeysAndValues(string name) { string buffer; cout << "############## print of all key/values of " << name.c_str() << " registry : ###################" << endl; for(registryMap_t::iterator registryIter = _registry.begin(); registryIter != _registry.end(); registryIter++) { buffer.erase(); cout << "\t" << "Key: "<< registryIter->first << endl; cout << "\t" << "Value: " << registryIter->second << endl; cout << "\t" << "References: " << buffer.c_str() << endl; buffer.erase(); registryIter->second->toString(&buffer); cout << "\t" << "Value toString: " << buffer.c_str() << endl; } } // TODO slow !!!! bool IntrospectionRegistry::registryContainsValue(FieldConstPtr const & field, int16& key) { for(registryMap_t::reverse_iterator registryRIter = _registry.rbegin(); registryRIter != _registry.rend(); registryRIter++) { if(*(field.get()) == *(registryRIter->second)) { key = registryRIter->first; return true; } } return false; } void IntrospectionRegistry::serialize(FieldConstPtr const & field, ByteBuffer* buffer, SerializableControl* control) { if (field.get() == NULL) { SerializationHelper::serializeNullField(buffer, control); } else { // do not cache scalars, scalarArrays // ... and (array of) variant unions - not worth the complex condition, // unless bool Field.cache() would exist if (field->getType() != scalar && field->getType() != scalarArray) { bool existing; const int16 key = registerIntrospectionInterface(field, existing); if (existing) { control->ensureBuffer(3); buffer->putByte(ONLY_ID_TYPE_CODE); buffer->putShort(key); return; } else { control->ensureBuffer(3); buffer->putByte(FULL_WITH_ID_TYPE_CODE); // could also be a mask buffer->putShort(key); } } field->serialize(buffer, control); } } FieldConstPtr IntrospectionRegistry::deserialize(ByteBuffer* buffer, DeserializableControl* control) { control->ensureData(1); size_t pos = buffer->getPosition(); const int8 typeCode = buffer->getByte(); if (typeCode == NULL_TYPE_CODE) { return FieldConstPtr(); } else if (typeCode == ONLY_ID_TYPE_CODE) { control->ensureData(sizeof(int16)/sizeof(int8)); return getIntrospectionInterface(buffer->getShort()); } // could also be a mask if(typeCode == IntrospectionRegistry::FULL_WITH_ID_TYPE_CODE) { control->ensureData(sizeof(int16)/sizeof(int8)); const short key = buffer->getShort(); FieldConstPtr field = _fieldCreate->deserialize(buffer, control); registerIntrospectionInterface(key, field); return field; } // return typeCode back buffer->setPosition(pos); return _fieldCreate->deserialize(buffer, control); } }}