2 * PROJECT: .inf file parser
3 * LICENSE: GPL - See COPYING in the top level directory
4 * COPYRIGHT: Copyright 2005 Ge van Geldorp <gvg@reactos.org>
7 /* INCLUDES *****************************************************************/
14 #define EOL _T("\r\n")
17 typedef struct _OUTPUTBUFFER
24 } OUTPUTBUFFER
, *POUTPUTBUFFER
;
27 Output(POUTPUTBUFFER OutBuf
, PCTSTR Text
)
34 if (! INF_SUCCESS(OutBuf
->Status
))
40 Length
= (ULONG
)_tcslen(Text
);
41 if (OutBuf
->FreeSize
< Length
+ 1 && INF_SUCCESS(OutBuf
->Status
))
43 DPRINT("Out of free space. TotalSize %u FreeSize %u Length %u\n",
44 (UINT
)OutBuf
->TotalSize
, (UINT
)OutBuf
->FreeSize
, (UINT
)Length
);
45 /* Round up to next SIZE_INC */
46 NewSize
= OutBuf
->TotalSize
+
47 (((Length
+ 1) - OutBuf
->FreeSize
+ (SIZE_INC
- 1)) /
49 DPRINT("NewSize %u\n", (UINT
)NewSize
);
50 NewBuf
= MALLOC(NewSize
);
54 DPRINT1("MALLOC() failed\n");
55 OutBuf
->Status
= INF_STATUS_NO_MEMORY
;
59 /* Need to copy old contents? */
60 if (NULL
!= OutBuf
->Buffer
)
62 DPRINT("Copying %u bytes from old content\n",
63 (UINT
)(OutBuf
->TotalSize
- OutBuf
->FreeSize
));
64 MEMCPY(NewBuf
, OutBuf
->Buffer
, OutBuf
->TotalSize
- OutBuf
->FreeSize
);
65 OutBuf
->Current
= NewBuf
+ (OutBuf
->Current
- OutBuf
->Buffer
);
70 OutBuf
->Current
= NewBuf
;
72 OutBuf
->Buffer
= NewBuf
;
73 OutBuf
->FreeSize
+= NewSize
- OutBuf
->TotalSize
;
74 OutBuf
->TotalSize
= NewSize
;
75 DPRINT("After reallocation TotalSize %u FreeSize %u\n",
76 (UINT
)OutBuf
->TotalSize
, (UINT
)OutBuf
->FreeSize
);
79 /* We're guaranteed to have enough room now. Copy char by char because of
80 possible "conversion" from Unicode to Ansi */
83 *OutBuf
->Current
++ = (char) *Text
++;
86 *OutBuf
->Current
= '\0';
90 InfpBuildFileBuffer(PINFCACHE Cache
,
95 PINFCACHESECTION CacheSection
;
96 PINFCACHELINE CacheLine
;
97 PINFCACHEFIELD CacheField
;
101 OutBuf
.Buffer
= NULL
;
102 OutBuf
.Current
= NULL
;
104 OutBuf
.TotalSize
= 0;
105 OutBuf
.Status
= INF_STATUS_SUCCESS
;
107 /* Iterate through list of sections */
108 CacheSection
= Cache
->FirstSection
;
109 while (CacheSection
!= NULL
)
111 DPRINT("Processing section " STRFMT
"\n", CacheSection
->Name
);
112 if (CacheSection
!= Cache
->FirstSection
)
114 Output(&OutBuf
, EOL
);
116 Output(&OutBuf
, _T("["));
117 Output(&OutBuf
, CacheSection
->Name
);
118 Output(&OutBuf
, _T("]"));
119 Output(&OutBuf
, EOL
);
121 /* Iterate through list of lines */
122 CacheLine
= CacheSection
->FirstLine
;
123 while (CacheLine
!= NULL
)
125 if (NULL
!= CacheLine
->Key
)
127 DPRINT("Line with key " STRFMT
"\n", CacheLine
->Key
);
128 Output(&OutBuf
, CacheLine
->Key
);
129 Output(&OutBuf
, _T(" = "));
133 DPRINT("Line without key\n");
136 /* Iterate through list of lines */
137 CacheField
= CacheLine
->FirstField
;
138 while (CacheField
!= NULL
)
140 if (CacheField
!= CacheLine
->FirstField
)
142 Output(&OutBuf
, _T(","));
144 p
= CacheField
->Data
;
146 while (_T('\0') != *p
&& ! NeedQuotes
)
148 NeedQuotes
= (BOOLEAN
)(_T(',') == *p
|| _T(';') == *p
||
154 Output(&OutBuf
, _T("\""));
155 Output(&OutBuf
, CacheField
->Data
);
156 Output(&OutBuf
, _T("\""));
160 Output(&OutBuf
, CacheField
->Data
);
163 /* Get the next field */
164 CacheField
= CacheField
->Next
;
167 Output(&OutBuf
, EOL
);
168 /* Get the next line */
169 CacheLine
= CacheLine
->Next
;
172 /* Get the next section */
173 CacheSection
= CacheSection
->Next
;
176 if (INF_SUCCESS(OutBuf
.Status
))
178 *Buffer
= OutBuf
.Buffer
;
179 *BufferSize
= OutBuf
.TotalSize
- OutBuf
.FreeSize
;
181 else if (NULL
!= OutBuf
.Buffer
)
186 return INF_STATUS_SUCCESS
;
190 InfpFindOrAddSection(PINFCACHE Cache
,
192 PINFCONTEXT
*Context
)
194 DPRINT("InfpFindOrAddSection section " STRFMT
"\n", Section
);
196 *Context
= MALLOC(sizeof(INFCONTEXT
));
197 if (NULL
== *Context
)
199 DPRINT1("MALLOC() failed\n");
200 return INF_STATUS_NO_MEMORY
;
203 (*Context
)->Inf
= Cache
;
204 (*Context
)->Section
= InfpFindSection(Cache
, Section
);
205 (*Context
)->Line
= NULL
;
206 if (NULL
== (*Context
)->Section
)
208 DPRINT("Section not found, creating it\n");
209 (*Context
)->Section
= InfpAddSection(Cache
, Section
);
210 if (NULL
== (*Context
)->Section
)
212 DPRINT("Failed to create section\n");
214 return INF_STATUS_NO_MEMORY
;
218 return INF_STATUS_SUCCESS
;
222 InfpAddLineWithKey(PINFCONTEXT Context
, PCTSTR Key
)
226 DPRINT1("Invalid parameter\n");
227 return INF_STATUS_INVALID_PARAMETER
;
230 Context
->Line
= InfpAddLine(Context
->Section
);
231 if (NULL
== Context
->Line
)
233 DPRINT("Failed to create line\n");
234 return INF_STATUS_NO_MEMORY
;
237 if (NULL
!= Key
&& NULL
== InfpAddKeyToLine(Context
->Line
, Key
))
239 DPRINT("Failed to add key\n");
240 return INF_STATUS_NO_MEMORY
;
243 return INF_STATUS_SUCCESS
;
247 InfpAddField(PINFCONTEXT Context
, PCTSTR Data
)
249 if (NULL
== Context
|| NULL
== Context
->Line
)
251 DPRINT1("Invalid parameter\n");
252 return INF_STATUS_INVALID_PARAMETER
;
255 if (NULL
== InfpAddFieldToLine(Context
->Line
, Data
))
257 DPRINT("Failed to add field\n");
258 return INF_STATUS_NO_MEMORY
;
261 return INF_STATUS_SUCCESS
;