--- /dev/null
+#include "myutils.h"\r
+#include "path.h"\r
+#include "timing.h"\r
+\r
+#define TRACE 0\r
+\r
+const unsigned PathMagic = 0x9A783A16;\r
+\r
+struct PathBuffer\r
+ {\r
+ unsigned Magic;\r
+ char *Buffer;\r
+ unsigned Size;\r
+ bool InUse;\r
+ };\r
+\r
+static PathBuffer **g_PathBuffers;\r
+static unsigned g_PathBufferSize;\r
+\r
+static char *AllocBuffer(unsigned Size)\r
+ {\r
+ if (Size == 0)\r
+ return 0;\r
+\r
+// Is a free buffer that is big enough?\r
+ for (unsigned i = 0; i < g_PathBufferSize; ++i)\r
+ {\r
+ PathBuffer *PB = g_PathBuffers[i];\r
+ asserta(PB->Magic == PathMagic);\r
+ if (!PB->InUse)\r
+ {\r
+ if (PB->Size >= Size)\r
+ {\r
+ PB->InUse = true;\r
+ return PB->Buffer;\r
+ }\r
+ if (PB->Buffer == 0)\r
+ {\r
+ unsigned Size2 = Size + 1024;\r
+ PB->Buffer = MYALLOC(char, Size2, Path);\r
+ PB->Size = Size2;\r
+ PB->InUse = true;\r
+ return PB->Buffer;\r
+ }\r
+ }\r
+ }\r
+\r
+// No available buffer, must expand g_PathBuffers[]\r
+ unsigned NewPathBufferSize = g_PathBufferSize + 1024;\r
+ PathBuffer **NewPathBuffers = MYALLOC(PathBuffer *, NewPathBufferSize, Path);\r
+ \r
+ for (unsigned i = 0; i < g_PathBufferSize; ++i)\r
+ NewPathBuffers[i] = g_PathBuffers[i];\r
+\r
+ for (unsigned i = g_PathBufferSize; i < NewPathBufferSize; ++i)\r
+ {\r
+ PathBuffer *PB = MYALLOC(PathBuffer, 1, Path);\r
+ PB->Magic = PathMagic;\r
+ PB->Buffer = 0;\r
+ PB->Size = 0;\r
+ PB->InUse = false;\r
+ NewPathBuffers[i] = PB;\r
+ }\r
+\r
+ PathBuffer *PB = NewPathBuffers[g_PathBufferSize];\r
+\r
+ MYFREE(g_PathBuffers, g_PathBufferSize, Path);\r
+ g_PathBuffers = NewPathBuffers;\r
+ g_PathBufferSize = NewPathBufferSize;\r
+\r
+ asserta(!PB->InUse && PB->Buffer == 0);\r
+\r
+ unsigned Size2 = Size + 1024;\r
+ PB->Buffer = MYALLOC(char, Size2, Path);\r
+ PB->Size = Size2;\r
+ PB->InUse = true;\r
+ return PB->Buffer;\r
+ }\r
+\r
+static void FreeBuffer(char *Buffer)\r
+ {\r
+ if (Buffer == 0)\r
+ return;\r
+\r
+ for (unsigned i = 0; i < g_PathBufferSize; ++i)\r
+ {\r
+ PathBuffer *PB = g_PathBuffers[i];\r
+ if (PB->Buffer == Buffer)\r
+ {\r
+ asserta(PB->InUse);\r
+ PB->InUse = false;\r
+ return;\r
+ }\r
+ }\r
+\r
+ Die("FreeBuffer, not found");\r
+ }\r
+\r
+void PathData::Alloc(unsigned MaxLen)\r
+ {\r
+ if (MaxLen < Bytes)\r
+ return;\r
+\r
+ StartTimer(PathAlloc);\r
+ if (Bytes > 0)\r
+ {\r
+ FreeBuffer(Front);\r
+ }\r
+\r
+ Bytes = MaxLen + 1;\r
+ Front = AllocBuffer(Bytes);\r
+ Back = Front + Bytes - 1;\r
+ Start = 0;\r
+ EndTimer(PathAlloc);\r
+ }\r
+\r
+void PathData::Free()\r
+ {\r
+ FreeBuffer(Front);\r
+ Front = 0;\r
+ Start = 0;\r
+ Back = 0;\r
+ }\r
+\r
+void PathData::Copy(const PathData &rhs)\r
+ {\r
+ Alloc(rhs.Bytes);\r
+ strcpy(Front, rhs.Front);\r
+ Start = Front + (rhs.Start - rhs.Front);\r
+ }\r
+\r
+void PathData::FromStr(const char *PathStr)\r
+ {\r
+ asserta(PathStr != 0);\r
+ unsigned NeededBytes = (unsigned) strlen(PathStr) + 1;\r
+ Alloc(NeededBytes);\r
+ strcpy(Front, PathStr);\r
+ Start = Front;\r
+ }\r
+\r
+void LogPathStats()\r
+ {\r
+ Log("\n");\r
+ unsigned Bytes = 0;\r
+ for (unsigned i = 0; i < g_PathBufferSize; ++i)\r
+ {\r
+ const PathBuffer *PB = g_PathBuffers[i];\r
+ Bytes += PB->Size;\r
+ }\r
+ Log("%u paths allocated, total memory %u bytes\n", g_PathBufferSize, Bytes);\r
+ }\r