Programming


Fedora install JDK (OpenJDK) 2

As we were setting up a machine that would be used for software development, we came to the need of installing a Java Development Kit (JDK).
There are two popular choices on the web between the OpenJDK and the Oracle JDK, we decided to go with the OpenJDK option which is a free and open source implementation of the Java Platform and it is part of the official Fedora repositories.

To install the OpenJDK along with all the needed libraries for development we used the following command:

sudo dnf install java-1.8.0-openjdk java-1.8.0-openjdk-devel;

On our GNU/Linux Fedora the installation folder of the JDK was /usr/lib/jvm/java-1.8.0-openjdk.

 


Count how many submissions per score

Recently, we had access to a database that contained the scores of a programming competitions system.
The database contained several contests, each contest contained several challenges and any competitor could make multiple submissions.
We wanted to extract a couple of charts showing

  • how many submissions we had per score and
  • how many submissions we had per score while filtering out the best submission (max score) per contestant per challenge per contest

The following code will return the number of submissions per score per challenge per contest.

SELECT contest_id, challenge_id, TRUNCATE(score, 1), COUNT(*)
FROM submissions
GROUP BY contest_id, challenge_id, TRUNCATE(score, 1)
ORDER BY contest_id, challenge_id, TRUNCATE(score, 1);

The next one will return the number of submissions per score per challenge per contest while filtering out the best submission (max score) per contestant per challenge per contest:

SELECT contest_id, challenge_id, TRUNCATE(max_score, 1), COUNT(*)
FROM
(
  SELECT contest_id, challenge_id, competitor_id, MAX(score) AS max_score
  FROM submissions
  GROUP BY contest_id, challenge_id, competitor_id
) AS max_scores
GROUP BY contest_id, challenge_id, TRUNCATE(max_score, 1)
ORDER BY contest_id, challenge_id, TRUNCATE(max_score, 1);


Converting a (void*) buffer to a std::vector

On a project we were recently working on, some legacy C code was producing a (void*) voidBuffer accompanied by its size.
The rest of the project was in C++ and we needed to convert the (void*) voidBuffer to a std::vector<unsigned char> vector.

To do so, we used the following code:

//First cast the (void *) voidBuffer to an (unsigned char *) to implicitly get the element size (1 Byte each)
const unsigned char *charBuffer = (unsigned char *) voidBuffer;
//Then we create the vector (named vectorBuffer) by copying the contents of charBuffer to the vector
std::vector<unsigned char> vectorBuffer(charBuffer, charBuffer + length);

Converting a (void*) buffer to a std::vector Example (compressed) (4 downloads)


Remove all non digit characters from String

The following Java snippet removes all non-digit characters from a String.
Non-digit characters are any characters that are not in the following set [0, 1, 2, 3, 4 ,5 ,6 ,7 ,8, 9].

myString.replaceAll("\\D", "");

For a summary of regular-expression constructs and information on the character classes supported by Java pattern visit the following link.

The \\D pattern that we used in our code is a predefined character class for non-digit characters. It is equivalent to [^0-9]that negates the predefined character class for digit characters [0-9].


Java: remove leading character (or any prefix) from String only if it matches

The following snippet allows you to check if a String in Java starts with a specific character (or a specific prefix) that you are looking for and remove it.
To keep the number of lines small, we used the Java ?: ternary operator, which defines a conditional expression in a compact way.
Then, to quickly check if the first character(s) is the one we are looking for before removing it we used the String.startsWith().
To compute the number of characters to remove we used the String.length() on the needle.
Finally, to strip the leading character(s) we used String.substring() whenever the prefix matched.

final String needle = "//";
final int needleSize = needle.length();
String haystack = "";
haystack = haystack.startsWith(needle) ? haystack.substring(needleSize) : haystack;
System.out.print(haystack);

haystack = "apple";
haystack = haystack.startsWith(needle) ? haystack.substring(needleSize) : haystack;
System.out.println(haystack);

