LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-gvariant.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 117 133 88.0 %
Date: 2015-07-29 18:47:03 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include "bus-type.h"
      23             : #include "bus-gvariant.h"
      24             : #include "bus-signature.h"
      25             : 
      26       31879 : int bus_gvariant_get_size(const char *signature) {
      27             :         const char *p;
      28       31879 :         int sum = 0, r;
      29             : 
      30             :         /* For fixed size structs. Fails for variable size structs. */
      31             : 
      32       31879 :         p = signature;
      33       79855 :         while (*p != 0) {
      34             :                 size_t n;
      35             : 
      36       31932 :                 r = signature_element_length(p, &n);
      37       31932 :                 if (r < 0)
      38       15835 :                         return r;
      39       31932 :                 else {
      40       31932 :                         char t[n+1];
      41             : 
      42       31932 :                         memcpy(t, p, n);
      43       31932 :                         t[n] = 0;
      44             : 
      45       31932 :                         r = bus_gvariant_get_alignment(t);
      46       31932 :                         if (r < 0)
      47           0 :                                 return r;
      48             : 
      49       31932 :                         sum = ALIGN_TO(sum, r);
      50             :                 }
      51             : 
      52       31932 :                 switch (*p) {
      53             : 
      54             :                 case SD_BUS_TYPE_BOOLEAN:
      55             :                 case SD_BUS_TYPE_BYTE:
      56       15838 :                         sum += 1;
      57       15838 :                         break;
      58             : 
      59             :                 case SD_BUS_TYPE_INT16:
      60             :                 case SD_BUS_TYPE_UINT16:
      61           2 :                         sum += 2;
      62           2 :                         break;
      63             : 
      64             :                 case SD_BUS_TYPE_INT32:
      65             :                 case SD_BUS_TYPE_UINT32:
      66             :                 case SD_BUS_TYPE_UNIX_FD:
      67         142 :                         sum += 4;
      68         142 :                         break;
      69             : 
      70             :                 case SD_BUS_TYPE_INT64:
      71             :                 case SD_BUS_TYPE_UINT64:
      72             :                 case SD_BUS_TYPE_DOUBLE:
      73          86 :                         sum += 8;
      74          86 :                         break;
      75             : 
      76             :                 case SD_BUS_TYPE_STRUCT_BEGIN:
      77             :                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
      78          91 :                         if (n == 2) {
      79             :                                 /* unary type () has fixed size of 1 */
      80           2 :                                 r = 1;
      81          89 :                         } else {
      82          89 :                                 char t[n-1];
      83             : 
      84          89 :                                 memcpy(t, p + 1, n - 2);
      85          89 :                                 t[n - 2] = 0;
      86             : 
      87          89 :                                 r = bus_gvariant_get_size(t);
      88          89 :                                 if (r < 0)
      89          62 :                                         return r;
      90             :                         }
      91             : 
      92          29 :                         sum += r;
      93          29 :                         break;
      94             :                 }
      95             : 
      96             :                 case SD_BUS_TYPE_STRING:
      97             :                 case SD_BUS_TYPE_OBJECT_PATH:
      98             :                 case SD_BUS_TYPE_SIGNATURE:
      99             :                 case SD_BUS_TYPE_ARRAY:
     100             :                 case SD_BUS_TYPE_VARIANT:
     101       15773 :                         return -EINVAL;
     102             : 
     103             :                 default:
     104           0 :                         assert_not_reached("Unknown signature type");
     105             :                 }
     106             : 
     107       16097 :                 p += n;
     108             :         }
     109             : 
     110       16044 :         r = bus_gvariant_get_alignment(signature);
     111       16044 :         if (r < 0)
     112           0 :                 return r;
     113             : 
     114       16044 :         return ALIGN_TO(sum, r);
     115             : }
     116             : 
     117       80160 : int bus_gvariant_get_alignment(const char *signature) {
     118       80160 :         size_t alignment = 1;
     119             :         const char *p;
     120             :         int r;
     121             : 
     122       80160 :         p = signature;
     123      240766 :         while (*p != 0 && alignment < 8) {
     124             :                 size_t n;
     125             :                 int a;
     126             : 
     127       80446 :                 r = signature_element_length(p, &n);
     128       80446 :                 if (r < 0)
     129           0 :                         return r;
     130             : 
     131       80446 :                 switch (*p) {
     132             : 
     133             :                 case SD_BUS_TYPE_BYTE:
     134             :                 case SD_BUS_TYPE_BOOLEAN:
     135             :                 case SD_BUS_TYPE_STRING:
     136             :                 case SD_BUS_TYPE_OBJECT_PATH:
     137             :                 case SD_BUS_TYPE_SIGNATURE:
     138       63612 :                         a = 1;
     139       63612 :                         break;
     140             : 
     141             :                 case SD_BUS_TYPE_INT16:
     142             :                 case SD_BUS_TYPE_UINT16:
     143           9 :                         a = 2;
     144           9 :                         break;
     145             : 
     146             :                 case SD_BUS_TYPE_INT32:
     147             :                 case SD_BUS_TYPE_UINT32:
     148             :                 case SD_BUS_TYPE_UNIX_FD:
     149         494 :                         a = 4;
     150         494 :                         break;
     151             : 
     152             :                 case SD_BUS_TYPE_INT64:
     153             :                 case SD_BUS_TYPE_UINT64:
     154             :                 case SD_BUS_TYPE_DOUBLE:
     155             :                 case SD_BUS_TYPE_VARIANT:
     156         473 :                         a = 8;
     157         473 :                         break;
     158             : 
     159       15583 :                 case SD_BUS_TYPE_ARRAY: {
     160       15583 :                         char t[n];
     161             : 
     162       15583 :                         memcpy(t, p + 1, n - 1);
     163       15583 :                         t[n - 1] = 0;
     164             : 
     165       15583 :                         a = bus_gvariant_get_alignment(t);
     166       15583 :                         break;
     167             :                 }
     168             : 
     169             :                 case SD_BUS_TYPE_STRUCT_BEGIN:
     170         275 :                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
     171         275 :                         char t[n-1];
     172             : 
     173         275 :                         memcpy(t, p + 1, n - 2);
     174         275 :                         t[n - 2] = 0;
     175             : 
     176         275 :                         a = bus_gvariant_get_alignment(t);
     177         275 :                         break;
     178             :                 }
     179             : 
     180             :                 default:
     181           0 :                         assert_not_reached("Unknown signature type");
     182             :                 }
     183             : 
     184       80446 :                 if (a < 0)
     185           0 :                         return a;
     186             : 
     187       80446 :                 assert(a > 0 && a <= 8);
     188       80446 :                 if ((size_t) a > alignment)
     189        1139 :                         alignment = (size_t) a;
     190             : 
     191       80446 :                 p += n;
     192             :         }
     193             : 
     194       80160 :         return alignment;
     195             : }
     196             : 
     197       31665 : int bus_gvariant_is_fixed_size(const char *signature) {
     198             :         const char *p;
     199             :         int r;
     200             : 
     201       31665 :         assert(signature);
     202             : 
     203       31665 :         p = signature;
     204       79077 :         while (*p != 0) {
     205             :                 size_t n;
     206             : 
     207       31713 :                 r = signature_element_length(p, &n);
     208       31713 :                 if (r < 0)
     209       15966 :                         return r;
     210             : 
     211       31713 :                 switch (*p) {
     212             : 
     213             :                 case SD_BUS_TYPE_STRING:
     214             :                 case SD_BUS_TYPE_OBJECT_PATH:
     215             :                 case SD_BUS_TYPE_SIGNATURE:
     216             :                 case SD_BUS_TYPE_ARRAY:
     217             :                 case SD_BUS_TYPE_VARIANT:
     218       15924 :                         return 0;
     219             : 
     220             :                 case SD_BUS_TYPE_BYTE:
     221             :                 case SD_BUS_TYPE_BOOLEAN:
     222             :                 case SD_BUS_TYPE_INT16:
     223             :                 case SD_BUS_TYPE_UINT16:
     224             :                 case SD_BUS_TYPE_INT32:
     225             :                 case SD_BUS_TYPE_UINT32:
     226             :                 case SD_BUS_TYPE_UNIX_FD:
     227             :                 case SD_BUS_TYPE_INT64:
     228             :                 case SD_BUS_TYPE_UINT64:
     229             :                 case SD_BUS_TYPE_DOUBLE:
     230       15724 :                         break;
     231             : 
     232             :                 case SD_BUS_TYPE_STRUCT_BEGIN:
     233          65 :                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
     234          65 :                         char t[n-1];
     235             : 
     236          65 :                         memcpy(t, p + 1, n - 2);
     237          65 :                         t[n - 2] = 0;
     238             : 
     239          65 :                         r = bus_gvariant_is_fixed_size(t);
     240          65 :                         if (r <= 0)
     241          42 :                                 return r;
     242          23 :                         break;
     243             :                 }
     244             : 
     245             :                 default:
     246           0 :                         assert_not_reached("Unknown signature type");
     247             :                 }
     248             : 
     249       15747 :                 p += n;
     250             :         }
     251             : 
     252       15699 :         return true;
     253             : }
     254             : 
     255       93322 : size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
     256       93322 :         if (sz + extra <= 0xFF)
     257       46866 :                 return 1;
     258       46456 :         else if (sz + extra*2 <= 0xFFFF)
     259          13 :                 return 2;
     260       46443 :         else if (sz + extra*4 <= 0xFFFFFFFF)
     261       46443 :                 return 4;
     262             :         else
     263           0 :                 return 8;
     264             : }
     265             : 
     266      139870 : size_t bus_gvariant_read_word_le(void *p, size_t sz) {
     267             :         union {
     268             :                 uint16_t u16;
     269             :                 uint32_t u32;
     270             :                 uint64_t u64;
     271             :         } x;
     272             : 
     273      139870 :         assert(p);
     274             : 
     275      139870 :         if (sz == 1)
     276      124373 :                 return *(uint8_t*) p;
     277             : 
     278       15497 :         memcpy(&x, p, sz);
     279             : 
     280       15497 :         if (sz == 2)
     281          16 :                 return le16toh(x.u16);
     282       15481 :         else if (sz == 4)
     283       15481 :                 return le32toh(x.u32);
     284           0 :         else if (sz == 8)
     285           0 :                 return le64toh(x.u64);
     286             : 
     287           0 :         assert_not_reached("unknown word width");
     288             : }
     289             : 
     290       46789 : void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
     291             :         union {
     292             :                 uint16_t u16;
     293             :                 uint32_t u32;
     294             :                 uint64_t u64;
     295             :         } x;
     296             : 
     297       46789 :         assert(p);
     298       46789 :         assert(sz == 8 || (value < (1ULL << (sz*8))));
     299             : 
     300       46789 :         if (sz == 1) {
     301       46759 :                 *(uint8_t*) p = value;
     302       46759 :                 return;
     303          30 :         } else if (sz == 2)
     304          30 :                 x.u16 = htole16((uint16_t) value);
     305           0 :         else if (sz == 4)
     306           0 :                 x.u32 = htole32((uint32_t) value);
     307           0 :         else if (sz == 8)
     308           0 :                 x.u64 = htole64((uint64_t) value);
     309             :         else
     310           0 :                 assert_not_reached("unknown word width");
     311             : 
     312          30 :         memcpy(p, &x, sz);
     313             : }

Generated by: LCOV version 1.11