blob: 9ea05e669aef3b3259188d0fb603d03fb825d88f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nokia - Initial API and implementation
*******************************************************************************/
#include "TCFInputStream.h"
extern "C" {
#include "errors.h"
};
TCFInputStream::TCFInputStream(InputStream * inp) {
inp_ = inp;
}
TCFInputStream::~TCFInputStream(void) {
}
static int readHex(InputStream * inp) {
int ch = read_stream(inp);
if (ch >= '0' && ch <= '9')
return ch - '0';
if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
exception(ERR_JSON_SYNTAX);
return 0;
}
static int readHexChar(InputStream * inp) {
int n = readHex(inp) << 12;
n |= readHex(inp) << 8;
n |= readHex(inp) << 4;
n |= readHex(inp);
return n;
}
static int read_esc_char(InputStream * inp) {
int ch = read_stream(inp);
switch (ch) {
case '"':
break;
case '\\':
break;
case '/':
break;
case 'b':
ch = '\b';
break;
case 'f':
ch = '\f';
break;
case 'n':
ch = '\n';
break;
case 'r':
ch = '\r';
break;
case 't':
ch = '\t';
break;
case 'u':
ch = readHexChar(inp);
break;
default:
exception(ERR_JSON_SYNTAX);
}
return ch;
}
std::string TCFInputStream::readString() {
std::string result;
InputStream* inp = inp_;
int ch = read_stream(inp);
if (ch == 'n') {
if (read_stream(inp) != 'u')
exception(ERR_JSON_SYNTAX);
if (read_stream(inp) != 'l')
exception(ERR_JSON_SYNTAX);
if (read_stream(inp) != 'l')
exception(ERR_JSON_SYNTAX);
} else {
if (ch != '"')
exception(ERR_JSON_SYNTAX);
for (;;) {
ch = read_stream(inp);
if (ch == '"')
break;
if (ch == '\\')
ch = read_esc_char(inp);
result += (char) ch;
}
}
return result;
}
unsigned long TCFInputStream::readULong() {
return json_read_ulong(inp_);
}
long TCFInputStream::readLong() {
return json_read_long(inp_);
}
void TCFInputStream::readZero() {
if (inp_->read(inp_) != 0)
exception(ERR_JSON_SYNTAX);
}
void TCFInputStream::readComplete() {
if (inp_->read(inp_) != MARKER_EOM)
exception(ERR_JSON_SYNTAX);
}
char* TCFInputStream::readBinaryData(int dataSize) {
char* memBuffer = new char[4 * ((dataSize + 2) / 3)];
JsonReadBinaryState state;
json_read_binary_start(&state, inp_);
json_read_binary_data(&state, memBuffer, dataSize);
json_read_binary_end(&state);
return memBuffer;
}
std::map<InputStream*, TCFInputStreamAdapter*> TCFInputStreamAdapter::adapterMap;
TCFInputStreamAdapter* TCFInputStreamAdapter::findInputStream(InputStream* stream) {
std::map<InputStream*, TCFInputStreamAdapter*>::iterator iter = adapterMap.find(stream);
if (iter != adapterMap.end()) {
return adapterMap[stream];
} else {
// should not get here
check_error(ERR_CHANNEL_CLOSED);
exit(1);
return 0; // quell warning
}
}
TCFInputStreamAdapter::TCFInputStreamAdapter(InputStream* input) {
theStream_ = input;
theStream_->cur = theStream_->end = 0;
theStream_->read = TCFInputStreamAdapter::read_impl;
theStream_->peek = TCFInputStreamAdapter::peek_impl;
adapterMap[theStream_] = this;
}
TCFInputStreamAdapter::~TCFInputStreamAdapter() {
adapterMap.erase(theStream_);
}
int TCFInputStreamAdapter::read_impl(InputStream * stream) {
TCFInputStreamAdapter* tcfStream = findInputStream(stream);
return tcfStream->read();
}
int TCFInputStreamAdapter::peek_impl(InputStream * stream) {
TCFInputStreamAdapter* tcfStream = findInputStream(stream);
return tcfStream->peek();
}