summaryrefslogtreecommitdiff
path: root/src/gmutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gmutil.c')
-rw-r--r--src/gmutil.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/gmutil.c b/src/gmutil.c
index 98e4d4d6..e59e6649 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -131,6 +131,16 @@ static iRangecc prevPathSeg_(const char *end, const char *start) {
131 return seg; 131 return seg;
132} 132}
133 133
134void stripUrlPort_String(iString *d) {
135 iUrl parts;
136 init_Url(&parts, d);
137 if (!isEmpty_Range(&parts.port)) {
138 /* Always preceded by a colon. */
139 remove_Block(&d->chars, parts.port.start - 1 - constBegin_String(d),
140 size_Range(&parts.port) + 1);
141 }
142}
143
134void stripDefaultUrlPort_String(iString *d) { 144void stripDefaultUrlPort_String(iString *d) {
135 iUrl parts; 145 iUrl parts;
136 init_Url(&parts, d); 146 init_Url(&parts, d);
@@ -248,6 +258,9 @@ iRangecc urlRoot_String(const iString *d) {
248 else { 258 else {
249 iUrl parts; 259 iUrl parts;
250 init_Url(&parts, d); 260 init_Url(&parts, d);
261 if (equalCase_Rangecc(parts.scheme, "about")) {
262 return (iRangecc){ constBegin_String(d), parts.path.start };
263 }
251 rootEnd = parts.path.start; 264 rootEnd = parts.path.start;
252 } 265 }
253 return (iRangecc){ constBegin_String(d), rootEnd }; 266 return (iRangecc){ constBegin_String(d), rootEnd };
@@ -681,6 +694,17 @@ const iString *withSpacesEncoded_String(const iString *d) {
681 return d; 694 return d;
682} 695}
683 696
697const iString *withScheme_String(const iString *d, const char *scheme) {
698 iUrl parts;
699 init_Url(&parts, d);
700 if (!equalCase_Rangecc(parts.scheme, scheme)) {
701 iString *repl = collectNewCStr_String(scheme);
702 appendRange_String(repl, (iRangecc){ parts.scheme.end, constEnd_String(d) });
703 return repl;
704 }
705 return d;
706}
707
684const iString *canonicalUrl_String(const iString *d) { 708const iString *canonicalUrl_String(const iString *d) {
685 /* The "canonical" form, used for internal storage and comparisons, is: 709 /* The "canonical" form, used for internal storage and comparisons, is:
686 - all non-reserved characters decoded (i.e., it's an IRI) 710 - all non-reserved characters decoded (i.e., it's an IRI)
@@ -880,3 +904,41 @@ const iGmError *get_GmError(enum iGmStatusCode code) {
880 iAssert(errors_[0].code == unknownStatusCode_GmStatusCode); 904 iAssert(errors_[0].code == unknownStatusCode_GmStatusCode);
881 return &errors_[0].err; /* unknown */ 905 return &errors_[0].err; /* unknown */
882} 906}
907
908int replaceRegExp_String(iString *d, const iRegExp *regexp, const char *replacement,
909 void (*matchHandler)(void *, const iRegExpMatch *),
910 void *context) {
911 iRegExpMatch m;
912 iString result;
913 int numMatches = 0;
914 const char *pos = constBegin_String(d);
915 init_RegExpMatch(&m);
916 init_String(&result);
917 while (matchString_RegExp(regexp, d, &m)) {
918 appendRange_String(&result, (iRangecc){ pos, begin_RegExpMatch(&m) });
919 /* Replace any capture group back-references. */
920 for (const char *ch = replacement; *ch; ch++) {
921 if (*ch == '\\') {
922 ch++;
923 if (*ch == '\\') {
924 appendCStr_String(&result, "\\");
925 }
926 else if (*ch >= '0' && *ch <= '9') {
927 appendRange_String(&result, capturedRange_RegExpMatch(&m, *ch - '0'));
928 }
929 }
930 else {
931 appendData_Block(&result.chars, ch, 1);
932 }
933 }
934 if (matchHandler) {
935 matchHandler(context, &m);
936 }
937 pos = end_RegExpMatch(&m);
938 numMatches++;
939 }
940 appendRange_String(&result, (iRangecc){ pos, constEnd_String(d) });
941 set_String(d, &result);
942 deinit_String(&result);
943 return numMatches;
944}