16 changed files with 684175 additions and 684048 deletions
@ -1,65 +0,0 @@ |
|||||
// Copyright 2023 The Ip2Region Authors. All rights reserved.
|
|
||||
// Use of this source code is governed by a Apache2.0-style
|
|
||||
// license that can be found in the LICENSE file.
|
|
||||
// @Author Alan <lzh.shap@gmail.com>
|
|
||||
// @Date 2023/07/25
|
|
||||
|
|
||||
using System; |
|
||||
using System.Buffers; |
|
||||
using System.IO; |
|
||||
|
|
||||
namespace IP2Region.Net.Internal.Abstractions; |
|
||||
|
|
||||
internal abstract class AbstractCacheStrategy |
|
||||
{ |
|
||||
protected const int HeaderInfoLength = 256; |
|
||||
protected const int VectorIndexRows = 256; |
|
||||
protected const int VectorIndexCols = 256; |
|
||||
protected const int VectorIndexSize = 8; |
|
||||
|
|
||||
protected readonly Stream XdbStream; |
|
||||
private const int BufferSize = 4096; |
|
||||
|
|
||||
internal int IoCount { get; private set; } |
|
||||
|
|
||||
protected AbstractCacheStrategy(Stream xdbStream) |
|
||||
{ |
|
||||
XdbStream = xdbStream; |
|
||||
} |
|
||||
|
|
||||
protected int GetVectorIndexStartPos(uint ip) |
|
||||
{ |
|
||||
var il0 = ip >> 24 & 0xFF; |
|
||||
var il1 = ip >> 16 & 0xFF; |
|
||||
var idx = il0 * VectorIndexCols * VectorIndexSize + il1 * VectorIndexSize; |
|
||||
return (int)idx; |
|
||||
} |
|
||||
|
|
||||
internal abstract ReadOnlyMemory<byte> GetVectorIndex(uint ip); |
|
||||
|
|
||||
internal virtual ReadOnlyMemory<byte> GetData(int offset, int length) |
|
||||
{ |
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(length); |
|
||||
int totalBytesRead = 0; |
|
||||
try |
|
||||
{ |
|
||||
XdbStream.Seek(offset, SeekOrigin.Begin); |
|
||||
|
|
||||
int bytesRead; |
|
||||
do |
|
||||
{ |
|
||||
int bytesToRead = Math.Min(BufferSize, length - totalBytesRead); |
|
||||
bytesRead = XdbStream.Read(buffer, totalBytesRead, bytesToRead); |
|
||||
totalBytesRead += bytesRead; |
|
||||
|
|
||||
IoCount++; |
|
||||
} while (bytesRead > 0 && totalBytesRead < length); |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
ArrayPool<byte>.Shared.Return(buffer); |
|
||||
} |
|
||||
|
|
||||
return new ReadOnlyMemory<byte>(buffer, 0, totalBytesRead); |
|
||||
} |
|
||||
} |
|
||||
@ -1,33 +1,21 @@ |
|||||
// Copyright 2023 The Ip2Region Authors. All rights reserved.
|
// Copyright 2025 The Ip2Region Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache2.0-style
|
// Use of this source code is governed by a Apache2.0-style
|
||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||
// @Author Alan <lzh.shap@gmail.com>
|
// @Author Alan <lzh.shap@gmail.com>
|
||||
// @Date 2023/07/25
|
// @Date 2023/07/25
|
||||
|
// Updated by Argo Zhang <argo@live.ca> at 2025/11/21
|
||||
|
|
||||
using IP2Region.Net.Internal.Abstractions; |
|
||||
using IP2Region.Net.XDB; |
using IP2Region.Net.XDB; |
||||
using System; |
|
||||
using System.IO; |
using System.IO; |
||||
|
|
||||
namespace IP2Region.Net.Internal; |
namespace IP2Region.Net.Internal; |
||||
|
|
||||
internal class CacheStrategyFactory |
static class CacheStrategyFactory |
||||
{ |
{ |
||||
private readonly Stream _xdbStream; |
public static ICacheStrategy CreateCacheStrategy(CachePolicy cachePolicy, Stream xdbStream) => cachePolicy switch |
||||
|
|
||||
public CacheStrategyFactory(Stream xdbStream) |
|
||||
{ |
|
||||
_xdbStream = xdbStream; |
|
||||
} |
|
||||
|
|
||||
public AbstractCacheStrategy CreateCacheStrategy(CachePolicy cachePolicy) |
|
||||
{ |
|
||||
return cachePolicy switch |
|
||||
{ |
{ |
||||
CachePolicy.Content => new ContentCacheStrategy(_xdbStream), |
CachePolicy.Content => new ContentCacheStrategy(xdbStream), |
||||
CachePolicy.VectorIndex => new VectorIndexCacheStrategy(_xdbStream), |
CachePolicy.VectorIndex => new VectorIndexCacheStrategy(xdbStream), |
||||
CachePolicy.File => new FileCacheStrategy(_xdbStream), |
_ => new StreamCacheStrategy(xdbStream), |
||||
_ => throw new ArgumentException(nameof(cachePolicy)) |
|
||||
}; |
}; |
||||
} |
} |
||||
} |
|
||||
@ -1,34 +1,37 @@ |
|||||
// Copyright 2023 The Ip2Region Authors. All rights reserved.
|
// Copyright 2025 The Ip2Region Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache2.0-style
|
// Use of this source code is governed by a Apache2.0-style
|
||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||
// @Author Alan <lzh.shap@gmail.com>
|
// @Author Alan <lzh.shap@gmail.com>
|
||||
// @Date 2023/07/25
|
// @Date 2023/07/25
|
||||
|
// Updated by Wong <vcd.hai@outlook.com> at 2025/12/31
|
||||
|
|
||||
using IP2Region.Net.Internal.Abstractions; |
|
||||
using System; |
using System; |
||||
using System.IO; |
using System.IO; |
||||
|
|
||||
namespace IP2Region.Net.Internal; |
namespace IP2Region.Net.Internal; |
||||
|
|
||||
internal class ContentCacheStrategy : AbstractCacheStrategy |
class ContentCacheStrategy(Stream _xdbStream) : ICacheStrategy |
||||
{ |
{ |
||||
private readonly ReadOnlyMemory<byte> _cacheData; |
// TODO: these constants can be moved to the interface as defaults when using .NET 10
|
||||
|
private const int HeaderInfoLength = 256; |
||||
|
private const int VectorIndexSize = 8; |
||||
|
|
||||
public ContentCacheStrategy(Stream xdbStream) : base(xdbStream) |
private readonly ReadOnlyMemory<byte> _cacheData = _xdbStream.GetAllBytes(); |
||||
{ |
|
||||
_cacheData = base.GetData(0, (int)XdbStream.Length); |
public int IoCount => 0; |
||||
XdbStream.Close(); |
|
||||
XdbStream.Dispose(); |
|
||||
} |
|
||||
|
|
||||
internal override ReadOnlyMemory<byte> GetVectorIndex(uint ip) |
public void ResetIoCount() |
||||
{ |
{ |
||||
int idx = GetVectorIndexStartPos(ip); |
// Do nothing
|
||||
return _cacheData.Slice(HeaderInfoLength + idx, VectorIndexSize); |
|
||||
} |
} |
||||
|
|
||||
internal override ReadOnlyMemory<byte> GetData(int offset, int length) |
public ReadOnlyMemory<byte> GetVectorIndex(int offset) |
||||
|
=> _cacheData.Slice(HeaderInfoLength + offset, VectorIndexSize); |
||||
|
|
||||
|
public ReadOnlyMemory<byte> GetData(long offset, int length) => _cacheData.Slice((int)offset, length); |
||||
|
|
||||
|
public void Dispose() |
||||
{ |
{ |
||||
return _cacheData.Slice(offset, length); |
// Do nothing
|
||||
} |
} |
||||
} |
} |
||||
@ -1,24 +1,15 @@ |
|||||
// Copyright 2023 The Ip2Region Authors. All rights reserved.
|
// Copyright 2025 The Ip2Region Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache2.0-style
|
// Use of this source code is governed by a Apache2.0-style
|
||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||
// @Author Alan <lzh.shap@gmail.com>
|
// @Author Alan <lzh.shap@gmail.com>
|
||||
// @Date 2023/07/25
|
// @Date 2023/07/25
|
||||
|
// Updated by Argo Zhang <argo@live.ca> at 2025/11/21
|
||||
|
|
||||
using IP2Region.Net.Internal.Abstractions; |
|
||||
using System; |
|
||||
using System.IO; |
using System.IO; |
||||
|
|
||||
namespace IP2Region.Net.Internal; |
namespace IP2Region.Net.Internal; |
||||
|
|
||||
internal class FileCacheStrategy : AbstractCacheStrategy |
class FileCacheStrategy(Stream xdbFileStream) : StreamCacheStrategy(xdbFileStream) |
||||
{ |
{ |
||||
public FileCacheStrategy(Stream xdbStream) : base(xdbStream) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
internal override ReadOnlyMemory<byte> GetVectorIndex(uint ip) |
|
||||
{ |
|
||||
var idx = GetVectorIndexStartPos(ip); |
|
||||
return GetData(HeaderInfoLength + idx, VectorIndexSize); |
|
||||
} |
|
||||
} |
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// Copyright 2025 The Ip2Region Authors. All rights reserved.
|
||||
|
// Use of this source code is governed by a Apache2.0-style
|
||||
|
// license that can be found in the LICENSE file.
|
||||
|
// @Author Alan <lzh.shap@gmail.com>
|
||||
|
// @Date 2023/07/25
|
||||
|
// Updated by Argo Zhang <argo@live.ca> at 2025/11/21
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace IP2Region.Net.Internal; |
||||
|
|
||||
|
internal interface ICacheStrategy : IDisposable |
||||
|
{ |
||||
|
int IoCount { get; } |
||||
|
|
||||
|
void ResetIoCount(); |
||||
|
|
||||
|
ReadOnlyMemory<byte> GetVectorIndex(int offset); |
||||
|
|
||||
|
ReadOnlyMemory<byte> GetData(long offset, int length); |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
using System; |
||||
|
using System.Buffers; |
||||
|
using System.IO; |
||||
|
|
||||
|
namespace IP2Region.Net.Internal; |
||||
|
internal class StreamCacheStrategy(Stream _xdbStream) : ICacheStrategy |
||||
|
{ |
||||
|
protected const int HeaderInfoLength = 256; |
||||
|
protected const int VectorIndexSize = 8; |
||||
|
|
||||
|
protected const int BufferSize = 64 * 1024; |
||||
|
|
||||
|
public int IoCount { get; set; } |
||||
|
|
||||
|
public void ResetIoCount() |
||||
|
{ |
||||
|
IoCount = 0; |
||||
|
} |
||||
|
|
||||
|
public virtual ReadOnlyMemory<byte> GetVectorIndex(int offset) => GetData(HeaderInfoLength + offset, VectorIndexSize); |
||||
|
|
||||
|
public virtual ReadOnlyMemory<byte> GetData(long offset, int length) |
||||
|
{ |
||||
|
var buffer = ArrayPool<byte>.Shared.Rent(length); |
||||
|
try |
||||
|
{ |
||||
|
int totalBytesRead = 0; |
||||
|
_xdbStream.Seek(offset, SeekOrigin.Begin); |
||||
|
|
||||
|
int bytesRead; |
||||
|
while (totalBytesRead < length) |
||||
|
{ |
||||
|
bytesRead = _xdbStream.Read(buffer, totalBytesRead, length - totalBytesRead); |
||||
|
if (bytesRead == 0) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
totalBytesRead += bytesRead; |
||||
|
IoCount++; |
||||
|
} |
||||
|
|
||||
|
var ret = new byte[totalBytesRead]; |
||||
|
if (totalBytesRead > 0) |
||||
|
{ |
||||
|
Array.Copy(buffer, 0, ret, 0, totalBytesRead); |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
ArrayPool<byte>.Shared.Return(buffer); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 释放文件句柄
|
||||
|
/// </summary>
|
||||
|
/// <param name="disposing"></param>
|
||||
|
protected virtual void Dispose(bool disposing) |
||||
|
{ |
||||
|
if (disposing) |
||||
|
{ |
||||
|
_xdbStream.Close(); |
||||
|
_xdbStream.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <inheritdoc/>
|
||||
|
/// </summary>
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
Dispose(true); |
||||
|
GC.SuppressFinalize(this); |
||||
|
} |
||||
|
} |
||||
@ -1,28 +1,26 @@ |
|||||
// Copyright 2023 The Ip2Region Authors. All rights reserved.
|
// Copyright 2025 The Ip2Region Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache2.0-style
|
// Use of this source code is governed by a Apache2.0-style
|
||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||
// @Author Alan <lzh.shap@gmail.com>
|
// @Author Alan <lzh.shap@gmail.com>
|
||||
// @Date 2023/07/25
|
// @Date 2023/07/25
|
||||
|
// Updated by Argo Zhang <argo@live.ca> at 2025/11/21
|
||||
|
|
||||
using IP2Region.Net.Internal.Abstractions; |
|
||||
using System; |
using System; |
||||
using System.IO; |
using System.IO; |
||||
|
|
||||
namespace IP2Region.Net.Internal; |
namespace IP2Region.Net.Internal; |
||||
|
|
||||
internal class VectorIndexCacheStrategy : AbstractCacheStrategy |
class VectorIndexCacheStrategy : StreamCacheStrategy |
||||
{ |
{ |
||||
private readonly ReadOnlyMemory<byte> _vectorIndex; |
private const int VectorIndexRows = 256; |
||||
|
private const int VectorIndexCols = 256; |
||||
|
|
||||
public VectorIndexCacheStrategy(Stream xdbStream) : base(xdbStream) |
private readonly ReadOnlyMemory<byte> _vectorCache; |
||||
{ |
|
||||
var vectorLength = VectorIndexRows * VectorIndexCols * VectorIndexSize; |
|
||||
_vectorIndex = base.GetData(HeaderInfoLength, vectorLength); |
|
||||
} |
|
||||
|
|
||||
internal override ReadOnlyMemory<byte> GetVectorIndex(uint ip) |
public VectorIndexCacheStrategy(Stream _xdbStream) : base(_xdbStream) |
||||
{ |
{ |
||||
var idx = GetVectorIndexStartPos(ip); |
_vectorCache = GetData(HeaderInfoLength, VectorIndexRows * VectorIndexCols * VectorIndexSize); |
||||
return _vectorIndex.Slice(idx, VectorIndexSize); |
|
||||
} |
} |
||||
|
|
||||
|
public override ReadOnlyMemory<byte> GetVectorIndex(int offset) => _vectorCache.Slice(offset, VectorIndexSize); |
||||
} |
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using LINGYUN.Abp.IP.Location; |
||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP2Region; |
||||
|
public class AbpIP2RegionLocationResolveOptions |
||||
|
{ |
||||
|
public Func<IPLocation, bool> UseCountry { get; set; } |
||||
|
public Func<IPLocation, bool> UseProvince { get; set; } |
||||
|
public AbpIP2RegionLocationResolveOptions() |
||||
|
{ |
||||
|
UseCountry = _ => true; |
||||
|
UseProvince = _ => true; |
||||
|
} |
||||
|
} |
||||
@ -1,80 +1,155 @@ |
|||||
using IP2Region.Net.Abstractions; |
// Copyright 2025 The Ip2Region Authors. All rights reserved.
|
||||
|
// Use of this source code is governed by a Apache2.0-style
|
||||
|
// license that can be found in the LICENSE file.
|
||||
|
// @Author Alan <lzh.shap@gmail.com>
|
||||
|
// @Date 2023/07/25
|
||||
|
// Updated by Argo Zhang <argo@live.ca> at 2025/11/21
|
||||
|
|
||||
|
using IP2Region.Net.Abstractions; |
||||
using IP2Region.Net.Internal; |
using IP2Region.Net.Internal; |
||||
using IP2Region.Net.Internal.Abstractions; |
|
||||
using IP2Region.Net.XDB; |
using IP2Region.Net.XDB; |
||||
|
using System; |
||||
|
using System.Buffers.Binary; |
||||
|
using System.Diagnostics.CodeAnalysis; |
||||
using System.IO; |
using System.IO; |
||||
using System.Net; |
using System.Net; |
||||
using System.Runtime.InteropServices; |
|
||||
using System.Text; |
using System.Text; |
||||
|
|
||||
namespace LINGYUN.Abp.IP2Region; |
namespace LINGYUN.Abp.IP2Region; |
||||
public class AbpSearcher : ISearcher |
public class AbpSearcher(CachePolicy cachePolicy, Stream xdbStream) : ISearcher |
||||
{ |
{ |
||||
const int SegmentIndexSize = 14; |
private readonly ICacheStrategy _cacheStrategy = CacheStrategyFactory.CreateCacheStrategy(cachePolicy, xdbStream); |
||||
|
|
||||
private readonly AbstractCacheStrategy _cacheStrategy; |
/// <summary>
|
||||
|
/// <inheritdoc/>
|
||||
|
/// </summary>
|
||||
public int IoCount => _cacheStrategy.IoCount; |
public int IoCount => _cacheStrategy.IoCount; |
||||
|
|
||||
public AbpSearcher(CachePolicy cachePolicy, Stream xdbStream) |
/// <summary>
|
||||
{ |
/// <inheritdoc/>
|
||||
var factory = new CacheStrategyFactory(xdbStream); |
/// </summary>
|
||||
_cacheStrategy = factory.CreateCacheStrategy(cachePolicy); |
|
||||
} |
|
||||
|
|
||||
public string? Search(string ipStr) |
public string? Search(string ipStr) |
||||
{ |
{ |
||||
var ip = Util.IpAddressToUInt32(ipStr); |
var ipAddress = IPAddress.Parse(ipStr); |
||||
return Search(ip); |
return SearchCore(ipAddress.GetAddressBytes()); |
||||
} |
} |
||||
|
|
||||
public string? Search(IPAddress ipAddress) |
/// <summary>
|
||||
|
/// <inheritdoc/>
|
||||
|
/// </summary>
|
||||
|
public string? Search(IPAddress ipAddress) => SearchCore(ipAddress.GetAddressBytes()); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// <inheritdoc/>
|
||||
|
/// </summary>
|
||||
|
[Obsolete("已弃用,请改用其他方法;Deprecated; please use Search(string) or Search(IPAddress) method.")] |
||||
|
[ExcludeFromCodeCoverage] |
||||
|
public string? Search(uint ipAddress) |
||||
{ |
{ |
||||
var ip = Util.IpAddressToUInt32(ipAddress); |
var bytes = BitConverter.GetBytes(ipAddress); |
||||
return Search(ip); |
Array.Reverse(bytes); |
||||
|
return SearchCore(bytes); |
||||
} |
} |
||||
|
|
||||
public string? Search(uint ip) |
string? SearchCore(byte[] ipBytes) |
||||
{ |
{ |
||||
var index = _cacheStrategy.GetVectorIndex(ip); |
// 重置 IO 计数器
|
||||
uint sPtr = MemoryMarshal.Read<uint>(index.Span); |
_cacheStrategy.ResetIoCount(); |
||||
uint ePtr = MemoryMarshal.Read<uint>(index.Span.Slice(4)); |
|
||||
|
// 每个 vector 索引项的字节数
|
||||
|
var vectorIndexSize = 8; |
||||
|
|
||||
|
// vector 索引的列数
|
||||
|
var vectorIndexCols = 256; |
||||
|
|
||||
|
// 计算得到 vector 索引项的开始地址。
|
||||
|
var il0 = ipBytes[0]; |
||||
|
var il1 = ipBytes[1]; |
||||
|
var idx = il0 * vectorIndexCols * vectorIndexSize + il1 * vectorIndexSize; |
||||
|
|
||||
|
var vector = _cacheStrategy.GetVectorIndex(idx); |
||||
|
var sPtr = BinaryPrimitives.ReadUInt32LittleEndian(vector.Span); |
||||
|
var ePtr = BinaryPrimitives.ReadUInt32LittleEndian(vector.Span.Slice(4)); |
||||
|
|
||||
|
var length = ipBytes.Length; |
||||
|
var indexSize = length * 2 + 6; |
||||
|
var l = 0; |
||||
|
var h = (ePtr - sPtr) / indexSize; |
||||
var dataLen = 0; |
var dataLen = 0; |
||||
uint dataPtr = 0; |
long dataPtr = 0; |
||||
uint l = 0; |
|
||||
uint h = (ePtr - sPtr) / SegmentIndexSize; |
|
||||
|
|
||||
while (l <= h) |
while (l <= h) |
||||
{ |
{ |
||||
var mid = Util.GetMidIp(l, h); |
int m = (int)(l + h) >> 1; |
||||
var pos = sPtr + mid * SegmentIndexSize; |
|
||||
|
|
||||
var buffer = _cacheStrategy.GetData((int)pos, SegmentIndexSize); |
var p = sPtr + m * indexSize; |
||||
uint sip = MemoryMarshal.Read<uint>(buffer.Span); |
var buff = _cacheStrategy.GetData(p, indexSize); |
||||
uint eip = MemoryMarshal.Read<uint>(buffer.Span.Slice(4)); |
|
||||
|
|
||||
if (ip < sip) |
var s = buff.Span.Slice(0, length); |
||||
|
var e = buff.Span.Slice(length, length); |
||||
|
if (ByteCompare(ipBytes, s) < 0) |
||||
{ |
{ |
||||
h = mid - 1; |
h = m - 1; |
||||
} |
} |
||||
else if (ip > eip) |
else if (ByteCompare(ipBytes, e) > 0) |
||||
{ |
{ |
||||
l = mid + 1; |
l = m + 1; |
||||
} |
} |
||||
else |
else |
||||
{ |
{ |
||||
dataLen = MemoryMarshal.Read<ushort>(buffer.Span.Slice(8)); |
dataLen = BinaryPrimitives.ReadUInt16LittleEndian(buff.Span.Slice(length * 2, 2)); |
||||
dataPtr = MemoryMarshal.Read<uint>(buffer.Span.Slice(10)); |
dataPtr = BinaryPrimitives.ReadUInt32LittleEndian(buff.Span.Slice(length * 2 + 2, 4)); |
||||
break; |
break; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
if (dataLen == 0) |
var regionBuff = _cacheStrategy.GetData(dataPtr, dataLen); |
||||
|
return Encoding.UTF8.GetString(regionBuff.Span.ToArray()); |
||||
|
} |
||||
|
|
||||
|
static int ByteCompare(byte[] ip1, ReadOnlySpan<byte> ip2) => ip1.Length == 4 ? IPv4Compare(ip1, ip2) : IPv6Compare(ip1, ip2); |
||||
|
|
||||
|
static int IPv4Compare(byte[] ip1, ReadOnlySpan<byte> ip2) |
||||
|
{ |
||||
|
var ret = 0; |
||||
|
for (int i = 0; i < ip1.Length; i++) |
||||
|
{ |
||||
|
var ip2Index = ip1.Length - 1 - i; |
||||
|
if (ip1[i] < ip2[ip2Index]) |
||||
|
{ |
||||
|
return -1; |
||||
|
} |
||||
|
else if (ip1[i] > ip2[ip2Index]) |
||||
|
{ |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
static int IPv6Compare(byte[] ip1, ReadOnlySpan<byte> ip2) |
||||
|
{ |
||||
|
var ret = 0; |
||||
|
for (int i = 0; i < ip1.Length; i++) |
||||
{ |
{ |
||||
return default; |
if (ip1[i] < ip2[i]) |
||||
|
{ |
||||
|
return -1; |
||||
|
} |
||||
|
else if (ip1[i] > ip2[i]) |
||||
|
{ |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
return ret; |
||||
} |
} |
||||
|
|
||||
var regionBuff = _cacheStrategy.GetData((int)dataPtr, dataLen); |
/// <summary>
|
||||
return Encoding.UTF8.GetString(regionBuff.Span.ToArray()); |
/// <inheritdoc/>
|
||||
|
/// </summary>
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_cacheStrategy.Dispose(); |
||||
|
GC.SuppressFinalize(this); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
Binary file not shown.
File diff suppressed because it is too large
Loading…
Reference in new issue