|
@@ -464,7 +464,7 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
|
|
|
#endif
|
|
|
|
|
|
/* Test the integrity of the source variant dimensions, make dimensions
|
|
|
- vector of one dimension if none defined */
|
|
|
+ * vector of one dimension if none defined */
|
|
|
UA_UInt32 arrayLength = (UA_UInt32)v->arrayLength;
|
|
|
const UA_UInt32 *dims = &arrayLength;
|
|
|
size_t dims_count = 1;
|
|
@@ -477,18 +477,32 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
|
|
|
if(elements != v->arrayLength)
|
|
|
return UA_STATUSCODE_BADINTERNALERROR;
|
|
|
}
|
|
|
-
|
|
|
- /* Test the integrity of the range */
|
|
|
+ UA_assert(dims_count > 0);
|
|
|
+
|
|
|
+ /* Test the integrity of the range and compute the max index used for every
|
|
|
+ * dimension. The standard says in Part 4, Section 7.22:
|
|
|
+ *
|
|
|
+ * When reading a value, the indexes may not specify a range that is within
|
|
|
+ * the bounds of the array. The Server shall return a partial result if some
|
|
|
+ * elements exist within the range. */
|
|
|
size_t count = 1;
|
|
|
+ UA_UInt32 *realmax = UA_alloca(sizeof(UA_UInt32) * dims_count);
|
|
|
if(range.dimensionsSize != dims_count)
|
|
|
return UA_STATUSCODE_BADINDEXRANGENODATA;
|
|
|
for(size_t i = 0; i < dims_count; ++i) {
|
|
|
if(range.dimensions[i].min > range.dimensions[i].max)
|
|
|
return UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
|
- if(range.dimensions[i].max >= dims[i])
|
|
|
+ if(range.dimensions[i].min >= dims[i])
|
|
|
return UA_STATUSCODE_BADINDEXRANGENODATA;
|
|
|
- count *= (range.dimensions[i].max - range.dimensions[i].min) + 1;
|
|
|
+
|
|
|
+ if(range.dimensions[i].max < dims[i])
|
|
|
+ realmax[i] = range.dimensions[i].max;
|
|
|
+ else
|
|
|
+ realmax[i] = dims[i] - 1;
|
|
|
+
|
|
|
+ count *= (realmax[i] - range.dimensions[i].min) + 1;
|
|
|
}
|
|
|
+
|
|
|
*total = count;
|
|
|
|
|
|
/* Compute the stride length and the position of the first element */
|
|
@@ -499,7 +513,7 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
|
|
|
UA_Boolean found_contiguous = false;
|
|
|
for(size_t k = dims_count; k > 0;) {
|
|
|
--k;
|
|
|
- size_t dimrange = 1 + range.dimensions[k].max - range.dimensions[k].min;
|
|
|
+ size_t dimrange = 1 + realmax[k] - range.dimensions[k].min;
|
|
|
if(!found_contiguous && dimrange != dims[k]) {
|
|
|
/* Found the maximum block that can be copied contiguously */
|
|
|
found_contiguous = true;
|
|
@@ -522,15 +536,21 @@ isStringLike(const UA_DataType *type) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+/* Returns the part of the string that lies within the rangedimension */
|
|
|
static UA_StatusCode
|
|
|
copySubString(const UA_String *src, UA_String *dst,
|
|
|
const UA_NumericRangeDimension *dim) {
|
|
|
if(dim->min > dim->max)
|
|
|
return UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
|
- if(dim->max >= src->length)
|
|
|
+ if(dim->min >= src->length)
|
|
|
return UA_STATUSCODE_BADINDEXRANGENODATA;
|
|
|
|
|
|
- size_t length = dim->max - dim->min + 1;
|
|
|
+ size_t length;
|
|
|
+ if(dim->max < src->length)
|
|
|
+ length = dim->max - dim->min + 1;
|
|
|
+ else
|
|
|
+ length = src->length - dim->min;
|
|
|
+
|
|
|
UA_StatusCode retval = UA_ByteString_allocBuffer(dst, length);
|
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
|
return retval;
|