String stuff that should be in stdlib but isn't.
Dependents: X10Svr SSDP_Server
SW_String.cpp
- Committer:
- WiredHome
- Date:
- 2019-02-27
- Revision:
- 3:bc30d348f5b4
- Parent:
- 2:c7a3039893cb
File content as of revision 3:bc30d348f5b4:
#include "SW_String.h" #define DEBUG "SWst" #include <cstdio> #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) #define DBG(x, ...) std::printf("[DBG %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #else #define DBG(x, ...) #define WARN(x, ...) #define ERR(x, ...) #define INFO(x, ...) #endif /// A more secure version of strcat /// /// This function is like a wrapper on strcat, to first validate the concatination /// and then if all parameters appear good, it will call strcat. It will not /// permit overlapping source and destination. /// /// If there is an error, no concatination is performed. /// /// @note This has a different return value than the normal strcat. /// /// @param[out] dst is a pointer to the start of the destination buffer (not necessarily /// where the next string will appear). /// @param[in] dstSize defines the size of the destination buffer. /// @param[in] src is a pointer to the source. /// /// @returns /// - 0 = no error /// - -1 = destination pointer invalid /// - -2 = source is too big to append into the destination /// - -3 = overlap between src and dst /// int strcat_s(char * dst, size_t dstSize, const char * src) { if (dst == NULL) { ERR("strcat_s FAIL destination == NULL"); return -1; } if (src == NULL || *src == '\0') return 0; // done, that was easy. // [Source .... // [Destination ... ] if (src >= dst && src < (dst + dstSize)) { ERR("strcat_s FAIL source overlaps destination"); return -3; } int dstLen = strlen(dst); int srcLen = strlen(src); // [Source ..... +srcLen] // [Destination + dstSize] if (src + srcLen >= dst && src + srcLen <= dst + dstSize) { ERR("strcat_s FAIL source + length overlaps destination"); return -3; } // [Source length > freespace] // [Destination ... \0[freespace]] if (dstLen + srcLen > dstSize) { ERR("strcat_s FAIL dstLen + srcLen > size"); return -2; } strcat(dst, src); return 0; } /// A more secure version of strcpy /// /// This function is like a wrapper on strcpy, to first validate the concatination /// and then if all parameters appear good, it will call strcpy. It will not /// permit overlapping source and destination. /// /// If there is an error, no copy is performed. /// /// @note This has a different return value than the normal strcpy. /// /// @param[out] dst is a pointer to the start of the destination buffer. /// @param[in] dstSize defines the size of the destination buffer. /// @param[in] src is a pointer to the source. /// /// @returns /// - 0 = no error /// - -1 = destination pointer invalid /// - -2 = source is too big to append into the destination /// - -3 = overlap between src and dst /// int strcpy_s(char * dst, size_t dstSize, const char * src) { if (dst == NULL) { ERR("strcpy_s FAIL destination == NULL"); return -1; } if (src == NULL || *src == '\0') { *dst = '\0'; return 0; // done, that was easy. } if (src >= dst && src < dst + dstSize) { ERR("strcpy_s FAIL source overlaps destination"); return -3; } int srcLen = strlen(src); if (src + srcLen >= dst && src + srcLen <= dst + dstSize) { ERR("strcpy_s FAIL source + length overlaps destination"); return -3; } if (srcLen > dstSize) { ERR("strcpy_s FAIL dstLen + srcLen > size"); return -2; } strcpy(dst, src); return 0; } /// sw_tolower exists because not all compiler libraries have this function /// /// This takes a character and if it is upper-case, it converts it to /// lower-case and returns it. /// /// @note an alternate means would be a 256-entry lookup table. Very fast... /// /// @param a is the character to convert /// @returns the lower case equivalent to a /// char sw_tolower(char a) { if (a >= 'A' && a <= 'Z') return (a - 'A' + 'a'); else return a; } /// sw_strnicmp exists because not all compiler libraries have this function. /// /// In a case-insensitive compare, evaluate 'n' characters of the left and /// right referenced strings. /// /// @note Some compilers have strnicmp, others _strnicmp, and others have C++ /// methods, which is outside the scope of this C-portable set of functions. /// /// @param l is a pointer to the string on the left /// @param r is a pointer to the string on the right /// @param n is the number of characters to compare /// @returns -1 if l < r /// @returns 0 if l == r /// @returns +1 if l > r /// int sw_strnicmp(const char *l, const char *r, size_t n) { int result = 0; if (n != 0) { do { result = sw_tolower(*l++) - sw_tolower(*r++); } while ((result == 0) && (*l != '\0') && (--n > 0)); } if (result < -1) result = -1; else if (result > 1) result = 1; return result; } /// sw_stristr exists because not all compiler libraries have this function. /// /// In a case-insenstive search, try to find the needle in the haystack. /// /// @param haystack is a pointer to string being searched /// @param needle is a pointer to a string to find /// @returns a pointer to the found needle in the haystack, or NULL /// const char * sw_stristr(const char * haystack, const char * needle) { while (*haystack) { if (sw_tolower(*haystack) == sw_tolower(*needle)) { if (sw_strnicmp(haystack, needle, strlen(needle)) == 0) { return (char *)haystack; } } haystack++; } return NULL; } /// sw_stristr exists because not all compiler libraries have this function. /// /// In a case-insenstive search, try to find the needle in the haystack. /// /// @param haystack is a pointer to string being searched /// @param needle is a pointer to a string to find /// @returns a pointer to the found needle in the haystack, or NULL /// char * sw_stristr(char * haystack, const char * needle) { while (*haystack) { if (sw_tolower(*haystack) == sw_tolower(*needle)) { if (sw_strnicmp(haystack, needle, strlen(needle)) == 0) { return (char *)haystack; } } haystack++; } return NULL; }