summaryrefslogtreecommitdiffstats
path: root/comm/suite/chatzilla/js/lib/text-logger.js
blob: 731dbd2eaf4585d8ee30cf28b60f2fa78a47c12b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/**
 * Serializer for lists of data that can be printed line-by-line.
 * If you pass an autoLimit, it will automatically call limit() once the number
 * of appended items exceeds the limit (so the number of items will never
 * exceed limit*2).
 */

function TextLogger(path, autoLimit)
{
    // Check if we can open the path. This will throw if it doesn't work
    var f = fopen(path, ">>");
    f.close();
    this.path = path;

    this.appended = 0;
    if (typeof autoLimit == "number")
        this.autoLimit = autoLimit;
    else
        this.autoLimit = -1;

    // Limit the amount of data in the file when constructing, when asked to.
    if (this.autoLimit != -1)
        this.limit();
}

/**
 * Append data (an array or single item) to the file
 */
TextLogger.prototype.append =
function tl_append(data)
{
    if (!isinstance(data, Array))
        data = [data];

    // If we go over the limit, don't write everything twice:
    if ((this.autoLimit != -1) &&
        (data.length + this.appended > this.autoLimit))
    {
        // Collect complete set of data instead:
        var dataInFile = this.read();
        var newData = dataInFile.concat(data);
        // Get the last |autoLimit| items: yay JS negative indexing!
        newData = newData.slice(-this.autoLimit);
        this.limit(newData);
        return true;
    }

    var file = fopen(this.path, ">>");
    for (var i = 0; i < data.length; i++)
        file.write(ecmaEscape(data[i]) + "\n");
    file.close();
    this.appended += data.length;

    return true;
}

/**
 * Limit the data already in the file to the data provided, or the count given.
 */
TextLogger.prototype.limit =
function tl_limit(dataOrCount)
{
    // Find data and count:
    var data = null, count = -1;
    if (isinstance(dataOrCount, Array))
    {
        data = dataOrCount;
        count = data.length;
    }
    else if (typeof dataOrCount == "number")
    {
        count = dataOrCount;
        data = this.read();
    }
    else if (this.autoLimit != -1)
    {
        count = this.autoLimit;
        data = this.read();
    }
    else
    {
        throw "Can't limit the length of the file without a limit..."
    }

    // Write the right data out. Note that we use the back of the array, not
    // the front (start from data.length - count), without dropping below 0:
    var start = Math.max(data.length - count, 0);
    var file = fopen(this.path, ">");
    for (var i = start; i < data.length; i++)
        file.write(ecmaEscape(data[i]) + "\n");
    file.close();
    this.appended = 0;

    return true;
}

/**
 * Reads out the data currently in the file, and returns an array.
 */
TextLogger.prototype.read =
function tl_read()
{
    var rv = new Array(), parsedLines = new Array(), buffer = "";
    var file = fopen(this.path, "<");
    while (true)
    {
        var newData = file.read();
        if (newData)
            buffer += newData;
        else if (buffer.length == 0)
            break;

        // Got more data in the buffer, so split into lines. Unless we're
        // done, the last one might not be complete yet, so save that one.
        // We split rather strictly on line ends, because empty lines should
        // be preserved.
        var lines = buffer.split(/\r?\n/);
        if (!newData)
            buffer = "";
        else
            buffer = lines.pop();

        rv = rv.concat(lines);
    }
    // Unescape here...
    for (var i = 0; i < rv.length; i++)
        rv[i] = ecmaUnescape(rv[i]);
    return rv;
}