CryEngine Internals Series #1 - String Types

This is going to be the starting of CryEngine Internals Series. We will explore the code base, and study together various sub-systems as they are the foundation of what makes CryEngine as a whole.

The code base is publicly exposed to end-users (or otherwise noted if it happen to be living inside internal development branch but I have permission to share them with you).

Each post in the series will be marked with #<number> e.g. #1 for ease of referencing back later, as well as to be easily tracked for the progress of how far we have made into the series.

We will start by exploring string.

There are going to be 3 parts

  1. String Types
    Touch the water by getting to know main string types provided by the engine.
  2. String Types - Example Usages
    Drill down slightly on how to practically use it with most frequently used functions of those string types.
  3. String Utilities
    There are ton of low-level string utilities provided by the engine, we will get to know them. They are very handy.

Although Crytek has maintained internal development branch, and public branch on Github. Differences between these twos as of the moment of this writing for strings are very minimal; mostly about modernization of C++ syntax. But the core is pretty much the same.

There are 3 main string header files located inside Code/CryEngine/CryCommon/CryString directory that defined string types we can use for various situations

  1. CryString.h Ref
  2. CryFixedString.h Ref
  3. HashedString.h Ref

Ref links above points to CryEngine’s Github release version 5.6.7.


string & wstring

Its definition depends on whether a definition NOT_USE_CRY_STRING is defined or not. If so, then it falls back to use STL strings i.e. std::string, and std::wstring.

As we know, STL’s strings manage memory on heap. So you have to be careful mostly about performance hit if declare to use it too frequently in hot codepath.

But if NOT_USE_CRY_STRING is not defined, then we will be using the following 2 groups depending on whether RESOURCE_COMPILER is defined or not.

Their typedef definitions are as follows

1st group: if RESOURCE_COMPILER is defined

2nd group: if RESOURCE_COMPILER is not defined

Main code base (per se main engine source code, not most of the tools, or RC) doesn’t define RESOURCE_COMPILER, so we will be using the second group above.

RESOURCE_COMPILER is defined for some projects like tools (locates at Code/Tools), or RC (Resource compiler; yep exactly the name; locates at Code/Tools/RC) project.

Fun fact: Amount of usage of string compared to stack_string is ~10x more at the time of this writing measured from internal development branch.

CryStringT Ref

This variant is reference-tracked string which helps solved situation if we need to avoid heap memory allocation. So we can pass this type of string around even across threads.

This is the main type of string used in code base.

CryStringLocalT Ref

This string type aims to provide string that doesn’t share memory with other strings. By closely compare to CryStringT, if look at the code, at a glance we see both types are really the similar but the core difference is at constructor function chosen to be called by CStringLocalT is variant of constructors from CryStringT.

So we will have a local managed string in memory not share with other strings.

The implementation is very simple that deceives the eyes, but above is the difference.

It can be used via another name CryStringLocal which is shorted for CryStringLocalT<char>.

(Bonus & Optional) CConstCharWrapper Ref (used internally)

This is merely used internally not elsewhere. It is a wrapper used as part of string creation without memory allocation. Its destructor function doesn’t free any memory, but let higher up string class to manage it. It instead sets string to empty.

Notice the use of constant string, and its GetCharPointer() to remove such const via const_cast<char*> to return char pointer.

It works internally by CryStringT to construct an object from its constructor function.


stack_string Ref

It is typedefed to be CryStackStringT<char, 512>.

It is always available to be used, no pre-processor definition would decide its availability. The string is allocated on stack, so it’s much more suitable if you need to use it in hot codepath e.g. in situation of logging a message out into file or console every now and then, thus we can avoid heap allocation unnecessary which could hurt performance.

It is defined as

CryFixedWStringT Ref

This is a template specialization for wchar_t which inherits from CryStackStringT.

CCryFixedStringListT Ref

This is a simple fixed list of CryFixedStringT with fixed string size, and maximum elements in the list. Note leading with CC for its type name.

CryPathString Ref

Regarded as special string mainly used for represent file path. Each platform defines the maximum length of characters through _MAX_PATH.

Its type defined as

typedef CryStackStringT<char, _MAX_PATH> CryPathString.


CHashedString Ref

Basically it is a hashed string. It accepts normal string input, then store its hashed representation of it with an option to store the original string if needed.

It’s always available to be used, no pre-processor definition would decide its availability.

There are 2 definitions which affect the functionality provided as follows (only for non-release build)

  1. HASHEDSTRING_STORES_SOURCE_STRING - for debugging purpose, store original string
  2. HASHEDSTRING_CHECKS_FOR_HASH_CONFLICTS - will also compare string even if hashed strings are equal

Its hashing function GetHashAsString is very simple that it gets the first 32-bit (uint32) data from input string converted into hexadecimal of 8 characters.

First published on March, 9, 2021

Written by Wasin Thonkaew
In case of reprinting, comments, suggestions
or to do anything with the article in which you are unsure of, please
write e-mail to wasin[add]wasin[dot]io

Copyright © 2019-2021 Wasin Thonkaew. All Rights Reserved.