initialize
diff --git a/.project b/.project
new file mode 100644
index 0000000..fb9ffc1
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<projectDescription>

+	<name>tcutils</name>

+	<comment></comment>

+	<projects>

+	</projects>

+	<buildSpec>

+		<buildCommand>

+			<name>org.python.pydev.PyDevBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+	</buildSpec>

+	<natures>

+		<nature>org.python.pydev.pythonNature</nature>

+	</natures>

+</projectDescription>

diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..a270ffe
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>

+<?eclipse-pydev version="1.0"?>

+

+<pydev_project>

+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>

+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>

+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">

+<path>/tcutils/src</path>

+</pydev_pathproperty>

+</pydev_project>

diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..9991c1a
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,4 @@
+#Mon Sep 26 12:39:46 CST 2011

+eclipse.preferences.version=1

+encoding//src/pybccclt.py=gbk

+encoding/setup.py=utf-8

diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..a49c273
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from distutils.core import setup
+import os
+
+def find_all_dist_module():
+    base_dir = 'src'
+    all_files = os.listdir(base_dir)
+    modules=[]
+    for f in all_files:
+        fname = os.path.join(base_dir,f)
+        if os.path.isfile(fname):
+            ext = f.split('.')[-1]
+            #print f.split('.')
+            if ext == 'py':
+                modules.append(f)
+                
+    return modules
+    
+#print find_all_dist_module()
+
+setup(
+    name = 'tcutils',
+    version = "0.2",
+    description = "Cheng Tang 's python libraries",
+    author = 'Cheng Tang',
+    author_email = 'cashtang@gmail.com',
+    platforms=['All'],
+    packages=['tcutils']
+    )
\ No newline at end of file
diff --git a/src/amassprotocol.py b/src/amassprotocol.py
new file mode 100644
index 0000000..5f56fee
--- /dev/null
+++ b/src/amassprotocol.py
@@ -0,0 +1,389 @@
+#!/usr/bin/python

+# -*- coding: gbk -*- 

+

+import sys,codecs,struct

+

+IFT_NULL=0

+IFT_ULONG=1

+IFT_BYTE=2

+IFT_USHORT=3

+IFT_DATETIME=4

+IFT_BUFFER=5

+IFT_STRING=6

+IFT_LONG=7

+

+# (0,0,1,IFT_BYTE,0,"msgtype","ÏûÏ¢Âë"),

+

+FLD_NO_IDX=0

+FLD_LENGTH_IDX=2

+FLD_TYPE_IDX=3

+FLD_FLAG_IDX=4

+FLD_NAME_IDX=5

+FLD_DESC_IDX=6

+

+HDFieldsDef = [

+(1,0,0,IFT_NULL,0,"extend","À©Õ¹Óò·ñ"),

+(2,0,4,IFT_ULONG,0,"terminalsn"," ÖÕ¶ËÐòÁкÅ"),

+(3,0,2,IFT_USHORT,0,"address","CANµØÖ·"),

+(4,0,4,IFT_ULONG,0,"cardnumber","¿¨ºÅ"),

+(5,0,1,IFT_BYTE,0,"indexofew"," Ç®°üË÷Òý"),

+(6,0,2,IFT_USHORT,0,"traceofew"," Ç®°üÁ÷Ë®ºÅ"),

+(7,0,4,IFT_LONG,0,"amount"," ½»Ò×½ð¶î"),

+(8,0,4,IFT_LONG,0,"additionalamount1","¸½¼Ó½ð¶î"),

+(9,0,4,IFT_ULONG,0,"traceofpos","POSÁ÷Ë®ºÅ"),

+(10,0,4,IFT_ULONG,0,"orgtranstrace","Ô­½»Ò×Á÷Ë®ºÅ"),

+(11,0,7,IFT_DATETIME,0,"datetime","½»Ò×ÈÕÆÚºÍʱ¼ä"),

+(12,0,1,IFT_BYTE,0,"responsecode","ÏìÓ¦Âë"),

+(13,0,2,IFT_USHORT,0,"terminalid","Öն˺Å"),

+(14,0,2,IFT_USHORT,0,"terminaltype","ÖÕ¶ËÀàÐÍ"),

+(15,0,2,IFT_USHORT,0,"merchantid","ÉÌ»§(Íøµã)ºÅ"),

+(16,0,4,IFT_ULONG,0,"operatorid","²Ù×÷Ô±ºÅ"),

+(17,0,8,IFT_BUFFER,0,"pin","¸öÈËʶ±ðÂëPIN"),

+(18,0,4,IFT_ULONG,0,"veroflist","ºÚÃûµ¥°æ±¾"),

+(19,0,4,IFT_ULONG,0,"managefee","½»Ò×Åú´ÎºÅ(Ôݲ»ÓÃ)"),

+(20,0,360,IFT_BUFFER,2,"additionaldata1","¸½¼ÓÐÅÏ¢1"),

+(21,0,528,IFT_BUFFER,2,"additionaldata2","¸½¼ÓÐÅÏ¢2"),

+(22,0,528,IFT_STRING,2,"additionaldata3","¸½¼ÓÐÅÏ¢3"),

+(23,0,528,IFT_STRING,2,"additionaldata4","¸½¼ÓÐÅÏ¢4"),

+(24,0,2,IFT_USHORT,0,"mac","ÏûÏ¢ÈÏÖ¤Âë")

+]

+

+class HDPack:

+    ''' »ã¶à 8583 ЭÒé°ü '''

+    def __init__(self):

+        self.msg_type = 0

+        self.value={}

+        self.field_idx={}

+        self.field_name={}

+        self.msgtype = 0

+        

+        self.load_config()

+        

+    def __eq__(self,other):

+        if not isinstance(other,HDPack):

+            return False

+        return self.compare(other)

+    def __ne__(self,other):

+        if not isinstance(other,HDPack):

+            return True

+        return not self.compare(other)

+        

+    def compare(self,other):

+        if self.msgtype != other.msgtype:

+            return False

+        for k,v in self.value.items():

+            if not other.value.has_key(k):

+                print "field [%s] not equal" % k

+                return False

+            if v <> other.get(k):

+                print "field [%s] value not equal [%s,%s]" % (k,v,other.get(k))

+                return False

+        return True

+        

+    def load_config(self):

+        for field in HDFieldsDef:

+            index,t,len,type,flag,name,desc = field

+            self.field_idx[index] = field

+            self.field_name[name] = field

+        #print self.field_name

+      

+    def get_field_def(self,index):

+        field_def = None

+        if isinstance(index,int):

+            if not self.field_idx.has_key(index):

+                raise ValueError("field index %d not exists" % index)

+            field_def = self.field_idx[index]

+        elif isinstance(index,str):

+            if not self.field_name.has_key(index):

+                raise ValueError("field index %s not exists" % index)

+            field_def = self.field_name[index]

+        else:

+            raise ValueError("field index type not support")

+            

+        return field_def

+        

+    def set(self,index,value):

+        field_def = self.get_field_def(index)

+        t = field_def[FLD_TYPE_IDX]

+        n = field_def[FLD_NAME_IDX]

+        l = field_def[FLD_LENGTH_IDX]

+        f = field_def[FLD_FLAG_IDX]

+        if t == IFT_USHORT or t == IFT_ULONG or t == IFT_NULL or t == IFT_BYTE or t == IFT_LONG:

+            if isinstance(value,int):

+                b = value

+            elif isinstance(value,str):

+                if value.startswith('0x'):

+                    b = int(value,16)

+                else:

+                    b = int(value)

+            else:

+                raise ValueError("field %s value type not integer" % n)

+        elif t == IFT_DATETIME:

+            if len(value) != 12 and len(value) != 14:

+                raise ValueError("field %s length must be 12 or 14" % n)

+            if len(value) == 14:

+                value = value[2:]

+            b = value + "00"

+        else:

+            if not isinstance(value,str):

+                raise ValueError("field %s value type not string" % n)

+                

+            if t == IFT_DATETIME:

+                l *= 2

+            elif value.startswith('0x'):

+                l *= 2

+                l += 2

+                

+            if f <> 2 and len(value) <> l:

+                raise ValueError("field %s value data length not equal %d<>%d " % (n,len(value),l))

+            elif len(value) > l:

+                raise ValueError("field %s value data length exceed %d " % (n,l))

+                

+            b = value

+                

+        self.value[n] = b

+        

+    def get(self,index):

+        field_def = self.get_field_def(index)

+        t = field_def[3]

+        n = field_def[5]

+        

+        if self.value.has_key(n):

+            return self.value[n]

+        raise ValueError("Field %s not specified" % n)

+        

+        

+    def encode_bitmap(self,bitmap):

+        buffer = ''

+        offset = 0

+        #print "bit len[%d]" % len(bitmap)

+        while offset < len(bitmap):

+            bit = 0

+            for i in range(8):

+                t = ord(bitmap[offset+i]) - 0x30

+                if t == 0: continue

+                bit |= (1 << (7 - i % 8))

+            buffer += chr(bit&0xFF)

+            offset += 8

+        return buffer

+            

