// // -------------------------------------------------------------------------- // Gurux Ltd // // // // Filename: $HeadURL$ // // Version: $Revision$, // $Date$ // $Author$ // // Copyright (c) Gurux Ltd // //--------------------------------------------------------------------------- // // DESCRIPTION // // This file is a part of Gurux Device Framework. // // Gurux Device Framework is Open Source software; you can redistribute it // and/or modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; version 2 of the License. // Gurux Device Framework is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // This code is licensed under the GNU General Public License v2. // Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt //--------------------------------------------------------------------------- #if _MSC_VER > 1400 #include #include #endif #include #include #include "gxmem.h" #if defined(_WIN32) || defined(_WIN64) #include #endif //defined(_WIN32) || defined(_WIN64) #if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC) #include //printf needs this or error is generated. #endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC) #include "helpers.h" #include "errorcodes.h" //Check byte order. unsigned char hlp_isBigEndian(void) { uint16_t a = 0x1234; return *((unsigned char*)&a) == 0x12; } const char* hlp_getErrorMessage(int error) { const char* str; if ((error & DLMS_ERROR_TYPE_EXCEPTION_RESPONSE) != 0) { switch (error & 0xFF) { case DLMS_EXCEPTION_SERVICE_ERROR_OPERATION_NOT_POSSIBLE: str = GET_STR_FROM_EEPROM("OperationNotPossible"); break; case DLMS_EXCEPTION_SERVICE_ERROR_SERVICE_NOT_SUPPORTED: str = GET_STR_FROM_EEPROM("ServiceNotSupported"); break; case DLMS_EXCEPTION_SERVICE_ERROR_OTHER_REASON: str = GET_STR_FROM_EEPROM("OtherReason"); break; case DLMS_EXCEPTION_SERVICE_ERROR_PDU_TOO_LONG: str = GET_STR_FROM_EEPROM("PduTooLong"); break; case DLMS_EXCEPTION_SERVICE_ERROR_DECIPHERING_ERROR: str = GET_STR_FROM_EEPROM("DecipheringError"); break; case DLMS_EXCEPTION_SERVICE_ERROR_INVOCATION_COUNTER_ERROR: str = GET_STR_FROM_EEPROM("InvocationCounterError"); break; default: str = GET_STR_FROM_EEPROM("Unknown Exception response."); break; } } else if ((error & DLMS_ERROR_TYPE_CONFIRMED_SERVICE_ERROR) != 0) { str = GET_STR_FROM_EEPROM("Confirmed Service Error."); } else if ((error & DLMS_ERROR_TYPE_COMMUNICATION_ERROR) != 0) { #if defined(_WIN32) || defined(_WIN64) || defined(__linux__) #if defined(_WIN32) || defined(_WIN64) wchar_t* s = NULL; FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error & ~DLMS_ERROR_TYPE_COMMUNICATION_ERROR, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&s, 0, NULL); printf("%S\n", s); LocalFree(s); str = GET_STR_FROM_EEPROM("Connection error."); #else str = strerror(error & ~DLMS_ERROR_TYPE_COMMUNICATION_ERROR); #endif str = GET_STR_FROM_EEPROM("Connection error."); #else str = GET_STR_FROM_EEPROM("Connection error."); #endif } else { switch (error) { case DLMS_ERROR_CODE_OK: str = GET_STR_FROM_EEPROM("OK"); break; case DLMS_ERROR_CODE_INVALID_PARAMETER: str = GET_STR_FROM_EEPROM("Invalid parameter."); break; case DLMS_ERROR_CODE_NOT_INITIALIZED: str = GET_STR_FROM_EEPROM("Server is not initialized."); break; case DLMS_ERROR_CODE_OUTOFMEMORY: str = GET_STR_FROM_EEPROM("Not enough memory available."); break; case DLMS_ERROR_CODE_NOT_REPLY: str = GET_STR_FROM_EEPROM("Packet is not a reply for a send packet."); break; case DLMS_ERROR_CODE_REJECTED: str = GET_STR_FROM_EEPROM("Meter rejects send packet."); break; case DLMS_ERROR_CODE_INVALID_LOGICAL_NAME: str = GET_STR_FROM_EEPROM("Invalid Logical Name."); break; case DLMS_ERROR_CODE_INVALID_CLIENT_ADDRESS: str = GET_STR_FROM_EEPROM("Client HDLC Address is not set."); break; case DLMS_ERROR_CODE_INVALID_SERVER_ADDRESS: str = GET_STR_FROM_EEPROM("Server HDLC Address is not set."); break; case DLMS_ERROR_CODE_INVALID_DATA_FORMAT: str = GET_STR_FROM_EEPROM("Not a HDLC frame."); break; case DLMS_ERROR_CODE_INVALID_VERSION_NUMBER: str = GET_STR_FROM_EEPROM("Invalid DLMS version number."); break; case DLMS_ERROR_CODE_CLIENT_ADDRESS_NO_NOT_MATCH: str = GET_STR_FROM_EEPROM("Client addresses do not match."); break; case DLMS_ERROR_CODE_SERVER_ADDRESS_NO_NOT_MATCH: str = GET_STR_FROM_EEPROM("Server addresses do not match."); break; case DLMS_ERROR_CODE_WRONG_CRC: str = GET_STR_FROM_EEPROM("CRC do not match."); break; case DLMS_ERROR_CODE_INVALID_RESPONSE: str = GET_STR_FROM_EEPROM("Invalid response"); break; case DLMS_ERROR_CODE_INVALID_TAG: str = GET_STR_FROM_EEPROM("Invalid Tag."); break; case DLMS_ERROR_CODE_ENCODING_FAILED: str = GET_STR_FROM_EEPROM("Encoding failed. Not enough data."); break; case DLMS_ERROR_CODE_REJECTED_PERMAMENT: str = GET_STR_FROM_EEPROM("Rejected permament."); break; case DLMS_ERROR_CODE_REJECTED_TRANSIENT: str = GET_STR_FROM_EEPROM("Rejected transient."); break; case DLMS_ERROR_CODE_NO_REASON_GIVEN: str = GET_STR_FROM_EEPROM("No reason given."); break; case DLMS_ERROR_CODE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED: str = GET_STR_FROM_EEPROM("Application context name not supported."); break; case DLMS_ERROR_CODE_AUTHENTICATION_MECHANISM_NAME_NOT_RECOGNISED: str = GET_STR_FROM_EEPROM("Authentication mechanism name not recognised."); break; case DLMS_ERROR_CODE_AUTHENTICATION_MECHANISM_NAME_REQUIRED: str = GET_STR_FROM_EEPROM("Authentication mechanism name required."); break; case DLMS_ERROR_CODE_AUTHENTICATION_FAILURE: str = GET_STR_FROM_EEPROM("Authentication failure."); break; case DLMS_ERROR_CODE_AUTHENTICATION_REQUIRED: str = GET_STR_FROM_EEPROM("Authentication required."); break; case DLMS_ERROR_CODE_HARDWARE_FAULT: str = GET_STR_FROM_EEPROM("Access Error : Device reports a hardware fault."); break; case DLMS_ERROR_CODE_TEMPORARY_FAILURE: str = GET_STR_FROM_EEPROM("Access Error : Device reports a temporary failure."); break; case DLMS_ERROR_CODE_READ_WRITE_DENIED: str = GET_STR_FROM_EEPROM("Access Error : Device reports Read-Write denied."); break; case DLMS_ERROR_CODE_UNDEFINED_OBJECT: str = GET_STR_FROM_EEPROM("Access Error : Device reports a undefined object."); break; case DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT: str = GET_STR_FROM_EEPROM("Access Error : Device reports a inconsistent Class or Object."); break; case DLMS_ERROR_CODE_UNAVAILABLE_OBJECT: str = GET_STR_FROM_EEPROM("Access Error : Device reports a unavailable object."); break; case DLMS_ERROR_CODE_UNMATCH_TYPE: str = GET_STR_FROM_EEPROM("Access Error : Device reports a unmatched type."); break; case DLMS_ERROR_CODE_ACCESS_VIOLATED: str = GET_STR_FROM_EEPROM("Access Error : Device reports scope of access violated."); break; case DLMS_ERROR_CODE_DATA_BLOCK_UNAVAILABLE: str = GET_STR_FROM_EEPROM("Access Error : Data Block Unavailable."); break; case DLMS_ERROR_CODE_LONG_GET_OR_READ_ABORTED: str = GET_STR_FROM_EEPROM("Access Error : Long Get Or Read Aborted."); break; case DLMS_ERROR_CODE_NO_LONG_GET_OR_READ_IN_PROGRESS: str = GET_STR_FROM_EEPROM("Access Error : No Long Get Or Read In Progress."); break; case DLMS_ERROR_CODE_LONG_SET_OR_WRITE_ABORTED: str = GET_STR_FROM_EEPROM("Access Error : Long Set Or Write Aborted."); break; case DLMS_ERROR_CODE_NO_LONG_SET_OR_WRITE_IN_PROGRESS: str = GET_STR_FROM_EEPROM("Access Error : No Long Set Or Write In Progress."); break; case DLMS_ERROR_CODE_DATA_BLOCK_NUMBER_INVALID: str = GET_STR_FROM_EEPROM("Access Error : Data Block Number Invalid."); break; case DLMS_ERROR_CODE_OTHER_REASON: str = GET_STR_FROM_EEPROM("Access Error : Other Reason."); break; case DLMS_ERROR_CODE_UNKNOWN: str = GET_STR_FROM_EEPROM("Unknown error."); break; case DLMS_ERROR_CODE_SEND_FAILED: str = GET_STR_FROM_EEPROM("Data send failed."); break; case DLMS_ERROR_CODE_RECEIVE_FAILED: str = GET_STR_FROM_EEPROM("Data receive failed."); break; case DLMS_ERROR_CODE_NOT_IMPLEMENTED: str = GET_STR_FROM_EEPROM("Not implemeted."); break; case DLMS_ERROR_CODE_INVALID_INVOKE_ID: str = GET_STR_FROM_EEPROM("Invalid Invoke ID."); break; case DLMS_ERROR_CODE_INVOCATION_COUNTER_TOO_SMALL: str = GET_STR_FROM_EEPROM("Invocation counter value is too small."); break; case DLMS_ERROR_CODE_INVALID_DECIPHERING_ERROR: str = GET_STR_FROM_EEPROM("Deciphering error."); break; case DLMS_ERROR_CODE_INVALID_SECURITY_SUITE: str = GET_STR_FROM_EEPROM("Client try to connect with wrong security suite."); break; default: str = GET_STR_FROM_EEPROM("Unknown error."); break; } } return str; } unsigned char hlp_getObjectCountSizeInBytes(uint32_t count) { if (count < 0x80) { return 1; } else if (count < 0x100) { return 2; } else if (count < 0x10000) { return 3; } else { return 5; } } int hlp_getObjectCount(gxByteBuffer* buff) { int ret; unsigned char ch; ret = bb_getUInt8(buff, &ch); if (ret != 0) { return -1; } if (ch > 0x80) { if (ch == 0x81) { ret = bb_getUInt8(buff, &ch); } else if (ch == 0x82) { uint16_t value; ret = bb_getUInt16(buff, &value); if (ret != 0) { return -1; } return value; } else if (ch == 0x83) { uint32_t value; ret = bb_getUInt24(buff, &value); if (ret != 0) { return -1; } return value; } else if (ch == 0x84) { uint32_t value; ret = bb_getUInt32(buff, &value); if (ret != 0) { return -1; } return value; } else { return -1; } } return ch; } int hlp_getObjectCount2(gxByteBuffer* buff, uint16_t* count) { int ret; unsigned char ch; ret = bb_getUInt8(buff, &ch); if (ret != 0) { return ret; } if (ch > 0x80) { if (ch == 0x81) { ret = bb_getUInt8(buff, &ch); *count = ch; } else if (ch == 0x82) { ret = bb_getUInt16(buff, count); } else if (ch == 0x83) { uint32_t value; ret = bb_getUInt24(buff, &value); *count = (uint16_t)value; } else if (ch == 0x84) { uint32_t value; ret = bb_getUInt32(buff, &value); *count = (uint16_t)value; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } } else { *count = ch; } return ret; } // Set count of items. int hlp_setObjectCount(uint32_t count, gxByteBuffer* buff) { int ret; if (count < 0x80) { ret = bb_setUInt8(buff, (unsigned char)count); } else if (count < 0x100) { if ((ret = bb_setUInt8(buff, 0x81)) == 0) { ret = bb_setUInt8(buff, (unsigned char)count); } } else if (count < 0x10000) { if ((ret = bb_setUInt8(buff, 0x82)) == 0) { ret = bb_setUInt16(buff, (uint16_t)count); } } else { if ((ret = bb_setUInt8(buff, 0x84)) == 0) { ret = bb_setUInt32(buff, count); } } return ret; } #ifndef DLMS_IGNORE_MALLOC char* hlp_bytesToHex(const unsigned char* bytes, int count) { const char hexArray[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; unsigned char tmp; int pos; char* hexChars; if (count != 0) { hexChars = (char*)gxmalloc(3 * count); if (hexChars != NULL) { for (pos = 0; pos != count; ++pos) { tmp = bytes[pos] & 0xFF; hexChars[pos * 3] = hexArray[tmp >> 4]; hexChars[pos * 3 + 1] = hexArray[tmp & 0x0F]; hexChars[pos * 3 + 2] = ' '; } hexChars[(3 * count) - 1] = '\0'; } } else { hexChars = (char*)gxmalloc(1); hexChars[0] = '\0'; } return hexChars; } #endif //DLMS_IGNORE_MALLOC int hlp_bytesToHex2(const unsigned char* bytes, uint16_t count, char* buff, uint16_t size) { const char hexArray[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; unsigned char tmp; int pos; if (3 * count > size) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } if (count != 0) { for (pos = 0; pos != count; ++pos) { tmp = bytes[pos] & 0xFF; buff[pos * 3] = hexArray[tmp >> 4]; buff[pos * 3 + 1] = hexArray[tmp & 0x0F]; buff[pos * 3 + 2] = ' '; } buff[(3 * count) - 1] = '\0'; } else { buff[0] = '\0'; } return 0; } unsigned char hlp_getValue(char c) { unsigned char value; if (c > '9') { if (c > 'Z') { value = (c - 'a' + 10); } else { value = (c - 'A' + 10); } } else { value = (c - '0'); } return value; } #ifndef DLMS_IGNORE_MALLOC int hlp_hexToBytes( const char* str, unsigned char** buffer, uint16_t* count) { *count = 0; if (buffer != NULL && *buffer != NULL) { gxfree(*buffer); } if (str == NULL) { return 0; } int len = (int)strlen(str); if (len == 0) { return 0; } unsigned char* tmp = (unsigned char*)gxmalloc(len / 2); if (tmp == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } *buffer = tmp; int lastValue = -1; for (int pos = 0; pos != len; ++pos) { if (*str >= '0' && *str < 'g') { if (lastValue == -1) { lastValue = hlp_getValue(*str); } else if (lastValue != -1) { tmp[*count] = (unsigned char)(lastValue << 4 | hlp_getValue(*str)); lastValue = -1; ++* count; } } else if (lastValue != -1) { tmp[*count] = hlp_getValue(*str); lastValue = -1; ++* count; } ++str; } if (len / 2 != *count) { #ifdef gxrealloc //If compiler supports realloc. *buffer = gxrealloc(*buffer, *count); #else //A few extra bytes are returned if compiler doesn't support realloc. #endif // gxrealloc } return 0; } #endif //DLMS_IGNORE_MALLOC int hlp_hexToBytes2( const char* str, unsigned char* buffer, uint16_t* count) { uint16_t max = *count; *count = 0; if (buffer == NULL) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } if (str == NULL) { return 0; } int len = (int)strlen(str); if (len == 0) { return 0; } int lastValue = -1; for (int pos = 0; pos != len; ++pos) { if (*str >= '0' && *str < 'g') { if (lastValue == -1) { lastValue = hlp_getValue(*str); } else if (lastValue != -1) { buffer[*count] = (unsigned char)(lastValue << 4 | hlp_getValue(*str)); lastValue = -1; ++* count; } } else if (lastValue != -1) { buffer[*count] = hlp_getValue(*str); lastValue = -1; ++* count; } if (max < *count) { return DLMS_ERROR_CODE_OUTOFMEMORY; } ++str; } return 0; } #if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC) void hlp_trace(unsigned char* data, int index, int count, unsigned char send) { char* buff = hlp_bytesToHex(data + index, count); if (send) { printf("<- %s\r\n", buff); } else { printf("-> %s\r\n", buff); } gxfree(buff); } int hlp_parseLogicalName(gxByteBuffer* value, unsigned char ln[6]) { char* ch; char* pOriginalBuff; char* pBuff; int val = 0, count = 0, size = value->size; if (size < 11) { return -1; } pBuff = (char*)gxmalloc(size + 1); pOriginalBuff = pBuff; memcpy(pBuff, value->data, size); pBuff[value->size] = 0; //AVR compiler can't handle this if casting to char* is removed. while ((ch = (char*)strchr(pBuff, '.')) != NULL) { *ch = '\0'; val = hlp_stringToInt(pBuff); if (val == -1) { return -1; } ln[count] = (unsigned char)val; pBuff = ch + sizeof(char); ++count; } if (count == 5) { val = hlp_stringToInt(pBuff); if (val == -1) { return -1; } ln[count] = (unsigned char)val; pBuff = ch + sizeof(char); ++count; } gxfree(pOriginalBuff); if (count != 6) { memset(ln, 0, 6); return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } //Set logical name from string. int hlp_setLogicalName2(dlmsVARIANT* ln, const char* name) { int ret; unsigned char tmp[6]; var_clear(ln); if ((ret = hlp_setLogicalName(tmp, name)) != 0) { return ret; } var_addBytes(ln, tmp, 6); return DLMS_ERROR_CODE_OK; } int hlp_printLogicalName(const char* format, const unsigned char value[6]) { char ln[25]; int ret = hlp_getLogicalNameToString(value, ln); if (ret != 0) { return ret; } if (format != NULL) { printf(format, ln); } else { printf("%s", ln); } return 0; } int hlp_appendLogicalName(gxByteBuffer* bb, const unsigned char value[6]) { char ln[25]; int ret = hlp_getLogicalNameToString(value, ln); if (ret != 0) { return ret; } return bb_addString(bb, ln); } #endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC) int hlp_getLogicalNameToString(const unsigned char value[6], char* ln) { int ret; #if defined(_WIN32) || defined(_WIN64) #if _MSC_VER > 1000 ret = sprintf_s(ln, 25, "%d.%d.%d.%d.%d.%d", value[0], value[1], value[2], value[3], value[4], value[5]); #else ret = sprintf(ln, "%d.%d.%d.%d.%d.%d", value[0], value[1], value[2], value[3], value[4], value[5]); #endif if (ret != -1) { ret = 0; } #else ret = hlp_intToString(ln, 25, value[0], 0, 1); if (ret != -1) { ln += ret; *ln = '.'; ++ln; ret = hlp_intToString(ln, 25, value[1], 0, 1); if (ret != -1) { ln += ret; *ln = '.'; ++ln; ret = hlp_intToString(ln, 25, value[2], 0, 1); if (ret != -1) { ln += ret; *ln = '.'; ++ln; ret = hlp_intToString(ln, 25, value[3], 0, 1); if (ret != -1) { ln += ret; *ln = '.'; ++ln; ret = hlp_intToString(ln, 25, value[4], 0, 1); if (ret != -1) { ln += ret; *ln = '.'; ++ln; ret = hlp_intToString(ln, 25, value[5], 0, 1); } } } } } if (ret != -1) { ret = 0; } #endif //WIN32 return ret; } #if !defined(DLMS_IGNORE_MALLOC) //Set logical name from string. int hlp_setLogicalName(unsigned char ln[6], const char* name) { char* ch; char* pOriginalBuff; char* pBuff; int val = 0, count = 0, size = (int)strlen(name); if (size < 11) { return -1; } pBuff = (char*)gxmalloc(size + 1); pOriginalBuff = pBuff; memcpy(pBuff, name, size); pBuff[size] = 0; //AVR compiler can't handle this if casting to char* is removed. while ((ch = (char*) strchr(pBuff, '.')) != NULL) { *ch = '\0'; val = hlp_stringToInt(pBuff); if (val == -1) { gxfree(pOriginalBuff); return -1; } ln[count] = (unsigned char)val; pBuff = ch + sizeof(char); ++count; } if (count == 5) { val = hlp_stringToInt(pBuff); if (val == -1) { gxfree(pOriginalBuff); return -1; } ln[count] = (unsigned char)val; pBuff = ch + sizeof(char); ++count; } gxfree(pOriginalBuff); if (count != 6) { memset(ln, 0, 6); return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //!defined(DLMS_IGNORE_MALLOC) void hlp_replace(gxByteBuffer* str, char oldCh, char newCh) { uint32_t pos; for (pos = 0; pos != str->size; ++pos) { if (str->data[pos] == oldCh) { str->data[pos] = newCh; } } } double hlp_getScaler(int scaler) { //If OS #if defined(_WIN32) || defined(_WIN64) || defined(__linux__) return pow((float)10, scaler); #else double ret = 1; if (scaler > 0) { while (scaler--) { ret *= 10; } } else if (scaler < 0) { while (scaler++) { ret /= 10; } } return ret; #endif } int hlp_getDataTypeSize(DLMS_DATA_TYPE type) { int size = -1; switch (type) { case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL: size = 1; break; case DLMS_DATA_TYPE_BOOLEAN: size = 1; break; case DLMS_DATA_TYPE_DATE: size = 5; break; case DLMS_DATA_TYPE_DATETIME: size = 12; break; case DLMS_DATA_TYPE_ENUM: size = 1; break; #ifndef GX_DLMS_MICROCONTROLLER case DLMS_DATA_TYPE_FLOAT32: size = 4; break; case DLMS_DATA_TYPE_FLOAT64: size = 8; break; #endif //GX_DLMS_MICROCONTROLLER case DLMS_DATA_TYPE_INT16: size = 2; break; case DLMS_DATA_TYPE_INT32: size = 4; break; case DLMS_DATA_TYPE_INT64: size = 8; break; case DLMS_DATA_TYPE_INT8: size = 1; break; case DLMS_DATA_TYPE_NONE: size = 0; break; case DLMS_DATA_TYPE_TIME: size = 4; break; case DLMS_DATA_TYPE_UINT16: size = 2; break; case DLMS_DATA_TYPE_UINT32: size = 4; break; case DLMS_DATA_TYPE_UINT64: size = 8; break; case DLMS_DATA_TYPE_UINT8: size = 1; break; default: break; } return size; } int hlp_intToString(char* str, int bufsize, int32_t value, unsigned char isSigned, unsigned char digits) { int cnt = 0; int32_t val = value; if (isSigned && value < 0) { if (bufsize < 1) { return -1; } *str = '-'; ++str; --bufsize; value = -value; val = value; ++cnt; } if (digits != 0) { --digits; } //Find length. while ((val = (val / 10)) > 0) { ++str; if (digits != 0) { --digits; } } *(str + digits + 1) = '\0'; while (digits != 0) { if (bufsize < 1) { return -1; } *str = '0'; --digits; --bufsize; ++str; ++cnt; } do { if (bufsize < 1) { return -1; } *str = (value % 10) + '0'; value /= 10; if (value != 0) { --str; } --bufsize; ++cnt; } while (value != 0); return cnt; } int hlp_uint64ToString(char* str, int bufsize, uint64_t value, unsigned char digits) { int cnt = 0; uint64_t val = value; if (digits != 0) { --digits; } //Find length. while ((val = (val / 10)) > 0) { ++str; if (digits != 0) { --digits; } } *(str + digits + 1) = '\0'; while (digits != 0) { if (bufsize < 1) { return -1; } *str = '0'; --digits; --bufsize; ++str; ++cnt; } do { if (bufsize < 1) { return -1; } *str = (value % 10) + '0'; value /= 10; if (value != 0) { --str; } --bufsize; ++cnt; } while (value != 0); return cnt; } int32_t hlp_stringToInt(const char* str) { if (str == NULL) { return -1; } int32_t value = 0; unsigned char minus = 0; if (*str == '-') { minus = 1; ++str; } while (*str != '\0') { if (*str < '0' || *str > '9') { return -1; } value *= 10; value += *str - '0'; ++str; } if (minus) { return -value; } return value; } int hlp_int64ToString(char* str, int bufsize, int64_t value, unsigned char isSigned) { int cnt = 0; int64_t val = value; if (isSigned && value < 0) { if (bufsize < 1) { return -1; } *str = '-'; ++str; --bufsize; value = -value; ++cnt; } //Find length. while ((val = (val / 10)) > 0) { ++str; } *(str + 1) = '\0'; do { if (bufsize < 1) { return -1; } *str = (value % 10) + '0'; --str; value /= 10; --bufsize; ++cnt; } while (value != 0); return cnt; } int64_t hlp_stringToInt64(const char* str) { if (str == NULL) { return -1; } int32_t value = 0; unsigned char minus = 0; if (*str == '-') { minus = 1; ++str; } while (*str != '\0') { if (*str < '0' || *str > '9') { return -1; } value *= 10; value += *str - '0'; ++str; } if (minus) { return -value; } return value; } uint16_t lfsr = 0xACE1u; unsigned bit; unsigned char hlp_rand(void) { bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1; return (unsigned char)(lfsr = (uint16_t)((lfsr >> 1) | (bit << 15))); } unsigned char hlp_swapBits(unsigned char value) { unsigned char ret = 0, pos; for (pos = 0; pos != 8; ++pos) { ret = (unsigned char)((ret << 1) | (value & 0x01)); value = (unsigned char)(value >> 1); } return ret; } int hlp_add(bitArray* arr, gxByteBuffer* bytes, uint16_t count) { uint16_t pos, bytePos = 0; int ret; unsigned char ch = 0; if (count == 0xFFFF) { count = (uint16_t)(bytes->size - bytes->position); } for (pos = 0; pos != count; ++pos) { //Get next byte. if ((pos % 8) == 0) { bytePos = 7; ret = bb_getUInt8ByIndex(bytes, bytes->position, &ch); if (ret != 0) { return ret; } ++bytes->position; } if ((ret = ba_setByIndex(arr, pos, (unsigned char)(ch & (1 << bytePos)))) != 0) { return ret; } --bytePos; ++arr->size; } return 0; }