diff --git a/erpc_c/infra/erpc_basic_codec.cpp b/erpc_c/infra/erpc_basic_codec.cpp index 2b5349cd..dcc97edd 100644 --- a/erpc_c/infra/erpc_basic_codec.cpp +++ b/erpc_c/infra/erpc_basic_codec.cpp @@ -109,8 +109,8 @@ void BasicCodec::writePtr(uintptr_t value) void BasicCodec::writeString(uint32_t length, const char *value) { - // Just treat the string as binary. - writeBinary(length, reinterpret_cast(value)); + // Just treat the string as binary but add trailing NULL. + writeBinary(length + 1, reinterpret_cast(value)); } void BasicCodec::writeBinary(uint32_t length, const uint8_t *value) diff --git a/erpcgen/src/CGenerator.cpp b/erpcgen/src/CGenerator.cpp index ca454b09..589ee6cb 100644 --- a/erpcgen/src/CGenerator.cpp +++ b/erpcgen/src/CGenerator.cpp @@ -2258,11 +2258,9 @@ void CGenerator::getEncodeDecodeBuiltin(Group *group, BuiltinType *t, data_map & if (t->isString()) { + templateData["zeroCopy"] = findAnnotation(structMember, DIRECT_ANNOTATION) && !findAnnotation(structMember, RETAIN_ANNOTATION); templateData["checkStringNull"] = false; - templateData["withoutAlloc"] = ((structMember->getDirection() == kInoutDirection) || - (structType && group->getSymbolDirections(structType).count(kInoutDirection))) ? - true : - false; + if (!isFunctionParam) { templateData["stringAllocSize"] = getOutputName(structMember) + "_len"; @@ -2280,10 +2278,6 @@ void CGenerator::getEncodeDecodeBuiltin(Group *group, BuiltinType *t, data_map & templateData["checkStringNull"] = true; templateData["stringLocalName"] = getOutputName(structMember); templateData["stringAllocSize"] = getAnnStringValue(structMember, MAX_LENGTH_ANNOTATION); - if (structMember->getDirection() == kInoutDirection || structMember->getDirection() == kOutDirection) - { - templateData["withoutAlloc"] = true; - } if (templateData["stringAllocSize"]->getvalue() == "") { diff --git a/erpcgen/src/annotations.h b/erpcgen/src/annotations.h index f51d036b..ec5238cf 100644 --- a/erpcgen/src/annotations.h +++ b/erpcgen/src/annotations.h @@ -67,6 +67,9 @@ //! Do not free memory for a parameter in the server shim. #define RETAIN_ANNOTATION "retain" +//! Do not alloc memory for a parameter in the server shim, just pass the pointer in the received buffer +#define DIRECT_ANNOTATION "direct" + //! Data handled through shared memory area #define SHARED_ANNOTATION "shared" diff --git a/erpcgen/src/templates/c_coders.template b/erpcgen/src/templates/c_coders.template index 6ffcad07..dadf41a1 100644 --- a/erpcgen/src/templates/c_coders.template +++ b/erpcgen/src/templates/c_coders.template @@ -1,24 +1,31 @@ {% def decodeBuiltinType(info) --------------- BuiltinType %} {% if info.builtinType == "kStringType" %} uint32_t {$info.stringLocalName}_len; +{% if (source == "server" && info.zeroCopy) %} +codec->readString(&{$info.stringLocalName}_len, (char**) &{$info.stringLocalName}); +{% else %} char * {$info.stringLocalName}_local; codec->readString(&{$info.stringLocalName}_len, &{$info.stringLocalName}_local); -{% if ((source == "client" && info.withoutAlloc == false) or source == "server") %} -{$info.name} = (char *) erpc_malloc(({$info.stringAllocSize} + 1) * sizeof(char)); -{% if generateAllocErrorChecks == true %} +{% if source == "server" && !info.zeroCopy %} +{$info.name} = ({$info.builtinTypeName}) erpc_malloc(({$info.stringAllocSize} + 1) * sizeof(char)); +{% if generateAllocErrorChecks == true %} if ({$info.name} == NULL) { codec->updateStatus(kErpcStatus_MemoryError); } else { -{% endif -- generateAllocErrorChecks == true %} -{% endif -- withoutAlloc %} -{% if (((source == "client" && info.withoutAlloc == false) or source == "server") && generateAllocErrorChecks == true) %} {% endif -- withoutAlloc %}memcpy({$info.name}, {$info.stringLocalName}_local, {$info.stringLocalName}_len); -{% if (((source == "client" && info.withoutAlloc == false) or source == "server") && generateAllocErrorChecks == true) %} {% endif -- withoutAlloc %}({$info.name})[{$info.stringLocalName}_len] = 0; -{% if (((source == "client" && info.withoutAlloc == false) or source == "server") && generateAllocErrorChecks == true) %} +{% endif -- generateAllocErrorChecks == true %} + memcpy({$info.name}, {$info.stringLocalName}_local, {$info.stringLocalName}_len); + ({$info.name})[{$info.stringLocalName}_len] = 0; +{% if generateAllocErrorChecks == true %} } -{% endif -- withoutAlloc && generateAllocErrorChecks %} +{% endif -- generateAllocErrorChecks %} +{% else %} +memcpy({$info.name}, {$info.stringLocalName}_local, {$info.stringLocalName}_len); +({$info.name})[{$info.stringLocalName}_len] = 0; +{% endif -- server && zeroCopy %} +{% endif -- server && !zeroCopy %} {% else %} {% if source == "client" && info.pointerScalarTypes %} codec->read({$info.name}); @@ -232,7 +239,11 @@ codec->readData({$info.name}, {$info.sizeTemp} * sizeof({$info.builtinTypeName}) {# Encode sending data #} {% def encodeBuiltinType(info) ----------------- %} {% if info.builtinType == "kStringType" %} -codec->writeString(strlen({$info.name}), {$info.name}); +{% if source == "client" && info.zeroCopy %} +codec->writeString(strlen((char*){$info.name}), (char*){$info.name}); +{% else %} +codec->writeBinary(strlen((char*){$info.name}), (uint8_t*){$info.name}); +{% endif -- zeroCopy %} {% else %} {% if source == "client" && info.pointerScalarTypes %} codec->write(*{$info.name}); diff --git a/erpcgen/src/templates/c_common_functions.template b/erpcgen/src/templates/c_common_functions.template index aae030cc..a89e1cb5 100644 --- a/erpcgen/src/templates/c_common_functions.template +++ b/erpcgen/src/templates/c_common_functions.template @@ -354,10 +354,12 @@ else {# ---------------- freeData ---------------- #} {% def freeData(info) %} +{% if !info.zeroCopy %} if ({$info.freeName}) { erpc_free({$info.freeName}); } +{% endif %} {% enddef ------------------------------- freeData %} {# ---------------- freeStruct ---------------- #}