formio/node_modules/bson/lib/bson/parser/calculate_size.js   F
last analyzed

Complexity

Total Complexity 93
Complexity/F 31

Size

Lines of Code 152
Function Count 3

Duplication

Duplicated Lines 92
Ratio 60.53 %

Importance

Changes 0
Metric Value
cc 0
wmc 93
nc 1
mnd 14
bc 35
fnc 3
dl 92
loc 152
rs 1.5789
bpm 11.6666
cpm 31
noi 1
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
B calculate_size.js ➔ calculateObjectSize 0 21 5
D calculate_size.js ➔ calculateElement 92 92 87
A calculate_size.js ➔ isDate 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
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