+    def pack(self,workkey=None):

+        buffer = ''

+        bitmap = ['0' for i in range(24)]

+        for field in HDFieldsDef:

+            index,x,len,t,flag,name,desc = field

+            if not self.value.has_key(name):

+                continue

+            

+            if t == IFT_USHORT or t == IFT_ULONG or t == IFT_NULL or t == IFT_BYTE or t == IFT_LONG:

+                buffer += self.int_2_buffer(self.value[name],t,len)

+            else:

+                buffer += self.string_2_buffer(self.value[name],t,len,flag)

+            bitmap[index-1] = '1'

+        #print bitmap

+        

+        bitmap_buffer = self.encode_bitmap(bitmap)

+        full_data = chr(self.msgtype&0xFF) + bitmap_buffer + buffer

+        header = self.data_header(full_data)

+        #print "h[%s]d[%s]" % (codecs.encode(header,'hex'),codecs.encode(full_data,'hex'))

+        return header + full_data

+    

+    def data_header(self,buffer):

+        if len(buffer) > 0xFFFF:

+            raise ValueError("Buffer max length exceed %d", len(buffer))

+        header = struct.pack('<H',len(buffer))

+        return header

+        

+    def int_2_buffer(self,value,type,length):

+        buffer = ''

+        if type == IFT_BYTE:

+            buffer = chr(value%0x100)

+        elif type == IFT_NULL:

+            return buffer

+        elif type == IFT_USHORT:

+            v = value % 0x10000

+            buffer = struct.pack('<H',v)

+        elif type == IFT_ULONG:

+            buffer = struct.pack('<I',value)

+        elif type == IFT_LONG:

+            buffer = struct.pack('<i',value)

+        else:

+            raise ValueError('Input Error')

+            

+        return buffer

+    

+    def encode_bcd(self,value):

+        if len(value) % 2 != 0:

+            raise ValueError("value length must div 2")

+        i = 0

+        #print "value [%s]" % value

+        buffer = ''

+        while i < len(value):

+            t1 = (ord(value[i]) - 0x30)& 0xFF

+            t2 = (ord(value[i+1]) - 0x30) & 0xFF

+            #print "t1[%d]t2[%d]" % (t1,t2)

+            t = ((t1<<4) | t2) & 0xFF

+            #print "t1[%d]t2[%d]t[%d]" % (t1,t2,t)

+            buffer += chr(t)

+            i += 2

+        #print "bcd value[%s]" % codecs.encode(buffer,'hex')

+        return buffer

+        

+    def decode_bcd(self,value):

+        buffer = ''

+        #print "bcd [%s]" % codecs.encode(value,'hex')

+        for c in value:

+            t = ord(c) & 0xFF

+            t1 = (t >> 4) & 0x0F

+            t2 = t & 0x0F

+            #print "t[%02x]t1[%d]t2[%d]" % (t,t1,t2)

+            buffer += chr(t1 + 0x30) + chr(t2 + 0x30)

+        #print "bcd value[%s]" % buffer

+        return buffer

+        

+    def string_2_buffer(self,value,type,length,flag):

+        buffer = ''

+        if type == IFT_STRING or type == IFT_BUFFER:

+            if value.startswith('0x'):

+                buffer = codecs.decode(value[2:],'hex')

+            else:

+                buffer = value

+        elif type == IFT_DATETIME:

+            buffer = ''

+            i = 0

+            while i < len(value):

+                t = int(value[i:i+2])

+                buffer += chr(t & 0xFF)

+                i += 2

+        else:

+            raise ValueError('Input Error')

+            

+        if flag == 2:

+            header = struct.pack('<H',len(buffer) % 0x10000)

+            return header + buffer

+        else:

+            #if type == IFT_BUFFER:

+            #    if len(buffer) % 2 <> 0 or len(buffer)/2 <> length:

+            #        raise ValueError("Value length not matched [%s]" % value)

+            #    buffer = codecs.decode(buffer,'hex')

+            if len(buffer) != length:

+                padlen = length - len(buffer)

+                if padlen < 0:

+                    raise ValueError("Value length not matched [%s]" % value)

+                

+                pad = chr(0) * padlen

+                buffer = pad + buffer

+            return buffer

+            

+    

+    def decode_bitmap(self,bitmap):

+        if len(bitmap) != 3:

+            raise ValueError("bitmap length error")

+        #print "bitmap[%s]" % codecs.encode(bitmap,'hex')

+        buffer=[]

+        for t in bitmap:

+            v = ord(t) & 0xFF

+            for i in range(8):

+                x = (v & (1 << (7-i)))

+                if x > 0:

