home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic 4 Unleashed
/
Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso
/
repease
/
util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-12
|
21KB
|
690 lines
/******************************************************************************
UTIL.C
Sub Systems, Inc.
Copyright (c) 1992, Sub Systems, Inc. All Rights Reserved.
159 Main Street, #8C, Stoneham, MA 02180, (617) 438-8901.
FileSort and FileJoin Utilities
This file is used only by the demo program. This file is not needed
by the ReportEase Plus DLL.
******************************************************************************/
#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
#include "dos.h"
#include "fcntl.h"
#include "io.h"
#include "signal.h"
#include "string.h"
#include "time.h"
/*****************************************************************************
Compiler specific include files and library translations
******************************************************************************/
#if defined(__TURBOC__)
#include "alloc.h"
#include "dir.h"
#include "string.h"
#include "mem.h"
#define _memavl coreleft
#define _makepath fnmerge
#define _splitpath fnsplit
#else
#include "string.h"
#include "malloc.h"
#include "memory.h"
#endif
/******************************************************************************
WIN32 specific defines
*******************************************************************************/
#if defined (_WIN32)
#if !defined(WIN32)
#define WIN32
#endif
#endif
#if defined (WIN32)
#define huge
#define _export
#else
#define huge huge
#endif
#include "util.h"
/******************************************************************************
Necessary Prototypes
*******************************************************************************/
int JoinArrayMem(void);
int JoinExtractCommonField(struct StrJoinRec far *,int,int);
int JoinFreeMem(struct StrJoinRec far *,int);
int JoinReadFile(LPSTR,struct StrJoinRec far *);
int JoinWriteFile(LPSTR);
int SortArrayMem(int);
int SortBuildKeys(void);
int SortReadFile(LPSTR);
int SortDoSort(void);
int SortWriteFile(LPSTR);
int FileLines(LPSTR);
int ExtractField(LPSTR,int far *,int,char far *);
void far *OurAlloc(long);
void OurFree(void far *);
int ltrm(LPSTR);
int rtrm(LPSTR);
int strtrm(LPSTR);
/******************************************************************************
Define statements
*******************************************************************************/
#define TRUE 1
#define FALSE 0
/******************************************************************************
Global Variables
*******************************************************************************/
struct StrJoinRec {
char far *rec; /* record pointer */
char far *field; /* common field */
} far *file1,far *file2;
struct StrSortRec {
char far *rec; /* record pointer */
char far *key; /* key pointer */
} far *item;
int TotalLines,TotalLines1,TotalLines2,key[10],TotalKeys;
char SortKey[10][80];
/******************************************************************************
Main routine.
*******************************************************************************/
int WINAPI _export FileJoin(LPSTR InputFile1,int field1,LPSTR InputFile2, int field2, LPSTR OutputFile)
{
TotalLines1=FileLines(InputFile1); /* find total number of lines in file1 */
TotalLines2=FileLines(InputFile2); /* find total number of lines in file2 */
if (TotalLines1<0 || TotalLines2<0) return FALSE;
if (!JoinArrayMem()) return FALSE; /* allocate memory for the line arrays */
if (!JoinReadFile(InputFile1,file1)) return FALSE; /* read the input file1 */
if (!JoinReadFile(InputFile2,file2)) return FALSE; /* read the input file2 */
if (!JoinExtractCommonField(file1,TotalLines1,field1)) return FALSE; /* extract the common field for file 1*/
if (!JoinExtractCommonField(file2,TotalLines2,field2)) return FALSE; /* extract the common field for file 2*/
if (!JoinWriteFile(OutputFile)) return FALSE; /* write the output file */
if (!JoinFreeMem(file1,TotalLines1)) return FALSE; // freeup memory
if (!JoinFreeMem(file2,TotalLines2)) return FALSE;
return TRUE;
}
/*****************************************************************************
WEP:
Library exit routine.
******************************************************************************/
CALLBACK _export WEP(int nParameter)
{
return 1;
}
/****************************************************************************
JoinArrayMem:
Allocate memory for the line array.
*****************************************************************************/
JoinArrayMem()
{
file1=(struct StrJoinRec far *) OurAlloc(((long)TotalLines1+1)*(long)sizeof(struct StrJoinRec));
file2=(struct StrJoinRec far *) OurAlloc(((long)TotalLines2+1)*(long)sizeof(struct StrJoinRec));
if (file1==NULL || file2==NULL) {
MessageBox(NULL,"Out of RAM for file pointers","JOIN",MB_OK);return FALSE;
}
return TRUE;
}
/*****************************************************************************
JoinReadFile:
Read the file into memory.
*****************************************************************************/
JoinReadFile(LPSTR FileName,struct StrJoinRec far *item)
{
char line[250];
LPSTR result;
int i=0;
FILE far *iStream;
if (NULL==(iStream=fopen(FileName,"rt"))) {
wsprintf(line,"Can not open the input file %s",(LPSTR)FileName);
MessageBox(NULL,line,"JOIN",MB_OK);
return FALSE;
}
NEXT_LINE:
result=fgets(line,250,iStream);
if (ferror(iStream)) {
wsprintf(line,"Error in reading the file: %s",(LPSTR)FileName);
MessageBox(NULL,line,"JOIN",MB_OK);
return FALSE;
}
if (feof(iStream)) goto END_FILE;
if (result==NULL) {
wsprintf(line,"Error in reading file: %s",(LPSTR)FileName);
MessageBox(NULL,line,"JOIN",MB_OK);
return FALSE;
}
if (NULL==(item[i].rec=OurAlloc(lstrlen(line)+1))) {
MessageBox(NULL,"Cannot load the file, out of memory\n","JOIN",MB_OK);return FALSE;
}
lstrcpy(item[i].rec,line);
i++;
goto NEXT_LINE;
END_FILE:
fclose(iStream);
return TRUE;
}
/*****************************************************************************
JoinFreeMem:
Free up memory used by a file
*****************************************************************************/
JoinFreeMem(struct StrJoinRec far *item, int TotalLines)
{
int i;
for (i=0;i<TotalLines;i++) {
OurFree(item[i].rec);
OurFree(item[i].field);
}
OurFree(item);
return TRUE;
}
/*****************************************************************************
JoinExtractCommonField:
Extract the common field from the file records
*****************************************************************************/
JoinExtractCommonField(struct StrJoinRec far *file,int TotalLines,int fld)
{
int line,LineIdx,CurLen,FieldNo;
char CurKey[240],KeyFound;
for (line=0;line<TotalLines;line++) { /* process each line */
LineIdx=0; /* prepare to scan the line */
CurLen=lstrlen(file[line].rec);
if (CurLen>0 && file[line].rec[CurLen-1]==0xA) CurLen--;
KeyFound=FALSE;
FieldNo=1;
while (TRUE) {
/* extract the fields */
if (!ExtractField(file[line].rec,&LineIdx,CurLen,CurKey)) break;
if (fld==FieldNo) {
KeyFound=TRUE;
break;
}
FieldNo++;
}
if (!KeyFound) {
wsprintf(CurKey,"Common field not found in record number: %d",line+1);
MessageBox(NULL,CurKey,NULL,MB_OK);
return FALSE;
}
/* build the full key */
if (NULL==(file[line].field=OurAlloc(lstrlen(CurKey)+1))) {
MessageBox(NULL,"Out of Memory during Key Build","JOIN",MB_OK);return FALSE;
}
lstrcpy(file[line].field,CurKey);
}
return TRUE;
}
/******************************************************************************
FileSort:
Main Sort routine.
*****************************************************************************/
int WINAPI _export FileSort(LPSTR InputFile, int NumKeys, LPINT KeyTable)
{
int i;
// save the sort keys
TotalKeys=NumKeys;
for (i=0;i<TotalKeys;i++) key[i]=KeyTable[i];
TotalLines=FileLines(InputFile);/* find total number of lines in the file */
if (TotalLines<0) return FALSE;
if (!SortArrayMem(TotalLines)) return FALSE; /* allocate memory for the line arrays */
if (!SortReadFile(InputFile)) return FALSE; /* read the input file */
if (!SortBuildKeys()) return FALSE; /* build keys */
if (!SortDoSort()) return FALSE; /* sort the file in the memory */
if (!SortWriteFile(InputFile)) return FALSE; /* write the output file */
return TRUE;
}
/****************************************************************************
SortArrayMem:
Allocate memory for the line array.
*****************************************************************************/
SortArrayMem(int TotalLines)
{
item=(struct StrSortRec far *)OurAlloc(((long)TotalLines+1)*(long)sizeof(struct StrSortRec));
if (item==NULL) {
MessageBox(NULL,"Out of RAM for file pointers","SORT",MB_OK);return FALSE;
}
return TRUE;
}
/*****************************************************************************
SortReadFile:
Read the file into memory.
*****************************************************************************/
SortReadFile(LPSTR InputFile)
{
char line[250],far *result;
int i=0;
FILE far *iStream;
if (NULL==(iStream=fopen(InputFile,"rt"))) {
wsprintf(line,"Can not open the input file %s",(LPSTR)InputFile);
MessageBox(NULL,line,"SORT",MB_OK);
return FALSE;
}
NEXT_LINE:
result=fgets(line,250,iStream);
if (ferror(iStream)) {
wsprintf(line,"Error in reading the file: %s",(LPSTR)InputFile);
MessageBox(NULL,line,"SORT",MB_OK);
return FALSE;
}
if (feof(iStream)) goto END_FILE;
if (result==NULL) {
wsprintf(line,"Error in reading file: %s",(LPSTR)InputFile);
MessageBox(NULL,line,"SORT",MB_OK);
return FALSE;
}
if (NULL==(item[i].rec=OurAlloc(strlen(line)+1))) {
MessageBox(NULL,"Cannot load the file, out of memory\n","SORT",MB_OK);return FALSE;
}
lstrcpy(item[i].rec,line);
i++;
goto NEXT_LINE;
END_FILE:
fclose(iStream);
return TRUE;
}
/*****************************************************************************
SortBuildKeys:
Build a key for each record line.
*****************************************************************************/
SortBuildKeys()
{
int line,LineIdx,CurLen,i,FieldNo;
char KeyString[240],CurKey[240],KeysFound;
for (line=0;line<TotalLines;line++) { /* process each line */
LineIdx=0; /* prepare to scan the line */
CurLen=lstrlen(item[line].rec);
if (CurLen>0 && item[line].rec[CurLen-1]==0xA) CurLen--;
KeysFound=0;
FieldNo=1;
for (i=0;i<TotalKeys;i++) SortKey[0][0]=0;
while (TRUE) {
/* extract the fields */
if (!ExtractField(item[line].rec,&LineIdx,CurLen,CurKey)) break;
for (i=0;i<TotalKeys;i++) {
if (key[i]==FieldNo) {
strcpy(SortKey[i],CurKey);
KeysFound++;
}
}
FieldNo++;
}
if (KeysFound!=TotalKeys) {
wsprintf(KeyString,"Sort key %d not found in record number: %d",key[KeysFound],line+1);
MessageBox(NULL,KeyString,"SORT",MB_OK);
return FALSE;
}
/* build the full key */
KeyString[0]=0;
for (i=0;i<TotalKeys;i++) strcat(KeyString,SortKey[i]);
if (NULL==(item[line].key=OurAlloc(strlen(KeyString)+1))) {
MessageBox(NULL,"Out of Memory during Key Build","SORT",MB_OK);return FALSE;
}
lstrcpy(item[line].key,KeyString);
}
return TRUE;
}
/*****************************************************************************
SortDoSort:
Sort the file in the memory
*****************************************************************************/
SortDoSort()
{
int i,j,SmallRecIdx;
struct StrSortRec TempItem;
for (i=0;i<TotalLines;i++) {
SmallRecIdx=i;
for(j=i;j<TotalLines;j++) {
if (lstrcmp(item[j].key,item[SmallRecIdx].key)<0) SmallRecIdx=j;
}
if (SmallRecIdx!=i) { /* exchange the words */
TempItem=item[i];
item[i]=item[SmallRecIdx];
item[SmallRecIdx]=TempItem;
}
}
return TRUE;
}
/*****************************************************************************
SortWriteFile:
write the output file
*****************************************************************************/
SortWriteFile(LPSTR InputFile)
{
FILE far *oStream;
int i;
char OutputFile[128],string[300];
for (i=0;i<129 && InputFile[i]!='.' && InputFile[i]!='\0';i++) OutputFile[i]=InputFile[i];
OutputFile[i]=0;
strcat(OutputFile,".SRT");
unlink(OutputFile);
if (NULL==(oStream=fopen(OutputFile,"wt"))) {
wsprintf(string,"Can not open the output file %s",(LPSTR)OutputFile);
MessageBox(NULL,string,"SORT",MB_OK);
return FALSE;
}
for (i=0;i<TotalLines;i++) {
lstrcpy(string,item[i].rec);
fputs(string,oStream);
}
fclose(oStream);
return TRUE;
}
/*****************************************************************************
FileLines:
find total number of lines in the file.
*****************************************************************************/
FileLines(LPSTR FileName)
{
char line[250];
LPSTR result;
int TotalLines=0;
FILE far *iStream;
if (NULL==(iStream=fopen(FileName,"rt"))) {
wsprintf(line,"Can not open the input file %s",(LPSTR)FileName);
MessageBox(NULL,line,"JOIN",MB_OK);
return -1;
}
NEXT_LINE:
result=fgets(line,250,iStream);
if (ferror(iStream)) {
wsprintf(line,"Error in reading the file: %s",(LPSTR)FileName);
MessageBox(NULL,line,"JOIN",MB_OK);
return -1;
}
if (feof(iStream)) goto END_FILE;
if (result==NULL) {
wsprintf(line,"Error in reading file: %s",(LPSTR)FileName);
MessageBox(NULL,line,"JOIN",MB_OK);
return -1;
}
TotalLines++;
if (TotalLines>30000) {
MessageBox(NULL,"Cannot sort this file larger than 30000 lines.","JOIN",MB_OK);
return -1;
}
goto NEXT_LINE;
END_FILE:
fclose(iStream);
return TotalLines;
}
/******************************************************************************
ExtractField:
This routine scans a text line to extract the next field.
The fields are assumed to be of character type.
******************************************************************************/
ExtractField(LPSTR line,int far *idx,int LineLen,char far *CharReturn)
{
char quote='"',string[240],far *ptr,SaveChar;
int i,j,k;
i=(*idx);
while (i<LineLen && line[i]==' ') i++; /* go past the spaces */
if (i>=LineLen) return FALSE; /* past the end of the line */
if (line[i]==quote) {
i++; /* skip over the first quote */
for (k=i;k<LineLen;k++) if (line[k]==quote) break;
if (k==LineLen) return FALSE;
ptr=&line[k];
j=1;
while (ptr[j]!=',' && ptr[j]!=0) j++;/* locate the next comma */
SaveChar=ptr[0]; /* extract the string */
ptr[0]=0;
lstrcpy(string,&line[i]);
ptr[0]=SaveChar;
(*idx)=i+lstrlen(string)+1+j; /* index to the next field */
}
else {
for (k=i;k<LineLen;k++) if (line[k]==',') break;
if (k==LineLen) ptr=&line[LineLen];
else ptr=&line[k];
SaveChar=ptr[0]; /* extract the string */
ptr[0]=0;
lstrcpy(string,&line[i]);
ptr[0]=SaveChar;
(*idx)=i+lstrlen(string)+1; /* index to the next field */
}
lstrcpy(CharReturn,string);
return TRUE;
}
/*****************************************************************************
JoinWriteFile:
write the output file
*****************************************************************************/
JoinWriteFile(LPSTR OutputFile)
{
FILE far *oStream;
int i,j,CurLen;
char line[500];
unlink(OutputFile);
if (NULL==(oStream=fopen(OutputFile,"wt"))) {
wsprintf(line,"Can not open the output file %s",(LPSTR)OutputFile);
MessageBox(NULL,line,"JOIN",MB_OK);
return FALSE;
}
for (i=0;i<TotalLines1;i++) { /* process each line of the primary file */
for(j=0;j<TotalLines2;j++) { /* match with the secondary file */
if (lstrcmp(file1[i].field,file2[j].field)==0) {
lstrcpy(line,file1[i].rec);
CurLen=lstrlen(line);
if (CurLen>0 && line[CurLen-1]==0xA) CurLen--;
line[CurLen]=','; /* comma delimiter */
CurLen++;
line[CurLen]=0;
if (CurLen+lstrlen(file2[j].rec)>499) {
MessageBox(NULL,"Record too big!","JOIN",MB_OK);
return FALSE;
}
lstrcat(line,file2[j].rec);
fputs(line,oStream);
}
}
}
fclose(oStream);
return TRUE;
}
/*******************************************************************************
strtrm:
Trim the spaces on left & right of the string
*******************************************************************************/
strtrm(LPSTR string)
{
rtrm(string);
ltrm(string);
return TRUE;
}
/*******************************************************************************
rtrm:
Trim the space on right side of the string
*******************************************************************************/
rtrm(LPSTR string)
{
int i,TmpLen;
TmpLen=lstrlen(string);
for (i=TmpLen-1;i>=0 && string[i] == ' ';i--);
string[i+1] = '\0';
return TRUE;
}
/*******************************************************************************
ltrm:
Trim the space on left side of the string
*******************************************************************************/
ltrm(LPSTR string)
{
int i,TmpLen,BegPoint;
char TmpStr[255];
TmpLen=lstrlen(string);
for (i=0;i < TmpLen && string[i] == ' ';i++);
BegPoint=i;
for (i=BegPoint;i<TmpLen;i++) TmpStr[i-BegPoint]=string[i];
TmpStr[TmpLen-BegPoint] = '\0';
lstrcpy(string,TmpStr);
return TRUE;
}
/*******************************************************************************
OurAlloc:
This routine allocates a specified number of byte from the global heap,
and returns a far pointer to the locked object.
*******************************************************************************/
void far *OurAlloc(long bytes)
{
HANDLE hnd;
LPSTR result;
if ( (NULL==(hnd=GlobalAlloc(GMEM_MOVEABLE,bytes+1)))
|| (NULL==(result=GlobalLock(hnd))) ) {
MessageBox(NULL,"Ran out of memory","JOIN",MB_OK);
return FALSE;
}
return result;
}
/******************************************************************************
OurFree:
Free up the given memory object. This object must have been allocated
using the OurAlloc routine.
*******************************************************************************/
void OurFree(void far *pMem)
{
HGLOBAL hMem;
if (pMem!=NULL) {
#if defined(WIN32)
hMem=GlobalHandle(pMem); // convert pointer to handle
#else
{
DWORD temp=GlobalHandle((UINT)(((DWORD)pMem)>>16));
hMem=(HGLOBAL)LOWORD(temp);
}
#endif
GlobalUnlock(hMem);
GlobalFree(hMem);
}
}