Реализация пользовательского диспетчера строк (расширенный метод)
В специализированных ситуациях может потребоваться реализовать пользовательский диспетчер строк, который делает больше, чем просто изменение кучи, используемой для выделения памяти. В этой ситуации необходимо вручную реализовать интерфейс IAtlStringMgr в качестве пользовательского диспетчера строк.
Для этого важно сначала понять, как CStringT использует этот интерфейс для управления строковыми данными. Каждый экземпляр CStringT
имеет указатель на структуру CStringData . Эта структура переменной длины содержит важные сведения о строке (например, длине), а также фактические символьные данные для строки. Каждый пользовательский диспетчер строк отвечает за выделение и освобождение этих структур по запросу CStringT
.
Структура CStringData
состоит из четырех полей:
PStringMgr Это поле указывает на интерфейс,
IAtlStringMgr
используемый для управления данными строки. ЕслиCStringT
необходимо перераспределить или освободить буфер строки, который вызывает методы Reallocate или Free этого интерфейса, передав структуруCStringData
в качестве параметра. При выделенииCStringData
структуры в диспетчере строк необходимо задать это поле для указания пользовательского диспетчера строк.nDataLength Это поле содержит текущую логическую длину строки, хранящейся в буфере, за исключением конца null.
CStringT
обновляет это поле при изменении длины строки. При выделенииCStringData
структуры диспетчер строк должен задать это поле равным нулю. При перемещении структуры настраиваемыйCStringData
диспетчер строк должен оставить это поле неизменным.NAllocLength Это поле содержит максимальное количество символов (за исключением конца NULL), которое можно хранить в этом буфере строки без перераспределения. Каждый раз
CStringT
, когда необходимо увеличить логическую длину строки, сначала проверяет это поле, чтобы убедиться, что в буфере достаточно места. Если проверка завершается ошибкой, вызовы в пользовательский диспетчер строк дляCStringT
перераспределации буфера. При выделении или перемещенииCStringData
структуры необходимо задать по крайней мере количество символов, запрошенных в параметре nChars , значение IAtlStringMgr::Allocate или IAtlStringMgr::Reallocate. Если в буфере больше места, чем запрошено, можно задать это значение, чтобы отразить фактическое количество свободного места. Это позволяетCStringT
увеличить строку для заполнения всего выделенного пространства, прежде чем он должен вернуться в диспетчер строк, чтобы перераспределить буфер.nRefs Это поле содержит текущее число ссылок буфера строки. Если значение равно одному, то один экземпляр
CStringT
использует буфер. Кроме того, экземпляр может читать и изменять содержимое буфера. Если значение больше одного, несколько экземпляровCStringT
могут использовать буфер. Так как буфер символов является общим,CStringT
экземпляры могут считывать только содержимое буфера. Чтобы изменить содержимое,CStringT
сначала создайте копию буфера. Если значение отрицательное, используется только один экземплярCStringT
буфера. В этом случае буфер считается заблокированным.CStringT
Если экземпляр использует заблокированный буфер, другие экземплярыCStringT
не могут совместно использовать буфер. Вместо этого эти экземпляры создают копию буфера перед обработкой содержимого. Кроме того, экземпляр, использующий заблокированный буфер,CStringT
не пытается совместно использовать буфер любого другогоCStringT
экземпляра, назначенного ему. В этом случаеCStringT
экземпляр копирует другую строку в заблокированный буфер.При выделении
CStringData
структуры необходимо задать это поле, чтобы отразить тип общего доступа, разрешенный для буфера. Для большинства реализаций задайте для этого значения одно значение. Это позволяет обычному поведению совместного использования копирования на записи. Однако если диспетчер строк не поддерживает общий доступ к буферу строки, задайте для этого поля состояние блокировки. Это заставляетCStringT
использовать только этот буфер для экземпляра, выделенногоCStringT
им.