+                    buffer.append('1')

+                else:

+                    buffer.append('0')

+        return buffer

+            

+    def unpack(self,data):

+        self.value = {}

+        #print "data[%s]" % codecs.encode(data,'hex')

+        data_len = struct.unpack('<H',data[:2])[0]

+        if len(data) != data_len + 2:

+            print "input[%d] extually[%d]" % (data_len,len(data))

+            return False

+        

+        offset = 2

+        self.msgtype = ord(data[offset]) & 0xFF

+        offset += 1

+        bitmap = self.decode_bitmap(data[offset:offset+3])

+        offset += 3

+        #print bitmap

+        for i in range(len(bitmap)):

+            if bitmap[i] == '0': continue

+            findex = i + 1

+            field = self.get_field_def(findex)

+            ftype = field[FLD_TYPE_IDX]

+            flen = field[FLD_LENGTH_IDX]

+            fflag = field[FLD_FLAG_IDX]

+            fname = field[FLD_NAME_IDX]

+            #print "parse field[%s] [%d]off[%d][%s]" % (fname,fflag,offset,codecs.encode(data[offset:offset+2],'hex'))

+            if fflag == 2: # ±ä³¤Êý¾Ý

+                #print "len [%s]" % codecs.encode(data[offset:offset+2],'hex')

+                endpos = self.buffer_2_int(data[offset:offset+2],IFT_USHORT)

+                offset += 2

+                endpos += offset 

+            else:

+                endpos = offset + flen

+                

+            if ftype == IFT_USHORT or ftype == IFT_ULONG or ftype == IFT_NULL or ftype == IFT_BYTE or ftype == IFT_LONG:

+                value = self.buffer_2_int(data[offset:endpos],ftype)

+            else:

+                #temp = self.buffer_2_string(data[offset:endpos],ftype)

+                #if fflag != 2 and ftype == IFT_STRING:

+                #    for i in temp:

+                #        print "char [%02x]" % ord(i)

+                #        if ord(i) > 0:

+                #            value += i

+                #else:

+                #    value = temp

+                value = self.buffer_2_string(data[offset:endpos],ftype)

+                if fflag <> 2 and ftype == IFT_BUFFER:

+                    value = '0x' + codecs.encode(value,'hex')

+            

+            self.set(findex,value)

+            #print "parse field[%s] OK =====" % fname

+            offset = endpos

+        #print self.value

+        return True

+    

+    def buffer_2_int(self,data,type):

+        if type == IFT_BYTE:

+            return ord(data)

+        elif type == IFT_USHORT:

+            return struct.unpack('<H',data)[0]

+        elif type == IFT_ULONG:

+            return struct.unpack('<I',data)[0]

+        elif type == IFT_LONG:

+            return struct.unpack('<i',data)[0]

+        elif type == IFT_NULL:

+            return None

+        else:

+            raise ValueError("input data type error")

+            

+    def buffer_2_string(self,data,type):

+        if type == IFT_STRING:

+            return data

+        elif type == IFT_BUFFER:

+            return data

+        elif type == IFT_DATETIME:

+            return self.decode_bcd(data)

+        else:

+            raise ValueError("input data type error")

+            

+            

+    def get_2byte_int(self,data):

+        return struct.unpack(">H",data)[0]

+        

+    def get_3byte_int(self,data):

+        temp = data + chr(0)

+        return struct.unpack("<I",temp)[0]

+        

+    def get_4byte_int(self,data):

+        return struct.unpack("<I",data)[0]

+        

+    def set_2byte_int(self,data):

+        return struct.pack('<H',data)

+    

+    def set_3byte_int(self,data):

+        temp = struct.pack('<H',data)

+        return temp[:-1]

+            

+    def set_4byte_int(self,data):

+        return struct.pack('<I',data)
\ No newline at end of file
diff --git a/src/pbocfunc.py b/src/pbocfunc.py
new file mode 100644
index 0000000..f21bf37
--- /dev/null
+++ b/src/pbocfunc.py
@@ -0,0 +1,131 @@
+#! /usr/bin/env python

+# vim: tabstop=4

+

+import pyDes, codecs

+

+

+

+def desencrypt(key, data, m=pyDes.ECB):

+    k = pyDes.des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)

+    return k.encrypt(data) 

+    

+def desdecrypt(key, data, m=pyDes.ECB):

+    k = pyDes.des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)

+    return k.decrypt(data) 

+

+def tripledesencrypt(key, data, m=pyDes.ECB):

+    k = pyDes.triple_des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)

+    return k.encrypt(data)

+    

+def tripledesdecrypt(key, data, m=pyDes.ECB):

