[Commit]
nickle ChangeLog, 1.34, 1.35 builtin.5c, 1.6, 1.7 string.5c,
1.3, 1.4
Bart Massey
commit at keithp.com
Fri Apr 16 00:46:04 PDT 2004
Committed by: bart
Update of /local/src/CVS/nickle
In directory home.keithp.com:/tmp/cvs-serv19527
Modified Files:
ChangeLog builtin.5c string.5c
Log Message:
* string.5c:
Added new string functions _dequote(), dequote(), inchars(),
readcsv(), and associated machinery.
* builtin.5c:
String depends on Ctype now, so reordered.
Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/nickle/ChangeLog,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- a/ChangeLog 16 Apr 2004 06:06:01 -0000 1.34
+++ b/ChangeLog 16 Apr 2004 07:46:02 -0000 1.35
@@ -1,3 +1,11 @@
+2004-04-15 Bart Massey <bart at cs.pdx.edu>
+
+ * string.5c:
+ Added new string functions _dequote(), dequote(), inchars(),
+ readcsv(), and associated machinery.
+ * builtin.5c:
+ String depends on Ctype now, so reordered.
+
2004-04-15 Keith Packard <keithp at keithp.com>
* array.c: (ArrayResize):
Index: builtin.5c
===================================================================
RCS file: /local/src/CVS/nickle/builtin.5c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- a/builtin.5c 16 Apr 2004 05:26:44 -0000 1.6
+++ b/builtin.5c 16 Apr 2004 07:46:02 -0000 1.7
@@ -77,8 +77,8 @@
}
# Load the prerequisites for the extra commands.
-library "string.5c";
library "ctype.5c";
+library "string.5c";
library "file.5c";
library "printf.5c";
library "history.5c";
Index: string.5c
===================================================================
RCS file: /local/src/CVS/nickle/string.5c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- a/string.5c 11 Apr 2004 09:33:25 -0000 1.3
+++ b/string.5c 16 Apr 2004 07:46:02 -0000 1.4
@@ -1,5 +1,122 @@
extend namespace String {
+ public string chomp(string s) {
+ if (s == "")
+ return s;
+ int l = length(s);
+ int i = 0;
+ while(i < l && Ctype::isspace(s[i]))
+ i++;
+ int j = l - 1;
+ while(j >= 0 && Ctype::isspace(s[j]))
+ --j;
+ return substr(s, i, j - i + 1);
+ }
+
+ typedef enum {normal, openq, xq} qstate;
+
+ public bool inchars(int c, string s) {
+ return index(String::new(c), s) >= 0;
+ }
+
+ public typedef struct {
+ string oq, cq, qq;
+ } quote_context;
+
+ public string _dequote(string s, quote_context q) {
+ string result = "";
+ qstate t = qstate.normal;
+ for (int cur = 0; cur < length(s); cur++) {
+ int c = s[cur];
+ switch(t) {
+ case qstate.normal:
+ if (inchars(c, q.oq)) {
+ t = qstate.openq;
+ continue;
+ }
+ raise invalid_argument("_dequote: leading garbage", 0, s);
+ break;
+ case qstate.openq:
+ if (inchars(c, q.qq)) {
+ t = qstate.xq;
+ continue;
+ }
+ if (inchars(c, q.cq)) {
+ if (cur != length(s) - 1)
+ raise invalid_argument("_dequote: trailing garbage", 0, s);
+ continue;
+ }
+ break;
+ case qstate.xq:
+ t = qstate.openq;
+ break;
+ }
+ result = result + String::new(c);
+ }
+ if (q.qq == q.cq && t == qstate.xq)
+ return result;
+ raise invalid_argument("_dequote: unexpected end of string", 0, s);
+ }
+
+ public quote_context default_quotes = {
+ oq = "\"", cq = "\"", qq = "\\"
+ };
+
+ public string dequote(string s) {
+ return _dequote(s, default_quotes);
+ }
+
+ public string[*] readcsv(string s) {
+ string[...] ss = {};
+ if (s == "" || s == "\n" || s == "\r\n")
+ return ss;
+ quote_context q = default_quotes;
+ q.qq = "\"";
+ string curs = "";
+ qstate t = qstate.normal;
+ int cur = 0;
+ while (cur < length(s)) {
+ int c = s[cur];
+# printf("%d: %c %v\n", cur, c, t);
+ switch(t) {
+ case qstate.normal:
+ if (c == ',') {
+ string t = chomp(curs);
+ if (t != "" && t[0] == '"')
+ t = _dequote(t, q);
+ ss[dim(ss)] = t;
+ curs = "";
+ cur++;
+ continue;
+ }
+ if (c == '"')
+ t = qstate.openq;
+ break;
+ case qstate.openq:
+ if (c == '"')
+ t = qstate.xq;
+ break;
+ case qstate.xq:
+ if (c == '"') {
+ t = qstate.openq;
+ break;
+ }
+ if (c == ',') {
+ t = qstate.normal;
+ continue;
+ }
+ t = qstate.normal;
+ break;
+ }
+ curs = curs + String::new(c);
+ cur++;
+ }
+ if (t != qstate.normal)
+ raise invalid_argument("readcsv: unexpected end of csv line", 0, s);
+ ss[dim(ss)] = curs;
+ return ss;
+ }
+
public int rindex(string target, string pattern) {
int pl = length(pattern);
for (int i = length(target) - pl; i >= 0; --i) {
@@ -40,4 +157,121 @@
return ss;
}
+ public string chomp(string s) {
+ if (s == "")
+ return s;
+ int l = length(s);
+ int i = 0;
+ while(i < l && Ctype::isspace(s[i]))
+ i++;
+ int j = l - 1;
+ while(j >= 0 && Ctype::isspace(s[j]))
+ --j;
+ return substr(s, i, j - i + 1);
+ }
+
+ public bool inchars(int c, string s) {
+ return index(String::new(c), s) >= 0;
+ }
+
+ public typedef struct {
+ string oq, cq, qq;
+ } quote_context;
+
+ typedef enum {normal, openq, xq} qstate;
+
+ public string _dequote(string s, quote_context q) {
+ string result = "";
+ qstate t = qstate.normal;
+ for (int cur = 0; cur < length(s); cur++) {
+ int c = s[cur];
+ switch(t) {
+ case qstate.normal:
+ if (inchars(c, q.oq)) {
+ t = qstate.openq;
+ continue;
+ }
+ raise invalid_argument("_dequote: leading garbage", 0, s);
+ break;
+ case qstate.openq:
+ if (inchars(c, q.qq)) {
+ t = qstate.xq;
+ continue;
+ }
+ if (inchars(c, q.cq)) {
+ if (cur != length(s) - 1)
+ raise invalid_argument("_dequote: trailing garbage", 0, s);
+ continue;
+ }
+ break;
+ case qstate.xq:
+ t = qstate.openq;
+ break;
+ }
+ result = result + String::new(c);
+ }
+ if (q.qq == q.cq && t == qstate.xq)
+ return result;
+ raise invalid_argument("_dequote: unexpected end of string", 0, s);
+ }
+
+ public quote_context default_quotes = {
+ oq = "\"", cq = "\"", qq = "\\"
+ };
+
+ public string dequote(string s) {
+ return _dequote(s, default_quotes);
+ }
+
+ public string[*] readcsv(string s) {
+ string[...] ss = {};
+ if (s == "" || s == "\n" || s == "\r\n")
+ return ss;
+ quote_context q = default_quotes;
+ q.qq = "\"";
+ string curs = "";
+ qstate t = qstate.normal;
+ int cur = 0;
+ while (cur < length(s)) {
+ int c = s[cur];
+# printf("%d: %c %v\n", cur, c, t);
+ switch(t) {
+ case qstate.normal:
+ if (c == ',') {
+ string t = chomp(curs);
+ if (t != "" && t[0] == '"')
+ t = _dequote(t, q);
+ ss[dim(ss)] = t;
+ curs = "";
+ cur++;
+ continue;
+ }
+ if (c == '"')
+ t = qstate.openq;
+ break;
+ case qstate.openq:
+ if (c == '"')
+ t = qstate.xq;
+ break;
+ case qstate.xq:
+ if (c == '"') {
+ t = qstate.openq;
+ break;
+ }
+ if (c == ',') {
+ t = qstate.normal;
+ continue;
+ }
+ t = qstate.normal;
+ break;
+ }
+ curs = curs + String::new(c);
+ cur++;
+ }
+ if (t != qstate.normal)
+ raise invalid_argument("readcsv: unexpected end of csv line", 0, s);
+ ss[dim(ss)] = curs;
+ return ss;
+ }
+
}
More information about the Commit
mailing list