bounded string
This commit is contained in:
@@ -134,6 +134,13 @@ bool operator==(const UnionArray& a, const UnionArray& b)
|
||||
return *(a.getUnion().get())==*(b.getUnion().get());
|
||||
}
|
||||
|
||||
bool operator==(const BoundedString& a, const BoundedString& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
return a.getMaximumLength()==b.getMaximumLength();
|
||||
}
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -111,6 +111,38 @@ void Scalar::deserialize(ByteBuffer* /*buffer*/, DeserializableControl* /*contro
|
||||
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string BoundedString::getID() const
|
||||
{
|
||||
std::ostringstream id;
|
||||
id << Scalar::getID() << '(' << maxLength << ')';
|
||||
return id.str();
|
||||
}
|
||||
|
||||
void BoundedString::serialize(ByteBuffer *buffer, SerializableControl *control) const
|
||||
{
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte(0x83);
|
||||
SerializeHelper::writeSize(maxLength, buffer, control);
|
||||
}
|
||||
|
||||
std::size_t BoundedString::getMaximumLength() const
|
||||
{
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
BoundedString::BoundedString(std::size_t maxStringLength) :
|
||||
Scalar(pvString), maxLength(maxStringLength)
|
||||
{
|
||||
if (maxLength == 0)
|
||||
throw std::invalid_argument("maxLength == 0");
|
||||
}
|
||||
|
||||
BoundedString::~BoundedString() {}
|
||||
|
||||
|
||||
static string emptyStringtring;
|
||||
|
||||
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
|
||||
@@ -684,6 +716,12 @@ FieldBuilderPtr FieldBuilder::add(string const & name, ScalarType scalarType)
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addBoundedString(std::string const & name, std::size_t maxLength)
|
||||
{
|
||||
fields.push_back(fieldCreate->createBoundedString(maxLength)); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::add(string const & name, FieldConstPtr const & field)
|
||||
{
|
||||
fields.push_back(field); fieldNames.push_back(name);
|
||||
@@ -719,6 +757,10 @@ FieldBuilderPtr FieldBuilder::addArray(string const & name, FieldConstPtr const
|
||||
fields.push_back(fieldCreate->createUnionArray(static_pointer_cast<const Union>(element)));
|
||||
break;
|
||||
case scalar:
|
||||
|
||||
if (std::tr1::dynamic_pointer_cast<const BoundedString>(element).get())
|
||||
throw std::invalid_argument("bounded string arrays are not supported");
|
||||
|
||||
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
|
||||
break;
|
||||
// scalarArray?
|
||||
@@ -828,7 +870,15 @@ ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
|
||||
|
||||
return scalars[scalarType];
|
||||
}
|
||||
|
||||
|
||||
BoundedStringConstPtr FieldCreate::createBoundedString(std::size_t maxLength) const
|
||||
{
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<BoundedString> s(new BoundedString(maxLength), Field::Deleter());
|
||||
BoundedStringConstPtr sa = s;
|
||||
return sa;
|
||||
}
|
||||
|
||||
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
|
||||
{
|
||||
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
|
||||
@@ -1047,6 +1097,20 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
// Type type = Type.union; variant union (aka any type)
|
||||
return variantUnion;
|
||||
}
|
||||
else if (typeCode == 0x83)
|
||||
{
|
||||
// TODO cache?
|
||||
// bounded string
|
||||
|
||||
size_t size = SerializeHelper::readSize(buffer, control);
|
||||
|
||||
// TODO use std::make_shared
|
||||
std::tr1::shared_ptr<Field> sp(
|
||||
new BoundedString(size),
|
||||
Field::Deleter());
|
||||
FieldConstPtr p = sp;
|
||||
return p;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("invalid type encoding");
|
||||
}
|
||||
|
||||
@@ -145,11 +145,18 @@ public:
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const;
|
||||
private:
|
||||
string value;
|
||||
std::size_t maxLength;
|
||||
};
|
||||
|
||||
BasePVString::BasePVString(ScalarConstPtr const & scalar)
|
||||
: PVString(scalar),value()
|
||||
{}
|
||||
{
|
||||
BoundedStringConstPtr boundedString = std::tr1::dynamic_pointer_cast<const BoundedString>(scalar);
|
||||
if (boundedString.get())
|
||||
maxLength = boundedString->getMaximumLength();
|
||||
else
|
||||
maxLength = 0;
|
||||
}
|
||||
|
||||
BasePVString::~BasePVString() {}
|
||||
|
||||
@@ -157,6 +164,9 @@ string BasePVString::get() const { return value;}
|
||||
|
||||
void BasePVString::put(string val)
|
||||
{
|
||||
if (maxLength > 0 && val.length() > maxLength)
|
||||
throw std::overflow_error("string too long");
|
||||
|
||||
value = val;
|
||||
postPut();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ bool epicsShareExtern operator==(const Structure&, const Structure&);
|
||||
bool epicsShareExtern operator==(const StructureArray&, const StructureArray&);
|
||||
bool epicsShareExtern operator==(const Union&, const Union&);
|
||||
bool epicsShareExtern operator==(const UnionArray&, const UnionArray&);
|
||||
bool epicsShareExtern operator==(const BoundedString&, const BoundedString&);
|
||||
|
||||
static inline bool operator!=(const Field& a, const Field& b)
|
||||
{return !(a==b);}
|
||||
@@ -50,6 +51,8 @@ static inline bool operator!=(const Union& a, const Union& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const UnionArray& a, const UnionArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const BoundedString& a, const BoundedString& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,6 +93,8 @@ class StructureArray;
|
||||
class Union;
|
||||
class UnionArray;
|
||||
|
||||
class BoundedString;
|
||||
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable Field.
|
||||
*/
|
||||
@@ -129,6 +131,10 @@ typedef std::tr1::shared_ptr<const Union> UnionConstPtr;
|
||||
* typedef for a shared pointer to an immutable UnionArray.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const UnionArray> UnionArrayConstPtr;
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable BoundedString.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<const BoundedString> BoundedStringConstPtr;
|
||||
|
||||
/**
|
||||
* Definition of support field types.
|
||||
@@ -366,6 +372,33 @@ private:
|
||||
friend class ScalarArray;
|
||||
friend class BoundedScalarArray;
|
||||
friend class FixedScalarArray;
|
||||
friend class BoundedString;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements introspection object for BoundedString.
|
||||
*/
|
||||
class epicsShareClass BoundedString : public Scalar{
|
||||
public:
|
||||
POINTER_DEFINITIONS(BoundedString);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~BoundedString();
|
||||
typedef BoundedString& reference;
|
||||
typedef const BoundedString& const_reference;
|
||||
|
||||
virtual std::string getID() const;
|
||||
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
|
||||
std::size_t getMaximumLength() const;
|
||||
|
||||
protected:
|
||||
BoundedString(std::size_t maxStringLength);
|
||||
private:
|
||||
std::size_t maxLength;
|
||||
friend class FieldCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -812,6 +845,14 @@ public:
|
||||
*/
|
||||
FieldBuilderPtr add(std::string const & name, ScalarType scalarType);
|
||||
|
||||
/**
|
||||
* Add a {@code BoundedString}.
|
||||
* @param name name of the array.
|
||||
* @param maxLength a string maximum length.
|
||||
* @return this instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr addBoundedString(std::string const & name, std::size_t maxLength);
|
||||
|
||||
/**
|
||||
* Add a {@code Field} (e.g. {@code Structure}, {@code Union}).
|
||||
* @param name name of the array.
|
||||
@@ -961,6 +1002,13 @@ public:
|
||||
* @throws An {@code IllegalArgumentException} if an illegal type is specified.
|
||||
*/
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const;
|
||||
/**
|
||||
* Create a {@code BoundedString}.
|
||||
* @param maxLength a string maximum length.
|
||||
* @return a {@code BoundedString} interface for the newly created object.
|
||||
* @throws An {@code IllegalArgumentException} if maxLength == 0.
|
||||
*/
|
||||
BoundedStringConstPtr createBoundedString(std::size_t maxLength) const;
|
||||
/**
|
||||
* Create an {@code Array} field, variable size array.
|
||||
* @param elementType The {@code scalarType} for array elements
|
||||
|
||||
@@ -720,6 +720,38 @@ void testArraySizeType() {
|
||||
serializationTest(pvs);
|
||||
}
|
||||
|
||||
void testBoundedString() {
|
||||
testDiag("Testing bounded string...");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
StructureConstPtr s = fieldCreate->createFieldBuilder()->
|
||||
add("str", pvString)->
|
||||
addBoundedString("boundedStr", 8)->
|
||||
add("scalar", pvDouble)->
|
||||
createStructure();
|
||||
testOk1(s.get() != 0);
|
||||
testOk1(Structure::DEFAULT_ID == s->getID());
|
||||
testOk1(3 == s->getFields().size());
|
||||
|
||||
serializationFieldTest(s);
|
||||
PVStructurePtr pvs = getPVDataCreate()->createPVStructure(s);
|
||||
serializationTest(pvs);
|
||||
|
||||
PVStringPtr pvStr = pvs->getSubField<PVString>("boundedStr");
|
||||
pvStr->put("");
|
||||
pvStr->put("small");
|
||||
pvStr->put("exact123");
|
||||
|
||||
try {
|
||||
pvStr->put("tooLargeString");
|
||||
testFail("too large string accepted");
|
||||
} catch (std::overflow_error oe) {
|
||||
// OK
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void testStringCopy() {
|
||||
string s1 = "abc";
|
||||
string s2 = s1;
|
||||
@@ -731,7 +763,7 @@ void testStringCopy() {
|
||||
|
||||
MAIN(testSerialization) {
|
||||
|
||||
testPlan(221);
|
||||
testPlan(226);
|
||||
|
||||
flusher = new SerializableControlImpl();
|
||||
control = new DeserializableControlImpl();
|
||||
@@ -751,6 +783,7 @@ MAIN(testSerialization) {
|
||||
testUnion();
|
||||
|
||||
testArraySizeType();
|
||||
testBoundedString();
|
||||
|
||||
|
||||
delete buffer;
|
||||
|
||||
@@ -225,6 +225,21 @@ static void testUnion()
|
||||
|
||||
}
|
||||
|
||||
static void testBoundedString()
|
||||
{
|
||||
testDiag("testBoundedString");
|
||||
|
||||
BoundedStringConstPtr bs = fieldCreate->createBoundedString(8);
|
||||
|
||||
Type type = bs->getType();
|
||||
testOk1(type==scalar);
|
||||
|
||||
ScalarType scalarType = bs->getScalarType();
|
||||
testOk1(scalarType==pvString);
|
||||
|
||||
testOk1(bs->getMaximumLength()==8);
|
||||
}
|
||||
|
||||
|
||||
#define testExcept(EXCEPT, CMD) try{ CMD; testFail( "No exception from: " #CMD); } \
|
||||
catch(EXCEPT& e) {testPass("Got expected exception from: " #CMD);} \
|
||||
@@ -296,7 +311,7 @@ static void testMapping()
|
||||
|
||||
MAIN(testIntrospect)
|
||||
{
|
||||
testPlan(324);
|
||||
testPlan(327);
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
@@ -304,6 +319,7 @@ MAIN(testIntrospect)
|
||||
testScalarArray();
|
||||
testStructure();
|
||||
testUnion();
|
||||
testBoundedString();
|
||||
testError();
|
||||
testMapping();
|
||||
return testDone();
|
||||
|
||||
Reference in New Issue
Block a user