Objectively
Object oriented framework for C.
Loading...
Searching...
No Matches
String.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include "Config.h"
25
26#include <assert.h>
27#include <iconv.h>
28#include <stdarg.h>
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32#include <wchar.h>
33
34#include "Hash.h"
35#include "String.h"
36
37#if defined(__MINGW32__)
38#define towlower_l _towlower_l
39#define towupper_l _towupper_l
40#endif
41
42#define _Class _String
43
44#pragma mark - Object
45
49static Object *copy(const Object *self) {
50
51 const String *this = (const String *) self;
52 String *that = $(alloc(String), initWithString, this);
53
54 return (Object *) that;
55}
56
60static void dealloc(Object *self) {
61
62 String *this = (String *) self;
63
64 free(this->chars);
65
66 super(Object, self, dealloc);
67}
68
72static String *description(const Object *self) {
73
74 return (String *) $((Object *) self, copy);
75}
76
80static int hash(const Object *self) {
81
82 String *this = (String *) self;
83
84 return HashForCString(HASH_SEED, this->chars);
85}
86
90static bool isEqual(const Object *self, const Object *other) {
91
92 if (super(Object, self, isEqual, other)) {
93 return true;
94 }
95
96 if (other && $(other, isKindOfClass, _String())) {
97
98 const String *this = (String *) self;
99 const String *that = (String *) other;
100
101 if (this->length == that->length) {
102
103 const Range range = { 0, this->length };
104 return $(this, compareTo, that, range) == OrderSame;
105 }
106 }
107
108 return false;
109}
110
111#pragma mark - String
112
117typedef struct {
120 char *in;
121 size_t length;
122 char *out;
123 size_t size;
124} Transcode;
125
131static size_t transcode(Transcode *trans) {
132
133 assert(trans);
134 assert(trans->to);
135 assert(trans->from);
136 assert(trans->out);
137 assert(trans->size);
138
139 iconv_t cd = iconv_open(NameForStringEncoding(trans->to), NameForStringEncoding(trans->from));
140 assert(cd != (iconv_t) -1);
141
142 char *in = trans->in;
143 char *out = trans->out;
144
145 size_t inBytesRemaining = trans->length;
146 size_t outBytesRemaining = trans->size;
147
148 const size_t ret = iconv(cd, &in, &inBytesRemaining, &out, &outBytesRemaining);
149 assert(ret != (size_t) -1);
150
151 int err = iconv_close(cd);
152 assert(err == 0);
153
154 return trans->size - outBytesRemaining;
155}
156
161static Order compareTo(const String *self, const String *other, const Range range) {
162
163 assert(range.location + range.length <= self->length);
164
165 if (other) {
166 const int i = strncmp(self->chars + range.location, other->chars, range.length);
167 if (i == 0) {
168 return OrderSame;
169 }
170 if (i > 0) {
171 return OrderDescending;
172 }
173 }
174
175 return OrderAscending;
176}
177
182static Array *componentsSeparatedByCharacters(const String *self, const char *chars) {
183
184 assert(chars);
185
186 Array *components = $(alloc(Array), init);
187
188 Range search = { 0, self->length };
189 Range result = $(self, rangeOfCharacters, chars, search);
190
191 while (result.length) {
192 search.length = result.location - search.location;
193
194 String *component = $(self, substring, search);
195 $(components, addObject, component);
196 release(component);
197
198 search.location = result.location + result.length;
199 search.length = self->length - search.location;
200
201 result = $(self, rangeOfCharacters, chars, search);
202 }
203
204 String *component = $(self, substring, search);
205 $(components, addObject, component);
206 release(component);
207
208 return components;
209}
210
215static Array *componentsSeparatedByString(const String *self, const String *string) {
216
217 assert(string);
218
220}
221
226static Data *getData(const String *self, StringEncoding encoding) {
227
228 Transcode trans = {
229 .to = encoding,
230 .from = STRING_ENCODING_UTF8,
231 .in = self->chars,
232 .length = self->length,
233 .out = calloc(self->length, sizeof(Unicode) / sizeof(char)),
234 .size = self->length * sizeof(Unicode)
235 };
236
237 assert(trans.out);
238
239 const size_t size = transcode(&trans);
240 assert(size <= trans.size);
241
242 return $$(Data, dataWithMemory, trans.out, size);
243}
244
249static bool hasPrefix(const String *self, const String *prefix) {
250
251 if (prefix->length > self->length) {
252 return false;
253 }
254
255 Range range = { 0, prefix->length };
256 return $(self, compareTo, prefix, range) == OrderSame;
257}
258
263static bool hasSuffix(const String *self, const String *suffix) {
264
265 if (suffix->length > self->length) {
266 return false;
267 }
268
269 Range range = { self->length - suffix->length, suffix->length };
270 return $(self, compareTo, suffix, range) == OrderSame;
271}
272
281static String *lowercaseString(const String *self) {
282
284 assert(data);
285
286 const size_t codepoints = data->length / sizeof(Unicode);
287 Unicode *unicode = (Unicode *) data->bytes;
288
289 for (size_t i = 0; i < codepoints; i++, unicode++) {
290 *unicode = towlower(*unicode);
291 }
292
294
295 release(data);
296 return lowercase;
297}
298
303static Range rangeOfCharacters(const String *self, const char *chars, const Range range) {
304
305 assert(chars);
306 assert(range.location > -1);
307 assert(range.length > 0);
308 assert(range.location + range.length <= self->length);
309
310 Range match = { -1, 0 };
311 const size_t len = strlen(chars);
312
313 const char *str = self->chars + range.location;
314 for (size_t i = 0; i < range.length; i++, str++) {
315 if (strncmp(str, chars, len) == 0) {
316 match.location = range.location + i;
317 match.length = len;
318 break;
319 }
320 }
321
322 return match;
323}
324
329static Range rangeOfString(const String *self, const String *string, const Range range) {
330
331 assert(string);
332
333 return $(self, rangeOfCharacters, string->chars, range);
334}
335
340static String *stringWithBytes(const uint8_t *bytes, size_t length, StringEncoding encoding) {
341
342 return $(alloc(String), initWithBytes, bytes, length, encoding);
343}
344
349static String *stringWithCharacters(const char *chars) {
350
351 return $(alloc(String), initWithCharacters, chars);
352}
353
358static String *stringWithContentsOfFile(const char *path, StringEncoding encoding) {
359
360 return $(alloc(String), initWithContentsOfFile, path, encoding);
361}
362
367static String *stringWithData(const Data *data, StringEncoding encoding) {
368
369 return $(alloc(String), initWithData, data, encoding);
370}
371
376static String *stringWithFormat(const char *fmt, ...) {
377
378 va_list args;
379 va_start(args, fmt);
380
381 String *string = $(alloc(String), initWithVaList, fmt, args);
382
383 va_end(args);
384
385 return string;
386}
387
392static String *stringWithMemory(const ident mem, size_t length) {
393
394 return $(alloc(String), initWithMemory, mem, length);
395}
396
401static String *substring(const String *self, const Range range) {
402
403 assert(range.location + range.length <= self->length);
404
405 ident mem = calloc(range.length + 1, sizeof(char));
406 assert(mem);
407
408 strncpy(mem, self->chars + range.location, range.length);
409
410 return $(alloc(String), initWithMemory, mem, range.length);
411}
412
417static String *trimmedString(const String *self) {
418
419 Range range = { .location = 0, .length = self->length };
420
421 while (isspace(self->chars[range.location])) {
422 range.location++;
423 range.length--;
424 }
425
426 while (range.length > 0 && isspace(self->chars[range.location + range.length - 1])) {
427 range.length--;
428 }
429
430 return $(self, substring, range);
431}
432
437static String *uppercaseString(const String *self) {
438
440 assert(data);
441
442 const size_t codepoints = data->length / sizeof(Unicode);
443 Unicode *unicode = (Unicode *) data->bytes;
444
445 for (size_t i = 0; i < codepoints; i++, unicode++) {
446 *unicode = towupper(*unicode);
447 }
448
450
451 release(data);
452 return uppercase;
453}
454
459static bool writeToFile(const String *self, const char *path, StringEncoding encoding) {
460
461 Data *data = $(self, getData, encoding);
462 assert(data);
463
464 const bool success = $(data, writeToFile, path);
465
466 release(data);
467 return success;
468}
469
470#pragma mark - String mutation
471
476static void appendBytes(String *self, const uint8_t *bytes, size_t length, StringEncoding encoding) {
477
478 if (bytes) {
479
480 Transcode trans = {
482 .from = encoding,
483 .in = (char *) bytes,
484 .length = length,
485 .out = calloc(length * sizeof(Unicode) + 1, sizeof(char)),
486 .size = length * sizeof(Unicode) + 1
487 };
488
489 assert(trans.out);
490
491 const size_t size = transcode(&trans);
492 assert(size < trans.size);
493
494 trans.out[size] = '\0';
495
496 $(self, appendCharacters, trans.out);
497
498 free(trans.out);
499 }
500}
501
506static void appendCharacters(String *self, const char *chars) {
507
508 if (chars) {
509
510 const size_t len = strlen(chars);
511 if (len) {
512
513 const size_t newSize = self->length + strlen(chars) + 1;
514 const size_t newCapacity = (newSize / _pageSize + 1) * _pageSize;
515
516 if (newCapacity > self->capacity) {
517
518 self->chars = realloc(self->chars, newCapacity);
519 assert(self->chars);
520 self->capacity = newCapacity;
521 }
522
523 ident ptr = self->chars + self->length;
524 memmove(ptr, chars, len);
525
526 self->chars[newSize - 1] = '\0';
527 self->length += len;
528 }
529 }
530}
531
536static void appendFormat(String *self, const char *fmt, ...) {
537
538 va_list args;
539 va_start(args, fmt);
540
541 $(self, appendVaList, fmt, args);
542
543 va_end(args);
544}
545
550static void appendString(String *self, const String *string) {
551
552 if (string) {
553 $(self, appendCharacters, string->chars);
554 }
555}
556
561static void appendVaList(String *self, const char *fmt, va_list args) {
562 char *chars;
563
564 const int len = vasprintf(&chars, fmt, args);
565 if (len > 0) {
566 $(self, appendCharacters, chars);
567 }
568
569 free(chars);
570}
571
576static void deleteCharactersInRange(String *self, const Range range) {
577
578 assert(range.location >= 0);
579 assert(range.length <= self->length);
580
581 ident ptr = self->chars + range.location;
582 const size_t length = self->length - range.location - range.length + 1;
583
584 memmove(ptr, ptr + range.length, length);
585
586 self->length -= range.length;
587}
588
593static String *init(String *self) {
594 return $(self, initWithCapacity, 0);
595}
596
601static String *initWithBytes(String *self, const uint8_t *bytes, size_t length, StringEncoding encoding) {
602
603 self = $(self, init);
604 if (self) {
605 $(self, appendBytes, bytes, length, encoding);
606 }
607
608 return self;
609}
610
615static String *initWithCapacity(String *self, size_t capacity) {
616
617 self = $(self, initWithMemory, NULL, 0);
618 if (self) {
619 self->capacity = capacity;
620 if (self->capacity) {
621 self->chars = calloc(self->capacity, sizeof(char));
622 assert(self->chars);
623 }
624 }
625
626 return self;
627}
628
633static String *initWithCharacters(String *self, const char *chars) {
634
635 self = $(self, init);
636 if (self) {
637 $(self, appendCharacters, chars);
638 }
639
640 return self;
641}
642
647static String *initWithContentsOfFile(String *self, const char *path, StringEncoding encoding) {
648
649 Data *data = $$(Data, dataWithContentsOfFile, path);
650 if (data) {
651 self = $(self, initWithData, data, encoding);
652 } else {
653 self = $(self, init);
654 }
655
656 release(data);
657 return self;
658}
659
664static String *initWithData(String *self, const Data *data, StringEncoding encoding) {
665
666 assert(data);
667
668 return $(self, initWithBytes, data->bytes, data->length, encoding);
669}
670
675static String *initWithFormat(String *self, const char *fmt, ...) {
676
677 self = $(self, init);
678 if (self) {
679
680 va_list args;
681 va_start(args, fmt);
682
683 $(self, appendVaList, fmt, args);
684
685 va_end(args);
686 }
687
688 return self;
689}
690
695static String *initWithMemory(String *self, const ident mem, size_t length) {
696
697 self = (String *) super(Object, self, init);
698 if (self) {
699 self->chars = (char *) mem;
700 self->length = length;
701 self->capacity = self->chars ? length + 1 : 0;
702 }
703
704 return self;
705}
706
711static String *initWithString(String *self, const String *string) {
712
713 self = $(self, init);
714 if (self) {
715 $(self, appendString, string);
716 }
717
718 return self;
719}
720
725static String *initWithVaList(String *self, const char *fmt, va_list args) {
726
727 self = $(self, init);
728 if (self) {
729 $(self, appendVaList, fmt, args);
730 }
731
732 return self;
733}
734
739static void insertCharactersAtIndex(String *self, const char *chars, size_t index) {
740
741 const Range range = { .location = index };
742
743 $(self, replaceCharactersInRange, range, chars);
744}
745
750static void insertStringAtIndex(String *self, const String *string, size_t index) {
751
752 $(self, insertCharactersAtIndex, string->chars, index);
753}
754
759static void replaceCharactersInRange(String *self, const Range range, const char *chars) {
760
761 assert(range.location >= 0);
762 assert(range.location + range.length <= self->length);
763
764 if (self->capacity == 0) {
765 $(self, appendCharacters, chars);
766 } else {
767 char *remainder = strdup(self->chars + range.location + range.length);
768
769 self->length = range.location;
770 self->chars[range.location] = '\0';
771
772 $(self, appendCharacters, chars);
773 $(self, appendCharacters, remainder);
774
775 free(remainder);
776 }
777}
778
783static void replaceOccurrencesOfCharacters(String *self, const char *chars, const char *replacement) {
784 $(self, replaceOccurrencesOfCharactersInRange, chars, (Range) { .length = self->length }, replacement);
785}
786
791static void replaceOccurrencesOfCharactersInRange(String *self, const char *chars, const Range range, const char *replacement) {
792
793 assert(chars);
794 assert(replacement);
795
796 assert(range.location >= 0);
797 assert(range.location + range.length <= self->length);
798
799 Range search = range;
800 while (true) {
801
802 const Range result = $((String *) self, rangeOfCharacters, chars, search);
803 if (result.location == -1) {
804 break;
805 }
806
807 $(self, replaceCharactersInRange, result, replacement);
808
809 search.length -= (result.location - search.location);
810 search.length -= strlen(replacement);
811 search.length += ((int) strlen(replacement) - (int) strlen(chars));
812
813 search.location = result.location + strlen(replacement);
814 }
815}
816
821static void replaceOccurrencesOfString(String *self, const String *string, const String *replacement) {
822 $(self, replaceOccurrencesOfStringInRange, string, (Range) { .length = self->length }, replacement);
823}
824
829static void replaceOccurrencesOfStringInRange(String *self, const String *string, const Range range, const String *replacement) {
830
831 assert(string);
832 assert(replacement);
833
834 $(self, replaceOccurrencesOfCharactersInRange, string->chars, range, replacement->chars);
835}
836
841static void replaceStringInRange(String *self, const Range range, const String *string) {
842
843 $(self, replaceCharactersInRange, range, string->chars);
844}
845
850static void setCharacters(String *self, const char *chars) {
851
852 $(self, setLength, 0);
853
854 $(self, appendCharacters, chars);
855}
856
861static void setFormat(String *self, const char *fmt, ...) {
862
863 $(self, setLength, 0);
864
865 va_list args;
866 va_start(args, fmt);
867
868 $(self, appendVaList, fmt, args);
869
870 va_end(args);
871}
872
877static void setLength(String *self, size_t length) {
878
879 if (length < self->length) {
880 self->length = length;
881 self->chars[length] = '\0';
882 }
883}
884
889static void setString(String *self, const String *string) {
890
891 $(self, setLength, 0);
892
893 $(self, appendString, string);
894}
895
900static String *string(void) {
901 return $(alloc(String), init);
902}
903
908static String *stringWithCapacity(size_t capacity) {
909 return $(alloc(String), initWithCapacity, capacity);
910}
911
916static void trim(String *self) {
917
918 String *trimmed = $((String *) self, trimmedString);
919
920 $(self, replaceStringInRange, (const Range) { .length = self->length }, trimmed);
921
922 release(trimmed);
923}
924
925#pragma mark - Class lifecycle
926
930static void initialize(Class *clazz) {
931
932 ((ObjectInterface *) clazz->interface)->copy = copy;
933 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
934 ((ObjectInterface *) clazz->interface)->description = description;
935 ((ObjectInterface *) clazz->interface)->hash = hash;
936 ((ObjectInterface *) clazz->interface)->isEqual = isEqual;
937
938 ((StringInterface *) clazz->interface)->compareTo = compareTo;
939 ((StringInterface *) clazz->interface)->componentsSeparatedByCharacters = componentsSeparatedByCharacters;
940 ((StringInterface *) clazz->interface)->componentsSeparatedByString = componentsSeparatedByString;
941 ((StringInterface *) clazz->interface)->getData = getData;
942 ((StringInterface *) clazz->interface)->hasPrefix = hasPrefix;
943 ((StringInterface *) clazz->interface)->hasSuffix = hasSuffix;
944 ((StringInterface *) clazz->interface)->initWithBytes = initWithBytes;
945 ((StringInterface *) clazz->interface)->initWithCharacters = initWithCharacters;
946 ((StringInterface *) clazz->interface)->initWithContentsOfFile = initWithContentsOfFile;
947 ((StringInterface *) clazz->interface)->initWithData = initWithData;
948 ((StringInterface *) clazz->interface)->initWithFormat = initWithFormat;
949 ((StringInterface *) clazz->interface)->initWithMemory = initWithMemory;
950 ((StringInterface *) clazz->interface)->initWithVaList = initWithVaList;
951 ((StringInterface *) clazz->interface)->lowercaseString = lowercaseString;
952 ((StringInterface *) clazz->interface)->appendBytes = appendBytes;
953 ((StringInterface *) clazz->interface)->appendCharacters = appendCharacters;
954 ((StringInterface *) clazz->interface)->appendFormat = appendFormat;
955 ((StringInterface *) clazz->interface)->appendString = appendString;
956 ((StringInterface *) clazz->interface)->appendVaList = appendVaList;
957 ((StringInterface *) clazz->interface)->deleteCharactersInRange = deleteCharactersInRange;
958 ((StringInterface *) clazz->interface)->init = init;
959 ((StringInterface *) clazz->interface)->initWithCapacity = initWithCapacity;
960 ((StringInterface *) clazz->interface)->initWithString = initWithString;
961 ((StringInterface *) clazz->interface)->insertCharactersAtIndex = insertCharactersAtIndex;
962 ((StringInterface *) clazz->interface)->insertStringAtIndex = insertStringAtIndex;
963 ((StringInterface *) clazz->interface)->replaceCharactersInRange = replaceCharactersInRange;
964 ((StringInterface *) clazz->interface)->replaceOccurrencesOfCharacters = replaceOccurrencesOfCharacters;
965 ((StringInterface *) clazz->interface)->replaceOccurrencesOfCharactersInRange = replaceOccurrencesOfCharactersInRange;
966 ((StringInterface *) clazz->interface)->replaceOccurrencesOfString = replaceOccurrencesOfString;
967 ((StringInterface *) clazz->interface)->replaceOccurrencesOfStringInRange = replaceOccurrencesOfStringInRange;
968 ((StringInterface *) clazz->interface)->replaceStringInRange = replaceStringInRange;
969 ((StringInterface *) clazz->interface)->setCharacters = setCharacters;
970 ((StringInterface *) clazz->interface)->setFormat = setFormat;
971 ((StringInterface *) clazz->interface)->setLength = setLength;
972 ((StringInterface *) clazz->interface)->setString = setString;
973 ((StringInterface *) clazz->interface)->string = string;
974 ((StringInterface *) clazz->interface)->stringWithCapacity = stringWithCapacity;
975 ((StringInterface *) clazz->interface)->trim = trim;
976 ((StringInterface *) clazz->interface)->rangeOfCharacters = rangeOfCharacters;
977 ((StringInterface *) clazz->interface)->rangeOfString = rangeOfString;
978 ((StringInterface *) clazz->interface)->stringWithBytes = stringWithBytes;
979 ((StringInterface *) clazz->interface)->stringWithCharacters = stringWithCharacters;
980 ((StringInterface *) clazz->interface)->stringWithContentsOfFile = stringWithContentsOfFile;
981 ((StringInterface *) clazz->interface)->stringWithData = stringWithData;
982 ((StringInterface *) clazz->interface)->stringWithFormat = stringWithFormat;
983 ((StringInterface *) clazz->interface)->stringWithMemory = stringWithMemory;
984 ((StringInterface *) clazz->interface)->substring = substring;
985 ((StringInterface *) clazz->interface)->trimmedString = trimmedString;
986 ((StringInterface *) clazz->interface)->uppercaseString = uppercaseString;
987 ((StringInterface *) clazz->interface)->writeToFile = writeToFile;
988}
989
995 static Class *clazz;
996 static Once once;
997
998 do_once(&once, {
999 clazz = _initialize(&(const ClassDef) {
1000 .name = "String",
1001 .superclass = _Object(),
1002 .instanceSize = sizeof(String),
1003 .interfaceSize = sizeof(StringInterface),
1004 .initialize = initialize,
1005 });
1006 });
1007
1008 return clazz;
1009}
1010
1011#undef _Class
1012
1014
1015 switch (encoding) {
1017 return "ASCII";
1019 return "ISO-8859-1";
1021 return "ISO-8859-2";
1023 return "MacRoman";
1025 return "UTF-16";
1027 return "UTF-32";
1029 return "UTF-8";
1031 return "WCHAR_T";
1032 }
1033
1034 return "ASCII";
1035}
1036
1038
1039 if (strcasecmp("ASCII", name) == 0) {
1040 return STRING_ENCODING_ASCII;
1041 } else if (strcasecmp("ISO-8859-1", name) == 0) {
1043 } else if (strcasecmp("ISO-8859-2", name) == 0) {
1045 } else if (strcasecmp("MacRoman", name) == 0) {
1047 } else if (strcasecmp("UTF-16", name) == 0) {
1048 return STRING_ENCODING_UTF16;
1049 } else if (strcasecmp("UTF-32", name) == 0) {
1050 return STRING_ENCODING_UTF32;
1051 } else if (strcasecmp("UTF-8", name) == 0) {
1052 return STRING_ENCODING_UTF8;
1053 } else if (strcasecmp("WCHAR", name) == 0) {
1054 return STRING_ENCODING_WCHAR;
1055 }
1056
1057 return STRING_ENCODING_ASCII;
1058}
1059
1060Order StringCompare(const ident a, const ident b) {
1061
1062 if (a) {
1063 if (b) {
1064 const int i = strcmp(((String *) a)->chars, ((String *) b)->chars);
1065 if (i == 0) {
1066 return OrderSame;
1067 }
1068 if (i > 0) {
1069 return OrderDescending;
1070 }
1071 } else {
1072 return OrderDescending;
1073 }
1074 }
1075 return OrderAscending;
1076}
1077
1078String *str(const char *fmt, ...) {
1079
1080 va_list args;
1081 va_start(args, fmt);
1082
1083 String *string = $(alloc(String), initWithVaList, fmt, args);
1084 assert(string);
1085
1086 va_end(args);
1087
1088 return string;
1089}
1090
1091char *strtrim(const char *s) {
1092
1093 assert(s);
1094 while (isspace(*s)) {
1095 s++;
1096 }
1097
1098 char *trimmed = strdup(s);
1099 assert(trimmed);
1100
1101 char *end = trimmed + strlen(trimmed);
1102 if (end > trimmed) {
1103 while (isspace(*(--end))) {
1104 *end = '\0';
1105 }
1106 }
1107
1108 return trimmed;
1109}
static void addObject(Array *self, const ident obj)
Definition Array.c:181
size_t _pageSize
Definition Class.c:44
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Definition Class.c:356
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:151
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:226
#define super(type, obj, method,...)
static Data * data(void)
Definition Data.c:286
static Data * dataWithContentsOfFile(const char *path)
Definition Data.c:133
static Data * dataWithMemory(ident mem, size_t length)
Definition Data.c:142
int HashForCString(int hash, const char *string)
Accumulates the hash value of the null-terminated string into hash.
Definition Hash.c:51
Utilities for calculating hash values.
#define HASH_SEED
The hash seed value.
Definition Hash.h:37
static bool isKindOfClass(const Object *self, const Class *clazz)
Definition Object.c:101
Class * _Object(void)
Definition Object.c:136
Pointer * ptr(ident pointer, Consumer destroy)
Definition Pointer.c:156
static Range rangeOfString(const String *self, const String *string, const Range range)
Definition String.c:329
static String * initWithData(String *self, const Data *data, StringEncoding encoding)
Definition String.c:664
static void insertCharactersAtIndex(String *self, const char *chars, size_t index)
Definition String.c:739
static String * stringWithData(const Data *data, StringEncoding encoding)
Definition String.c:367
static void replaceOccurrencesOfCharactersInRange(String *self, const char *chars, const Range range, const char *replacement)
Definition String.c:791
static size_t transcode(Transcode *trans)
Transcodes input from one character encoding to another via iconv.
Definition String.c:131
static String * init(String *self)
Definition String.c:593
static String * initWithContentsOfFile(String *self, const char *path, StringEncoding encoding)
Definition String.c:647
static String * stringWithCapacity(size_t capacity)
Definition String.c:908
static bool writeToFile(const String *self, const char *path, StringEncoding encoding)
Definition String.c:459
static String * initWithCapacity(String *self, size_t capacity)
Definition String.c:615
static String * stringWithFormat(const char *fmt,...)
Definition String.c:376
static bool isEqual(const Object *self, const Object *other)
Definition String.c:90
static bool hasSuffix(const String *self, const String *suffix)
Definition String.c:263
static void deleteCharactersInRange(String *self, const Range range)
Definition String.c:576
static Range rangeOfCharacters(const String *self, const char *chars, const Range range)
Definition String.c:303
const char * NameForStringEncoding(StringEncoding encoding)
Definition String.c:1013
static void setString(String *self, const String *string)
Definition String.c:889
static String * description(const Object *self)
Definition String.c:72
static String * initWithString(String *self, const String *string)
Definition String.c:711
static String * initWithMemory(String *self, const ident mem, size_t length)
Definition String.c:695
static String * initWithFormat(String *self, const char *fmt,...)
Definition String.c:675
static bool hasPrefix(const String *self, const String *prefix)
Definition String.c:249
static String * uppercaseString(const String *self)
Definition String.c:437
static String * string(void)
Definition String.c:900
static void appendVaList(String *self, const char *fmt, va_list args)
Definition String.c:561
static void replaceCharactersInRange(String *self, const Range range, const char *chars)
Definition String.c:759
char * strtrim(const char *s)
Copies the given null-terminated C string, trimming leading and trailing whitespace.
Definition String.c:1091
String * str(const char *fmt,...)
Definition String.c:1078
static String * stringWithContentsOfFile(const char *path, StringEncoding encoding)
Definition String.c:358
static Array * componentsSeparatedByString(const String *self, const String *string)
Definition String.c:215
static void setLength(String *self, size_t length)
Definition String.c:877
static void setFormat(String *self, const char *fmt,...)
Definition String.c:861
static void trim(String *self)
Definition String.c:916
static String * lowercaseString(const String *self)
Definition String.c:281
static String * substring(const String *self, const Range range)
Definition String.c:401
static void dealloc(Object *self)
Definition String.c:60
static void replaceOccurrencesOfCharacters(String *self, const char *chars, const char *replacement)
Definition String.c:783
static String * initWithBytes(String *self, const uint8_t *bytes, size_t length, StringEncoding encoding)
Definition String.c:601
static void appendCharacters(String *self, const char *chars)
Definition String.c:506
static String * trimmedString(const String *self)
Definition String.c:417
static void appendFormat(String *self, const char *fmt,...)
Definition String.c:536
static String * stringWithCharacters(const char *chars)
Definition String.c:349
static Object * copy(const Object *self)
Definition String.c:49
static Array * componentsSeparatedByCharacters(const String *self, const char *chars)
Definition String.c:182
StringEncoding StringEncodingForName(const char *name)
Definition String.c:1037
static void initialize(Class *clazz)
Definition String.c:930
static void replaceOccurrencesOfString(String *self, const String *string, const String *replacement)
Definition String.c:821
static void appendBytes(String *self, const uint8_t *bytes, size_t length, StringEncoding encoding)
Definition String.c:476
static String * initWithVaList(String *self, const char *fmt, va_list args)
Definition String.c:725
static void appendString(String *self, const String *string)
Definition String.c:550
static Data * getData(const String *self, StringEncoding encoding)
Definition String.c:226
static String * stringWithMemory(const ident mem, size_t length)
Definition String.c:392
static void setCharacters(String *self, const char *chars)
Definition String.c:850
Class * _String(void)
Definition String.c:994
static void insertStringAtIndex(String *self, const String *string, size_t index)
Definition String.c:750
Order StringCompare(const ident a, const ident b)
Definition String.c:1060
static void replaceOccurrencesOfStringInRange(String *self, const String *string, const Range range, const String *replacement)
Definition String.c:829
static String * initWithCharacters(String *self, const char *chars)
Definition String.c:633
static void replaceStringInRange(String *self, const Range range, const String *string)
Definition String.c:841
static int hash(const Object *self)
Definition String.c:80
static Order compareTo(const String *self, const String *other, const Range range)
Definition String.c:161
static String * stringWithBytes(const uint8_t *bytes, size_t length, StringEncoding encoding)
Definition String.c:340
UTF-8 strings.
StringEncoding
Character encodings for Strings.
Definition String.h:46
@ STRING_ENCODING_LATIN1
Definition String.h:48
@ STRING_ENCODING_WCHAR
Definition String.h:54
@ STRING_ENCODING_UTF32
Definition String.h:52
@ STRING_ENCODING_MACROMAN
Definition String.h:50
@ STRING_ENCODING_UTF16
Definition String.h:51
@ STRING_ENCODING_ASCII
Definition String.h:47
@ STRING_ENCODING_LATIN2
Definition String.h:49
@ STRING_ENCODING_UTF8
Definition String.h:53
wchar_t Unicode
The Unicode type.
Definition String.h:41
void * ident
The identity type, similar to Objective-C id.
Definition Types.h:49
Order
Comparison constants.
Definition Types.h:70
@ OrderSame
Definition Types.h:72
@ OrderDescending
Definition Types.h:73
@ OrderAscending
Definition Types.h:71
long Once
The Once type.
Definition Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition Once.h:43
Arrays.
Definition Array.h:56
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition Class.h:41
The runtime representation of a Class.
Definition Class.h:90
ident interface
The interface of the Class.
Definition Class.h:100
Data buffers.
Definition Data.h:50
size_t length
The length of bytes.
Definition Data.h:76
uint8_t * bytes
The bytes.
Definition Data.h:66
Data * initWithBytes(Data *self, const uint8_t *bytes, size_t length)
Initializes this Data by copying length of bytes.
Definition Data.c:151
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
int hash(const Object *self)
Definition Array.c:129
void dealloc(Object *self)
Frees all resources held by this Object.
Definition Array.c:99
A location and length into contiguous collections.
Definition Types.h:54
ssize_t location
The location.
Definition Types.h:59
size_t length
The length.
Definition Types.h:64
UTF-8 strings.
Definition String.h:69
String * uppercaseString(const String *self)
Definition String.c:437
char * chars
The backing null-terminated UTF-8 encoded character array.
Definition String.h:85
void appendBytes(String *self, const uint8_t *bytes, size_t length, StringEncoding encoding)
Appends the decoded contents of bytes.
Definition String.c:476
bool writeToFile(const String *self, const char *path, StringEncoding encoding)
Writes this String to path.
Definition String.c:459
String * initWithVaList(String *self, const char *fmt, va_list args)
Initializes this String with the specified arguments list.
Definition String.c:725
String * stringWithMemory(const ident mem, size_t length)
Returns a new String with the given buffer.
Definition String.c:392
size_t length
The length of the String in bytes.
Definition String.h:90
String * lowercaseString(const String *self)
Definition String.c:281
String * initWithCharacters(String *self, const char *chars)
Initializes this String by copying chars.
Definition String.c:633
String * trimmedString(const String *self)
Creates a copy of this String with leading and trailing whitespace removed.
Definition String.c:417
String * stringWithData(const Data *data, StringEncoding encoding)
Returns a new String with the the given Data.
Definition String.c:367
String * stringWithFormat(const char *fmt)
Returns a new String with the given format string.
String * initWithMemory(String *self, const ident mem, size_t length)
Initializes this String with the specified buffer.
Definition String.c:695
void insertCharactersAtIndex(String *self, const char *chars, size_t index)
Inserts the specified String at the given index.
Definition String.c:739
String * stringWithCapacity(size_t capacity)
Returns a new String with the given capacity.
Definition String.c:908
String * substring(const String *string, const Range range)
Creates a new String from a subset of this one.
Definition String.c:401
String * initWithData(String *self, const Data *data, StringEncoding encoding)
Initializes this String with the given Data.
Definition String.c:664
String * initWithContentsOfFile(String *self, const char *path, StringEncoding encoding)
Initializes this String with the contents of the FILE at path.
Definition String.c:647
void trim(String *self)
Trims leading and trailing whitespace from this String.
Definition String.c:916
String * initWithString(String *self, const String *string)
Initializes this String with the contents of string.
Definition String.c:711
String * initWithCapacity(String *self, size_t capacity)
Initializes this String with the given capacity.
Definition String.c:615
String * initWithFormat(String *self, const char *fmt,...)
Initializes this String with the specified format string.
Definition String.c:675
String * stringWithContentsOfFile(const char *path, StringEncoding encoding)
Returns a new String with the contents of the FILE at path.
Definition String.c:358
String * stringWithCharacters(const char *chars)
Returns a new String by copying chars.
Definition String.c:349
Character transcoding context for iconv.
Definition String.c:117
char * out
Definition String.c:122
char * in
Definition String.c:120
size_t length
Definition String.c:121
StringEncoding from
Definition String.c:119
size_t size
Definition String.c:123
StringEncoding to
Definition String.c:118