Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Dynamic strings implementation
- * Smagin Maksim 2015
- */
- #include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include <memory.h>
- // #include "dstring.h" //Я ламерок и не умею в хеадеронли - моё место на помойке
- // я посто спрятал структуру в dstring.c чтобы не дать туда явный доступ
- ////в 2015, если у тебя нет хеадеронли - твоё и твоей либе место на помойке. Особенно, если у тебя доступ к полям через методы. В крестах это делается подефолту - подефолту инлайн в методах с телом.
- #define dstr_malloc malloc //я ламерок и не умею в функции - моё место на помойке
- #define dstr_realloc realloc//я ламерок и не умею в функции - моё место на помойке
- #define dstr_free free//я ламерок и не умею в функции - моё место на помойке
- // *** я думал о том что бы сделать их функциями и я знал, что не буду писать аллокаторы и точно буду буду использовать malloc и компанию.
- // *** по этому для меня сейчас актуален и стандартный алокатор
- //.. тут дело не в написании аллокатора, а в:
- // void * dstr_malloc(size_t n) {return malloc(n);}
- // ну и да - тебе не надо писать маллок - тебе надо написать примитивную обёртку над mmap()
- struct dstring {
- char * data;//терминальная лс"ная нулина.
- // *** а вчем разниза если написать data[0] ?
- //.. В том, что будет 1 маллок, а не 2.
- size_t length;
- size_t capacity;//я у мамы ламерок - увидел что-то у крестов и своими 3-мя извилинами попытался повторить.
- // *** по моему это логично знать сколько памяти занято и сколько есть свободной.
- // *** еще раз скажу что я ничего у кестов не смотрел)
- //.. в чём смысл? Попытка оптимизировать кол-во реаллокаций? mreamap() в realloc() это сделает за тебя. Тут нет никаких копирований и прочего.
- //.. Тем более юзать убогий malloc() тебе ничего не мешало, значит к оптимизации твой код не имеет никакого отношения. А уж про днище в toupper я и молчу.
- };//я ламерок и не умею в тайпдеф и структуры - моё место на помойке
- // *** ну это ты уже засунул хедер сюда. они были в разных файлах, так что верхний комент - это бред.
- //.. Нет, всё в моём коммента правильно - нахрен вообще нужно struct dstring, если у тебя оно неиспользуется?
- typedef struct dstring dstring_t;
- typedef struct {
- uint64_t len, capacity;
- char data[0];
- } string_t;
- typedef string_t * string_ptr_t;
- string_ptr_t string_alloc(uint64_t capacity) {
- return memcpy(malloc(capacity + sizeof(string_t)), &(string_t){0, capacity}, sizeof(string_t));
- }
- char * get_data(string_ptr_t str) {
- return str->data;
- }
- string_ptr_t string_realloc(string_ptr_t str, uint64_t new_capacity) {
- return memcpy(realloc(str, new_capacity), &(string_t){str->len, new_capacity}, sizeof(string_t));
- }
- //а теперь сравни со своей куллстори с десятью маллоками.
- dstring_t * dstr_new(const char * init);
- void dstr_delete(dstring_t * str);
- dstring_t * dstr_set(dstring_t * str, const char * val);
- dstring_t * dstr_truncate(dstring_t * str, size_t len);
- size_t dstr_len(const dstring_t * str);
- void dstr_swap(dstring_t * str1, dstring_t * str2);
- dstring_t * dstr_insert(dstring_t * str, const char * val, size_t n);
- dstring_t * dstr_append(dstring_t * str, const char * val);
- dstring_t * dstr_appendc(dstring_t * str, char c);
- dstring_t * dstr_prepend(dstring_t * str, const char * val);
- int dstr_equal(const dstring_t * str1, const dstring_t * str2);
- dstring_t * dstr_toupper(dstring_t * str);
- dstring_t * dstr_tolower(dstring_t * str);
- void dstr_fprint(const dstring_t * str, FILE * file);
- // *** о enum { ... } я знаю. почему не использовал его? Ну признаю что просто хоетл написать define) согласен что надо заменить на enum
- #define DSTRING_CAPMARGIN 48//я ламерок и не умею в переменные - моё место на помойке
- #define DSTRING_DEFAULT_CAPACITY 16//я ламерок и не умею в переменные - моё место на помойке
- #define DSTRING_ERR_RESIZE 0//я ламерок и не умею в переменные - моё место на помойке
- #define DSTRING_SUCC_RESIZE 1//я ламерок и не умею в переменные - моё место на помойке
- /* Resize dstring capacity */
- static int dstr_capacity_resize(dstring_t * str, size_t capacity) {//статик инты и прочий мусор - я не умею писать код
- char * temp_data_ptr = (char *)dstr_realloc(str->data, capacity);//очередной С/С++ ламерок.
- if(temp_data_ptr == NULL) return DSTRING_ERR_RESIZE;//Очередная ламерюга, не умеющая в Си.
- str->data = temp_data_ptr;//Ламерюга не умеющая в Си.
- str->capacity = capacity;//То же самое.
- return DSTRING_SUCC_RESIZE;//Ламерюга не умеет в !succ - надо же заваять тонну дерьма, но !succ не осилилось
- }
- /*
- * Base function implementation
- */
- /* Create new dynamic string and init that string $init.
- Return pointer into created dynamic string, or NULL if can't allocate memory for that.
- */
- dstring_t * dstr_new(const char * init) {
- dstring_t * str = (dstring_t *)dstr_malloc(sizeof(dstring_t));//ламерок не может в Си. Зачем юзать маллок один раз, если можно заюзать его 2 раза. А что не три?
- // *** понятно что можно сделать один маллок и туда и стрктуру воткнуть и данные. но если надо их ресайзить то
- if(str == NULL) return NULL;//просто ахриненная история - ламерок опять не умеет в си.
- size_t data_capacity = DSTRING_DEFAULT_CAPACITY;//ламерок не умеет в си.
- size_t init_len = 0;//ламерок не умеет в си.
- if(init != NULL) {//логика убогих мне не ясная
- init_len = strlen(init);//Я не умею в Си.
- data_capacity += init_len;//facepalm
- }
- str->data = (char *)dstr_malloc(data_capacity);//я умамы ламерок
- if(str->data == NULL) {//я не умею в си.
- free(str);
- return NULL;
- }
- str->length = init_len;//я не умею в си.
- str->capacity = data_capacity;//я не умею в си.
- memcpy(str->data, init, init_len);//я не умею в си.
- return str;//я не умею в си.
- }
- /* Free memory which takes dynamic string. */
- void dstr_delete(dstring_t * str) {
- if(str != NULL) {//я не умею в си.
- dstr_free(str->data);//я не умею в си.
- dstr_free(str);//я не умею в си.
- }
- // *** на ноль проверяю что бы не освобождать память по NULL указателю - это бессмысленно
- // (хотя тут следовало бы говорить что в функцию суют указатель на NULL)
- //..free() сам проверяет и ничего не освобожает.
- }
- /* Truncate dynamic string $str to fixed length $len from the beginning $str. */
- dstring_t * dstr_truncate(dstring_t * str, size_t len) {//дерьмо.
- if(str != NULL && str->length > len) {
- if(dstr_capacity_resize(str, DSTRING_DEFAULT_CAPACITY + len))
- str->length = len;
- }
- return str;
- }
- /* Set value of dynamic string $str equal $val.
- dstring_t * dstr_set(dstring_t * str, const char * val) {//дерьмо
- if(val == NULL && dstr_capacity_resize(str, DSTRING_DEFAULT_CAPACITY))
- str->length = 0;
- else {
- size_t val_len = strlen(val);
- if(dstr_capacity_resize(str, DSTRING_DEFAULT_CAPACITY + val_len)) {
- str->length = val_len;
- memcpy(str->data, val, val_len);
- }
- }
- return str;
- }
- */
- /* Output dstring value into stream */
- void dstr_fprint(const dstring_t * str, FILE * file) {//дерьмо
- if(file == NULL || str == NULL) return;
- fwrite(str->data, 1, str->length, file);
- // *** я не могу получитиь доступ к структуре ибо она спрятана. По этому я пишу в файл через функцию
- //.. тут дело в моей жопаболи от fwrite() и в том, что эта операция просто не имеет смысла. Сделай get_length().
- //а если я хочу записать половину твоей строки? Что я буду делать?
- }
- /* Return length of dynamic string $str. */
- size_t dstr_len(const dstring_t * str) {
- return str->length;
- }
- /* Swaps values of two dynamic strings.
- void dstr_swap(dstring_t * str1, dstring_t * str2) {//зачем это надо? Опять школьник вчера увидивший кресты стал у мамки сишником?
- if(str1 == NULL || str2 == NULL) return;
- char * temp_data_ptr = str1->data;
- size_t temp_length = str1->length;
- size_t temp_capacity = str1->capacity;
- str1->capacity = str2->capacity;
- str1->length = str2->length;
- str1->data = str2->data;
- str2->data = temp_data_ptr;
- str2->capacity = temp_capacity;
- str2->length = temp_length;
- }
- */
- /* Append string into dsting.
- dstring_t * dstr_append(dstring_t * str, const char * val) {//просто дерьмо, зачем нужно dstr_set(), если это то же самое?
- if(str == NULL || val == NULL) return str;
- size_t val_len = strlen(val);
- if(val_len > (str->capacity - str->length)) {
- size_t new_capacity = str->capacity + val_len + DSTRING_CAPMARGIN;
- if(!dstr_capacity_resize(str, new_capacity))
- return str;
- str->capacity = new_capacity;
- }
- memcpy(str->data + str->length, val, val_len);
- str->length += val_len;
- return str;
- }
- /* Append single char into dsting. */
- dstring_t * dstr_appendc(dstring_t * str, char c) {//просто нахрен дерьмо
- if(str == NULL) return str;
- if((str->capacity - str->length) < 1) {
- if(!dstr_capacity_resize(str, str->capacity + DSTRING_CAPMARGIN)) return str;
- str->capacity += DSTRING_CAPMARGIN;
- }
- str->data[str->length] = c;
- str->length++;
- return str;
- // *** нет не дерьмо. ради вставки одного симвла мне нужно дергать memcpy ? зачем?
- // *** плюс надо будет передавать в двойных кавычках строку в одним смволом. зачем?
- // *** ( хотя проверку на длинну можно вставить в append )
- // само добавление символа не имеет смысла.
- }
- //
- dstring_t * dstr_coolreasize(dstring_t * str, uint64_t len) {
- //логика работы такая - после вызова этой функции гарантируется, что append() на len байт влезет по capacity.
- }
- //теперь твоё днище превращается в
- dstring_t * dstr_appendc(dstring_t * str, char c) {//просто нахрен дерьмо
- if(str == NULL) return str;
- dstr_coolreasize(str, 1);//как-то так и тебе не надо писать одно и тоже в каждой функции на 10строк
- *(str->data + (++str->length)) = c;//как-то так
- }
- /* Prepend string into dsting. */
- dstring_t * dstr_prepend(dstring_t * str, const char * val) {//Л - логика.
- // а в чем проблема? вставка в начало строки)
- if(str == NULL || val == NULL) return str;
- if(str->length == 0) return str = dstr_set(str, val);
- size_t val_len = strlen(val);
- if(val_len == 0) return str;
- size_t new_capacity = str->capacity + val_len;
- if(!dstr_capacity_resize(str, new_capacity))
- return str;
- str->capacity = new_capacity;
- // move the $str value on $val_len characters to rigth
- memmove(str->data + val_len, str->data, str->length);
- memcpy(str->data, val, val_len);
- str->length += val_len;
- return str;
- }
- /* Compare two dynamic strings and return 1 if they are equals or 0 - if don't. */
- int dstr_equal(const dstring_t * str1, const dstring_t * str2) {
- if(str1->length != str2->length) return 0;//я у мамы ламерок. Это типа куллоптимизация?
- return strncmp(str1->data, str2->data, str1->length) == 0;//а если str2 меньше str1?
- // *** функция называется equal - это либо равно либо нет.
- // *** так что больше или меньше и какая из строк не интересует.
- // *** проверка на равенство длинн - логична в этом контексте,
- // *** ибо нафига сравнивать две строки с разной длинной - он и так не равны.
- // *** (я не учитываю строки забитые с конца пробелами одинаковой длинны и тд)
- //.. Я про другое. Она не логична - это куллоптимизация, которая итак должна быть в strcmp().
- //Далее ты заюзал strncmp(), а не strcmp() из-за куллоптимизация, при этом это абсолютно(в50%+) не имеет смысла, ибо всё равно каждый символ проверяет на терминатор.
- //если ты хотел куллоптимизацию, чтобы как бэ у строк без терминатора, то memcmp(a, a, min(alen, blen));
- }
- // Converts dynamic string characters to uppercase.
- /*
- dstring_t * dstr_toupper(dstring_t * str) {//таким дерьмом можешь только подтереться
- for(size_t i = 0; i < str->length; i++)
- str->data[i] = toupper(str->data[i]);
- return str;
- }
- // Converts dynamic string characters to lowercase.
- dstring_t * dstr_tolower(dstring_t * str) {//и этим тоже.
- for(size_t i = 0; i < str->length; i++)
- str->data[i] = tolower(str->data[i]);
- return str;
- }
- */
- //..Давай поясню почему это мусор - это в 10+раз тормазнее нормальной реализации не через таблицу.
- //тебе надо поднять диапазон a-z до a-A - это всё идеально векторизуется в if(c >= 'a' && c <= 'z') c += diffAa;
- /* Insert value of string $val after $n character $str. */
- dstring_t * dstr_insert(dstring_t * str, const char * val, size_t n) { //т.е. твоя вставка в начало не вставка? Просто логика
- // *** тут я не понял что ты умеешь ввиду
- // *** это вставка после n-ного символа в строке
- //// я имею ввиду то, что у тебя есть вставка в начало, которая эквивалентна dstr_insert(x, y, 0); Зачем писать ещё одну куллфункцию раздувая код?
- if(val == NULL || n > str->length) return str;
- size_t val_len = strlen(val);
- if(val_len == 0) return str;
- size_t new_capacity = str->capacity + val_len;
- if(dstr_capacity_resize(str, new_capacity))
- str->capacity = new_capacity;
- // move the $str value on $val_len characters to rigth
- memmove(str->data + val_len + n, str->data + n, str->length - n);
- memcpy(str->data + n, val, val_len);
- str->length += val_len;
- return str;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement