/*FieldCreateFactory.cpp*/ /** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvDataCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include #include #include #include #include using std::tr1::static_pointer_cast; using std::size_t; namespace epics { namespace pvData { static DebugLevel debugLevel = lowDebug; static void newLine(StringBuilder buffer, int indentLevel) { *buffer += "\n"; for(int i=0; iensureBuffer(1); buffer->putByte(typeCodeLUT[scalarType]); } void Scalar::deserialize(ByteBuffer *buffer, DeserializableControl *control) { // must be done via FieldCreate throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control) { FieldConstPtrArray const & fields = structure->getFields(); StringArray const & fieldNames = structure->getFieldNames(); std::size_t len = fields.size(); SerializeHelper::writeSize(len, buffer, control); for (std::size_t i = 0; i < len; i++) { SerializeHelper::serializeString(fieldNames[i], buffer, control); control->cachedSerialize(fields[i], buffer); } } static StructureConstPtr deserializeStructureField(const FieldCreate* fieldCreate, ByteBuffer* buffer, DeserializableControl* control) { const std::size_t size = SerializeHelper::readSize(buffer, control); FieldConstPtrArray fields; fields.reserve(size); StringArray fieldNames; fieldNames.reserve(size); for (std::size_t i = 0; i < size; i++) { fieldNames.push_back(SerializeHelper::deserializeString(buffer, control)); fields.push_back(control->cachedDeserialize(buffer)); } return fieldCreate->createStructure(fieldNames, fields); } ScalarArray::ScalarArray(ScalarType elementType) : Field(scalarArray),elementType(elementType){} ScalarArray::~ScalarArray() {} void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{ ScalarTypeFunc::toString(buffer,elementType); *buffer += "[]"; } void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) const { control->ensureBuffer(1); buffer->putByte(0x10 | typeCodeLUT[elementType]); } void ScalarArray::deserialize(ByteBuffer *buffer, DeserializableControl *control) { throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } StructureArray::StructureArray(StructureConstPtr const & structure) : Field(structureArray),pstructure(structure) { } StructureArray::~StructureArray() { if(debugLevel==highDebug) printf("~StructureArray\n"); } void StructureArray::toString(StringBuilder buffer,int indentLevel) const { if(indentLevel==0) { *buffer += "structure[]"; newLine(buffer,indentLevel + 1); pstructure->toString(buffer,indentLevel + 1); return; } pstructure->toString(buffer,indentLevel); } void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) const { control->ensureBuffer(1); buffer->putByte(0x90); control->cachedSerialize(pstructure, buffer); } void StructureArray::deserialize(ByteBuffer *buffer, DeserializableControl *control) { throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } Structure::Structure (StringArray const & fieldNames,FieldConstPtrArray const & infields) : Field(structure), fieldNames(fieldNames), fields(infields) { if(fieldNames.size()!=fields.size()) { throw std::invalid_argument("fieldNames.size()!=fields.size()"); } size_t number = fields.size(); for(size_t i=0; igetType()) { case scalar: case scalarArray: pfield->toString(buffer, indentLevel); *buffer += " "; *buffer += fieldNames[i]; break; case structure: { Field const *xxx = pfield.get(); Structure const *pstruct = static_cast(xxx); *buffer += "structure "; *buffer += fieldNames[i]; pstruct->toStringCommon(buffer,indentLevel + 1); break; } case structureArray: *buffer += "structure[] " + fieldNames[i]; newLine(buffer,indentLevel +1); pfield->toString(buffer,indentLevel +1); break; } if(iensureBuffer(1); buffer->putByte(0x80); serializeStructureField(this, buffer, control); } void Structure::deserialize(ByteBuffer *buffer, DeserializableControl *control) { throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const { // TODO use singleton instance ScalarConstPtr scalar(new Scalar(scalarType), Field::Deleter()); return scalar; } ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const { // TODO use singleton instance ScalarArrayConstPtr scalarArray(new ScalarArray(elementType), Field::Deleter()); return scalarArray; } StructureConstPtr FieldCreate::createStructure ( StringArray const & fieldNames,FieldConstPtrArray const & fields) const { StructureConstPtr structure( new Structure(fieldNames,fields), Field::Deleter()); return structure; } StructureArrayConstPtr FieldCreate::createStructureArray( StructureConstPtr const & structure) const { StructureArrayConstPtr structureArray( new StructureArray(structure), Field::Deleter()); return structureArray; } StructureConstPtr FieldCreate::appendField( StructureConstPtr const & structure,String fieldName, FieldConstPtr const & field) const { StringArray oldNames = structure->getFieldNames(); FieldConstPtrArray oldFields = structure->getFields(); size_t oldLen = oldNames.size(); StringArray newNames(oldLen+1); FieldConstPtrArray newFields(oldLen+1); for(size_t i = 0; igetFieldNames(); FieldConstPtrArray oldFields = structure->getFields(); size_t oldLen = oldNames.size(); size_t extra = fieldNames.size(); StringArray newNames(oldLen+extra); FieldConstPtrArray newFields(oldLen+extra); for(size_t i = 0; i> 5) { case 0: return pvBoolean; case 1: return integerLUT[code & 0x0F]; case 2: return floatLUT[code & 0x0F]; case 3: return pvString; default: return -1; } } FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl* control) const { control->ensureData(1); int8 code = buffer->getByte(); if (code == -1) return FieldConstPtr(); int typeCode = code & 0xE0; bool notArray = ((code & 0x10) == 0); if (notArray) { if (typeCode < 0x80) { // Type type = Type.scalar; int scalarType = decodeScalar(code); if (scalarType == -1) throw std::invalid_argument("invalid scalar type encoding"); return FieldConstPtr(new Scalar(static_cast(scalarType)), Field::Deleter()); } else if (typeCode == 0x80) { // Type type = Type.structure; return deserializeStructureField(this, buffer, control); } else throw std::invalid_argument("invalid type encoding"); } else // array { if (typeCode < 0x80) { // Type type = Type.scalarArray; int scalarType = decodeScalar(code); if (scalarType == -1) throw std::invalid_argument("invalid scalarArray type encoding"); return FieldConstPtr(new ScalarArray(static_cast(scalarType)), Field::Deleter()); } else if (typeCode == 0x80) { // Type type = Type.structureArray; StructureConstPtr elementStructure = std::tr1::static_pointer_cast(control->cachedDeserialize(buffer)); return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter()); } else throw std::invalid_argument("invalid type encoding"); } } FieldCreatePtr FieldCreate::getFieldCreate() { static FieldCreatePtr fieldCreate; static Mutex mutex; Lock xx(mutex); if(fieldCreate.get()==0) fieldCreate = FieldCreatePtr(new FieldCreate()); return fieldCreate; } FieldCreate::FieldCreate(){} FieldCreatePtr getFieldCreate() { return FieldCreate::getFieldCreate(); } }}