// ============================================================= //
//                                                               //
//   File      : arb_strbuf.cxx                                  //
//   Purpose   : "unlimited" output buffer                       //
//                                                               //
//   Institute of Microbiology (Technical University Munich)     //
//   http://www.arb-home.de/                                     //
//                                                               //
// ============================================================= //

#include "arb_strbuf.h"

void GBS_strstruct::vnprintf(size_t maxlen, const char *templat, va_list& parg) {
    ensure_mem(maxlen+1);

    char *buffer = data+pos;
    int   printed;

#ifdef LINUX
    printed = vsnprintf(buffer, maxlen+1, templat, parg);
#else
    printed = vsprintf(buffer, templat, parg);
#endif

    assert_or_exit(printed >= 0 && (size_t)printed <= maxlen);
    inc_pos(printed);
}

void GBS_strstruct::nprintf(size_t maxlen, const char *templat, ...) {
    va_list parg;
    va_start(parg, templat);
    vnprintf(maxlen, templat, parg);
}

// --------------------------------------------------------------------------------

#ifdef UNIT_TESTS
#ifndef TEST_UNIT_H
#include <test_unit.h>
#endif

#define EXPECT_CONTENT(expected)             TEST_EXPECT_EQUAL(buf.get_data(), expected)
#define EXPECT_CONTENT__BROKEN(expected,got) TEST_EXPECT_EQUAL__BROKEN(buf.get_data(), expected, got)

void TEST_GBS_strstruct() {
    { GBS_strstruct buf; buf.put ('c');      EXPECT_CONTENT("c");   }
    { GBS_strstruct buf; buf.cat ("abc");    EXPECT_CONTENT("abc"); }
    { GBS_strstruct buf; buf.nput('x', 0);   EXPECT_CONTENT("");    }

    { GBS_strstruct buf; buf.ncat("abc", 0); EXPECT_CONTENT(""); }
    { GBS_strstruct buf; buf.cat ("");       EXPECT_CONTENT("");  }
    { GBS_strstruct buf;                     EXPECT_CONTENT(""); }

    // test multiple consecutive write commands:
    {
        GBS_strstruct buf(1000); EXPECT_CONTENT("");

        buf.nput('b', 3);        EXPECT_CONTENT("bbb");
        buf.putlong(17);         EXPECT_CONTENT("bbb17");
        buf.put('_');            EXPECT_CONTENT("bbb17_");
        buf.putfloat(3.5);       EXPECT_CONTENT("bbb17_3.500000");

        TEST_EXPECT_EQUAL(buf.get_position(), 14);

        buf.cut_tail(13);        EXPECT_CONTENT("b");
        buf.cat("utter");        EXPECT_CONTENT("butter");
        buf.ncat("flying", 3);   EXPECT_CONTENT("butterfly");

        buf.cut(4, 2);           EXPECT_CONTENT("buttfly");

        buf.cat("er");           EXPECT_CONTENT("buttflyer");

        buf.cut(99, 99);         EXPECT_CONTENT("buttflyer");
        buf.cut(0, 0);           EXPECT_CONTENT("buttflyer");
        buf.cut(4, 0);           EXPECT_CONTENT("buttflyer");
        buf.cut(0, 4);           EXPECT_CONTENT("flyer");
        buf.cut(3, 2);           EXPECT_CONTENT("fly");
        buf.cut(3, 99);          EXPECT_CONTENT("fly");
        buf.cut(4, 99);          EXPECT_CONTENT("fly");
        buf.cut(2, 1);           EXPECT_CONTENT("fl");
        buf.cut(1, 99);          EXPECT_CONTENT("f");
    }

    // test reallocation works:
    {
        GBS_strstruct buf(10);
        size_t        oldbufsize = buf.get_buffer_size();
        buf.nput('x', 20); // trigger reallocation of buffer

        TEST_EXPECT_DIFFERENT(oldbufsize, buf.get_buffer_size()); // did we reallocate?
        EXPECT_CONTENT("xxxxxxxxxxxxxxxxxxxx");
    }
}

#endif // UNIT_TESTS

// --------------------------------------------------------------------------------