haystack = "//banana";
haystack = haystack.startsWith(needle) ? haystack.substring(needleSize) : haystack;
System.out.println(haystack);

The above code will result in the following:

apple
banana

 

Bonus: to remove all the instances of a character anywhere in a string:

final String needle = "a";
final int needleSize = needle.length();
String haystack = "banana";
haystack = haystack.replace(needle,"");
System.out.println(haystack);

The above code will result in the following:

bnn

Bonus: to remove the first instance of a character anywhere in a string:

final String needle = "a";
final int needleSize = needle.length();
String haystack = "banana";
haystack = haystack.replaceFirst(needle,"");
System.out.println(haystack);

The above code will result in the following:

bnana

Android Studio – No space left on device 2

Recently we tried to install some packages from the Android SDK through Android Studio 3.0.1 and we got the error that the PC ran out of space while downloading the necessary packages and could not perform the operation.

Full Error Log:

To install:
- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)
Preparing "Install Google APIs Intel x86 Atom System Image (revision: 2)".
Downloading https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r02.zip
An error occurred while preparing SDK package Google APIs Intel x86 Atom System Image: Cannot download 'https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r02.zip': No space left on device
, response: 200 OK.
"Install Google APIs Intel x86 Atom System Image (revision: 2)" failed.
Failed packages:
- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)

Although the disk had a lot of free space, we got this error because the /tmp partition on our GNU/Linux Fedora 27 workstation was too small (~4GB).

$ df -h;
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 107M 3.8G 3% /dev/shm
tmpfs 3.9G 1.9M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/fedora-root 50G 35G 12G 75% /
tmpfs 3.9G 2.1M 3.9G 1% /tmp
/dev/sdb1 477M 179M 269M 41% /boot
/dev/mapper/fedora-home 178G 37G 132G 22% /home
tmpfs 794M 16K 794M 1% /run/user/42
tmpfs 794M 9.2M 785M 2% /run/user/1000

/tmp was not explicitly set so it was automatically configured to have half of the size of the RAM.
We didn’t not want to change the download path for the Java environment (and hence Android Studio and Android SDK tools) as after leaving the tmpfs folder it could mean that we would have to manually maintain the new path and clean it up. So we ended up in temporarily increasing the size of /tmp partition which did the trick and the virtual device was installed successfully.

Solution – temporarily increase the size of the /tmp partition:

The command we used to increase the size of the /tmp partition on Fedora 27 was the following:

sudo mount -o remount,size=8G,noatime /tmp;

After executing we, it we immediately saw that the results were applied without the need for a restart or any other operation and we could proceed to use the PC as normal.

$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 89M 3.8G 3% /dev/shm
tmpfs 3.9G 1.9M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/fedora-root 50G 35G 12G 75% /
tmpfs 8.0G 2.0M 8.0G 1% /tmp
/dev/sdb1 477M 179M 269M 41% /boot
/dev/mapper/fedora-home 178G 37G 132G 22% /home
tmpfs 794M 16K 794M 1% /run/user/42
tmpfs 794M 6.9M 787M 1% /run/user/1000

The information for tmpfs we got it from: https://wiki.archlinux.org/index.php/Tmpfs

Full Correct Execution Log:

To install:
- Google APIs Intel x86 Atom System Image (system-images;android-27;google_apis;x86)
Preparing "Install Google APIs Intel x86 Atom System Image (revision: 2)".
Downloading https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r02.zip
"Install Google APIs Intel x86 Atom System Image (revision: 2)" ready.
Installing Google APIs Intel x86 Atom System Image in /home/xeirwn/Android/Sdk/system-images/android-27/google_apis/x86
"Install Google APIs Intel x86 Atom System Image (revision: 2)" complete.
"Install Google APIs Intel x86 Atom System Image (revision: 2)" finished.


Manually set the CMake output folder

