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