diff --git a/epan/column-utils.c b/epan/column-utils.c index a3bfe87ecc..a4a9cf9a24 100644 --- a/epan/column-utils.c +++ b/epan/column-utils.c @@ -25,10 +25,6 @@ #include #include -#ifdef _WIN32 -#include -#endif - #include "column-utils.h" #include "timestamp.h" #include "to_str.h" @@ -45,7 +41,9 @@ #include #include #include + #include +#include #ifdef HAVE_LUA #include @@ -445,21 +443,9 @@ col_snprint_port(gchar *buf, gulong buf_siz, port_type typ, guint16 val) if (gbl_resolv_flags.transport_name && (str = try_serv_name_lookup(typ, val)) != NULL) { -/* - * I'm not sure what GLib is doing on Windows, but according to the VS 2013 - * profiler StringCchPrintf does it in 100x fewer samples. - */ -#ifdef _WIN32 - StringCchPrintfA(buf, buf_siz, "%s(%hu)", str, val); -#else - g_snprintf(buf, buf_siz, "%s(%"G_GUINT16_FORMAT")", str, val); -#endif + ws_snprintf(buf, buf_siz, "%s(%"G_GUINT16_FORMAT")", str, val); } else { -#ifdef _WIN32 - StringCchPrintfA(buf, buf_siz, "%hu", val); -#else - g_snprintf(buf, buf_siz, "%"G_GUINT16_FORMAT, val); -#endif + ws_snprintf(buf, buf_siz, "%"G_GUINT16_FORMAT, val); } } diff --git a/epan/expert.c b/epan/expert.c index b45541da2e..75e5981978 100644 --- a/epan/expert.c +++ b/epan/expert.c @@ -27,6 +27,8 @@ #include #include +#include + #include "packet.h" #include "expert.h" #include "uat.h" @@ -539,7 +541,7 @@ expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int sever } if (use_vaformat) { - g_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap); + ws_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap); } else { g_strlcpy(formatted, format, ITEM_LABEL_LENGTH); } diff --git a/wsutil/Makefile.am b/wsutil/Makefile.am index 95c57d2582..2cedf9ddbb 100644 --- a/wsutil/Makefile.am +++ b/wsutil/Makefile.am @@ -89,7 +89,8 @@ libwsutil_nonrepl_INCLUDES = \ utf8_entities.h \ ws_cpuid.h \ ws_mempbrk.h \ - ws_mempbrk_int.h + ws_mempbrk_int.h \ + ws_printf.h # Header files for functions in libwsutil's ABI on this platform. libwsutil_abi_INCLUDES = \ diff --git a/wsutil/ws_printf.h b/wsutil/ws_printf.h new file mode 100644 index 0000000000..1ee3bf69e6 --- /dev/null +++ b/wsutil/ws_printf.h @@ -0,0 +1,100 @@ +/* + * Wrappers for printf like functions. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 2007 Gerald Combs + * + * This program is free 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __WS_PRINTF_H__ +#define __WS_PRINTF_H__ + +/* + * GLib's string utility routines are slow on windows, likely due to calling + * g_printf_string_upper_bound. Using ws_snprintf and ws_vsnprintf in hot + * code paths can speed up program execution. Otherwise you're probably safe + * sticking with g_snprintf and g_vsnprintf. + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef _WIN32 +#include + +#if _MSC_VER < 1900 +#include + +/* + * vsnprintf_s's return value isn't compatible with C99 vsnprintf. We don't + * return anything in order to avoid confusion. + */ + +static __inline void +ws_vsnprintf(char *buffer, size_t size_of_buffer, const char *format, va_list argptr) { + /* We could alternatively use StringCchVPrintfA */ + vsnprintf_s(buffer, size_of_buffer, _TRUNCATE, format, argptr); +} + +#else /* _MSC_VER uses UCRT */ + +/* The UCRT versions of snprintf and vsnprintf conform to C99 */ + +static __inline void +ws_vsnprintf(char *buffer, size_t size_of_buffer, const char *format, va_list argptr) +{ + vsnprintf(buffer, size_of_buffer, format, argptr); +} + +#endif /* _MSC_VER */ + +#else /* _WIN32 */ + +#include + +/* + * Use g_vsnprintf. On Linux and macOS these should be a thin wrapper around + * vsprintf. + */ + +static inline void +ws_vsnprintf(char *buffer, size_t size_of_buffer, const char *format, va_list argptr) +{ + g_vsnprintf(buffer, (gulong) size_of_buffer, format, argptr); +} + +#endif /* _WIN32 */ + +#ifdef _WIN32 +static __inline void +#else +static inline void +#endif +ws_snprintf(char *buffer, size_t size_of_buffer, const char * format, ...) { + va_list argptr; + + va_start(argptr, format); + ws_vsnprintf(buffer, size_of_buffer, format, argptr); + va_end(argptr); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __WS_PRINTF_H__ */