Browse Source

Merge branch '0.2' into merge_02

Julius Pfrommer 7 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
 This changelog reports changes to the public API. Internal refactorings and bug
 fixes are not reported here.
 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>
 2017-07-03 jpfr <julius.pfrommer at web.de>
 
 
  * Implement asynchronous service calls for the client
  * 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.
 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)
 [![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
 ### Features
 
 

+ 30 - 10
src/ua_types.c

@@ -467,7 +467,7 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
 #endif
 #endif
 
 
     /* Test the integrity of the source variant dimensions, make dimensions
     /* 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;
     u32 arrayLength = (u32)v->arrayLength;
     const u32 *dims = &arrayLength;
     const u32 *dims = &arrayLength;
     size_t dims_count = 1;
     size_t dims_count = 1;
@@ -480,18 +480,32 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range,
         if(elements != v->arrayLength)
         if(elements != v->arrayLength)
             return UA_STATUSCODE_BADINTERNALERROR;
             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;
     size_t count = 1;
+    UA_UInt32 *realmax = (UA_UInt32*)UA_alloca(sizeof(UA_UInt32) * dims_count);
     if(range.dimensionsSize != dims_count)
     if(range.dimensionsSize != dims_count)
         return UA_STATUSCODE_BADINDEXRANGENODATA;
         return UA_STATUSCODE_BADINDEXRANGENODATA;
     for(size_t i = 0; i < dims_count; ++i) {
     for(size_t i = 0; i < dims_count; ++i) {
         if(range.dimensions[i].min > range.dimensions[i].max)
         if(range.dimensions[i].min > range.dimensions[i].max)
             return UA_STATUSCODE_BADINDEXRANGEINVALID;
             return UA_STATUSCODE_BADINDEXRANGEINVALID;
-        if(range.dimensions[i].max >= dims[i])
+        if(range.dimensions[i].min >= dims[i])
             return UA_STATUSCODE_BADINDEXRANGENODATA;
             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;
     *total = count;
 
 
     /* Compute the stride length and the position of the first element */
     /* 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;
     bool found_contiguous = false;
     for(size_t k = dims_count; k > 0;) {
     for(size_t k = dims_count; k > 0;) {
         --k;
         --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]) {
         if(!found_contiguous && dimrange != dims[k]) {
             /* Found the maximum block that can be copied contiguously */
             /* Found the maximum block that can be copied contiguously */
             found_contiguous = true;
             found_contiguous = true;
@@ -525,15 +539,21 @@ isStringLike(const UA_DataType *type) {
     return false;
     return false;
 }
 }
 
 
+/* Returns the part of the string that lies within the rangedimension */
 static UA_StatusCode
 static UA_StatusCode
 copySubString(const UA_String *src, UA_String *dst,
 copySubString(const UA_String *src, UA_String *dst,
               const UA_NumericRangeDimension *dim) {
               const UA_NumericRangeDimension *dim) {
     if(dim->min > dim->max)
     if(dim->min > dim->max)
         return UA_STATUSCODE_BADINDEXRANGEINVALID;
         return UA_STATUSCODE_BADINDEXRANGEINVALID;
-    if(dim->max >= src->length)
+    if(dim->min >= src->length)
         return UA_STATUSCODE_BADINDEXRANGENODATA;
         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);
     UA_StatusCode retval = UA_ByteString_allocBuffer(dst, length);
     if(retval != UA_STATUSCODE_GOOD)
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
         return retval;
@@ -585,13 +605,13 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
 
 
     /* Allocate the array */
     /* Allocate the array */
     UA_Variant_init(dst);
     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)
     if(!dst->data)
         return UA_STATUSCODE_BADOUTOFMEMORY;
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
 
     /* Copy the range */
     /* Copy the range */
     size_t block_count = count / block;
     size_t block_count = count / block;
+    size_t elem_size = src->type->memSize;
     uintptr_t nextdst = (uintptr_t)dst->data;
     uintptr_t nextdst = (uintptr_t)dst->data;
     uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
     uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
     if(nextrange.dimensionsSize == 0) {
     if(nextrange.dimensionsSize == 0) {

+ 19 - 0
tests/check_types_builtin.c

@@ -1292,6 +1292,23 @@ START_TEST(UA_Variant_copyShallWorkOnSingleValueExample) {
 }
 }
 END_TEST
 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) {
 START_TEST(UA_Variant_copyShallWorkOn1DArrayExample) {
     // given
     // given
     UA_String *srcArray = UA_Array_new(3, &UA_TYPES[UA_TYPES_STRING]);
     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_copyShallWorkOnSingleValueExample);
     tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn1DArrayExample);
     tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn1DArrayExample);
     tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn2DArrayExample);
     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_DiagnosticInfo_copyShallWorkOnExample);
     tcase_add_test(tc_copy, UA_ApplicationDescription_copyShallWorkOnExample);
     tcase_add_test(tc_copy, UA_ApplicationDescription_copyShallWorkOnExample);
     tcase_add_test(tc_copy, UA_QualifiedName_copyShallWorkOnInputExample);
     tcase_add_test(tc_copy, UA_QualifiedName_copyShallWorkOnInputExample);