Browse Source

Merge branch '0.2' into merge_02

Julius Pfrommer 6 years ago
parent
commit
2a42d8f1e6
4 changed files with 66 additions and 14 deletions
  1. 12 0
      CHANGELOG
  2. 5 4
      README.md
  3. 30 10
      src/ua_types.c
  4. 19 0
      tests/check_types_builtin.c

+ 12 - 0
CHANGELOG

@@ -1,6 +1,18 @@
 This changelog reports changes to the public API. Internal refactorings and bug
 fixes are not reported here.
 
+
+2017-07-04 jpfr <julius.pfrommer at web.de>
+
+ * Return partially overlapping ranges
+
+   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 speify a range that is within
+   the bounds of the array. The Server shall return a partial result if some
+   elements exist within the range.
+
 2017-07-03 jpfr <julius.pfrommer at web.de>
 
  * Implement asynchronous service calls for the client

+ 5 - 4
README.md

@@ -8,10 +8,11 @@ open62541 is licensed under the Mozilla Public License v2.0. So the *open62541 l
 The library is [available](https://github.com/open62541/open62541/releases) in standard source and binary form. In addition, the single-file source distribution merges the entire library into a single .c and .h file that can be easily added to existing projects. Example server and client implementations can be found in the [/examples](examples/) directory or further down on this page.
 
 [![Ohloh Project Status](https://www.ohloh.net/p/open62541/widgets/project_thin_badge.gif)](https://www.ohloh.net/p/open62541)
-[![Build Status](https://travis-ci.org/open62541/open62541.png?branch=0.2)](https://travis-ci.org/open62541/open62541)
-[![MSVS build status](https://ci.appveyor.com/api/projects/status/kkxppc28ek5t6yk8/branch/0.2?svg=true)](https://ci.appveyor.com/project/open62541/open62541/branch/0.2)
-[![Coverage Status](https://coveralls.io/repos/open62541/open62541/badge.png?branch=0.2)](https://coveralls.io/r/open62541/open62541?branch=0.2)
-[![Coverity Scan Build Status](https://scan.coverity.com/projects/12248/badge.svg)](https://scan.coverity.com/projects/open62541-open62541)
+[![Build Status](https://img.shields.io/travis/open62541/open62541/0.2.svg)](https://travis-ci.org/open62541/open62541)
+[![MSVS build status](https://img.shields.io/appveyor/ci/open62541/open62541/0.2.svg)](https://ci.appveyor.com/project/open62541/open62541/branch/0.2)
+[![Coverity Scan Build Status](https://img.shields.io/coverity/scan/12248.svg)](https://scan.coverity.com/projects/open62541-open62541)
+[![Coverage Status](https://img.shields.io/coveralls/open62541/open62541/0.2.svg)](https://coveralls.io/r/open62541/open62541?branch=0.2)
+[![Overall Downloads](https://img.shields.io/github/downloads/open62541/open62541/total.svg)](https://github.com/open62541/open62541/releases)
 
 ### Features
 

+ 30 - 10
src/ua_types.c

@@ -467,7 +467,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 */
     u32 arrayLength = (u32)v->arrayLength;
     const u32 *dims = &arrayLength;
     size_t dims_count = 1;
@@ -480,18 +480,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_UInt32*)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 */
@@ -502,7 +516,7 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
     bool 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;
@@ -525,15 +539,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;
@@ -585,13 +605,13 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
 
     /* Allocate the array */
     UA_Variant_init(dst);
-    size_t elem_size = src->type->memSize;
-    dst->data = UA_malloc(elem_size * count);
+    dst->data = UA_Array_new(count, src->type);
     if(!dst->data)
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
     /* Copy the range */
     size_t block_count = count / block;
+    size_t elem_size = src->type->memSize;
     uintptr_t nextdst = (uintptr_t)dst->data;
     uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
     if(nextrange.dimensionsSize == 0) {

+ 19 - 0
tests/check_types_builtin.c

@@ -1292,6 +1292,23 @@ START_TEST(UA_Variant_copyShallWorkOnSingleValueExample) {
 }
 END_TEST
 
+START_TEST(UA_Variant_copyShallWorkOnByteStringIndexRange) {
+    UA_ByteString text = UA_BYTESTRING("My xml");
+    UA_Variant src;
+    UA_Variant_setScalar(&src, &text, &UA_TYPES[UA_TYPES_BYTESTRING]);
+
+    UA_NumericRangeDimension d1 = {0, 8388607};
+    UA_NumericRange nr;
+    nr.dimensionsSize = 1;
+    nr.dimensions = &d1;
+
+    UA_Variant dst;
+    UA_StatusCode retval = UA_Variant_copyRange(&src, &dst, nr);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    UA_Variant_deleteMembers(&dst);
+}
+END_TEST
+
 START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
     // given
     UA_String *srcArray = UA_Array_new(3, &UA_TYPES[UA_TYPES_STRING]);
@@ -1515,6 +1532,8 @@ static Suite *testSuite_builtin(void) {
     tcase_add_test(tc_copy, UA_Variant_copyShallWorkOnSingleValueExample);
     tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn1DArrayExample);
     tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn2DArrayExample);
+    tcase_add_test(tc_copy, UA_Variant_copyShallWorkOnByteStringIndexRange);
+
     tcase_add_test(tc_copy, UA_DiagnosticInfo_copyShallWorkOnExample);
     tcase_add_test(tc_copy, UA_ApplicationDescription_copyShallWorkOnExample);
     tcase_add_test(tc_copy, UA_QualifiedName_copyShallWorkOnInputExample);