1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian#include <binder/BufferedTextOutput.h>
18002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian#include <binder/Debug.h>
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Atomic.h>
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/RefBase.h>
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Vector.h>
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <cutils/threads.h>
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
26002e1e58dfe19dd3e49a59c6827cbf51573941a2Mathias Agopian#include <private/binder/Static.h>
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdio.h>
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h>
30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android {
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstruct BufferedTextOutput::BufferState : public RefBase
36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    BufferState(int32_t _seq)
38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        : seq(_seq)
39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        , buffer(NULL)
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        , bufferPos(0)
41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        , bufferSize(0)
42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        , atFront(true)
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        , indent(0)
44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        , bundle(0) {
45edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ~BufferState() {
47edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        free(buffer);
48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t append(const char* txt, size_t len) {
51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if ((len+bufferPos) > bufferSize) {
52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            void* b = realloc(buffer, ((len+bufferPos)*3)/2);
53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (!b) return NO_MEMORY;
54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            buffer = (char*)b;
55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        memcpy(buffer+bufferPos, txt, len);
57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        bufferPos += len;
58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return NO_ERROR;
59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    void restart() {
62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        bufferPos = 0;
63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        atFront = true;
64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (bufferSize > 256) {
65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            void* b = realloc(buffer, 256);
66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (b) {
67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                buffer = (char*)b;
68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                bufferSize = 256;
69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const int32_t seq;
74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    char* buffer;
75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    size_t bufferPos;
76edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    size_t bufferSize;
77edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    bool atFront;
78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int32_t indent;
79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int32_t bundle;
80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project};
81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstruct BufferedTextOutput::ThreadState
83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Vector<sp<BufferedTextOutput::BufferState> > states;
85edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project};
86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic mutex_t          gMutex;
88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
89edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic thread_store_t   tls;
90edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
91edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectBufferedTextOutput::ThreadState* BufferedTextOutput::getThreadState()
92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ThreadState*  ts = (ThreadState*) thread_store_get( &tls );
94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (ts) return ts;
95edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ts = new ThreadState;
96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    thread_store_set( &tls, ts, threadDestructor );
97edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return ts;
98edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid BufferedTextOutput::threadDestructor(void *st)
101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    delete ((ThreadState*)st);
103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic volatile int32_t gSequence = 0;
106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
107edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic volatile int32_t gFreeBufferIndex = -1;
108edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic int32_t allocBufferIndex()
110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int32_t res = -1;
112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mutex_lock(&gMutex);
114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (gFreeBufferIndex >= 0) {
116edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        res = gFreeBufferIndex;
117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        gFreeBufferIndex = gTextBuffers[res];
118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        gTextBuffers.editItemAt(res) = -1;
119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    } else {
121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        res = gTextBuffers.size();
122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        gTextBuffers.add(-1);
123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mutex_unlock(&gMutex);
126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return res;
128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic void freeBufferIndex(int32_t idx)
131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mutex_lock(&gMutex);
133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    gTextBuffers.editItemAt(idx) = gFreeBufferIndex;
134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    gFreeBufferIndex = idx;
135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mutex_unlock(&gMutex);
136edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
137edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------
139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectBufferedTextOutput::BufferedTextOutput(uint32_t flags)
141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    : mFlags(flags)
142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    , mSeq(android_atomic_inc(&gSequence))
143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    , mIndex(allocBufferIndex())
144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
145edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mGlobalState = new BufferState(mSeq);
146edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (mGlobalState) mGlobalState->incStrong(this);
147edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
149edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectBufferedTextOutput::~BufferedTextOutput()
150edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
151edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (mGlobalState) mGlobalState->decStrong(this);
152edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    freeBufferIndex(mIndex);
153edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
154edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t BufferedTextOutput::print(const char* txt, size_t len)
156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    //printf("BufferedTextOutput: printing %d\n", len);
158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    AutoMutex _l(mLock);
160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    BufferState* b = getBuffer();
161edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
162edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const char* const end = txt+len;
163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    status_t err;
165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    while (txt < end) {
167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Find the next line.
168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const char* first = txt;
169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        while (txt < end && *txt != '\n') txt++;
170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Include this and all following empty lines.
172edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        while (txt < end && *txt == '\n') txt++;
173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Special cases for first data on a line.
175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (b->atFront) {
176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (b->indent > 0) {
177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // If this is the start of a line, add the indent.
178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                const char* prefix = stringForIndent(b->indent);
179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                err = b->append(prefix, strlen(prefix));
180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (err != NO_ERROR) return err;
181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            } else if (*(txt-1) == '\n' && !b->bundle) {
183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // Fast path: if we are not indenting or bundling, and
184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // have been given one or more complete lines, just write
185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // them out without going through the buffer.
186edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
187edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                // Slurp up all of the lines.
188edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                const char* lastLine = txt+1;
189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                while (txt < end) {
190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    if (*txt++ == '\n') lastLine = txt;
191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                }
192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                struct iovec vec;
193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                vec.iov_base = (void*)first;
194edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                vec.iov_len = lastLine-first;
195edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                //printf("Writing %d bytes of data!\n", vec.iov_len);
196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                writeLines(vec, 1);
197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                txt = lastLine;
198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                continue;
199edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
200edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
201edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
202edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Append the new text to the buffer.
203edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        err = b->append(first, txt-first);
204edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (err != NO_ERROR) return err;
205edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        b->atFront = *(txt-1) == '\n';
206edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
207edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // If we have finished a line and are not bundling, write
208edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // it out.
209edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        //printf("Buffer is now %d bytes\n", b->bufferPos);
210edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (b->atFront && !b->bundle) {
211edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            struct iovec vec;
212edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            vec.iov_base = b->buffer;
213edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            vec.iov_len = b->bufferPos;
214edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            //printf("Writing %d bytes of data!\n", vec.iov_len);
215edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            writeLines(vec, 1);
216edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            b->restart();
217edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
218edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
219edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return NO_ERROR;
221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid BufferedTextOutput::moveIndent(int delta)
224edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
225edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    AutoMutex _l(mLock);
226edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    BufferState* b = getBuffer();
227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    b->indent += delta;
228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (b->indent < 0) b->indent = 0;
229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
230edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
231edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid BufferedTextOutput::pushBundle()
232edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    AutoMutex _l(mLock);
234edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    BufferState* b = getBuffer();
235edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    b->bundle++;
236edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
237edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
238edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid BufferedTextOutput::popBundle()
239edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    AutoMutex _l(mLock);
241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    BufferState* b = getBuffer();
242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    b->bundle--;
243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    LOG_FATAL_IF(b->bundle < 0,
244edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        "TextOutput::popBundle() called more times than pushBundle()");
245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (b->bundle < 0) b->bundle = 0;
246edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (b->bundle == 0) {
248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // Last bundle, write out data if it is complete.  If it is not
249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // complete, don't write until the last line is done... this may
250edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // or may not be the write thing to do, but it's the easiest.
251edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (b->bufferPos > 0 && b->atFront) {
252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            struct iovec vec;
253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            vec.iov_base = b->buffer;
254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            vec.iov_len = b->bufferPos;
255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            writeLines(vec, 1);
256edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            b->restart();
257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
258edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
261edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectBufferedTextOutput::BufferState* BufferedTextOutput::getBuffer() const
262edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if ((mFlags&MULTITHREADED) != 0) {
264edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        ThreadState* ts = getThreadState();
265edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (ts) {
266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            while (ts->states.size() <= (size_t)mIndex) ts->states.add(NULL);
267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            BufferState* bs = ts->states[mIndex].get();
268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (bs != NULL && bs->seq == mSeq) return bs;
269edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
270edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            ts->states.editItemAt(mIndex) = new BufferState(mIndex);
271edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            bs = ts->states[mIndex].get();
272edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (bs != NULL) return bs;
273edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
274edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
275edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
276edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mGlobalState;
277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android
280