55interface
66
77uses
8- Classes, SysUtils, bufstream, Contnrs, Math;
8+ Classes, SysUtils, bufstream, Contnrs, Math, util ;
99
1010procedure ReadMeasurements (inputFile: string);
1111
@@ -44,12 +44,12 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
4444begin
4545 while idx < (bufferLength - 1 ) do
4646 begin
47- // read the city until separator
48- // city := '';
47+ // read the city by looking for semicolon
48+ city := ' ' ;
4949 cityStart := idx;
5050 while buffer[idx] <> REC_SEP do Inc(idx);
5151 SetString(city, @buffer[cityStart], (idx - cityStart));
52- // increment through temp reading and calculate integer temp (*100)
52+ // parse the temp reading
5353 Inc(idx); // move pointer past the ;
5454 currentTempSign := 1 ;
5555 // check for negative sign, if so flag the multiplier and then move past neg sign
@@ -59,20 +59,16 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
5959 Inc(idx);
6060 end ;
6161 // look ahead - is decimal point 2 spaces away then we have two digits
62+ temp := 0 ;
6263 if buffer[idx + 2 ] = DECIMAL_POINT then
6364 begin
64- temp := currentTempSign * (100 * byte(buffer[idx]) + 10 *
65- byte(buffer[idx + 1 ]) + byte(buffer[idx + 2 ]) - 5328 );
66- // move past digits and CRLF and position pointer to first character of next record
67- idx := idx + 6 ;
68- end
69- else
70- begin
71- temp := currentTempSign * (10 * byte(buffer[idx + 1 ]) +
72- byte(buffer[idx + 2 ]) - 528 );
73- // move past digits and CRLF and position pointer to first character of next record
74- idx := idx + 5 ;
65+ temp := 100 * (byte(buffer[idx]) - ANSI_ZERO);
66+ Inc(idx);
7567 end ;
68+ temp := temp + 10 * (byte(buffer[idx]) - ANSI_ZERO);
69+ idx := idx + 2 ;
70+ temp := currentTempSign * (temp + (byte(buffer[idx]) - ANSI_ZERO));
71+ idx := idx + 3 ;
7672 reading := results.Find(city);
7773 if reading = nil then
7874 begin
@@ -94,51 +90,6 @@ procedure ProcessMeasurements(var buffer: array of char; bufferLength: integer;
9490 end ;
9591end ;
9692
97- function PascalRound (x: double): double;
98- var
99- t: double;
100- begin
101- // round towards positive infinity
102- t := Trunc(x);
103- if (x < 0.0 ) and (t - x = 0.5 ) then
104- begin
105- // Do nothing
106- end
107- else if Abs(x - t) >= 0.5 then
108- begin
109- t := t + Math.Sign(x);
110- end ;
111-
112- if t = 0.0 then
113- Result := 0.0
114- else
115- Result := t;
116- end ;
117-
118-
119- function RoundEx (x: double): double;
120- begin
121- Result := PascalRound(x * 10.0 ) / 10.0 ;
122- end ;
123-
124- function Compare (AList: TStringList; AIndex1, AIndex2: integer): integer;
125- var
126- Pos1, Pos2: integer;
127- Str1, Str2: string;
128- begin
129- Result := 0 ;
130- Str1 := AList.Strings[AIndex1];
131- Str2 := AList.Strings[AIndex2];
132- Pos1 := Pos(' =' , Str1);
133- Pos2 := Pos(' =' , Str2);
134- if (Pos1 > 0 ) and (Pos2 > 0 ) then
135- begin
136- Str1 := Copy(Str1, 1 , Pos1 - 1 );
137- Str2 := Copy(Str2, 1 , Pos2 - 1 );
138- Result := CompareStr(Str1, Str2);
139- end ;
140- end ;
141-
14293procedure DumpMeasurements (results: TFPHashList);
14394var
14495 i: integer;
@@ -160,11 +111,6 @@ procedure DumpMeasurements(results: TFPHashList);
160111 mean := RoundEx(reading^.total / reading^.numReadings / 10 );
161112 readingStr := reading^.city + ' =' + FormatFloat(' 0.0' , min) +
162113 ' /' + FormatFloat(' 0.0' , mean) + ' /' + FormatFloat(' 0.0' , max);
163- { $IFDEF DEBUG}
164- readingStr := reading^.city + ' =' + FormatFloat(' 0.0' , min) +
165- ' /' + FormatFloat(' 0.0' , mean) + ' /' + FormatFloat(' 0.0' , max) +
166- ' /' + IntToStr(reading^.total) + ' /' + IntToStr(reading^.numReadings);
167- { $ENDIF}
168114 weatherStationList.Add(readingStr);
169115 Dispose(reading);
170116 end ;
@@ -183,40 +129,14 @@ procedure DumpMeasurements(results: TFPHashList);
183129 WriteLn(' }' );
184130end ;
185131
186-
187- procedure DumpExceptionCallStack (E: Exception);
188- var
189- I: integer;
190- Frames: PPointer;
191- Report: string;
192- begin
193- Report := ' Program exception! ' + LineEnding + ' Stacktrace:' +
194- LineEnding + LineEnding;
195- if E <> nil then
196- begin
197- Report := Report + ' Exception class: ' + E.ClassName + LineEnding +
198- ' Message: ' + E.Message + LineEnding;
199- end ;
200- Report := Report + BackTraceStrFunc(ExceptAddr);
201- Frames := ExceptFrames;
202- for I := 0 to ExceptFrameCount - 1 do
203- Report := Report + LineEnding + BackTraceStrFunc(Frames[I]);
204- WriteLn(Report);
205- Halt; // End of program execution
206- end ;
207-
208-
209132procedure ReadMeasurements (inputFile: string);
210133var
211134 totalBytesRead, BytesRead: int64;
212135 Buffer: array [0 ..BUFFER_SIZE] of char;
213136 FileStream: TFileStream;
214137 fileSize: int64;
215138 ReadBufferStream: TReadBufStream;
216- starttime: uint64;
217- elapsedTimeSec, MBRead: double;
218139 results: TFPHashList;
219- currentChar: char;
220140 idx: integer;
221141 startOfNextRecord: string;
222142 startOfNextRecordLength: integer;
@@ -228,50 +148,29 @@ procedure ReadMeasurements(inputFile: string);
228148 ReadBufferStream := TReadBufStream.Create(FileStream);
229149 fileSize := FileStream.size;
230150 totalBytesRead := 0 ;
231- starttime := GetTickCount64;
232151 results := TFPHashList.Create;
233152 startOfNextRecord := ' ' ;
234153 while totalBytesRead <= fileSize do
235154 // While the amount of data read is less than or equal to the size of the stream do
236155 begin
237156 startOfNextRecordLength := Length(startOfNextRecord);
238- // WriteLn('startOfNextRecordLength: ', startOfNextRecordLength);
239157 // if we have leftover from previous read then prepend it to this buffer
240158 if startOfNextRecordLength > 0 then
241159 Move(PChar(startOfNextRecord)^, Buffer[0 ], startOfNextRecordLength);
242160 BytesRead := ReadBufferStream.Read(Buffer[startOfNextRecordLength], READ_SIZE);
243- // WriteLn('Bytes read: ', BytesRead);
244161 if BytesRead < 1 then break;
245162 // now look in buffer backwards until we find the first LF
246163 bufferLength := startOfNextRecordLength + BytesRead;
247164 idx := bufferLength - 1 ;
248- currentChar := buffer[idx];
249- while (currentChar <> LF) do
250- begin
251- Dec(idx);
252- currentChar := buffer[idx];
253- end ;
165+ while (buffer[idx] <> LF) do Dec(idx);
254166 ProcessMeasurements(Buffer, idx + 1 , results);
255167 startOfNextRecord := ' ' ;
256168 startOfNextRecordLength := bufferLength - idx - 1 ;
257- // WriteLn('startOfNextRecordLength: ', startOfNextRecordLength);
258169 if startOfNextRecordLength > 0 then
259170 SetString(startOfNextRecord, @buffer[idx + 1 ], startOfNextRecordLength);
260171 Inc(totalBytesRead, BytesRead);
261172 end ;
262173 DumpMeasurements(results);
263- elapsedTimeSec := (GetTickCount64() - starttime) / 1000 ;
264- MBRead := (totalBytesRead / (1024 * 1024 ));
265- { $IFDEF DEBUG}
266- WriteLn(inputFile);
267- WriteLn(' Buffer size: ' , SizeOf(Buffer));
268- WriteLn(' Read size: ' , READ_SIZE);
269- WriteLn(' File size: ' , FileStream.Size);
270- WriteLn(' Total Bytes Read: ' , totalBytesRead);
271- WriteLn(Format(' %f MB read' , [MBRead]));
272- WriteLn(Format(' %f secs' , [elapsedTimeSec]));
273- WriteLn(Format(' %f MB/s processed' , [MBRead / elapsedTimeSec]));
274- { $ENDIF}
275174 ReadBufferStream.Free;
276175 FileStream.Free;
277176 results.Free;
0 commit comments