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 26char const* SPACES = " "; 27const int SPACE_COUNT = strlen(SPACES); 28 29Out::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 38Out::~Out() 39{ 40 fclose(mOut); 41} 42 43int 44Out::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 58void 59Out::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 102void 103Out::indent() 104{ 105 mPendingIndent = true; 106 mIndent += 2; 107} 108 109void 110Out::dedent() 111{ 112 if (mIndent > 0) { 113 mIndent -= 2; 114 } 115} 116 117void 118Out::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