If you want to manually set the global output folder for you whole CMake project and depending on the output you expect add the following configuration lines in the root CMakeLists.txt file of your project:

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

In case you wan to specify those folders per target, you can update them as follows:

set_target_properties( target_or_targets
  PROPERTIES
  ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
  LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

Please note that we are setting the same properties using different variables.

The CMAKE_ARCHIVE_OUTPUT_DIRECTORY variable is used to initialize the ARCHIVE_OUTPUT_DIRECTORY property on all the targets.
ARCHIVE_OUTPUT_DIRECTORY property specifies the directory into which archive target files should be built.
An archive output artifact of a buildsystem target may be:

  • The static library file (e.g. .lib or .a) of a static library target created by the add_library() command with the STATIC option.
  • On DLL platforms: the import library file (e.g. .lib) of a shared library target created by the add_library() command with the SHARED option.
  • On DLL platforms: the import library file (e.g. .lib) of an executable target created by the add_executable() command when its ENABLE_EXPORTS target property is set.

 

The CMAKE_LIBRARY_OUTPUT_DIRECTORY variable is used to initialize the LIBRARY_OUTPUT_DIRECTORY property on all the targets.
LIBRARY_OUTPUT_DIRECTORY property specifies the directory into which library target files should be built.
A library output artifact of a buildsystem target may be:
The loadable module file (e.g. .dll or .so) of a module library target created by the add_library() command with the MODULE option.
On non-DLL platforms: the shared library file (e.g. .so or .dylib) of a shared shared library target created by the add_library() command with the SHARED option.

 

The CMAKE_RUNTIME_OUTPUT_DIRECTORY variable is used to initialize the RUNTIME_OUTPUT_DIRECTORY property on all the targets.
RUNTIME_OUTPUT_DIRECTORY property specifies the directory into which runtime target files should be built.
A runtime output artifact of a buildsystem target may be:

  • The executable file (e.g. .exe) of an executable target created by the add_executable() command.
  • On DLL platforms: the executable file (e.g. .dll) of a shared library target created by the add_library() command with the SHARED option.

From: https://cmake.org/documentation/


Two ways to append a new argument to CMAKE_ARGS list for ExternalProject_Add

Recently, we wanted to pass a new cached value to an external project in CMake via the CMAKE_ARGS variable.

CMAKE_ARGS holds various types of arguments. From which, the arguments in the form -Dname:type=value are passed to the CMake command line and cannot be changed by the user.

We found two ways to add a new argument pair to the CMAKE_ARGS of the external project.

The first method uses the set function:

set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR}${CACHE_VAR_TYPE}=\"${${CACHE_VAR}}\"")

where basically we create a new string that starts with the existing value of CMAKE_ARGS and then we append to its end the new pair.

The second method uses the list function:

list(APPEND CMAKE_ARGS "-D${CACHE_VAR}${CACHE_VAR_TYPE}=${${CACHE_VAR}}")

that treats CMAKE_ARGS as a list and it appends to its end the new pair.

To verify by hand that they were equivalent we did the following small test with success

#Copy the original value of ${CMAKE_ARGS}
set(CMAKE_ARGS_ORIGINAL ${CMAKE_ARGS})

#Define the Name, Type and Value for the new argument pairs
set(CACHE_VAR_P_NAME PRODUCTS_DIR)
set(CACHE_VAR_P_TYPE string)
set(CACHE_VAR_P_VALUE "someplace/with spaces")

set(CACHE_VAR_C_NAME CLIENTS_DIR)
set(CACHE_VAR_C_TYPE string)
set(CACHE_VAR_C_VALUE "another/place")

#Print the original value of ${CMAKE_ARGS}
MESSAGE(STATUS "CMAKE_ARGS: '" ${CMAKE_ARGS} "'")

