pack.c
来自「GNet是一个简单的网络库。它是目标定向的」· C语言 代码 · 共 1,001 行 · 第 1/2 页
C
1,001 行
case '<': sizemode = 1; ++p; break; case '>': case '!': sizemode = 2; ++p; break; } for (; *p; ++p) { switch (*p) { case 'x': { for (mult=(mult?mult:1); mult; --mult) { g_return_val_if_fail (n + 1 <= len, -1); *buffer++ = 0; ++n; } mult = 0; break; } case 'b': { PACK(gint8, int); break; } case 'B': { PACK(guint8, unsigned int); break; } case 'h': { PACK2(short, int, gint16); break; } case 'H': { PACK2(unsigned short, unsigned int, guint16); break; } case 'i': { PACK2(int, int, gint32); break; } case 'I': { PACK2(unsigned int, unsigned int, guint32); break; } case 'l': { PACK2(long, int, gint32); break; } case 'L': { PACK2(unsigned long, unsigned int, guint32); break; } case 'f': { PACK(float, double); break; } case 'd': { PACK(double, double); break; } case 'v': { PACK2(void*, void*, void*); break; } case 's': { for (mult=(mult?mult:1); mult; --mult) { gchar* s; guint slen; s = va_arg (args, gchar*); g_return_val_if_fail (s, -1); slen = strlen(s); g_return_val_if_fail (n + slen + 1 <= len, -1); memcpy (buffer, s, slen + 1); /* include the 0 */ buffer += slen + 1; n += slen + 1; } mult = 0; break; } case 'S': { gchar* s; s = va_arg (args, gchar*); g_return_val_if_fail (s, -1); if (!mult) { guint slen; slen = strlen(s); g_return_val_if_fail (n + slen <= len, -1); memcpy (buffer, s, slen); /* don't include the 0 */ buffer += slen; n += slen; } else { guint i; g_return_val_if_fail (n + mult <= len, -1); for (i = 0; i < mult && s[i]; ++i) *buffer++ = s[i]; for (; i < mult; ++i) *buffer++ = 0; n += mult; } mult = 0; break; } case 'r': { for (mult=(mult?mult:1); mult; --mult) { gchar* s; guint ln; s = va_arg (args, gchar*); ln = va_arg (args, guint); g_return_val_if_fail (s, -1); g_return_val_if_fail (n + ln <= len, -1); memcpy(buffer, s, ln); buffer += ln; n += ln; } mult = 0; break; } case 'R': { gchar* s; s = va_arg (args, gchar*); g_return_val_if_fail (s, -1); g_return_val_if_fail (mult, -1); g_return_val_if_fail (n + mult <= len, -1); memcpy (buffer, s, mult); buffer += mult; n += mult; mult = 0; break; } case 'p': { for (mult=(mult?mult:1); mult; --mult) { gchar* s; guint slen; s = va_arg (args, char*); g_return_val_if_fail (s, -1); slen = strlen(s); g_return_val_if_fail (n < 256, -1); g_return_val_if_fail (n + slen + 1 <= len, -1); *buffer++ = slen; memcpy (buffer, s, slen); buffer += slen; n += slen + 1; } mult = 0; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { mult *= 10; mult += (*p - '0'); break; } case ' ': case '\t': case '\n': break; default: g_return_val_if_fail (FALSE, -1); } } return n;}/* **************************************** */#define UNPACK(TYPE) \ do { \ for (mult=(mult?mult:1); mult; --mult) \ { \ TYPE* t; \ g_return_val_if_fail (n + sizeof(TYPE) <= len, FALSE); \ t = va_arg (args, TYPE*); \ MEMCPY((char*) t, buffer, sizeof(TYPE)); \ buffer += sizeof(TYPE); \ n += sizeof(TYPE); \ } \ mult = 0; \ } while(0)#define UNPACK2(TYPENATIVE, TYPESTD) \ do { \ for (mult=(mult?mult:1); mult; --mult) \ { \ if (sizemode == 0) \ { \ TYPENATIVE* t; \ g_return_val_if_fail (n + sizeof(TYPENATIVE) <= len, -1); \ t = va_arg (args, TYPENATIVE*); \ MEMCPY((char*) t, buffer, sizeof(TYPENATIVE)); \ buffer += sizeof(TYPENATIVE); \ n += sizeof(TYPENATIVE); \ } \ else if (sizemode == 1) \ { \ TYPESTD* t; \ g_return_val_if_fail (n + sizeof(TYPESTD) <= len, -1); \ t = va_arg (args, TYPESTD*); \ LEMEMCPY((char*) t, buffer, sizeof(TYPESTD)); \ buffer += sizeof(TYPESTD); \ n += sizeof(TYPESTD); \ } \ else if (sizemode == 2) \ { \ TYPESTD* t; \ g_return_val_if_fail (n + sizeof(TYPESTD) <= len, -1); \ t = va_arg (args, TYPESTD*); \ BEMEMCPY((char*) t, buffer, sizeof(TYPESTD)); \ buffer += sizeof(TYPESTD); \ n += sizeof(TYPESTD); \ } \ } \ mult = 0; \ } while(0)/* **************************************** *//** * gnet_unpack: * @format: Unpack format * @buffer: Buffer to unpack from * @len: Length of buffer * @Varargs: Addresses of variables to unpack to * * The unpack format string is a list of types. Each type is * represented by a character. Most types can be prefixed by an * integer, which represents how many times it is repeated (eg, * "4i2b" is equivalent to "iiiibb". * * In unpack, the arguments must be pointers to the appropriate type. * Strings and byte arrays are allocated dynamicly (by g_new). The * caller is responsible for g_free()-ing it. * * Native size/order is the default. If the first character of * FORMAT is < then little endian order and standard size are used. * If the first character is > or !, then big endian (or network) * order and standard size are used. Standard sizes are 1 byte for * chars, 2 bytes for shorts, and 4 bytes for ints and longs. * * x is a pad byte. The byte is skipped and not stored. We do not * check its value. * * b/B are signed/unsigned chars * * h/H are signed/unsigned shorts (h is from sHort) * * i/I are signed/unsigned ints * * l/L are signed/unsigned longs * * f/D are floats/doubles (always native order/size) * * v is a void pointer (always native size) * * s is a zero-terminated string. REPEAT is repeat. * * S is a zero-padded string of length REPEAT. We read REPEAT * characters or until a NULL character. Any remaining characters are * filled in with 0's. REPEAT must be specified. * * r is a byte array of NEXT bytes. NEXT is the next argument and is * an integer. REPEAT is repeat. (r is from "raw") * * R is a byte array of REPEAT bytes. REPEAT must be specified. * * String/byte array memory is allocated by unpack. * * Mnemonics: sHort, Integer, Float, Double, Pointer, String, Raw * * unpack was mostly inspired by Python's unpack, with some awareness * of Perl's unpack. * * Returns: bytes unpacked; -1 if error. * **/gint gnet_unpack (const gchar* format, gchar* buffer, guint len, ...){ va_list args; gint rv; va_start (args, len); rv = gnet_vunpack (format, buffer, len, args); va_end (args); return rv;}/** * gnet_vunpack: * @format: Unpack format (see below) * @buffer: Buffer to unpack from * @len: Length of buffer * @args: var args * * Var arg interface to gnet_unpack(). See gnet_unpack() for format * information. * * Returns: bytes packed; -1 if error. * **/gint gnet_vunpack (const gchar* format, gchar* buffer, guint len, va_list args){ guint n = 0; gchar* p = (gchar*) format; guint mult = 0; gint sizemode = 0; /* 1 = little, 2 = big */ g_return_val_if_fail (format, -1); g_return_val_if_fail (buffer, -1); switch (*p) { case '@': ++p; break; case '<': sizemode = 1; ++p; break; case '>': case '!': sizemode = 2; ++p; break; } for (; *p; ++p) { switch (*p) { case 'x': { mult = mult? mult:1; g_return_val_if_fail (n + mult <= len, FALSE); buffer += mult; n += mult; mult = 0; break; } case 'b': { UNPACK(gint8); break; } case 'B': { UNPACK(guint8); break; } case 'h': { UNPACK2(short, gint16); break; } case 'H': { UNPACK2(unsigned short, guint16); break; } case 'i': { UNPACK2(int, gint32); break; } case 'I': { UNPACK2(unsigned int, guint32); break; } case 'l': { UNPACK2(long, gint32); break; } case 'L': { UNPACK2(unsigned long, guint32); break; } case 'f': { UNPACK(float); break; } case 'd': { UNPACK(double); break; } case 'v': { UNPACK2(void*, void*); break; } case 's': { for (mult=(mult?mult:1); mult; --mult) { gchar** sp; guint slen; sp = va_arg (args, gchar**); g_return_val_if_fail (sp, -1); slen = strlenn(buffer, len - n); g_return_val_if_fail (n + slen <= len, FALSE); *sp = g_new(gchar, slen + 1); memcpy (*sp, buffer, slen); (*sp)[slen] = 0; buffer += slen + 1; n += slen + 1; } mult = 0; break; } case 'S': { gchar** sp; guint slen; g_return_val_if_fail (mult, -1); sp = va_arg (args, gchar**); g_return_val_if_fail (sp, -1); slen = MIN(mult, strlenn(buffer, len - n)); g_return_val_if_fail (n + slen <= len, -1); *sp = g_new(gchar, mult + 1); memcpy (*sp, buffer, slen); while (slen < mult + 1) (*sp)[slen++] = 0; buffer += mult; n += mult; mult = 0; break; } case 'r': /* r is the same as s, in this case. */ { for (mult=(mult?mult:1); mult; --mult) { gchar** sp; guint ln; sp = va_arg (args, gchar**); ln = va_arg (args, guint); g_return_val_if_fail (sp, -1); g_return_val_if_fail (n + ln <= len, FALSE); *sp = g_new(char, ln); memcpy(*sp, buffer, ln); buffer += ln; n += ln; } mult = 0; break; } case 'R': { gchar** sp; sp = va_arg (args, gchar**); g_return_val_if_fail (sp, -1); g_return_val_if_fail (mult, -1); g_return_val_if_fail (n + mult <= len, -1); *sp = g_new(char, mult); memcpy(*sp, buffer, mult); buffer += mult; n += mult; mult = 0; break; } case 'p': { for (mult=(mult?mult:1); mult; --mult) { gchar** sp; guint slen; sp = va_arg (args, gchar**); g_return_val_if_fail (sp, -1); g_return_val_if_fail (n + 1 <= len, FALSE); slen = *buffer++; ++n; g_return_val_if_fail (n + slen <= len, FALSE); *sp = g_new(gchar, slen + 1); memcpy (*sp, buffer, slen); (*sp)[slen] = 0; buffer += slen; n += slen; } mult = 0; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { mult *= 10; mult += (*p - '0'); break; } case ' ': case '\t': case '\n': break; default: g_return_val_if_fail (FALSE, -1); } } return n;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?