1bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber/*
2bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Copyright 2012, The Android Open Source Project
3bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *
4bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * you may not use this file except in compliance with the License.
6bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * You may obtain a copy of the License at
7bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *
8bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *
10bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Unless required by applicable law or agreed to in writing, software
11bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * See the License for the specific language governing permissions and
14bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * limitations under the License.
15bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber */
16bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
17bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include "ParsedMessage.h"
18bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
19bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <ctype.h>
20bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
21bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/ADebug.h>
22bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
23bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubernamespace android {
24bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
25bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static
26bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubersp<ParsedMessage> ParsedMessage::Parse(
27bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *data, size_t size, bool noMoreData, size_t *length) {
28bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<ParsedMessage> msg = new ParsedMessage;
29bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t res = msg->parse(data, size, noMoreData);
30bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
31bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
32bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        *length = 0;
33bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return NULL;
34bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
35bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
36bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *length = res;
37bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return msg;
38bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
39bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
40bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberParsedMessage::ParsedMessage() {
41bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
42bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
43bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberParsedMessage::~ParsedMessage() {
44bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
45bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
46bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::findString(const char *name, AString *value) const {
47bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString key = name;
48bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    key.tolower();
49bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
50bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mDict.indexOfKey(key);
51bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
52bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
53bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        value->clear();
54bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
55bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return false;
56bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
57bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
58bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *value = mDict.valueAt(index);
59bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return true;
60bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
61bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
62bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::findInt32(const char *name, int32_t *value) const {
63bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString stringValue;
64bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
65bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (!findString(name, &stringValue)) {
66bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return false;
67bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
68bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
69bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    char *end;
70bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *value = strtol(stringValue.c_str(), &end, 10);
71bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
72bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (end == stringValue.c_str() || *end != '\0') {
73bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        *value = 0;
74bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return false;
75bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
76bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
77bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return true;
78bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
79bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
80bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberconst char *ParsedMessage::getContent() const {
81bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return mContent.c_str();
82bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
83bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
84bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberssize_t ParsedMessage::parse(const char *data, size_t size, bool noMoreData) {
85bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (size == 0) {
86bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -1;
87bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
88bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
89bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t lastDictIndex = -1;
90bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
91bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    size_t offset = 0;
92bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    while (offset < size) {
93bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        size_t lineEndOffset = offset;
94bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        while (lineEndOffset + 1 < size
95bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                && (data[lineEndOffset] != '\r'
96bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        || data[lineEndOffset + 1] != '\n')) {
97bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ++lineEndOffset;
98bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
99bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
100bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (lineEndOffset + 1 >= size) {
101bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            return -1;
102bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
103bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
104bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        AString line(&data[offset], lineEndOffset - offset);
105bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
106bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (offset == 0) {
107bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            // Special handling for the request/status line.
108bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
109bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mDict.add(AString("_"), line);
110bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            offset = lineEndOffset + 2;
111bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
112bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            continue;
113bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
114bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
115bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (lineEndOffset == offset) {
116bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            offset += 2;
117bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
118bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
119bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
120bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
121bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            // Support for folded header values.
122bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
123bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (lastDictIndex >= 0) {
124bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                // Otherwise it's malformed since the first header line
125bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                // cannot continue anything...
126bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
127bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                AString &value = mDict.editValueAt(lastDictIndex);
128bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                value.append(line);
129bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
130bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
131bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            offset = lineEndOffset + 2;
132bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            continue;
133bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
134bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
135bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ssize_t colonPos = line.find(":");
136bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (colonPos >= 0) {
137bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            AString key(line, 0, colonPos);
138bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            key.trim();
139bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            key.tolower();
140bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
141bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            line.erase(0, colonPos + 1);
142bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
143bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            lastDictIndex = mDict.add(key, line);
144bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
145bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
146bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        offset = lineEndOffset + 2;
147bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
148bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
149bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    for (size_t i = 0; i < mDict.size(); ++i) {
150bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mDict.editValueAt(i).trim();
151bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
152bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
153bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    // Found the end of headers.
154bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
155bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int32_t contentLength;
156bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (!findInt32("content-length", &contentLength) || contentLength < 0) {
157bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        contentLength = 0;
158bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
159bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
160bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    size_t totalLength = offset + contentLength;
161bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
162bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (size < totalLength) {
163bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -1;
164bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
165bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
166bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mContent.setTo(&data[offset], contentLength);
167bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
168bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return totalLength;
169bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
170bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
171bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ParsedMessage::getRequestField(size_t index, AString *field) const {
172bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString line;
173bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK(findString("_", &line));
174bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
175bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    size_t prevOffset = 0;
176bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    size_t offset = 0;
177bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    for (size_t i = 0; i <= index; ++i) {
178bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ssize_t spacePos = line.find(" ", offset);
179bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
180bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (spacePos < 0) {
181bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            spacePos = line.size();
182bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
183bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
184bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        prevOffset = offset;
185bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        offset = spacePos + 1;
186bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
187bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
188bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    field->setTo(line, prevOffset, offset - prevOffset - 1);
189bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
190bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
191bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::getStatusCode(int32_t *statusCode) const {
192bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString statusCodeString;
193bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    getRequestField(1, &statusCodeString);
194bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
195bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    char *end;
196bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *statusCode = strtol(statusCodeString.c_str(), &end, 10);
197bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
198bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (*end != '\0' || end == statusCodeString.c_str()
199bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            || (*statusCode) < 100 || (*statusCode) > 999) {
200bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        *statusCode = 0;
201bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return false;
202bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
203bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
204bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return true;
205bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
206bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
207bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberAString ParsedMessage::debugString() const {
208bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString line;
209bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK(findString("_", &line));
210bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
211bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    line.append("\n");
212bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
213bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    for (size_t i = 0; i < mDict.size(); ++i) {
214bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const AString &key = mDict.keyAt(i);
215bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const AString &value = mDict.valueAt(i);
216bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
217bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (key == AString("_")) {
218bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            continue;
219bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
220bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
221bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        line.append(key);
222bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        line.append(": ");
223bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        line.append(value);
224bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        line.append("\n");
225bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
226bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
227bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    line.append("\n");
228bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    line.append(mContent);
229bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
230bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return line;
231bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
232bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
233bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static
234bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::GetAttribute(
235bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *s, const char *key, AString *value) {
236bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    value->clear();
237bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
238bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    size_t keyLen = strlen(key);
239bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
240bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    for (;;) {
241bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        while (isspace(*s)) {
242bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ++s;
243bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
244bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
245bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *colonPos = strchr(s, ';');
246bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
247bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        size_t len =
248bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (colonPos == NULL) ? strlen(s) : colonPos - s;
249bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
250bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
251bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            value->setTo(&s[keyLen + 1], len - keyLen - 1);
252bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            return true;
253bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
254bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
255bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (colonPos == NULL) {
256bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            return false;
257bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
258bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
259bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        s = colonPos + 1;
260bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
261bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
262bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
263bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static
264bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ParsedMessage::GetInt32Attribute(
265bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *s, const char *key, int32_t *value) {
266bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString stringValue;
267bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (!GetAttribute(s, key, &stringValue)) {
268bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        *value = 0;
269bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return false;
270bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
271bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
272bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    char *end;
273bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *value = strtol(stringValue.c_str(), &end, 10);
274bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
275bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (end == stringValue.c_str() || *end != '\0') {
276bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        *value = 0;
277bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return false;
278bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
279bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
280bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return true;
281bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
282bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
283bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}  // namespace android
284bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
285