Total Complexity | 93 |
Complexity/F | 31 |
Lines of Code | 152 |
Function Count | 3 |
Duplicated Lines | 92 |
Ratio | 60.53 % |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like formio/node_modules/bson/lib/bson/parser/calculate_size.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | "use strict" |
||
2 | |||
3 | var writeIEEE754 = require('../float_parser').writeIEEE754 |
||
4 | , readIEEE754 = require('../float_parser').readIEEE754 |
||
5 | , Long = require('../long').Long |
||
6 | , Double = require('../double').Double |
||
7 | , Timestamp = require('../timestamp').Timestamp |
||
8 | , ObjectID = require('../objectid').ObjectID |
||
9 | , Symbol = require('../symbol').Symbol |
||
10 | , BSONRegExp = require('../regexp').BSONRegExp |
||
11 | , Code = require('../code').Code |
||
12 | , Decimal128 = require('../decimal128') |
||
13 | , MinKey = require('../min_key').MinKey |
||
14 | , MaxKey = require('../max_key').MaxKey |
||
15 | , DBRef = require('../db_ref').DBRef |
||
16 | , Binary = require('../binary').Binary; |
||
17 | |||
18 | // To ensure that 0.4 of node works correctly |
||
19 | var isDate = function isDate(d) { |
||
20 | return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; |
||
21 | } |
||
22 | |||
23 | var calculateObjectSize = function calculateObjectSize(object, serializeFunctions, ignoreUndefined) { |
||
24 | var totalLength = (4 + 1); |
||
25 | |||
26 | if(Array.isArray(object)) { |
||
27 | for(var i = 0; i < object.length; i++) { |
||
28 | totalLength += calculateElement(i.toString(), object[i], serializeFunctions, true, ignoreUndefined) |
||
29 | } |
||
30 | } else { |
||
31 | // If we have toBSON defined, override the current object |
||
32 | if(object.toBSON) { |
||
33 | object = object.toBSON(); |
||
34 | } |
||
35 | |||
36 | // Calculate size |
||
37 | for(var key in object) { |
||
38 | totalLength += calculateElement(key, object[key], serializeFunctions, false, ignoreUndefined) |
||
39 | } |
||
40 | } |
||
41 | |||
42 | return totalLength; |
||
43 | } |
||
44 | |||
45 | /** |
||
46 | * @ignore |
||
47 | * @api private |
||
48 | */ |
||
49 | View Code Duplication | function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefined) { |
|
50 | // If we have toBSON defined, override the current object |
||
51 | if(value && value.toBSON){ |
||
52 | value = value.toBSON(); |
||
53 | } |
||
54 | |||
55 | switch(typeof value) { |
||
|
|||
56 | case 'string': |
||
57 | return 1 + Buffer.byteLength(name, 'utf8') + 1 + 4 + Buffer.byteLength(value, 'utf8') + 1; |
||
58 | case 'number': |
||
59 | if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { |
||
60 | if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit |
||
61 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (4 + 1); |
||
62 | } else { |
||
63 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1); |
||
64 | } |
||
65 | } else { // 64 bit |
||
66 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1); |
||
67 | } |
||
68 | case 'undefined': |
||
69 | if(isArray || !ignoreUndefined) return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1); |
||
70 | return 0; |
||
71 | case 'boolean': |
||
72 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1 + 1); |
||
73 | case 'object': |
||
74 | if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { |
||
75 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1); |
||
76 | } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { |
||
77 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (12 + 1); |
||
78 | } else if(value instanceof Date || isDate(value)) { |
||
79 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1); |
||
80 | } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { |
||
81 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (1 + 4 + 1) + value.length; |
||
82 | } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp |
||
83 | || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { |
||
84 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (8 + 1); |
||
85 | } else if(value instanceof Decimal128 || value['_bsontype'] == 'Decimal128') { |
||
86 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (16 + 1); |
||
87 | } else if(value instanceof Code || value['_bsontype'] == 'Code') { |
||
88 | // Calculate size depending on the availability of a scope |
||
89 | if(value.scope != null && Object.keys(value.scope).length > 0) { |
||
90 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + 4 + Buffer.byteLength(value.code.toString(), 'utf8') + 1 + calculateObjectSize(value.scope, serializeFunctions, ignoreUndefined); |
||
91 | } else { |
||
92 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + Buffer.byteLength(value.code.toString(), 'utf8') + 1; |
||
93 | } |
||
94 | } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { |
||
95 | // Check what kind of subtype we have |
||
96 | if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { |
||
97 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (value.position + 1 + 4 + 1 + 4); |
||
98 | } else { |
||
99 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + (value.position + 1 + 4 + 1); |
||
100 | } |
||
101 | } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { |
||
102 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + Buffer.byteLength(value.value, 'utf8') + 4 + 1 + 1; |
||
103 | } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { |
||
104 | // Set up correct object for serialization |
||
105 | var ordered_values = { |
||
106 | '$ref': value.namespace |
||
107 | , '$id' : value.oid |
||
108 | }; |
||
109 | |||
110 | // Add db reference if it exists |
||
111 | if(null != value.db) { |
||
112 | ordered_values['$db'] = value.db; |
||
113 | } |
||
114 | |||
115 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + calculateObjectSize(ordered_values, serializeFunctions, ignoreUndefined); |
||
116 | } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { |
||
117 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + Buffer.byteLength(value.source, 'utf8') + 1 |
||
118 | + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 |
||
119 | } else if(value instanceof BSONRegExp || value['_bsontype'] == 'BSONRegExp') { |
||
120 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + Buffer.byteLength(value.pattern, 'utf8') + 1 |
||
121 | + Buffer.byteLength(value.options, 'utf8') + 1 |
||
122 | } else { |
||
123 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + calculateObjectSize(value, serializeFunctions, ignoreUndefined) + 1; |
||
124 | } |
||
125 | case 'function': |
||
126 | // WTF for 0.4.X where typeof /someregexp/ === 'function' |
||
127 | if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { |
||
128 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + Buffer.byteLength(value.source, 'utf8') + 1 |
||
129 | + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 |
||
130 | } else { |
||
131 | if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { |
||
132 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + 4 + Buffer.byteLength(value.toString(), 'utf8') + 1 + calculateObjectSize(value.scope, serializeFunctions, ignoreUndefined); |
||
133 | } else if(serializeFunctions) { |
||
134 | return (name != null ? (Buffer.byteLength(name, 'utf8') + 1) : 0) + 1 + 4 + Buffer.byteLength(value.toString(), 'utf8') + 1; |
||
135 | } |
||
136 | } |
||
137 | } |
||
138 | |||
139 | return 0; |
||
140 | } |
||
141 | |||
142 | var BSON = {}; |
||
143 | |||
144 | // BSON MAX VALUES |
||
145 | BSON.BSON_INT32_MAX = 0x7FFFFFFF; |
||
146 | BSON.BSON_INT32_MIN = -0x80000000; |
||
147 | |||
148 | // JS MAX PRECISE VALUES |
||
149 | BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. |
||
150 | BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. |
||
151 | |||
152 | module.exports = calculateObjectSize; |
||
153 |