(linenum→info "unix/slp.c:2238")

dbus/1.0.2/dbus/dbus-marshal-basic.c

    1: /* -*- mode: C; c-file-style: "gnu" -*- */
    2: /* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
    3:  *
    4:  * Copyright (C) 2002 CodeFactory AB
    5:  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
    6:  *
    7:  * Licensed under the Academic Free License version 2.1
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 2 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  *
   19:  * You should have received a copy of the GNU General Public License
   20:  * along with this program; if not, write to the Free Software
   21:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22:  *
   23:  */
   24: 
   25: #include "dbus-internals.h"
   26: #include "dbus-marshal-basic.h"
   27: #include "dbus-signature.h"
   28: 
   29: #include <string.h>
   30: 
   31: /**
   32:  * @defgroup DBusMarshal marshaling and unmarshaling
   33:  * @ingroup  DBusInternals
   34:  * @brief functions to marshal/unmarshal data from the wire
   35:  *
   36:  * Types and functions related to converting primitive data types from
   37:  * wire format to native machine format, and vice versa.
   38:  *
   39:  * A signature is just a string with multiple types one after the other.
   40:  * for example a type is "i" or "(ii)", a signature is "i(ii)"
   41:  * where i is int and (ii) is struct { int; int; }
   42:  *
   43:  * @{
   44:  */
   45: 
   46: static void
   47: pack_2_octets (dbus_uint16_t   value,
   48:                int             byte_order,
   49:                unsigned char  *data)
   50: {
   51:   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
   52: 
   53:   if ((byte_order) == DBUS_LITTLE_ENDIAN)
   54:     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
   55:   else
   56:     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
   57: }
   58: 
   59: static void
   60: pack_4_octets (dbus_uint32_t   value,
   61:                int             byte_order,
   62:                unsigned char  *data)
   63: {
   64:   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
   65: 
   66:   if ((byte_order) == DBUS_LITTLE_ENDIAN)
   67:     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
   68:   else
   69:     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
   70: }
   71: 
   72: static void
   73: pack_8_octets (DBusBasicValue     value,
   74:                int                byte_order,
   75:                unsigned char     *data)
   76: {
   77:   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
   78: 
   79: #ifdef DBUS_HAVE_INT64
   80:   if ((byte_order) == DBUS_LITTLE_ENDIAN)
   81:     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
   82:   else
   83:     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
   84: #else
   85:   *(DBus8ByteStruct*)data = value.u64;
   86:   swap_8_octets ((DBusBasicValue*)data, byte_order);
   87: #endif
   88: }
   89: 
   90: /**
   91:  * Packs a 32 bit unsigned integer into a data pointer.
   92:  *
   93:  * @param value the value
   94:  * @param byte_order the byte order to use
   95:  * @param data the data pointer
   96:  */
   97: void
   98: _dbus_pack_uint32 (dbus_uint32_t   value,
   99:                    int             byte_order,
  100:                    unsigned char  *data)
  101: {
  102:   pack_4_octets (value, byte_order, data);
  103: }
  104: 
  105: #ifndef DBUS_HAVE_INT64
  106: /* from ORBit */
  107: static void
  108: swap_bytes (unsigned char *data,
  109:             unsigned int   len)
  110: {
  111:   unsigned char *p1 = data;
  112:   unsigned char *p2 = data + len - 1;
  113: 
  114:   while (p1 < p2)
  115:     {
  116:       unsigned char tmp = *p1;
  117:       *p1 = *p2;
  118:       *p2 = tmp;
  119: 
  120:       --p2;
  121:       ++p1;
  122:     }
  123: }
  124: #endif /* !DBUS_HAVE_INT64 */
  125: 
  126: static void
  127: swap_8_octets (DBusBasicValue    *value,
  128:                int                byte_order)
  129: {
  130:   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
  131:     {
  132: #ifdef DBUS_HAVE_INT64
  133:       value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
  134: #else
  135:       swap_bytes ((unsigned char *)value, 8);
  136: #endif
  137:     }
  138: }
  139: 
  140: #if 0
  141: static DBusBasicValue
  142: unpack_8_octets (int                  byte_order,
  143:                  const unsigned char *data)
  144: {
  145:   DBusBasicValue r;
  146: 
  147:   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
  148:   _dbus_assert (sizeof (r) == 8);
  149: 
  150: #ifdef DBUS_HAVE_INT64
  151:   if (byte_order == DBUS_LITTLE_ENDIAN)
  152:     r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
  153:   else
  154:     r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
  155: #else
  156:   r.u64 = *(DBus8ByteStruct*)data;
  157:   swap_8_octets (&r, byte_order);
  158: #endif
  159: 
  160:   return r;
  161: }
  162: #endif
  163: 
  164: #ifndef _dbus_unpack_uint16
  165: /**
  166:  * Unpacks a 16 bit unsigned integer from a data pointer
  167:  *
  168:  * @param byte_order The byte order to use
  169:  * @param data the data pointer
  170:  * @returns the integer
  171:  */
  172: dbus_uint16_t
  173: _dbus_unpack_uint16 (int                  byte_order,
  174:                      const unsigned char *data)
  175: {
  176:   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
  177: 
  178:   if (byte_order == DBUS_LITTLE_ENDIAN)
  179:     return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
  180:   else
  181:     return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
  182: }
  183: #endif /* _dbus_unpack_uint16 */
  184: 
  185: #ifndef _dbus_unpack_uint32
  186: /**
  187:  * Unpacks a 32 bit unsigned integer from a data pointer
  188:  *
  189:  * @param byte_order The byte order to use
  190:  * @param data the data pointer
  191:  * @returns the integer
  192:  */
  193: dbus_uint32_t
  194: _dbus_unpack_uint32 (int                  byte_order,
  195:                      const unsigned char *data)
  196: {
  197:   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
  198: 
  199:   if (byte_order == DBUS_LITTLE_ENDIAN)
  200:     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
  201:   else
  202:     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
  203: }
  204: #endif /* _dbus_unpack_uint32 */
  205: 
  206: static void
  207: set_2_octets (DBusString          *str,
  208:               int                  offset,
  209:               dbus_uint16_t        value,
  210:               int                  byte_order)
  211: {
  212:   char *data;
  213: 
  214:   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
  215:                 byte_order == DBUS_BIG_ENDIAN);
  216: 
  217:   data = _dbus_string_get_data_len (str, offset, 2);
  218: 
  219:   pack_2_octets (value, byte_order, data);
  220: }
  221: 
  222: static void
  223: set_4_octets (DBusString          *str,
  224:               int                  offset,
  225:               dbus_uint32_t        value,
  226:               int                  byte_order)
  227: {
  228:   char *data;
  229: 
  230:   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
  231:                 byte_order == DBUS_BIG_ENDIAN);
  232: 
  233:   data = _dbus_string_get_data_len (str, offset, 4);
  234: 
  235:   pack_4_octets (value, byte_order, data);
  236: }
  237: 
  238: static void
  239: set_8_octets (DBusString          *str,
  240:               int                  offset,
  241:               DBusBasicValue       value,
  242:               int                  byte_order)
  243: {
  244:   char *data;
  245: 
  246:   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
  247:                 byte_order == DBUS_BIG_ENDIAN);
  248: 
  249:   data = _dbus_string_get_data_len (str, offset, 8);
  250: 
  251:   pack_8_octets (value, byte_order, data);
  252: }
  253: 
  254: /**
  255:  * Sets the 4 bytes at the given offset to a marshaled unsigned
  256:  * integer, replacing anything found there previously.
  257:  *
  258:  * @param str the string to write the marshalled int to
  259:  * @param pos the byte offset where int should be written
  260:  * @param value the value
  261:  * @param byte_order the byte order to use
  262:  *
  263:  */
  264: void
  265: _dbus_marshal_set_uint32 (DBusString          *str,
  266:                           int                  pos,
  267:                           dbus_uint32_t        value,
  268:                           int                  byte_order)
  269: {
  270:   set_4_octets (str, pos, value, byte_order);
  271: }
  272: 
  273: /**
  274:  * Sets the existing marshaled string at the given offset with
  275:  * a new marshaled string. The given offset must point to
  276:  * an existing string or the wrong length will be deleted
  277:  * and replaced with the new string.
  278:  *
  279:  * Note: no attempt is made by this function to re-align
  280:  * any data which has been already marshalled after this
  281:  * string. Use with caution.
  282:  *
  283:  * @param str the string to write the marshalled string to
  284:  * @param pos the position of the marshaled string length
  285:  * @param value the value
  286:  * @param byte_order the byte order to use
  287:  * @param old_end_pos place to store byte after the nul byte of the old value
  288:  * @param new_end_pos place to store byte after the nul byte of the new value
  289:  * @returns #TRUE on success, #FALSE if no memory
  290:  *
  291:  */
  292: static dbus_bool_t
  293: set_string (DBusString          *str,
  294:             int                  pos,
  295:             const char          *value,
  296:             int                  byte_order,
  297:             int                 *old_end_pos,
  298:             int                 *new_end_pos)
  299: {
  300:   int old_len, new_len;
  301:   DBusString dstr;
  302: 
  303:   _dbus_string_init_const (&dstr, value);
  304: 
  305:   _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
  306:   old_len = _dbus_unpack_uint32 (byte_order,
  307:                                  _dbus_string_get_const_data_len (str, pos, 4));
  308: 
  309:   new_len = _dbus_string_get_length (&dstr);
  310: 
  311:   if (!_dbus_string_replace_len (&dstr, 0, new_len,
  312:                                  str, pos + 4, old_len))
  313:     return FALSE;
  314: 
  315:   _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
  316: 
  317:   if (old_end_pos)
  318:     *old_end_pos = pos + 4 + old_len + 1;
  319:   if (new_end_pos)
  320:     *new_end_pos = pos + 4 + new_len + 1;
  321: 
  322:   return TRUE;
  323: }
  324: 
  325: /**
  326:  * Sets the existing marshaled signature at the given offset to a new
  327:  * marshaled signature. Same basic ideas as set_string().
  328:  *
  329:  * @param str the string to write the marshalled signature to
  330:  * @param pos the position of the marshaled signature length
  331:  * @param value the value
  332:  * @param byte_order the byte order to use
  333:  * @param old_end_pos place to store byte after the nul byte of the old value
  334:  * @param new_end_pos place to store byte after the nul byte of the new value
  335:  * @returns #TRUE on success, #FALSE if no memory
  336:  *
  337:  */
  338: static dbus_bool_t
  339: set_signature (DBusString          *str,
  340:                int                  pos,
  341:                const char          *value,
  342:                int                  byte_order,
  343:                int                 *old_end_pos,
  344:                int                 *new_end_pos)
  345: {
  346:   int old_len, new_len;
  347:   DBusString dstr;
  348: 
  349:   _dbus_string_init_const (&dstr, value);
  350: 
  351:   old_len = _dbus_string_get_byte (str, pos);
  352:   new_len = _dbus_string_get_length (&dstr);
  353: 
  354:   if (!_dbus_string_replace_len (&dstr, 0, new_len,
  355:                                  str, pos + 1, old_len))
  356:     return FALSE;
  357: 
  358:   _dbus_string_set_byte (str, pos, new_len);
  359: 
  360:   if (old_end_pos)
  361:     *old_end_pos = pos + 1 + old_len + 1;
  362:   if (new_end_pos)
  363:     *new_end_pos = pos + 1 + new_len + 1;
  364: 
  365:   return TRUE;
  366: }
  367: 
  368: /**
  369:  * Sets an existing basic type value to a new value.
  370:  * Arguments work the same way as _dbus_marshal_basic_type().
  371:  *
  372:  * @param str the string
  373:  * @param pos location of the current value
  374:  * @param type the type of the current and new values
  375:  * @param value the address of the new value
  376:  * @param byte_order byte order for marshaling
  377:  * @param old_end_pos location to store end position of the old value, or #NULL
  378:  * @param new_end_pos location to store end position of the new value, or #NULL
  379:  * @returns #FALSE if no memory
  380:  */
  381: dbus_bool_t
  382: _dbus_marshal_set_basic (DBusString       *str,
  383:                          int               pos,
  384:                          int               type,
  385:                          const void       *value,
  386:                          int               byte_order,
  387:                          int              *old_end_pos,
  388:                          int              *new_end_pos)
  389: {
  390:   const DBusBasicValue *vp;
  391: 
  392:   vp = value;
  393: 
  394:   switch (type)
  395:     {
  396:     case DBUS_TYPE_BYTE:
  397:       _dbus_string_set_byte (str, pos, vp->byt);
  398:       if (old_end_pos)
  399:         *old_end_pos = pos + 1;
  400:       if (new_end_pos)
  401:         *new_end_pos = pos + 1;
  402:       return TRUE;
  403:       break;
  404:     case DBUS_TYPE_INT16:
  405:     case DBUS_TYPE_UINT16:
  406:       pos = _DBUS_ALIGN_VALUE (pos, 2);
  407:       set_2_octets (str, pos, vp->u16, byte_order);
  408:       if (old_end_pos)
  409:         *old_end_pos = pos + 2;
  410:       if (new_end_pos)
  411:         *new_end_pos = pos + 2;
  412:       return TRUE;
  413:       break;
  414:     case DBUS_TYPE_BOOLEAN:
  415:     case DBUS_TYPE_INT32:
  416:     case DBUS_TYPE_UINT32:
  417:       pos = _DBUS_ALIGN_VALUE (pos, 4);
  418:       set_4_octets (str, pos, vp->u32, byte_order);
  419:       if (old_end_pos)
  420:         *old_end_pos = pos + 4;
  421:       if (new_end_pos)
  422:         *new_end_pos = pos + 4;
  423:       return TRUE;
  424:       break;
  425:     case DBUS_TYPE_INT64:
  426:     case DBUS_TYPE_UINT64:
  427:     case DBUS_TYPE_DOUBLE:
  428:       pos = _DBUS_ALIGN_VALUE (pos, 8);
  429:       set_8_octets (str, pos, *vp, byte_order);
  430:       if (old_end_pos)
  431:         *old_end_pos = pos + 8;
  432:       if (new_end_pos)
  433:         *new_end_pos = pos + 8;
  434:       return TRUE;
  435:       break;
  436:     case DBUS_TYPE_STRING:
  437:     case DBUS_TYPE_OBJECT_PATH:
  438:       pos = _DBUS_ALIGN_VALUE (pos, 4);
  439:       _dbus_assert (vp->str != NULL);
  440:       return set_string (str, pos, vp->str, byte_order,
  441:                          old_end_pos, new_end_pos);
  442:       break;
  443:     case DBUS_TYPE_SIGNATURE:
  444:       _dbus_assert (vp->str != NULL);
  445:       return set_signature (str, pos, vp->str, byte_order,
  446:                             old_end_pos, new_end_pos);
  447:       break;
  448:     default:
  449:       _dbus_assert_not_reached ("not a basic type");
  450:       return FALSE;
  451:       break;
  452:     }
  453: }
  454: 
  455: /**
  456:  * Convenience function to demarshal a 32 bit unsigned integer.
  457:  *
  458:  * @param str the string containing the data
  459:  * @param byte_order the byte order
  460:  * @param pos the position in the string
  461:  * @param new_pos the new position of the string
  462:  * @returns the demarshaled integer.
  463:  */
  464: dbus_uint32_t
  465: _dbus_marshal_read_uint32  (const DBusString *str,
  466:                             int               pos,
  467:                             int               byte_order,
  468:                             int              *new_pos)
  469: {
  470:   pos = _DBUS_ALIGN_VALUE (pos, 4);
  471: 
  472:   if (new_pos)
  473:     *new_pos = pos + 4;
  474: 
  475:   _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
  476:   
  477:   return _dbus_unpack_uint32 (byte_order,
  478:                               _dbus_string_get_const_data (str) + pos);
  479: }
  480: 
  481: /**
  482:  * Demarshals a basic-typed value. The "value" pointer is always
  483:  * the address of a variable of the basic type. So e.g.
  484:  * if the basic type is "double" then the pointer is
  485:  * a double*, and if it's "char*" then the pointer is
  486:  * a "char**".
  487:  *
  488:  * A value of type #DBusBasicValue is guaranteed to be large enough to
  489:  * hold any of the types that may be returned, which is handy if you
  490:  * are trying to do things generically. For example you can pass
  491:  * a DBusBasicValue* in to this function, and then pass the same
  492:  * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
  493:  * move a value from one place to another.
  494:  *
  495:  * @param str the string containing the data
  496:  * @param pos position in the string
  497:  * @param type type of value to demarshal
  498:  * @param value pointer to return value data
  499:  * @param byte_order the byte order
  500:  * @param new_pos pointer to update with new position, or #NULL
  501:  **/
  502: void
  503: _dbus_marshal_read_basic (const DBusString      *str,
  504:                           int                    pos,
  505:                           int                    type,
  506:                           void                  *value,
  507:                           int                    byte_order,
  508:                           int                   *new_pos)
  509: {
  510:   const char *str_data;
  511:   DBusBasicValue *vp;
  512: 
  513:   _dbus_assert (dbus_type_is_basic (type));
  514: 
  515:   str_data = _dbus_string_get_const_data (str);
  516:   vp = value;
  517: 
  518:   switch (type)
  519:     {
  520:     case DBUS_TYPE_BYTE:
  521:       vp->byt = _dbus_string_get_byte (str, pos);
  522:       (pos)++;
  523:       break;
  524:     case DBUS_TYPE_INT16:
  525:     case DBUS_TYPE_UINT16:
  526:       pos = _DBUS_ALIGN_VALUE (pos, 2);
  527:       vp->u16 = *(dbus_uint16_t *)(str_data + pos);
  528:       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
  529:         vp->u16 = DBUS_UINT16_SWAP_LE_BE (vp->u16);
  530:       pos += 2;
  531:       break;
  532:     case DBUS_TYPE_INT32:
  533:     case DBUS_TYPE_UINT32:
  534:     case DBUS_TYPE_BOOLEAN:
  535:       pos = _DBUS_ALIGN_VALUE (pos, 4);
  536:       vp->u32 = *(dbus_uint32_t *)(str_data + pos);
  537:       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
  538:         vp->u32 = DBUS_UINT32_SWAP_LE_BE (vp->u32);
  539:       pos += 4;
  540:       break;
  541:     case DBUS_TYPE_INT64:
  542:     case DBUS_TYPE_UINT64:
  543:     case DBUS_TYPE_DOUBLE:
  544:       pos = _DBUS_ALIGN_VALUE (pos, 8);
  545: #ifdef DBUS_HAVE_INT64
  546:       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
  547:         vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
  548:       else
  549:         vp->u64 = *(dbus_uint64_t*)(str_data + pos);
  550: #else
  551:       vp->u64 = *(DBus8ByteStruct*) (str_data + pos);
  552:       swap_8_octets (vp, byte_order);
  553: #endif
  554:       pos += 8;
  555:       break;
  556:     case DBUS_TYPE_STRING:
  557:     case DBUS_TYPE_OBJECT_PATH:
  558:       {
  559:         int len;
  560: 
  561:         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
  562: 
  563:         vp->str = (char*) str_data + pos;
  564: 
  565:         pos += len + 1; /* length plus nul */
  566:       }
  567:       break;
  568:     case DBUS_TYPE_SIGNATURE:
  569:       {
  570:         int len;
  571: 
  572:         len = _dbus_string_get_byte (str, pos);
  573:         pos += 1;
  574: 
  575:         vp->str = (char*) str_data + pos;
  576: 
  577:         pos += len + 1; /* length plus nul */
  578:       }
  579:       break;
  580:     default:
  581:       _dbus_warn_check_failed ("type %s %d not a basic type\n",
  582: