-
Notifications
You must be signed in to change notification settings - Fork 55
/
structure.js
104 lines (89 loc) · 2.98 KB
/
structure.js
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
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;
};