OSDN Git Service

crystaledit: Make almost the same code into a common function
[winmerge-jp/winmerge-jp.git] / Externals / crystaledit / editlib / parsers / ini.cpp
1 ///////////////////////////////////////////////////////////////////////////
2 //  File:    ini.cpp
3 //  Version: 1.2
4 //  Updated: 02-Dec-2006
5 //
6 //  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei,
7 //              Tim Gerundt, Kimmo Varis
8 //  E-mail:     prantl@ff.cuni.cz
9 //
10 //  INI syntax highlighing definition
11 //
12 //  You are free to use or modify this code to the following restrictions:
13 //  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
14 //  will be enough. If you can't (or don't want to), contact me personally.
15 //  - LEAVE THIS HEADER INTACT
16 ////////////////////////////////////////////////////////////////////////////
17
18 #include "StdAfx.h"
19 #include "crystallineparser.h"
20 #include "../SyntaxColors.h"
21 #include "../utils/string_util.h"
22
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
27 DWORD
28 CrystalLineParser::ParseLineIni (DWORD dwCookie, const TCHAR *pszChars, int nLength, TEXTBLOCK * pBuf, int &nActualItems)
29 {
30   if (nLength == 0)
31     return dwCookie & COOKIE_EXT_COMMENT;
32
33   bool bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
34   bool bRedefineBlock = true;
35   bool bDecIndex = false;
36   int nIdentBegin = -1;
37   int nPrevI = -1;
38   int I=0;
39   for (I = 0;; nPrevI = I, I = static_cast<int>(::CharNext(pszChars+I) - pszChars))
40     {
41       if (I == nPrevI)
42         {
43           // CharNext did not advance, so we're at the end of the string
44           // and we already handled this character, so stop
45           break;
46         }
47
48       if (bRedefineBlock)
49         {
50           int nPos = I;
51           if (bDecIndex)
52             nPos = nPrevI;
53           if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
54             {
55               DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
56             }
57           else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
58             {
59               DEFINE_BLOCK (nPos, COLORINDEX_STRING);
60             }
61           else if (dwCookie & COOKIE_SECTION)
62             {
63               DEFINE_BLOCK (nPos, COLORINDEX_FUNCNAME);
64             }
65           else if (dwCookie & COOKIE_KEY)
66             {
67               DEFINE_BLOCK (nPos, COLORINDEX_KEYWORD);
68             }
69           else
70             {
71               if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (*::CharPrev(pszChars, pszChars + nPos)) && !xisalpha (*::CharNext(pszChars + nPos))))
72                 {
73                   DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
74                 }
75               else
76                 {
77                   DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
78                   bRedefineBlock = true;
79                   bDecIndex = true;
80                   goto out;
81                 }
82             }
83           bRedefineBlock = false;
84           bDecIndex = false;
85         }
86 out:
87
88       // Can be bigger than length if there is binary data
89       // See bug #1474782 Crash when comparing SQL with with binary data
90       if (I >= nLength || pszChars[I] == 0)
91         break;
92
93       if (dwCookie & COOKIE_COMMENT)
94         {
95           DEFINE_BLOCK (I, COLORINDEX_COMMENT);
96           dwCookie |= COOKIE_COMMENT;
97           break;
98         }
99
100       //  String constant "...."
101       if (dwCookie & COOKIE_STRING)
102         {
103           if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
104             {
105               dwCookie &= ~COOKIE_STRING;
106               bRedefineBlock = true;
107             }
108           continue;
109         }
110
111       //  Char constant '..'
112       if (dwCookie & COOKIE_CHAR)
113         {
114           if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[nPrevI] != '\\' || I >= 2 && (pszChars[nPrevI] != '\\' || *::CharPrev(pszChars, pszChars + nPrevI) == '\\')))
115             {
116               dwCookie &= ~COOKIE_CHAR;
117               bRedefineBlock = true;
118             }
119           continue;
120         }
121
122       // Section header [...]
123       if (dwCookie & COOKIE_SECTION)
124         {
125           if (pszChars[I] == ']')
126             {
127               dwCookie &= ~COOKIE_SECTION;
128               bRedefineBlock = true;
129             }
130           continue;
131         }
132
133       // Key
134       if (dwCookie & COOKIE_KEY)
135         {
136           if (I + 1 < nLength && pszChars[I + 1] == '=')
137             {
138               dwCookie &= ~COOKIE_KEY;
139               bRedefineBlock = true;
140             }
141           continue;
142         }
143
144       //  Normal text
145       if (pszChars[I] == '"')
146         {
147           DEFINE_BLOCK (I, COLORINDEX_STRING);
148           dwCookie |= COOKIE_STRING;
149           continue;
150         }
151       if (pszChars[I] == '\'')
152         {
153           // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
154           if (!I || !xisalnum (pszChars[nPrevI]))
155             {
156               DEFINE_BLOCK (I, COLORINDEX_STRING);
157               dwCookie |= COOKIE_CHAR;
158               continue;
159             }
160         }
161
162       if (bFirstChar)
163         {
164           if (pszChars[I] == ';') // Comment
165             {
166               DEFINE_BLOCK (I, COLORINDEX_COMMENT);
167               dwCookie |= COOKIE_COMMENT;
168               break;
169             }
170           else if (pszChars[I] == '[') // Section header [...]
171             {
172               DEFINE_BLOCK (I, COLORINDEX_FUNCNAME);
173               dwCookie |= COOKIE_SECTION;
174               continue;
175             }
176           else // Key
177             {
178               DEFINE_BLOCK (I, COLORINDEX_KEYWORD);
179               dwCookie |= COOKIE_KEY;
180             }
181           if (!xisspace (pszChars[I]))
182             bFirstChar = false;
183         }
184
185       if (pBuf == nullptr)
186         continue;               //  We don't need to extract keywords,
187       //  for faster parsing skip the rest of loop
188
189       if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[nPrevI]) && !xisalpha (pszChars[I + 1])))
190         {
191           if (nIdentBegin == -1)
192             nIdentBegin = I;
193         }
194       else
195         {
196           if (nIdentBegin >= 0)
197             {
198               if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
199                 {
200                   DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
201                 }
202               bRedefineBlock = true;
203               bDecIndex = true;
204               nIdentBegin = -1;
205             }
206         }
207     }
208
209   if (nIdentBegin >= 0)
210     {
211       if (IsXNumber (pszChars + nIdentBegin, I - nIdentBegin))
212         {
213           DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
214         }
215     }
216
217   dwCookie &= COOKIE_EXT_COMMENT;
218   return dwCookie;
219 }