blob: dbdc7414a18f8fa24eaf968aad6873f14bde74d9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_sstream_hpp
#define tuscany_sstream_hpp
/**
* Char buffer based streams.
*/
#include <stdio.h>
#include <stdarg.h>
#include <memory.h>
#include "string.hpp"
#include "stream.hpp"
#include "list.hpp"
namespace tuscany {
/**
* Instrumentable memcpy.
*/
inline void* stream_memcpy(void* t, const void* s, const size_t n) {
return memcpy(t, s, n);
}
/**
* Write a list of strings into a buffer.
*/
const bool writeList(const list<string>& l, char* const buf) {
if (isNil(l))
return true;
const string c = car(l);
char* b = buf - length(c);
memcpy(b, c_str(c), length(c));
return writeList(cdr(l), b);
}
/**
* Output stream backed by a char buffer.
*/
class ostringstream : public ostream {
public:
inline ostringstream() : len(0), accumbuf(NULL), accumlen(0), buf() {
}
inline ~ostringstream() {
}
inline ostringstream(const ostringstream& os) : len(os.len), accumbuf(os.accumbuf), accumlen(os.accumlen), buf(os.buf) {
}
inline ostringstream& vprintf(const char* const fmt, ...) {
va_list args;
va_start (args, fmt);
const size_t l = vsnprintf(NULL, 0, fmt, args);
if (l <= 256) {
char c[256];
va_start (args, fmt);
vsnprintf(c, l + 1, fmt, args);
va_end (args);
accumulate(c, l);
return *this;
}
spill();
char* const sbuf = gc_cnew(l + 1);
va_start (args, fmt);
vsnprintf(sbuf, l + 1, fmt, args);
va_end (args);
buf = cons(string(sbuf, l, false), (const list<string>)buf);
len += l;
return *this;
}
inline ostringstream& write(const string& s) {
if (s.len <= 256) {
accumulate(s.buf, s.len);
return *this;
}
spill();
buf = cons(s, (const list<string>)buf);
len += s.len;
return *this;
}
inline ostringstream& write(const char c) {
accumulate(&c, 1);
return *this;
}
inline ostringstream& flush() {
spill();
return *this;
}
private:
inline const string str() {
spill();
if (isNil((const list<string>)buf))
return emptyString;
char* const sbuf = gc_cnew(len + 1);
writeList(buf, sbuf + len);
sbuf[len] = '\0';
return string(sbuf, len, false);
}
inline const bool accumulate(const char* const c, const size_t l) {
if (accumbuf == NULL)
accumbuf = gc_cnew(65);
for(size_t i = 0; i < l; i++) {
accumbuf[accumlen] = c[i];
accumlen++;
if (accumlen == 64) {
accumbuf[accumlen] = '\0';
buf = cons(string(accumbuf, accumlen, false), (const list<string>)buf);
accumbuf = i < l? gc_cnew(65) : NULL;
accumlen = 0;
}
}
accumbuf[accumlen] = '\0';
len += l;
return true;
}
inline const bool spill() {
if (accumbuf == NULL)
return true;
buf = cons(string(accumbuf, accumlen), (const list<string>)buf);
accumbuf = NULL;
accumlen = 0;
return true;
}
friend const string str(ostringstream& os);
size_t len;
char* accumbuf;
size_t accumlen;
gc_mutable_ref<list<string> > buf;
};
/**
* Return a string representation of a stream.
*/
inline const string str(ostringstream& os) {
return os.str();
}
/**
* Input stream backed by a char buffer
*/
class istringstream : public istream {
public:
inline istringstream(const string& s) : len(length(s)), cur(0), buf(c_str(s)) {
}
inline ~istringstream() {
}
inline istringstream(const istringstream& is) : len(is.len), cur(is.cur), buf(is.buf) {
}
inline const size_t read(void* const b, const size_t size) {
const size_t n = len - cur;
if (n == 0)
return 0;
if (n > size) {
stream_memcpy(b, buf + cur, size);
cur = cur + size;
return size;
}
stream_memcpy(b, buf + cur, n);
cur = cur + n;
return n;
}
inline const bool eof() {
return cur == len;
}
inline const bool fail() {
return false;
}
inline const int get() {
if (cur == len)
return -1;
return buf[cur++];
}
inline const int peek() {
if (cur == len)
return -1;
return buf[cur];
}
private:
const size_t len;
size_t cur;
const char* buf;
};
/**
* Tokenize a string into a list of strings.
*/
inline const list<string> tokenize(const char* const sep, const string& str) {
const lambda<const list<string>(const char* const, const size_t, const string&, const size_t)> tokenize = [&tokenize](const char* const sep, const size_t slen, const string& str, const size_t start) -> const list<string> {
if (start >= length(str))
return list<string>();
const size_t i = find(str, sep, start);
if (i == length(str))
return mklist(string(substr(str, start)));
return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen));
};
return tokenize(sep, strlen(sep), str, 0);
}
/**
* Join a list of strings into a single string.
*/
inline const string join(const char* const sep, const list<string>& l) {
ostringstream os;
const lambda<ostringstream&(const char* const, const list<string>&, ostringstream&)> join = [&join](const char* const sep, const list<string>& l, ostringstream& os) -> ostringstream& {
if (isNil(l))
return os;
os << car(l);
if (!isNil(cdr(l)))
os << sep;
return join(sep, cdr(l), os);
};
return str(join(sep, l, os));
}
/**
* Returns a lazy list view of an input stream.
*/
inline const list<string> streamList(istream& is) {
const lambda<const list<string>()> ilistRead = [&is, &ilistRead]() -> const list<string> {
char buffer[1024];
const size_t n = read(is, buffer, sizeof(buffer));
if (n ==0)
return list<string>();
return cons(string(buffer, n), ilistRead());
};
return ilistRead();
}
/**
* Fragment the first element of a list of strings to fit the given max length.
*/
inline const list<string> fragment(const list<string>& l, const size_t max) {
const string s = car(l);
if (length(s) <= max)
return l;
return cons(substr(s, 0, max), cons(substr(s, max), cdr(l)));
}
/**
* Write a list of strings to an output stream.
*/
inline ostream& write(const list<string>& l, ostream& os) {
if(isNil(l))
return os;
os << car(l);
return write(cdr(l), os);
}
/**
* Convert a list of strings to a string.
*/
inline const string write(const list<string>& l) {
if (isNil(l))
return emptyString;
if (isNil(cdr(l)))
return car(l);
ostringstream os;
write(l, os);
return str(os);
}
}
#endif /* tuscany_sstream_hpp */