strorder.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /* Copyright 1995-1996,1999-2000,2004,2006,2008-2010,2018
  2. Free Software Foundation, Inc.
  3. This file is part of Guile.
  4. Guile is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Guile is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with Guile. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #ifdef HAVE_CONFIG_H
  16. # include <config.h>
  17. #endif
  18. #include "boolean.h"
  19. #include "chars.h"
  20. #include "gsubr.h"
  21. #include "pairs.h"
  22. #include "srfi-13.h"
  23. #include "strings.h"
  24. #include "symbols.h"
  25. #include "strorder.h"
  26. SCM_C_INLINE_KEYWORD static SCM
  27. srfi13_cmp (SCM s1, SCM s2, SCM (*cmp) (SCM, SCM, SCM, SCM, SCM, SCM))
  28. {
  29. if (scm_is_true (cmp (s1, s2,
  30. SCM_UNDEFINED, SCM_UNDEFINED,
  31. SCM_UNDEFINED, SCM_UNDEFINED)))
  32. return SCM_BOOL_T;
  33. else
  34. return SCM_BOOL_F;
  35. }
  36. static SCM scm_i_string_equal_p (SCM s1, SCM s2, SCM rest);
  37. SCM_DEFINE (scm_i_string_equal_p, "string=?", 0, 2, 1,
  38. (SCM s1, SCM s2, SCM rest),
  39. "Lexicographic equality predicate; return @code{#t} if the two\n"
  40. "strings are the same length and contain the same characters in\n"
  41. "the same positions, otherwise return @code{#f}.\n"
  42. "\n"
  43. "The procedure @code{string-ci=?} treats upper and lower case\n"
  44. "letters as though they were the same character, but\n"
  45. "@code{string=?} treats upper and lower case as distinct\n"
  46. "characters.")
  47. #define FUNC_NAME s_scm_i_string_equal_p
  48. {
  49. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  50. return SCM_BOOL_T;
  51. while (!scm_is_null (rest))
  52. {
  53. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_eq)))
  54. return SCM_BOOL_F;
  55. s1 = s2;
  56. s2 = scm_car (rest);
  57. rest = scm_cdr (rest);
  58. }
  59. return srfi13_cmp (s1, s2, scm_string_eq);
  60. }
  61. #undef FUNC_NAME
  62. SCM scm_string_equal_p (SCM s1, SCM s2)
  63. #define FUNC_NAME s_scm_i_string_equal_p
  64. {
  65. return srfi13_cmp (s1, s2, scm_string_eq);
  66. }
  67. #undef FUNC_NAME
  68. static SCM scm_i_string_ci_equal_p (SCM s1, SCM s2, SCM rest);
  69. SCM_DEFINE (scm_i_string_ci_equal_p, "string-ci=?", 0, 2, 1,
  70. (SCM s1, SCM s2, SCM rest),
  71. "Case-insensitive string equality predicate; return @code{#t} if\n"
  72. "the two strings are the same length and their component\n"
  73. "characters match (ignoring case) at each position; otherwise\n"
  74. "return @code{#f}.")
  75. #define FUNC_NAME s_scm_i_string_ci_equal_p
  76. {
  77. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  78. return SCM_BOOL_T;
  79. while (!scm_is_null (rest))
  80. {
  81. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_ci_eq)))
  82. return SCM_BOOL_F;
  83. s1 = s2;
  84. s2 = scm_car (rest);
  85. rest = scm_cdr (rest);
  86. }
  87. return srfi13_cmp (s1, s2, scm_string_ci_eq);
  88. }
  89. #undef FUNC_NAME
  90. SCM scm_string_ci_equal_p (SCM s1, SCM s2)
  91. #define FUNC_NAME s_scm_i_string_ci_equal_p
  92. {
  93. return srfi13_cmp (s1, s2, scm_string_ci_eq);
  94. }
  95. #undef FUNC_NAME
  96. static SCM scm_i_string_less_p (SCM s1, SCM s2, SCM rest);
  97. SCM_DEFINE (scm_i_string_less_p, "string<?", 0, 2, 1,
  98. (SCM s1, SCM s2, SCM rest),
  99. "Lexicographic ordering predicate; return @code{#t} if @var{s1}\n"
  100. "is lexicographically less than @var{s2}.")
  101. #define FUNC_NAME s_scm_i_string_less_p
  102. {
  103. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  104. return SCM_BOOL_T;
  105. while (!scm_is_null (rest))
  106. {
  107. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_lt)))
  108. return SCM_BOOL_F;
  109. s1 = s2;
  110. s2 = scm_car (rest);
  111. rest = scm_cdr (rest);
  112. }
  113. return srfi13_cmp (s1, s2, scm_string_lt);
  114. }
  115. #undef FUNC_NAME
  116. SCM scm_string_less_p (SCM s1, SCM s2)
  117. #define FUNC_NAME s_scm_i_string_less_p
  118. {
  119. return srfi13_cmp (s1, s2, scm_string_lt);
  120. }
  121. #undef FUNC_NAME
  122. static SCM scm_i_string_leq_p (SCM s1, SCM s2, SCM rest);
  123. SCM_DEFINE (scm_i_string_leq_p, "string<=?", 0, 2, 1,
  124. (SCM s1, SCM s2, SCM rest),
  125. "Lexicographic ordering predicate; return @code{#t} if @var{s1}\n"
  126. "is lexicographically less than or equal to @var{s2}.")
  127. #define FUNC_NAME s_scm_i_string_leq_p
  128. {
  129. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  130. return SCM_BOOL_T;
  131. while (!scm_is_null (rest))
  132. {
  133. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_le)))
  134. return SCM_BOOL_F;
  135. s1 = s2;
  136. s2 = scm_car (rest);
  137. rest = scm_cdr (rest);
  138. }
  139. return srfi13_cmp (s1, s2, scm_string_le);
  140. }
  141. #undef FUNC_NAME
  142. SCM scm_string_leq_p (SCM s1, SCM s2)
  143. #define FUNC_NAME s_scm_i_string_leq_p
  144. {
  145. return srfi13_cmp (s1, s2, scm_string_le);
  146. }
  147. #undef FUNC_NAME
  148. static SCM scm_i_string_gr_p (SCM s1, SCM s2, SCM rest);
  149. SCM_DEFINE (scm_i_string_gr_p, "string>?", 0, 2, 1,
  150. (SCM s1, SCM s2, SCM rest),
  151. "Lexicographic ordering predicate; return @code{#t} if @var{s1}\n"
  152. "is lexicographically greater than @var{s2}.")
  153. #define FUNC_NAME s_scm_i_string_gr_p
  154. {
  155. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  156. return SCM_BOOL_T;
  157. while (!scm_is_null (rest))
  158. {
  159. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_gt)))
  160. return SCM_BOOL_F;
  161. s1 = s2;
  162. s2 = scm_car (rest);
  163. rest = scm_cdr (rest);
  164. }
  165. return srfi13_cmp (s1, s2, scm_string_gt);
  166. }
  167. #undef FUNC_NAME
  168. SCM scm_string_gr_p (SCM s1, SCM s2)
  169. #define FUNC_NAME s_scm_i_string_gr_p
  170. {
  171. return srfi13_cmp (s1, s2, scm_string_gt);
  172. }
  173. #undef FUNC_NAME
  174. static SCM scm_i_string_geq_p (SCM s1, SCM s2, SCM rest);
  175. SCM_DEFINE (scm_i_string_geq_p, "string>=?", 0, 2, 1,
  176. (SCM s1, SCM s2, SCM rest),
  177. "Lexicographic ordering predicate; return @code{#t} if @var{s1}\n"
  178. "is lexicographically greater than or equal to @var{s2}.")
  179. #define FUNC_NAME s_scm_i_string_geq_p
  180. {
  181. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  182. return SCM_BOOL_T;
  183. while (!scm_is_null (rest))
  184. {
  185. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_ge)))
  186. return SCM_BOOL_F;
  187. s1 = s2;
  188. s2 = scm_car (rest);
  189. rest = scm_cdr (rest);
  190. }
  191. return srfi13_cmp (s1, s2, scm_string_ge);
  192. }
  193. #undef FUNC_NAME
  194. SCM scm_string_geq_p (SCM s1, SCM s2)
  195. #define FUNC_NAME s_scm_i_string_geq_p
  196. {
  197. return srfi13_cmp (s1, s2, scm_string_ge);
  198. }
  199. #undef FUNC_NAME
  200. static SCM scm_i_string_ci_less_p (SCM s1, SCM s2, SCM rest);
  201. SCM_DEFINE (scm_i_string_ci_less_p, "string-ci<?", 0, 2, 1,
  202. (SCM s1, SCM s2, SCM rest),
  203. "Case insensitive lexicographic ordering predicate; return\n"
  204. "@code{#t} if @var{s1} is lexicographically less than @var{s2}\n"
  205. "regardless of case.")
  206. #define FUNC_NAME s_scm_i_string_ci_less_p
  207. {
  208. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  209. return SCM_BOOL_T;
  210. while (!scm_is_null (rest))
  211. {
  212. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_ci_lt)))
  213. return SCM_BOOL_F;
  214. s1 = s2;
  215. s2 = scm_car (rest);
  216. rest = scm_cdr (rest);
  217. }
  218. return srfi13_cmp (s1, s2, scm_string_ci_lt);
  219. }
  220. #undef FUNC_NAME
  221. SCM scm_string_ci_less_p (SCM s1, SCM s2)
  222. #define FUNC_NAME s_scm_i_string_ci_less_p
  223. {
  224. return srfi13_cmp (s1, s2, scm_string_ci_lt);
  225. }
  226. #undef FUNC_NAME
  227. static SCM scm_i_string_ci_leq_p (SCM s1, SCM s2, SCM rest);
  228. SCM_DEFINE (scm_i_string_ci_leq_p, "string-ci<=?", 0, 2, 1,
  229. (SCM s1, SCM s2, SCM rest),
  230. "Case insensitive lexicographic ordering predicate; return\n"
  231. "@code{#t} if @var{s1} is lexicographically less than or equal\n"
  232. "to @var{s2} regardless of case.")
  233. #define FUNC_NAME s_scm_i_string_ci_leq_p
  234. {
  235. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  236. return SCM_BOOL_T;
  237. while (!scm_is_null (rest))
  238. {
  239. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_ci_le)))
  240. return SCM_BOOL_F;
  241. s1 = s2;
  242. s2 = scm_car (rest);
  243. rest = scm_cdr (rest);
  244. }
  245. return srfi13_cmp (s1, s2, scm_string_ci_le);
  246. }
  247. #undef FUNC_NAME
  248. SCM scm_string_ci_leq_p (SCM s1, SCM s2)
  249. #define FUNC_NAME s_scm_i_string_ci_leq_p
  250. {
  251. return srfi13_cmp (s1, s2, scm_string_ci_le);
  252. }
  253. #undef FUNC_NAME
  254. static SCM scm_i_string_ci_gr_p (SCM s1, SCM s2, SCM rest);
  255. SCM_DEFINE (scm_i_string_ci_gr_p, "string-ci>?", 0, 2, 1,
  256. (SCM s1, SCM s2, SCM rest),
  257. "Case insensitive lexicographic ordering predicate; return\n"
  258. "@code{#t} if @var{s1} is lexicographically greater than\n"
  259. "@var{s2} regardless of case.")
  260. #define FUNC_NAME s_scm_i_string_ci_gr_p
  261. {
  262. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  263. return SCM_BOOL_T;
  264. while (!scm_is_null (rest))
  265. {
  266. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_ci_gt)))
  267. return SCM_BOOL_F;
  268. s1 = s2;
  269. s2 = scm_car (rest);
  270. rest = scm_cdr (rest);
  271. }
  272. return srfi13_cmp (s1, s2, scm_string_ci_gt);
  273. }
  274. #undef FUNC_NAME
  275. SCM scm_string_ci_gr_p (SCM s1, SCM s2)
  276. #define FUNC_NAME s_scm_i_string_ci_gr_p
  277. {
  278. return srfi13_cmp (s1, s2, scm_string_ci_gt);
  279. }
  280. #undef FUNC_NAME
  281. static SCM scm_i_string_ci_geq_p (SCM s1, SCM s2, SCM rest);
  282. SCM_DEFINE (scm_i_string_ci_geq_p, "string-ci>=?", 0, 2, 1,
  283. (SCM s1, SCM s2, SCM rest),
  284. "Case insensitive lexicographic ordering predicate; return\n"
  285. "@code{#t} if @var{s1} is lexicographically greater than or\n"
  286. "equal to @var{s2} regardless of case.")
  287. #define FUNC_NAME s_scm_i_string_ci_geq_p
  288. {
  289. if (SCM_UNBNDP (s1) || SCM_UNBNDP (s2))
  290. return SCM_BOOL_T;
  291. while (!scm_is_null (rest))
  292. {
  293. if (scm_is_false (srfi13_cmp (s1, s2, scm_string_ci_ge)))
  294. return SCM_BOOL_F;
  295. s1 = s2;
  296. s2 = scm_car (rest);
  297. rest = scm_cdr (rest);
  298. }
  299. return srfi13_cmp (s1, s2, scm_string_ci_ge);
  300. }
  301. #undef FUNC_NAME
  302. SCM scm_string_ci_geq_p (SCM s1, SCM s2)
  303. #define FUNC_NAME s_scm_i_string_ci_geq_p
  304. {
  305. return srfi13_cmp (s1, s2, scm_string_ci_ge);
  306. }
  307. #undef FUNC_NAME
  308. void
  309. scm_init_strorder ()
  310. {
  311. #include "strorder.x"
  312. }