Home | History | Annotate | Download | only in incident_report
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "printer.h"
     18 
     19 #include <unistd.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <stdarg.h>
     23 
     24 #define INITIAL_BUF_SIZE (16*1024)
     25 
     26 char const* SPACES = "                                                            ";
     27 const int SPACE_COUNT = strlen(SPACES);
     28 
     29 Out::Out(int fd)
     30     :mOut(fd == STDOUT_FILENO ? stdout : fdopen(fd, "w")),
     31      mBufSize(INITIAL_BUF_SIZE),
     32      mBuf((char*)malloc(INITIAL_BUF_SIZE)),
     33      mIndent(0),
     34      mPendingIndent(false)
     35 {
     36 }
     37 
     38 Out::~Out()
     39 {
     40     fclose(mOut);
     41 }
     42 
     43 int
     44 Out::reallocate(int size)
     45 {
     46     if (size > mBufSize) {
     47         char* p = (char*)malloc(size);
     48         if (p != NULL) {
     49             free(mBuf);
     50             mBufSize = size;
     51             mBuf = p;
     52             return size;
     53         }
     54     }
     55     return mBufSize;
     56 }
     57 
     58 void
     59 Out::printf(const char* format, ...)
     60 {
     61     if (mPendingIndent) {
     62         print_indent();
     63         mPendingIndent = false;
     64     }
     65 
     66     int len;
     67 
     68     va_list args;
     69     va_start(args, format);
     70 
     71     len = vsnprintf(mBuf, mBufSize, format, args);
     72     va_end(args);
     73     bool truncated = (len >= mBufSize) && (reallocate(len) < len);
     74 
     75     va_start(args, format);
     76     len = vsnprintf(mBuf, mBufSize, format, args);
     77     va_end(args);
     78 
     79     if (len > 0) {
     80         if (mIndent == 0) {
     81             fwrite(mBuf, len, 1, mOut);
     82         } else {
     83             char* last = mBuf;
     84             char* p;
     85             do {
     86                 p = strchr(last, '\n');
     87                 int size = p != NULL ? p - last + 1 : strlen(last);
     88                 fwrite(last, size, 1, mOut);
     89                 if (p != NULL) {
     90                     if (p[1] == '\0') {
     91                         mPendingIndent = true;
     92                     } else {
     93                         print_indent();
     94                     }
     95                 }
     96                 last = p+1;
     97             } while (p != NULL);
     98         }
     99     }
    100 }
    101 
    102 void
    103 Out::indent()
    104 {
    105     mPendingIndent = true;
    106     mIndent += 2;
    107 }
    108 
    109 void
    110 Out::dedent()
    111 {
    112     if (mIndent > 0) {
    113         mIndent -= 2;
    114     }
    115 }
    116 
    117 void
    118 Out::print_indent()
    119 {
    120 #if 0
    121     fprintf(mOut, "[%d]", mIndent);
    122 #else
    123     int indent = mIndent;
    124     while (indent > SPACE_COUNT) {
    125         fwrite(SPACES, SPACE_COUNT, 1, mOut);
    126         indent -= SPACE_COUNT;
    127     }
    128     fwrite(SPACES + SPACE_COUNT - indent, indent, 1, mOut);
    129 #endif
    130 }
    131