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 + -
显示快捷键?