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