#Append the two pairs to ${CMAKE_ARGS} using set
set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR_P_NAME}:${CACHE_VAR_P_TYPE}=\"${CACHE_VAR_P_VALUE}\"")
set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR_C_NAME}:${CACHE_VAR_C_TYPE}=\"${CACHE_VAR_C_VALUE}\"")

#Print the modified value of ${CMAKE_ARGS}
MESSAGE(STATUS "CMAKE_ARGS: '" ${CMAKE_ARGS} "'")

#Reset ${CMAKE_ARGS} to its original value
set(CMAKE_ARGS ${CMAKE_ARGS_ORIGINAL})

#Print the original value of ${CMAKE_ARGS} for verification
MESSAGE( STATUS "CMAKE_ARGS: '" ${CMAKE_ARGS} "'")

#Append the two pairs to ${CMAKE_ARGS} using list
list(APPEND CMAKE_ARGS "-D${CACHE_VAR_P_NAME}:${CACHE_VAR_P_TYPE}=\"${CACHE_VAR_P_VALUE}\"")
list(APPEND CMAKE_ARGS "-D${CACHE_VAR_C_NAME}:${CACHE_VAR_C_TYPE}=\"${CACHE_VAR_C_VALUE}\"")

#Print the modified value of ${CMAKE_ARGS}
#Notice that here we surrounded ${CMAKE_ARGS} with quotes so that it is printed as list of delimiter separated values
#Between each element the character ';' will be added because ${CMAKE_ARGS} is surrounded with quotes
MESSAGE(STATUS "CMAKE_ARGS: '" "${CMAKE_ARGS}" "'")

Which resulted in the following output

-- CMAKE_ARGS: ''
-- CMAKE_ARGS: ' -DPRODUCTS_DIR:string="someplace/with spaces" -DCLIENTS_DIR:string="another/place"'
-- CMAKE_ARGS: ''
-- CMAKE_ARGS: '-DPRODUCTS_DIR:string="someplace/with spaces";-DCLIENTS_DIR:string="another/place"'

From the output we can see that the two options treat the variable in a different way as using set just created a huge string containing both pairs while list created a list of two elements.
Both methods seem to work properly but we chose the list method for our external project.

The CMakeLists.txt file that we used to include the external project using custom CMAKE_ARGS resulted as follows:

cmake_minimum_required (VERSION 3.2.2)
include (ExternalProject)

set (TARGET c-banana-eat-banana)
project (${TARGET} C)

set (BANANA_ROOT ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "")

#Add custom CMake arguments to be passed to the CMake command line of the external project
list(APPEND CMAKE_ARGS "-DARTIFACTS_DIR:string=\"${LIBRARIES_DIR}/${TARGET}\"")

ExternalProject_Add (${TARGET}
 URL ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET}.zip
 URL URL_HASH MD5=34734a678729967f426931d913326112
 CMAKE_ARGS "${CMAKE_ARGS}"
 BUILD_IN_SOURCE 1)

JavaSript: Remove all non printable and all non ASCII characters from text

According to the ASCII character encoding, there are 95 printable characters in total.
Those characters are in the range [0x20 to 0x7E] ([32 to 126] in decimal) and they represent letters, digits, punctuation marks, and a few miscellaneous symbols.
Character 0x20 (or 32 in decimal) is the space character ' ' and
character 0x7E (or 126 in decimal) is the tilde character '~'.
Source: https://en.wikipedia.org/wiki/ASCII#Printable_characters

Since all the printable characters of ASCII are conveniently in one continuous range, we used the following to filter all other characters out of our string in JavaScript.

printable_ASCII_only_string = input_string.replace(/[^ -~]+/g, "");

What the above code does is that it passes the input string through a regular expression which will match all characters out of the printable range and replace them with nothing (hence, delete them).
In case you do not like writing your regular expression with the space character to it, you can re-write the above regular expression using the hex values of the two characters as follows:

printable_ASCII_only_string = input_string.replace(/[^\x20-\x7E]+/g, "");