/**
* This file is part of SesaJsTools.
* Copyright 2014-2015, Association Sésamath
*
* SesaJsTools is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation.
*
* SesaJsTools is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SesaJsTools (LICENCE.txt).
* @see http://www.gnu.org/licenses/agpl.txt
*
*
* Ce fichier fait partie de l'application Sésathèque, créée par l'association Sésamath.
*
* Sésathèque est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant
* les termes de la GNU Affero General Public License version 3 telle que publiée par la
* Free Software Foundation.
* Sésathèque est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE,
* sans même la garantie tacite de QUALITÉ MARCHANDE ou d'ADÉQUATION à UN BUT PARTICULIER.
* Consultez la GNU Affero General Public License pour plus de détails.
* Vous devez avoir reçu une copie de la GNU General Public License en même temps que Sésathèque
* (cf LICENCE.txt et http://vvlibri.org/fr/Analyse/gnu-affero-general-public-license-v3-analyse
* pour une explication en français)
*/
'use strict'
var tools = require('../index')
var hasProp = tools.hasProp
/**
* dump un objet de manière plus complète qu'un stringify
* @param obj
* @param indent
* @returns {*}
*/
module.exports = function dump (obj, indent) {
// on traite déjà null
if (obj === null) return 'null'
// puis les types natifs basiques
var type = typeof obj
switch (type) {
case 'undefined':
return obj
case 'number':
case 'boolean':
return String(obj)
case 'string':
return '"' + obj.replace('"', '\\"') + '"'
case 'symbol':
return '[Symbol ' + obj.toString() + ']'
default:
if (!indent) indent = 0
// decalage de base
var prefix = (' ').repeat(indent)
indent += 2
var innerPrefix = prefix + ' '
var pile = []
var buffer
// object et symbol
// on regarde d'abord si on a une méthode toSource toute prête qui existe sur cet objet
// (sauf pour les date qui posent pb sous node)
if (tools.isDate(obj)) {
return JSON.stringify(obj)
} else if (tools.isArray(obj)) {
buffer = '[\n'
obj.forEach(function (elt, index) {
buffer += innerPrefix + dump(elt, indent) + (index === obj.length - 1 ? '\n' : ',\n')
})
if (obj.length) buffer += prefix + ']'
else buffer += ']'
return buffer
} else if (tools.isRegExp(obj) || tools.isFunction(obj)) {
// dans un navigateur toSource existe pour eux, mais pas dans node
return (typeof obj.toSource === 'function') ? obj.toSource() : obj.toString()
} else if (tools.isObject(obj)) {
var nbp = 0
for (var p in obj) {
if (hasProp(obj, p)) {
nbp++
// pour détecter les refs circulaires, on regarde si JSON.stringify plante,
// pas génial mais évite de lancer une récursion infinie, à pas si cher (et dump est vraiment rarement utilisé en prod)
try {
JSON.stringify(obj[p])
pile.push(p + ': ' + dump(obj[p], indent))
} catch (error) {
pile.push(p + ': "' + error.toString().replace('"', '\\"') + '"')
}
}
}
if (nbp) return '{\n' + innerPrefix + pile.join(',\n' + innerPrefix) + '\n' + prefix + '}'
else if (tools.isObjectPlain(obj)) return prefix + '{}'
else return prefix + obj.toString()
} else {
console.error('dump est tombé sur un truc qui ne ressemble à rien de connu', obj)
return tools.stringify(obj, 2)
}
}
}