- PVSM.RU - https://www.pvsm.ru -

Процессинг строк в RayFoundation. Часть 1 RCString

image
(здесь должна быть картинка со строками, наверное)

RCString– это мини-контейнер для хранения 0-терминированных С-строк.
Сегодня для меня маленький праздник, т.к. число строк в RCString.c стало 533, т.е. это побило мой рекорд с RArray в 491 строку. Теперь RCString.c самый длинный файл в foundation.
Далее лирика (и исходники конечно же) о том, что я хотел сделать, и что я сделал.

Лирическое отступление

Т.к. я obj-c программист, идею RayFoundation я взял оттуда. Поэтому некоторые методы называются одинаково, а некоторые по разному. Статью, о том, как я все же решился сделать это можно прочитать тут [1], а полные исходники строк тут [2], далее будет идти препроцессеный код, т.к. судя по всему читатели не очень любят мой адский 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 доступен тут [3].

UPD. массив подстрок разделенный символами из строки (aka strtok) таки допилено.

Автор: StrangerInRed

Источник [4]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/c-3/72640

Ссылки в тексте:

[1] тут: http://habrahabr.ru/post/239505/

[2] тут: https://github.com/kojiba/RayLanguage/tree/master/Classes/RayFoundation/RCString

[3] тут: https://github.com/kojiba/RayLanguage

[4] Источник: http://habrahabr.ru/post/241439/