| /* |
| * 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 */ |