Added significantly improved platform support.

Reviewed by me.
This commit is contained in:
Francisco Tolmasky committed 2009-03-16 07:10:42 -07:00
1 parent 409fab31e6
commit b3cc75fe46
13 files changed
+159 -511

No files matched your search

+3 -2
View File
@@ -32,7 +32,8 @@ Specs[:AppKitDebug] = ObjectiveJ::BundleSpecification.new do |s|
s.license = ObjectiveJ::License::LGPL_v2_1
s.build_path = File.join($BUILD_DIR, 'Debug', 'AppKit')
s.intermediates_path = File.join($BUILD_DIR, 'AppKit.build', 'Debug')
s.flags = ['PLATFORM_DOM', 'DEBUG']
s.flags = ['DEBUG']
s.platforms = [ObjectiveJ::Platform::Browser, ObjectiveJ::Platform::Rhino]
end
bundle Specs[:AppKitDebug], :AppKitDebug
@@ -50,7 +51,7 @@ Specs[:AppKitRelease] = ObjectiveJ::BundleSpecification.new do |s|
s.license = ObjectiveJ::License::LGPL_v2_1
s.build_path = File.join($BUILD_DIR, 'Release', 'AppKit')
s.intermediates_path = File.join($BUILD_DIR, 'AppKit.build', 'Release')
s.flag = 'PLATFORM_DOM'
s.platforms = [ObjectiveJ::Platform::Browser, ObjectiveJ::Platform::Rhino]
end
bundle Specs[:AppKitRelease], :AppKitRelease
-253
View File
@@ -1,253 +0,0 @@
importPackage(java.lang);
importClass(java.io.File);
importClass(java.io.BufferedReader);
importClass(java.io.FileReader);
importClass(java.io.BufferedWriter);
importClass(java.io.FileWriter);
function main()
{
var index = 0,
count = arguments.length,
bundlePath = NULL;
for (; index < count; ++index)
bundlePath = arguments[index];
alert(bundlePath)
var bundleFile = new File(bundlePath).getCanonicalFile(),
bundlePath = String(bundleFile.getCanonicalPath()),
inlinedBundle = readBundle(bundleFile, true),
inlinedFiles = [],
replacedFiles = [],
staticContent = "";
// Find all internal bundles.
var bundleCandidates = getFiles(bundleFile, "plist"),
bundleCandidatesCount = bundleCandidates.length;
while (bundleCandidatesCount--)
{
var bundleCandidate = bundleCandidates[bundleCandidatesCount];
// We only care about Info.plists, specifically the ones that aren't us.
if (String(bundleCandidate.getName()) !== "Info.plist" || String(bundleCandidate.getCanonicalPath()) === inlinedBundle.path)
continue;
var infoDictionary = readPlist(bundleCandidate);
// At least one of these two has to be present for this to be a real deal bundle.
if (!dictionary_getValue(infoDictionary, "CPBundleIdentifier") && !dictionary_getValue(infoDictionary, "CPBundleName"))
continue;
java.lang.System.out.println(" Examining " + pathRelativeTo(bundleCandidate.getCanonicalPath(), bundlePath));
dictionary_removeValue(infoDictionary, "CPBundleExecutable");
var bundle = readBundle(bundleCandidate.getParentFile(), true);
bundle.path = pathRelativeTo(bundle.path, bundlePath);
// We want to inline the info plist too.
var inlinedFiles = [makeOBJJPlistFile(infoDictionary, bundleCandidate, bundle)].concat(bundle.files),
index = 0,
count = inlinedFiles.length;
for (; index < count; ++index)
{
var file = inlinedFiles[index];
file.path = pathRelativeTo(String(file.path), bundlePath);
java.lang.System.out.println(" Inlining " + file.path);
replacedFiles.push(file.path);
staticContent += fileToMarkedString(inlinedFiles[index], true);
}
}
var index = 0,
existingStaticFiles = inlinedBundle.files,
count = existingStaticFiles.length,
topLevelContent = "@STATIC;1.0;";
for (; index < count; ++index)
{
var file = existingStaticFiles[index];
// If this isn't actually part of our bundle, drop it!
if (file.bundle !== inlinedBundle)
continue;
file.path = pathRelativeTo(String(file.path), bundlePath);
replacedFiles.push(file.path);
topLevelContent += fileToMarkedString(file, false);
}
dictionary_setValue(inlinedBundle.info, "CPBundleReplacedFiles", replacedFiles);
writeContentsToFile(CPPropertyListCreateXMLData(inlinedBundle.info).string, inlinedBundle.path);
writeContentsToFile(topLevelContent + staticContent, inlinedBundle._staticContentPath);
}
function fileToMarkedString(anOBJJFile, encodeBundle)
{
var markedString = "";
markedString += MARKER_PATH + ';' + anOBJJFile.path.length + ';' + anOBJJFile.path;
if (encodeBundle)
markedString += MARKER_BUNDLE + ';' + anOBJJFile.bundle.path.length + ';' + anOBJJFile.bundle.path;
var fragments = anOBJJFile.fragments;
if (fragments && fragments.length > 0)
{
var fragmentIndex = 0,
fragmentCount = fragments.length;
for (; fragmentIndex < fragmentCount; ++fragmentIndex)
markedString += fragments[fragmentIndex].toMarkedString();
}
else
markedString += MARKER_TEXT + ';' + anOBJJFile.contents.length + ';' + anOBJJFile.contents;
return markedString;
}
function makeOBJJPlistFile(aDictionary, aFile, aBundle)
{
var file = new objj_file();
file.path = typeof aFile === "string" ? aFile : aFile.getCanonicalPath();
file.bundle = aBundle;
file.contents = CPPropertyListCreate280NorthData(aDictionary).string;
return file;
}
function pathRelativeTo(target, relativeTo)
{
var components = [],
targetParts = target.split("/"),
relativeParts = relativeTo ? relativeTo.split("/") : [];
var i = 0;
while (i < targetParts.length)
{
if (targetParts[i] != relativeParts[i])
break;
i++;
}
for (var j = i; j < relativeParts.length; j++)
components.push("..");
for (var j = i; j < targetParts.length; j++)
components.push(targetParts[j]);
var result = components.join("/");
return result;
}
function readPlist(/*File*/ aFile)
{
var fileContents = readFile(aFile);
var data = new objj_data();
data.string = fileContents;
return new CPPropertyListCreateFromData(data);
}
function readBundle(/*File*/ aFile, /*Boolean*/ shouldDecompile)
{
var bundlePath = typeof aFile === "string" ? new File(aFile).getCanonicalPath() : aFile.getCanonicalPath(),
infoPath = bundlePath + "/Info.plist";
//err
var bundle = new objj_bundle();
bundle.path = infoPath;
bundle.info = readPlist(infoPath);
bundle._staticFilePaths = dictionary_getValue(bundle.info, "CPBundleReplacedFiles");
if (bundle._staticFilePaths.length)
{
bundle._staticContentPath = staticContentPath = bundlePath + '/' + dictionary_getValue(bundle.info, "CPBundleExecutable");
//err
bundle._staticContent = readFile(staticContentPath);
if (shouldDecompile)
bundle.files = objj_decompile(bundle._staticContent, bundle);
}
else
bundle._staticContent = "";
return bundle;
}
function getFiles(/*File*/ sourceDirectory, /*nil|String|Array<String>*/ extensions, /*Array*/ exclusions)
{
var matches = [],
files = sourceDirectory.listFiles(),
hasMultipleExtensions = typeof extensions !== "string";
if (files)
{
var index = 0,
count = files.length;
for (; index < count; ++index)
{
var file = files[index].getCanonicalFile(),
name = String(file.getName()),
isValidExtension = !extensions;
if (exclusions && fileArrayContainsFile(exclusions, file))
continue;
if (!isValidExtension)
if (hasMultipleExtensions)
{
var extensionCount = extensions.length;
while (extensionCount-- && !isValidExtension)
{
var extension = extensions[extensionCount];
if (name.substring(name.length - extension.length - 1) === ("." + extension))
isValidExtension = true;
}
}
else if (name.substring(name.length - extensions.length - 1) === ("." + extensions))
isValidExtension = true;
if (isValidExtension)
matches.push(file);
if (file.isDirectory())
matches = matches.concat(getFiles(file, extensions, exclusions));
}
}
return matches;
}
function writeContentsToFile(/*String*/ contents, /*File*/ aFile)
{
var writer = new BufferedWriter(new FileWriter(aFile));
writer.write(contents);
writer.close();
}
main.apply(main, arguments);
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env ruby
require 'rake'
require '../../../common'
require 'objective-j'
$BUNDLE_SCRIPT = File.join($BUILD_DIR, 'bundle.build', $CONFIGURATION, 'main-concat.js')
$BUNDLE_CLASS = File.join($ENVIRONMENT_LIB_DIR, 'bundle', 'main.class')
$BUNDLE_EXECUTABLE = File.join($ENVIRONMENT_BIN_DIR, 'bundle')
$STANDARD_EXECUTABLE = File.expand_path(File.join('..', 'executable'))
task :build => [$BUNDLE_CLASS, $BUNDLE_EXECUTABLE]
Files = [ File.join($HOME_DIR, 'Tools', 'Utilities', 'bridge.js'), #yuck!
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'Rhino.platform', 'Objective-J.js'),
'main.js'];
file_d $BUNDLE_EXECUTABLE => [$STANDARD_EXECUTABLE] do
cp($STANDARD_EXECUTABLE, $BUNDLE_EXECUTABLE)
File.chmod 0755, $BUNDLE_EXECUTABLE
end
file_d $BUNDLE_SCRIPT => Files do |t|
cat(Files, $BUNDLE_SCRIPT)
end
file_d $BUNDLE_CLASS => $BUNDLE_SCRIPT do |t|
js2java($BUNDLE_SCRIPT, 'main.class', false)
cp(File.join(File.dirname($BUNDLE_SCRIPT), 'main.class'), $BUNDLE_CLASS)
end
+1 -1
View File
@@ -14,7 +14,7 @@ task :build => [$CPLUTIL_CLASS, $CPLUTIL_EXECUTABLE]
Files = [ File.join($HOME_DIR, 'Tools', 'Utilities', 'bridge.js'), #yuck!
File.join($HOME_DIR, 'Tools', 'Utilities', 'regex-bridge.js'), #double-yuck!
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'Rhino.platform', 'Objective-J.js'),
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'rhino.platform', 'Objective-J.js'),
'main.js'];
file_d $CPLUTIL_EXECUTABLE => [$STANDARD_EXECUTABLE] do
+1 -1
View File
@@ -13,7 +13,7 @@ $STANDARD_EXECUTABLE = File.expand_path(File.join('..', 'executable'))
task :build => [$OBJJ_CLASS, $OBJJ_EXECUTABLE]
Files = [ File.join($HOME_DIR, 'Tools', 'Utilities', 'bridge.js'), #yuck!
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'Rhino.platform', 'Objective-J.js'),
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'rhino.platform', 'Objective-J.js'),
'main.js'];
file_d $OBJJ_EXECUTABLE => [$STANDARD_EXECUTABLE] do
+1 -1
View File
@@ -123,7 +123,7 @@ function preprocess(aFilePath, outFilePath, gccArgs, flags)
fragments = objj_preprocess(fileContents, { path:"/x" }, {path:filePath}, flags),
index = 0,
count = fragments.length,
preprocessed = MARKER_PATH + ';' + filePath.length + ';' + filePath;
preprocessed = "";
// Writer preprocessed fragments out.
for (; index < count; ++index)
+1 -1
View File
@@ -15,7 +15,7 @@ task :build => [$OBJJC_CLASS, $OBJJC_EXECUTABLE, $OBJJC_JS_COMPILER]
Files = [ File.join($HOME_DIR, 'Tools', 'Utilities', 'bridge.js'), #yuck!
File.join($HOME_DIR, 'Tools', 'Utilities', 'regex-bridge.js'), #double-yuck!
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'Rhino.platform', 'Objective-J.js'),
File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J', 'rhino.platform', 'Objective-J.js'),
'main.js'];
file_d $OBJJC_EXECUTABLE => [$STANDARD_EXECUTABLE] do
+1 -1
View File
@@ -4,7 +4,7 @@ require 'rake'
require '../../common'
subprojects = %w{bundle cplutil objj objjc}
subprojects = %w{cplutil objj objjc}
%w(build clean).each do |task_name|
task task_name do
+24 -1
View File
@@ -27,6 +27,7 @@
// Look inside bundleResponseCallback.
OBJJ_PLATFORMS = PLATFORMS
#define DIRECTORY(aPath) (aPath).substr(0, (aPath).lastIndexOf('/') + 1)
OBJJFileNotFoundException = "OBJJFileNotFoundException";
@@ -364,6 +365,28 @@ objj_search.prototype.didReceiveBundleResponse = function(aResponse)
if (executablePath)
{
var platform = NULL,
platforms = dictionary_getValue(bundle.info, "CPBundlePlatforms"),
index = 0,
count = OBJJ_PLATFORMS.length,
inner_count = platforms.length;
// Ugh, no indexOf, no objects-in-common.
for(; index < count; ++index)
{
var innerIndex = 0,
currentPlatform = OBJJ_PLATFORMS[index];
for (; innerIndex < inner_count; ++innerIndex)
if(OBJJ_PLATFORMS[index] === platforms[innerIndex])
{
platform = currentPlatform;
break;
}
}
executablePath = platform + ".platform/" + executablePath;
this.request(DIRECTORY(aResponse.filePath) + executablePath, this.didReceiveExecutableResponse);
// FIXME: Is this the right approach?
@@ -581,7 +604,7 @@ function objj_decompile(aString, bundle)
{
case MARKER_PATH: if (file && file.contents && file.path === file.bundle.path)
file.bundle.info = CPPropertyListCreateWithData({string:file.contents});
file = new objj_file();
file.path = DIRECTORY(bundle.path) + text;
file.bundle = bundle;
+8 -4
View File
@@ -10,7 +10,7 @@ $ENVIRONMENT_PRODUCT = File.join($ENVIRONMENT_FRAMEWORKS_DIR, 'Objective-J')
$LICENSE_FILE = File.join($PRODUCT, 'LICENSE')
$BROWSER_FILE = File.join($PRODUCT, 'Objective-J.js')
$RHINO_FILE = File.join($PRODUCT, 'Rhino.platform', 'Objective-J.js')
$RHINO_FILE = File.join($PRODUCT, 'rhino.platform', 'Objective-J.js')
task :Products => [$BROWSER_FILE, $RHINO_FILE]
@@ -34,11 +34,11 @@ Files = [ 'LICENSE.txt',
'bootstrap.js'];
file_d $BROWSER_FILE => Files do |t|
build_product(t.name)
build_product(t.name, platform_flags(ObjectiveJ::Platform::Browser, ObjectiveJ::Platform::ObjJ))
end
file_d $RHINO_FILE => Files do |t|
build_product(t.name, 'RHINO')
build_product(t.name, platform_flags(ObjectiveJ::Platform::Rhino, ObjectiveJ::Platform::ObjJ))
end
#Framework in environment directory
@@ -46,7 +46,11 @@ file_d $ENVIRONMENT_PRODUCT => [:Products] do
cp_r($PRODUCT, $ENVIRONMENT_PRODUCT)
end
def build_product(path, *flags)
def platform_flags(*platforms)
return { 'PLATFORMS' => ('"[' + platforms.uniq.map { |platform| '\"' + platform + '\"' }.join(', ') + ']"') }
end
def build_product(path, flags)
IO.popen("gcc #{resolve_flags(flags)} -E -x c -P -", "w+") do |preprocessor|
+11 -3
View File
@@ -1,12 +1,18 @@
require 'rake'
require 'date'
require 'plist'
module ObjectiveJ
class Platform
OBJJ = 'objj'
RHINO = 'rhino'
BROWSER = 'browser'
ObjJ = 'objj'
Rhino = 'rhino'
Desktop = 'desktop'
Browser = 'browser'
BrowserDesktop = 'browser-desktop'
BrowserIPhone = 'browser-iphone'
BrowseriPhone = 'browser-iphone'
end
##
@@ -197,6 +203,7 @@ module ObjectiveJ
attribute :date
required_attribute :summary
required_attribute :identifier
required_attribute :platforms, [Platform::ObjJ]
read_only :specification_version
@@ -224,6 +231,7 @@ module ObjectiveJ
# attribute_alias_singular :executable, :executables
attribute_alias_singular :author, :authors
attribute_alias_singular :flag, :flags
attribute_alias_singular :platform, :platforms
# attribute_alias_singular :require_path, :require_paths
# attribute_alias_singular :test_file, :test_files
+108 -78
View File
@@ -1,43 +1,29 @@
require 'rake'
require 'objective-j/plist'
module ObjectiveJ
# Create a package based upon a Gem spec. Gem packages, as well as
# zip files and tar/gzipped packages can be produced by this task.
#
# In addition to the Rake targets generated by PackageTask, a
# GemPackageTask will also generate the following tasks:
#
# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.gem"</b>]
# Create a Ruby GEM package with the given name and version.
#
# Example using a Ruby GEM spec:
#
# require 'rubygems'
#
# spec = Gem::Specification.new do |s|
# s.platform = Gem::Platform::RUBY
# s.summary = "Ruby based make-like utility."
# s.name = 'rake'
# s.version = PKG_VERSION
# s.requirements << 'none'
# s.require_path = 'lib'
# s.autorequire = 'rake'
# s.files = PKG_FILES
# s.description = <<EOF
# Rake is a Make-like program implemented in Ruby. Tasks
# and dependencies are specified in standard Ruby syntax.
# EOF
# end
#
# Rake::GemPackageTask.new(spec) do |pkg|
# pkg.need_zip = true
# pkg.need_tar = true
# end
#
class BundleTask < Rake::Task
PLATFORM_DIRECTORIES =
{
Platform::ObjJ => 'objj.platform',
Platform::Rhino => 'rhino.platform',
Platform::Browser => 'browser.platform',
Platform::BrowserDesktop => 'browser-desktop.platform',
Platform::BrowserIPhone => 'browser-iphone.platform'
}
PLATFORM_FLAGS =
{
Platform::ObjJ => [],
Platform::Rhino => ['PLATFORM_RHINO'],
Platform::Browser => ['PLATFORM_BROWSER', 'PLATFORM_DOM'],
Platform::BrowserDesktop => ['PLATFORM_BROWSER', 'PLATFORM_DOM', 'PLATFORM_DESKTOP'],
Platform::BrowserIPhone => ['PLATFORM_BROWSER', 'PLATFORM_DOM', 'PLATFORM_IPHONE', 'PLATFORM_MOBILE']
}
# Objective-J Bundle spec containing the metadata for this bundle.
attr_accessor :bundle_spec
@@ -67,33 +53,48 @@ module ObjectiveJ
copied_resources << copied_resource
end
objects_path = @bundle_spec.intermediates_path
objects = []
replaced_files = []
# create file tasks for object files
@bundle_spec.sources.each do |source|
object_path = File.join(objects_path, File.basename(source, File.extname(source))) + '.o'
flags = []
@bundle_spec.flags.each do |flag|
flags << '-D' + flag
info_plist_path = @bundle_spec.build_path + '/Info.plist'
info_plist = @bundle_spec.info_plist
info_plist['CPBundlePlatforms'] = @bundle_spec.platforms;
file_d info_plist_path do
File.open(info_plist_path, 'w') do |file|
file.puts info_plist.to_plist
end
file_d object_path => source do
IO.popen("objjc #{flags.join(' ')} #{source} -o #{object_path}") do |objjc|
puts objjc.read
end
end
objects << object_path
replaced_files << File.basename(source)
end
#the actual executable path
executable_path = File.join(@bundle_spec.build_path, @bundle_spec.name + '.sj')
preprocessed_files = []
# create file tasks for object files
@bundle_spec.platforms.uniq.each do |platform|
executable_path = File.join(@bundle_spec.build_path, PLATFORM_DIRECTORIES[platform], @bundle_spec.name + '.sj')
enhance([executable_path])
file_d executable_path do
BundleTask.compact(@bundle_spec.build_path)
end
# Yes its unfortunate that we need to regenerate the whole executable if the Info.plist changes. Oh well.
file_d executable_path => info_plist_path
@bundle_spec.sources.each do |source|
preprocessed_file = File.join(@bundle_spec.build_path, PLATFORM_DIRECTORIES[platform], File.basename(source))
file_d preprocessed_file => source do
IO.popen("objjc #{resolve_flags(@bundle_spec.flags)} #{resolve_flags(PLATFORM_FLAGS[platform])} #{source} -o #{preprocessed_file}") do |objjc|
puts objjc.read
end
end
preprocessed_files << preprocessed_file
file_d executable_path => preprocessed_file
end
end
# copy license file
license_path = nil
@@ -108,39 +109,68 @@ module ObjectiveJ
else
license_path = license
end
file_d executable_path => copied_license
file_d copied_license => license_path do
cp(license_path, copied_license)
end
end
enhance(preprocessed_files + copied_resources + [info_plist_path])
end
def BundleTask.compact(path, *patterns)
puts 'Compacting ' + path
file executable_path => objects do
File.open(executable_path, "w") do |file|
file.write('@STATIC;1.0;')
info_plist_path = File.join(path, 'Info.plist')
info_plist = Plist::parse_xml(info_plist_path)
absolute_path = File.expand_path(path) + '/'
patterns = patterns.map { |pattern| "#{path}/#{pattern}" }
bundle_name = info_plist['CPBundleName']
replaced_files = []
FileList.new(File.join(path, '**', '*.platform')).each do |platform|
FileList.new(File.join(platform, '*.j')) do |list|
objects.each do |object|
file.write(IO.read(object))
end
list.include(*patterns)
executable_path = File.join(platform, bundle_name) + '.sj'
platform_absolute_path = File.expand_path(platform) + '/'
File.open(executable_path, 'w+') do |executable|
executable.write '@STATIC;1.0;'
list.each do |fileName|
File.open(fileName) do |file|
if fileName.index(platform_absolute_path) == 0
fileName = File.expand_path(fileName)[platform_absolute_path.length..-1]
else
fileName = File.expand_path(fileName)[absolute_path.length..-1]
end
executable.write "p;#{fileName.length};#{fileName}#{file.read}"
replaced_files << fileName
end
end
end
end
end
info_plist_path = @bundle_spec.build_path + '/Info.plist'
info_plist = @bundle_spec.info_plist
info_plist['CPBundleReplacedFiles'] = replaced_files.uniq
info_plist['CPBundleExecutable'] = bundle_name + '.sj'
info_plist['CPBundleExecutable'] = File.basename(executable_path)
info_plist['CPBundleReplacedFiles'] = replaced_files
file_d info_plist_path do
File.open(info_plist_path, 'w') do |file|
file.puts info_plist.to_plist
end
File.open(info_plist_path, 'w') do |file|
file.puts info_plist.to_plist
end
enhance(copied_resources + [executable_path, info_plist_path])
end
end
end
-134
View File
@@ -1,134 +0,0 @@
require 'rake'
module ObjectiveJ
PLIST_START = '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">'
PLIST_END = '</plist>'
end
class Module
def objj_extension(method)
if instance_methods.include?(method)
$stderr.puts "WARNING: Possible conflict with Objective-J extension: #{self}##{method} already exists"
else
yield
end
end
end
class Array
objj_extension('to_plist') do
def to_plist(start = true)
str = '<array>'
each do |value|
str += value.to_plist(false)
end
str = str + '</array>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END if start
return str
end
end
end
class FalseClass
objj_extension('to_plist') do
def to_plist(start = true)
str = '<false/>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END if start
return str
end
end
end
class Float
objj_extension('to_plist') do
def to_plist(start = true)
str = '<real>' + to_s + '</real>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END if start
return str
end
end
end
class Hash
objj_extension('to_plist') do
def to_plist(start = true)
str = '<dict>'
each do |key, value|
str += '<key>' + key.html_encode + '</key>' + value.to_plist(false)
end
str += '</dict>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END if start
return str
end
end
end
class Integer
objj_extension('to_plist') do
def to_plist(start = true)
str = '<integer>' + to_s + '</integer>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END
return str
end
end
end
class String
objj_extension('to_plist') do
def to_plist(start = true)
str = '<string>' + html_encode + '</string>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END if start
return str
end
end
objj_extension('html_encode') do
def html_encode
return self.gsub(/</, '&lt;').
gsub(/>/, '&gt;').
gsub(/"/,'&quot;').
gsub(/'/, '&apos;').
gsub(/&/, '&amp;')
end
end
end
class TrueClass
objj_extension('to_plist') do
def to_plist(start = true)
str = '<true/>'
str = ObjectiveJ::PLIST_START + str + ObjectiveJ::PLIST_END if start
return str
end
end
end