LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - safe_print.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 102 15.7 %
Date: 2024-10-16 11:38:27 Functions: 2 12 16.7 %
Branches: 9 52 17.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andres Noetzli
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * Definition of print functions that are safe to use in a signal
      14                 :            :  * handler.
      15                 :            :  *
      16                 :            :  * Signal handlers only allow a very limited set of operations, e.g. dynamic
      17                 :            :  * memory allocation is not possible. This set of functions can be used to
      18                 :            :  * print information from a signal handler. All output is written to file
      19                 :            :  * descriptors using the async-signal-safe write() function.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "safe_print.h"
      23                 :            : 
      24                 :            : #include <time.h>
      25                 :            : #include <unistd.h>
      26                 :            : 
      27                 :            : #include <cstdlib>
      28                 :            : 
      29                 :            : /* Size of buffers used */
      30                 :            : #define BUFFER_SIZE 20
      31                 :            : 
      32                 :            : namespace cvc5::internal {
      33                 :            : 
      34                 :            : template <>
      35                 :         28 : void safe_print(int fd, const std::string& msg) {
      36                 :            :   // Print characters one by one instead of using
      37                 :            :   // string::data()/string::c_str() to avoid allocations (pre-c++11)
      38         [ +  + ]:        299 :   for (size_t i = 0; i < msg.length(); i++) {
      39         [ -  + ]:        271 :     if (write(fd, &(msg[i]), 1) != 1) {
      40                 :          0 :       abort();
      41                 :            :     }
      42                 :            :   }
      43                 :         28 : }
      44                 :            : 
      45                 :            : template <>
      46                 :          0 : void safe_print(int fd, const int64_t& _i) {
      47                 :            :   char buf[BUFFER_SIZE];
      48                 :          0 :   int64_t i = _i;
      49                 :            : 
      50         [ -  - ]:          0 :   if (i == 0) {
      51                 :          0 :     safe_print(fd, "0");
      52                 :          0 :     return;
      53         [ -  - ]:          0 :   } else if (i < 0) {
      54                 :          0 :     safe_print(fd, "-");
      55                 :          0 :     i *= -1;
      56                 :            :   }
      57                 :            : 
      58                 :            :   // This loop fills the buffer from the end. The number of elements in the
      59                 :            :   // buffer is BUFER_SIZE - idx - 1 and they start at position idx + 1.
      60                 :          0 :   ssize_t idx = BUFFER_SIZE - 1;
      61 [ -  - ][ -  - ]:          0 :   while (i != 0 && idx >= 0) {
      62                 :          0 :     buf[idx] = '0' + i % 10;
      63                 :          0 :     i /= 10;
      64                 :          0 :     idx--;
      65                 :            :   }
      66                 :            : 
      67                 :          0 :   ssize_t nbyte = BUFFER_SIZE - idx - 1;
      68         [ -  - ]:          0 :   if (write(fd, buf + idx + 1, nbyte) != nbyte) {
      69                 :          0 :     abort();
      70                 :            :   }
      71                 :            : }
      72                 :            : 
      73                 :            : template <>
      74                 :          0 : void safe_print(int fd, const int32_t& i) {
      75                 :          0 :   safe_print<int64_t>(fd, i);
      76                 :          0 : }
      77                 :            : 
      78                 :            : template <>
      79                 :         16 : void safe_print(int fd, const uint64_t& _i) {
      80                 :            :   char buf[BUFFER_SIZE];
      81                 :         16 :   uint64_t i = _i;
      82                 :            : 
      83         [ +  + ]:         16 :   if (i == 0) {
      84                 :         12 :     safe_print(fd, "0");
      85                 :         12 :     return;
      86                 :            :   }
      87                 :            : 
      88                 :            :   // This loop fills the buffer from the end. The number of elements in the
      89                 :            :   // buffer is BUFER_SIZE - idx - 1 and they start at position idx + 1.
      90                 :          4 :   ssize_t idx = BUFFER_SIZE - 1;
      91 [ +  + ][ +  - ]:          9 :   while (i != 0 && idx >= 0) {
      92                 :          5 :     buf[idx] = '0' + i % 10;
      93                 :          5 :     i /= 10;
      94                 :          5 :     idx--;
      95                 :            :   }
      96                 :            : 
      97                 :          4 :   ssize_t nbyte = BUFFER_SIZE - idx - 1;
      98         [ -  + ]:          4 :   if (write(fd, buf + idx + 1, nbyte) != nbyte) {
      99                 :          0 :     abort();
     100                 :            :   }
     101                 :            : }
     102                 :            : 
     103                 :            : template <>
     104                 :          0 : void safe_print(int fd, const uint32_t& i) {
     105                 :          0 :   safe_print<uint64_t>(fd, i);
     106                 :          0 : }
     107                 :            : 
     108                 :            : template <>
     109                 :          0 : void safe_print(int fd, const double& _d) {
     110                 :            :   // Note: this print function for floating-point values is optimized for
     111                 :            :   // simplicity, not correctness or performance.
     112                 :            :   char buf[BUFFER_SIZE];
     113                 :          0 :   double d = _d;
     114                 :            : 
     115                 :          0 :   ssize_t i = 0;
     116                 :          0 :   int64_t v = static_cast<int64_t>(d);
     117                 :          0 :   d -= v;
     118                 :            : 
     119         [ -  - ]:          0 :   if (d < 0.0) {
     120                 :          0 :     d *= -1.0;
     121                 :            :   }
     122                 :            : 
     123                 :          0 :   safe_print<int64_t>(fd, v);
     124                 :          0 :   safe_print(fd, ".");
     125                 :            : 
     126                 :            :   // Print decimal digits as long as the remaining value is larger than zero
     127                 :            :   // and print at least one digit.
     128 [ -  - ][ -  - ]:          0 :   while (i == 0 || (d > 0.0 && i < BUFFER_SIZE)) {
                 [ -  - ]
     129                 :          0 :     d *= 10.0;
     130                 :          0 :     char c = static_cast<char>(d);
     131                 :          0 :     buf[i] = '0' + c;
     132                 :          0 :     d -= c;
     133                 :          0 :     i++;
     134                 :            :   }
     135                 :            : 
     136         [ -  - ]:          0 :   if (write(fd, buf, i) != i) {
     137                 :          0 :     abort();
     138                 :            :   }
     139                 :          0 : }
     140                 :            : 
     141                 :            : template <>
     142                 :          0 : void safe_print(int fd, const float& f) {
     143                 :          0 :   safe_print<double>(fd, (double)f);
     144                 :          0 : }
     145                 :            : 
     146                 :            : template <>
     147                 :          0 : void safe_print(int fd, const bool& b) {
     148         [ -  - ]:          0 :   if (b) {
     149                 :          0 :     safe_print(fd, "true");
     150                 :            :   } else {
     151                 :          0 :     safe_print(fd, "false");
     152                 :            :   }
     153                 :          0 : }
     154                 :            : 
     155                 :            : template <>
     156                 :          0 : void safe_print(int fd, void* const& addr) {
     157                 :          0 :   safe_print_hex(fd, (uint64_t)addr);
     158                 :          0 : }
     159                 :            : 
     160                 :            : template <>
     161                 :          0 : void safe_print(int fd, const timespec& t) {
     162                 :          0 :   safe_print<uint64_t>(fd, t.tv_sec);
     163                 :          0 :   safe_print(fd, ".");
     164                 :          0 :   safe_print_right_aligned(fd, t.tv_nsec, 9);
     165                 :          0 : }
     166                 :            : 
     167                 :          0 : void safe_print_hex(int fd, uint64_t i) {
     168                 :            :   char buf[BUFFER_SIZE];
     169                 :            : 
     170                 :          0 :   safe_print(fd, "0x");
     171         [ -  - ]:          0 :   if (i == 0) {
     172                 :          0 :     safe_print(fd, "0");
     173                 :          0 :     return;
     174                 :            :   }
     175                 :            : 
     176                 :            :   // This loop fills the buffer from the end. The number of elements in the
     177                 :            :   // buffer is BUFER_SIZE - idx - 1 and they start at position idx + 1.
     178                 :          0 :   ssize_t idx = BUFFER_SIZE - 1;
     179 [ -  - ][ -  - ]:          0 :   while (i != 0 && idx >= 0) {
     180                 :          0 :     char current = i % 16;
     181         [ -  - ]:          0 :     if (current <= 9) {
     182                 :          0 :       buf[idx] = '0' + current;
     183                 :            :     } else {
     184                 :          0 :       buf[idx] = 'a' + current - 10;
     185                 :            :     }
     186                 :          0 :     i /= 16;
     187                 :          0 :     idx--;
     188                 :            :   }
     189                 :            : 
     190                 :          0 :   ssize_t nbyte = BUFFER_SIZE - idx - 1;
     191         [ -  - ]:          0 :   if (write(fd, buf + idx + 1, nbyte) != nbyte) {
     192                 :          0 :     abort();
     193                 :            :   }
     194                 :            : }
     195                 :            : 
     196                 :          0 : void safe_print_right_aligned(int fd, uint64_t i, ssize_t width) {
     197                 :            :   char buf[BUFFER_SIZE];
     198                 :            : 
     199                 :            :   // Make sure that the result fits in the buffer
     200                 :          0 :   width = (width < BUFFER_SIZE) ? width : BUFFER_SIZE;
     201                 :            : 
     202         [ -  - ]:          0 :   for (ssize_t j = 0; j < width; j++) {
     203                 :          0 :     buf[j] = '0';
     204                 :            :   }
     205                 :            : 
     206                 :          0 :   ssize_t idx = width - 1;
     207 [ -  - ][ -  - ]:          0 :   while (i != 0 && idx >= 0) {
     208                 :          0 :     buf[idx] = '0' + i % 10;
     209                 :          0 :     i /= 10;
     210                 :          0 :     idx--;
     211                 :            :   }
     212                 :            : 
     213         [ -  - ]:          0 :   if (write(fd, buf, width) != width) {
     214                 :          0 :     abort();
     215                 :            :   }
     216                 :          0 : }
     217                 :            : 
     218                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14