#include "ml-string.h"
#include "ml.h"
+#include "ml-texp.h"
#include "mlenv.h"
#include "motorenv.h"
#include "motoroutput.h"
*/
/*DOC:
+===eq===
+ (eq STRING STRING...) -> 1 or NIL
+ (string-eq STRING STRING...) -> 1 or NIL
+
+全てのSTRINGが同じ時、1を返す。
+
+*/
+//#AFUNC eq ml_string_eq
+//#AFUNC string-eq ml_string_eq
+//#WIKIFUNC eq
+//#WIKIFUNC string-eq
+MNode* ml_string_eq (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring v1, v2;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+
+ v1 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ while (arg) {
+ v2 = eval_str (arg->car (), mlenv);
+ if (v1 == v2) {
+ } else {
+ return newMNode_bool (false);
+ }
+ nextNode (arg);
+ }
+ return newMNode_bool (true);
+}
+
+/*DOC:
+===ne===
+ (ne STRING STRING) -> 1 or NIL
+ (string-ne STRING STRING) -> 1 or NIL
+
+STRINGが異なる時、1を返す。
+
+*/
+//#AFUNC ne ml_string_ne
+//#AFUNC string-ne ml_string_ne
+//#WIKIFUNC ne
+//#WIKIFUNC string-ne
+MNode* ml_string_ne (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring v1, v2;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+
+ v1 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (! arg)
+ throw (uErrorWrongNumber);
+ v2 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ return newMNode_bool (v1 != v2);
+}
+
+//#AFUNC lt ml_string_lt
+//#AFUNC string-lt ml_string_lt
+//#WIKIFUNC lt
+//#WIKIFUNC string-lt
+MNode* ml_string_lt (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring v1, v2;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ v1 = eval_str (arg->car (), mlenv);
+ nextNodeNonNil (arg);
+ v2 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ return newMNode_bool (v1 < v2);
+}
+
+//#AFUNC le ml_string_le
+//#AFUNC string-le ml_string_le
+//#WIKIFUNC le
+//#WIKIFUNC string-le
+MNode* ml_string_le (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring v1, v2;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ v1 = eval_str (arg->car (), mlenv);
+ nextNodeNonNil (arg);
+ v2 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ return newMNode_bool (v1 <= v2);
+}
+
+//#AFUNC gt ml_string_gt
+//#AFUNC string-gt ml_string_gt
+//#WIKIFUNC gt
+//#WIKIFUNC string-gt
+MNode* ml_string_gt (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring v1, v2;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ v1 = eval_str (arg->car (), mlenv);
+ nextNodeNonNil (arg);
+ v2 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ return newMNode_bool (v1 > v2);
+}
+
+//#AFUNC ge ml_string_ge
+//#AFUNC string-ge ml_string_ge
+//#WIKIFUNC ge
+//#WIKIFUNC string-ge
+MNode* ml_string_ge (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring v1, v2;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ v1 = eval_str (arg->car (), mlenv);
+ nextNodeNonNil (arg);
+ v2 = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ return newMNode_bool (v1 >= v2);
+}
+
+/*DOC:
+===emptyp===
+ (emptyp TEXT...) -> 1 or NIL
+
+文字列TEXTの長さが0の時、1を返す。
+
+*/
+//#AFUNC emptyp ml_emptyp
+//#WIKIFUNC emptyp
+MNode* ml_emptyp (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring u;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+
+ while (arg) {
+ u = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (u.size () > 0)
+ return newMNode_bool (false);
+ }
+ return newMNode_bool (true);
+}
+
+/*DOC:
+===not-emptyp===
+ (not-emptyp TEXT...) -> 1 or NIL
+
+文字列TEXTの長さが0でない時、1を返す。
+
+*/
+//#AFUNC not-emptyp ml_not_emptyp
+//#WIKIFUNC not-emptyp
+MNode* ml_not_emptyp (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring u;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+
+ while (arg) {
+ u = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (u.size () == 0)
+ return newMNode_bool (false);
+ }
+ return newMNode_bool (true);
+}
+
+/*DOC:
===concat===
(concat STRING...) -> STRING
-パラメータの文字列を連結して一つの文字列を返す。
+パラメータの文字列STRINGを連結して一つの文字列を返す。
*/
//#AFUNC concat ml_concat
===megabyte===
(megabyte NUMBER) -> STRING
+数値NUMBERをK、M、G、T、P単位(1024の倍数)の文字列に変換する。
+
*/
//#AFUNC megabyte ml_megabyte
//#WIKIFUNC megabyte
===c3===
(c3 INTEGER) -> STRING
+数値INTEGERを3桁ごとにカンマ区切りの文字列に変換する。
+
*/
//#AFUNC c3 ml_c3
//#WIKIFUNC c3
if (keywords[0] && eval_bool (keywords[0], mlenv))
f |= boost::regex_constants::icase;
- ans = wsearch_env (mlenv, text, reg, f);
+ ans = wsearch_env (mlenv->regenv, text, reg, f);
return newMNode_bool (ans);
}
if (arg)
throw (uErrorWrongNumber);
- if (0 <= n && n < mlenv->regmatch.size ()) {
- ans = newMNode_str (new ustring (wtou (std::wstring (mlenv->regmatch[n].first, mlenv->regmatch[n].second))));
+ if (0 <= n && n < mlenv->regenv.regmatch.size ()) {
+ ans = newMNode_str (new ustring (wtou (std::wstring (mlenv->regenv.regmatch[n].first, mlenv->regenv.regmatch[n].second))));
}
return ans;
MNode* ml_prematch (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
MNode* ans = NULL;
- std::wstring::const_iterator b = mlenv->regtext.begin ();
+ std::wstring::const_iterator b = mlenv->regenv.regtext.begin ();
if (arg)
throw (uErrorWrongNumber);
- ans = newMNode_str (new ustring (wtou (std::wstring (b, mlenv->regmatch[0].first))));
+ ans = newMNode_str (new ustring (wtou (std::wstring (b, mlenv->regenv.regmatch[0].first))));
return ans;
}
MNode* ml_postmatch (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
MNode* ans = NULL;
- std::wstring::const_iterator e = mlenv->regtext.end ();
+ std::wstring::const_iterator e = mlenv->regenv.regtext.end ();
if (arg)
throw (uErrorWrongNumber);
- ans = newMNode_str (new ustring (wtou (std::wstring (mlenv->regmatch[0].second, e))));
+ ans = newMNode_str (new ustring (wtou (std::wstring (mlenv->regenv.regmatch[0].second, e))));
return ans;
}
if (keywords[0] && eval_bool (keywords[0], mlenv))
f |= boost::regex_constants::icase;
if (evkw (1, t)) {
- max = to_int (t ());
- if (max < 0)
+ int num = to_int (t ());
+ if (num < 0) {
max = 0;
+ } else {
+ max = num;
+ }
}
- if (wsearch_env (mlenv, text, reg, f)) {
- ustring ans = wtou (std::wstring (mlenv->regmatch[0].first, mlenv->regmatch[0].second));
+ if (wsearch_env (mlenv->regenv, text, reg, f)) {
+ ustring ans = wtou (std::wstring (mlenv->regenv.regmatch[0].first, mlenv->regenv.regmatch[0].second));
if (max > 0) {
substring (ans, 0, max, true, ans);
}
if (keywords[0] && eval_bool (keywords[0], mlenv))
f |= boost::regex_constants::icase;
- if (wsearch_env (mlenv, text, reg, f)) {
- std::wstring::const_iterator b = mlenv->regtext.begin ();
- std::wstring::const_iterator e = mlenv->regtext.end ();
- ans.append (newMNode_str (new ustring (wtou (std::wstring (b, mlenv->regmatch[0].first)))));
- ans.append (newMNode_str (new ustring (wtou (std::wstring (mlenv->regmatch[0].second, e)))));
+ if (wsearch_env (mlenv->regenv, text, reg, f)) {
+ std::wstring::const_iterator b = mlenv->regenv.regtext.begin ();
+ std::wstring::const_iterator e = mlenv->regenv.regtext.end ();
+ ans.append (newMNode_str (new ustring (wtou (std::wstring (b, mlenv->regenv.regmatch[0].first)))));
+ ans.append (newMNode_str (new ustring (wtou (std::wstring (mlenv->regenv.regmatch[0].second, e)))));
} else {
ans.append (newMNode_str (new ustring (text)));
ans.append (NULL);
/*DOC:
===split===
- (split REGEX STRING) -> STRING_LIST
+ (split REGEX STRING [#keep] [#i]) -> STRING_LIST
+ (split REGEX STRING #vector [#keep] [#i]) -> STRING_VECTOR
*/
//#AFUNC split ml_split
MNode* ml_split (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
ustring reg;
- ustring t;
- MNodeList ans;
-
- if (! arg)
- throw (uErrorWrongNumber);
-
- reg = eval_str (arg->car (), mlenv);
- nextNodeNonNil (arg);
- t = eval_str (arg->car (), mlenv);
- nextNode (arg);
-
- if (arg)
- throw (uErrorWrongNumber);
-
- try {
- std::wstring wt = utow (t);
- std::wstring wreg = utow (reg);
- boost::wregex wre (wreg);
- WSplitter sp (wt, wre);
- size_t m = wt.length () + 1;
+ ustring text;
+ bool flagKeep = false;
+ bool flagVector = false;
+ ListMakerPtr ans;
+ std::vector<MNode*> params;
+ std::vector<MNode*> keywords;
+ static paramList kwlist[] = {
+ {CharConst ("keep"), true}, // 空フィールドの削除をしない
+ {CharConst ("vector"), true},
+// {CharConst ("i"), true},
+ {NULL, 0, 0}
+ };
- while (sp.next ()) {
- ans.append (newMNode_str (new ustring (sp.cur ())));
- m --;
- if (m == 0)
- throw (uErrorRegexp);
+ setParams (arg, 2, ¶ms, kwlist, &keywords, NULL);
+ reg = eval_str (params[0], mlenv);
+ text = eval_str (params[1], mlenv);
+ if (keywords[0] && eval_bool (keywords[0], mlenv))
+ flagKeep = true;
+ if (keywords[1] && eval_bool (keywords[1], mlenv))
+ flagVector = true;
+// if (keywords[1] && eval_bool (keywords[1], mlenv))
+// flagReg |= boost::regex_constants::icase;
+ if (flagVector)
+ ans = new ListMakerVector;
+ else
+ ans = new ListMakerList;
+
+ if (reg.length () == 0) {
+ uiterator b = text.begin ();
+ uiterator e = text.end ();
+ uiterator s;
+ while (b < e) {
+ s = b;
+ nextChar (b, e);
+ ans.append (newMNode_str (new ustring (s, b)));
+ }
+ } else {
+ try {
+ std::wstring wt = utow (text);
+ std::wstring wreg = utow (reg);
+ boost::wregex wre (wreg);
+ WSplitter sp (wt, wre);
+ size_t m = wt.length () + 1;
+
+ bool (WSplitter::*nfn)();
+ if (flagKeep)
+ nfn = &WSplitter::nextSep;
+ else
+ nfn = &WSplitter::next;
+ while ((sp.*nfn) ()) {
+ ans.append (newMNode_str (new ustring (sp.cur ())));
+ m --;
+ if (m == 0)
+ throw (uErrorRegexp);
+ }
+ if (flagKeep)
+ ans.append (newMNode_str (new ustring (sp.cur ())));
+ } catch (boost::regex_error& err) {
+ throw (uErrorRegexp);
}
- } catch (boost::regex_error& err) {
- throw (uErrorRegexp);
}
return ans.release ();
}
/*DOC:
===string-join===
- (string-join TEXT [STRING | ARRAY | LIST]...) -> STRING
+ (string-join TEXT [STRING | ARRAY | LIST | VECTOR]...) -> STRING
*/
//#AFUNC string-join ml_string_join
if (! isNil (a->car ()))
ans.append (a->car ()->to_string ());
}
+ } else if (val ()->isVector ()) {
+ size_t n = val ()->vectorSize ();
+ size_t i;
+ for (i = 0; i < n; ++ i) {
+ if (i > 0)
+ ans.append (sep);
+ MNode* a = val ()->vectorGet (i);
+ if (! isNil (a))
+ ans.append (a->to_string ());
+ }
} else {
var = val ()->to_string ();
if (c == 0)
/*DOC:
===password-crypt===
- (password-crypt PASSWORD) -> STRING
+ (password-crypt PASSWORD [#md5 | #sha256 | #sha512]) -> STRING
+
+deprecated.
*/
//#AFUNC password-crypt ml_password_crypt
MNode* ml_password_crypt (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
ustring pass;
+ passCryptFormat format;
+ std::vector<MNode*> params;
+ std::vector<MNode*> keywords;
+ static paramList kwlist[] = {
+ {CharConst ("md5"), true},
+ {CharConst ("sha256"), true},
+ {CharConst ("sha512"), true},
+// {CharConst ("bf"), true},
+ {NULL, 0, 0}
+ };
- if (! arg)
- throw (uErrorWrongNumber);
- pass = eval_str (arg->car (), mlenv);
- nextNode (arg);
- if (arg)
- throw (uErrorWrongNumber);
+ format = FORMAT_MD5;
+ setParams (arg, 1, ¶ms, kwlist, &keywords, NULL);
+ pass = eval_str (params[0], mlenv);
+ if (keywords[0] && eval_bool (keywords[0], mlenv))
+ format = FORMAT_MD5;
+ if (keywords[1] && eval_bool (keywords[1], mlenv))
+ format = FORMAT_SHA256;
+ if (keywords[2] && eval_bool (keywords[2], mlenv))
+ format = FORMAT_SHA512;
+// if (keywords[3] && eval_bool (keywords[3], mlenv))
+// format = FORMAT_BF;
- return newMNode_str (new ustring (passCrypt (pass)));
+ return newMNode_str (new ustring (passCrypt (pass, format)));
}
/*DOC:
(substring STR INDEX LENGTH) -> STRING
(substring STR INDEX) -> STRING
+INDEX number of the first character of STR is 0.
+
*/
//#AFUNC substring ml_substring
//#WIKIFUNC substring
}
/*DOC:
+===tail-substring===
+ (tail-substring STR INDEX LENGTH) -> STRING
+ (tail-substring STR INDEX) -> STRING
+
+INDEX number of the last character of STR is 0.
+
+*/
+//#AFUNC tail-substring ml_tail_substring
+//#WIKIFUNC tail-substring
+MNode* ml_tail_substring (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring str;
+ size_t index;
+ size_t length;
+ int mode;
+ ustring ans;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ str = eval_str (arg->car (), mlenv);
+ nextNodeNonNil (arg);
+ index = eval_int (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg) {
+ mode = 3;
+ length = eval_int (arg->car (), mlenv);
+ nextNode (arg);
+ } else {
+ mode = 2;
+ }
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ size_t s = strLength (str);
+ if (mode == 3)
+ substring (str, s - index - 1, length, 1, ans);
+ else
+ substring (str, s - index - 1, 0, 0, ans);
+ return newMNode_str (new ustring (ans));
+}
+
+/*DOC:
===length===
(length STRING) -> NUMBER
}
/*DOC:
+===byte-length===
+ (byte-length STRING) -> NUMBER
+
+*/
+//#AFUNC byte-length ml_byte_length
+//#WIKIFUNC byte-length
+MNode* ml_byte_length (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring str;
+ size_t ans;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ str = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ ans = str.length ();
+ return newMNode_num (ans);
+}
+
+/*DOC:
===pad0===
(pad0 NUMBER STRING) -> STRING
(pad0 NUMBER STRING_LIST) -> STRING_LIST
}
/*DOC:
-===dump-to-sexp===
+===to-symbol===
+ (to-symbol STRING) -> SYMBOL
+
+*/
+//#AFUNC to-symbol ml_to_symbol
+//#WIKIFUNC to-symbol
+MNode* ml_to_symbol (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ MNodePtr text;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ text = eval (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ if (text ()) {
+ if (text ()->isSym ()) {
+ return text.release ();
+ } else {
+ return newMNode_sym (new ustring (text ()->to_string ()));
+ }
+ } else {
+ return NULL;
+ }
+}
+
+/*DOC:
+===dump-to-texp, dump-to-sexp===
+ (dump-to-texp OBJECT...) -> STRING
(dump-to-sexp OBJECT...) -> STRING
*/
-//#AFUNC dump-to-sexp ml_dump_to_sexp
+//#AFUNC dump-to-texp ml_dump_to_texp
+//#AFUNC dump-to-sexp ml_dump_to_texp
+//#WIKIFUNC dump-to-texp
//#WIKIFUNC dump-to-sexp
-MNode* ml_dump_to_sexp (MNode* cell, MlEnv* mlenv) {
+MNode* ml_dump_to_texp (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
MNodePtr e;
ustring text;
while (arg) {
-// text = eval_str (arg->car (), mlenv);
e = eval (arg->car (), mlenv);
nextNode (arg);
if (text.length () > 0)
text.append (CharConst (" "));
- text.append (dump_to_sexp (e ()));
+ text.append (dump_to_texp (e ()));
}
return newMNode_str (new ustring (text));
}
/*DOC:
//===to-sexp===
// (to-sexp STRING) -> OBJECT
-===read-sexp===
+===read-texp, read-sexp===
(read-sexp STRING) -> OBJECT
+ (read-texp STRING) -> OBJECT
*/
// //#AFUNC to-sexp ml_to_sexp
// //#WIKIFUNC to-sexp
-//#AFUNC read-sexp ml_read_sexp
+//#AFUNC read-texp ml_read_texp
+//#AFUNC read-sexp ml_read_texp
+//#WIKIFUNC read-texp
//#WIKIFUNC read-sexp
-//MNode* ml_to_sexp (MNode* cell, MlEnv* mlenv) {
-MNode* ml_read_sexp (MNode* cell, MlEnv* mlenv) {
+MNode* ml_read_texp (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
ustring text;
- MotorSexp ml (NULL);
+ MotorTexp ml (NULL);
if (! arg)
throw (uErrorWrongNumber);
if (arg)
throw (uErrorWrongNumber);
- ans = checkASCII (text);
+// ans = checkASCII (text);
+ ans = matchASCII (text.begin (), text.end ());
return newMNode_bool (ans);
}
return newMNode_str (new ustring (toLower (text)));
}
+
+/*DOC:
+===hex-to-dec===
+ (hex-to-dec STRING) -> NUMBER
+
+*/
+//#AFUNC hex-to-dec ml_hex_to_dec
+//#WIKIFUNC hex-to-dec
+MNode* ml_hex_to_dec (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ ustring text;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+ text = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+ if (arg)
+ throw (uErrorWrongNumber);
+ if (text.length () > 8)
+ throw (uErrorBadArg);
+
+ return newMNode_num (hextoul (text.begin (), text.end ()));
+}