1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE a_modes.inc}
19 interface
21 uses
22 Classes,
26 // ////////////////////////////////////////////////////////////////////////// //
27 type
31 // this is base type for all scalars (and arrays)
33 public
34 type
35 TType = (TBool, TChar, TByte, TUByte, TShort, TUShort, TInt, TUInt, TString, TPoint, TSize, TList, TTrigData);
36 // TPoint: pair of Shorts
37 // TSize: pair of UShorts
38 // TList: actually, array of records
39 // TTrigData: array of mMaxDim bytes, but internally a record (mRecRef)
40 // arrays of chars are pascal shortstrings (with counter in the first byte)
42 type
46 private
47 type
50 private
71 // default value
78 mEBSType: TObject; // either TDynRecord or TDynEBS; nil means "simple type"; nil for `TTrigData` too
80 // temp
83 private
88 procedure parseDefaultValue (); // parse `mDefUnparsed` to `mDefSVal`, `mDefIVal`, `mDefIVal2`, `mDefRecRef`
92 public
109 // won't work for lists
114 public
122 //property list: TDynRecordArray read mRVal write mRVal;
139 // "value" header record contains TList fields, with name equal to record type
141 private
151 mHeaderRec: TDynRecord; // for "value" records this is header record with data, for "type" records this is header type record
153 private
163 protected
168 public
185 public
199 private
208 private
217 public
223 public
232 public
237 private
242 public
250 // creates new header record
253 // creates new header record
256 public
261 implementation
263 uses
264 SysUtils,
265 utils;
268 // ////////////////////////////////////////////////////////////////////////// //
270 begin
280 begin
287 begin
294 begin
326 var
328 begin
363 // won't work for lists
365 begin
383 begin
393 var
395 begin
397 try
399 finally
406 var
412 begin
414 begin
419 end
420 else
421 begin
427 try
434 finally
446 // default value should be parsed
448 begin
451 begin
453 raise Exception.Create(Format('field ''%s'' in record ''%s'' of record type ''%s'' is not set', [mName, mOwner.mId, mOwner.mName]));
456 begin
458 {
459 if (mDefRecRef <> nil) then
460 begin
461 rec := mDefRecRef.clone();
462 rec.mHeaderRec := mOwner.mHeaderRec;
463 try
464 mOwner.addRecordByType(mEBSTypeName, rec);
465 mRecRef := rec;
466 rec := nil;
467 finally
468 rec.Free();
469 end;
470 end;
471 }
480 // default value should be parsed
482 begin
495 begin
516 begin
525 TEBS.TBitSet: begin result += ' bitset '; if mBitSetUnique then result += 'unique '; result += mEBSTypeName; end;
529 begin
530 if (mType = TType.TPoint) then begin if (mAsT) then result += ' as txy' else result += ' as xy'; end
531 else if (mType = TType.TSize) then begin if (mAsT) then result += ' as twh' else result += ' as wh'; end;
539 var
556 begin
577 // field name
580 // field type
584 // fixed-size array?
586 begin
588 if (lmaxdim < 1) then raise Exception.Create(Format('invalid field ''%s'' array size', [fldname]));
593 begin
595 begin
596 if (fldofs >= 0) then raise Exception.Create(Format('duplicate field ''%s'' offset', [fldname]));
599 continue;
603 begin
609 continue;
613 begin
615 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
617 continue;
621 begin
623 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
626 continue;
630 begin
631 if hasdefStr or hasdefInt or hasdefId then raise Exception.Create(Format('field ''%s'' has duplicate default', [fldname]));
634 begin
639 begin
644 begin
648 else
651 continue;
655 begin
657 continue;
661 begin
663 continue;
666 if (pr.tokType <> pr.TTId) then raise Exception.Create(Format('field ''%s'' has something unexpected in definition', [fldname]));
668 if (Length(fldrecname) <> 0) then raise Exception.Create(Format('field ''%s'' already typed as ''%s''', [fldname, fldrecname]));
675 // create field
690 else raise Exception.Create(Format('field ''%s'' has invalid type ''%s''', [fldname, fldtype]));
692 if (lmaxdim > 0) and (mType <> TType.TChar) and (mType <> TType.TTrigData) then raise Exception.Create(Format('field ''%s'' of type ''%s'' cannot be array', [fldname, fldtype]));
694 begin
695 if (lmaxdim < 1) then raise Exception.Create(Format('field ''%s'' of type ''%s'' cannot be array', [fldname, fldtype]));
696 if (Length(fldrecname) > 0) then raise Exception.Create(Format('field ''%s'' of type ''%s'' cannot have another type', [fldname, fldtype]));
720 var
726 begin
730 begin
732 begin
733 // this must be triggerdata
735 begin
736 raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
738 // write triggerdata
740 if (buf = nil) then raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
741 try
744 begin
749 finally
753 exit;
755 // record reference
757 begin
758 // no ref, write -1
763 else raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
765 exit;
774 else raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
776 // find record number
778 if (f < 0) then raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' not found in record list', [mEBSTypeName, mName]));
779 if (f > maxv) then raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' has too big index', [mEBSTypeName, mName]));
784 else raise Exception.Create(Format('record reference type ''%s'' in field ''%s'' cannot be written', [mEBSTypeName, mName]));
786 exit;
795 begin
797 exit;
800 begin
801 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
803 begin
804 if (Length(mSVal) <> 1) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
806 end
807 else
808 begin
809 if (Length(mSVal) > mMaxDim) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
814 exit;
818 begin
819 // triggerdata array was processed earlier
820 if (mMaxDim >= 0) then Exception.Create(Format('byte array in field ''%s'' cannot be written', [mName]));
822 exit;
826 begin
827 if (mMaxDim >= 0) then raise Exception.Create(Format('short array in field ''%s'' cannot be written', [mName]));
829 exit;
833 begin
834 if (mMaxDim >= 0) then raise Exception.Create(Format('int array in field ''%s'' cannot be written', [mName]));
836 exit;
839 begin
844 begin
845 if (mMaxDim >= 0) then raise Exception.Create(Format('pos/size array in field ''%s'' cannot be written', [mName]));
848 exit;
851 begin
853 exit;
856 begin
858 exit;
866 var
870 begin
876 begin
878 begin
880 end
882 begin
884 end
885 else
886 begin
890 exit;
893 begin
894 //def := mOwner.mOwner;
895 //es := def.findEBSType(mEBSTypeName);
898 if (es = nil) or (not es.mIsEnum) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
900 begin
902 begin
905 exit;
908 raise Exception.Create(Format('value %d in record enum type ''%s'' for field ''%s'' not found', [mIVal, mEBSTypeName, mName]));
911 begin
912 //def := mOwner.mOwner;
913 //es := def.findEBSType(mEBSTypeName);
916 if (es = nil) or es.mIsEnum then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
917 // none?
919 begin
921 begin
923 begin
926 exit;
929 raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [0, mEBSTypeName, mName]));
931 // not none
935 begin
937 begin
940 begin
942 begin
946 break;
949 if not found then raise Exception.Create(Format('value %d in record bitset type ''%s'' for field ''%s'' not found', [mask, mEBSTypeName, mName]));
954 exit;
961 begin
963 exit;
966 begin
967 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
970 exit;
978 begin
980 exit;
983 begin
986 exit;
990 begin
992 exit;
995 begin
997 exit;
1000 begin
1002 exit;
1013 begin
1015 if (mIVal < min) or (mIVal > max) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1019 var
1024 begin
1025 // if this field should contain struct, convert type and parse struct
1029 begin
1030 // ugly hack. sorry.
1032 begin
1035 begin
1036 // '{}'
1039 end
1040 else
1041 begin
1043 // find trigger definition
1045 if (tfld = nil) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' without ''type'' field', [mName, rec.mName]));
1046 if (tfld.mEBS <> TEBS.TEnum) then raise Exception.Create(Format('triggerdata value for field ''%s'' in record ''%s'' with bad ''type'' field', [mName, rec.mName]));
1048 if (rc = nil) then raise Exception.Create(Format('triggerdata definition for field ''%s'' in record ''%s'' with type ''%s'' not found', [mName, rec.mName, tfld.mSVal]));
1051 //writeln(rc.definition);
1057 exit;
1059 // other record types
1061 begin
1063 begin
1065 end
1066 else
1067 begin
1069 if (rec = nil) then raise Exception.Create(Format('record ''%s'' (%s) value for field ''%s'' not found', [pr.tokStr, mEBSTypeName, mName]));
1075 exit;
1076 end
1078 begin
1079 //rec := mOwner.mOwner.findRecType(mEBSTypeName); // find in mapdef
1082 if (rec = nil) then raise Exception.Create(Format('record type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1090 exit;
1095 begin
1096 //es := mOwner.mOwner.findEBSType(mEBSTypeName); // find in mapdef
1099 if (es = nil) or (not es.mIsEnum) then raise Exception.Create(Format('record enum type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1101 if not es.has[tk] then raise Exception.Create(Format('record enum value ''%s'' of type ''%s'' for field ''%s'' not found', [tk, mEBSTypeName, mName]));
1104 //writeln('ENUM ', mEBSName, '; element <', mSVal, '> with value ', mIVal);
1107 exit;
1110 begin
1111 //es := mOwner.mOwner.findEBSType(mEBSTypeName); // find in mapdef
1114 if (es = nil) or es.mIsEnum then raise Exception.Create(Format('record bitset type ''%s'' for field ''%s'' not found', [mEBSTypeName, mName]));
1117 begin
1119 if not es.has[tk] then raise Exception.Create(Format('record bitset value ''%s'' of type ''%s'' for field ''%s'' not found', [tk, mEBSTypeName, mName]));
1123 if mBitSetUnique then raise Exception.Create(Format('record bitset of type ''%s'' for field ''%s'' expects only one value', [tk, mEBSTypeName, mName]));
1124 //pr.expectDelim('|');
1129 exit;
1136 begin
1142 exit;
1145 begin
1146 if (mMaxDim = 0) then raise Exception.Create(Format('invalid string size definition for field ''%s''', [mName]));
1149 begin
1150 // single char
1151 if (Length(mSVal) <> 1) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
1154 end
1155 else
1156 begin
1157 // string
1158 if (Length(mSVal) > mMaxDim) then raise Exception.Create(Format('invalid string size for field ''%s''', [mName]));
1162 exit;
1165 begin
1168 exit;
1171 begin
1174 exit;
1177 begin
1180 exit;
1183 begin
1186 exit;
1189 begin
1192 exit;
1195 begin
1198 exit;
1201 begin
1205 exit;
1209 begin
1213 begin
1214 if (mIVal < -32768) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1215 end
1216 else
1217 begin
1218 if (mIVal < 0) or (mIVal > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1222 begin
1223 if (mIVal2 < -32768) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1224 end
1225 else
1226 begin
1227 if (mIVal2 < 0) or (mIVal2 > 32767) then raise Exception.Create(Format('invalid %s value for field ''%s''', [getTypeName(mType), mName]));
1232 exit;
1235 begin
1237 exit;
1240 begin
1242 exit;
1251 begin
1255 // ////////////////////////////////////////////////////////////////////////// //
1257 begin
1258 if (pr = nil) then raise Exception.Create('cannot create record type without type definition');
1272 begin
1283 begin
1293 begin
1296 begin
1305 begin
1311 var
1313 begin
1320 begin
1326 var
1328 begin
1336 var
1338 begin
1347 begin
1360 var
1363 begin
1366 // find record data
1369 if (fld.mType <> fld.TType.TList) then raise Exception.Create(Format('cannot get record of type ''%s'' due to name conflict with ordinary field', [atypename]));
1370 // find by id
1372 begin
1375 // alas
1379 function TDynRecord.findRecordNumByType (const atypename: AnsiString; rc: TDynRecord): Integer;
1380 var
1383 begin
1385 // find record data
1388 if (fld.mType <> fld.TType.TList) then raise Exception.Create(Format('cannot get record of type ''%s'' due to name conflict with ordinary field', [atypename]));
1389 // find by ref
1391 begin
1394 // alas
1399 var
1401 begin
1402 // find record data
1405 begin
1406 // first record
1412 if (fld.mType <> fld.TType.TList) then raise Exception.Create(Format('cannot append record of type ''%s'' due to name conflict with ordinary field', [atypename]));
1413 // append
1420 var
1422 begin
1428 begin
1436 var
1439 begin
1441 begin
1444 begin
1446 begin
1450 if isForTrig[tdn] then raise Exception.Create(Format('duplicate trigdata ''%s'' trigtype ''%s''', [mName, tdn]));
1454 end
1455 else
1456 begin
1462 end
1463 else
1464 begin
1469 begin
1472 begin
1473 if (mSize > 0) then raise Exception.Create(Format('duplicate `size` in record ''%s''', [mName]));
1475 if (mSize < 1) then raise Exception.Create(Format('invalid record ''%s'' size: %d', [mName, mSize]));
1477 continue;
1480 begin
1481 if (mBinBlock >= 0) then raise Exception.Create(Format('duplicate `binblock` in record ''%s''', [mName]));
1483 if (mBinBlock < 1) then raise Exception.Create(Format('invalid record ''%s'' binblock: %d', [mName, mBinBlock]));
1484 continue;
1490 // load fields
1492 begin
1494 if hasByName(fld.name) then begin fld.Free(); raise Exception.Create(Format('duplicate field ''%s''', [fld.name])); end;
1495 // append
1499 // done with field
1500 //writeln('DEF: ', fld.definition);
1507 var
1509 begin
1511 begin
1512 // trigger data
1515 begin
1518 begin
1523 end
1524 else
1525 begin
1528 end
1529 else
1530 begin
1531 // record
1538 begin
1548 var
1557 begin
1559 begin
1560 if (mBinBlock < 1) then raise Exception.Create('cannot write binary record without block number');
1563 end
1564 else
1565 begin
1568 try
1573 // write normal fields
1575 begin
1577 // record list?
1581 if (fld.mBinOfs >= bufsz) then raise Exception.Create('binary value offset is outside of the buffer');
1583 //writeln('writing field <', fld.mName, '>');
1587 // write block with normal fields
1589 begin
1591 // signature and version
1602 // write other blocks, if any
1604 begin
1605 // calculate blkmax
1608 begin
1610 // record list?
1612 begin
1620 // write blocks
1622 begin
1626 begin
1628 // record list?
1630 begin
1636 //rec.writeBinTo(ws);
1640 // flush block
1642 begin
1654 finally
1662 var
1665 begin
1667 begin
1674 try
1676 begin
1678 // record list?
1680 begin
1683 begin
1688 continue;
1695 finally
1704 var
1708 begin
1709 if (mOwner = nil) then raise Exception.Create(Format('can''t parse record ''%s'' value without owner', [mName]));
1711 // not a header?
1713 begin
1714 // id?
1716 end
1717 else
1718 begin
1722 //writeln('parsing record <', mName, '>');
1725 begin
1727 //writeln('<', mName, '.', pr.tokStr, '>');
1729 // records
1731 begin
1732 // add records with this type (if any)
1735 begin
1738 try
1742 begin
1745 begin
1747 begin
1748 if (Length(fld.mRVal[c].mId) > 0) and (CompareText(fld.mRVal[c].mId, rec.mId) = 0) then raise Exception.Create(Format('duplicate thing ''%s'' in record ''%s''', [fld.mName, mName]));
1754 finally
1757 continue;
1761 // fields
1764 begin
1765 if fld.defined then raise Exception.Create(Format('duplicate field ''%s'' in record ''%s''', [fld.mName, mName]));
1766 if fld.internal then raise Exception.Create(Format('internal field ''%s'' in record ''%s''', [fld.mName, mName]));
1769 continue;
1772 // something is wrong
1776 // fix field defaults
1778 //writeln('done parsing record <', mName, '>');
1783 begin
1787 // ////////////////////////////////////////////////////////////////////////// //
1789 begin
1796 begin
1803 begin
1814 begin
1817 begin
1826 begin
1832 var
1834 begin
1841 var
1843 begin
1847 // fields
1850 begin
1854 begin
1858 end
1859 else
1860 begin
1865 // max field
1872 var
1878 begin
1887 begin
1890 begin
1891 if (CompareText(mIds[f], idname) = 0) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1893 if (CompareText(mMaxName, idname) = 0) then raise Exception.Create(Format('duplicate field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1897 // has value?
1899 begin
1901 begin
1902 if (Length(mMaxName) > 0) then raise Exception.Create(Format('duplicate max field ''%s'' in enum/bitset ''%s''', [idname, mName]));
1905 end
1906 else
1907 begin
1913 // append it?
1915 begin
1916 // fix maxvalue
1918 begin
1925 // next cv
1927 begin
1936 // add max field
1938 begin
1947 // ////////////////////////////////////////////////////////////////////////// //
1949 begin
1958 var
1960 begin
1972 begin
1979 var
1981 begin
1983 begin
1991 var
1993 begin
1995 begin
2003 var
2005 begin
2007 begin
2015 var
2021 // setup header links and type links
2023 var
2025 begin
2028 begin
2034 begin
2036 if (fld.mEBSType = nil) then raise Exception.Create(Format('field ''%s'' of type ''%s'' has no correcponding record definition', [fld.mName, fld.mEBSTypeName]));
2040 begin
2042 if (fld.mEBSType = nil) then raise Exception.Create(Format('field ''%s'' of type ''%s'' has no correcponding enum/bitset', [fld.mName, fld.mEBSTypeName]));
2043 if ((fld.mEBS = TDynField.TEBS.TEnum) <> (fld.mEBSType as TDynEBS).mIsEnum) then raise Exception.Create(Format('field ''%s'' of type ''%s'' enum/bitset type conflict', [fld.mName, fld.mEBSTypeName]));
2049 // setup default values
2051 var
2053 begin
2055 begin
2061 begin
2064 begin
2069 begin
2072 begin
2079 //writeln(eb.definition); writeln;
2080 continue;
2084 begin
2087 begin
2089 begin
2097 //writeln(dr.definition); writeln;
2098 continue;
2102 //writeln(dr.definition); writeln;
2103 if (findRecType(rec.name) <> nil) then begin rec.Free(); raise Exception.Create(Format('duplicate record ''%s''', [rec.name])); end;
2104 if (hdr <> nil) and (CompareText(rec.name, hdr.name) = 0) then begin rec.Free(); raise Exception.Create(Format('duplicate record ''%s''', [rec.name])); end;
2107 begin
2108 if (hdr <> nil) then begin rec.Free(); raise Exception.Create(Format('duplicate header record ''%s'' (previous is ''%s'')', [rec.name, hdr.name])); end;
2110 end
2111 else
2112 begin
2118 // put header record to top
2124 // setup header links and type links
2128 // setup default values
2134 // ////////////////////////////////////////////////////////////////////////// //
2136 var
2138 begin
2140 try
2148 begin
2157 begin