#ifndef XPP_MYSTRING_H
#define XPP_MYSTRING_H
#include <cstring>
#include <cstdlib>
#include <string>
int sizeOfStr(const char str[]);
/**
* Thread Non-Safe
* Mutable => String 은 Immutable 하게 구현하는 것이 좋다.
* Not Cached in inner Map
* => 만일 특정 종류의 문자열을 여러번 다루는 경우, 생성자를 private 으로 감추고
* 팩토리 패턴으로만 인스턴스를 생성하면서
* 내부에서 이미 동등한 인스턴스가 존재하는지 cache 를 검사하게 할 수도 있다.
*/
class MyDynamicString {
private:
char *memory;
public:
//동적할당이 아니고 immutable 하게 한다면 이것도 가능하다.
//MyDynamicString(char str[] = "") : memory(str) {}
MyDynamicString(char str[] = "");
MyDynamicString(const MyDynamicString &other);
MyDynamicString &operator=(MyDynamicString &other);
friend std::ostream& operator<<(std::ostream &os, MyDynamicString &myDynamicString);
/*
* @return dynamic 하게 계산된 길이
* 매번 loop 를 돌면서 계산하는 것 말고, 길이가 바뀔때마다 길이 필드를 update 하는 것이 더 좋을 수 있다.
*/
int size() const{
return sizeOfStr(memory);
}
void cpy(const char str[], bool deleting = true);
public:
//동적할당이 아니고 immutable 하게 한다면 이것도 가능하다.
//MyDynamicString(char str[] = "") : memory(str) {}
MyDynamicString(char str[] = "");
MyDynamicString(const MyDynamicString &other);
MyDynamicString &operator=(const MyDynamicString &other);
friend std::ostream& operator<<(std::ostream &os, const MyDynamicString &myDynamicString);
/*
* @return dynamic 하게 계산된 길이
* 매번 loop 를 돌면서 계산하는 것 말고, 길이가 바뀔때마다 길이 필드를 update 하는 것이 더 좋을 수 있다.
*/
int size() const{
return sizeOfStr(memory);
}
void cpy(const char str[], const bool deleting = true);
void cat(const char str[]);
int cmp(const char str[]) const;
std::string tostring() const{
return memory;
}
~MyDynamicString() {
delete[] memory;
}
};
int sizeOfStr(const char str[]) {
int counter = 0;
const char *m = str;
while (*(m++) != '\0') {
counter++;
}
return counter;
}
#endif //XPP_MOCK_H
#include "mystring.h"
MyDynamicString::MyDynamicString(char str[]) {
int len = sizeOfStr(str);
memory = new char[len]();
for (int i = 0; i < len; ++i) {
memory[i] = str[i];
}
}
MyDynamicString::MyDynamicString(const MyDynamicString &other) {
cpy(other.memory, false);
}
MyDynamicString &MyDynamicString::operator=(const MyDynamicString &other) {
cpy(other.memory, false);
return *this;
}
std::ostream& operator<<(std::ostream &os, const MyDynamicString &myDynamicString){
os<<myDynamicString.tostring()<<'\n';
return os;
}
void MyDynamicString::cpy(const char str[], const bool deleting) {
int len = sizeOfStr(str);
char *temp = new char[len]();
for (int j = 0; j < len; ++j) {
temp[j] = str[j];
}
if (deleting) {
/*
* 실증용 : 기본 타입의 배열이므로 free 도 작동한다.
* 원칙적으로는 new 또는 사용자 정의 객체인경우 delete 를 쓴다.
*/
free(memory);
}
memory = temp;
}
void MyDynamicString::cat(const char str[]) {
const int strLen = sizeOfStr(str);
const int oldMemoryLen = size();
//const 가 앞에 있으므로, 포인터가 const 인 것이 아니고, 포인터가 가리키는 곳을 const로 취급
const char *temp = memory;
char *concatenated = new char[oldMemoryLen + strLen]();
for (int j = 0; j < oldMemoryLen; ++j) {
//concatenated[j] = memory[j]; // => 이것도 가능.
concatenated[j] = *(temp++); // => 이것도 가능. 그냥 포인터로 해봤다.
}
for (int i = 0; i < strLen; ++i) {
concatenated[oldMemoryLen + i] = str[i];
}
delete[] memory;
memory = concatenated;
}
int MyDynamicString::cmp(const char str[]) const{
char *temp = memory;
int i;
for (i = 0; i < size(); ++i, temp++) {
if (str[i] != *temp) {
return *temp - str[i] > 0 ? 1 : -1;
}
}
return str[i] == '\0' ? 0 : 1; //str 의 크기가 memory의 크기 초과이면 1을 반환
}