[Unreal] 언리얼 문자열 처리 방식
Table of Contents
UTF-16에 대해 알아보자 #
- 문자열 처리방식은 ANSI, ASCII, EUC-KR, CP949, UTF-8 BOM, UTF-8, UTF-16 등 정말 다양하다.
- 유니코드(Unicode)
- 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현할 수 있도록 고안된 코드 집합(표)이다.
- 인코딩 방식이란?
- 문자나 기호들을 컴퓨터가 이용할 수 있는 신호로 만드는 것을 말한다.
- 즉, 문자들을 바이트열에 표현하는 방식이다.
- 유니코드의 인코딩 방식
- 여기에는 UTF-8, UTF-16 등이 있다.
- ANSI, ASCII, EUC-KR, CP949 등의 인코딩 방식은 코드 표에서 원하는 문자에 해당하는 코드를 찾아 그대로 바이트열에 쓰는 방식이었다.
- 하지만 유니코드는 똑같은 문자도 인코딩 방식에 따라 바이트열에 다르게 표현될 수 있다.
- 먼저 유니코드 표에서 인코딩하고자 하는 문자의 코드를 찾는다.
- 다음으로, 그 코드를 각 인코딩 방식에서 정해둔 어떤 규칙에 따라 변형시켜서 바이트열에 표현한다.
- UTF-16 (16-bit Unicode Transformation Format)
- 인코딩 하려는 문자가 속한 범위에 따라서 16bit 단위로 늘려가며 인코딩하는 가변 인코딩 방식이다.
- 주로 사용되는 기본 다국어 평면 (BMP, Basic multilingual plane)에 속하는 문자들은 그대로 16bit 값으로 인코딩이 되고, 그 이상의 문자는 특별히 정해진 방식으로 32bit로 인코딩이 된다.
- BOM(Byte Order Mark, 바이트 순서 표시)
- 파일의 맨 앞에 붙여서, 바이트를 저장한 방식이 리틀 엔디언인지 빅 엔디언인지 전달한다.
- 리틀 엔디언(Little Endian) 과 빅 엔디언(Big Endian)
- 컴퓨터는 데이터를 byte 단위로 나눠서 메모리에 저장하는데, 이 때 데이터를 메모리에 어떤 순서로 저장할 것인가(바이트 오더)를 엔디안이라고 한다.
항목 설명 0x12345678
의 표현리틀 엔디언 낮은 주소에 MSB부터 저장하는 방식이다.
(Most Significant Bit, 최상위 비트)0x12
,0x34
,0x56
,0x78
빅 엔디언 낮은 주소에 LSB부터 저장하는 방식이다.
(Least Significant Bit, 최하위 비트)0x78
,0x56
,0x34
,0x12
- 컴퓨터는 데이터를 byte 단위로 나눠서 메모리에 저장하는데, 이 때 데이터를 메모리에 어떤 순서로 저장할 것인가(바이트 오더)를 엔디안이라고 한다.
언리얼의 문자열 처리 방식 #
- 언리얼은 문자열 처리방식을 통일하여 UTF-16을 사용한다.
- 동아시아(한국어 포함) 인코딩의 경우 UTF-8 방식으로 저장해야 한다.
- 언리얼 공식 문서 : 캐릭터 인코딩
- 인코딩 변환 매크로들
- 스트링을 다양한 인코딩으로 상호 변환할 수 있는 매크로가 많이 있다.
TCHAR_TO_ANSI(str)
TCHAR_TO_OEM(str)
ANSI_TO_TCHAR(str)
TCHAR_TO_UTF8(str)
UTF8_TO_TCHAR(str)
- 유니코드를 위한 언리얼 표준 캐릭터 타입(네이티브 유니코드 인코딩)이 바로
TCHAR
이다. TEXT()
매크로를 사용해서 문자열을 지정하면TCHAR[]
배열로 지정된다.TEXT()
매크로를 지정하지 않으면, 리터럴은 ANSI 를 사용해서 인코딩되기에, 지원되는 글자가 크게 제한된다.- ANSI 리터럴을
FString
로 전달하면TCHAR
으로의 변환하는 과정을 겪어야 하기에,TEXT()
를 사용하는 편이 보다 효율적이다.
- ANSI 리터럴을
- 언리얼 공식 문서 : 문자열 처리
FString
#
- 조작이 가능한 유일한 스트링 클래스이다.
TCHAR[]
배열로 만들어져있다.
FString
과TCHAR
와의 관계
// TCHAR 배열
TCHAR LogCharArray[] = TEXT("Hello Unreal");
UE_LOG(LogTemp, Log, LogCharArray);
// TCHAR 배열을 다루는 FString 클래스 -> *연산자 붙여야 한다.
FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString);
// FString 클래스에 *연산자를 붙이면 const TCHAR*를 받을 수 있다.
const TCHAR* LogCharPtr = *LogCharString;
// FString 클래스 안에 있는 진짜 데이터를 끄집어내는 방법 -> 문자열 수정 가능
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData();
- 다른 타입과
FString
간의 변환
int32 IntValue = 32;
float FloatValue = 3.141592;
// Int, Float -> FString
FString FloatIntString = FString::Printf(TEXT("Int : %d, Float : %f"), IntValue, FloatValue);
FString IntString = FString::FromInt(IntValue);
FString FloatString = FString::SanitizeFloat(FloatValue);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString);
UE_LOG(LogTemp, Log, TEXT("Int : %s, Float : %s"), *IntString, *FloatString);
// FString -> Int, Float (안전하지 않으므로 주의가 필요하다.)
int32 IntValueFromString = FCString::Atoi(*IntString);
float FloatValueFromString = FCString::Atof(*FloatString);
FString FloatIntString2 = FString::Printf(TEXT("Int : %d, Float : %f"), IntValueFromString, FloatValueFromString);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString2);
FString
은 용도에 따라FName
,FText
로 관리될 수 있다.
FName
#
- 에셋 관리를 위해 사용되는 문자열 체계이다. 문자를 표현하는 용도가 아닌 에셋 키를 지정하는 용도로 사용한다.
- 대소문자를 구분하지 않고, 한 번 선언되면 변경이 불가능하다.
FNamePool
이라는 싱글톤 자료구조가 있고, 그 안에서FName
을 해시 테이블로 관리한다.- 해시를 사용하므로 찾기가 매우 빠르다.
FName
을 생성할 때는 문자열을 Key로 변환하고 전역 Pool에 있는지를 검사하는 오버헤드가 발생하므로 주의가 필요하다.
// 빈번하게 호출되는 상황
for (int i = 0; i < 10000; i++)
{
// FName 생성자에 문자열을 넣으면?
// 문자열을 Key로 변환하고 전역 Pool에 있는지를 검사하는 오버헤드가 발생한다.
// 따라서 주의가 필요하다.
FName SearchInNamePool = FName(TEXT("pelvis"));
// 이렇게 한번만 처리하도록 하는 것이 좋겠다.
const static FName StaticOnlyOnce(TEXT("pelvis"));
}
FText
#
- 다국어 지원을 위한 문자열 체계이다.
- 별도의 문자열 테이블 정보가 추가로 요구된다.
- 게임 빌드시 자동으로 다양한 국가별 언어로 변환된다.
상호 간의 변환 #
FString
으로의 변환
from | to | 코드 |
---|---|---|
FName |
FString |
MyName.ToString(); |
FText |
FString |
MyText.ToString(); 언어 변환시 손실 위험 때문에 안전하지 않다. |
FName
으로의 변환
from | to | 코드 |
---|---|---|
FString |
FName |
FName(*MyString); FName 이 대소문자 구분 없기에 손실 위험이 있다. |
FText |
FName |
FText → FString → FName (직접 변환 없음)FName 이 대소문자 구분 없기에 손실 위험이 있다. |
FText
으로의 변환
from | to | 코드 |
---|---|---|
FString |
FText |
FText::FromString(MyString); 자동 현지화 못받을 수 있다. |
FName |
FText |
FText::FromName(MyName); 자동 현지화 못받을 수 있다. |