Skip to content

fisher158163/swiftini

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Using my app is also a way to support me:
Zipora: Zip/RAR/7Z Unarchiver Scap: Screenshot & Markup Edit Screen Test Deskmark Keyzer Vidwall Hub VidCrop Vidwall Mousio Hint Mousio Musicer Audioer FileSentinel FocusCursor Videoer KeyClicker DayBar Iconed Menuist Quick RSS Quick RSS Web Serve Copybook Generator DevTutor for SwiftUI RegexMate Time Passage Iconize Folder Textsound Saver Create Custom Symbols DevHub Resume Revise Palette Genius Symbol Scribe

中文InstallationUsagePublic API


SwiftINI

Buy me a coffee Follow On X

SwiftINI is a small Swift Package for parsing and serializing INI data. Its behavior is modeled after npm's ini package, including bracketed arrays, duplicate-key arrays, dotted nested sections, quoted values, escaped comments, and typed true / false / null values.

Features

  • Parse INI text or files.
  • Serialize INIObject values back to INI text.
  • Supports ; and # comments.
  • Supports [section] and [parent.child] nested sections.
  • Supports key[] = value arrays.
  • Supports duplicate-key arrays.
  • Supports escaped \; and \# so values are not treated as comments.
  • Supports quoted keys and values.
  • Supports typed true, false, and null values.
  • Keeps numbers as strings by default, matching npm ini.
  • Skips __proto__ keys to avoid prototype-pollution style issues.

Installation

Add the package to Package.swift:

dependencies: [
    .package(url: "https://github.com/jaywcjlove/SwiftINI.git", from: "1.0.0")
]

Then add SwiftINI to your target dependencies:

targets: [
    .target(
        name: "YourTarget",
        dependencies: ["SwiftINI"]
    )
]

For local development, use a path dependency:

.package(path: "/Users/wong/git/packages/SwiftINI")

Usage

import SwiftINI

let text = """
; This comment is ignored
scope = global

[database]
user = dbuser
password = dbpassword
database = use_this_database

[paths.default]
datadir = /var/lib/data
array[] = first value
array[] = second value
array[] = third value
"""

let config = INI.parse(text)

print(config["scope"]?.string ?? "")
print(config["database"]?["user"]?.string ?? "")
print(config["paths"]?["default"]?["datadir"]?.string ?? "")
print(config["paths"]?["default"]?["array"]?.array ?? [])

Reading Files

let config = try INI.parse(contentsOfFile: "path/to/config.ini")
print(config["Header"]?["Key"]?.string ?? "")

You can also read from a URL:

let url = URL(fileURLWithPath: "path/to/config.ini")
let config = try INI.parse(contentsOf: url)

Serializing

let object: INIObject = [
    "scope": "global",
    "database": [
        "user": "dbuser",
        "password": "dbpassword",
        "database": "use_this_database",
    ],
    "paths": [
        "default": [
            "datadir": "/var/lib/data",
            "array": [
                "first value",
                "second value",
                "third value",
            ],
        ],
    ],
]

let output = INI.stringify(object)
print(output)

Output:

scope=global

[database]
user=dbuser
password=dbpassword
database=use_this_database

[paths.default]
datadir=/var/lib/data
array[]=first value
array[]=second value
array[]=third value

Public API

INI.parse(_ text: String) -> INIObject
INI.parse(contentsOfFile path: String) throws -> INIObject
INI.parse(contentsOf url: URL) throws -> INIObject

INI.decode(_ text: String) -> INIObject

INI.stringify(_ object: INIObject) -> String
INI.encode(_ object: INIObject) -> String

Recommended semantics:

  • parse: parse INI text or files.
  • decode: alias of parse(_:), matching npm ini.
  • stringify: serialize an INIObject to INI text.
  • encode: alias of stringify(_:), matching npm ini.

Accessing Values

INIObject subscripting returns INIValue?, and object values can be chained:

let value = config["database"]?["user"]?.string

Common value accessors:

value.string   // String?
value.bool     // Bool?
value.array    // [INIValue]?
value.object   // INIObject?

INIValue supports:

case string(String)
case bool(Bool)
case null
case array([INIValue])
case object(INIObject)

Decode Options

let config = INI.parse(text, options: .init(bracketedArray: true))

INI.DecodeOptions:

Option Default Description
bracketedArray true When true, key[] = value is parsed as an array. When false, repeated keys are parsed as arrays.

Example:

array[] = first
array[] = second

Default result:

["array": ["first", "second"]]

Duplicate-key mode:

let config = INI.parse(text, options: .init(bracketedArray: false))
array = first
array = second

Result:

["array": ["first", "second"]]

Encode Options

let output = INI.stringify(
    object,
    options: .init(
        align: true,
        sort: true,
        whitespace: true
    )
)

INI.EncodeOptions:

Option Default Description
section nil Wraps output in a section prefix.
align false Aligns = and implies whitespace.
newline false Adds a blank line after section headers.
sort false Sorts keys before encoding.
whitespace false Uses key = value; otherwise outputs key=value.
platform nil Use "win32" for CRLF output.
bracketedArray true When true, emits key[]=value; when false, emits repeated key=value lines.

Section Prefix

let output = INI.stringify(
    ["type": "file"],
    options: .init(section: "log")
)

Output:

[log]
type=file

Array Format

Arrays are emitted as key[] by default:

let output = INI.stringify([
    "items": ["first", "second"]
])
items[]=first
items[]=second

With bracketedArray: false:

let output = INI.stringify(
    ["items": ["first", "second"]],
    options: .init(bracketedArray: false)
)
items=first
items=second

Format Behavior

Comments

Lines starting with ; or # are ignored:

; comment
# comment
name = SwiftINI

Inline comments are cut off at unescaped ; or #:

name = value ; comment
hash = value # comment

Escape ; or # when the character is part of the value:

semicolon = this\; is not a comment
hash = this\# is not a comment

Quotes

Quoted values are parsed as JSON strings when possible, preserving leading/trailing spaces and escaped characters:

value = " a "

Parsed result:

" a "

Type Conversion

Only these literal values are converted automatically:

enabled = true
disabled = false
empty = null
count = 10

Parsed result:

enabled  // .bool(true)
disabled // .bool(false)
empty    // .null
count    // .string("10")

10 remains a string.

Testing

swift test

The tests cover parsing, serializing, arrays, duplicate keys, nested sections, CRLF input/output, escaped comments, __proto__ protection, and the main fixture behaviors from npm ini.

License

Licensed under the MIT License.

About

An ini parser/serializer in Swift

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Swift 100.0%