| /** |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| 'License'); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| http://www.apache.org/licenses/LICENSE-2.0 |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| var pbxProj = require('./pbxProject'), |
| util = require('util'), |
| f = util.format, |
| INDENT = '\t', |
| COMMENT_KEY = /_comment$/, |
| QUOTED = /^"(.*)"$/, |
| EventEmitter = require('events').EventEmitter |
| |
| // indentation |
| function i(x) { |
| if (x <=0) |
| return ''; |
| else |
| return INDENT + i(x-1); |
| } |
| |
| function comment(key, parent) { |
| var text = parent[key + '_comment']; |
| |
| if (text) |
| return text; |
| else |
| return null; |
| } |
| |
| // copied from underscore |
| function isObject(obj) { |
| return obj === Object(obj) |
| } |
| |
| function isArray(obj) { |
| return Array.isArray(obj) |
| } |
| |
| function pbxWriter(contents, options) { |
| if (!options) { |
| options = {} |
| } |
| if (options.omitEmptyValues === undefined) { |
| options.omitEmptyValues = false |
| } |
| |
| this.contents = contents; |
| this.sync = false; |
| this.indentLevel = 0; |
| this.omitEmptyValues = options.omitEmptyValues |
| } |
| |
| util.inherits(pbxWriter, EventEmitter); |
| |
| pbxWriter.prototype.write = function (str) { |
| var fmt = f.apply(null, arguments); |
| |
| if (this.sync) { |
| this.buffer += f("%s%s", i(this.indentLevel), fmt); |
| } else { |
| // do stream write |
| } |
| } |
| |
| pbxWriter.prototype.writeFlush = function (str) { |
| var oldIndent = this.indentLevel; |
| |
| this.indentLevel = 0; |
| |
| this.write.apply(this, arguments) |
| |
| this.indentLevel = oldIndent; |
| } |
| |
| pbxWriter.prototype.writeSync = function () { |
| this.sync = true; |
| this.buffer = ""; |
| |
| this.writeHeadComment(); |
| this.writeProject(); |
| |
| return this.buffer; |
| } |
| |
| pbxWriter.prototype.writeHeadComment = function () { |
| if (this.contents.headComment) { |
| this.write("// %s\n", this.contents.headComment) |
| } |
| } |
| |
| pbxWriter.prototype.writeProject = function () { |
| var proj = this.contents.project, |
| key, cmt, obj; |
| |
| this.write("{\n") |
| |
| if (proj) { |
| this.indentLevel++; |
| |
| for (key in proj) { |
| // skip comments |
| if (COMMENT_KEY.test(key)) continue; |
| |
| cmt = comment(key, proj); |
| obj = proj[key]; |
| |
| if (isArray(obj)) { |
| this.writeArray(obj, key) |
| } else if (isObject(obj)) { |
| this.write("%s = {\n", key); |
| this.indentLevel++; |
| |
| if (key === 'objects') { |
| this.writeObjectsSections(obj) |
| } else { |
| this.writeObject(obj) |
| } |
| |
| this.indentLevel--; |
| this.write("};\n"); |
| } else if (this.omitEmptyValues && (obj === undefined || obj === null)) { |
| continue; |
| } else if (cmt) { |
| this.write("%s = %s /* %s */;\n", key, obj, cmt) |
| } else { |
| this.write("%s = %s;\n", key, obj) |
| } |
| } |
| |
| this.indentLevel--; |
| } |
| |
| this.write("}\n") |
| } |
| |
| pbxWriter.prototype.writeObject = function (object) { |
| var key, obj, cmt; |
| |
| for (key in object) { |
| if (COMMENT_KEY.test(key)) continue; |
| |
| cmt = comment(key, object); |
| obj = object[key]; |
| |
| if (isArray(obj)) { |
| this.writeArray(obj, key) |
| } else if (isObject(obj)) { |
| this.write("%s = {\n", key); |
| this.indentLevel++; |
| |
| this.writeObject(obj) |
| |
| this.indentLevel--; |
| this.write("};\n"); |
| } else { |
| if (this.omitEmptyValues && (obj === undefined || obj === null)) { |
| continue; |
| } else if (cmt) { |
| this.write("%s = %s /* %s */;\n", key, obj, cmt) |
| } else { |
| this.write("%s = %s;\n", key, obj) |
| } |
| } |
| } |
| } |
| |
| pbxWriter.prototype.writeObjectsSections = function (objects) { |
| var first = true, |
| key, obj; |
| |
| for (key in objects) { |
| if (!first) { |
| this.writeFlush("\n") |
| } else { |
| first = false; |
| } |
| |
| obj = objects[key]; |
| |
| if (isObject(obj)) { |
| this.writeSectionComment(key, true); |
| |
| this.writeSection(obj); |
| |
| this.writeSectionComment(key, false); |
| } |
| } |
| } |
| |
| pbxWriter.prototype.writeArray = function (arr, name) { |
| var i, entry; |
| |
| this.write("%s = (\n", name); |
| this.indentLevel++; |
| |
| for (i=0; i < arr.length; i++) { |
| entry = arr[i] |
| |
| if (entry.value && entry.comment) { |
| this.write('%s /* %s */,\n', entry.value, entry.comment); |
| } else if (isObject(entry)) { |
| this.write('{\n'); |
| this.indentLevel++; |
| |
| this.writeObject(entry); |
| |
| this.indentLevel--; |
| this.write('},\n'); |
| } else { |
| this.write('%s,\n', entry); |
| } |
| } |
| |
| this.indentLevel--; |
| this.write(");\n"); |
| } |
| |
| pbxWriter.prototype.writeSectionComment = function (name, begin) { |
| if (begin) { |
| this.writeFlush("/* Begin %s section */\n", name) |
| } else { // end |
| this.writeFlush("/* End %s section */\n", name) |
| } |
| } |
| |
| pbxWriter.prototype.writeSection = function (section) { |
| var key, obj, cmt; |
| |
| // section should only contain objects |
| for (key in section) { |
| if (COMMENT_KEY.test(key)) continue; |
| |
| cmt = comment(key, section); |
| obj = section[key] |
| |
| if (obj.isa == 'PBXBuildFile' || obj.isa == 'PBXFileReference') { |
| this.writeInlineObject(key, cmt, obj); |
| } else { |
| if (cmt) { |
| this.write("%s /* %s */ = {\n", key, cmt); |
| } else { |
| this.write("%s = {\n", key); |
| } |
| |
| this.indentLevel++ |
| |
| this.writeObject(obj) |
| |
| this.indentLevel-- |
| this.write("};\n"); |
| } |
| } |
| } |
| |
| pbxWriter.prototype.writeInlineObject = function (n, d, r) { |
| var output = []; |
| var self = this |
| |
| var inlineObjectHelper = function (name, desc, ref) { |
| var key, cmt, obj; |
| |
| if (desc) { |
| output.push(f("%s /* %s */ = {", name, desc)); |
| } else { |
| output.push(f("%s = {", name)); |
| } |
| |
| for (key in ref) { |
| if (COMMENT_KEY.test(key)) continue; |
| |
| cmt = comment(key, ref); |
| obj = ref[key]; |
| |
| if (isArray(obj)) { |
| output.push(f("%s = (", key)); |
| |
| for (var i=0; i < obj.length; i++) { |
| output.push(f("%s, ", obj[i])) |
| } |
| |
| output.push("); "); |
| } else if (isObject(obj)) { |
| inlineObjectHelper(key, cmt, obj) |
| } else if (self.omitEmptyValues && (obj === undefined || obj === null)) { |
| continue; |
| } else if (cmt) { |
| output.push(f("%s = %s /* %s */; ", key, obj, cmt)) |
| } else { |
| output.push(f("%s = %s; ", key, obj)) |
| } |
| } |
| |
| output.push("}; "); |
| } |
| |
| inlineObjectHelper(n, d, r); |
| |
| this.write("%s\n", output.join('').trim()); |
| } |
| |
| module.exports = pbxWriter; |