lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / jvmfwk / plugins / sunmajor / pluginlib / sunversion.cxx
blob7711a9e79907e2362fd2d503770343f80cc9d020
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "sunversion.hxx"
22 #include <osl/diagnose.h>
23 #include <osl/thread.h>
24 #include <osl/process.h>
25 #include <osl/security.hxx>
26 #include <rtl/character.hxx>
27 #include <string.h>
28 #include "diagnostics.h"
29 using namespace osl;
31 namespace jfw_plugin { //stoc_javadetect
34 #if OSL_DEBUG_LEVEL >= 2
35 class SelfTest
37 public:
38 SelfTest();
39 } test;
40 #endif
42 SunVersion::SunVersion(const OUString &usVer):
43 m_nUpdateSpecial(0), m_preRelease(Rel_NONE),
44 usVersion(usVer)
46 memset(m_arVersionParts, 0, sizeof(m_arVersionParts));
47 OString sVersion= OUStringToOString(usVer, osl_getThreadTextEncoding());
48 m_bValid = init(sVersion.getStr());
50 SunVersion::SunVersion(const char * szVer):
51 m_nUpdateSpecial(0), m_preRelease(Rel_NONE)
53 memset(m_arVersionParts, 0, sizeof(m_arVersionParts));
54 m_bValid = init(szVer);
55 usVersion= OUString(szVer,strlen(szVer),osl_getThreadTextEncoding());
59 /**Format major.minor.maintenance_update
61 bool SunVersion::init(const char *szVersion)
63 if (!szVersion || szVersion[0] == '\0')
64 return false;
66 //first get the major,minor,maintenance
67 const char * pLast = szVersion;
68 const char * pCur = szVersion;
69 //pEnd point to the position after the last character
70 const char * pEnd = szVersion + strlen(szVersion);
71 // 0 = major, 1 = minor, 2 = maintenance, 3 = update
72 int nPart = 0;
73 // position within part beginning with 0
74 int nPartPos = 0;
75 char buf[128];
77 //char must me a number 0 - 999 and no leading
78 while (true)
80 if (pCur < pEnd && rtl::isAsciiDigit(static_cast<unsigned char>(*pCur)))
82 pCur ++;
83 nPartPos ++;
85 //if correct separator then form integer
86 else if (
87 (nPartPos != 0) // prevents: ".4.1", "..1", part must start with digit
88 && (
89 //separators after maintenance (1.4.1_01, 1.4.1-beta, or 1.4.1)
90 (pCur == pEnd || *pCur == '_' || *pCur == '-')
92 //separators between major-minor and minor-maintenance
93 (nPart < 2 && *pCur == '.') )
94 && (
95 //prevent 1.4.0. 1.4.0-
96 pCur + 1 != pEnd
97 || rtl::isAsciiDigit(static_cast<unsigned char>(*pCur))) )
99 bool afterMaint = pCur == pEnd || *pCur == '_' || *pCur == '-';
101 int len = pCur - pLast;
102 if (len >= 127)
103 return false;
105 strncpy(buf, pLast, len);
106 buf[len] = 0;
107 pCur ++;
108 pLast = pCur;
110 m_arVersionParts[nPart] = atoi(buf);
112 if (afterMaint)
113 nPart = 2;
114 nPart ++;
115 nPartPos = 0;
116 if (nPart == 3)
117 break;
119 //check next character
120 if (! ( (pCur < pEnd)
121 && ( (nPart < 3)
122 && rtl::isAsciiDigit(
123 static_cast<unsigned char>(*pCur)))))
124 return false;
126 else
128 return false;
131 if (pCur >= pEnd)
132 return true;
133 //We have now 1.4.1. This can be followed by _01, -beta, etc.
134 // _01 (update) According to docu must not be followed by any other
135 //characters, but on Solaris 9 we have a 1.4.1_01a!!
136 if (* (pCur - 1) == '_')
137 {// _01, _02
138 // update is the last part _01, _01a, part 0 is the digits parts and 1 the trailing alpha
139 while (true)
141 if (pCur <= pEnd)
143 if ( ! rtl::isAsciiDigit(static_cast<unsigned char>(*pCur)))
145 //1.8.0_102-, 1.8.0_01a,
146 size_t len = pCur - pLast;
147 if (len > sizeof(buf) - 1)
148 return false;
149 //we've got the update: 01, 02 etc
150 strncpy(buf, pLast, len);
151 buf[len] = 0;
152 m_arVersionParts[nPart] = atoi(buf);
153 if (pCur == pEnd)
155 break;
157 if (*pCur == 'a' && (pCur + 1) == pEnd)
159 //check if it s followed by a simple "a" (not specified)
160 m_nUpdateSpecial = *pCur;
161 break;
163 else if (*pCur == '-' && pCur < pEnd)
165 //check 1.5.0_01-ea
166 PreRelease pr = getPreRelease(++pCur);
167 if (pr == Rel_NONE)
168 return false;
169 //just ignore -ea because its no official release
170 break;
172 else
174 return false;
177 if (pCur < pEnd)
178 pCur ++;
179 else
180 break;
184 // 1.4.1-ea
185 else if (*(pCur - 1) == '-')
187 m_preRelease = getPreRelease(pCur);
188 if (m_preRelease == Rel_NONE)
189 return false;
190 #if defined(FREEBSD)
191 if (m_preRelease == Rel_FreeBSD)
193 pCur++; //eliminate 'p'
194 if (pCur < pEnd
195 && rtl::isAsciiDigit(static_cast<unsigned char>(*pCur)))
196 pCur ++;
197 int len = pCur - pLast -1; //eliminate 'p'
198 if (len >= 127)
199 return false;
200 strncpy(buf, (pLast+1), len); //eliminate 'p'
201 buf[len] = 0;
202 m_nUpdateSpecial = atoi(buf)+100; //hack for FBSD #i56953#
203 return true;
205 #endif
207 else
209 return false;
211 return true;
214 SunVersion::PreRelease SunVersion::getPreRelease(const char *szRelease)
216 if (szRelease == nullptr)
217 return Rel_NONE;
218 if( ! strcmp(szRelease,"internal"))
219 return Rel_INTERNAL;
220 else if( ! strcmp(szRelease,"ea"))
221 return Rel_EA;
222 else if( ! strcmp(szRelease,"ea1"))
223 return Rel_EA1;
224 else if( ! strcmp(szRelease,"ea2"))
225 return Rel_EA2;
226 else if( ! strcmp(szRelease,"ea3"))
227 return Rel_EA3;
228 else if ( ! strcmp(szRelease,"beta"))
229 return Rel_BETA;
230 else if ( ! strcmp(szRelease,"beta1"))
231 return Rel_BETA1;
232 else if ( ! strcmp(szRelease,"beta2"))
233 return Rel_BETA2;
234 else if ( ! strcmp(szRelease,"beta3"))
235 return Rel_BETA3;
236 else if (! strcmp(szRelease, "rc"))
237 return Rel_RC;
238 else if (! strcmp(szRelease, "rc1"))
239 return Rel_RC1;
240 else if (! strcmp(szRelease, "rc2"))
241 return Rel_RC2;
242 else if (! strcmp(szRelease, "rc3"))
243 return Rel_RC3;
244 #if defined (FREEBSD)
245 else if (! strncmp(szRelease, "p", 1))
246 return Rel_FreeBSD;
247 #endif
248 else
249 return Rel_NONE;
252 SunVersion::~SunVersion()
257 /* Examples:
258 a) 1.0 < 1.1
259 b) 1.0 < 1.0.0
260 c) 1.0 < 1.0_00
262 returns false if both values are equal
264 bool SunVersion::operator > (const SunVersion& ver) const
266 if( &ver == this)
267 return false;
269 //compare major.minor.maintenance
270 for( int i= 0; i < 4; i ++)
272 // 1.4 > 1.3
273 if(m_arVersionParts[i] > ver.m_arVersionParts[i])
275 return true;
277 else if (m_arVersionParts[i] < ver.m_arVersionParts[i])
279 return false;
282 //major.minor.maintenance_update are equal. Test for a trailing char
283 if (m_nUpdateSpecial > ver.m_nUpdateSpecial)
285 return true;
288 //Until here the versions are equal
289 //compare pre -release values
290 if ((m_preRelease == Rel_NONE && ver.m_preRelease == Rel_NONE)
292 (m_preRelease != Rel_NONE && ver.m_preRelease == Rel_NONE))
293 return false;
294 else if (m_preRelease == Rel_NONE && ver.m_preRelease != Rel_NONE)
295 return true;
296 else if (m_preRelease > ver.m_preRelease)
297 return true;
299 return false;
302 bool SunVersion::operator < (const SunVersion& ver) const
304 return (! operator > (ver)) && (! operator == (ver));
307 bool SunVersion::operator == (const SunVersion& ver) const
309 bool bRet= true;
310 for(int i= 0; i < 4; i++)
312 if( m_arVersionParts[i] != ver.m_arVersionParts[i])
314 bRet= false;
315 break;
318 bRet = m_nUpdateSpecial == ver.m_nUpdateSpecial && bRet;
319 bRet = m_preRelease == ver.m_preRelease && bRet;
320 return bRet;
324 #if OSL_DEBUG_LEVEL >= 2
325 SelfTest::SelfTest()
327 bool bRet = true;
329 static char const * versions[] = {"1.4.0", "1.4.1", "1.0.0", "10.0.0", "10.10.0",
330 "10.2.2", "10.10.0", "10.10.10", "111.0.999",
331 "1.4.1_01", "9.90.99_09", "1.4.1_99",
332 "1.4.1_00a",
333 "1.4.1-ea", "1.4.1-beta", "1.4.1-rc1",
334 "1.5.0_01-ea", "1.5.0_01-rc2"};
335 static char const * badVersions[] = {".4.0", "..1", "", "10.0", "10.10.0.", "10.10.0-", "10.10.0.",
336 "10.2-2", "10_10.0", "10..10","10.10", "a.0.999",
337 "1.4b.1_01", "9.90.-99_09", "1.4.1_99-",
338 "1.4.1_00a2", "1.4.0_z01z", "1.4.1__99A",
339 "1.4.1-1ea", "1.5.0_010", "1.5.0._01-", "1.5.0_01-eac"};
340 static char const * orderedVer[] = { "1.3.1-ea", "1.3.1-beta", "1.3.1-rc1",
341 "1.3.1", "1.3.1_00a", "1.3.1_01", "1.3.1_01a",
342 "1.3.2", "1.4.0", "1.5.0_01-ea", "2.0.0"};
344 int num = SAL_N_ELEMENTS (versions);
345 int numBad = SAL_N_ELEMENTS (badVersions);
346 int numOrdered = SAL_N_ELEMENTS (orderedVer);
347 //parsing test (positive)
348 for (int i = 0; i < num; i++)
350 SunVersion ver(versions[i]);
351 if ( ! ver)
353 bRet = false;
354 break;
357 OSL_ENSURE(bRet, "SunVersion selftest failed");
358 //Parsing test (negative)
359 for ( int i = 0; i < numBad; i++)
361 SunVersion ver(badVersions[i]);
362 if (ver)
364 bRet = false;
365 break;
368 OSL_ENSURE(bRet, "SunVersion selftest failed");
370 // Ordering test
371 bRet = true;
372 int j = 0;
373 for (int i = 0; i < numOrdered; i ++)
375 SunVersion curVer(orderedVer[i]);
376 if ( ! curVer)
378 bRet = false;
379 break;
381 for (j = 0; j < numOrdered; j++)
383 SunVersion compVer(orderedVer[j]);
384 if (i < j)
386 if ( !(curVer < compVer))
388 bRet = false;
389 break;
392 else if ( i == j)
394 if (! (curVer == compVer
395 && ! (curVer > compVer)
396 && ! (curVer < compVer)))
398 bRet = false;
399 break;
402 else if (i > j)
404 if ( !(curVer > compVer))
406 bRet = false;
407 break;
411 if ( ! bRet)
412 break;
414 if (bRet)
415 JFW_TRACE2("Testing class SunVersion succeeded.");
416 else
417 OSL_ENSURE(bRet, "[Java framework] sunjavaplugin: SunVersion self test failed.");
419 #endif
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */