We're distributing a Cocoa framework with regular updates. We'll be updating the version numbers with each release. The Apple documentation appears to suggest that version numbers should be consecutive incrementing integers. We are distributing output in several formats, and the framework is only one of them. We would rather not have to maintain a separate numbering system just for our frameworks.
We don't really care about the precise format of the version numbers of the framework, so long as they change whenever the product changes, and behave in a correct, sensible and expected manner. I'm looking for a way of avoiding having to run a separate version number counter.
One suggestion is that for product version 12.34.56 we could simply remove the dots and say the framework version is 123456 (with appropriate zero padding).
Is there a constraint on the type of number that can be represented (uint? long?)
Does it have to be a number? Could it be a string?
Do the numbers have to be consecutive?
Is there a standard way of doing things in this situation?
As I understand it, the reason for this requirement is so that you can have macro checks like:
#if FRAMEWORKNAME_VERSION >= 123456
// some stuff
#else
// some other stuff
#endif
The numbers do not need to be consecutive, and your suggested scheme is quite sensible:
#define MAKE_VERSION(MAJOR,MINOR,PATCH) ((MAJOR*10000)+(MINOR*100)+PATCH)
I would also suggest that in addition to defining a version, you also define constants for each version...
#define FRAMEWORKNAME_VERSION_1_0_0 MAKE_VERSION(1,0,0)
#define FRAMEWORKNAME_VERSION_1_0_1 MAKE_VERSION(1,0,1)
That way, you can check in multiple ways... either:
#if FRAMEWORKNAME_VERSION >= MAKE_VERSION(1,0,1)
// 1.0.1 and later
#else
// Before 1.0.1
#endif
Or:
#if defined(FRAMEWORKNAME_VERSION_1_0_1)
// 1.0.1 and later
#else
// Before 1.0.1
#endif
The key requirements that you should satisfy are:
The numbers are monotonically increasing
The numbers are predictable
The numbers are easily comparable
If you want to supply a string representation of your version in addition to the integer representation, by all means go ahead; however, I would strongly suggest that you have an integer representation available, as it simplifies comparison and allows the version to be checked in the preprocessor.
Related
I've noticed that the Tool Help Library offers some functions and structures with 2 versions: normal and ending with W. For example: Process32First and Process32FirstW. Since their documentation is identical, I wonder what are the differences between those two?
The W and A versions stand for "wide" and "ANSI". In the past they made different functions, structures and types for both ANSI and unicode strings. For the purpose of this answer, unicode is widechar which is 2 bytes per character and ANSI is 1 byte per character (but it's actually more complicated than that). By supplying both types, the developer can use whichever he wants but the standard today is to use unicode.
If you look at the ToolHelp32 header file it does include both A and W versions of the structures and functions. If you're not finding them, you're not looking hard enough, do an explicit search for the identifiers and you will find them. If you're just doing "view definition" you will find the #ifdef macros. If you still can't find them, change your character set in your Visual Studio project and check again.
Due to wide char arrays being twice the size, structure alignment will be incorrect if you do not use the correct types. Let the macros resolve them for you, by setting the correct character set and using PROCESSENTRY32 instead of indicating A or W, this is the preferred method. Some APIs you are better off using the ANSI version to be honest but that is something you will learn with experience and have to make your own decision.
Here is an excellent article on the topic of character sets / encoding
When I used #define INF (1.0/0.0) to define infinite number, it called the error C2124, which means that a constant expression has a zero denominator. It was told that do not divide by zero can avoid it. But I really need to define inifite number, could someone give a simple way to solve it?
Not sure if it works in VS, especially such an old version, but STL has special provision for that:
double never = std::numeric_limits<double>::infinity();
The C++ standard way is to utilize the function std::numeric_limits<double>::infinity() in the <limits> library.
This is also only meaningful if std::numeric_limits<double>::has_infinity is true (which it usually will be).
I would like three lines of code not to be included if compiled after a certain date.
The reason being is they provide backwards compatibility. To support a staggered release between client and embedding it is required to be there now.
Once the next software release comes along this support is to be dropped to force customers to upgrade the embedded software. Since this is a few months away there is risk of these lines being forgotten.
So ideally I would like a
#if __DATE__ > MyDate
code here
#endif
or something equivalent.
Is there any way of doing this?
*The code is compiled with GCC
This solution is specifically for Windows platform and is something I use in production.
I exploit the environment variable %DATE%, and in a batch file used to launch my IDE, I have VA_CURRENT_DATE=%DATE:~6,4%%DATE:~3,2%%DATE:~0,2% (which transforms to an ISO8601 date for my specific locale).
Then in my preprocessor definitions for my project I define VA_BUILD_DATE to VA_CURRENT_DATE
Then I have some code like:
long day = VA_BUILD_DATE;
long year = day / 10000;
day -= year * 10000;
long month = day / 100;
day -= month * 100;
You can't do this with __DATE__, because it expands to a string constant, and string constants can't be used in #if. Also, setting a fixed date is a bad idea, because you may need to do bug-fix releases to the older version that should preserve the backward compatibility.
(Do you really need to drop backward compatibility? If it's only three lines of code, consider just keeping them around forever. Your customers will not thank you for "forcing them to upgrade.")
The good way to do this sort of thing is via your version control system. You should be maintaining a branch for each release anyway, so write your code like this:
#ifdef BACKWARD_COMPAT_VERSION_1_0
compatibility code here
#endif
and then change the Makefile on the release branch, only, to include -DBACKWARD_COMPAT_VERSION_1_0 in your CFLAGS.
Now I am running the risk of not answering your question directly. But I'd take the risk and suggest you NOT to do so. How many times does a project get released on time? The date is, too prone to change. And you never know that.
Why not use the version of your project instead?
// Only defined in old projects that you want this legacy code in.
#ifdef OLD__VERSION
code here
#endif
Unfortunately this won't work as __DATE__ produces a string in the form "Sep 5 2013", which is useless for comparison.
Ideally the compiler should support a constant like __DATEFLAT__ which produces an integer like 20130905, which would be ideal for such as task. However this doesn't exist.
In the file file.h, following code is seen.
#ifndef FILE_H
#define FILE_H
...
...
#endif
QUESTION: Who generated FILE_H (is FILE_H called identifier?) What is this naming convention called? What I should read to understand more of this?
At the moment, I know this is called include guard, and stuff to do with preprocessor. But I can't seem to google futher. Any links would be highly appreciated.
Include guards are not actually a feature of the language itself, they're just a way to ensure the same header file isn't included twice into the same translation unit, and they're built from lower-level language features.
The actual features that make this possible are macro replacement (specifically object-like macros) and conditional inclusion.
Hence, to find out where the FILE_H comes from, you need to examine two things.
The first is the limitations imposed by the standard (C11 6.4.2 for example). In macro replacement, the macro name must be drawn from a limited character set, the minimum of which includes the upper and lower case letters, the underscore, and the digits (there are all sorts of extras that can be allowed, such as universal character names or other implementation-defined characters but this is the mandated baseline).
The second is the mind of the developer. Beyond the constraints of the standard, the developer must provide a unique identifier used for the include guard and the easiest way to do this is to make it reliant somehow on the file name itself. Hence, one practice is to use the uppercase file name with . replaced by an underscore.
That's why you'll end up with an include guard for btree.h being of the form:
#ifndef BTREE_H
#define BTREE_H
// weave your magic here
#endif
You should keep in mind however that it doesn't always work out well. Sometimes you may end up with two similarly named header files that use the same include guard name, resulting in one of the header files not being included at all. This happens infrequently enough that it's usually not worth being concerned about.
I'm trying to take a numeric value in a string and raise it by a power of 10. stumbled upon – decimalNumberByMultiplyingByPowerOf10:withBehavior: which looks promising but I can't for the life of me figure out how to configure/set the withBehavior argument. I think I need to set it to NSRoundDown so when raising to negative power it won't round 'up' some values below a certain number of decimal places...but how does one set/use this NSDecimalNumberBehaviors gizmo? Sure wish Apple provided some examples in their docs...
Check out NSDecimalNumberHandler. It conforms to the NSDecimalNumberBehaviors protocol, as required by the API, and allows you to configure all the behaviors you're likely to need.