All files / node_modules/dbf/src structure.js

92.86% Statements 13/14
66.67% Branches 4/6
100% Functions 5/5
92.86% Lines 13/14
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  1x 1x             1x   6x 6x 6x 6x                   6x 6x                       6x                                 3x     6x             30x                                                                                
var fieldSize = require('./fieldsize'),
    lib = require('./lib'),
    fields = require('./fields');
 
/**
 * @param {Array} data
 * @param {Array} meta
 * @returns {Object} view
 */
module.exports = function structure(data, meta) {
 
    var field_meta = meta || fields.multi(data),
        fieldDescLength = (32 * field_meta.length) + 1,
        bytesPerRecord = fields.bytesPer(field_meta), // deleted flag
        buffer = new ArrayBuffer(
            // field header
            fieldDescLength +
            // header
            32 +
            // contents
            (bytesPerRecord * data.length) +
            // EOF marker
            1
    ),
        now = new Date(),
        view = new DataView(buffer);
 
    // version number - dBase III
    view.setUint8(0, 0x03);
    // date of last update
    view.setUint8(1, now.getFullYear() - 1900);
    view.setUint8(2, now.getMonth() + 1);
    view.setUint8(3, now.getDate());
    // number of records
    view.setUint32(4, data.length, true);
 
    // length of header
    var headerLength = fieldDescLength + 32;
    view.setUint16(8, headerLength, true);
    // length of each record
    view.setUint16(10, bytesPerRecord, true);
 
    // Terminator
    view.setInt8(32 + fieldDescLength - 1, 0x0D);
 
    field_meta.forEach(function(f, i) {
        // field name
        f.name.split('').slice(0, 10).forEach(function(c, x) {
            view.setInt8(32 + i * 32 + x, c.charCodeAt(0));
        });
        // field type
        view.setInt8(32 + i * 32 + 11, f.type.charCodeAt(0));
        // field length
        view.setInt8(32 + i * 32 + 16, f.size);
        if (f.type == 'N') view.setInt8(32 + i * 32 + 17, 3);
    });
 
    var offset = fieldDescLength + 32;
 
    data.forEach(function(row, num) {
        // delete flag: this is not deleted
        view.setUint8(offset, 32);
        offset++;
        field_meta.forEach(function(f) {
            var val = row[f.name];
            if (val === null || typeof val === 'undefined') val = '';
 
            switch (f.type) {
                // boolean
                case 'L':
                    view.setUint8(offset, val ? 84 : 70);
                    offset++;
                    break;
 
                // date
                case 'D':
                    offset = lib.writeField(view, 8,
                        lib.lpad(val.toString(), 8, ' '), offset);
                    break;
 
                // number
                case 'N':
                    offset = lib.writeField(view, f.size,
                        lib.lpad(val.toString(), f.size, ' ').substr(0, 18),
                        offset);
                    break;
 
                // string
                case 'C':
                    offset = lib.writeField(view, f.size,
                        lib.rpad(val.toString(), f.size, ' '), offset);
                    break;
 
                default:
                    throw new Error('Unknown field type');
            }
        });
    });
 
    // EOF flag
    view.setUint8(offset, 0x1A);
 
    return view;
};