libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

convert.c (7278B)


      1 /* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include "ixp_local.h"
      8 
      9 int _IXP_ASSERT_VERSION;
     10 
     11 enum {
     12 	SByte = 1,
     13 	SWord = 2,
     14 	SDWord = 4,
     15 	SQWord = 8,
     16 };
     17 
     18 static void
     19 ixp_puint(IxpMsg *msg, uint size, uint32_t *val) {
     20 	uint8_t *pos;
     21 	int v;
     22 
     23 	if(msg->pos + size <= msg->end) {
     24 		pos = (uint8_t*)msg->pos;
     25 		switch(msg->mode) {
     26 		case MsgPack:
     27 			v = *val;
     28 			switch(size) {
     29 			case SDWord:
     30 				pos[3] = v>>24;
     31 				pos[2] = v>>16;
     32 			case SWord:
     33 				pos[1] = v>>8;
     34 			case SByte:
     35 				pos[0] = v;
     36 				break;
     37 			}
     38 		case MsgUnpack:
     39 			v = 0;
     40 			switch(size) {
     41 			case SDWord:
     42 				v |= pos[3]<<24;
     43 				v |= pos[2]<<16;
     44 			case SWord:
     45 				v |= pos[1]<<8;
     46 			case SByte:
     47 				v |= pos[0];
     48 				break;
     49 			}
     50 			*val = v;
     51 		}
     52 	}
     53 	msg->pos += size;
     54 }
     55 
     56 /**
     57  * Function: ixp_pu8
     58  * Function: ixp_pu16
     59  * Function: ixp_pu32
     60  * Function: ixp_pu64
     61  *
     62  * These functions pack or unpack an unsigned integer of the
     63  * specified size.
     64  *
     65  * If P<msg>->mode is MsgPack, the value pointed to by P<val> is
     66  * packed into the buffer at P<msg>->pos. If P<msg>->mode is
     67  * MsgUnpack, the packed value at P<msg>->pos is loaded into the
     68  * location pointed to by P<val>. In both cases, P<msg>->pos is
     69  * advanced by the number of bytes read or written. If the call
     70  * would advance P<msg>->pos beyond P<msg>->end, P<msg>->pos is
     71  * advanced, but nothing is modified.
     72  *
     73  * See also:
     74  *	T<IxpMsg>
     75  */
     76 void
     77 ixp_pu8(IxpMsg *msg, uint8_t *val) {
     78 	uint32_t v;
     79 
     80 	v = *val;
     81 	ixp_puint(msg, SByte, &v);
     82 	*val = (uint8_t)v;
     83 }
     84 void
     85 ixp_pu16(IxpMsg *msg, uint16_t *val) {
     86 	uint32_t v;
     87 
     88 	v = *val;
     89 	ixp_puint(msg, SWord, &v);
     90 	*val = (uint16_t)v;
     91 }
     92 void
     93 ixp_pu32(IxpMsg *msg, uint32_t *val) {
     94 	ixp_puint(msg, SDWord, val);
     95 }
     96 void
     97 ixp_pu64(IxpMsg *msg, uint64_t *val) {
     98 	uint32_t vl, vb;
     99 
    100 	vl = (uint)*val;
    101 	vb = (uint)(*val>>32);
    102 	ixp_puint(msg, SDWord, &vl);
    103 	ixp_puint(msg, SDWord, &vb);
    104 	*val = vl | ((uint64_t)vb<<32);
    105 }
    106 
    107 /**
    108  * Function: ixp_pstring
    109  *
    110  * Packs or unpacks a UTF-8 encoded string. The packed
    111  * representation of the string consists of a 16-bit unsigned
    112  * integer followed by the contents of the string. The unpacked
    113  * representation is a nul-terminated character array.
    114  *
    115  * If P<msg>->mode is MsgPack, the string pointed to by P<s> is
    116  * packed into the buffer at P<msg>->pos. If P<msg>->mode is
    117  * MsgUnpack, the address pointed to by P<s> is loaded with a
    118  * malloc(3) allocated, nul-terminated representation of the
    119  * string packed at P<msg>->pos. In either case, P<msg>->pos is
    120  * advanced by the number of bytes read or written. If the
    121  * action would advance P<msg>->pos beyond P<msg>->end,
    122  * P<msg>->pos is still advanced but no other action is taken.
    123  *
    124  * See also:
    125  *	T<IxpMsg>, F<ixp_pstrings>, F<ixp_pdata>
    126  */
    127 void
    128 ixp_pstring(IxpMsg *msg, char **s) {
    129 	uint16_t len;
    130 
    131 	if(msg->mode == MsgPack)
    132 		len = strlen(*s);
    133 	ixp_pu16(msg, &len);
    134 
    135 	if(msg->pos + len <= msg->end) {
    136 		if(msg->mode == MsgUnpack) {
    137 			*s = emalloc(len + 1);
    138 			memcpy(*s, msg->pos, len);
    139 			(*s)[len] = '\0';
    140 		}else
    141 			memcpy(msg->pos, *s, len);
    142 	}
    143 	msg->pos += len;
    144 }
    145 
    146 /**
    147  * Function: ixp_pstrings
    148  *
    149  * Packs or unpacks an array of UTF-8 encoded strings. The packed
    150  * representation consists of a 16-bit element count followed by
    151  * an array of strings as packed by F<ixp_pstring>. The unpacked
    152  * representation is an array of nul-terminated character arrays.
    153  *
    154  * If P<msg>->mode is MsgPack, P<*num> strings in the array
    155  * pointed to by P<strings> are packed into the buffer at
    156  * P<msg>->pos. If P<msg>->mode is MsgUnpack, P<*num> is loaded
    157  * with the number of strings unpacked, the array at
    158  * P<*strings> is loaded with pointers to the unpacked strings,
    159  * and P<(*strings)[0]> must be freed by the user. In either
    160  * case, P<msg>->pos is advanced by the number of bytes read or
    161  * written. If the action would advance P<msg>->pos beyond
    162  * P<msg>->end, P<msg>->pos is still advanced, but no other
    163  * action is taken. If P<*num> is greater than P<max>,
    164  * P<msg>->pos is set beyond P<msg>->end and no other action is
    165  * taken.
    166  * 
    167  * See also:
    168  *	P<IxpMsg>, P<ixp_pstring>, P<ixp_pdata>
    169  */
    170 void
    171 ixp_pstrings(IxpMsg *msg, uint16_t *num, char *strings[], uint max) {
    172 	char *s;
    173 	uint i, size;
    174 	uint16_t len;
    175 
    176 	ixp_pu16(msg, num);
    177 	if(*num > max) {
    178 		msg->pos = msg->end+1;
    179 		return;
    180 	}
    181 
    182 	SET(s);
    183 	if(msg->mode == MsgUnpack) {
    184 		s = msg->pos;
    185 		size = 0;
    186 		for(i=0; i < *num; i++) {
    187 			ixp_pu16(msg, &len);
    188 			msg->pos += len;
    189 			size += len;
    190 			if(msg->pos > msg->end)
    191 				return;
    192 		}
    193 		msg->pos = s;
    194 		size += *num;
    195 		s = emalloc(size);
    196 	}
    197 
    198 	for(i=0; i < *num; i++) {
    199 		if(msg->mode == MsgPack)
    200 			len = strlen(strings[i]);
    201 		ixp_pu16(msg, &len);
    202 
    203 		if(msg->mode == MsgUnpack) {
    204 			memcpy(s, msg->pos, len);
    205 			strings[i] = (char*)s;
    206 			s += len;
    207 			msg->pos += len;
    208 			*s++ = '\0';
    209 		}else
    210 			ixp_pdata(msg, &strings[i], len);
    211 	}
    212 }
    213 
    214 /**
    215  * Function: ixp_pdata
    216  *
    217  * Packs or unpacks a raw character buffer of size P<len>.
    218  *
    219  * If P<msg>->mode is MsgPack, buffer pointed to by P<data> is
    220  * packed into the buffer at P<msg>->pos. If P<msg>->mode is
    221  * MsgUnpack, the address pointed to by P<s> is loaded with a
    222  * malloc(3) allocated buffer with the contents of the buffer at
    223  * P<msg>->pos.  In either case, P<msg>->pos is advanced by the
    224  * number of bytes read or written. If the action would advance
    225  * P<msg>->pos beyond P<msg>->end, P<msg>->pos is still advanced
    226  * but no other action is taken.
    227  *
    228  * See also:
    229  *	T<IxpMsg>, F<ixp_pstring>
    230  */
    231 void
    232 ixp_pdata(IxpMsg *msg, char **data, uint len) {
    233 	if(msg->pos + len <= msg->end) {
    234 		if(msg->mode == MsgUnpack) {
    235 			*data = emalloc(len);
    236 			memcpy(*data, msg->pos, len);
    237 		}else
    238 			memcpy(msg->pos, *data, len);
    239 		}
    240 	msg->pos += len;
    241 }
    242 
    243 /**
    244  * Function: ixp_pfcall
    245  * Function: ixp_pqid
    246  * Function: ixp_pqids
    247  * Function: ixp_pstat
    248  * Function: ixp_sizeof_stat
    249  *
    250  * These convenience functions pack or unpack the contents of
    251  * libixp structures into their wire format. They behave as if
    252  * F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>, F<ixp_pu64>, and
    253  * F<ixp_pstring> were called for each member of the structure
    254  * in question. ixp_pqid is to ixp_pqid as F<ixp_pstrings> is to
    255  * ixp_pstring.
    256  *
    257  * ixp_sizeof_stat returns the size of the packed represention
    258  * of P<stat>.
    259  *
    260  * See also:
    261  *	T<IxpMsg>, F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>,
    262  *	F<ixp_pu64>, F<ixp_pstring>, F<ixp_pstrings>
    263  */
    264 void
    265 ixp_pqid(IxpMsg *msg, IxpQid *qid) {
    266 	ixp_pu8(msg, &qid->type);
    267 	ixp_pu32(msg, &qid->version);
    268 	ixp_pu64(msg, &qid->path);
    269 }
    270 
    271 void
    272 ixp_pqids(IxpMsg *msg, uint16_t *num, IxpQid qid[], uint max) {
    273 	int i;
    274 
    275 	ixp_pu16(msg, num);
    276 	if(*num > max) {
    277 		msg->pos = msg->end+1;
    278 		return;
    279 	}
    280 
    281 	for(i = 0; i < *num; i++)
    282 		ixp_pqid(msg, &qid[i]);
    283 }
    284 
    285 void
    286 ixp_pstat(IxpMsg *msg, IxpStat *stat) {
    287 	uint16_t size;
    288 
    289 	if(msg->mode == MsgPack)
    290 		size = ixp_sizeof_stat(stat) - 2;
    291 
    292 	ixp_pu16(msg, &size);
    293 	ixp_pu16(msg, &stat->type);
    294 	ixp_pu32(msg, &stat->dev);
    295 	ixp_pqid(msg, &stat->qid);
    296 	ixp_pu32(msg, &stat->mode);
    297 	ixp_pu32(msg, &stat->atime);
    298 	ixp_pu32(msg, &stat->mtime);
    299 	ixp_pu64(msg, &stat->length);
    300 	ixp_pstring(msg, &stat->name);
    301 	ixp_pstring(msg, &stat->uid);
    302 	ixp_pstring(msg, &stat->gid);
    303 	ixp_pstring(msg, &stat->muid);
    304 }