+    k = pyDes.triple_des(key, pad=None, padmode=pyDes.PAD_NORMAL, mode=m)

+    return k.decrypt(data)

+

+

+def desencrypthex(key, data):

+    k = pyDes.des(codecs.decode(key, 'hex'), pad=None, padmode=pyDes.PAD_NORMAL)

+    e = k.encrypt(codecs.decode(data, 'hex')) 

+    return codecs.encode(e, 'hex')

+

+def tripledesencrypthex(key, data):

+    k = pyDes.triple_des(codecs.decode(key, 'hex'), pad=None, padmode=pyDes.PAD_NORMAL)

+    e1 = k.encrypt(codecs.decode(data, 'hex'))

+    return codecs.encode(e1, 'hex')

+

+def DataNot(data):

+    r = ''

+    for a in data:

+        r = r + chr((~ord(a)) & 0xFF)

+    return r

+        

+def PadCardPhyNo(phyno):

+    r = ''

+    if len(phyno) < 8:

+        pad = "\x80\x00\x00\x00\x00\x00\x00\x00"

+        l = 8 - len(phyno)

+        r = phyno + pad[:l]

+    elif len(phyno) == 8:

+        r = phyno

+    else:

+        r = phyno[:8]

+    return r

+    

+def PadCardPhyNoHex(phyno):

+    return codecs.encode(PadCardPhyNo(codecs.decode(phyno, 'hex')), 'hex')

+    

+def PbocDeliveryKey(factor, key):

+    cipherdatanot = ''

+    cipherdata = PadCardPhyNo(factor)

+    

+    print "factor is [%s]" % codecs.encode(cipherdata, 'hex')

+

+    if len(key) == 8: # singledes delivery

+        k1 = desencrypt(key, cipherdata)

+        return k1

+    elif len(key) == 16:

+        cipherdatanot = DataNot(cipherdata)

+        

+        k1 = tripledesencrypt(key, cipherdata)

+        k2 = tripledesencrypt(key, cipherdatanot)

+        

+        return k1 + k2

+    else:

+        raise ValueError('key length error')

+    

+def PbocDeliveryKeyHex(factor, key):

+    f = codecs.decode(factor, 'hex')

+    k = codecs.decode(key, 'hex')

+    k1 = PbocDeliveryKey(f, k)

+    return codecs.encode(k1, 'hex')

+   

+

+def CalcMac3DES(data, initdata, key):

+    datalen = len(data)

+    k = pyDes.des(key[:8], pad=None, padmode=pyDes.PAD_NORMAL)

+

+    for i in range(datalen / 8):

+        m = ""

+        for j in range(len(initdata)):

+            m = m + chr(ord(initdata[j]) ^ ord(data[i * 8 + j]))

+

+        initdata = m

+        x = k.encrypt(initdata)

+        initdata = x

+

+

+    k1 = pyDes.des(key[8:], pad=None, padmode=pyDes.PAD_NORMAL)

+    n = k1.decrypt(initdata)

+    initdata = k.encrypt(n)

+    return initdata

+    

+def CalcMac3DESHex(data, initdata, key):

+    d = codecs.decode(data, 'hex')

+    id = codecs.decode(initdata, 'hex')

+    k = codecs.decode(key, 'hex')

+    k1 = CalcMac3DES(d, id, k)

+    return codecs.encode(k1, 'hex')

+    

+def CalcMacDES(data, initdata, key):

+    datalen = len(data)

+    k = pyDes.des(key, pad=None, padmode=pyDes.PAD_NORMAL)

+    

+    for i in range(datalen / 8):

+        m = ""

+        for j in range(len(initdata)):

+            m = m + chr(ord(initdata[j]) ^ ord(data[i * 8 + j]))

+

+        initdata = m

+        x = k.encrypt(initdata)

+        initdata = x

+        

+    return initdata

+        

+def CalcMacDESHex(data, initdata, key):

+    d = codecs.decode(data, 'hex')

+    id = codecs.decode(initdata, 'hex')

+    k = codecs.decode(key, 'hex')

+    k1 = CalcMacDES(d, id, k)

+    return codecs.encode(k1, 'hex')

+    

+

+        

diff --git a/src/performance.py b/src/performance.py
new file mode 100644
index 0000000..ce3cf93
--- /dev/null
+++ b/src/performance.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env

+

+import datetime, threading, thread

+

+class CheckPerf:

+    writelock = threading.Lock()

+    def __init__(self):

+        self.begintime = datetime.datetime.now()

+        self.endtime = None

+        self.mintime = 0.0

+        self.maxtime = 0.0

