Created
February 13, 2012 19:35
-
-
Save shimondoodkin/1819395 to your computer and use it in GitHub Desktop.
json database for node.js , preserves recursive data structures. may need a cleanup a little bit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Module dependencies. | |
| */ | |
| var express = require('express') | |
| , routes = require('./routes') | |
| var app = module.exports = express.createServer(); | |
| // Configuration | |
| app.configure(function(){ | |
| app.set('views', __dirname + '/views'); | |
| app.set('view engine', 'ejs'); | |
| app.use(express.bodyParser()); | |
| app.use(express.methodOverride()); | |
| app.use(app.router); | |
| app.use(express.static(__dirname + '/public')); | |
| }); | |
| app.configure('development', function(){ | |
| app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); | |
| }); | |
| app.configure('production', function(){ | |
| app.use(express.errorHandler()); | |
| }); | |
| // Routes | |
| app.get('/', routes.index); | |
| app.get('/run', routes.run); | |
| app.listen(3000); | |
| console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); | |
| process.on('uncaughtException', function (err) { | |
| console.log('Caught exception: ' + err.stack); | |
| }); | |
| function handleexit(cb) | |
| { | |
| var f=require.resolve('./get.js'); | |
| if(require.cache[f]) | |
| { | |
| //console.log('a',require.cache[f]); | |
| if(require.cache[f].exports.unload) | |
| require.cache[f].exports.unload(cb) | |
| else | |
| if(cb)cb(); | |
| } | |
| else | |
| if(cb)cb(); | |
| } | |
| process.on('SIGTERM', function () { | |
| console.log('Got SIGTERM, will exit in 10 seconds '); | |
| var num=1; | |
| var n=setInterval(function(){ | |
| console.log(num) | |
| num++; | |
| },1000); | |
| var c=setTimeout(function(){ | |
| if(n)clearTimeout(n); | |
| process.exit(0); | |
| },10000) | |
| handleexit(function(){ | |
| if(c)clearTimeout(c); | |
| if(n)clearTimeout(n); | |
| process.exit(0); | |
| }) | |
| }); | |
| process.on('SIGINT', function () { | |
| console.log('Got SIGINT, will exit in 10 seconds '); | |
| var num=1; | |
| var n=setInterval(function(){ | |
| console.log(num) | |
| num++; | |
| },1000); | |
| var c=setTimeout(function(){ | |
| if(n)clearTimeout(n); | |
| process.exit(0); | |
| },10000) | |
| handleexit(function(){ | |
| if(c)clearTimeout(c); | |
| if(n)clearTimeout(n); | |
| process.exit(0); | |
| }) | |
| }); | |
| // var f=require.resolve('../../get.js');if(require.cache[f]){if(require.cache[f].unload) require.cache[f].unload()}delete require.cache[f];f=require(f); | |
| // f.run(req,res); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| exports.querystring=require('querystring'); | |
| var EventEmitter = require('events').EventEmitter; | |
| EventEmitter.prototype._maxListeners=1000; | |
| exports.unload=function(cb) | |
| { | |
| if(cb)cb(); | |
| } | |
| ///////////string between: | |
| String.prototype.between = function(prefix, suffix) { | |
| var r,s,pl,sl,e; | |
| if(prefix instanceof RegExp) | |
| { | |
| r=prefix.exec(this); | |
| if(r==null)s=-1; else s=r.index; | |
| pl=r[0].length | |
| } | |
| else | |
| { | |
| s = this.indexOf(prefix); | |
| pl= prefix.length | |
| } | |
| if (s == -1) { return ' error:between-no-start '; } | |
| if(suffix instanceof RegExp) | |
| { | |
| r=suffix.exec(this.substring(s+pl,this.length)); | |
| if(r==null) e=-1; else e=r.index+s+pl; | |
| sl=r[0].length | |
| } | |
| else | |
| { | |
| e = this.indexOf(suffix,s+pl); | |
| sl= suffix.length | |
| } | |
| if (e == -1) { return ' error:between-no-end '; } | |
| return this.substring(s+pl, e);//e | |
| } | |
| String.prototype.php_split=function explode (delimiter, limit) { | |
| var string=this.valueOf(); | |
| // Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. | |
| // | |
| // version: 1109.2015 | |
| // discuss at: http://phpjs.org/functions/explode | |
| // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) | |
| // + improved by: kenneth | |
| // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) | |
| // + improved by: d3x | |
| // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) | |
| // * example 1: explode(' ', 'Kevin van Zonneveld'); | |
| // * returns 1: {0: 'Kevin', 1: 'van', 2: 'Zonneveld'} | |
| // * example 2: explode('=', 'a=bc=d', 2); | |
| // * returns 2: ['a', 'bc=d'] | |
| var emptyArray = { | |
| 0: '' | |
| }; | |
| // third argument is not required | |
| if (arguments.length < 2 || typeof arguments[0] == 'undefined' || typeof arguments[1] == 'undefined') { | |
| return null; | |
| } | |
| if (delimiter === '' || delimiter === false || delimiter === null) { | |
| return false; | |
| } | |
| if (typeof delimiter == 'function' || typeof delimiter == 'object' || typeof string == 'function' || typeof string == 'object') { | |
| return emptyArray; | |
| } | |
| if (delimiter === true) { | |
| delimiter = '1'; | |
| } | |
| if (!limit) { | |
| return string.toString().split(delimiter.toString()); | |
| } | |
| // support for limit argument | |
| var splitted = string.toString().split(delimiter.toString()); | |
| var partA = splitted.splice(0, limit - 1); | |
| var partB = splitted.join(delimiter.toString()); | |
| partA.push(partB); | |
| return partA; | |
| } | |
| String.prototype.betweeninc = function(prefix, suffix) { | |
| var r,s,pl,sl,e; | |
| if(prefix instanceof RegExp) | |
| { | |
| r=prefix.exec(this); | |
| if(r==null)s=-1; else s=r.index; | |
| pl=r[0].length | |
| } | |
| else | |
| { | |
| s = this.indexOf(prefix); | |
| pl= prefix.length | |
| } | |
| if (s == -1) { return ' error:between-no-start '; } | |
| if(suffix instanceof RegExp) | |
| { | |
| r=suffix.exec(this.substring(s+pl,this.length)); | |
| if(r==null) e=-1; else e=r.index+s+pl; | |
| sl=r[0].length | |
| } | |
| else | |
| { | |
| e = this.indexOf(suffix,s+pl); | |
| sl= suffix.length | |
| } | |
| if (e == -1) { return ' error:between-no-end '; } | |
| return this.substring(s, e+sl);//e | |
| } | |
| String.prototype.cuttailof = function(prefix) { | |
| var s = this.indexOf(prefix); | |
| if (s == -1) { return ' error:cuttailfrom-no-start '; } | |
| return this.substring(0,s+prefix.length); | |
| } | |
| String.prototype.cuttailofinc = function(prefix) { | |
| var s = this.indexOf(prefix); | |
| if (s == -1) { return ' error:cuttailfrominc-no-start '; } | |
| return this.substring(0,s); | |
| } | |
| String.prototype.cuttailfrom = function(prefix) { | |
| var s = this.lastIndexOf(prefix); | |
| if (s == -1) { return ' error:cuttailfrom-no-start '; } | |
| return this.substring(0,s+prefix.length); | |
| } | |
| String.prototype.cuttailfrominc = function(prefix) { | |
| var s = this.lastIndexOf(prefix); | |
| if (s == -1) { return ' error:cuttailfrominc-no-start '; } | |
| return this.substring(0,s); | |
| } | |
| String.prototype.cutheadfrom = function(suffix) { | |
| var e = this.indexOf(suffix); | |
| if (e == -1) { return ' error:cutheadfrom-no-end '; } | |
| return this.substring(e); | |
| } | |
| String.prototype.cutheadfrominc = function(suffix) { | |
| var e = this.indexOf(suffix); | |
| if (e == -1) { return ' error:cutheadfrominc-no-end '; } | |
| return this.substring(e+suffix.length); | |
| } | |
| String.prototype.pad = String.prototype.pad || function(len, chr, dir) { | |
| var str = this.valueOf(); | |
| len = (typeof len == 'number') ? len : 0; | |
| chr = (typeof chr == 'string') ? chr : ' '; | |
| dir = (/left|right|both/i).test(dir) ? dir : 'right'; | |
| var repeat = function(c, l) { // inner "character" and "length" | |
| var repeat = ''; | |
| while (repeat.length < l) { | |
| repeat += c; | |
| } | |
| return repeat.substr(0, l); | |
| } | |
| var diff = len - str.length; | |
| if (diff > 0) { | |
| switch (dir) { | |
| case 'left': | |
| str = '' + repeat(chr, diff) + str; | |
| break; | |
| case 'both': | |
| var half = repeat(chr, Math.ceil(diff / 2)); | |
| str = (half + str + half).substr(1, len); | |
| break; | |
| default: // and "right" | |
| str = '' + str + repeat(chr, diff); | |
| } | |
| } | |
| return str; | |
| }; | |
| Number.prototype.pad = Number.prototype.pad || String.prototype.pad; | |
| String.prototype.repeat = String.prototype.repeat || function(count) { | |
| if (count < 1) return ''; | |
| var result = '', pattern = this.valueOf(); | |
| while (count > 0) { | |
| if (count & 1) result += pattern; | |
| count >>= 1, pattern += pattern; | |
| }; | |
| return result; | |
| }; | |
| Number.prototype.escapeHtml=String.prototype.escapeHtml=function escapeHtml() { | |
| return this.valueOf() | |
| .replace(/&/g, "&") | |
| .replace(/</g, "<") | |
| .replace(/>/g, ">") | |
| .replace(/"/g, """) | |
| .replace(/'/g, "'"); | |
| } | |
| ////////////object clone: | |
| var ce=require('cloneextend'); // npm install cloneextend | |
| //console.log({aa:'bb',dd:new Date('10/10/2011')}); | |
| //console.log(ce.clone({aa:'bb',dd:new Date('10/10/2011')})); | |
| exports.clone=ce.clone; | |
| exports.extend=ce.extend; | |
| Object.prototype.clone = function (name,recourlist,recourvalues) | |
| { | |
| var srcInstance=this; | |
| if( srcInstance == null || typeof(srcInstance) != 'object' ) | |
| return srcInstance; | |
| if( srcInstance instanceof Date ) | |
| { | |
| var newInstance = new srcInstance.constructor(); | |
| newInstance.setTime(srcInstance.getTime()) | |
| return newInstance ; | |
| } | |
| else if( srcInstance instanceof Number || srcInstance instanceof String || srcInstance instanceof Boolean ) | |
| { | |
| return srcInstance.valueOf(); | |
| } | |
| if(!(recourlist instanceof Array))recourlist=[]; | |
| var newInstance = srcInstance.constructor(); | |
| for(var i in srcInstance) | |
| if(srcInstance.hasOwnProperty(i)) | |
| //newInstance[i] = clone.call(srcInstance[i],i); | |
| newInstance[i] = arguments.callee.call(srcInstance[i],i); | |
| return newInstance; | |
| } | |
| //////////// | |
| /* | |
| * Date Format 1.2.3 | |
| * (c) 2007-2009 Steven Levithan <stevenlevithan.com> | |
| * MIT license | |
| * | |
| * Includes enhancements by Scott Trenda <scott.trenda.net> | |
| * and Kris Kowal <cixar.com/~kris.kowal/> | |
| * | |
| * Accepts a date, a mask, or a date and a mask. | |
| * Returns a formatted version of the given date. | |
| * The date defaults to the current date/time. | |
| * The mask defaults to dateFormat.masks.default. | |
| */ | |
| var dateFormat = function () { | |
| var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, | |
| timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, | |
| timezoneClip = /[^-+\dA-Z]/g, | |
| pad = function (val, len) { | |
| val = String(val); | |
| len = len || 2; | |
| while (val.length < len) val = "0" + val; | |
| return val; | |
| }; | |
| // Regexes and supporting functions are cached through closure | |
| return function (date, mask, utc) { | |
| var dF = dateFormat; | |
| // You can't provide utc if you skip other args (use the "UTC:" mask prefix) | |
| if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { | |
| mask = date; | |
| date = undefined; | |
| } | |
| // Passing date through Date applies Date.parse, if necessary | |
| date = date ? new Date(date) : new Date; | |
| if (isNaN(date)) throw SyntaxError("invalid date"); | |
| mask = String(dF.masks[mask] || mask || dF.masks["default"]); | |
| // Allow setting the utc argument via the mask | |
| if (mask.slice(0, 4) == "UTC:") { | |
| mask = mask.slice(4); | |
| utc = true; | |
| } | |
| var _ = utc ? "getUTC" : "get", | |
| d = date[_ + "Date"](), | |
| D = date[_ + "Day"](), | |
| m = date[_ + "Month"](), | |
| y = date[_ + "FullYear"](), | |
| H = date[_ + "Hours"](), | |
| M = date[_ + "Minutes"](), | |
| s = date[_ + "Seconds"](), | |
| L = date[_ + "Milliseconds"](), | |
| o = utc ? 0 : date.getTimezoneOffset(), | |
| flags = { | |
| d: d, | |
| dd: pad(d), | |
| ddd: dF.i18n.dayNames[D], | |
| dddd: dF.i18n.dayNames[D + 7], | |
| m: m + 1, | |
| mm: pad(m + 1), | |
| mmm: dF.i18n.monthNames[m], | |
| mmmm: dF.i18n.monthNames[m + 12], | |
| yy: String(y).slice(2), | |
| yyyy: y, | |
| h: H % 12 || 12, | |
| hh: pad(H % 12 || 12), | |
| H: H, | |
| HH: pad(H), | |
| M: M, | |
| MM: pad(M), | |
| s: s, | |
| ss: pad(s), | |
| l: pad(L, 3), | |
| L: pad(L > 99 ? Math.round(L / 10) : L), | |
| t: H < 12 ? "a" : "p", | |
| tt: H < 12 ? "am" : "pm", | |
| T: H < 12 ? "A" : "P", | |
| TT: H < 12 ? "AM" : "PM", | |
| Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), | |
| o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), | |
| S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] | |
| }; | |
| return mask.replace(token, function ($0) { | |
| return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); | |
| }); | |
| }; | |
| }(); | |
| // Some common format strings | |
| dateFormat.masks = { | |
| "default": "ddd mmm dd yyyy HH:MM:ss", | |
| shortDate: "m/d/yy", | |
| mediumDate: "mmm d, yyyy", | |
| longDate: "mmmm d, yyyy", | |
| fullDate: "dddd, mmmm d, yyyy", | |
| shortTime: "h:MM TT", | |
| mediumTime: "h:MM:ss TT", | |
| longTime: "h:MM:ss TT Z", | |
| isoDate: "yyyy-mm-dd", | |
| isoTime: "HH:MM:ss", | |
| isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", | |
| isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'", | |
| isoRFC: "ddd, d mmm yyyy HH:MM:ss o" | |
| }; | |
| // Internationalization strings | |
| dateFormat.i18n = { | |
| dayNames: [ | |
| "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", | |
| "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" | |
| ], | |
| monthNames: [ | |
| "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", | |
| "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" | |
| ] | |
| }; | |
| // For convenience... | |
| Date.prototype.format = function (mask, utc) { | |
| return dateFormat(this, mask, utc); | |
| }; | |
| ////////////html parsing tools | |
| var htmlparser = require("htmlparser2"); | |
| function parsehtml(data,cb) | |
| { | |
| var handler = new htmlparser.DefaultHandler(function (error, dom) {cb(error,[data,dom]);}); | |
| var parser = new htmlparser.Parser(handler); | |
| parser.write(data); | |
| parser.done(); | |
| }exports.parsehtml=parsehtml; | |
| function decode_entities(s) | |
| { | |
| if(s==undefined)return ""; | |
| return s.replace( /\&/g, '&' ).replace( /\ /g, ' ' ).replace( /\"/g, '"' ).trim(); | |
| }exports.decode_entities=decode_entities; | |
| var rxparams=/\s*([^\s=]+)\s*=\s*'([^']*)'|\s*([^\s=]+)\s*=\s*"([^"]*)"|\s*([^\s=]+)\s*=\s*([^\s>]+)\s*|\s*([^>\s]+)\s*/gmi; | |
| function parse_params(str) | |
| { | |
| var params={},m; | |
| if(str) | |
| while((m=rxparams.exec(str))!==null) | |
| { | |
| //console.log(m) | |
| //params.exec("a=aa b='bb' c=\"\" d") | |
| if(m[1]!=undefined) | |
| p=[ | |
| m[1], // 'b', | |
| m[2], // 'bb', | |
| "'" | |
| ] | |
| //console.log(p) | |
| if(m[3]!=undefined) | |
| p=[ | |
| m[3],// 'c', | |
| m[4],// '', | |
| '"' | |
| ] | |
| //console.log(p) | |
| if(m[5]!=undefined) | |
| p=[ | |
| m[5],// 'a', | |
| m[6],// 'aa', | |
| "" | |
| ] | |
| //console.log(p) | |
| if(m[7]!=undefined) | |
| p=[ | |
| m[7],// 'd', | |
| true, | |
| "novalue" | |
| ] | |
| //console.log(p) | |
| if(typeof p[1]=="boolean") | |
| params[decode_entities(p[0].toLowerCase())]=p[1]; | |
| else | |
| params[decode_entities(p[0].toLowerCase())]=decode_entities(p[1]); | |
| //allp.push(p); | |
| }//while tags | |
| return params; | |
| } | |
| var inputrxtags=/<input(\s*(\s*[^\s=]+\s*=\s*'[^']*'|\s*[^\s=]+\s*=\s*"[^"]*"|\s*[^\s=]+\s*=\s*[^\s>]+\s*|\s*[^>\s]+\s*)*\s*)>/gmi; | |
| function get_input_tags(data) | |
| { | |
| var tags=[],t; | |
| while((t=inputrxtags.exec(data))!==null) | |
| { | |
| tags.push(parse_params(t[1])) | |
| //all.push([t[0],t[1],allp]) | |
| }//while tag | |
| return tags; | |
| } | |
| exports.get_input_tags=get_input_tags; | |
| //get_input_tags("<INPUT AAA=\"XXX\" sss='aa'><input ff=xx ><input ddd=\"\" ><input cc >") | |
| function getform(data,formname) | |
| { | |
| data=data.between(new RegExp("<form.*"+formname+".*>","im"),"</form>"); | |
| var inputs=get_input_tags(data); | |
| inputs=inputs.filter(function(i) | |
| { | |
| if(!i.name||i.name=='') return false; | |
| if(i.type=='checkbox') | |
| { | |
| if(i.checked) | |
| return true; | |
| else | |
| return false; | |
| } | |
| else | |
| { | |
| return true; | |
| } | |
| }); | |
| var re_num=/^[-]{0,1}\d+[\.]{0,1}\d*$/ | |
| var a={};inputs.forEach(function(i) | |
| { | |
| a[i.name]=i.value==undefined?(i.type.toLowerCase()=='checkbox'?'on':''):( re_num.test(i.value)?parseFloat(i.value):i.value ); | |
| }); | |
| inputs=a; | |
| return inputs; | |
| }exports.getform=getform; | |
| function getformtag(data,formname) | |
| { | |
| var rxtags=new RegExp("<form(.*"+formname+".*)>","im"); | |
| var t; | |
| while((t=rxtags.exec(data))!==null) | |
| { | |
| return parse_params(t[1]); | |
| }; | |
| return {notfound:true}; | |
| }exports.getformtag=getformtag; | |
| function printpaths(name,obj) | |
| { | |
| var re_num=/^\d+$/, re_validname=/^[a-zA-Z][a-zA-Z0-9]*$/; | |
| function smartjoin(a) | |
| { | |
| var s=''; | |
| for(var i=0;i<a.length;i++) | |
| { | |
| if( re_num.test(a[i]) ) | |
| s+='['+a[i]+']' | |
| else if( re_validname.test(a[i]) ) | |
| s+=(i>0?'.':'')+a[i] | |
| else | |
| { | |
| s+='['; | |
| try{s+=JSON.stringify(a[i])}catch(e){s+='error'} | |
| s+=']'; | |
| } | |
| } | |
| return s; | |
| } | |
| var t="",s=[name],printed=[]; | |
| function recur(o) | |
| { | |
| if(printed.indexOf(o)==-1) | |
| { | |
| printed.push(o) | |
| for(var i in o) | |
| { | |
| if(Object.hasOwnProperty.call(o,i)) | |
| { | |
| s.push(i); | |
| if(o[i] instanceof Array) | |
| recur(o[i]); | |
| else if(typeof o[i] == 'function') | |
| t+=smartjoin(s)+'='+JSON.stringify(o[i].toString())+'\r\n'; | |
| else if(typeof o[i] == 'object') | |
| recur(o[i]); | |
| else | |
| t+=smartjoin(s)+'='+JSON.stringify(o[i])+'\r\n'; | |
| s.pop(); | |
| } | |
| } | |
| } | |
| } | |
| if(obj instanceof Array) | |
| recur(obj); | |
| else if(typeof obj == 'function') | |
| t+=smartjoin(s)+'='+JSON.stringify(obj[i].toString())+'\r\n'; | |
| else if(typeof obj == 'object') | |
| recur(obj); | |
| else | |
| { | |
| t+=smartjoin(s)+'='; | |
| try{ | |
| t+=JSON.stringify(obj)+'\r\n'; | |
| }catch(e){ | |
| t+=':error:'; | |
| } | |
| } | |
| return t; | |
| }exports.printpaths=printpaths; | |
| ////////////request | |
| var request1=require('request'); | |
| var Iconv=require('iconv').Iconv; | |
| var iconv_utf8_to_latin = new Iconv('utf-8','iso-8859-1'); | |
| var iconv_iso8859_8i_to_utf8 = new Iconv('iso-8859-8','utf-8'); | |
| function request(options,cb) | |
| { | |
| if(options.encoding=='iso-8859-8') | |
| { | |
| options.encoding='binary'; | |
| return request1(options, function(error,request,data){ | |
| try{ | |
| var data2=iconv_iso8859_8i_to_utf8.convert(iconv_utf8_to_latin.convert(data)).toString('utf8') //conver buffer to string | |
| } | |
| catch(e) | |
| { | |
| data2=null; | |
| error=e; | |
| } | |
| cb(error,request,data2); | |
| }); | |
| } | |
| else | |
| return request1(options,cb); | |
| } | |
| request.__proto__=request1; | |
| exports.request=request; | |
| ////////////json | |
| function stringify_stats(a,stats,context) | |
| { | |
| var clean_context; | |
| if(typeof a === 'object') | |
| { | |
| if(!context) | |
| { | |
| clean_context=true; | |
| stats=[a]; | |
| context=[]; | |
| } | |
| else | |
| { | |
| a_pos=context.indexOf(a); | |
| if( a_pos!=-1 ) | |
| { | |
| if(stats.indexOf(a)==-1) | |
| { | |
| stats.push(a); | |
| } | |
| return; | |
| } | |
| } | |
| if(context.length>900&&context.length%1000==0) console.log("doing stringify. objects done: "+context.length) | |
| context.push(a); | |
| if (a instanceof Array) | |
| { | |
| for(var l=a.length,key=0;key<l;key++) | |
| { | |
| if(typeof a[key] === 'object' && a[key] !== null) | |
| stringify_stats(a[key], stats, context ); | |
| } | |
| } | |
| else | |
| { | |
| var comma=false | |
| for (key in a) | |
| { | |
| if(Object.prototype.hasOwnProperty.call(a, key)) | |
| { | |
| if(typeof a[key] === 'object' && a[key] !== null) | |
| stringify_stats(a[key],stats,context ); | |
| } | |
| } | |
| } | |
| if(clean_context) | |
| { | |
| delete context; | |
| return stats; | |
| } | |
| } | |
| else | |
| return []; | |
| } | |
| function stringify_var(a,file) | |
| { | |
| if(a === undefined) | |
| { | |
| if(file) | |
| { | |
| file.write('undefined'); | |
| return; | |
| } | |
| else | |
| return 'undefined'; | |
| } | |
| else if(typeof a === 'object' && a === null) | |
| { | |
| if(file) | |
| { | |
| file.write('null'); | |
| return; | |
| } | |
| else | |
| return 'null'; | |
| } | |
| else if(typeof a === 'function') | |
| { | |
| if(file) | |
| { | |
| file.write(a.toString()); | |
| return; | |
| } | |
| else | |
| return a.toString(); | |
| } | |
| else if(a instanceof Date) | |
| { | |
| if(file) | |
| { | |
| file.write('new Date("'+a.toString()+'")'); | |
| return; | |
| } | |
| else | |
| return 'new Date("'+a.toString()+'")'; | |
| } | |
| else | |
| { | |
| if(file) | |
| file.write(JSON.stringify(a)); | |
| else | |
| return JSON.stringify(a); | |
| } | |
| } | |
| function stringify(a ,varname,prefix ,sufix,file,callback,context,stats ) | |
| { | |
| var out,clean_context; | |
| if(typeof a !== 'object') | |
| { | |
| if(file) | |
| file.write(JSON.stringify(a)) | |
| else | |
| out=JSON.stringify(a); | |
| return out; | |
| } | |
| else | |
| { | |
| if(context===undefined) | |
| { | |
| clean_context=true; | |
| if(!varname) varname='self'; | |
| if(!prefix) prefix=''; | |
| if(!sufix) sufix=''; | |
| context=[]; | |
| stats=stringify_stats(a); // find used self references | |
| //console.log('stats done'); | |
| // put the first element and the stack in. | |
| out=prefix+'var '+varname+'_temp=[],'+varname+'='+varname+'_temp[0]='; | |
| if(file)file.write(out); | |
| } | |
| else | |
| { | |
| out=""; | |
| a_pos=context.indexOf(a); | |
| if( a_pos!=-1 ) | |
| { | |
| a_pos=stats.indexOf(a); | |
| if( a_pos!=-1 ) | |
| { | |
| if(file){file.write(varname+"_temp["+a_pos+"]"); return;} | |
| else | |
| return varname+"_temp["+a_pos+"]"; | |
| } | |
| } | |
| else | |
| { | |
| a_pos=stats.indexOf(a); | |
| if( a_pos!=-1 ) | |
| { | |
| if(file) | |
| file.write(varname+"_temp["+a_pos+"]="); | |
| else | |
| out+=varname+"_temp["+a_pos+"]="; | |
| } | |
| } | |
| } | |
| if(context.length>900&&context.length%1000==0) console.log(context.length) | |
| context.push(a); | |
| var do_stringify_var=false; | |
| if (a instanceof Array) | |
| { | |
| if(file) | |
| file.write("["); | |
| else | |
| out+="["; | |
| for(var l=a.length,key=0;key<l;key++) | |
| { | |
| if(key!=0) | |
| { | |
| if(file) | |
| file.write(","); | |
| else | |
| out+=','; | |
| } | |
| do_stringify_var=false; | |
| if(typeof a[key] === 'object') | |
| { | |
| if( a[key] === null ) | |
| { | |
| do_stringify_var=true; | |
| } | |
| else if( a[key].constructor.name==='Object' || a[key] instanceof Array ) | |
| { | |
| if(file) | |
| stringify(a[key],varname,null,null,file,null,context,stats ); | |
| else | |
| out+=stringify(a[key],varname,null,null,file,null,context,stats ); | |
| } | |
| else | |
| { | |
| do_stringify_var=true; | |
| } | |
| } | |
| else | |
| { | |
| do_stringify_var=true; | |
| } | |
| if(do_stringify_var) | |
| { | |
| if(file) | |
| stringify_var(a[key],file); | |
| else | |
| out+=stringify_var(a[key]); | |
| } | |
| } | |
| if(file) | |
| file.write(']'); | |
| else | |
| out+=']'; | |
| } | |
| else | |
| { | |
| if(file) | |
| file.write('{'); | |
| else | |
| out+="{"; | |
| var comma=false | |
| for (key in a) | |
| { | |
| if(Object.prototype.hasOwnProperty.call(a, key)) | |
| { | |
| if(comma) | |
| { | |
| if(file) | |
| file.write(','); | |
| else | |
| out+=','; | |
| } | |
| else | |
| comma=true; | |
| if(file) | |
| { | |
| file.write(JSON.stringify(key)); | |
| file.write(':'); | |
| } | |
| else | |
| { | |
| out+=JSON.stringify(key); | |
| out+=':'; | |
| } | |
| do_stringify_var=false; | |
| if(typeof a[key] === 'object') | |
| { | |
| if( a[key] === null ) | |
| { | |
| do_stringify_var=true; | |
| } | |
| else if( a[key].constructor.name==='Object' || a[key] instanceof Array ) | |
| { | |
| if(file) | |
| stringify(a[key],varname,null,null,file,null,context,stats ); | |
| else | |
| out+=stringify(a[key],varname,null,null,file,null,context,stats ); | |
| } | |
| else | |
| { | |
| do_stringify_var=true; | |
| } | |
| } | |
| else | |
| { | |
| do_stringify_var=true; | |
| } | |
| if(do_stringify_var) | |
| { | |
| if(file) | |
| stringify_var(a[key],file); | |
| else | |
| out+=stringify_var(a[key]); | |
| } | |
| } | |
| } | |
| if(file) | |
| file.write('}'); | |
| else | |
| out+="}"; | |
| } | |
| if(clean_context) | |
| { | |
| delete context; | |
| delete stats; | |
| if(file) | |
| file.write(";delete "+varname+'_temp;'+sufix); | |
| else | |
| out+=";delete "+varname+'_temp;'+sufix; | |
| //console.log('stringify done'); | |
| if(callback)callback(); | |
| } | |
| } | |
| return out; | |
| } | |
| exports.stringify=stringify; // a very good function it preserves recursive data structure, but returns regular javascript, not json. | |
| var fs=require('fs'); | |
| exports.fs=fs; | |
| var path=require('path'); | |
| function save_json( object, filename, callback ) | |
| { | |
| if(!filename) throw new Error("No filename defined (wrong arguments)"); | |
| file = fs.createWriteStream(filename,{ 'flags': 'w+', /*'encoding': 'utf-8',*/ 'mode': 0777}); | |
| stringify(object,"obj","","module.exports=obj;",file, function(){ | |
| file.end(); | |
| if(callback)callback(); | |
| }); | |
| }exports.save_json=save_json; | |
| function load_json( object, filename) | |
| { | |
| // to prevent saving the source of the loaded file in memory | |
| // load the file, clone the object and return the cloned object | |
| // then unload the module | |
| if(!filename) throw new Error("No filename defined (wrong arguments)"); | |
| if(!path.existsSync(filename)) return object; | |
| var f=require.resolve(filename); | |
| var o=require(f); | |
| var oo=ce.clone(o);// clone it is a prototyped function from above | |
| delete o; | |
| if(require.cache[f])delete require.cache[f]; | |
| //if(callback)callback(); | |
| //else | |
| return oo; | |
| }exports.load_json=load_json; | |
| /// simple in memory json database | |
| var database={}; | |
| exports.database=database; | |
| exports.database_dir=__dirname+'/database'; | |
| function load_data(name,default_object) | |
| { | |
| if(database[name]) return; | |
| var file=path.resolve(exports.database_dir,name+'.js'); | |
| var d= | |
| { | |
| name:name, | |
| file:file, | |
| last_saved:new Date(), | |
| last_activity:new Date(), | |
| mark:function() | |
| { | |
| this.__proto__.last_activity=new Date(); | |
| }, | |
| save:function(cb) | |
| { | |
| save_data(name,cb) | |
| }, | |
| unload:function(cb) | |
| { | |
| unload_data(name,cb) | |
| } | |
| //,onsave:function(db,cb){ do_something_with(db); if(cb)cb();}; | |
| //,onunload:function(db,cb){ do_something_with(db); if(cb)cb();}; | |
| } | |
| var db=load_json( default_object, file ); | |
| db.__proto__=d; | |
| database[name]=db; | |
| return db; | |
| } | |
| function save_data(name,cb) | |
| { | |
| if(!database.hasOwnProperty(name)) return; | |
| var d=database[name]; | |
| if(d.__proto__.last_activity>d.__proto__.last_saved)// checked 3 times little too much... | |
| { | |
| function save() | |
| { | |
| if(d.__proto__.last_activity>d.__proto__.last_saved) // check again maybe on save modified something | |
| { | |
| save_json( d, d.file, cb ) | |
| d.__proto__.last_saved=new Date(); | |
| } | |
| else | |
| if(cb)cb(); | |
| } | |
| if(d.onsave) | |
| d.onsave(d,save); | |
| else | |
| save(); | |
| } | |
| else | |
| if(cb)cb(); | |
| } | |
| function unload_data(name,cb) | |
| { | |
| if(!database.hasOwnProperty(name)) return; | |
| var d=database[name]; | |
| function unload() | |
| { | |
| save_data(d.name,function(){ | |
| delete database[name]; | |
| if(cb)cb(); | |
| }); | |
| } | |
| if(d.onunload) | |
| d.onunload(d,unlaod); | |
| else | |
| unload(); | |
| } | |
| var async=require('async'); | |
| exports.async=async; | |
| var saveing_data=false; | |
| function saveall_data(cb) | |
| { | |
| if(saveing_data)return; | |
| saveing_data=true; | |
| var loop_keys=Object.keys(database); | |
| function next() | |
| { | |
| if(loop_keys.length>0)loop(); | |
| else | |
| { | |
| saveing_data=false; if(cb)cb(); | |
| } | |
| } | |
| function loop() | |
| { | |
| var name=loop_keys.pop(); | |
| var d=database[name]; | |
| if(d.__proto__.last_activity>d.__proto__.last_saved) | |
| { | |
| save_data(name,next) | |
| } | |
| else | |
| { | |
| next() | |
| } | |
| } | |
| next(); | |
| } | |
| database.__proto__={ | |
| load:load_data, //f.database.load('myname',default_object) | |
| unload:unload_data, //f.database.unload('myname',function cb(){}) | |
| save:save_data, //f.database.save('myname',function cb(){}) | |
| saveall:saveall_data // //f.database.saveall(function cb(){}) | |
| } | |
| // f.database.myname.value=1 | |
| // f.database.myname.mark(); | |
| setInterval(saveall_data,10000); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //create folder database | |
| var f=require('./functions.js') | |
| f.loadall_data(); | |
| f.database.load('test',{newval:1}); | |
| console.log(f.database.test); | |
| f.database.test.gg=6 | |
| console.log(f.database.test); | |
| f.database.test.mark(); // mark to save later in10 seconds, call it each time you modify something. | |
| f.database.test.save(); | |
| f.database.saveall(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment