blob: 17fd28b48b4d11eb5f69aef8feac09a3e70f8d68 [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.
*/
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* 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:
ostringstream() : len(0) {
}
~ostringstream() {
}
ostringstream(const ostringstream& os) {
len = os.len;
buf = os.buf;
}
ostringstream& vprintf(const char* fmt, ...) {
va_list args;
string s;
va_start (args, fmt);
s.len = vsnprintf(NULL, 0, fmt, args);
s.buf = gc_cnew(s.len + 1);
va_start (args, fmt);
vsnprintf(s.buf, s.len + 1, fmt, args);
buf = cons(s, buf);
len += s.len;
va_end (args);
return *this;
}
ostringstream& write(const string& s) {
buf = cons(s, buf);
len += s.len;
return *this;
}
ostringstream& flush() {
return *this;
}
private:
const string str() {
if (isNil(buf))
return string();
string s;
s.len = len;
s.buf = gc_cnew(s.len + 1);
writeList(buf, s.buf + len);
s.buf[s.len] = '\0';
return s;
}
friend const string str(ostringstream& os);
size_t len;
list<string> buf;
};
/**
* Return a string representation of a stream.
*/
const string str(ostringstream& os) {
return os.str();
}
/**
* Input stream backed by a char buffer
*/
class istringstream : public istream {
public:
istringstream(const string& s) {
cur = 0;
const size_t slen = length(s);
len = slen;
buf = c_str(s);
}
~istringstream() {
}
istringstream(const istringstream& is) {
len = is.len;
cur = is.cur;
buf = is.buf;
}
const size_t read(void* b, 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;
}
const bool eof() {
return cur == len;
}
const bool fail() {
return false;
}
const int get() {
if (eof())
return -1;
const int c = buf[cur];
cur += 1;
return c;
}
const int peek() {
if (eof())
return -1;
return buf[cur];
}
private:
size_t len;
size_t cur;
const char* buf;
};
/**
* Tokenize a string into a list of strings.
*/
const list<string> tokenize(const char* sep, const string& str) {
struct nested {
static const list<string> tokenize(const char* sep, const size_t slen, const string& str, const size_t start) {
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 nested::tokenize(sep, strlen(sep), str, 0);
}
/**
* Join a list of strings into a single string.
*/
const string join(const char* sep, const list<string>& l) {
struct nested {
static ostringstream& join(const char* sep, const list<string>& l, ostringstream& os) {
if (isNil(l))
return os;
os << car(l);
if (!isNil(cdr(l)))
os << sep;
return join(sep, cdr(l), os);
}
};
ostringstream os;
return str(nested::join(sep, l, os));
}
/**
* Returns a lazy list view of an input stream.
*/
struct ilistRead{
istream &is;
ilistRead(istream& is) : is(is) {
}
const list<string> operator()() {
char buffer[1024];
const size_t n = read(is, buffer, sizeof(buffer));
if (n ==0)
return list<string>();
return cons(string(buffer, n), (*this)());
}
};
const list<string> streamList(istream& is) {
return ilistRead(is)();
}
/**
* Fragment the first element of a list of strings to fit the given max length.
*/
const list<string> fragment(list<string> l, 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.
*/
ostream& write(const list<string>& l, ostream& os) {
if(isNil(l))
return os;
os << car(l);
return write(cdr(l), os);
}
}
#endif /* tuscany_sstream_hpp */