+        self.successcount = 0

+        self.failedcount = 0

+        self.totaltime = 0.0

+        self.reportmsg = ''

+        self.prechktime = None

+        

+    def startchk(self):

+        self.begintime = datetime.datetime.now()

+        self.endtime = None

+        self.mintime = 99999999.0

+        self.maxtime = 0.0

+        self.checkcount = 0

+        self.totaltime = 0.0

+        self.reportmsg = ''

+        self.prechktime = self.begintime

+    

+    def setchkpoint(self, success=True):

+        self.endtime = datetime.datetime.now()

+        delta = self.endtime - self.prechktime

+        t = delta.seconds + delta.microseconds / 1000000.0

+        if t < self.mintime: self.mintime = t

+        if t > self.maxtime: self.maxtime = t

+        if success:

+            self.successcount += 1

+        else:

+            self.failedcount += 1

+        self.totaltime += t

+        self.prechktime = self.endtime

+        

+    def _output_file(self, out_file):

+        handler = open(out_file, 'a+b')

+        handler.write("thrd[%d]" % thread.get_ident())

+        handler.write(' - ' + self.reportmsg + '\n')

+        handler.close()

+        

+    def _reportToFile(self, out_file):

+        CheckPerf.writelock.acquire()

+        try:

+            self._output_file(out_file)

+            print "generate report file " , out_file

+        except Exception, ex:

+            print "generator report file ", out_file , " Error ", ex

+        CheckPerf.writelock.release()

+        

+    def report_msg(self):

+        totalcheckcount = self.successcount + self.failedcount

+        if totalcheckcount > 2:

+            avg = (self.totaltime - self.mintime - self.maxtime) / (totalcheckcount - 2)

+        elif totalcheckcount == 0:

+            rpt = "No check point has been set"

+            return rpt

+        else:

+            avg = self.totaltime / totalcheckcount

+        rpt = 'execute[%d]count cost(s) [%.4f]max[%.4f]min[%.4f]avg[%.4f] success[%d] failed[%d]' \

+            % (totalcheckcount, self.totaltime, self.maxtime, self.mintime, avg, \

+            self.successcount, self.failedcount)

+        return rpt

+        

+    def report(self, out_file=None):

+        self.reportmsg = self.report_msg()

+        if out_file:

+            self._reportToFile(out_file)

+        return self.reportmsg

+        

diff --git a/src/pybccclt.py b/src/pybccclt.py
new file mode 100644
index 0000000..ce10630
--- /dev/null
+++ b/src/pybccclt.py
@@ -0,0 +1,353 @@
+#!/usr/bin/python

+# -*- coding: gbk -*-

+

+from ctypes import *

+

+bccclt_dll = None

+xpack_path = 'cpack.dat'

+

+cpack_fields = [

+"scust_no",

+"scust_no2",

+"sholder_ac_no",

+"sholder_ac_no2",

+"sholder_type",

+"sholder_type2",

+"sname",

+"sname2",

+"sall_name",

+"smarket_code",

+"smarket_code2",

+"sdate0",

+"sdate1",

+"sdate2",

+"sdate3",

+"stime0",

+"stime1",

+"stime2",

+"stime3",

+"lvol0",

+"lvol1",

+"lvol2",

+"lvol3",

+"lvol4",

+"lvol5",

+"lvol6",

+"lvol7",

+"lvol8",

+"lvol9",

+"lvol10",

+"lvol11",

+"lvol12",

+"damt0",

+"damt1",

+"damt2",

+"damt3",

+"damt4",

+"damt5",

+"damt6",

+"damt7",

+"damt8",

+"damt9",

+"damt10",

+"damt11",

+"damt12",

+"damt13",

+"damt14",

+"damt15",

+"damt16",

+"damt17",

+"damt18",

+"damt19",

+"damt20",

+"damt21",

+"damt22",

+"damt23",

+"damt24",

+"damt25",

+"damt26",

+"damt27",

+"damt28",

+"damt29",

+"damt30",

+"damt31",

+"damt32",

+"damt33",

+"sstock_code",

+"sstock_code2",

+"scust_type",

+"scust_type2",

+"sstat_type",

+"sstat_type2",

+"sroom_no",

+"sroom_no2",

+"sopen_emp",

+"sclose_emp",

+"schange_emp",

+"scheck_emp",

+"semp",

+"snation_code",

+"lcert_code",

+"stx_pwd",

+"stx_pwd2",

+"swithdraw_pwd",

+"swithdraw_pwd2",

+"semp_pwd",

+"semp_pwd2",

+"sbank_pwd",

+"sbank_pwd2",

+"scust_auth",

+"scust_auth2",

+"scust_limit",

+"scust_limit2",

+"lsafe_level",

+"lsafe_level2",

+"spost_code",

+"spost_code2",

+"sphone",

+"sphone2",

+"sphone3",

+"spager",

+"semail",

+"semail2",

+"snote",

+"snote2",

+"scert_no",

+"scert_no2",

+"scert_addr",

+"sstatus0",

+"sstatus1",

+"sstatus2",

+"sstatus3",

+"sstatus4",

+"lwithdraw_flag",

+"saddr",

+"saddr2",

+"sserial0",

+"sserial1",

+"sserial2",

+"sserial3",

+"sserial4",

+"scurrency_type",

+"scurrency_type2",

+"sbranch_code0",

+"sbranch_code1",

+"sbranch_code2",

+"usset0",

+"usset1",

+"usset2",

+"usset3",

+"usset4",

+"usset5",

+"usset6",

+"sstation0",

+"sstation1",

+"sbank_acc",

+"sbank_acc2",

+"lbank_acc_type",

+"lbank_acc_type2",

+"smain_flag",

+"smain_flag2",

+"sbank_code",

+"sbank_code2",

+"semp_no",

+"semp_no2",

+"drate0",

+"drate1",

+"lserial0",

+"lserial1",

+"sbankname",

+"sbankname2",

+"scard0",

+"scard1",

+"sorder0",

+"sorder1",

+"sorder2",

+"scusttypes",

+"ssectypes",

+"vsmess",

+"vsvarstr0",

+"vsvarstr1",

+"vsvarstr2"

+]

+

+def load_bccclt():

+    global bccclt_dll

+    bccclt_dll = cdll.LoadLibrary('bccclt.dll')

+    

+  

+load_bccclt()  

+

+class pyBccclt:

+    drtp_no = -1

+    

+    def setup(ip,port,xpack='cpack.dat',debug=0):

+        ''' ³õʼ»¯ '''

+        global xpack_path

+        xpack_path = xpack

+        bccclt_dll.SetDebugSwitch( debug )

+        r = bccclt_dll.BCCCLTInit(1)

+        if not r:

+            raise RuntimeError("³õʼ»¯Á¬½Óʧ°Ü")

+        no = bccclt_dll.AddDrtpNode(ip,port)

+        pyBccclt.drtp_no = no

+        if pyBccclt.drtp_no < 0:

+            raise RuntimeError('³õʼ»¯Í¨Ñ¶Æ½Ì¨Á¬½Óʧ°Ü')

+            

+        

+        

+    setup = staticmethod(setup)

+        

+    def __init__(self,mainfunc):

+        self.handle = bccclt_dll.NewXpackHandle( xpack_path )

+        self.mainfunc = mainfunc

+        self.reset()

+        

+    def get_errormsg(self):

+        return self.error_msg.value

+        

+    def reset(self):

+        self.request_row = 0

+        self.error_code = c_int(0)

+        self.error_msg = create_string_buffer('\000' * 1024)

+        self.return_code = c_int(0)

+        self.record_count = 0

+        self.record = None

+        self.timeout = 5000

+        self.response_row = 0

+        bccclt_dll.ResetPackHandle(self.handle)

+        

+    def close(self):

+        if self.handle <> None:

+            bccclt_dll.DeleteXpackHandle( self.handle )

+            self.handle = None

+        

+    def callsvr(self,func,request,timeout = 1000):

+        self.reset()

+        self.timeout = timeout

+        for k,v in request.iteritems():

+            if k not in cpack_fields:

+                raise ValueError("×Ö¶Î %s ²»´æÔÚ" % k)

+            

+            if isinstance(v,int):

+                bccclt_dll.SetIntFieldByName(self.handle,self.request_row,k,v)

+            elif isinstance(v,float):

+                bccclt_dll.SetDoubleFieldByName(self.handle,self.request_row,k,v)

+            elif isinstance(v,str):

+                bccclt_dll.SetStringFieldByName(self.handle,self.request_row,k,v)

+            else:

+                raise ValueError("×Ö¶Î %s Êý¾ÝÀàÐÍ´íÎó" % k)

+               

+        bccclt_dll.SetRequestType(self.handle,func)

+        #print "CallRequest %d:%d" % (self.mainfunc,func)

+        if not bccclt_dll.CallRequest(self.handle,pyBccclt.drtp_no,0,self.mainfunc,timeout,byref(self.error_code),self.error_msg):

+            #print "CallRequest error "

+            return False

+            

+        self.get_return_error()

+        

+        cnt = c_int(0)

+        bccclt_dll.GetRecordCount(self.handle,byref(cnt))

+        self.record_count = cnt.value

+        return True

+                

+    def get_retcode(self):

+        return self.return_code.value

+        

+    def get_return_error(self):

+        r = bccclt_dll.GetRetCode(self.handle,byref(self.return_code))

+        if not r:

+            raise RuntimeError('È¡·µ»ØÂë´íÎó')

+        if self.get_retcode() <> 0:

+            bccclt_dll.GetStringFieldByName(self.handle,0,"vsmess",self.error_msg)

+        return self.return_code.value

+        

+    def has_more_record(self):

+        #print "resp:%d, record: %d" % (self.response_row , self.record_count)

+        if self.response_row < self.record_count:

+            return True

+        elif not bccclt_dll.HaveNextPack( self.handle ):

+            return False

+        elif not bccclt_dll.CallNext(self.handle,self.timeout,byref(self.error_code),self.error_msg):

+            raise RuntimeError('»ñÈ¡ºóÐøÊý¾Ý°üÒì³£')

+        else:

+            self.response_row = 0

+            self.record_count = 0

+            self.get_return_error()

+            if self.get_retcode() <> 0:

+                raise RuntimeError('È¡ºóÐøÊý¾Ý·µ»Ø´íÎó£¬ret=%d' % self.get_retcode())

+            cnt = c_int(0)

+            bccclt_dll.GetRecordCount(self.handle,byref(cnt))

+            self.record_count = cnt.value

+            if self.response_row  < self.record_count:

+                return True

+            return False

+    

+    def convert_ascii(self,data):

+        i = 0

+        datalen = len(data)

+        result = ''

+        while i < datalen:

+            t = data[i:i+2]

+            t1 = int(t,16) & 0xFF

+            if (t1 < ord('0') or t1 > ord('9')) and (t1 < ord('A') or t1 > ord('F')):

+                raise ValueError("Value is non-hexdicimal %s:%d" % (chr(t1),t1))

+            result += chr(t1)

+            i += 2

+        return result

+        

+    def next_record(self,fields):

+        if self.response_row >= self.record_count:

+            raise ValueError('ÎÞ¿ÉÓüǼ')

+        

+        self.record = {}

+        for f in fields:

+            #print "»ñÈ¡×Ö¶Î ",f

+            if f not in cpack_fields:

+                raise ValueError("×Ö¶Î %s ²»´æÔÚ" % f)

+            

+            ctype_field = create_string_buffer(f)

+            if f[0] == 'l':

+                v = c_int(0)

+                r = bccclt_dll.GetIntFieldByName(self.handle,self.response_row,ctype_field,byref(v))

+                if not r:

+                    raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)

+                self.record[f] = v.value

+            elif f[0] == 's':

+                v = create_string_buffer('\000' * 512)

+                r = bccclt_dll.GetStringFieldByName(self.handle,self.response_row,ctype_field,v,511)

+                if not r:

+                    raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)

+                #print "%s: %s" % (f,v.value)

+                self.record[f] = v.value

+            elif f[0] == 'd':

+                v = c_double(0.0)

+                r = bccclt_dll.GetDoubleFieldByName(self.handle,self.response_row,ctype_field,byref(v))

+                if not r:

+                    raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)

+                self.record[f] = v.value

+            elif f[0] == 'u':

+                v = create_string_buffer('\000' * 1024)

+                r = bccclt_dll.GetStringFieldByName(self.handle,self.response_row,ctype_field,v,1023)

+                if not r:

+                    raise ValueError("×Ö¶Î %s δ·µ»Ø" % f)

+                    

+                data = v.value

+                data = data[2:]

+                data = self.convert_ascii(data)

+                self.record[f] = data

+            else:

+                raise ValueError('×Ö¶ÎÀàÐÍ´íÎó %s' % f)

+        self.response_row += 1

+        #print "fetch one record , " ,self.record

+        return self.record

+        

+    def fetch_record(self,fields):

+        while self.has_more_record():

+            ret = self.next_record(fields)

+            yield ret

+            

+    

+    

+    

+        
\ No newline at end of file
diff --git a/src/tcutils_module/__init__.py b/src/tcutils_module/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tcutils_module/__init__.py
diff --git a/src/tcutils_module/testmodule.py b/src/tcutils_module/testmodule.py
new file mode 100644
index 0000000..3dfec02
--- /dev/null
+++ b/src/tcutils_module/testmodule.py
@@ -0,0 +1,5 @@
+'''
+Created on 2011-9-26
+
+@author: cheng.tang
+'''