commit 82f6feeb9cbe041f52f369f323189f7b6c8d0049
parent f6445e59a70e9378fe5f08052302d12928cfa8d0
Author: ssnf <ssnf@ssnf.xyz>
Date: Fri, 11 Jul 2025 01:22:00 +0000
add libsdbr manpage
Diffstat:
2 files changed, 343 insertions(+), 0 deletions(-)
diff --git a/man/man3/INDEX b/man/man3/INDEX
@@ -1171,6 +1171,24 @@ s_restart string.3
s_terminate string.3
s_tolower string.3
s_unique string.3
+sdbr_add sdbr.3
+sdbr_arg2r sdbr.3
+sdbr_attr sdbr.3
+sdbr_close sdbr.3
+sdbr_dup sdbr.3
+sdbr_edit sdbr.3
+sdbr_edit2 sdbr.3
+sdbr_escape sdbr.3
+sdbr_init sdbr.3
+sdbr_match sdbr.3
+sdbr_n sdbr.3
+sdbr_print sdbr.3
+sdbr_query sdbr.3
+sdbr_str2r sdbr.3
+sdbr_val sdbr.3
+sdbr_zero sdbr.3
+vsdbr_join sdbr.3
+sdbr sdbr.3
Str str.3
Strn str.3
Straddc str.3
diff --git a/man/man3/sdbr.3 b/man/man3/sdbr.3
@@ -0,0 +1,325 @@
+.TH SDBR 3
+.SH NAME
+sdbr_add, sdbr_arg2r, sdbr_attr, sdbr_close, sdbr_dup, sdbr_edit, sdbr_edit2, sdbr_escape, sdbr_init, sdbr_match, sdbr_n, sdbr_print, sdbr_query, sdbr_str2r, sdbr_val, sdbr_zero, vsdbr_join \- simple database records
+.SH SYNOPSIS
+.B #include <u.h>
+.br
+.B #include <libc.h>
+.br
+.B #include <str.h>
+.br
+.B #include <vec.h>
+.br
+.B #include <sdbr.h>
+.PP
+.ft L
+.nf
+.ta \w'\fL 'u +\w'\fLString 'u
+typedef struct {
+ String *attr;
+ String *val;
+} Sdbr;
+.fi
+.PP
+.ta \w'\fLvoid 'u
+.B
+void sdbr_add(Sdbr *r, String attr, String val)
+.PP
+.B
+void sdbr_arg2r(Sdbr *r, char *argv[])
+.PP
+.B
+int sdbr_attr(Sdbr r, char *attr)
+.PP
+.B
+void sdbr_close(Sdbr *r)
+.PP
+.B
+void sdbr_dup(Sdbr *sr, Sdbr r)
+.PP
+.B
+void sdbr_edit(Sdbr *sr, Sdbr r)
+.PP
+.B
+void sdbr_edit2(Sdbr *r, String attr, String val)
+.PP
+.B
+char* sdbr_escape(String *s, String val)
+.PP
+.B
+void sdbr_init(Sdbr *r)
+.PP
+.B
+char sdbr_match(char *k, char *v)
+.PP
+.B
+ulong sdbr_n(Sdbr r)
+.PP
+.B
+void sdbr_print(Sdbr r)
+.PP
+.B
+int sdbr_query(Sdbr r, Sdbr q)
+.PP
+.B
+void sdbr_str2r(Sdbr *sr, String s)
+.PP
+.B
+String sdbr_val(Sdbr r, char *attr)
+.PP
+.B
+void sdbr_zero(Sdbr *r)
+.PP
+.B
+void vsdbr_join(Sdbr *v[], Sdbr r)
+.SH DESCRIPTION
+These functions provide a simple database record system for storing and querying
+attribute-value pairs using the same format as Plan 9's network database (ndb).
+An
+.B Sdbr
+record contains vectors of attribute names and their corresponding values,
+both stored as dynamic strings.
+While ndb is designed specifically for network configuration,
+sdb records can be used for any general-purpose attribute-value data.
+.PP
+.I Sdbr_init
+initializes a record
+.IR r .
+The record is initially empty.
+.PP
+.I Sdbr_close
+frees all memory associated with record
+.IR r .
+.PP
+.I Sdbr_add
+adds an attribute-value pair to record
+.IR r .
+The attribute name is
+.I attr
+and its value is
+.IR val .
+.PP
+.I Sdbr_n
+returns the number of attribute-value pairs in record
+.IR r .
+.PP
+.I Sdbr_zero
+removes all attribute-value pairs from record
+.I r
+but keeps the record structure intact for reuse.
+.PP
+.I Sdbr_dup
+copies all attribute-value pairs from record
+.I src
+to record
+.IR dst .
+.PP
+.I Sdbr_str2r
+parses a string
+.I s
+containing space-separated attribute=value pairs and adds them to record
+.IR r .
+Values containing spaces can be quoted with double quotes.
+Escape sequences \e0, \et, \en, \e", and \e\e are supported within quoted values.
+.PP
+.I Sdbr_arg2r
+parses command-line arguments
+.I argv
+(null-terminated array) as alternating attribute-value pairs and adds them to record
+.IR r .
+Arguments are processed in pairs where argv[0] is the attribute and argv[1] is the value.
+.PP
+.I Sdbr_val
+returns the value of attribute
+.I attr
+in record
+.IR r .
+If the attribute is not found, it returns an empty string.
+The attribute name can contain glob patterns.
+.PP
+.I Sdbr_attr
+returns the index of attribute
+.I attr
+in record
+.IR r ,
+or -1 if not found.
+.PP
+.I Sdbr_match
+tests whether
+.I value
+matches
+.IR pattern .
+The pattern supports glob-style wildcards (*) and comparison operators
+(>, >=, <, <=).
+These operators perform lexicographic string comparison, not numeric.
+Literal asterisks can be escaped with backslash.
+.PP
+.I Sdbr_query
+tests whether record
+.I r
+matches all conditions specified in query record
+.IR query .
+It returns 1 if the record matches, 0 otherwise.
+Attribute names in the query starting with '!' are negated conditions.
+.PP
+.I Sdbr_edit
+applies edits from record
+.I r
+to record
+.IR sr .
+For each attribute in
+.IR r ,
+the corresponding value in
+.I sr
+is updated or added.
+.PP
+.I Sdbr_edit2
+updates or adds a single attribute-value pair in record
+.IR r .
+.PP
+.I Sdbr_escape
+formats string
+.I val
+for output, escaping special characters and storing the result in string
+.IR s .
+It returns a pointer to the formatted string.
+.PP
+.I Sdbr_print
+prints record
+.I r
+to standard output in attribute=value format.
+.PP
+.I Vsdbr_join
+appends record
+.I r
+to the vector of records
+.IR v .
+.SH EXAMPLES
+.PP
+Basic record operations:
+.IP
+.EX
+Sdbr r;
+
+sdbr_init(&r);
+sdbr_add(&r, Str("name"), Str("John"));
+sdbr_add(&r, Str("age"), Str("30"));
+sdbr_print(r);
+sdbr_close(&r);
+.EE
+.PP
+Parsing from string:
+.IP
+.EX
+Sdbr r;
+String s;
+
+sdbr_init(&r);
+s = Str("name=John age=30 city=\\"New York\\"");
+sdbr_str2r(&r, s);
+print("Name: %s\en", sdbr_val(r, "name").s);
+sdbr_close(&r);
+.EE
+.PP
+Querying records:
+.IP
+.EX
+Sdbr r, q;
+
+sdbr_init(&r);
+sdbr_init(&q);
+sdbr_add(&r, Str("type"), Str("user"));
+sdbr_add(&r, Str("status"), Str("active"));
+sdbr_add(&q, Str("type"), Str("user"));
+sdbr_add(&q, Str("!status"), Str("inactive"));
+if(sdbr_query(r, q))
+ print("Record matches query\en");
+sdbr_close(&r);
+sdbr_close(&q);
+.EE
+.PP
+Pattern matching:
+.IP
+.EX
+if(sdbr_match("*user*", "admin_user"))
+ print("Pattern matches\en");
+if(sdbr_match(">=100", "150"))
+ print("Comparison matches\en");
+.EE
+.PP
+Process tracking:
+.IP
+.EX
+Sdbr r;
+
+sdbr_init(&r);
+sdbr_str2r(&r, "pid=1234 cmd=rc user=glenda cpu=0.5");
+sdbr_add(&r, Str("tags"), Str("shell,interactive"));
+sdbr_add(&r, Str("started"), Str("2025-01-15T10:30:00"));
+sdbr_print(r);
+sdbr_close(&r);
+.EE
+.PP
+Configuration with inheritance:
+.IP
+.EX
+Sdbr def, usr;
+
+sdbr_init(&def);
+sdbr_init(&usr);
+sdbr_str2r(&def, "editor=sam theme=light font=lucsans");
+sdbr_str2r(&usr, "theme=dark font=go");
+sdbr_edit(&def, usr);
+print("Font: %s\en", sdbr_val(def, "font").s);
+sdbr_close(&def);
+sdbr_close(&usr);
+.EE
+.PP
+Date range queries:
+.IP
+.EX
+Sdbr ev, q;
+
+sdbr_init(&ev);
+sdbr_init(&q);
+sdbr_str2r(&ev, "timestamp=2025-01-15T14:30:00 level=error");
+sdbr_str2r(&q,
+ "timestamp=>=2025-01-15T14:00:00 "
+ "timestamp=<=2025-01-15T15:00:00");
+if(sdbr_query(ev, q))
+ print("Event in time range\en");
+sdbr_close(&ev);
+sdbr_close(&q);
+.EE
+.PP
+Geographic range queries:
+.IP
+.EX
+Sdbr loc, q;
+
+sdbr_init(&loc);
+sdbr_init(&q);
+sdbr_str2r(&loc, "lat=40.7128 lon=-74.0060 city=\"New York\"");
+sdbr_str2r(&q,
+ "lat=>=40.0 lat=<=41.0 "
+ "lon=>=-73.0 lon=<=-75.0");
+if(sdbr_query(loc, q))
+ print("Location in bounding box\en");
+sdbr_close(&loc);
+sdbr_close(&q);
+.EE
+.SH SOURCE
+.B \*9/src/libsdbr
+.SH SEE ALSO
+.MR ndb (3) ,
+.MR ndb (7) ,
+.MR sdb (1) ,
+.MR sdb (3) ,
+.MR str (3) ,
+.MR vec (3)
+.SH DIAGNOSTICS
+Functions call
+.I sysfatal
+if memory allocation fails.
+.SH BUGS
+None.