(здесь должна быть картинка со строками, наверное)
RCString– это мини-контейнер для хранения 0-терминированных С-строк.
Сегодня для меня маленький праздник, т.к. число строк в RCString.c стало 533, т.е. это побило мой рекорд с RArray в 491 строку. Теперь RCString.c самый длинный файл в foundation.
Далее лирика (и исходники конечно же) о том, что я хотел сделать, и что я сделал.
Лирическое отступление
Т.к. я obj-c программист, идею RayFoundation я взял оттуда. Поэтому некоторые методы называются одинаково, а некоторые по разному. Статью, о том, как я все же решился сделать это можно прочитать тут, а полные исходники строк тут, далее будет идти препроцессеный код, т.к. судя по всему читатели не очень любят мой адский define-based синтаксис, но в исходниках он находится в первозданном виде. ВНИМАНИЕ, это классические ascii-строки. Next step будет полный переход на utf-8.
TodoList(уже реализовано)
- инициализация с-строкой
- инициализация с-строкой с дальнейшим копированием
- замена символов в строке
- замена подстрок в строке
- нахождение подстроки по
- – диапазону
- – символьным границам (аля разделенные символами [ и ])
- – до символа
- – все подстроки разделенные символом
- копия строки
- количество повторений символа
- сравнение строк
- считывание строки из файла
- приведение всех символов к верхнему регистру
- приведение всех символов к нижнему регистру
- вставка подстроки в строку (размер меняется)
- задание подстроки в диапазоне (размер не меняется)
- индекс первого включения конкретного элемента
- индекс последнего включения конкретного элемента
- удаление
- — всех заданных символов
- — всех заданных подстрок
- — повторений заданных символов
- — повторений заданных подстрок
- — в заданном диапазоне
- рандомный видимый символ (все символы из base64)
- рандомная видимая строка (так же base64)
- массив подстрок разделенный символами из строки (aka strtok)
typedef struct RCString RCString;
uint64_t indexOfFirstCharacterCString (const char *string, uint64_t size, char character);
uint64_t indexOfLastCharacterCString (const char *string, uint64_t size, char character);
RCString* randomRCString (void);
char randomCharacter (void);
typedef struct RCString { uint64_t classId;
char *baseString;
uint64_t size;
} RCString;
RCString* constructorOfRCString (RCString *object);
void destructorOfRCString (RCString *object);
void printerOfRCString (RCString *object);
void flushRCString(RCString *object);
RCString * setStringRCString(RCString *object, const char *string);
RCString * setConstantStringRCString(RCString *object, char const *string);
void replaceCharactersRCString(RCString *object, char characterToReplace, char replacer);
void replaceSubstringsRCString(RCString *object, RCString *toReplace, RCString *replacer);
uint64_t numberOfRepetitionsRCString(RCString *object, char character);
RCString * deleteAllCharactersRCString(RCString *object, char character);
void removeRepetitionsOfRCString(RCString *object, char character);
RCString * deleteAllSubstringsRCString(RCString *object, const RCString *substring);
void removeRepetitionsOfStringRCString(RCString *object, const RCString *substring);
RCString * deleteCharacterAtRCString(RCString *object, uint64_t index);
void deleteInRangeRCString(RCString *object, RRange range);
RCString * setSubstringInRangeRCString(RCString *object, RRange range, const char *string);
RCString * insertSubstringAtRCString(RCString *object, RCString *substring, uint64_t place);
RCString * substringToSymbolRCString(RCString *object, char symbol);
RCString * substringInRangeRCString(RCString *object, RRange range);
RCString * substringByBoundsRCString(RCString *object, RBounds bounds);
RArray * substringsSeparatedBySymbolRCString(RCString *object, char symbol);
RArray * substringsSeparatedBySymbolsRCString(RCString *object, RCString *separatorsString);
RCString * copyRCString(RCString *object);
RCompareFlags compareWithRCString(RCString *object, const RCString *checkString);
void fromFileRCString(RCString *object, const RCString *filename);
void concatenateRCString(RCString *object, const RCString *string);
RCString* toUpperCaseRCString(RCString *object);
RCString* toLowerCaseRCString(RCString *object);
uint64_t indexOfFirstCharacterCString(const char *string, uint64_t size, char character) {
register uint64_t iterator = 0;
while(iterator < size) {
if(string[iterator] == character) {
break;
} else {
++iterator;
}
}
return iterator;
}
uint64_t indexOfLastCharacterCString(const char *string, uint64_t size, char character) {
register uint64_t iterator = 0;
register uint64_t last = size;
while(iterator < size) {
if(string[iterator] == character) {
last = iterator;
}
++iterator;
}
return last;
}
char randomCharacter(void) {
register char character = ((char)rand());
while(character < 34 ||
character > 126) {
character = ((char)rand());
}
return character;
}
RCString *randomRCString(void) {
register uint64_t iterator;
RCString *string = constructorOfRCString((NULL));
register uint64_t size = ((uint64_t)rand()) % 50;
char *cstring;
while(size == 0) {
size = ((uint64_t)rand()) % 50;
}
cstring = malloc(size * sizeof(char));
for(iterator = 0; iterator < size; ++iterator){
cstring[iterator] = randomCharacter();
}
setConstantStringRCString(string, cstring);
return string;
}
RCString* constructorOfRCString (RCString *object) {
object = malloc(sizeof(RCString));
if(object) {
object->classId = 1;
object->size = 0;
}
return object;
}
void destructorOfRCString (RCString *object) {
free(object->baseString);;
object->size = 0;
}
void printerOfRCString (RCString *object) {
printf("%sn", object->baseString);
}
void flushRCString(RCString *object) {
if(object->size != 0 && object->baseString != (NULL)) {
free(object->baseString);;
object->size = 0;
}
}
RCString * setStringRCString(RCString *object, const char *string) {
if(string != (NULL)) {
register uint64_t stringSize = strlen(string) + 1;
if(object->size != 0 && object->baseString != (NULL)
|| object->size < stringSize) {
free(object->baseString);;
object->baseString = malloc(stringSize * sizeof(char));
}
object->size = stringSize;
memcpy (object->baseString, string, object->size, __builtin_object_size (object->baseString, 0));
--object->size;
} else {
printf("Warning. RCS. Setted strings is empty, please delete function call, or fix it.n");
}
return object;
}
RCString * setConstantStringRCString(RCString *object, char const *string) {
if(string != (NULL)) {
object->baseString = string;
object->size = strlen(string);
} else {
printf("Warning. RCS. Setted strings is empty, please delete function call, or fix it.n");
}
return object;
}
void replaceCharactersRCString(RCString *object, char characterToReplace, char replacer) {
register uint64_t iterator = 0;
while(iterator < object->size) {
if(object->baseString[iterator] == characterToReplace) {
object->baseString[iterator] = replacer;
}
++iterator;
}
}
void replaceSubstringsRCString(RCString *object, RCString *toReplace, RCString *replacer) {
if(toReplace != (NULL)
&& replacer != (NULL)
&& toReplace->size != 0
&& replacer->size != 0
&& toReplace->size <= object->size) {
register uint64_t iterator;
for(iterator = 0; iterator < object->size; ++iterator) {
if(object->baseString[iterator] == toReplace->baseString[0]) {
if(memcmp(object->baseString + iterator + 1, toReplace->baseString + 1, toReplace->size - 1) == 0) {
insertSubstringAtRCString(object, replacer, iterator);
deleteInRangeRCString(object, makeRRange(iterator + replacer->size, toReplace->size));
}
}
}
} else {
printf("Warning. RCS. Bad strings, or sizes, please delete function call, or fix it.n");
}
}
uint64_t numberOfRepetitionsRCString(RCString *object, char character) {
register uint64_t reps = 0;
register uint64_t iterator;
for(iterator = 0; iterator < object->size; ++iterator) {
if(object->baseString[iterator] == character) {
++reps;
}
}
return reps;
}
RCString * deleteAllCharactersRCString(RCString *object, char character) {
register uint64_t iterator;
for(iterator = 0; iterator < object->size; ++iterator) {
if(object->baseString[iterator] == character) {
memcpy (object->baseString + iterator, object->baseString + iterator + 1, object->size + 1 - iterator, __builtin_object_size (object->baseString + iterator, 0));
--iterator;
--object->size;
}
}
return object;
}
void removeRepetitionsOfRCString(RCString *object, char character) {
register uint64_t iterator;
register uint64_t inner;
for(iterator = 0; iterator < object->size - 1; ++iterator) {
if(object->baseString[iterator] == character) {
for(inner = 0; inner < object->size - iterator; ++inner) {
if(object->baseString[inner + iterator + 1] != character){
break;
}
}
if(inner > 0) {
deleteInRangeRCString(object, makeRRange(iterator + 1, inner));
}
}
}
}
RCString * deleteAllSubstringsRCString(RCString *object, const RCString *substring) {
register uint64_t iterator;
register uint64_t inner;
register byte flag = 1;
if(substring->size != 0
|| substring->baseString == (NULL)) {
for(iterator = 0; iterator < object->size - substring->size; ++iterator) {
if(object->baseString[iterator] == substring->baseString[0]) {
for(inner = 1; inner < substring->size; ++inner) {
if(object->baseString[iterator + 1] != substring->baseString[inner]) {
flag = 0;
break;
}
}
} else {
flag = 0;
}
if(flag == 1) {
memcpy (object->baseString + iterator, object->baseString + iterator + substring->size, object->size + 1 - iterator - substring->size, __builtin_object_size (object->baseString + iterator, 0));
--iterator;
object->size -= substring->size;
} else {
flag = 1;
}
}
return object;
} else {
printf("Warning. RCS. Substring size is 0, or, substring is NULL.n");
}
return (NULL);
}
void removeRepetitionsOfStringRCString(RCString *object, const RCString *substring) {
if(compareWithRCString(object->baseString, substring) != equals
&& object->size >= substring->size * 2) {
register uint64_t iterator;
register uint64_t place;
register uint64_t repetitionsCount;
for(iterator = 0; iterator < object->size - substring->size; ++iterator) {
if(object->size - iterator >= substring->size
&& object->baseString[iterator] == substring->baseString[0]) {
if(memcmp(object->baseString + iterator + 1, substring->baseString + 1, substring->size - 1) == 0) {
iterator += substring->size;
place = iterator;
for(repetitionsCount = 0; repetitionsCount < (object->size / substring->size - 1); ) {
if (memcmp(object->baseString + iterator, substring->baseString, substring->size) == 0) {
++repetitionsCount;
iterator += substring->size;
} else {
break;
}
}
if(repetitionsCount > 0) {
deleteInRangeRCString(object, makeRRange(place, repetitionsCount * substring->size));
iterator -= repetitionsCount * substring->size;
}
}
}
}
}
}
RCString * deleteCharacterAtRCString(RCString *object, uint64_t index) {
if(index > object->size) {
printf("Error. RCS. Bad index!");
} else {
memmove (object->baseString + index, object->baseString + index + 1, object->size - index, __builtin_object_size (object->baseString + index, 0));
}
return object;
}
void deleteInRangeRCString(RCString *object, RRange range) {
if(range.count != 0
&& ((range.from + range.count) < object->size)) {
memmove (object->baseString + range.from, object->baseString + range.from + range.count, object->size - range.count - range.from + 1, __builtin_object_size (object->baseString + range.from, 0));
object->size -= range.count;
object->baseString[object->size + 1] = 0;
} else {
printf("ERRROR. RCS. deleteInRange, bad range, do nothing.n");
}
}
RCString * setSubstringInRangeRCString(RCString *object, RRange range, const char *string) {
if(range.count != 0 && ((range.from + range.count - 1) < object->size)) {
memmove (object->baseString + range.from, string, range.count, __builtin_object_size (object->baseString + range.from, 0));
} else {
printf("ERROR. RCS. BAD RANGE!n");
}
return object;
}
RCString * insertSubstringAtRCString(RCString *object, RCString *substring, uint64_t place) {
if(place < object->size) {
char *result = malloc(object->size + substring->size + 1);
memmove (result, object->baseString, place, __builtin_object_size (result, 0));
memmove (result + place, substring->baseString, substring->size, __builtin_object_size (result + place, 0));
memmove (result + place + substring->size, object->baseString + place, object->size - place, __builtin_object_size (result + place + substring->size, 0));
free(object->baseString);;
object->size += substring->size;
object->baseString = result;
} else if(place == object->size) {
concatenateRCString(object, substring);
} else {
printf("Warning. RCS. BAD place to insert!n");
}
return object;
}
RCString * substringInRangeRCString(RCString *object, RRange range) {
if(range.count != 0 && range.from < object->size) {
char *cstring = malloc(range.count + 1 * sizeof(char));
memmove (cstring, object->baseString + range.from, range.count, __builtin_object_size (cstring, 0));
cstring[range.count + 1] = 0;
RCString *rcString = constructorOfRCString((NULL) );
rcString->size = range.count;
rcString->baseString = cstring;
return rcString;
} else {
printf("ERROR. RCS. BAD RANGE!n");
return (NULL);
}
}
RCString * substringToSymbolRCString(RCString *object, char symbol) {
register uint64_t index = indexOfFirstCharacterCString(object->baseString, object->size, symbol);
if(index != object->size) {
return substringInRangeRCString(object, makeRRange(0, index));
} else {
return (NULL);
}
}
RArray * substringsSeparatedBySymbolRCString(RCString *object, char symbol) {
RCString tempObject = *object;
RArray *result = (NULL);
RCString *string = substringToSymbolRCString(object, symbol);
if(string != (NULL)) {
result = constructorOfRArray((NULL), (NULL));
result->destructorDelegate = destructorOfRCString;
result->printerDelegate = printerOfRCString;
}
while(string != (NULL)) {
addObjectRArray(result, string);
object->baseString += string->size + 1;
object->size -= string->size + 1;
string = substringToSymbolRCString(object, symbol);
if(string == (NULL)) {
addObjectRArray(result, copyRCString(object) );
}
}
*object = tempObject;
if(result != (NULL)) {
sizeToFitRArray(result );
}
return result;
}
RArray * substringsSeparatedBySymbolsRCString(RCString *object, RCString *separatorsString) {
register uint64_t iterator = 0;
RArray *result = (NULL);
if(separatorsString != (NULL)
&& separatorsString->size != 0
&& object != (NULL)
&& object->size != 0) {
while(iterator < separatorsString->size) {
if(separatorsString->baseString[iterator] != ' ') {
replaceCharactersRCString(object, separatorsString->baseString[iterator], ' ');
}
++iterator;
}
}
return result;
}
RCString * substringByBoundsRCString(RCString *object, RBounds bounds) {
register RRange range;
range.from = indexOfFirstCharacterCString(object->baseString, object->size, bounds.startSymbol) + 1;
range.count = indexOfLastCharacterCString (object->baseString, object->size, bounds.endSymbol) - range.from;
return substringInRangeRCString(object, range);
}
RCString * copyRCString(RCString *object) {
RCString *copy = substringInRangeRCString(object, makeRRange(0, object->size));
return copy;
}
RCompareFlags compareWithRCString(RCString *object, const RCString *checkString) {
static uint64_t iterator;
if(checkString == (NULL) || object == (NULL)) {
printf("Warning. RCS. One of compare strings is empty, please delete function call, or fix it.n");
return not_equals;
} else {
if (checkString == object) {
return equals;
} else {
if (checkString->size == object->size) {
for(iterator = 0; iterator < object->size; ++iterator) {
if(object->baseString[iterator] != checkString->baseString[iterator]){
return not_equals;
}
}
return equals;
} else {
if(checkString->size == object->size) {
return shorter;
} else {
return longer;
}
}
}
}
return not_equals;
}
void fromFileRCString(RCString *object, const RCString *filename) {
FILE *file = fopen(filename->baseString, "rb");
char *buffer;
long fileSize;
if(file != (NULL)) {
fseek(file, 0, 2);
fileSize = ftell(file);
rewind(file);
buffer = malloc(fileSize * (sizeof(char)));
fread(buffer, sizeof(char), fileSize, file);
fclose(file);
setConstantStringRCString(object, buffer);
} else {
printf("Warning. RCS. Cannot open file.n");
}
}
void concatenateRCString(RCString *object, const RCString *string) {
if(string->size != 0 && string->baseString != (NULL)) {
char *concatenationResult = malloc(string->size + object->size + 1);
memmove (concatenationResult, object->baseString, object->size, __builtin_object_size (concatenationResult, 0));
memmove (concatenationResult + object->size, string->baseString, string->size, __builtin_object_size (concatenationResult + object->size, 0));
concatenationResult[string->size + object->size + 1] = 0;
free(object->baseString);;
object->baseString = concatenationResult;
object->size += string->size;
} else {
printf("Warning. RCS. Bad concatenate string.n");
}
}
RCString* toUpperCaseRCString(RCString *object) {
register uint64_t iterator;
for(iterator = 0; iterator < object->size; ++iterator) {
if(object->baseString[iterator] > 96 && object->baseString[iterator] < 123 ) {
object->baseString[iterator] -= 32;
}
}
return object;
}
RCString* toLowerCaseRCString(RCString *object) {
register uint64_t iterator;
for(iterator = 0; iterator < object->size; ++iterator) {
if(object->baseString[iterator] > 64 && object->baseString[iterator] < 91 ) {
object->baseString[iterator] += 32;
}
}
return object;
}
P.S. Присылайте свои предложения по улучшению и добавлению необходимых функций.
P.S.S. Полностью RayFoundation доступен тут.
UPD. массив подстрок разделенный символами из строки (aka strtok) таки допилено.
Автор: StrangerInRed