/* * 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 #include #include #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& 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 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 tokenize(const char* sep, const string& str) { struct nested { static const list tokenize(const char* sep, const size_t slen, const string& str, const size_t start) { if (start >= length(str)) return list(); 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& l) { struct nested { static ostringstream& join(const char* sep, const list& 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 operator()() { char buffer[1024]; const size_t n = read(is, buffer, sizeof(buffer)); if (n ==0) return list(); return cons(string(buffer, n), (*this)()); } }; const list streamList(istream& is) { return ilistRead(is)(); } /** * Fragment the first element of a list of strings to fit the given max length. */ const list fragment(list 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& l, ostream& os) { if(isNil(l)) return os; os << car(l); return write(cdr(l), os); } } #endif /* tuscany_sstream_hpp */