diff --git a/ddt.h b/ddt.h index f142f8e..760b443 100644 --- a/ddt.h +++ b/ddt.h @@ -71,6 +71,21 @@ struct PTPText { Octet *text; }; +/* A static_ptp_text is like a PTPText but includes space to store the + * text inside the struct. The text array must always be + * null-terminated. Also tracks a maximum number of symbols. Note in + * UTF-8, # symbols != # bytes. + */ +#define MAX_PTP_OCTETS 255 +struct static_ptp_text { + /* null-terminated array of UTF-8 symbols */ + Octet text[MAX_PTP_OCTETS + 1]; + /* number of used bytes in text, not including trailing null */ + int length; + /* max number of UTF-8 symbols that can be in text */ + int max_symbols; +}; + struct FaultRecord { UInteger16 faultRecordLength; struct Timestamp faultTime; diff --git a/util.c b/util.c index 4f432a6..cb8db61 100644 --- a/util.c +++ b/util.c @@ -17,6 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include +#include #include "sk.h" #include "util.h" @@ -90,3 +91,60 @@ int generate_clock_identity(struct ClockIdentity *ci, char *name) ci->id[7] = mac[5]; return 0; } + +/* Naive count of utf8 symbols. Doesn't detect invalid UTF-8 and + * probably doesn't count combining characters correctly. */ +static size_t strlen_utf8(const Octet *s) +{ + size_t len = 0; + char c; + while ((c = *(s++))) { + if ((c & 0xC0) != 0x80) + len++; + } + return len; +} + +int static_ptp_text_copy(struct static_ptp_text *dst, const struct PTPText *src) +{ + int len = src->length; + if (dst->max_symbols > 0 && strlen_utf8(src->text) > dst->max_symbols) + return -1; + dst->length = len; + memcpy(dst->text, src->text, len); + dst->text[len] = '\0'; + return 0; +} + +void ptp_text_copy(struct PTPText *dst, const struct static_ptp_text *src) +{ + dst->length = src->length; + dst->text = (Octet *)src->text; +} + +int ptp_text_set(struct PTPText *dst, const char *src) +{ + size_t len; + if (src) { + len = strlen(src); + if (len > MAX_PTP_OCTETS) + return -1; + dst->length = len; + dst->text = (Octet *)src; + } else { + dst->length = 0; + dst->text = NULL; + } + return 0; +} + +int static_ptp_text_set(struct static_ptp_text *dst, const char *src) +{ + struct PTPText t; + size_t len = strlen(src); + if (len > MAX_PTP_OCTETS) + return -1; + t.length = len; + t.text = (Octet *)src; + return static_ptp_text_copy(dst, &t); +} diff --git a/util.h b/util.h index d538cce..5fe9dda 100644 --- a/util.h +++ b/util.h @@ -56,4 +56,42 @@ char *pid2str(struct PortIdentity *id); int generate_clock_identity(struct ClockIdentity *ci, char *name); +/** + * Copies a PTPText to a static_ptp_text. This copies the text into + * the static_ptp_text.o + * @param dst The static_ptp_text to copy to + * @param src The PTPText to copy from + * @return Zero on success, -1 if text in src is too long or not valid + * UTF8 + */ +int static_ptp_text_copy(struct static_ptp_text *dst, const struct PTPText *src); + +/** + * Copies a static_ptp_text to a PTPText. This makes the PTPText point + * to the memory inside the static_ptp_text. + * @param dst The PTPText to copy to + * @param src The static_ptp_text to copy from + */ +void ptp_text_copy(struct PTPText *dst, const struct static_ptp_text *src); + +/** + * Sets a PTPText from a null-terminated char*. After returning, the + * PTPText field points to the same memory as str, so str should not + * be modified and should remain valid as long as the PTPText can be + * used. + * @param dst The PTPText to copy to + * @param src The text to copy from + * @return Zero on success, -1 if src is too long + */ +int ptp_text_set(struct PTPText *dst, const char *src); + +/** + * Sets a static_ptp_text from a null-terminated char*. + * @param dst The static_ptp_text to copy to + * @param src The text to copy from + * @return Zero on success, -1 if text in src is too long or not valid + * UTF8 + */ +int static_ptp_text_set(struct static_ptp_text *dst, const char *src); + #endif