├── opam ├── findlib ├── descr └── opam ├── docs ├── html.stamp ├── type_Plist.html ├── index_classes.html ├── index_class_types.html ├── index_exceptions.html ├── index_extensions.html ├── index_methods.html ├── index_module_types.html ├── index_attributes.html ├── index_types.html ├── index_modules.html ├── index.html ├── index_values.html ├── Plist.html └── style.css ├── .merlin ├── .gitignore ├── configure ├── examples └── e1.ml ├── Makefile ├── README.md ├── lib ├── plist.ml └── plist_ml_stubs.c ├── _oasis └── setup.ml /opam/findlib: -------------------------------------------------------------------------------- 1 | plist 2 | -------------------------------------------------------------------------------- /docs/html.stamp: -------------------------------------------------------------------------------- 1 | 1a2c4ca69fbe973d95a7b929b59a7aff -------------------------------------------------------------------------------- /opam/descr: -------------------------------------------------------------------------------- 1 | Native OCaml Plist manipulation 2 | 3 | Plist 4 | -------------------------------------------------------------------------------- /.merlin: -------------------------------------------------------------------------------- 1 | PKG lambdasoup yojson 2 | PKG alcotest osx-plutil 3 | 4 | PKG plist oasis 5 | 6 | S . 7 | B _build/** 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.annot 2 | *.cmo 3 | *.cma 4 | *.cmi 5 | *.a 6 | *.o 7 | *.cmx 8 | *.cmxs 9 | *.cmxa 10 | 11 | # ocamlbuild working directory 12 | _build/ 13 | 14 | # ocamlbuild targets 15 | *.byte 16 | *.native 17 | 18 | # alcotest outputs 19 | _tests/ 20 | 21 | # oasis generated files 22 | setup.data 23 | setup.log 24 | plist.0.1 25 | 26 | # editor backups 27 | *~ 28 | test-idea.plist 29 | api.docdir -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # OASIS_START 4 | # DO NOT EDIT (digest: dc86c2ad450f91ca10c931b6045d0499) 5 | set -e 6 | 7 | FST=true 8 | for i in "$@"; do 9 | if $FST; then 10 | set -- 11 | FST=false 12 | fi 13 | 14 | case $i in 15 | --*=*) 16 | ARG=${i%%=*} 17 | VAL=${i##*=} 18 | set -- "$@" "$ARG" "$VAL" 19 | ;; 20 | *) 21 | set -- "$@" "$i" 22 | ;; 23 | esac 24 | done 25 | 26 | ocaml setup.ml -configure "$@" 27 | # OASIS_STOP 28 | -------------------------------------------------------------------------------- /docs/type_Plist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Plist 10 | 11 | 12 | sig  end -------------------------------------------------------------------------------- /docs/index_classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of classes 11 | 12 | 13 | 15 |

Index of classes

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/index_class_types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of class types 11 | 12 | 13 | 15 |

Index of class types

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/index_exceptions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of exceptions 11 | 12 | 13 | 15 |

Index of exceptions

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/index_extensions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of extensions 11 | 12 | 13 | 15 |

Index of extensions

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/index_methods.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of class methods 11 | 12 | 13 | 15 |

Index of class methods

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/index_module_types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of module types 11 | 12 | 13 | 15 |

Index of module types

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/index_attributes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of class attributes 11 | 12 | 13 | 15 |

Index of class attributes

16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /examples/e1.ml: -------------------------------------------------------------------------------- 1 | let () = 2 | let f () = 3 | let json = 4 | (`Assoc [("hello", `List [`String "world"; `Int 10])]) 5 | in 6 | let p = Plist.from_yojson json in 7 | Plist.to_file "test-idea.plist" true p; 8 | print_endline (Plist.to_string p) 9 | in 10 | f (); 11 | Gc.major (); 12 | print_endline "Finished GC Stress"; 13 | let b () = 14 | let p = Plist.from_file "test-idea.plist" in 15 | let s = Plist.to_string p in 16 | print_endline s; 17 | in 18 | b (); 19 | 20 | let h () = 21 | let error = Plist.from_string "Hello world" in 22 | () 23 | in 24 | (try h (); 25 | with Invalid_argument e -> print_endline e); 26 | let j () = 27 | let p = 28 | Plist.from_file "test-idea.plist" 29 | |> Plist.to_bytes 30 | in 31 | print_endline p 32 | in 33 | j () 34 | -------------------------------------------------------------------------------- /docs/index_types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of types 11 | 12 | 13 | 15 |

Index of types

16 | 17 | 18 | 19 | 20 |

P
plist [Plist]
21 | 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: a3c674b4239234cbbe53afe090018954) 3 | 4 | SETUP = ocaml setup.ml 5 | 6 | build: setup.data 7 | $(SETUP) -build $(BUILDFLAGS) 8 | 9 | doc: setup.data build 10 | $(SETUP) -doc $(DOCFLAGS) 11 | 12 | test: setup.data build 13 | $(SETUP) -test $(TESTFLAGS) 14 | 15 | all: 16 | $(SETUP) -all $(ALLFLAGS) 17 | 18 | install: setup.data 19 | $(SETUP) -install $(INSTALLFLAGS) 20 | 21 | uninstall: setup.data 22 | $(SETUP) -uninstall $(UNINSTALLFLAGS) 23 | 24 | reinstall: setup.data 25 | $(SETUP) -reinstall $(REINSTALLFLAGS) 26 | 27 | clean: 28 | $(SETUP) -clean $(CLEANFLAGS) 29 | 30 | distclean: 31 | $(SETUP) -distclean $(DISTCLEANFLAGS) 32 | 33 | setup.data: 34 | $(SETUP) -configure $(CONFIGUREFLAGS) 35 | 36 | configure: 37 | $(SETUP) -configure $(CONFIGUREFLAGS) 38 | 39 | .PHONY: build doc test all install uninstall reinstall clean distclean configure 40 | 41 | # OASIS_STOP 42 | -------------------------------------------------------------------------------- /docs/index_modules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of modules 11 | 12 | 13 | 15 |

Index of modules

16 | 17 | 18 | 19 | 24 |

P
Plist
20 | OCaml bindings to native Objective-C handling of plists; works on 21 | Linux and OS X 22 |
23 |
25 | 26 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

15 | 20 |

21 | 22 | 27 |
Plist
23 | OCaml bindings to native Objective-C handling of plists; works on 24 | Linux and OS X 25 |
26 |
28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | plists 2 | ------ 3 | 4 | Use `plists` from OCaml, easily change to `Yojson`. 5 | 6 | ``` 7 | $ opam install plist 8 | ``` 9 | 10 | Works on `Linux` and `OS X`, lets you write `Yojson` as a binary 11 | `plist`. 12 | 13 | Uses native `plist` manipulation in `Objective-C`, `Linux` 14 | installation requires `gnustep`. Use `opam depext` to have `opam` 15 | install requiremented system dependencies for you! 16 | 17 | # Example 18 | 19 | ```ocaml 20 | let () = 21 | let f () = 22 | let json = 23 | (`Assoc [("hello", `List [`String "world"; `Int 10])]) 24 | in 25 | let p = Plist.from_yojson json in 26 | Plist.to_file "test-idea.plist" true p; 27 | print_endline (Plist.to_string p) 28 | in 29 | f (); 30 | Gc.major (); 31 | print_endline "Finished GC Stress"; 32 | let b () = 33 | let p = Plist.from_file "test-idea.plist" in 34 | let s = Plist.to_string p in 35 | print_endline s; 36 | in 37 | b (); 38 | 39 | let h () = 40 | let error = Plist.from_string "Hello world" in 41 | () 42 | in 43 | (try h (); 44 | with Invalid_argument e -> print_endline e); 45 | let j () = 46 | let p = 47 | Plist.from_file "test-idea.plist" 48 | |> Plist.to_bytes 49 | in 50 | print_endline p 51 | in 52 | j () 53 | ``` 54 | -------------------------------------------------------------------------------- /lib/plist.ml: -------------------------------------------------------------------------------- 1 | (** OCaml bindings to native Objective-C handling of plists; works on 2 | Linux and OS X *) 3 | 4 | type plist 5 | 6 | (** Create a plist from a JSON formatted string, raises 7 | Invalid_argument if input string isn't in a Plist readable 8 | format *) 9 | external from_string : string -> plist = "plist_ml_from_string" 10 | 11 | (** Convert a Plist into a pretty formated JSON string, raises 12 | Invalid_argument when plist can't be turned into a string *) 13 | external to_string : plist -> string = "plist_ml_to_string" 14 | 15 | (** Writing a plist to file, second argument is whether to write as 16 | binary; raises Invalid_argument if trying to convert plist to 17 | binary fails, raises Failure if writing to a file location 18 | fails. *) 19 | external to_file : string -> bool -> plist -> unit = "plist_ml_to_file" 20 | 21 | (** Raises Invalid_argument if file does not exist *) 22 | external from_file : string -> plist = "plist_ml_from_file" 23 | 24 | (** Returns the plist as raw binary bytes, raises Invalid_argument if 25 | plist can't be turned into raw bytes *) 26 | external to_bytes : plist -> bytes = "plist_ml_to_bytes" 27 | 28 | (** Simple helpers *) 29 | let from_yojson s = from_string (Yojson.Basic.to_string s) 30 | let to_yojson p = to_string p |> (Yojson.Basic.from_string) 31 | -------------------------------------------------------------------------------- /opam/opam: -------------------------------------------------------------------------------- 1 | # -*- conf -*- 2 | opam-version: "1.2" 3 | name: "plist" 4 | version: "1.0.0" 5 | maintainer: "Edgar Aroutiounian " 6 | authors: [ "Edgar Aroutiounian " ] 7 | license: "BSD-3-clause" 8 | homepage: "https://github.com/fxfactorial/ocaml-plist" 9 | dev-repo: "https://github.com/fxfactorial/ocaml-plist.git" 10 | bug-reports: "https://github.com/fxfactorial/ocaml-plist/issues" 11 | tags: [ "clib:objc" "clib:gnustep" ] 12 | build: [ 13 | ["oasis" "setup"] 14 | ["ocaml" "setup.ml" "-configure" "--prefix" prefix] 15 | ["ocaml" "setup.ml" "-build"] 16 | ] 17 | install: ["ocaml" "setup.ml" "-install"] 18 | remove: [ 19 | ["ocamlfind" "remove" "plist"] 20 | ] 21 | depexts: [ 22 | [["debian"] ["gobjc" "gobjc++" "gnustep" "gnustep-devel" "libgnustep-base-dev"]] 23 | [["ubuntu"] ["gobjc" "gobjc++" "gnustep" "gnustep-devel" "libgnustep-base-dev"]] 24 | ] 25 | build-test: [ 26 | ["oasis" "setup"] 27 | ["ocaml" "setup.ml" "-configure" "--enable-tests"] 28 | ["ocaml" "setup.ml" "-build"] 29 | ["ocaml" "setup.ml" "-test"] 30 | ] 31 | build-doc: [ "ocaml" "setup.ml" "-doc" ] 32 | depends: [ 33 | "oasis" {build & >= "0.4.7"} 34 | "ocamlbuild" {build} 35 | "ocamlfind" {build} 36 | "yojson" {>= "1.3.3"} 37 | ] 38 | post-messages:[ 39 | "You need to have gnustep installed, opam depexts can install it for you." 40 | {failure & (os = "linux")} 41 | ] 42 | available: [ ocaml-version >= "4.04.0" ] 43 | -------------------------------------------------------------------------------- /_oasis: -------------------------------------------------------------------------------- 1 | # -*- conf -*- 2 | OASISFormat: 0.4 3 | Name: plist 4 | Version: 1.0.0 5 | Synopsis: OCaml Plist manipulation 6 | Authors: Edgar Aroutiounian 7 | Maintainers: Edgar Aroutiounian 8 | Homepage: https://github.com/fxfactorial/ocaml-plist 9 | License: BSD-3-clause 10 | OCamlVersion: >= 4.04.0 11 | AlphaFeatures: ocamlbuild_more_args 12 | Plugins: META (0.4), DevFiles (0.4) 13 | BuildTools: ocamlbuild, ocamldoc 14 | Description: Plist 15 | 16 | Library plist 17 | Path: lib 18 | Modules: Plist 19 | install: true 20 | if system(macosx) 21 | CCOpt: 22 | -g -ObjC -fno-objc-arc 23 | CClib: -framework Foundation 24 | else 25 | CCOpt: 26 | -x objective-c $(OBJC_FLAGS) 27 | -fconstant-string-class=NSConstantString 28 | CClib: 29 | -lgnustep-base -lobjc 30 | NativeOpt: 31 | -g -w +a-4-40..42-44-45-48 32 | ByteOpt: -g -w +a-4-40..42-44-45-48 33 | CSources: plist_ml_stubs.c 34 | BuildDepends: yojson 35 | 36 | Executable object_test 37 | Path: examples 38 | BuildTools:ocamlbuild 39 | install: false 40 | MainIs: e1.ml 41 | CompiledObject: native 42 | NativeOpt: -g -w +a-4-40..42-44-45-48 43 | ByteOpt: -g -w +a-4-40..42-44-45-48 44 | BuildDepends: plist 45 | 46 | SourceRepository master 47 | Type: git 48 | Location: https://github.com/fxfactorial/ocaml-plist.git 49 | Browser: https://github.com/fxfactorial/ocaml-plist 50 | 51 | Document api 52 | Title: Documentation and API reference for Plist 53 | Type: ocamlbuild (0.4) 54 | BuildTools+: ocamldoc 55 | InstallDir: $htmldir/plist 56 | PostCommand: cp docs/style.css api.docdir && cp api.docdir/* docs 57 | XOCamlbuildPath: docs 58 | XOCamlbuildModules: lib/Plist 59 | Install: true 60 | XOCamlbuildExtraArgs: 61 | "-docflags '-colorize-code -charset utf-8 -hide Plist -hide Pervasives'" 62 | -------------------------------------------------------------------------------- /docs/index_values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Index of values 11 | 12 | 13 | 15 |

Index of values

16 | 17 | 18 | 19 | 23 | 24 | 30 | 31 | 35 | 36 | 37 | 42 | 43 | 50 | 51 | 56 | 57 | 58 |

F
from_file [Plist]
20 | Raises Invalid_argument if file does not exist 21 |
22 |
from_string [Plist]
25 | Create a plist from a JSON formatted string, raises 26 | Invalid_argument if input string isn't in a Plist readable 27 | format 28 |
29 |
from_yojson [Plist]
32 | Simple helpers 33 |
34 |

T
to_bytes [Plist]
38 | Returns the plist as raw binary bytes, raises Invalid_argument if 39 | plist can't be turned into raw bytes 40 |
41 |
to_file [Plist]
44 | Writing a plist to file, second argument is whether to write as 45 | binary; raises Invalid_argument if trying to convert plist to 46 | binary fails, raises Failure if writing to a file location 47 | fails. 48 |
49 |
to_string [Plist]
52 | Convert a Plist into a pretty formated JSON string, raises 53 | Invalid_argument when plist can't be turned into a string 54 |
55 |
to_yojson [Plist]
59 | 60 | -------------------------------------------------------------------------------- /setup.ml: -------------------------------------------------------------------------------- 1 | (* setup.ml generated for the first time by OASIS v0.4.8 *) 2 | 3 | (* OASIS_START *) 4 | (* DO NOT EDIT (digest: a426e2d026defb34183b787d31fbdcff) *) 5 | (******************************************************************************) 6 | (* OASIS: architecture for building OCaml libraries and applications *) 7 | (* *) 8 | (* Copyright (C) 2011-2016, Sylvain Le Gall *) 9 | (* Copyright (C) 2008-2011, OCamlCore SARL *) 10 | (* *) 11 | (* This library is free software; you can redistribute it and/or modify it *) 12 | (* under the terms of the GNU Lesser General Public License as published by *) 13 | (* the Free Software Foundation; either version 2.1 of the License, or (at *) 14 | (* your option) any later version, with the OCaml static compilation *) 15 | (* exception. *) 16 | (* *) 17 | (* This library is distributed in the hope that it will be useful, but *) 18 | (* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *) 19 | (* or FITNESS FOR A PARTICULAR PURPOSE. See the file COPYING for more *) 20 | (* details. *) 21 | (* *) 22 | (* You should have received a copy of the GNU Lesser General Public License *) 23 | (* along with this library; if not, write to the Free Software Foundation, *) 24 | (* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) 25 | (******************************************************************************) 26 | 27 | let () = 28 | try 29 | Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH") 30 | with Not_found -> () 31 | ;; 32 | #use "topfind";; 33 | #require "oasis.dynrun";; 34 | open OASISDynRun;; 35 | 36 | let setup_t = BaseCompat.Compat_0_4.adapt_setup_t setup_t 37 | open BaseCompat.Compat_0_4 38 | (* OASIS_STOP *) 39 | 40 | let _ = 41 | BaseEnv.var_define 42 | "OBJC_FLAGS" 43 | (fun () -> 44 | let os_name = 45 | OASISExec.run_read_one_line 46 | ~ctxt:!OASISContext.default 47 | "uname" 48 | [] 49 | in 50 | if os_name = "Darwin" then "" 51 | else 52 | OASISExec.run_read_one_line 53 | ~ctxt:!OASISContext.default 54 | "gnustep-config" 55 | ["--objc-flags"] 56 | ) 57 | () 58 | 59 | let () = setup ();; 60 | -------------------------------------------------------------------------------- /docs/Plist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Plist 13 | 14 | 15 | 17 |

Module Plist

18 | 19 |
module Plist: sig .. end
20 | OCaml bindings to native Objective-C handling of plists; works on 21 | Linux and OS X
22 |
23 |
24 | 25 |
type plist 
26 | 27 | 28 |
val from_string : string -> plist
29 | Create a plist from a JSON formatted string, raises 30 | Invalid_argument if input string isn't in a Plist readable 31 | format
32 |
33 | 34 |
val to_string : plist -> string
35 | Convert a Plist into a pretty formated JSON string, raises 36 | Invalid_argument when plist can't be turned into a string
37 |
38 | 39 |
val to_file : string -> bool -> plist -> unit
40 | Writing a plist to file, second argument is whether to write as 41 | binary; raises Invalid_argument if trying to convert plist to 42 | binary fails, raises Failure if writing to a file location 43 | fails.
44 |
45 | 46 |
val from_file : string -> plist
47 | Raises Invalid_argument if file does not exist
48 |
49 | 50 |
val to_bytes : plist -> bytes
51 | Returns the plist as raw binary bytes, raises Invalid_argument if 52 | plist can't be turned into raw bytes
53 |
54 | 55 |
val from_yojson : Yojson.Basic.json -> plist
56 | Simple helpers
57 |
58 | 59 |
val to_yojson : plist -> Yojson.Basic.json
-------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | /* A style for ocamldoc. Daniel C. Buenzli */ 2 | 3 | /* Reset a few things. */ 4 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre, 5 | a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp, 6 | small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset, 7 | form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td 8 | { margin: 0; padding: 0; border: 0 none; outline: 0; font-size: 100%; 9 | font-weight: inherit; font-style:inherit; font-family:inherit; 10 | line-height: inherit; vertical-align: baseline; text-align:inherit; 11 | color:inherit; background: transparent; } 12 | 13 | table { border-collapse: collapse; border-spacing: 0; } 14 | 15 | /* Basic page layout */ 16 | 17 | body { font: normal 10pt/1.375em helvetica, arial, sans-serif; text-align:left; 18 | margin: 1.375em 10%; min-width: 40ex; max-width: 72ex; 19 | color: black; background: white /* url(line-height-22.gif) */; } 20 | 21 | b { font-weight: bold } 22 | em { font-style: italic } 23 | 24 | tt, code, pre { font-family: WorkAroundWebKitAndMozilla, monospace; 25 | font-size: 1em; } 26 | pre code { font-size : inherit; } 27 | .codepre { margin-bottom:1.375em /* after code example we introduce space. */ } 28 | 29 | pre { padding: 5px; } 30 | code.code, pre.codepre, pre.verbatim { background-color: #f7f7f7; border-radius: 3px; } 31 | code.code { font-size: 95%; padding: 0.1em 0.2em; } 32 | pre.codepre code.code { padding: 0; } 33 | 34 | 35 | .superscript,.subscript 36 | { font-size : 0.813em; line-height:0; margin-left:0.4ex;} 37 | .superscript { vertical-align: super; } 38 | .subscript { vertical-align: sub; } 39 | 40 | /* ocamldoc markup workaround hacks */ 41 | 42 | 43 | 44 | hr, hr + br, div + br, center + br, span + br, ul + br, ol + br, pre + br 45 | { display: none } /* annoying */ 46 | 47 | div.info + br { display:block} 48 | 49 | .codepre br + br { display: none } 50 | h1 + pre { margin-bottom:1.375em} /* Toplevel module description */ 51 | 52 | /* Sections and document divisions */ 53 | 54 | /* .navbar { margin-bottom: -1.375em } */ 55 | h1 { font-weight: bold; font-size: 1.5em; /* margin-top:1.833em; */ 56 | margin-top:0.917em; padding-top:0.875em; 57 | border-top-style:solid; border-width:1px; border-color:#AAA; } 58 | h2 { font-weight: bold; font-size: 1.313em; margin-top: 1.048em } 59 | h3 { font-weight: bold; font-size: 1.125em; margin-top: 1.222em } 60 | h3 { font-weight: bold; font-size: 1em; margin-top: 1.375em} 61 | h4 { font-style: italic; } 62 | 63 | /* Used by OCaml's own library documentation. */ 64 | h6 { font-weight: bold; font-size: 1.125em; margin-top: 1.222em } 65 | .h7 { font-weight: bold; font-size: 1em; margin-top: 1.375em } 66 | 67 | p { margin-top: 1.375em } 68 | pre { margin-top: 1.375em } 69 | .info { margin: 0.458em 0em -0.458em 2em;}/* Description of types values etc. */ 70 | td .info { margin:0; padding:0; margin-left: 2em;} /* Description in indexes */ 71 | 72 | ul, ol { margin-top:0.688em; padding-bottom:0.687em; 73 | list-style-position:outside} 74 | ul + p, ol + p { margin-top: 0em } 75 | ul { list-style-type: square } 76 | 77 | 78 | /* h2 + ul, h3 + ul, p + ul { } */ 79 | ul > li { margin-left: 1.375em; } 80 | ol > li { margin-left: 1.7em; } 81 | /* Links */ 82 | 83 | a, a:* { text-decoration: underline } 84 | *:target {background-color: #FFFF99;} /* anchor highlight */ 85 | 86 | /* Code */ 87 | 88 | .keyword { font-weight: bold; } 89 | .comment { color : red } 90 | .constructor { color : green } 91 | .string { color : #957; } 92 | .warning { color : red ; font-weight : bold } 93 | 94 | /* Functors */ 95 | 96 | .paramstable { border-style : hidden ; padding-bottom:1.375em} 97 | .paramstable code { margin-left: 1ex; margin-right: 1ex } 98 | .sig_block {margin-left: 1em} 99 | 100 | /* Images */ 101 | 102 | img { margin-top: 1.375em; display:block } 103 | li img { margin-top: 0em; } 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /lib/plist_ml_stubs.c: -------------------------------------------------------------------------------- 1 | // -*- objc -*- 2 | 3 | #define CAML_NAME_SPACE 4 | 5 | #import 6 | 7 | #import 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | #define NSDict(v) (*(NSMutableDictionary**)Data_custom_val(v)) 15 | 16 | void release_nsdict(value this_dict) 17 | { 18 | [NSDict(this_dict) release]; 19 | } 20 | 21 | long nsdict_hash(value this_dict) 22 | { 23 | return [NSDict(this_dict) hash]; 24 | } 25 | 26 | static struct custom_operations nsdict_custom_ops = { 27 | .identifier = "com.hyegar.plist", 28 | .finalize = release_nsdict, 29 | .compare = NULL, 30 | .hash = nsdict_hash, 31 | .serialize = NULL, 32 | .deserialize = NULL 33 | }; 34 | 35 | CAMLprim value 36 | plist_ml_from_string(value str) 37 | { 38 | CAMLparam1(str); 39 | CAMLlocal1(wrapper); 40 | NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init]; 41 | 42 | NSError *error = nil; 43 | NSData *s1 = [NSData dataWithBytes:String_val(str) length:caml_string_length(str)]; 44 | NSMutableDictionary *dict = 45 | [NSJSONSerialization JSONObjectWithData:s1 46 | options:NSJSONReadingMutableContainers 47 | error:&error]; 48 | if (error) { 49 | const char *e_message = [[error localizedDescription] UTF8String]; 50 | [myPool drain]; 51 | caml_invalid_argument(e_message); 52 | } 53 | wrapper = caml_alloc_custom(&nsdict_custom_ops, sizeof(id), 0, 1); 54 | // We need to hold onto the NSMutableDictionary 55 | [dict retain]; 56 | memcpy(Data_custom_val(wrapper), &dict, sizeof(id)); 57 | [myPool drain]; 58 | CAMLreturn(wrapper); 59 | } 60 | 61 | CAMLprim value 62 | plist_ml_to_file(value filename, value as_binary, value plist_dict) 63 | { 64 | CAMLparam3(filename, as_binary, plist_dict); 65 | NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init]; 66 | 67 | NSError *error = nil; 68 | BOOL write_success = YES; 69 | 70 | id d = NSDict(plist_dict); 71 | NSString *filepath = 72 | [[NSString alloc] initWithBytes:String_val(filename) 73 | length:caml_string_length(filename) 74 | encoding:NSUTF8StringEncoding]; 75 | 76 | if (Bool_val(as_binary)) { 77 | d = [NSPropertyListSerialization 78 | dataWithPropertyList:d 79 | format:NSPropertyListBinaryFormat_v1_0 80 | options:0 81 | error:&error]; 82 | if (error) { 83 | const char *e_message = [[error localizedDescription] UTF8String]; 84 | [myPool drain]; 85 | caml_invalid_argument(e_message); 86 | } 87 | 88 | } 89 | 90 | caml_release_runtime_system(); 91 | write_success = [d writeToFile:filepath atomically:YES]; 92 | caml_acquire_runtime_system(); 93 | 94 | [myPool drain]; 95 | 96 | if (write_success == NO) caml_failwith("Couldn't write to file"); 97 | 98 | CAMLreturn(Val_unit); 99 | } 100 | 101 | CAMLprim value 102 | plist_ml_to_string(value plist_dict) 103 | { 104 | CAMLparam1(plist_dict); 105 | CAMLlocal1(ml_string); 106 | NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init]; 107 | 108 | NSMutableDictionary *d = NSDict(plist_dict); 109 | NSError *error = nil; 110 | NSData *dump = 111 | [NSJSONSerialization dataWithJSONObject:d 112 | options:NSJSONWritingPrettyPrinted 113 | error:&error]; 114 | if (error) { 115 | const char *e_message = [[error localizedDescription] UTF8String]; 116 | [myPool drain]; 117 | caml_invalid_argument(e_message); 118 | } 119 | 120 | NSString *s = [[NSString alloc] initWithData:dump encoding:NSUTF8StringEncoding]; 121 | const size_t length = [s lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 122 | 123 | ml_string = caml_alloc_string(length); 124 | memmove(String_val(ml_string), [s UTF8String], length); 125 | [myPool drain]; 126 | CAMLreturn(ml_string); 127 | } 128 | 129 | CAMLprim value 130 | plist_ml_from_file(value filename) 131 | { 132 | CAMLparam1(filename); 133 | CAMLlocal1(plist); 134 | NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init]; 135 | 136 | NSString *file_path = 137 | [[NSString alloc] initWithBytes:String_val(filename) 138 | length:caml_string_length(filename) 139 | encoding:NSUTF8StringEncoding]; 140 | BOOL file_exists = [[NSFileManager defaultManager] fileExistsAtPath:file_path]; 141 | if (file_exists == NO) caml_invalid_argument("File does not exist"); 142 | 143 | caml_release_runtime_system(); 144 | id p = [[NSDictionary alloc] initWithContentsOfFile:file_path]; 145 | caml_acquire_runtime_system(); 146 | 147 | plist = caml_alloc_custom(&nsdict_custom_ops, sizeof(id), 0, 1); 148 | memcpy(Data_custom_val(plist), &p, sizeof(id)); 149 | // Hold onto the Dict 150 | [p retain]; 151 | [myPool drain]; 152 | CAMLreturn(plist); 153 | } 154 | 155 | CAMLprim value 156 | plist_ml_to_bytes(value plist) 157 | { 158 | CAMLparam1(plist); 159 | CAMLlocal1(raw_bytes); 160 | NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init]; 161 | NSError *error = nil; 162 | 163 | NSData *d = [NSPropertyListSerialization 164 | dataWithPropertyList:NSDict(plist) 165 | format:NSPropertyListBinaryFormat_v1_0 166 | options:0 167 | error:&error]; 168 | if (error) { 169 | const char *e_message = [[error localizedDescription] UTF8String]; 170 | [myPool drain]; 171 | caml_invalid_argument(e_message); 172 | } 173 | 174 | raw_bytes = caml_alloc_string([d length]); 175 | memcpy(String_val(raw_bytes), [d bytes], [d length]); 176 | [myPool drain]; 177 | CAMLreturn(raw_bytes); 178 | } 179 | --------------------------------------------------------------------------------