⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fastdbfields.cs

📁 嵌入式数据库软件 嵌入式数据库软件 嵌入式数据库软件
💻 CS
📖 第 1 页 / 共 3 页
字号:
using System;using System.Text;using System.Collections;using System.Runtime.InteropServices;using System.Diagnostics;namespace FastDbNet{  //-------------------------------------------------------------------------  /// <summary>  /// FastDbBuffer encapsulates a binding between a memory buffer and an   /// object used to get/set data in the buffer.  /// </summary>  public class FastDbBuffer: IDisposable {    public static readonly int MIN_CAPACITY = ALIGN(30);    internal static int ALIGN(int size) { return size + size % Marshal.SizeOf(typeof(Int64)); }    public IntPtr buffer;    public string name;    public int    flags;  // cli_field_flags     public int    bound_to_statement = -1;    // Make sure the delegate stays alive while in unmanaged code    internal unsafe static CLI.CliColumnGetEx doGetColumn = new CLI.CliColumnGetEx(GetColumn);    internal unsafe static CLI.CliColumnSetEx doSetColumn = new CLI.CliColumnSetEx(SetColumn);    private bool disposed;    public unsafe FastDbBuffer(string name, CLI.FieldType var_type, CLI.FieldFlags idx_flags) {      buffer            = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(CLI.UnmanagedBuffer)));      ((CLI.UnmanagedBuffer*)buffer)->fetch_data = true;      ((CLI.UnmanagedBuffer*)buffer)->type       = (int)var_type;      ((CLI.UnmanagedBuffer*)buffer)->size       = CLI.SizeOfCliType[(int)var_type];      ((CLI.UnmanagedBuffer*)buffer)->capacity   = 0;      ((CLI.UnmanagedBuffer*)buffer)->data       = Marshal.AllocCoTaskMem(MIN_CAPACITY);      this.name  = name; //Marshal.StringToHGlobalAnsi(name);      this.flags = (int)idx_flags;      disposed = false;    }    // Use C# destructor syntax for finalization code.    // This destructor will run only if the Dispose method does not get called.    // It gives the base class the opportunity to finalize.    ~FastDbBuffer() {      // Do not re-create Dispose clean-up code here.      // Calling Dispose(false) is optimal in terms of      // readability and maintainability.      Dispose(false);    }    internal unsafe static IntPtr GetColumn(int var_type, IntPtr var_ptr, ref int len,       string column_name, int statement,       void* user_data)     {      CLI.UnmanagedBuffer* buffer = (CLI.UnmanagedBuffer*)user_data;      if (CLI.IsArrayType((CLI.FieldType)var_type))         len = buffer->size / CLI.SizeOfCliType[var_type - (int)CLI.FieldType.cli_array_of_oid];      else if (var_type == (int)CLI.FieldType.cli_asciiz || var_type == (int)CLI.FieldType.cli_pasciiz)         len = buffer->size-1;      else         len = buffer->size;      return buffer->data;    }    internal unsafe static IntPtr SetColumn(int var_type,       IntPtr var_ptr, int len, string column_name,      int statement, IntPtr data_ptr,       void* user_data)     {      CLI.UnmanagedBuffer* buffer = (CLI.UnmanagedBuffer*)user_data;      if (var_type == (int)CLI.FieldType.cli_asciiz || var_type == (int)CLI.FieldType.cli_pasciiz) {        SetBufferTypeAndSize(buffer, (CLI.FieldType)var_type, len, true);        return buffer->data;      }      else if (CLI.IsArrayType((CLI.FieldType)var_type)) {        if (buffer->fetch_data) {          SetBufferTypeAndSize(buffer, (CLI.FieldType)var_type,             len*CLI.SizeOfCliType[(int)var_type - (int)CLI.FieldType.cli_array_of_oid], true);          return buffer->data;        }        else          return IntPtr.Zero;        // FastDB won't fetch a field if we return nil      }      else // sanity check        throw new CliError("Unsupported type: "+Enum.GetName(typeof(CLI.FieldType), buffer->type));    }    protected unsafe static void SetBufferTypeAndSize(CLI.UnmanagedBuffer* buf,       CLI.FieldType NewType, int NewSize, bool TypeCheck)     {      int n;      if (!TypeCheck || CLI.IsArrayType(NewType))        n = NewSize;      else if (NewType == CLI.FieldType.cli_asciiz || NewType == CLI.FieldType.cli_pasciiz)        n = NewSize+1;      else        n = CLI.SizeOfCliType[(int)NewType];      if (buf->capacity != 0) {        if (n > buf->capacity) {          buf->data = Marshal.ReAllocCoTaskMem(buf->data, ALIGN(n));          buf->capacity = n;        }      } else {        if (buf->size != n && n > MIN_CAPACITY)          buf->data = Marshal.ReAllocCoTaskMem(buf->data, (n > MIN_CAPACITY) ? ALIGN(n) : MIN_CAPACITY);      }      buf->size = n;      if (buf->type != (int)NewType)        buf->type = (int)NewType;    }    /// <summary>    /// Use Assign() method to copy the content of on FastDbBuffer to another.    /// </summary>    /// <param name="var">is the source FastDbBuffer to be copied from.</param>    public unsafe virtual void Assign(FastDbBuffer var) {      this.name = var.Name;      this.Capacity = var.Capacity;      this.bound_to_statement = var.StatementID;      this.FetchData = var.FetchData;      CopyBufferData(var.Type, var.Size, ((CLI.UnmanagedBuffer*)var.buffer.ToPointer())->data);    }    internal unsafe void CopyBufferData(CLI.FieldType type, int size, IntPtr data)     {      SetBufferTypeAndSize((CLI.UnmanagedBuffer*)buffer.ToPointer(), type, size, true);      Int64* pend  = (Int64*)((byte*)data.ToPointer() + ALIGN(size));      Int64* pfrom = (Int64*)data.ToPointer();      Int64* pto   = (Int64*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer();      while(pfrom < pend)        *pto++ = *pfrom++;      // for(int i=0; i < size; i++)      //   *pto++ = *pfrom++;      // Note: buffers are always aligned to 8 bytes, so we can simply copy by       // iterating over 8 byte integers.      //if (type == CLI.FieldType.cli_asciiz || type == CLI.FieldType.cli_pasciiz)      //  *pto = (byte)'\0';    }    /// <summary>    /// Bind() abstract method binds a FastDbBuffer to a FastDb statement obtained by calling    /// cli_statement() API function.  The descendants are requiered to override this method.    /// </summary>    /// <param name="StatementID">integer value representing a FastDB statement</param>    internal unsafe virtual void Bind(int StatementID) {} // bound_to_statement = StatementID; }    /// <summary>    /// Unbind() clears the buffer binding to a statement.    /// </summary>    internal virtual unsafe void UnBind() { bound_to_statement = -1; }  // Note: since 0 is a valid statement we initialize this to a negative value    /// <summary>    /// Returns the name of this field/parameter.    /// </summary>    public unsafe string         Name         { get { return name; } }    /// <summary>    /// Capacity controls internally allocated memory for the buffer.      /// By default minimum size of the buffer is 30 bytes, however, if you are    /// reading/writing large arrays or string values, you may consider setting     /// the Capacity field to a larger value in order to minimize memory reallocations.    /// </summary>    public unsafe int            Capacity     { get { return ((CLI.UnmanagedBuffer*)buffer.ToPointer())->capacity; } set { ((CLI.UnmanagedBuffer*)buffer.ToPointer())->capacity = value; } }    /// <summary>    /// Determines the size in bytes of current value in the buffer.    /// </summary>    public unsafe int            Size         { get { return ((CLI.UnmanagedBuffer*)buffer.ToPointer())->size; } }    /// <summary>    /// Returns the type of the value in the buffer.    /// </summary>    public unsafe CLI.FieldType  Type         { get { return (CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type; } }       /// <summary>    /// Contains index flags indicating the types of indexes (hash/T-tree) on this field.    /// </summary>    public unsafe CLI.FieldFlags Flags        { get { return (CLI.FieldFlags)flags; } }      /// <summary>    /// Internal statement's ID that this buffer is bound to.     /// </summary>    public unsafe int            StatementID  { get { return bound_to_statement; } }    /// <summary>    /// For array fields FetchData controls whether to copy the field's content    /// to the buffer when a cursor is moved to another record.  By setting this     /// value to false, it may increase performance on queries that don't need to use    /// the content of the array field.     /// </summary>    public unsafe bool           FetchData    { get { return ((CLI.UnmanagedBuffer*)buffer.ToPointer())->fetch_data; } set { ((CLI.UnmanagedBuffer*)buffer.ToPointer())->fetch_data = value; } }          public bool   asBoolean {get {return (bool)getValue(typeof(bool));}     set {setValue(value);}}      public Int16  asInt16   {get {return (Int16)getValue(typeof(Int16));}   set {setValue(value);}}      public int    asInteger {get {return (int)getValue(typeof(int));}       set {setValue(value);}}      public uint   asOID     {get {return (uint)getValue(typeof(uint));}     set {setValue(value);}}      public Int64  asInt64   {get {return (Int64)getValue(typeof(Int64));}   set {setValue(value);}}      public double asDouble  {get {return (double)getValue(typeof(double));} set {setValue(value);}}    public string asString  {get {return (string)getValue(typeof(string));} set {setValue(value);}}    protected unsafe virtual Object getValue(Type t) {      switch((CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type) {        case CLI.FieldType.cli_bool:         case CLI.FieldType.cli_int1:    return Convert.ChangeType(*(sbyte*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_int2:    return Convert.ChangeType(*(short*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_oid:     return Convert.ChangeType(*(uint*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_int4:    return Convert.ChangeType(*(int*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_int8:    return Convert.ChangeType(*(Int64*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_real4:   return Convert.ChangeType(*(Single*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_datetime:        case CLI.FieldType.cli_real8:   return Convert.ChangeType(*(double*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer(), t);        case CLI.FieldType.cli_asciiz:        case CLI.FieldType.cli_pasciiz: return Convert.ChangeType(Marshal.PtrToStringAnsi(((CLI.UnmanagedBuffer*)buffer.ToPointer())->data), t);        default:                        throw new CliError("getValue: Unsupported type!"+Enum.GetName(typeof(CLI.FieldType), ((CLI.UnmanagedBuffer*)buffer.ToPointer())->type));      }    }    protected unsafe void setValue(Object Value) {      switch((CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type) {        case CLI.FieldType.cli_oid:          *(uint*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToUInt32(Value);          break;        case CLI.FieldType.cli_int4:          *(int*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToInt32(Value);          break;        case CLI.FieldType.cli_bool:        case CLI.FieldType.cli_int1:          *(sbyte*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToSByte(Value);          break;        case CLI.FieldType.cli_int2:          *(Int16*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToInt16(Value);          break;        case CLI.FieldType.cli_int8:          *(Int64*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToInt64(Value);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -