#include "stdafx.h" #include #include "TSServer.h" #include "TSField.h" /* * Base list class methods. */ TSList::TSList() { first = last = NULL; length = 0; } TSList::~TSList() { } TSPosition *TSList::GetFirst() { return first; } TSPosition *TSList::GetLast() { return last; } TSPosition *TSList::GetNext(TSPosition *pos) { if(pos == NULL) return NULL; return pos->next; } TSPosition *TSList::GetPrev(TSPosition *pos) { if(pos == NULL) return NULL; return pos->prev; } TSObject *TSList::GetAt(TSPosition *pos) { return pos->object; } int TSList::AddHead(TSObject *object) { first = new TSPosition(first, NULL, object); if (first == NULL) { TSSetLastError(TS_MEMORY_ERROR); return TS_MEMORY_ERROR; } if(last == NULL) last = first; else first->next->prev = first; length++; return TS_OK; } int TSList::AddTail(TSObject *object) { last = new TSPosition(NULL, last, object); if (last == NULL) { TSSetLastError(TS_MEMORY_ERROR); return TS_MEMORY_ERROR; } if (first == NULL) first = last; else last->prev->next = last; length++; return TS_OK; } int TSList::InsertAfter(TSPosition *pos, TSObject *object) { if (pos == NULL) return TS_ERROR; TSPosition *newPos; newPos = new TSPosition(pos->next, pos, object); if (newPos == NULL) return TS_MEMORY_ERROR; if (last == pos) last = newPos; pos->next->prev = newPos; pos->next = newPos; length ++; return TS_OK; } int TSList::InsertBefore(TSPosition *pos, TSObject *object) { if (pos == NULL) return TS_ERROR; TSPosition *newPos = new TSPosition(pos, pos->prev, object); if (newPos == NULL) return TS_MEMORY_ERROR; if (first == pos) first = newPos; pos->prev->next = newPos; pos->prev = newPos; length ++; return TS_OK; } /* * duplicate the contents of this list onto newList. */ int TSList::Duplicate(TSList *newList) { TSPosition *pos; TSObject *obj; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { obj = pos->object->Duplicate(); if(obj == NULL) { TSSetLastError(TS_MEMORY_ERROR); return TS_MEMORY_ERROR; } newList->AddTail(obj); } return TS_OK; } /* * Copies the contents of newList list onto this list. */ int TSList::Copy(TSList *newList) { TSPosition *pos; for(pos = newList->GetFirst(); pos != NULL; pos = newList->GetNext(pos)) { AddTail(pos->object); } return TS_OK; } TSString TSList::StringDump(int recursive, TSString indentation) { TSPosition *pos; TSString s = indentation + "LIST:\n"; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { s += pos->object->StringDump(recursive, indentation + " "); } return s; } int TSList::SocketString(TSString &str) { TSPosition *pos; TSString tmp; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { pos->object->SocketString(tmp); str += tmp; } str += "\r\n"; return TS_OK; } TSPosition *TSList::Get(int index) { TSPosition *pos; int cntr = 0; for(pos = GetFirst(); pos != NULL && cntr != index; pos = GetNext(pos)) { cntr ++; } return pos; } TSObject* TSList::RemoveObject(TSObject *pObject) { // First find the position, then call the other remove object; for (TSPosition *pos = GetFirst(); pos != NULL; pos = GetNext( pos )) { if ( pos->object == pObject ) return RemoveObject( pos ); } return NULL; } TSObject *TSList::RemoveObject(int index) { return RemoveObject(Get(index)); } TSObject *TSList::RemoveObject(TSPosition *pos) { if (pos == NULL) return NULL; if (pos->next) pos->next->prev = pos->prev; else last = pos->prev; if (pos->prev) pos->prev->next = pos->next; else first = pos->next; TSObject *obj = pos->object; delete pos; length--; return obj; } void TSList::EmptyList() { TSObject *obj; while ((obj = RemoveObject(0)) != NULL); } void TSList::EmptyAndDestroyList() { TSObject *obj; while ((obj = RemoveObject(0)) != NULL) { delete obj; } } /* * RecordList methods. */ TSRecordList::TSRecordList() : TSList(), m_bIsFieldList( FALSE ) {} TSRecordList::~TSRecordList() {} int TSRecordList::Receive(TSServer *server, TSSocket *socket) { TSRecord *rec; int fieldType; int tableId; char ch; int nReturn = socket->ReceiveInt(&tableId); if ( nReturn != TS_OK ) { TSSetLastError(nReturn); return nReturn; } // Create one master record which reads the schema information and // then duplicate it for each record in the list. TSRecord master( tableId, server ); while( socket->ReceiveInt(&fieldType) == TS_OK ) { rec = (TSRecord *) master.Duplicate(); rec->fieldType = fieldType; nReturn = rec->Receive(socket); if ( nReturn != TS_OK ) { TSSetLastError(nReturn); return nReturn; } // If this is a fields list of records, eliminate dups. This is very // important since duplicate field records may make the CopyFrom and // CopyTo functions work incorrectly. if ( m_bIsFieldList ) { TSRecord *pTempRec = FindRecord( rec->GetString( "name" ), rec->tableId, rec->fieldType, rec->sqlDataType ); if ( pTempRec ) { delete RemoveObject( pTempRec ); } } nReturn = AddTail(rec); if ( nReturn != TS_OK ) { TSSetLastError(nReturn); return nReturn; } } /* * There's always a \r\n at the end of the list, * but usually the \r has already been read so read * up till the next \n. */ while ((ch = socket->ReadChar()) != 0) if( ch == '\n') break; return TS_OK; } int TSRecordList::SocketString(TSString &str) { TSPosition *pos; TSRecord *rec; TSString s; str = ""; // All of the records in the list had better have the // same table id so we'll get it from the first record. pos = GetFirst(); if(pos != NULL) { TSEncodeInt(GetAt(pos)->tableId, str); while( pos != NULL) { rec = GetAt(pos); s = ""; TSEncodeInt(rec->fieldType, s); str += s; rec->SocketString(s); str += s; pos = GetNext(pos); } } else { // If there's nothing in the list we still need to // in a tableId for a place holder. TSEncodeInt(0,str); } str += "\r\n"; return TS_OK; } // Find a record with the same structure rather than the same data. TSRecord* TSRecordList::FindRecord(const char *fieldName, int nTableId, int nFieldType, int nSqlDataType) { TSRecord *rec; TSPosition *pos; if ( !fieldName ) return NULL; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if (( rec->tableId == nTableId ) && ( rec->fieldType == nFieldType ) && ( rec->sqlDataType == nSqlDataType ) && rec->GetString( "name" ) && ( strcmp( rec->GetString( "name" ), fieldName ) == 0 )) { return rec; } } return NULL; } TSRecord *TSRecordList::FindRecord(const char *fieldName, int searchValue) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if ( rec->GetInt(fieldName) == searchValue ) { return rec; } } return NULL; } TSRecord *TSRecordList::FindRecord(const char *fieldName, double searchValue) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if ( rec->GetDouble(fieldName) == searchValue ) { return rec; } } return NULL; } TSRecord *TSRecordList::FindRecord(const char *fieldName, const char *searchValue) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); char *str = rec->GetString(fieldName); if( str ) { if ( strcmp(str, searchValue) == 0 ) { return rec; } } } return NULL; } TSRecord *TSRecordList::FindRecord(int recId) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if ( rec->GetInt("id") == recId ) { return rec; } } return NULL; } /* * Field list methods. */ TSString TSFieldList::DumpSchema(TSString indentation) { TSPosition *pos; TSString s = indentation + "LIST:\n"; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { s += GetAt(pos)->DumpSchema(indentation + " "); } return s; } TSField *TSFieldList::FindFieldByName(const char *fieldName, int fieldType) { if ( !fieldName ) return NULL; TSPosition *pos; TSField *field; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { field = GetAt(pos); #ifdef WIN32 if(stricmp(field->fieldName,fieldName) == 0 && (field->fieldType == fieldType || fieldType == 0 || field->fieldType == 0)) #else if(strcasecmp(field->fieldName,fieldName) == 0 && (field->fieldType == fieldType || fieldType == 0 || field->fieldType == 0)) #endif { return field; } } return NULL; } /* * Tree list methods */ TSRecord *TSTreeList::FindRecord(int recId) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if ( rec->GetInt("id") == recId ) { return rec; } // Search sub tree TSTreeList *subList = rec->GetSubTreeList(); if(subList != NULL) { rec = subList->FindRecord(recId); if(rec != NULL) { return rec; } } } return NULL; } TSRecord *TSTreeList::FindRecord(const char *fieldName, int searchValue) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if ( rec->GetInt(fieldName) == searchValue) { return rec; } // Search sub tree TSTreeList *subList = rec->GetSubTreeList(); if(subList != NULL) { rec = subList->FindRecord(fieldName, searchValue); if(rec != NULL) { return rec; } } } return NULL; } TSRecord *TSTreeList::FindRecord(const char *fieldName, double searchValue) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); if ( rec->GetDouble(fieldName) == searchValue ) { return rec; } // Search sub tree TSTreeList *subList = rec->GetSubTreeList(); if(subList != NULL) { rec = subList->FindRecord(fieldName, searchValue); if(rec != NULL) { return rec; } } } return NULL; } TSRecord *TSTreeList::FindRecord(const char *fieldName, const char *searchValue) { TSRecord *rec; TSPosition *pos; for(pos = GetFirst(); pos != NULL; pos = GetNext(pos)) { rec = GetAt(pos); char *str = rec->GetString(fieldName); if ( strcmp(str, searchValue) == 0 ) { return rec; } // Search sub tree TSTreeList *subList = rec->GetSubTreeList(); if(subList != NULL) { rec = subList->FindRecord(fieldName, searchValue); if(rec != NULL) { return rec; } } } return NULL; } /* * Position object methods. */ TSPosition::TSPosition() { next = prev = NULL; object = NULL; } TSPosition::TSPosition(TSPosition *nextPos, TSPosition *prevPos, TSObject *thisObj) { next = nextPos; prev = prevPos; object = thisObj; }