void GfxLinearAllocatorPage::Initialize(size_t pageSizeInByte, bool cpuAccess) { SI_ASSERT(m_pageSize == 0); m_pageSize = pageSizeInByte; BaseDevice& device = SI_BASE_DEVICE(); SI_ASSERT(m_buffer == nullptr); GfxBufferDesc desc; desc.m_bufferSizeInByte = pageSizeInByte; if(cpuAccess) { desc.m_heapType = GfxHeapType::Upload; desc.m_resourceFlags = GfxResourceFlag::None; desc.m_resourceStates = GfxResourceState::GenericRead; } else { desc.m_heapType = GfxHeapType::Default; desc.m_resourceFlags = GfxResourceFlag::AllowUnorderedAccess; desc.m_resourceStates = GfxResourceState::UnorderedAccess; } m_buffer = device.CreateBuffer(desc); m_gpuAddr = m_buffer->GetGpuAddr(); m_cpuAddr = (size_t)m_buffer->Map(0); }
GfxLinearAllocatorPageManager::~GfxLinearAllocatorPageManager() { Terminate(); SI_ASSERT(m_queueBufferCount==0); SI_ASSERT(m_usingPages==nullptr); }
GfxLinearAllocatorPage::~GfxLinearAllocatorPage() { Terminate(); SI_ASSERT(m_pageSize==0); SI_ASSERT(m_buffer==nullptr); SI_ASSERT(m_cpuAddr==0); SI_ASSERT(m_gpuAddr==0); }
/* * Exported function to return whether a UTF-8 sequence is legal or not. * This is not used here; it's just exported. */ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { SI_ASSERT(NULL != source); SI_ASSERT(NULL != sourceEnd); int length = trailingBytesForUTF8[*source]+1; if (source+length > sourceEnd) { return false; } return isLegalUTF8(source, length); }
static Boolean isLegalUTF8(const UTF8 *source, int length) { SI_ASSERT(NULL != source); UTF8 a; const UTF8 *srcptr = source+length; switch (length) { default: return false; /* Everything else falls through when "true"... */ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 2: if ((a = (*--srcptr)) > 0xBF) return false; switch (*source) { /* no fall-through in this inner switch */ case 0xE0: if (a < 0xA0) return false; break; case 0xED: if (a > 0x9F) return false; break; case 0xF0: if (a < 0x90) return false; break; case 0xF4: if (a > 0x8F) return false; break; default: if (a < 0x80) return false; } case 1: if (*source >= 0x80 && *source < 0xC2) return false; } if (*source > 0xF4) return false; return true; }
void GfxLinearAllocatorPageManager::Initialize(uint32_t queueBufferCount, bool cpuAccess) { SI_ASSERT(m_queueBufferCount==0); m_queueBufferCount = queueBufferCount; SI_ASSERT(m_usingPages==nullptr); m_usingPages = SI_NEW_ARRAY(std::vector<GfxLinearAllocatorPage*>, m_queueBufferCount); m_avaiablePages.reserve(128); for(uint32_t i=0; i<m_queueBufferCount; ++i) { m_usingPages[i].reserve(128); } m_cpuAccess = cpuAccess; }
void PoolAllocator::Initialize(void* poolMemory, size_t poolMemorySize) { m_poolMemory = poolMemory; m_poolMemorySize = poolMemorySize; SI_ASSERT(m_mspace == nullptr); m_mspace = create_mspace_with_base(poolMemory , poolMemorySize , 1); // thread safeのためlockedにしておく. }
int BaseBuffer::Initialize(ID3D12Device& device, const GfxBufferDesc& desc) { D3D12_HEAP_PROPERTIES heapProperties = {}; heapProperties.Type = GetDx12HeapType(desc.m_heapType); heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; heapProperties.CreationNodeMask = 1; heapProperties.VisibleNodeMask = 1; D3D12_RESOURCE_DESC resourceDesc = {}; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; resourceDesc.Alignment = 0; resourceDesc.Width = desc.m_bufferSizeInByte; resourceDesc.Height = 1; resourceDesc.DepthOrArraySize = 1; resourceDesc.MipLevels = 1; resourceDesc.Format = DXGI_FORMAT_UNKNOWN; resourceDesc.SampleDesc.Count = 1; resourceDesc.SampleDesc.Quality = 0; resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; resourceDesc.Flags = GetDx12ResourceFlags(desc.m_resourceFlags); D3D12_RESOURCE_STATES resourceState = GetDx12ResourceStates(desc.m_resourceStates); HRESULT hr = device.CreateCommittedResource( &heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, resourceState, nullptr, IID_PPV_ARGS(&m_resource)); if(FAILED(hr)) { SI_ASSERT(0, "error device.CreateCommittedResource", _com_error(hr).ErrorMessage()); return -1; } m_bufferSizeInByte = desc.m_bufferSizeInByte; m_location = m_resource->GetGPUVirtualAddress(); if(desc.m_name) { wchar_t wName[64]; wName[0] = 0; size_t num = 0; errno_t ret = mbstowcs_s(&num, wName, desc.m_name, ArraySize(wName)); if(ret == 0) { m_resource->SetName(wName); } } return 0; }
ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { SI_ASSERT(NULL != sourceStart); SI_ASSERT(NULL != *sourceStart); SI_ASSERT(NULL != targetStart); SI_ASSERT(NULL != *targetStart); // -------------------------------- SI_ASSERT(NULL != sourceEnd); SI_ASSERT(NULL != targetEnd); ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; ch = *source++; if (flags == strictConversion ) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } /* * Figure out how many bytes the result will require. Turn any * illegally large UTF32 things (> Plane 17) into replacement chars. */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; result = sourceIllegal; } target += bytesToWrite; if (target > targetEnd) { --source; /* Back up source pointer! */ target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result; }
void* BaseBuffer::Map(uint32_t subResourceId) { D3D12_RANGE range = {0, 0}; void* addr = nullptr; HRESULT hr = m_resource->Map(subResourceId, &range, &addr); if(FAILED(hr)) { SI_ASSERT(0); return nullptr; } return addr; }
ConversionResult ConvertUTF32toUTF16 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { SI_ASSERT(NULL != sourceStart); SI_ASSERT(NULL != *sourceStart); SI_ASSERT(NULL != targetStart); SI_ASSERT(NULL != *targetStart); // -------------------------------- SI_ASSERT(NULL != sourceEnd); SI_ASSERT(NULL != targetEnd); ConversionResult result = conversionOK; const UTF32* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { UTF32 ch; if (target >= targetEnd) { result = targetExhausted; break; } ch = *source++; if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = (UTF16)ch; /* normal case */ } } else if (ch > UNI_MAX_LEGAL_UTF32) { if (flags == strictConversion) { result = sourceIllegal; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ if (target + 1 >= targetEnd) { --source; /* Back up source pointer! */ result = targetExhausted; break; } ch -= halfBase; *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); } } *sourceStart = source; *targetStart = target; return result; }
void Geometry::ImportSerializeData(const GeometrySerializeData& s) { GfxDevice& device = *GfxDevice::GetInstance(); m_vertexLayout = s.m_vertexLayout; m_is16bitIndex = s.m_is16bitIndex; m_vertexBuffer.InitializeAsVertex( "vertex", s.m_rawVertexBuffer.GetItemsAddr(), s.m_rawVertexBuffer.GetItemCount()/m_vertexLayout.m_stride, m_vertexLayout.m_stride, 0); m_indexBuffer.InitializeAsIndex( "index", s.m_rawIndexBuffer.GetItemsAddr(), s.m_rawIndexBuffer.GetItemCount() / (m_is16bitIndex!=0? 2 : 4), m_is16bitIndex!=0); m_inputElements.Setup(m_vertexLayout.m_attributeCount); uint32_t offset = 0; for(uint8_t attr=0; attr<m_vertexLayout.m_attributeCount; ++attr) { const VertexSemanticsAndFormat& vsf = m_vertexLayout.m_attributes[attr]; GfxInputElement& ve = m_inputElements[attr]; ve = GfxInputElement( GetSemanticsName(vsf.m_semantics.m_semanticsType), vsf.m_semantics.m_semanticsIndex, vsf.m_format, 0, offset); uint32_t formatBits = (uint32_t)GetFormatBits(vsf.m_format); SI_ASSERT(formatBits%8==0); offset += formatBits/8; } }
PoolAllocator::~PoolAllocator() { SI_ASSERT(m_mspace == nullptr); SI_ASSERT(m_poolMemory == nullptr); SI_ASSERT(m_poolMemorySize == 0); }
ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { SI_ASSERT(NULL != sourceStart); SI_ASSERT(NULL != *sourceStart); SI_ASSERT(NULL != targetStart); SI_ASSERT(NULL != *targetStart); // -------------------------------- SI_ASSERT(NULL != sourceEnd); SI_ASSERT(NULL != targetEnd); ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { UTF32 ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ result = sourceExhausted; break; } } else if (flags == strictConversion) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } /* Figure out how many bytes the result will require */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; } target += bytesToWrite; if (target > targetEnd) { source = oldSource; /* Back up source pointer! */ target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result; }
void* PoolAllocator::Allocate(size_t size, size_t alignment) { void* p = mspace_memalign(m_mspace, alignment, size); SI_ASSERT(p != nullptr); return p; }
void* PoolAllocator::Allocate(size_t size) { void* p = mspace_malloc(m_mspace, size); SI_ASSERT(p != nullptr); return p; }
void PoolAllocator::Deallocate(void* p) { SI_ASSERT((uintptr_t)m_poolMemory <= (uintptr_t)p); SI_ASSERT((uintptr_t)p<(uintptr_t)m_poolMemory + m_poolMemorySize); mspace_free(m_mspace, p); }
ConversionResult ConvertUTF8toUTF32 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { SI_ASSERT(NULL != sourceStart); SI_ASSERT(NULL != *sourceStart); SI_ASSERT(NULL != targetStart); SI_ASSERT(NULL != *targetStart); // -------------------------------- SI_ASSERT(NULL != sourceEnd); SI_ASSERT(NULL != targetEnd); ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF32* target = *targetStart; while (source < sourceEnd) { UTF32 ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { result = sourceExhausted; break; } /* Do this check whether lenient or strict */ if (! isLegalUTF8(source, extraBytesToRead+1)) { result = sourceIllegal; break; } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; case 4: ch += *source++; ch <<= 6; case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up the source pointer! */ result = targetExhausted; break; } if (ch <= UNI_MAX_LEGAL_UTF32) { /* * UTF-16 surrogate values are illegal in UTF-32, and anything * over Plane 17 (> 0x10FFFF) is illegal. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = ch; } } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ result = sourceIllegal; *target++ = UNI_REPLACEMENT_CHAR; } } *sourceStart = source; *targetStart = target; return result; }
int BaseGraphicsState::Initialize(ID3D12Device& device, const GfxGraphicsStateDesc& desc) { D3D12_INPUT_ELEMENT_DESC elements[32]; SI_ASSERT(desc.m_inputElementCount < ArraySize(elements)); uint32_t elementCont = SI::Min((uint32_t)desc.m_inputElementCount, (uint32_t)ArraySize(elements)); for(uint32_t e=0; e<elementCont; ++e) { D3D12_INPUT_ELEMENT_DESC& outElem = elements[e]; const GfxInputElement& inElem = desc.m_inputElements[e]; outElem.SemanticName = inElem.m_semanticsName; outElem.SemanticIndex = inElem.m_semanticsId; outElem.Format = SI::GetDx12Format(inElem.m_format); outElem.InputSlot = inElem.m_inputSlot; outElem.AlignedByteOffset = inElem.m_alignedByteOffset; outElem.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; outElem.InstanceDataStepRate = 0; } const BaseShader* vertexShader = desc.m_vertexShader->GetBaseShader(); const BaseShader* pixelShader = desc.m_pixelShader->GetBaseShader(); D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { elements, elementCont }; psoDesc.pRootSignature = desc.m_rootSignature->GetBaseRootSignature()->GetComPtrRootSignature().Get(); psoDesc.VS.pShaderBytecode = vertexShader? vertexShader->GetBinary() : nullptr; psoDesc.VS.BytecodeLength = vertexShader? vertexShader->GetBinarySize() : 0; psoDesc.PS.pShaderBytecode = pixelShader? pixelShader->GetBinary() : nullptr; psoDesc.PS.BytecodeLength = pixelShader? pixelShader->GetBinarySize() : 0; psoDesc.RasterizerState.FillMode = GetDx12FillMode(desc.m_fillMode); psoDesc.RasterizerState.CullMode = GetDx12CullMode(desc.m_cullMode); psoDesc.RasterizerState.FrontCounterClockwise = desc.m_frontCounterClockwise? TRUE : FALSE; psoDesc.RasterizerState.DepthBias = desc.m_depthBias; psoDesc.RasterizerState.DepthBiasClamp = desc.m_depthBiasClamp; psoDesc.RasterizerState.SlopeScaledDepthBias = desc.m_slopeScaledDepthBias; psoDesc.RasterizerState.DepthClipEnable = TRUE; psoDesc.RasterizerState.MultisampleEnable = FALSE; psoDesc.RasterizerState.AntialiasedLineEnable = FALSE; psoDesc.RasterizerState.ForcedSampleCount = 0; psoDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = GetDx12PrimitiveTopologyType(desc.m_primitiveTopologyType); psoDesc.SampleDesc.Count = 1; psoDesc.NumRenderTargets = desc.m_renderTargetCount; psoDesc.BlendState.AlphaToCoverageEnable = FALSE; psoDesc.BlendState.IndependentBlendEnable = FALSE; psoDesc.DepthStencilState.DepthEnable = desc.m_depthEnable? TRUE : FALSE; psoDesc.DepthStencilState.StencilEnable = desc.m_stencilEnable? TRUE : FALSE; if(psoDesc.DepthStencilState.DepthEnable) { psoDesc.DepthStencilState.DepthWriteMask = GetDx12DepthWriteMask(desc.m_depthWriteMask); psoDesc.DepthStencilState.DepthFunc = GetDx12ComparisonFunc(desc.m_depthFunc); } SI_ASSERT(desc.m_renderTargetCount <= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT); UINT blendRtCount = psoDesc.BlendState.IndependentBlendEnable? psoDesc.NumRenderTargets : 1; for (UINT rt = 0; rt<blendRtCount; ++rt) { D3D12_RENDER_TARGET_BLEND_DESC& outBlend = psoDesc.BlendState.RenderTarget[rt]; const GfxRenderTargetBlendDesc& inBlend = desc.m_rtvBlend[rt]; outBlend.BlendEnable = inBlend.m_blendEnable? TRUE : FALSE; outBlend.LogicOpEnable = inBlend.m_logicOpEnable? TRUE : FALSE; outBlend.SrcBlend = GetDx12Blend(inBlend.m_srcBlend); outBlend.DestBlend = GetDx12Blend(inBlend.m_destBlend); outBlend.BlendOp = GetDx12BlendOp(inBlend.m_blendOp); outBlend.SrcBlendAlpha = GetDx12Blend(inBlend.m_srcBlendAlpha); outBlend.DestBlendAlpha = GetDx12Blend(inBlend.m_destBlendAlpha); outBlend.BlendOpAlpha = GetDx12BlendOp(inBlend.m_blendOpAlpha); outBlend.LogicOp = GetDx12LogicOp(inBlend.m_logicOp); outBlend.RenderTargetWriteMask = GetDx12RenderTargetWriteMask(inBlend.m_rtWriteMask); } for (UINT rt = 0; rt<psoDesc.NumRenderTargets; ++rt) { psoDesc.RTVFormats[rt] = GetDx12Format(desc.m_rtvFormats[rt]); } psoDesc.DSVFormat = GetDx12Format(desc.m_dsvFormat); HRESULT hr = device.CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)); if(FAILED(hr)) { SI_ASSERT(0); return -1; } if(desc.m_name) { wchar_t wName[64]; wName[0] = 0; size_t num = 0; errno_t ret = mbstowcs_s(&num, wName, desc.m_name, ArraySize(wName)); if(ret == 0) { m_pipelineState->SetName(wName); } } return 0; }
ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { SI_ASSERT(NULL != sourceStart); SI_ASSERT(NULL != *sourceStart); SI_ASSERT(NULL != targetStart); SI_ASSERT(NULL != *targetStart); // -------------------------------- SI_ASSERT(NULL != sourceEnd); SI_ASSERT(NULL != targetEnd); ConversionResult result = conversionOK; const UTF8* source = *sourceStart; UTF16* target = *targetStart; while (source < sourceEnd) { UTF32 ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { result = sourceExhausted; break; } /* Do this check whether lenient or strict */ if (! isLegalUTF8(source, extraBytesToRead+1)) { result = sourceIllegal; break; } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ result = targetExhausted; break; } if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (flags == strictConversion) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ result = sourceIllegal; break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = (UTF16)ch; /* normal case */ } } else if (ch > UNI_MAX_UTF16) { if (flags == strictConversion) { result = sourceIllegal; source -= (extraBytesToRead+1); /* return to the start */ break; /* Bail out; shouldn't continue */ } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ if (target + 1 >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ result = targetExhausted; break; } ch -= halfBase; *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); } } *sourceStart = source; *targetStart = target; return result; }
ConversionResult ConvertUTF16toUTF32 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { SI_ASSERT(NULL != sourceStart); SI_ASSERT(NULL != *sourceStart); SI_ASSERT(NULL != targetStart); SI_ASSERT(NULL != *targetStart); // -------------------------------- SI_ASSERT(NULL != sourceEnd); SI_ASSERT(NULL != targetEnd); ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF32* target = *targetStart; UTF32 ch, ch2; while (source < sourceEnd) { const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ result = sourceExhausted; break; } } else if (flags == strictConversion) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } if (target >= targetEnd) { source = oldSource; /* Back up source pointer! */ result = targetExhausted; break; } *target++ = ch; } *sourceStart = source; *targetStart = target; #ifdef CVTUTF_DEBUG if (result == sourceIllegal) { fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); fflush(stderr); } #endif return result; }