Compress JSON file by eliminating whitespace - json

I am working with a large json file (~100,000 lines) and need to compress it down to make a program run faster. I wish to delete all the horizontal tabs, returns, etc. to minimize the size of the file.
For example if a line was originally:
"name_id": "Richard Feynman",
"occupation": "Professional Bongos Player"
it should be compressed to:
"name_id":"Richard Feynman","occupation":"Professional Bongos Player"`
I have scoured the Internet (forgive me if it is a simple answer, I am a beginner) and can't seem to find a command for the terminal that will help me do this. Any help would be much appreciated

Looks like you're looking for a JSON minifier.
There are some around, both online and standalone.
Try googling these terms + your favorite language, I'm sure you'll find something that suits your needs.
There are other tools that modify your JSON to make it smaller, but you'll end up with a different JSON, I guess. Haven't tried those.

Using GNU awk for RT:
$ awk 'BEGIN{RS="\""} NR%2{gsub(/[[:space:]]/,"")} {ORS=RT;print} END{printf "\n"}' file
"name_id":"Richard Feynman","occupation":"Professional Bongos Player"

The following flex(1) program will do the work. It makes a lexical analisys of json source and eliminates comments and spaces between tokens, respecting the in-string spaces. It also recognizes unquoted identifiers, and quotes them.
To compile it, just do
make json
Use it with the following command:
json [ file ... ]
if you don't specify a file, the program will read from stdin.
Here's the source:
%{
/* json-min. JSON minimizer.
* Author: Luis Colorado <lc#luiscoloradosistemas.com>
* Date: Wed Aug 13 07:35:23 EEST 2014
* Disclaimer: This program is GPL, as of GPL version 3, you
* may have received a copy of that document, or you can
* instead look at http://www.gnu.org/licenses/gpl.txt to read
* it. There's no warranty, nor assumed nor implicit on the
* use of this program, you receive it `as is' so whatever you
* do with it is only your responsibility. Luis Colorado
* won't assume any responsibility of the use or misuse of
* this program. You are warned.
*/
%}
dec ([1-9][0-9]*)
oct (0[0-7]*)
hex (0[xX][0-9a-fA-F]*)
doub ({dec}"."([0-9]*)?|{dec}?"."[0-9]+)
strd (\"([^\"]|\\.)*\")
t "true"
f "false"
n "null"
com1 "//".*
com2b "/*"
endc "*/"
ident ([a-zA-Z_][a-zA-Z0-9_]*)
%x INCOMMENT
%option noyywrap
%%
{dec} |
{oct} |
{hex} |
{doub} |
{strd} |
{t} |
{f} |
{n} |
"{" |
":" |
";" |
"}" |
"[" |
"]" |
"," ECHO;
[\ \t\n] |
{com1} ;
{com2b} BEGIN(INCOMMENT);
<INCOMMENT>. ;
<INCOMMENT>{endc} BEGIN(INITIAL);
{ident} { fprintf(stderr, "WARNING:"
"unquoted identifier %s "
"in source. Quoting.\n",
yytext);
printf("\"%s\"", yytext);
}
. { fprintf(stderr,
"WARNING: unknown symbol %s "
"in source, copied to output\n",
yytext);
ECHO;
}
%%
void process(const char *fn);
int main(int argc, const char **argv)
{
int i;
if (argc > 1) for (i = 1; i < argc; i++)
process(argv[i]);
else process(NULL); /* <-- stdin */
} /* main */
void process(const char *fn)
{
FILE *f = stdin;
if (fn) {
f = fopen(fn, "r");
if (!f) {
fprintf(stderr,
"ERROR:fopen:%s:%s(errno=%d)\n",
fn, strerror(errno), errno);
exit(EXIT_FAILURE);
} /* if */
} /* if */
yyin = f;
yylex();
if (fn) /* only close if we opened, don't close stdin. */
fclose(f);
printf("\n");
}
I have just written it, so there's little testing on it. Use it with care (conserve a backup of your original file) It doesn't overwrite the original file, just outputs to stdout, so you don't overwrite your data using it.
BR,
Luis

Related

How to develop tool in C/C++ whose command interface is Tcl shell?

Suppose a tool X need to developed which are written in C/C++ and having Tcl commanline interface, what will the steps or way?
I know about Tcl C API which can be used to extend Tcl by writing C extension for it.
What you're looking to do is embedding Tcl (totally a supported use case; Tcl remembers that it is a C library) but still making something tclsh-like. The simplest way of doing this is:
Grab a copy of tclAppInit.c (e.g., this is the current one in the Tcl 8.6 source tree as I write this) and adapt it, probably by putting the code to register your extra commands, linked variables, etc. in the Tcl_AppInit() function; you can probably trim a bunch of stuff out simply enough. Then build and link directly against the Tcl library (without stubs) to get effectively your own custom tclsh with your extra functionality.
You can use Tcl's API more extensively than that if you're not interested in interactive use. The core for non-interactive use is:
// IMPORTANT: Initialises the Tcl library internals!
Tcl_FindExecutable(argv[0]);
Tcl_Interp *interp = Tcl_CreateInterp();
// Register your custom stuff here
int code = Tcl_Eval(interp, "your script");
// Or Tcl_EvalFile(interp, "yourScriptFile.tcl");
const char *result = Tcl_GetStringResult(interp);
if (code == TCL_ERROR) {
// Really good idea to print out error messages
fprintf(stderr, "ERROR: %s\n", result);
// Probably a good idea to print error traces too; easier from in Tcl
Tcl_Eval(interp, "puts stderr $errorInfo");
exit(1);
}
// Print a non-empty result
if (result[0]) {
printf("%s\n", result);
}
That's about all you need unless you're doing interactive use, and that's when Tcl_Main() becomes really useful (it handles quite a few extra fiddly details), which the sample tclAppInit.c (mentioned above) shows how to use.
Usually, SWIG (Simplified Wrapper and Interface Generator) is the way to go.
SWIG HOMEPAGE
This way, you can write code in C/C++ and define which interface you want to expose.
suppose you have some C functions you want added to Tcl:
/* File : example.c */
#include <time.h>
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
char *get_time()
{
time_t ltime;
time(&ltime);
return ctime(&ltime);
}
Now, in order to add these files to your favorite language, you need to write an "interface file" which is the input to SWIG. An interface file for these C functions might look like this :
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
At the UNIX prompt, type the following:
unix % swig -tcl example.i
unix % gcc -fpic -c example.c example_wrap.c \
-I/usr/local/include
unix % gcc -shared example.o example_wrap.o -o example.so
unix % tclsh
% load ./example.so example
% puts $My_variable
3.0
% fact 5
120
% my_mod 7 3
1
% get_time
Sun Feb 11 23:01:07 2018
The swig command produces a file example_wrap.c that should be compiled and linked with the rest of the program. In this case, we have built a dynamically loadable extension that can be loaded into the Tcl interpreter using the 'load' command.
Taken from http://www.swig.org/tutorial.html

systemtap userspace function tracing

I have a simple c++ program
main.cpp
#include <iostream>
using namespace std;
int addition (int a, int b)
{
int r;
r=a+b;
return r;
}
int main ()
{
int z;
z = addition (5,3);
cout << "The result is " << z;
}
I want to generate the function tracing for this
- print function names and its input output and return types
My systemtap script : para-callgraph.stp
#! /usr/bin/env stap
function trace(entry_p, extra) {
%( $# > 1 %? if (tid() in trace) %)
printf("%s%s%s %s\n",
thread_indent (entry_p),
(entry_p>0?"->":"<-"),
probefunc (),
extra)
}
probe $1.call { trace(1, $$parms) }
probe $1.return { trace(-1, $$return) }
My C++ Exec is called : a ( compiled as g++ -g main.cpp)
Command I run
stap para-callgraph.stp 'process("a").function("*")' -c "./a > /dev/null"
0 a(15119):->_GLOBAL__I__Z8additionii
27 a(15119): ->__static_initialization_and_destruction_0 __initialize_p=0x0 __priority=0x0
168 a(15119): <-__static_initialization_and_destruction_0
174 a(15119):<-_GLOBAL__I__Z8additionii
0 a(15119):->main
18 a(15119): ->addition a=0x0 b=0x400895
30 a(15119): <-addition return=0x8
106 a(15119):<-main return=0x0
Here ->addition a=0x0 b=0x400895 : its address and not actual values ie 5, 3 which I want.
How to modify my stap script?
This appears to be a systemtap bug. It should print the value of b, not its address. Please report it to the systemtap#sourceware.org mailing list (with compiler/etc. versions and other info, as outlined in man error::reporting.
As to changing the script, the $$parms part is where the local variables are being transformed into a pretty-printed string. It could be changed to something like...
trace(1, $$parms . (#defined($foobar) ? (" foobar=".$foobar$) : ""))
to append foobar=XYZ to the trace record, whereever a parameter foobar is available. To work around the systemtap bug in question, you could try
trace(1, $$parms . (#defined($b) ? (" *b=".user_int($b)) : ""))
to dereference the b variable as if it were an int *.

Tcl C API: redirect stdout of embedded Tcl interp to a file without affecting the whole program

#include <tcl.h>
int main(int argc, char** argv)
{
Tcl_Interp *interp = Tcl_CreateInterp();
Tcl_Channel stdoutChannel = Tcl_GetChannel(interp, "stdout", NULL);
Tcl_UnregisterChannel(interp, stdoutChannel);
Tcl_Channel myChannel = Tcl_OpenFileChannel(interp, "/home/aminasya/nlb_rundir/imfile", "w", 0744);
Tcl_RegisterChannel(interp, myChannel);
Tcl_Eval(interp, "puts hello");
}
In this code I have tried to close stdout channel and redirect it to file. (As described Get the output from Tcl C Procedures). After running, "imfile" is created but empty. What am doing wrong?
I have seen How can I redirect stdout into a file in tcl too, but I need to do it using Tcl C API.
I have also tried this way, but again no result.
FILE *myfile = fopen("myfile", "W+");
Tcl_Interp *interp = Tcl_CreateInterp();
Tcl_Channel myChannel = Tcl_MakeFileChannel(myfile, TCL_WRITABLE);
Tcl_SetStdChannel(myChannel, TCL_STDOUT);
The difficulty in your case is the interaction between the standard channels of a Tcl interpreter and the file descriptors (FDs) of the standard streams as seen by the main program (and the C runtime), coupled with the semantics of open(2) in Unix.
The process which makes all your output redirected rolls like this:
The OS makes sure the three standard file descriptors (FDs) are open (and numbered 0, 1 and 2, with 1 being the standard output) by the time the program starts executing.
As soon as the Tcl interpreter you create initializes its three standard channels (this happens when you call Tcl_GetChannel() for "stdout", as described here), they get associated with those already existing three FDs in the main program.
Note that the underlying FDs are not cloned, instead, they are just "borrowed" from the enclosing program. In fact, I think in 99% of cases this is a sensible thing to do.
When you close (which happend when unregisteting) the standard channel stdout in your Tcl interpreter, the underlying FD (1) is closed as well.
The call to fopen(3) internally calls open(2) which picks up the lowest free FD, which is 1, and thus the standard output stream as understood by the main program (and the C runtime) is now connected to that opened file.
You then create a Tcl channel out of your file and register it with the interpreter. The channel indeed becomes stdout for the interpreter.
In the end, both writes to the standard output stream in your main program and writes to the standard output channel in your Tcl interpreter are sent do the same underlying FD and hence end up in the same file.
I can see two ways to deal with this behaviour:
Play a neat trick to "reconnect" the FD 1 to the same stream it was initially opened to and make the file opened for the Tcl interpreter's stdout use an FD greater than 2.
Instead of first letting the Tcl interpreter initialize its standard channels and then reinitializing one of them, initialize them all manually before letting that auto-vivification machinery kick in.
Both approaches have their pros and cons:
"Preserving FD 1" is generally simpler to implement, and if you want to redirect only stdout in your Tcl interpreter, and leave the two other standard channels to be connected to the same standard streams used by the enclosing program, this approach seems to be sensible to employ. The possible downsides are:
Too much magic involved (extensive commenting the code is advised).
Not sure how this would work on Windows: there's no dup(2) there (see below) and some other approach might be needed.
Not using the standard streams for stdin and stderr from the enclosing program might be useful.
Initializing the standard channels in the Tcl interpreter by hand requires more code and supposedly warrants the correct ordering (stdin, stdout, stderr, in that order). If you want the remaining two standard channels in your Tcl interpreter to be connected to the matching streams of the enclosing program, this approach is more work; the first approach does this for free.
Here's how to preserve FD 1 to make only stdout in the Tcl interpreter be connected to a file; for the enclosing program FD 1 is still connected to the same stream as set up by the OS.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <tcl.h>
int redirect(Tcl_Interp *interp)
{
Tcl_Channel chan;
int rc;
int fd;
/* Get the channel bound to stdout.
* Initialize the standard channels as a byproduct
* if this wasn't already done. */
chan = Tcl_GetChannel(interp, "stdout", NULL);
if (chan == NULL) {
return TCL_ERROR;
}
/* Duplicate the descriptor used for stdout. */
fd = dup(1);
if (fd == -1) {
perror("Failed to duplicate stdout");
return TCL_ERROR;
}
/* Close stdout channel.
* As a byproduct, this closes the FD 1, we've just cloned. */
rc = Tcl_UnregisterChannel(interp, chan);
if (rc != TCL_OK)
return rc;
/* Duplicate our saved stdout descriptor back.
* dup() semantics are such that if it doesn't fail,
* we get FD 1 back. */
rc = dup(fd);
if (rc == -1) {
perror("Failed to reopen stdout");
return TCL_ERROR;
}
/* Get rid of the cloned FD. */
rc = close(fd);
if (rc == -1) {
perror("Failed to close the cloned FD");
return TCL_ERROR;
}
/* Open a file for writing and create a channel
* out of it. As FD 1 is occupied, this FD won't become
* stdout for the C code. */
chan = Tcl_OpenFileChannel(interp, "aaa.txt", "w", 0666);
if (chan == NULL)
return TCL_ERROR;
/* Since stdout channel does not exist in the interp,
* this call will make our file channel the new stdout. */
Tcl_RegisterChannel(interp, chan);
return TCL_OK;
}
int main(void)
{
Tcl_Interp *interp;
int rc;
interp = Tcl_CreateInterp();
rc = redirect(interp);
if (rc != TCL_OK) {
fputs("Failed to redirect stdout", stderr);
return 1;
}
puts("before");
rc = Tcl_Eval(interp, "puts stdout test");
if (rc != TCL_OK) {
fputs("Failed to eval", stderr);
return 2;
}
puts("after");
Tcl_Finalize();
return 0;
}
Building and running (done in Debian Wheezy):
$ gcc -W -Wall -I/usr/include/tcl8.5 -L/usr/lib/tcl8.5 -ltcl main.c
$ ./a.out
before
after
$ cat aaa.txt
test
As you can see, the string "test" output by puts goes to the file while the strings "before" and "after", which are write(2)n to FD 1 in the enclosing program (this is what puts(3) does in the end) go to the terminal.
The hand-initialization approach would be something like this (sort of pseudocode):
Tcl_Channel stdin, stdout, stderr;
stdin = Tcl_OpenFileChannel(interp, "/dev/null", "r", 0666);
stdout = Tcl_OpenFileChannel(interp, "aaa.txt", "w", 0666);
stderr = Tcl_OpenFileChannel(interp, "/dev/null", "w", 0666);
Tcl_RegisterChannel(interp, stdin);
Tcl_RegisterChannel(interp, stdout);
Tcl_RegisterChannel(interp, stderr);
I have not tested this approach though.
At the level of the C API, and assuming that you are on a Unix-based OS (i.e., not Windows), you can do this far more simply by using the right OS calls:
#include <fcntl.h>
#include <unistd.h>
// ... now inside a function
int fd = open("/home/aminasya/nlb_rundir/imfile", O_WRONLY|O_CREAT, 0744);
// Important: deal with errors here!
dup2(fd, STDOUT_FILENO);
close(fd);
You could also use dup() to save the old stdout (to an arbitrary number that Tcl will just ignore) so that you can restore it later, if desired.
Try this:
FILE *myfile = fopen("myfile", "W+");
Tcl_Interp *interp = Tcl_CreateInterp();
Tcl_Channel myChannel = Tcl_MakeFileChannel(myfile, TCL_WRITABLE);
Tcl_RegisterChannel(myChannel);
Tcl_SetStdChannel(myChannel, TCL_STDOUT);
You need to register the channel with the interpreter before you can reset the std channel to use it.

SQL Scripts - Does the equivalent of a #define exist?

I have a script that I use to construct both the tables and stored procedures. For example I have a column of type varchar. varchar requires a size parameter, that size I also use as parameters in stored procedures and within those procedures.
is it possible to have thequivalentnt of a #define for its size, so I can easily adjust the size without the necessity of having to change ithroughht the whole of the script?
I am using MySql workbench.
EDIT
I have tried SET and DECLARE
I have a script - this is (abridged)
CREATE TABLE `locations`
(
`location` VARCHAR(25) NOT NULL
);
...
CREATE PROCEDURE AddLocation (IN location VARCHAR(25)
BEGIN
...
END$$
What I am trying to achieve is replace the values 25 in the script with a constant - similar to a #define at the top of the script that creates the table and stored procedures, so I am able to easily change the 25 to another number.
Anybody has found a solution to this problem?
The C Pre Processor (cpp) is historically associated with C (hence the name), but it really is a generic text processor that can be used (or abused) for something else.
Consider this file, named location.src (more on that later).
// C++ style comments works here
/* C style works also */
-- plain old SQL comments also work,
-- but you should avoid using '#' style of comments,
-- this will confuse the C pre-processor ...
#define LOCATION_LEN 25
/* Debug helper macro */
#include "debug.src"
DROP TABLE IF EXISTS test.locations;
CREATE TABLE test.locations
(
`location` VARCHAR(LOCATION_LEN) NOT NULL
);
DROP PROCEDURE IF EXISTS test.AddLocation;
delimiter $$
CREATE PROCEDURE test.AddLocation (IN location VARCHAR(LOCATION_LEN))
BEGIN
-- example of macro
ASSERT(length(location) > 0, "lost or something ?");
-- do something
select "Hi there.";
END
$$
delimiter ;
and file debug.src, which is included:
#ifdef HAVE_DEBUG
#define ASSERT(C, T) \
begin \
if (not (C)) then \
begin \
declare my_msg varchar(1000); \
set my_msg = concat("Assert failed, file:", __FILE__, \
", line: ", __LINE__, \
", condition ", #C, \
", text: ", T); \
signal sqlstate "HY000" set message_text = my_msg; \
end; \
end if; \
end
#else
#define ASSERT(C, T) begin end
#endif
When compiled with:
cpp -E location.src -o location.sql
you get the code you are looking for, with cpp expanding #define values.
When compiled with:
cpp -E -DHAVE_DEBUG location.src -o location.sql
you get the same, plus the ASSERT macro (posted as a bonus, to show what could be done).
Assuming a build with HAVE_DEBUG deployed in a testing environment (in 5.5 or later since SIGNAL is used), the result looks like this:
mysql> call AddLocation("Here");
+-----------+
| Hi there. |
+-----------+
| Hi there. |
+-----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> call AddLocation("");
ERROR 1644 (HY000): Assert failed, file:location.src, line: 24, condition length(location) > 0, text: lost or something ?
Note how the file name, line number, and condition points right at the place in the source code in location.src where the assert is raised, thanks again to the C pre processor.
Now, about the ".src" file extension:
you can use anything.
Having a different file extension helps with makefiles, etc, and prevents confusion.
EDIT: Originally posted as .xql, renamed to .src for clarity. Nothing related to xml queries here.
As with any tools, using cpp can lead to good things, and the use case for maintaining LOCATION_LEN in a portable way looks very reasonable.
It can also lead to bad things, with too many #include, nested #ifdef hell, macros, etc that at the end obfuscate the code, so your mileage may vary.
With this answer, you get the whole thing (#define, #include, #ifdef, __FILE__, __LINE__, #C, command line options to build), so I hope it should cover it all.
Have you tried SET?
here is an example :
SET #var_name = expr
more examples here :
http://dev.mysql.com/doc/refman/5.0/en/user-variables.html
It sounds like you're looking for user defined data types. Unfortunately for us all mySQL doesn't yet support user defined data types like SQL Server, Oracle, and others do.
Here's a list of supported data types:
http://dev.mysql.com/doc/refman/5.0/en/data-types.html
For those that are interested:
I ended up writing a PHP script because:
a) The machine that can access the database does not belong to me and I cannot access the C
preprocessor
b) The other the two answers do not work.
c) Seemed the simplest solution
Here is the script for those who might find it useful. I am using it to define the tables column
widths and then use those same values in the stored procedures. This is due to the column
widths have not yet been fully decided for production.
I have also built in that you can define strings that last over a few lines. This has the advantage that I can obey the 80 column width (hence printing looks readable).
Here is the script
<?php
if (1==count($argv))
{
?>
Processing #defines from stdin and send to SQL server:
This script will remove
1. #define <name> <integer>
2. #define <name> '<string>'
3. #define <name> '<string>' \
'<continuation of string>'
and replace the occurances of name with the #define value as specified
<name> is upper case alpha numberics or underscores, not starting with a
digit.
The arguments of this script is passed to the mysql executable.
<?php
exit(1);
}
function replace(&$newValues, $a, $b, $c)
{
return $a . (array_key_exists($b, $newValues) ? $newValues[$b] : $b) . $c;
}
// The patterns to be used
$numberPattern='/^#define[ \t]+([A-Z_][A-Z0-9_]*)[ \t]+(0|([1-9][0-9]*))'.
'[ \t]*[\r\n]+$/';
$stringPattern= '/^#define[ \t]+([A-Z_][A-Z0-9_]*)[ \t]+\''.
'((\\\'|[^\'\r\n])*)\'[ \t]*(\\\\{0,1})[\n\r]+$/';
$continuationPattern='/^[ \t]*\'((\\\'|[^\'\r\n])*)\'[ \t]*'.
'(\\\\{0,1})[\n\r]+$/';
// String to be evaluated to replace define values with a new value
$evalStr='replace($newValues, \'\1\', \'\2\', \'\3\');';
array_splice($argv, 0, 1);
// Open up the process
$mysql=popen("mysql ".implode(' ', $argv), 'w');
$newValues=array(); // Stores the defines new values
// Variables to control the replacement process
$define=false;
$continuation=false;
$name='';
$value='';
while ($line=fgets(STDIN))
{
$matches=array();
// #define numbers
if (!$define &&
1 == preg_match($numberPattern, $line, $matches))
{
$define = true;
$continuation = false;
$name = $matches[1];
$value = $matches[2];
}
// #define strings
if (!$define &&
1 == preg_match($stringPattern,
$line, $matches))
{
$define = true;
$continuation = ('\\' == $matches[4]);
$name = $matches[1];
$value = $matches[2];
}
// For #define strings that continue over more than one line
if ($continuation &&
1 == preg_match($continuationPattern,
$line, $matches))
{
$value .= $matches[1];
$continuation = ('\\' == $matches[3]);
}
// Have a complete #define, add to the array
if ($define && !$continuation)
{
$define = $continuation = false;
$newValues[$name]=$value;
}
elseif (!$define)
{
// Do any replacements
$line = preg_replace('/(^| |\()([A-Z_][A-Z0-9_]*)(\)| |$)/e',
$evalStr, $line);
echo $line; // In case we need to have pure SQL.
// Send it to be processed.
fwrite($mysql, $line) or die("MySql has failed!");
}
}
pclose($mysql);
?>

Reversing every character in a file

I'm in a little trouble here.
Can anyone help me implement a solution that reverses every byte so 0xAB becomes 0xBA but not so "abcd" becomes "dcba". I need it so AB CD EF becomes BA DC FE.
Preferably in C or C++ but it doesn't really matter provided it can run.
So far, I've implemented a UBER CRAPPY solution that doesn't even work (and yes, I know that converting to string and back to binary is a crappy solution) in PureBasic.
OpenConsole()
filename$ = OpenFileRequester("Open File","","All types | *.*",0)
If filename$ = ""
End
EndIf
OpenFile(0,filename$)
*Byte = AllocateMemory(1)
ProcessedBytes = 0
Loc=Loc(0)
Repeat
FileSeek(0,Loc(0)+1)
PokeB(*Byte,ReadByte(0))
BitStr$ = RSet(Bin(Asc(PeekS(*Byte))),16,"0")
FirstStr$ = Left(BitStr$,8)
SecondStr$ = Right(BitStr$,8)
BitStr$ = SecondStr$ + FirstStr$
Bit.b = Val(BitStr$)
WriteByte(0,Bit)
ProcessedBytes = ProcessedBytes + 1
ClearConsole()
Print("Processed Bytes: ")
Print(Str(ProcessedBytes))
Loc=Loc(0)
Until Loc = Lof(0)
Delay(10000)
Thanks for reading.
Reading your PureBasic code (I skipped it at first), it does seem you want to swap endian, even though it's not what your text is asking—0xAB practically always means a byte with decimal value 171, not two bytes, and it's extremely common to display a byte as two hex digits, where you use A-F in your example.
#include <iostream>
int main() {
using namespace std;
for (char a; cin.get(a);) {
char b;
if (!cin.get(b)) {
cout.put(a); // better to write it than lose it
cerr << "Damn it, input ends with an odd byte, is it in "
"the right format?\n";
return 1;
}
cout.put(b);
cout.put(a);
}
return 0;
}
// C version is a similar easy translation from the original code
import numpy
import sys
numpy.fromfile(sys.stdin, numpy.int16).byteswap(True).tofile(sys.stdout)
Original answer:
I'm not sure why you want this (it doesn't convert endian, for example, if you want that), but here you go:
#include <stdio.h>
int main() {
for (char c; (c == getchar()) != EOF;) {
putchar((c & 0xF << 4) | ((int)c & 0xF0 >> 4));
}
return 0;
}
#include <iostream>
int main() {
for (char c; std::cin.get(c);) {
std::cout.put((c & 0xF << 4) | ((int)c & 0xF0 >> 4));
}
return 0;
}
import sys
for line in sys.stdin:
sys.stdout.write("".join(
chr((ord(c) & 0xF << 4) | (ord(c) & 0xF0 >> 4))
for c in line
))
All assume that text translations don't occur (such as \n to \r\n and vice versa); you'll have to change them to opening files in binary mode if that's the case. They read from stdin and write to stdout, if you're unfamiliar with that, so just use programname < inputfile > outputfile to run them.
Reversing the high and low half-byte is possible through a simple arithmetic formula (assuming you operate on unsigned bytes):
reversed = (original % 16) * 16 + (original / 16);
A Haskell solution:
module ReverseBytes where
import qualified Data.ByteString as B
import Data.Bits
import Data.Word
-----------------------------------------------------------
main :: IO ()
main = B.getContents >>= B.putStr . B.map reverseByte
reverseByte :: Word8 -> Word8
reverseByte = flip rotate 4
runghc ReverseBytes.hs < inputfile > outputfile